/* ═══════════════════════════════════════════════════════════════
   Wo in jedem Akt was steht — und welche Dauerbewegung darauf
   liegt. Die Choreografie (was wann passiert) macht scenes.js;
   hier steht nur das Bühnenbild.
   ═══════════════════════════════════════════════════════════════ */

/* ─── Kulisse ────────────────────────────────────────────────────
   Die Sonne sitzt links, weil oben rechts der Ton-Schalter klebt. */

.k-sonne {
  width: min(28vw, 130px);
  height: auto;
  top: calc(var(--sicher-oben) + 1rem);
  left: 1rem;
  color: var(--stift);
}

#sonne-strahlen {
  transform-origin: 70px 70px;
  animation: sonne-dreht 90s linear infinite;
}

.k-wolke {
  width: min(38vw, 170px);
  height: auto;
  color: var(--stift);
  animation: ballon-treibt 14s ease-in-out infinite;
}

.k-wolke-1 { top: calc(var(--sicher-oben) + 4.5rem); right: 6vw; }

.k-wolke-2 {
  top: calc(var(--sicher-oben) + 11rem);
  left: 8vw;
  width: min(28vw, 120px);
  opacity: .8;
  animation-duration: 19s;
  animation-direction: reverse;
}

.k-haus {
  width: min(22vw, 110px);
  height: auto;
  right: 7vw;
  bottom: calc(9dvh + var(--sicher-unten));
  opacity: .9;
  color: var(--stift);
}

.k-boden {
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: min(16dvh, 120px);
  color: var(--stift);
}

/* ═══ Akt 0 — der erste Tap ═══════════════════════════════════ */

#akt-start { cursor: pointer; }

#akt-start .finger {
  width: min(24vw, 110px);
  animation: tippt 1.6s ease-in-out infinite;
  color: var(--stift);
}

@keyframes tippt {
  0%, 100% { transform: translateY(0) rotate(-4deg); }
  45%      { transform: translateY(14px) rotate(2deg); }
}

.tipp-ringe path {
  animation: ring-pulst 1.6s ease-out infinite;
  transform-origin: 39px 26px;
}
.tipp-ringe path:nth-child(2) { animation-delay: .18s; }

@keyframes ring-pulst {
  0%   { opacity: 0;  transform: scale(.6); }
  40%  { opacity: .7; }
  100% { opacity: 0;  transform: scale(1.25); }
}

/* ═══ Akt 1 — Intro ═══════════════════════════════════════════ */

#ballons {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.ballon {
  position: absolute;
  width: min(17vw, 78px);
  height: auto;
  color: var(--stift);
  animation:
    ballon-steigt 1.6s cubic-bezier(.2, .8, .3, 1) both,
    ballon-treibt 5.5s ease-in-out infinite 1.6s;
}

.ballon:nth-child(1) { left: 5vw;  top: 14dvh; animation-delay: .1s, 1.7s; }
.ballon:nth-child(2) { right: 6vw; top: 20dvh; animation-delay: .3s, 1.9s; animation-duration: 1.7s, 6.4s; }
.ballon:nth-child(3) { left: 14vw; top: 62dvh; animation-delay: .5s, 2.1s; animation-duration: 1.8s, 5.9s; }
.ballon:nth-child(4) { right: 11vw; top: 58dvh; animation-delay: .7s, 2.3s; animation-duration: 1.5s, 6.8s; }

#intro-titel  { position: relative; z-index: 2; }
#intro-alter  { position: relative; z-index: 2; }
#intro-text   { position: relative; z-index: 2; }
#intro-knopf  { position: relative; z-index: 2; margin-top: .4rem; }

/* Das Geburtstagskind in der unteren rechten Ecke. Absolut
   positioniert wie die Ballons — der Text in der Mitte soll von ihm
   nichts merken. pointer-events: none, damit es niemals zwischen
   Finger und Knopf gerät.

   Es kommt erst, wenn der Titel fertig gekritzelt ist; deshalb die
   Verzögerung. Die steckt hier und nicht in scenes.js, weil sie zum
   Bild gehört und nicht zum Ablauf. */
.held-intro {
  position: absolute;
  right: 3vw;
  bottom: calc(var(--sicher-unten) + 1dvh);
  width: min(30vw, 165px);
  z-index: 1;
  pointer-events: none;
  color: var(--stift);
  animation: steigt-auf .75s cubic-bezier(.2, .9, .3, 1) both 1.3s;
}

.held-intro .winkarm {
  transform-origin: 118px 122px;
  animation: winken .8s ease-in-out infinite 2.1s;
}

/* ═══ Akt 2 — das Geschenk ════════════════════════════════════ */

