/* ============================================================
 * PROJEKT „MALAFFE" (malaffe-projects)
 * Großer Affe + Sprechblase. Alle Maße hängen über Container-Einheiten an
 * der Bühne (.mx-stage = --stage-height) → passt auf jeden Schirm.
 * Die Zauber-Effekte (Zahlen, Foto, Splitter, Blitz) liegen in einer eigenen
 * fixen Ebene .mx-fx am <body> (gebaut von malaffe-projects.js).
 * ============================================================ */

.mx-stage {
    position: relative;
    height: var(--stage-height);
    overflow: hidden;
    container: mxstage / size;
    background: #fff;
}

.mx-scene {
    position: absolute;
    inset: 0;
    /* Affe: Bildverhältnis 513 × 592. */
    --mx-ape-w: min(66cqh, 38cqw);
    --mx-ape-h: calc(var(--mx-ape-w) * 1.154);
    --mx-gap: clamp(10px, 2.6cqw, 44px);
    --mx-bubble-w: min(640px, calc(96cqw - var(--mx-ape-w) - var(--mx-gap)));
    /* Spricht der Affe, rückt er nach links: Affe + Blase stehen ZUSAMMEN mittig. */
    --mx-shift: calc((var(--mx-gap) + var(--mx-bubble-w)) / -2);
    /* Sprechblase: Rahmen + Zipfel. */
    --mx-bw: clamp(3px, 0.5cqmin, 5px);
    --mx-tail: clamp(16px, 3cqmin, 34px);
}

/* ===== AFFE ===== */
.mx-ape-btn {
    position: absolute;
    left: 50%;
    top: 50%;
    width: var(--mx-ape-w);
    height: var(--mx-ape-h);
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    cursor: pointer;
    transform: translate(-50%, -50%);
    transition: transform 0.7s cubic-bezier(0.45, 0, 0.2, 1);
    -webkit-tap-highlight-color: transparent;
}

.mx-scene.is-aside .mx-ape-btn {
    transform: translate(calc(-50% + var(--mx-shift)), -50%);
}

.mx-scene.is-busy .mx-ape-btn,
.mx-scene.is-done .mx-ape-btn {
    cursor: default;
}

