/* ===========================================================================
   Onda – der Buddy                                    components/buddy/buddy.css
   Regeln: R2.1.2 (Blob, Öhrchen, Wangen, Augen, Lächeln), R2.1.3 (drei
   Ausdrücke), R2.1.7 (Gefühle: gehalten und einmalig, Rückweg, Blinzeln),
   R2.1.8 (Mund folgt der Lautstärke), R2.4.2 (Jubel mit Tröte und Konfetti),
   R14.4.9 (48 / 112 px), R14.2.6 (Blob).
   Stand 2026-09-16 – aus der Probe „Leben im Buddy" (Dummy, probe-buddy.html)
   freigegeben von Jan-Philip. Der Dummy holt diese Datei per kit-holen.py.
   Mund seit 2026-10-10 (Entscheidungsboard Mund und Sprechblase, nach Miras
   Call): offen ein Blob in Beere statt eines Ovals aus Tinte, ohne Zähne,
   4 px tiefer; solange Onda spricht, ist die weiße Lippe weg. Rückweg zum
   Lächeln seit 10.10. weich: Der Bogen zieht sich aus dem Spalt in die Breite
   und wird dabei weiß (Board „Übergang", Variante E; Nachlauf in buddy-leben.js).

   Aufbau: Grundmaß 150 x 152, skaliert über --buddy (0.32 = 48 px,
   0.747 = 112 px). Die Silhouette ist aus <div>s gebaut, kein SVG – so bleibt
   sie einfärbbar und skaliert als lebende Komponente (readme, Index).

   <span class="buddy" data-ausdruck="neutral|freut-sich|staunt"
                       data-gefuehl="neutral|neugierig|denkt-nach|staunt|schlaefrig
                                     |stolz|kichert|ermutigt|freut-sich"
                       data-schweben="ja">
     <span class="figur">
       <span class="teil ohr ohr-l"></span><span class="teil ohr ohr-r"></span>
       <span class="teil koerper"></span>
       <span class="teil wange wange-l"></span><span class="teil wange wange-r"></span>
       <span class="teil auge auge-l"></span><span class="teil auge auge-r"></span>
       <span class="teil pupille pupille-l"></span><span class="teil pupille pupille-r"></span>
       <span class="teil lid lid-l"></span><span class="teil lid lid-r"></span>
       <span class="teil lid-u lid-u-l"></span><span class="teil lid-u lid-u-r"></span>
       <span class="teil mund"></span>
       <span class="teil troete"></span>
     </span>
   </span>

   Ein Gefühl ist ein Ausdruck (R2.1.3) plus kleine Mittel; buddy-leben.js
   setzt beides (fuehle) und den Mund (--mund) aus dem Pegel der Ansage.
   data-ausdruck allein reicht, wo kein Ablauf dahintersteht (Tor, Abschluss).

   Variablen auf .buddy (setzt buddy-leben.js oder ein Gefühl):
     --mund        0..1   Mundöffnung – folgt der Lautstärke der Ansage
     --blick-x/-y  px     Pupillenversatz
     --lid         0..1   wie weit das obere Lid fällt
     --wangen      0..1   Kraft der Wangen (Deckkraft und Größe)
     --neigung     deg    Kopfneigung
     --laecheln    0..1   Breite des Lächelbogens
     --sx / --sy          Stauchen und Strecken um den Fußpunkt
     --troete      0..1   wie weit das Papier der Tröte ausgerollt ist
   =========================================================================== */

.buddy {
  position: relative;
  display: inline-block;
  width: calc(150px * var(--buddy, 1));
  height: calc(152px * var(--buddy, 1));
  flex-shrink: 0;
  --mund: 0; --blick-x: 0px; --blick-y: 0px; --lid: 0; --wangen: 0;
  --neigung: 0deg; --laecheln: 1; --sx: 1; --sy: 1; --troete: 0;
}
/* Figur: Skalierung, Stauchen um den Fuß, Neigung um die Mitte. Die Dauern
   sind gestaffelt (Blick .3, Lid .35, Wangen .45, Neigung .5, Ohren .6 s):
   So kommt das Gesicht nach einem Gefühl nicht auf einmal zurück, sondern
   wie ein Ausatmen (R2.1.7). */
.buddy > .figur {
  position: absolute;
  top: 0; left: 0;
  width: 150px; height: 152px;
  transform-origin: top left;
  transform:
    scale(var(--buddy, 1))
    translate(75px, 148px) scale(var(--sx), var(--sy)) translate(-75px, -148px)
    translate(75px, 80px) rotate(var(--neigung)) translate(-75px, -80px);
  transition: transform .5s ease;
}
.buddy .teil { position: absolute; display: block; }