#geschenk-figur {
  cursor: pointer;
  animation: huepfen 1.5s cubic-bezier(.3, .7, .4, 1) infinite;
}

/* Sobald es offen ist, hört das Zappeln auf. */
#geschenk-figur.offen { animation: none; }

#geschenk-figur .zeichnung { position: relative; z-index: 2; }

.strahlen {
  position: absolute;
  inset: -35% -35% auto -35%;
  width: 170%;
  height: auto;
  z-index: 1;
  /* Die Strahlen sind 170 % breit und ragen weit über den Karton
     hinaus — auf niedrigen Bildschirmen liegen sie über dem Knopf
     „Was ist da drin?". Ohne das hier schluckt reine Deko den Tap
     und die Show bleibt stehen. */
  pointer-events: none;
  opacity: 0;
  transform: scale(.3);
  transform-origin: 50% 40%;
}

.strahlen.raus {
  animation: strahlen-brechen .9s cubic-bezier(.2, 1, .4, 1) forwards;
}

@keyframes strahlen-brechen {
  0%   { opacity: 0; transform: scale(.25) rotate(-14deg); }
  45%  { opacity: .95; transform: scale(1.05) rotate(4deg); }
  100% { opacity: .5;  transform: scale(1) rotate(0deg); }
}

#geschenk-deckel { transform-origin: 150px 110px; }

#geschenk-deckel.fliegt {
  animation: deckel-fliegt 1s cubic-bezier(.25, .9, .4, 1) forwards;
}

@keyframes deckel-fliegt {
  0%   { transform: translate(0, 0) rotate(0deg); }
  25%  { transform: translate(-14px, -46px) rotate(-16deg); }
  100% { transform: translate(-120px, -80dvh) rotate(-190deg); opacity: 0; }
}

/* Die Schleife löst sich einen Wimpernschlag vor dem Deckel. */
#geschenk-schleife.loest {
  animation: schleife-loest .45s ease-in forwards;
  transform-origin: 150px 92px;
}

@keyframes schleife-loest {
  0%   { transform: scale(1) rotate(0deg); }
  40%  { transform: scale(1.16) rotate(-8deg); }
  100% { transform: scale(.6) rotate(26deg); opacity: 0; }
}

.fragezeichen {
  position: absolute;
  font-family: var(--schrift-gross);
  font-size: clamp(1.6rem, 7vw, 2.4rem);
  color: var(--akzent);
  -webkit-text-stroke: 1.5px var(--stift);
  opacity: 0;
  animation: frage-ploppt 2.4s ease-in-out infinite;
  pointer-events: none;
  z-index: 3;
}

.fragezeichen.f1 { left: 6%;  top: 6%;  animation-delay: 0s;   }
.fragezeichen.f2 { right: 8%; top: 2%;  animation-delay: .8s;  }
.fragezeichen.f3 { left: 46%; top: -6%; animation-delay: 1.6s; }

@keyframes frage-ploppt {
  0%   { opacity: 0; transform: translateY(10px) scale(.5) rotate(-14deg); }
  25%  { opacity: 1; transform: translateY(-8px) scale(1.1) rotate(8deg); }
  60%  { opacity: 1; transform: translateY(-18px) scale(1) rotate(-6deg); }
  100% { opacity: 0; transform: translateY(-34px) scale(.8) rotate(10deg); }
}

#geschenk-hinweis { margin-top: .8rem; }

/* ═══ Akt 3 — die Kuh ═════════════════════════════════════════ */

.kuh-buehne {
  position: relative;
  width: min(94vw, 460px);
  /* Der wichtigste Wert im ganzen Stylesheet: er hält die Kuh so
     groß wie möglich, ohne dass Text und Knopf darunter aus dem
     Bild rutschen. */
  height: min(46dvh, 340px);
  flex: 0 1 auto;
}

.offener-karton {
  position: absolute;
  bottom: 0;
  left: 50%;
  width: 58%;
  height: auto;
  transform: translateX(-50%);
  z-index: 1;
  color: var(--stift);
}

.kuh-figur {
  position: absolute;
  bottom: 14%;
  left: 50%;
  width: 96%;
  max-width: none;
  transform: translateX(-50%);
  z-index: 2;
  color: var(--stift);
}

.kuh-figur.taucht-auf .kuh-auftritt {
  animation: kuh-steigt-aus-karton 1.3s cubic-bezier(.3, 1.1, .4, 1) both;
  transform-origin: center bottom;
}