.mx-ape-btn:focus-visible {
    outline: 3px solid var(--blue-main, #3498db);
    outline-offset: 6px;
    border-radius: 20px;
}

.mx-ape {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
    pointer-events: none;
    transform-origin: 50% 100%;
    animation: mx-breathe 3.4s ease-in-out infinite;
    transition: filter 0.2s ease;
    /* Eigene Ebene: das Drehen des großen Bildes läuft auf der GPU, ohne Neuzeichnen. */
    will-change: transform;
    backface-visibility: hidden;
}

.mx-scene:not(.is-busy):not(.is-done) .mx-ape-btn:hover .mx-ape {
    filter: drop-shadow(0 8px 14px rgba(0, 0, 0, 0.22));
}

/* Spricht = sanftes Hin- und Herwiegen, solange die Blase steht.
   🔴 `alternate` zwischen ZWEI Endlagen: mit Zwischen-Keyframes bremst jedes
   Segment einzeln ab (ease-in-out je Segment) → der Affe stockte mitten im
   Schwung kurz (sah aus wie ein Ruckler). */
.mx-scene.is-speaking .mx-ape {
    animation: mx-talk 0.8s ease-in-out infinite alternate;
}

/* Zaubern = kräftiges Wackeln von links nach rechts. */
.mx-scene .mx-ape.is-casting {
    animation: mx-wobble 0.34s ease-in-out infinite alternate;
}

/* Nach der Explosion: benommen ausschwingen. */
.mx-scene .mx-ape.is-dizzy {
    animation: mx-dizzy 1.8s ease-out;
}

@keyframes mx-breathe {
    0%, 100% { transform: scale(1, 1); }
    50%      { transform: scale(1.012, 1.03); }
}

@keyframes mx-talk {
    from { transform: rotate(-2.5deg); }
    to   { transform: rotate(2.5deg); }
}

@keyframes mx-wobble {
    from { transform: translateX(-7%) rotate(-10deg); }
    to   { transform: translateX(7%) rotate(10deg); }
}

@keyframes mx-dizzy {
    0%   { transform: rotate(0deg); }
    12%  { transform: rotate(-8deg); }
    26%  { transform: rotate(7deg); }
    42%  { transform: rotate(-5deg); }
    58%  { transform: rotate(3.5deg); }
    74%  { transform: rotate(-2deg); }
    88%  { transform: rotate(1deg); }
    100% { transform: rotate(0deg); }
}

/* ===== SPRECHBLASE =====
   Steht rechts neben dem Affen, ihre MITTE auf Höhe seines Gesichts; der
   Zipfel zeigt nach links auf ihn. */
.mx-bubble {
    position: absolute;
    left: calc(50cqw - (var(--mx-ape-w) + var(--mx-gap) + var(--mx-bubble-w)) / 2
          + var(--mx-ape-w) + var(--mx-gap));
    top: calc(50cqh - var(--mx-ape-h) * 0.18);
    width: var(--mx-bubble-w);
    max-height: 92cqh;
    box-sizing: border-box;
    padding: clamp(12px, 2.6cqmin, 34px) clamp(16px, 3.4cqmin, 46px);
    background: #fff;
    border: var(--mx-bw) solid var(--dark-bg, #2c3e50);
    border-radius: clamp(18px, 3.6cqmin, 42px);
    box-shadow: 0 10px 28px rgba(0, 0, 0, 0.14);
    transform: translateY(-50%);
    transform-origin: 0 50%;
    scale: 0.4;
    opacity: 0;
    pointer-events: none;
    transition: scale 0.45s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.22s ease;
}

.mx-bubble.is-shown {
    scale: 1;
    opacity: 1;
}

/* Zipfel = halb herausragende, gedrehte Raute mit Rand auf zwei Seiten
   (deckt dabei innen die Randlinie der Blase ab → nahtloser Übergang). */
.mx-bubble::before {
    content: '';
    position: absolute;
    top: 50%;
    left: calc(var(--mx-bw) / -2 - var(--mx-tail) / 2);
    width: var(--mx-tail);
    height: var(--mx-tail);
    margin-top: calc(var(--mx-tail) / -2);
    box-sizing: border-box;
    background: #fff;
    border-left: var(--mx-bw) solid var(--dark-bg, #2c3e50);
    border-bottom: var(--mx-bw) solid var(--dark-bg, #2c3e50);
    transform: rotate(45deg);
}

.mx-text {
    margin: 0;
    font-family: var(--ui-font);
    font-weight: 800;
    font-size: clamp(15px, min(5.4cqh, 2.7cqw), 40px);
    line-height: 1.45;
    color: var(--dark-bg, #2c3e50);
    text-align: left;
    hyphens: none;
}

/* Ein Wort bricht nie zwischen seinen Silben um. */
.mx-word {
    white-space: nowrap;
}

/* Silbenfarben: 1. Silbe rot, 2. blau, 3. wieder rot … (dieselben Farben wie
   Zehner/Einer im Projekt). */
.mx-syl-r { color: var(--red-main, #e74c3c); }
.mx-syl-b { color: var(--blue-main, #3498db); }

/* ===== FARBTAFEL (Klick nach Sprechblase 2) =====
   Steht an der Stelle der Sprechblase rechts neben dem Affen: 10 Karten in
   5 Spalten × 2 Reihen, je Karte die zwei Zahlen + Farbname (wie „4_Farbtafel.pdf"). */
/* Tafel-Zustand: Affe kleiner, Tafel = der GANZE Platz rechts von ihm
   (ohne die 640-px-Grenze der Sprechblase). Der Affe gleitet dabei mit
   (width/height/transform-Übergang am .mx-ape-btn). */
.mx-scene.is-chart {
    --mx-ape-w: min(48cqh, 24cqw);
    --mx-bubble-w: calc(97cqw - var(--mx-ape-w) - var(--mx-gap));
}

.mx-scene.is-chart .mx-ape-btn {
    transition: transform 0.7s cubic-bezier(0.45, 0, 0.2, 1),
                width 0.7s cubic-bezier(0.45, 0, 0.2, 1),
                height 0.7s cubic-bezier(0.45, 0, 0.2, 1);
}

.mx-chart {
    position: absolute;
    left: calc(50cqw - (var(--mx-ape-w) + var(--mx-gap) + var(--mx-bubble-w)) / 2
          + var(--mx-ape-w) + var(--mx-gap));
    top: 50%;
    width: var(--mx-bubble-w);
    height: 94cqh;
    transform: translateY(-50%);
    display: none;
    grid-template-columns: repeat(5, 1fr);
    grid-template-rows: repeat(2, 1fr);
    gap: clamp(6px, 1.4cqmin, 16px);
}

.mx-chart.is-shown {
    display: grid;
}

.mx-card {
    container-type: size;
    min-width: 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    box-sizing: border-box;
    border: 2px solid #333;
    border-radius: clamp(8px, 1.6cqmin, 16px);
    background: var(--mx-card-bg);
    color: var(--mx-card-ink);
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.12);
    animation: mx-card-in 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) both;
    animation-delay: calc(var(--i) * 70ms);
}

/* Zwei Zahlen UNTEREINANDER (wie auf der Farbtafel-Vorlage) — so dürfen sie
   viel größer sein als nebeneinander. */
.mx-card-nums {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.12em;
    font-family: var(--math-font);
    font-weight: 900;
    line-height: 1;
    font-size: min(44cqw, 30cqh);
}

.mx-card-name {
    padding-bottom: 6cqh;
    font-family: var(--ui-font);
    font-weight: 800;
    font-size: min(13cqw, 11cqh);
    white-space: nowrap;
}

@keyframes mx-card-in {
    from { opacity: 0; transform: scale(0.4) rotate(-8deg); }
    to   { opacity: 1; transform: scale(1) rotate(0deg); }
}

/* ===== HOCHFORMAT: Blase oben, Affe darunter ===== */
@container mxstage (max-aspect-ratio: 4 / 5) {
    .mx-scene {
        --mx-ape-w: min(70cqw, 42cqh);
        --mx-shift: 0px;
    }

    .mx-ape-btn,
    .mx-scene.is-aside .mx-ape-btn {
        top: auto;
        bottom: 3cqh;
        transform: translateX(-50%);
        transition: transform 0.7s cubic-bezier(0.45, 0, 0.2, 1),
                    width 0.7s cubic-bezier(0.45, 0, 0.2, 1),
                    height 0.7s cubic-bezier(0.45, 0, 0.2, 1);
    }

    /* Zaubern: Affe kleiner an den linken Rand → rechts daneben Platz fürs Foto. */
    .mx-scene.is-spell {
        --mx-ape-w: min(46cqw, 42cqh);
    }

    .mx-scene.is-spell .mx-ape-btn {
        transform: translateX(calc(-50cqw + 3cqw));
    }

    .mx-bubble {
        left: 50%;
        top: 3cqh;
        width: 92cqw;
        max-height: calc(94cqh - var(--mx-ape-h) - 6cqh);
        overflow: auto;
        transform: translateX(-50%);
        transform-origin: 50% 100%;
    }

    /* Zipfel unten mittig, zeigt nach unten auf den Affen. */
    .mx-bubble::before {
        top: auto;
        bottom: calc(var(--mx-bw) / -2 - var(--mx-tail) / 2);
        left: calc(50% - var(--mx-tail) / 2);
        margin-top: 0;
        transform: rotate(-45deg);
    }

    .mx-text {
        font-size: clamp(15px, min(5.6cqw, 3.6cqh), 36px);
    }

    /* Farbtafel oben über dem (jetzt kleinen) Affen, über die volle Breite. */
    .mx-scene.is-chart {
        --mx-ape-w: min(34cqw, 20cqh);
    }

    .mx-chart {
        left: 50%;
        top: 2cqh;
        width: 96cqw;
        height: calc(96cqh - var(--mx-ape-h) - 5cqh);
        transform: translateX(-50%);
        /* Hochformat: schmale Breite → 4 Spalten (4 + 4 + 2). */
        grid-template-columns: repeat(4, 1fr);
        grid-template-rows: repeat(3, 1fr);
    }
}

/* ===== BÜHNE WACKELT (kurz vor und bei der Explosion) ===== */
.mx-stage.is-shaking {
    animation: mx-shake 0.09s linear infinite;
}

@keyframes mx-shake {
    0%   { transform: translate(0, 0); }
    25%  { transform: translate(-0.5vmin, 0.4vmin); }
    50%  { transform: translate(0.5vmin, -0.3vmin); }
    75%  { transform: translate(-0.3vmin, -0.4vmin); }
    100% { transform: translate(0, 0); }
}

/* ===== ZAUBER-EBENE (am <body>, über der Bühne, unter der Kopfzeile) ===== */
.mx-fx {
    position: fixed;
    inset: 0;
    z-index: 900;
    pointer-events: none;
    overflow: hidden;
    /* Was hier passiert, löst nie ein Layout der übrigen Seite aus. */
    contain: strict;
}

/* Zahlen + Sterne: EINE Zeichenfläche (Partikel, gezeichnet im JS). */
.mx-canvas {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

/* Das Foto ist eine Canvas mit fertig gemaltem Schein (makePhotoArt im JS) —
   bewusst KEIN CSS-filter: der müsste bei jeder Drehung neu gerechnet werden. */
.mx-photo {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    will-change: transform;
}

/* Blitz + Ringe werden schon vor der Explosion unsichtbar angelegt (fertig
   gerastert), erst die Animation macht sie sichtbar. */
.mx-flash,
.mx-ring {
    will-change: transform, opacity;
}

.mx-ring {
    opacity: 0;
}

/* Glühen hinter dem drehenden Foto (wächst per opacity/transform). */
.mx-glow {
    position: absolute;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(255, 225, 110, 0.95) 0%,
                rgba(255, 200, 60, 0.45) 40%, rgba(255, 200, 60, 0) 70%);
    will-change: transform, opacity;
}

.mx-flash {
    position: absolute;
    inset: 0;
    /* Mittelpunkt = Ort des Fotos (setzt das JS). */
    background: radial-gradient(circle at var(--mx-cx, 50%) var(--mx-cy, 50%),
                #fff 0%, #fff8d6 35%, rgba(255, 255, 255, 0) 78%);
    opacity: 0;
}

.mx-ring {
    position: absolute;
    left: 50%;
    top: 50%;
    width: 24vmin;
    height: 24vmin;
    box-sizing: border-box;
    border: 10px solid #ffd84d;
    border-radius: 50%;
}