.buddy .ohr {
  top: 2px; width: 34px; height: 40px;
  background: var(--koerper, var(--onda-petrol));
  border-radius: 62% 62% 48% 48%;
  transition: transform .6s ease;
}
.buddy .ohr-l { left: 30px;  transform: rotate(-22deg); }
.buddy .ohr-r { right: 30px; transform: rotate(22deg); }

.buddy .koerper {
  top: 16px; left: 9px; width: 132px; height: 132px;
  background: var(--koerper, var(--onda-petrol));
  border-radius: var(--onda-blob-radius);
  box-shadow: 0 16px 30px rgba(2, 104, 115, .22);
}

/* Wangen: Kraft, Heben beim Lächeln, Mitgehen mit dem Mund */
.buddy .wange {
  top: 94px; width: 16px; height: 9px;
  background: var(--onda-pink); border-radius: 50%;
  opacity: calc(.7 + .3 * var(--wangen));
  transform:
    translateY(calc(-3px * var(--wangen) + 1.5px * var(--mund)))
    scale(calc(1 + .3 * var(--wangen)));
  transition: transform .45s ease, opacity .45s ease, background .45s ease;
}
.buddy .wange-l { left: 38px; }
.buddy .wange-r { left: 97px; }
/* Gedehnt gesprochen (R6.3.4.4): die Wangen blähen sich, solange das Wort läuft */
.buddy[data-dehnt="ja"] .wange { transform: translateY(1px) scale(1.45, 1.25); opacity: .85; }

/* Augen: blinzeln in jedem Gefühl (R2.1.7), Takt und Versatz je Buddy
   verschieden (setzt buddy-leben.js zufällig zwischen 4 und 6 s) */
.buddy .auge {
  top: 66px; width: 19px; height: 23px;
  background: var(--onda-white); border-radius: 50%;
  transform-origin: 50% 60%;
  animation: buddy-blinzeln var(--blinzel-takt, 5.2s) ease-in-out var(--blinzel-versatz, 0s) infinite;
  transition: top .3s ease, left .3s ease, width .3s ease, height .3s ease;
}
.buddy .auge-l { left: 48px; }
.buddy .auge-r { left: 84px; }
.buddy .pupille {
  top: 73px; width: 9px; height: 10px;
  background: var(--onda-ink); border-radius: 50%;
  transform: translate(var(--blick-x), var(--blick-y));
  transition: transform .3s ease, opacity .25s ease;
}
.buddy .pupille-l { left: 53px; }
.buddy .pupille-r { left: 89px; }

/* Oberes Lid: halbes Oval in Körperfarbe, fällt von oben über das Auge
   (denkt nach, schläfrig). Blinzelt das Auge, bleibt das Lid ruhig – Lid und
   Lidschlag sind zwei Dinge. */
.buddy .lid {
  top: 62px; width: 24px; height: 30px;
  background: var(--koerper, var(--onda-petrol));
  border-radius: 50%;
  transform: scaleY(var(--lid));
  transform-origin: 50% 0;
  transition: transform .35s ease;
}
.buddy .lid-l { left: 45px; }
.buddy .lid-r { left: 82px; }
/* Unteres Lid: steigt bei „freut sich" und lässt eine Sichel stehen – die
   Augenbögen, die blenden können (freigegeben 16.09. statt der Strich-Bögen) */
.buddy .lid-u {
  top: 62px; width: 24px; height: 30px;
  background: var(--koerper, var(--onda-petrol));
  border-radius: 50%;
  transform: scaleY(0);
  transform-origin: 50% 100%;
  transition: transform .35s ease;
}
.buddy .lid-u-l { left: 45px; }
.buddy .lid-u-r { left: 82px; }

/* Mund: der Lächelbogen ist die Unterlippe. Die Öffnung ist ein Blob in
   Beere, leicht schief, der mit --mund aus der Bogenmitte wächst (R2.1.8) –
   geschlossen unsichtbar. Solange Onda spricht (data-spricht, setzt
   buddy-leben.js), ist die weiße Lippe weg und zwischen den Silben bleibt ein
   schmaler Spalt; nach dem Satz kommt das Lächeln zurück. Der Rückweg ist
   langsamer als der Hinweg: Beim ersten Laut geht alles sofort (0,1–0,15 s),
   danach schließt sich der Spalt in 0,4 s, und der Bogen wächst aus Spaltbreite
   in 0,5 s zum Lächeln, während er weiß wird. Die Dauer gilt jeweils für den
   Zustand, in den gewechselt wird. Die Zunge ist ein Verlauf am Grund der
   Öffnung, so ragt sie nie über den Rand. */