/* Dauerbewegung der Körperteile */
.ohr-links  { transform-origin: 50px 112px; animation: ohr-zuckt 6s ease-in-out infinite; }
.ohr-rechts { transform-origin: 118px 114px; animation: ohr-zuckt 6s ease-in-out infinite .9s; }
.schwanz    { transform-origin: 286px 112px; animation: schwanz-pendelt 2.4s ease-in-out infinite; }
.kuh-augen  { transform-origin: 87px 126px; animation: blinzeln 5s ease-in-out infinite; }

/* Im Metzger-Akt reißt sie die Augen auf und blinzelt nicht mehr. */
.kuh-augen.erschrocken { animation: zappeln .35s ease-in-out infinite; }

/* Das Schwein. Die Breite ist kein freier Wert: sie muss sich zur
   viewBox genauso verhalten wie bei der Kuh (96 % zu 340), sonst
   zeichnet derselbe Stift beim kleineren Tier plötzlich dünner.
   200 × 96 / 340 ≈ 56,5 %. Wer die Zahl ändert, ändert die
   Strichstärke mit. */
.schwein-figur {
  position: absolute;
  bottom: 2%;
  left: 6%;
  width: 56.5%;
  z-index: 3;
  color: var(--stift);
}

.schwein-figur.taucht-auf .schwein-auftritt {
  animation: kuh-steigt-aus-karton 1.1s cubic-bezier(.3, 1.1, .4, 1) both;
  transform-origin: center bottom;
}

#schwein-blase {
  top: -12%;
  left: 0;
  z-index: 4;
  font-size: clamp(.95rem, 4.2vw, 1.4rem);
  animation: ploppt-rein .45s cubic-bezier(.2, 1.6, .5, 1) both,
             wackeln 2.9s ease-in-out infinite .5s;
}

#kuh-blase {
  top: -4%;
  right: -2%;
  animation: ploppt-rein .45s cubic-bezier(.2, 1.6, .5, 1) both,
             wackeln 2.6s ease-in-out infinite .5s;
}

/* ═══ Akt 4 — der Metzger ═════════════════════════════════════ */

.metzger-buehne {
  position: relative;
  width: min(96vw, 520px);
  height: min(48dvh, 380px);
  flex: 0 1 auto;
}

.kuh-opfer {
  position: absolute;
  right: -4%;
  bottom: 4%;
  width: 66%;
  z-index: 2;
  color: var(--stift);
}

/* Auch hier gilt das Verhältnis von Breite zu viewBox aus Akt 3:
   die Kuh steht mit 66 % zu 340, das Schwein braucht 200 × 66/340
   ≈ 38,8 %, damit beide Tiere mit demselben Strich gezeichnet
   aussehen. Es steht vor der Kuh und einen Tick tiefer. */
.schwein-opfer {
  position: absolute;
  right: 22%;
  bottom: 0;
  width: 38.8%;
  z-index: 3;
  color: var(--stift);
}

/* Es zittert am ganzen Leib. Die Kuh reißt dafür die Augen auf —
   beim Schwein sieht man die Augen zu schlecht, also zappelt es
   komplett. */
.schwein-opfer .zappelt { animation: zappeln .35s ease-in-out infinite; }

.metzger {
  position: absolute;
  left: 2%;
  bottom: 2%;
  width: 40%;
  z-index: 3;
  color: var(--stift);
  transform: translateX(-70vw);
}

/* Zwei getrennte Klassen, und das mit Absicht:

   .kommt trägt die Wanderung über den Bildschirm und bleibt danach
   liegen (forwards), damit er stehen bleibt, wo er angekommen ist.

   .laeuft trägt das Gehen — Beinwechsel und Wippen, beides in einer
   Endlosschleife. Die nimmt scenes.js beim Ankommen wieder ab. Lägen
   beide auf derselben Klasse, würde er bis zum Abspann auf der
   Stelle weitertrampeln. */

.metzger.kommt {
  animation: metzger-laeuft 2.2s linear forwards;
}

.metzger.laeuft .oberkoerper { animation: koerper-wippt .5s ease-in-out infinite; }
.metzger.laeuft .schritt-a   { animation: beine-wechseln .34s steps(1) infinite; }
.metzger.laeuft .schritt-b   { animation: beine-wechseln-b .34s steps(1) infinite; }

/* Im Stand steht er still und nur ein Bein ist zu sehen. */
.schritt-a { opacity: 1; }
.schritt-b { opacity: 0; }

#metzger-arm    { transform-origin: 100px 120px; }
#metzger-messer { transform-origin: 152px 82px; }

#metzger-messer.holt-aus {
  animation: messer-holt-aus .95s cubic-bezier(.4, 0, .2, 1) forwards;
}

.staubwolke {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 108%;
  height: auto;
  transform: translate(-50%, -50%);
  z-index: 5;
  color: var(--stift);
}

.staubwolke .wolke-koerper {
  transform-origin: center;
  animation: wolke-quillt 2.1s ease-out forwards,
             wolke-rumpelt .22s steps(2) infinite;
}

.wolken-zeichen {
  font-family: var(--schrift-gross);
  font-size: 46px;
  fill: var(--stift);
}

/* Zentriert über die volle Breite statt per translateX(-50%) —
   die Animation belegt transform selbst und würde eine
   Verschiebung dort sofort wieder wegwerfen. */
#zack {
  left: 0;
  right: 0;
  top: 26%;
  text-align: center;
  transform-origin: center;
  animation: zack-knallt 1.5s cubic-bezier(.2, 1.4, .4, 1) forwards;
}

/* Bebt die ganze Bühne beim Schnitt */
#buehne.bebt   { animation: buehne-bebt .5s ease-out; }
#kulisse.bebt  { animation: buehne-bebt .5s ease-out; }
#blitz.blitzt  { animation: blitzt .32s ease-out; }

.engel-kuh {
  position: absolute;
  right: 2%;
  bottom: 14%;
  width: 52%;
  z-index: 4;
  color: var(--stift);
  animation: engel-schwebt-hoch 5.5s cubic-bezier(.35, 0, .5, 1) forwards;
}

/* Das Schwein zieht links daneben hoch, etwas kleiner und etwas
   langsamer. Beide exakt gleich steigen zu lassen sähe nach einem
   Kopierfehler aus. */
.engel-schwein {
  position: absolute;
  left: 30%;
  bottom: 2%;
  width: 32%;
  z-index: 4;
  color: var(--stift);
  animation: engel-schwebt-hoch 6.2s cubic-bezier(.35, 0, .5, 1) forwards;
}

.heiligenschein { animation: heiligenschein-glimmt 1.8s ease-in-out infinite; }

.fluegel-hinten { transform-origin: 200px 100px; animation: fluegel-schlagen .9s ease-in-out infinite; }
.fluegel-vorne  { transform-origin: 220px 106px; animation: fluegel-schlagen .9s ease-in-out infinite .12s; }
.winkehuf       { transform-origin: 262px 168px; animation: winken .8s ease-in-out infinite; }

.beute-pop {
  transform-origin: 80px 55px;
  animation: ploppt-rein .6s cubic-bezier(.2, 1.5, .5, 1) both,
             schweben 2.6s ease-in-out infinite .6s;
}

/* ═══ Akt 5 — die Fleischbox ══════════════════════════════════ */

.fleisch-buehne {
  position: relative;
  width: min(84vw, 340px);
  color: var(--stift);
  flex: 0 1 auto;
}

/* Alle Stücke und beide Kistenwände starten unsichtbar. scenes.js
   holt sie nacheinander herein — das Stapeln ist die Pointe des
   Aktes und darf nicht schon beim Bildwechsel vorbei sein. */
.stueck,
.kiste-hinten,
.kiste-vorne { opacity: 0; }

.stueck.faellt {
  animation: faellt-rein .5s cubic-bezier(.3, 1.35, .6, 1) both;
}

.kiste-hinten.kommt {
  animation: blendet-auf .45s ease-out both;
}

/* Die Vorderwand schiebt sich von unten hoch — dadurch sieht es
   aus, als würde die Kiste um den Stapel herum gebaut, und nicht,
   als läge der Stapel plötzlich darin. */
.kiste-vorne.kommt {
  animation: kiste-schiebt-hoch .55s cubic-bezier(.2, 1.25, .4, 1) both;
}

/* Das Schild auf der Kistenfront, deckungsgleich mit der hellen
   Fläche im SVG (x 108…276 von 380, y 206…258 von 290). Es muss
   zwei Zeilen tragen — mit einem flacheren Feld hing „von …" unten
   heraus.

   Bewusst ohne translateX(-50%) zum Zentrieren: die Auftrittsanimation
   unten setzt selbst ein transform, und ein CSS-transform ersetzt das
   andere, statt sich damit zu verrechnen — das Schild rutschte um
   seine halbe Breite nach rechts aus der Kiste. Dieselbe Falle wie
   bei der Kuh und beim Steak in der Metzgerhand. */
.kiste-schild {
  position: absolute;
  left: 28.5%;
  top: 71.5%;
  width: 44%;
  display: grid;
  justify-items: center;
  gap: .05em;
  text-align: center;
  line-height: 1.2;
  color: #4a3520;
  pointer-events: none;
  animation: ploppt-rein .45s cubic-bezier(.2, 1.5, .5, 1) both;
}