.buddy .mund {
  top: 96px; left: calc(77px - 13px * var(--laecheln));
  width: calc(26px * var(--laecheln)); height: 14px;
  border-bottom: 3px solid var(--onda-white); border-radius: 0 0 28px 28px;
  transition: top .3s ease, left .5s ease, width .5s ease, height .3s ease, border-radius .3s ease, border-color .55s ease .12s;
}
.buddy .mund::before {
  content: "";
  position: absolute;
  left: 50%; top: 42%;
  width: calc(15px + 13px * var(--mund));
  height: calc(20px * var(--mund));
  transform: translate(-50%, -50%) rotate(-6deg);
  background:
    radial-gradient(ellipse calc(26% + 10% * var(--mund)) calc(max(0%, (var(--mund) - .35) * 62%)) at 56% 102%,
      var(--onda-pink-soft) 94%, transparent 100%),
    var(--onda-pink-deep);
  border-radius: 58% 42% 55% 45% / 38% 46% 62% 54%;
  min-height: 0px; min-width: 0px;
  transition: min-height .4s ease, min-width .4s ease;
}
/* Sprechen: Lippe weg, der (unsichtbare) Bogen so schmal wie der Spalt */
.buddy[data-spricht="ja"] .mund {
  width: 12px; left: 71px;
  border-bottom-color: transparent;
  transition: top .3s ease, left .15s ease, width .15s ease, height .3s ease, border-radius .3s ease, border-color .12s ease;
}
.buddy[data-spricht="ja"] .mund::before { min-height: 3.5px; min-width: 12px; transition: min-height .1s ease, min-width .1s ease; }

/* --- Ausdruck: freut sich (R2.1.3) – Sichel-Augen, breiter Mund, helle Wangen */
.buddy[data-ausdruck="freut-sich"] .auge { animation: none; }
.buddy[data-ausdruck="freut-sich"] .pupille { opacity: 0; }
.buddy[data-ausdruck="freut-sich"] .lid-u { transform: scaleY(.72); }
.buddy[data-ausdruck="freut-sich"] .mund {
  top: 92px; left: calc(73px - 15px * var(--laecheln)); width: calc(30px * var(--laecheln)); height: 17px;
  border-bottom-width: 4px; border-radius: 0 0 30px 30px;
}
.buddy[data-ausdruck="freut-sich"] .wange { background: var(--onda-white); opacity: calc(.55 + .3 * var(--wangen)); }
.buddy[data-ausdruck="freut-sich"][data-spricht="ja"] .mund { width: 12px; left: 67px; }

/* --- Ausdruck: staunt (R2.1.3) – große Augen, runder Mund in Beere, der sich aus der Mitte öffnet */
.buddy[data-ausdruck="staunt"] .auge { top: 63px; width: 22px; height: 27px; }
.buddy[data-ausdruck="staunt"] .auge-l { left: 46px; }
.buddy[data-ausdruck="staunt"] .auge-r { left: 83px; }
.buddy[data-ausdruck="staunt"] .mund {
  top: 98px; left: 70px; width: 12px; height: 12px;
  border: 0; border-radius: 58% 42% 55% 45% / 38% 46% 62% 54%; background: var(--onda-pink-deep);
}
.buddy[data-ausdruck="staunt"][data-spricht="ja"] .mund { left: 70px; }
.buddy[data-ausdruck="staunt"] .mund::before { top: 50%; width: calc(12px + 8px * var(--mund)); height: calc(12px + 10px * var(--mund)); }

/* --- Gefühle (R2.1.7): je ein Satz Variablen, der Ausdruck kommt von buddy-leben.js */
.buddy[data-gefuehl="neugierig"] { --neigung: -7deg; --blick-x: 3px; --blick-y: -2px; }
.buddy[data-gefuehl="neugierig"] .ohr-l { transform: rotate(-32deg) translateY(-2px); }
.buddy[data-gefuehl="neugierig"] .ohr-r { transform: rotate(14deg); }

.buddy[data-gefuehl="denkt-nach"] { --lid: .42; --blick-x: -3px; --blick-y: -3px; --laecheln: .7; --neigung: 3deg; }

.buddy[data-gefuehl="stolz"] { --wangen: 1; --sy: 1.03; }          /* Ausdruck: freut sich */
.buddy[data-gefuehl="stolz"] > .figur { animation: buddy-huepfer .7s ease-out 1; }

.buddy[data-gefuehl="ermutigt"] { --wangen: .5; --laecheln: .85; --blick-y: 1px; }   /* neutral – die Antwort auf den Fehlversuch (R14.6.1) */
.buddy[data-gefuehl="ermutigt"] > .figur { animation: buddy-nicken .8s ease-in-out 1; }

.buddy[data-gefuehl="kichert"] { --wangen: 1; --neigung: 2deg; }   /* Ausdruck: freut sich */
.buddy[data-gefuehl="kichert"] > .figur { animation: buddy-kichern .6s ease-in-out 1; }