.kiste-schild #box-fuer {
  font-family: var(--schrift-gross);
  font-size: clamp(.95rem, 4.6vw, 1.35rem);
}

.kiste-schild #box-von {
  font-size: clamp(.75rem, 3.4vw, .95rem);
  opacity: .8;
}

/* Der Glanz läuft über eine eigene Schicht, die grob die Form der
   Kiste ausschneidet — sonst wanderte ein sichtbares Rechteck über
   das Bild. */
.glanz {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
  clip-path: inset(30% 12% 8% 12% round 6px);
}

.glanz::before {
  content: '';
  position: absolute;
  inset: -20% -60%;
  background: linear-gradient(100deg,
              transparent 38%, rgba(255,255,255,.85) 50%, transparent 62%);
  /* Ohne das steht der helle Streifen die ganze Zeit im Bild und
     sieht aus wie ein Rechteck, das jemand vergessen hat. Sichtbar
     wird er allein während glanz-wandert — die Keyframes blenden
     ihn selbst auf und wieder weg. */
  opacity: 0;
}

.glanz.laeuft::before {
  animation: glanz-wandert 1.1s ease-in-out;
}

#box-titel { position: relative; z-index: 2; }
#box-fuss  { position: relative; z-index: 2; }

/* Das Geburtstagskind an der Gitarre. Akt 5 ist der vollste Akt —
   Titel, Steak, Gutschein, zwei Knöpfe. Deshalb steht er außen
   links, liegt unter allem (z-index 0) und nimmt keine Tipps an.

   Seine Breite hängt an der Höhe des Fensters, nicht an der Breite:
   frei ist nur der Streifen zwischen Gutschein und unterem Rand,
   und der wächst mit dvh. 14dvh Breite ergeben bei einem
   Seitenverhältnis von 220:300 rund 19dvh Höhe — genau dieser
   Streifen. Stünde hier eine feste Pixelbreite, ragte ihm der
   Gutschein auf kleinen Geräten mitten durchs Gesicht. */
.held-rock {
  position: absolute;
  left: 1vw;
  bottom: calc(var(--sicher-unten) + .5dvh);
  width: min(34vw, 14dvh);
  z-index: 0;
  pointer-events: none;
  color: var(--stift);
}

.held-rock.rockt { animation: ploppt-rein .5s cubic-bezier(.2, 1.6, .5, 1) both; }

/* Die Dauerbewegung setzt erst ein, wenn der Auftritt durch ist —
   sonst nickt er schon, während er noch aus dem Nichts kommt. */
.held-rock.rockt .schlagarm  { transform-origin: 82px 124px; animation: schrammelt .28s ease-in-out infinite .5s; }
.held-rock.rockt .held-kopf  { transform-origin: 60px 106px; animation: headbangt .56s ease-in-out infinite .5s; }

/* Das Haar hinkt dem Kopf ein Stück hinterher. Genau das macht aus
   einem nickenden Kopf eine wehende Mähne. */
.held-rock.rockt .straehne-links,
.held-rock.rockt .straehne-rechts {
  transform-origin: 60px 28px;
  animation: haar-schwingt .56s ease-in-out infinite .62s;
}

.knopf-reihe {
  display: flex;
  flex-wrap: wrap;
  gap: .8rem;
  justify-content: center;
  align-items: center;
  flex: 0 0 auto;
}

.knopf-reihe .knopf {
  font-size: clamp(.95rem, 4vw, 1.2rem);
  padding: .55em 1.1em;
  text-decoration: none;
}

/* ─── Enge Bildschirme ───────────────────────────────────────────
   Auf einem alten iPhone SE ist in der Höhe kaum Platz. Dort
   schrumpfen die Figuren, damit nichts unter den Rand rutscht.   */

@media (max-height: 700px) {
  .kuh-buehne     { height: min(38dvh, 260px); }
  .metzger-buehne { height: min(40dvh, 290px); }
  .fleisch-buehne { width: min(72vw, 270px); }
  .k-haus         { display: none; }
  .k-wolke-2      { display: none; }
  .held-intro     { width: min(24vw, 120px); }
}

/* Auf einem liegenden Handy ist der Platz vorbei. Erst gehen die
   Ballons, und mit ihnen geht auch er — sonst steht er dem Text im
   Weg, den man ja lesen soll. */
@media (max-height: 560px) {
  .akt         { gap: .4rem; }
  #ballons     { display: none; }
  .held-intro  { display: none; }
  .held-rock   { display: none; }
  .fleisch-buehne { width: min(52vw, 200px); }
  #box-fuss       { display: none; }
}