.buddy[data-gefuehl="schlaefrig"] { --lid: .62; --blick-y: 3px; --laecheln: .55; --neigung: 4deg; animation-duration: 7.5s; }
.buddy[data-gefuehl="schlaefrig"] .ohr-l { transform: rotate(-38deg) translateY(4px); }
.buddy[data-gefuehl="schlaefrig"] .ohr-r { transform: rotate(38deg) translateY(4px); }

/* --- Jubel mit Tröte (R2.4.2): ein Aufsatz vor dem Mund, kein neues
   Körperteil (R2.1.2). Kegel gestreift Pink/Weiß, das Papier rollt sich mit
   dem Klang aus (--troete aus buddy-leben.js), die Wangen blähen sich, der
   Mund bleibt zu – ein Klang ist keine Stimme (R2.1.8). Jeder Toot schießt
   Konfetti aus der Spitze (.konfetti-salve). ---------------------------- */
.buddy .troete {
  top: 94px; left: 84px; width: 40px; height: 22px;
  transform-origin: 0 50%;
  transform: rotate(-16deg) scale(0);
  opacity: 0;
  transition: transform .25s cubic-bezier(.3, 1.4, .6, 1), opacity .2s ease;
}
.buddy .troete::before {
  content: "";
  position: absolute; inset: 0;
  background: repeating-linear-gradient(115deg, var(--onda-pink) 0 5px, var(--onda-white) 5px 9px);
  clip-path: polygon(0 40%, 100% 0, 100% 100%, 0 60%);
}
.buddy .troete::after {
  content: "";
  position: absolute;
  left: 100%; top: 50%;
  width: calc(4px + 40px * var(--troete));
  height: 6px;
  margin-top: -3px;
  background: var(--onda-sage);
  border-radius: 3px;
  box-shadow: calc(2px + 40px * var(--troete)) -5px 0 0 var(--onda-sage);   /* der Kringel am Ende */
}
.buddy[data-jubel="ja"] .troete { transform: rotate(calc(-16deg - 6deg * var(--troete))) scale(calc(1 + .12 * var(--troete))); opacity: 1; transition: opacity .2s ease; }
.buddy[data-jubel="ja"] .wange { transform: translateY(1px) scale(1.4, 1.25); opacity: .9; }
.buddy[data-jubel="ja"] .mund::before { display: none; }

.konfetti-salve {
  position: absolute; inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 3;
}
.konfetti-salve span { position: absolute; border-radius: 2px; }

@keyframes buddy-blinzeln {
  0%, 92%, 100% { transform: scaleY(1); }
  95%           { transform: scaleY(.08); }
}
@keyframes buddy-huepfer {
  0%   { transform: scale(var(--buddy, 1)) translate(75px, 148px) scale(1, 1)      translate(-75px, -148px); }
  25%  { transform: scale(var(--buddy, 1)) translate(75px, 148px) scale(1.08, .9)  translate(-75px, -148px); }
  55%  { transform: scale(var(--buddy, 1)) translate(75px, 148px) scale(.95, 1.1)  translate(-75px, -148px) translateY(-10px); }
  100% { transform: scale(var(--buddy, 1)) translate(75px, 148px) scale(1, 1.03)   translate(-75px, -148px); }
}
@keyframes buddy-nicken {
  0%, 100% { transform: scale(var(--buddy, 1)) translate(75px, 80px) rotate(0deg)  translate(-75px, -80px); }
  35%      { transform: scale(var(--buddy, 1)) translate(75px, 80px) rotate(5deg)  translate(-75px, -80px) translateY(5px); }
  70%      { transform: scale(var(--buddy, 1)) translate(75px, 80px) rotate(-2deg) translate(-75px, -80px) translateY(-1px); }
}
@keyframes buddy-kichern {
  0%, 100% { transform: scale(var(--buddy, 1)) translate(75px, 80px) rotate(0deg)  translate(-75px, -80px); }
  20%      { transform: scale(var(--buddy, 1)) translate(75px, 80px) rotate(-4deg) translate(-75px, -80px); }
  40%      { transform: scale(var(--buddy, 1)) translate(75px, 80px) rotate(4deg)  translate(-75px, -80px); }
  60%      { transform: scale(var(--buddy, 1)) translate(75px, 80px) rotate(-3deg) translate(-75px, -80px); }
  80%      { transform: scale(var(--buddy, 1)) translate(75px, 80px) rotate(2deg)  translate(-75px, -80px); }
}

/* --- Schweben (Bewegung, readme: sanft, nichts Hektisches) ---------------- */
.buddy[data-schweben="ja"] { animation: buddy-schweben 4.6s ease-in-out infinite; }
@keyframes buddy-schweben {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-9px); }
}

@media (prefers-reduced-motion: reduce) {
  .buddy[data-schweben="ja"] { animation: none; }
  .buddy .auge { animation: none !important; }
  .buddy > .figur { animation: none !important; }
  .konfetti-salve { display: none; }
}
