/* ===== SoulKeeper - Level 1 Gameplay ====================================
   Gegner (Rabe/Zombie/Hexe), Trefferboxen, Gameplay-HUD (Punkte/Timer/
   Waffenwahl/Hexen-Leiste). Alles hier lebt ausschließlich innerhalb des
   bestehenden Ankers #level1-spielbereich bzw. als eigenes HUD-Overlay in
   #scene-level1 (siehe index.html) - die Parallax-Ebenen selbst (css/
   level1.css) bleiben unangetastet. Erzeugt/positioniert von
   js/level1-gameplay.js. */

/* ===== Gameplay-HUD =====
   Eine obere Zeile (Held+Leben/Punkte/Zeit/Ges. Punkte/Best) plus höchstens
   eine Boss-Leiste als zweite Zeile darunter (siehe .level1-hud-block/
   .level1-hud-reihe weiter unten). Die Waffenauswahl ist NICHT mehr Teil
   dieser HUD-Zeile, sondern ein eigener Overlay unten links (siehe
   .level1-waffen-auswahl weiter unten). */
.level1-spiel-hud {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    z-index: 6;
    display: flex;
    justify-content: center;
    padding: clamp(0.8rem, calc(2.5 * var(--uw)), 1.6rem);
    pointer-events: none;
}

/* Umschließt obere Zeile + optionale Boss-Leiste - sitzt eng um seinen
   Inhalt (width:fit-content). Dadurch übernimmt eine width:100% auf der
   Boss-Leiste automatisch exakt die Breite der oberen Zeile, ohne dass JS
   irgendetwas messen müsste ("Endboss-Anzeige an die Breite der oberen
   Zeile angepasst"). max-width verhindert Überlauf auf schmalen Screens -
   dort wrappen stattdessen die einzelnen Kästen der oberen Zeile
   (.level1-hud-reihe hat flex-wrap). */
.level1-hud-block {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 0.5rem;
    width: fit-content;
    max-width: 100%;
}

.level1-hud-reihe {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    justify-content: center;
    gap: 0.8rem;
}

.level1-hud-spieler,
.level1-hud-punkte,
.level1-hud-timer {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.25rem;
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 8px;
    padding: 0.5rem 0.8rem;
    backdrop-filter: blur(3px);
}

.level1-hud-label {
    font-size: 0.55rem;
    letter-spacing: 0.05em;
    color: var(--text-dim);
}

.level1-hud-wert {
    font-size: 0.8rem;
    color: var(--accent-bright);
}

.level1-hud-ziel-trenner {
    color: var(--text-dim);
}

/* ===== Seelen-Kasten (Punktesystem Teil 4) =====
   Nutzt bewusst die unveränderte .level1-hud-punkte-Basis (Rahmen, Panel-
   Hintergrund, Label/Wert-Muster) - keine zweite Kastenoptik und keine neue
   Farbwelt. Einziger Unterschied: die rechte Zahl (insgesamt BEFREITE
   Seelen) ist gedimmt wie der Trenner daneben, damit die linke Zahl - die
   im LAUFENDEN Level gesammelten, also die während des Spielens
   aussagekräftigere - klar die Hauptzahl bleibt. Befüllt von
   js/endauswertung.js: aktualisiereSeelenAnzeige, siehe #level1-hud-seelen
   in index.html. */
.level1-hud-seelen .level1-hud-seelen-befreit {
    color: var(--text-dim);
}

/* ===== Phasen-Punkte-Kasten (Punkte X / Ziel) =====
   Eigener Rahmenzustand statt des normalen --panel-border (siehe
   .level1-hud-punkte oben, gilt für diesen Kasten weiterhin als
   Basis-Look) - Rot solange die Schwelle der aktuellen Punktesammelphase
   nicht erreicht ist (js/level1-gameplay.js: aktualisierePhasenZielStatus),
   selbe Rotfarbe wie der bestehende Lebensverlust-Blitz (--danger-color,
   siehe css/variables.css und weiter unten) statt einer neu erfundenen
   Farbe. Wird während der Bossphase komplett ausgeblendet (dort gilt die
   Hexen-LP-Leiste), siehe js/level1-gameplay.js: starteHexenPhase. */
.level1-hud-punkte-phase {
    border-color: var(--danger-color);
    transition: border-color 0.25s ease, box-shadow 0.25s ease;
    /* Nur Positionierungskontext für den Perfekt-Schein weiter unten
       (.level1-hud-punkte-phase--perfekt::after) - position:relative
       ändert am Fluss-Layout des Kastens nichts. */
    position: relative;
}

/* Schwelle erreicht/übertroffen - schwenkt auf die bestehende Erfolgs-/
   Akzentfarbe um (dasselbe Muster wie z.B. .level1-waffe-knopf[aria-
   pressed="true"] oder .schwierigkeit-swatch[aria-pressed="true"]), keine
   neue Farbwelt. */
.level1-hud-punkte-phase--erreicht {
    border-color: var(--accent-bright);
    box-shadow: 0 0 10px var(--accent);
}

/* Einmaliger, kurzer Blitz beim ERSTEN Erreichen der Schwelle in dieser
   Phase (nicht bei jedem weiteren Kill danach) - dieselbe Blitz-Technik wie
   .level1-lebenverlust-blitz weiter unten, hier aber
   direkt auf den Kastenrahmen statt eines bildschirmfüllenden Overlays.
   Keine Dauerschleife (kein infinite), klingt nach 0.6s wieder in den
   normalen "erreicht"-Zustand ab. */
.level1-hud-punkte-phase--blitz {
    animation: level1-ziel-erreicht-blitz-kf 0.6s ease-out;
}

@keyframes level1-ziel-erreicht-blitz-kf {
    0%   { box-shadow: 0 0 0 0 var(--accent-bright); }
    35%  { box-shadow: 0 0 20px 5px var(--accent-bright); }
    100% { box-shadow: 0 0 10px var(--accent); }
}

/* Perfekte Runde (Punktesystem Teil 3) - dauerhaft pulsierender gelber
   Schein, solange die laufende Kreaturenphase noch fehlerfrei ist (kein
   Fehlschuss, keine ungetroffen entkommene Kreatur). Wird ab dem 10. Kill
   gesetzt und beim Verlust der Perfekten Runde sofort und endgültig
   wieder entfernt, siehe js/level1-gameplay.js/js/level2-gameplay.js:
   aktualisierePerfektPuls/brichPerfekteRundeAb (beide Level teilen sich
   dasselbe HUD-Element #level1-hud-punkte-phase und damit diese Regel).

   Bewusst ein eigenes ::after-Overlay statt einer weiteren Animation auf
   dem Kasten selbst: border-color und box-shadow des Kastens tragen
   bereits den Schwellenstatus (rot / erreicht) samt einmaligem
   Schwellen-Blitz. Beides bliebe nicht gleichzeitig ablesbar, wenn der
   Dauerpuls dieselben Eigenschaften überschriebe - die letzte
   Animation gewänne und der Schwellen-Blitz wäre nicht mehr
   erkennbar. Auf dem Overlay stören sich die beiden Aussagen dagegen
   nicht: Farbe = Schwelle, gelber Ring darum = perfekt. */
.level1-hud-punkte-phase--perfekt::after {
    content: '';
    position: absolute;
    /* Liegt als Ring AUSSERHALB des Kastenrahmens, verdeckt also weder
       Rahmenfarbe noch Inhalt. Der HUD-Abstand (.level1-hud-reihe gap
       0.8rem) ist groß genug, dass nichts an den Nachbarkasten stößt. */
    inset: -4px;
    border: 2px solid var(--perfekt-color);
    border-radius: 11px;
    pointer-events: none;
    animation: level1-perfekt-puls-kf 1.1s ease-in-out infinite;
}

@keyframes level1-perfekt-puls-kf {
    0%, 100% { opacity: 0.35; box-shadow: 0 0 4px 0 var(--perfekt-color); }
    50%      { opacity: 1;    box-shadow: 0 0 14px 3px var(--perfekt-color); }
}

/* ===== Waffenauswahl (unten links) =====
   Eigener Overlay wie .audio-controls (css/himmel.css), spiegelbildlich
   unten links statt unten rechts, mit demselben Randabstand (identische
   clamp()-Werte). Pistole über Pumpgun statt nebeneinander. Sichtbarkeit
   läuft synchron zu #level1-spiel-hud, siehe js: zeigeSpielHud()/
   versteckeSpielHud() (level1/2/3-gameplay.js). */
.level1-waffen-auswahl {
    position: absolute;
    left: clamp(0.8rem, calc(2.5 * var(--uw)), 1.6rem);
    bottom: clamp(0.8rem, calc(2.5 * var(--uw)), 1.6rem);
    z-index: 6;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 8px;
    padding: 0.5rem;
    backdrop-filter: blur(3px);
    pointer-events: auto;
}

.level1-waffe-knopf {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.5rem 0.6rem;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid var(--panel-border);
    color: var(--text);
    cursor: pointer;
    border-radius: 4px;
    white-space: nowrap;
}

.level1-waffe-knopf:hover {
    border-color: var(--accent-bright);
}

.level1-waffe-knopf[aria-pressed="true"] {
    border-color: var(--accent-bright);
    color: var(--accent-bright);
    box-shadow: 0 0 10px var(--accent);
}

/* Icon deutlich größer als die HUD-Pixel-Schrift (Vorgabe: "kaum zu
   erkennen") - bewusst UNABHÄNGIG vom Breakpoint unten, nicht nur im
   Icon-only-Zustand. */
.level1-waffe-icon {
    font-size: 1.4rem;
    line-height: 1;
}

.level1-waffe-text {
    font-size: 0.55rem;
}

/* Schmale Screens: nur noch die Icons, kein Text mehr (Punkt 2). */
@media (max-width: 560px) {
    .level1-waffe-text {
        display: none;
    }
}

/* ===== Boss-LP-Leiste (zweite HUD-Zeile) =====
   Eigenes, HORIZONTALES Layout (anders als die Kästen der oberen Zeile) -
   Bossname direkt neben dem Balken, in einer Linie. width:100% vom
   umgebenden .level1-hud-block (siehe oben) übernimmt automatisch die
   Breite der oberen Zeile. */
.level1-hexe-leiste {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 0.6rem;
    width: 100%;
    box-sizing: border-box;
    background: var(--panel-bg);
    border: 1px solid var(--panel-border);
    border-radius: 8px;
    padding: 0.5rem 0.8rem;
    backdrop-filter: blur(3px);
}

.level1-hexe-balken-huelle {
    flex: 1 1 auto;
    min-width: 60px;
    height: 10px;
    border-radius: 5px;
    background: rgba(255, 255, 255, 0.12);
    border: 1px solid var(--panel-border);
    overflow: hidden;
}

.level1-hexe-balken-fuellung {
    height: 100%;
    width: 100%;
    background: linear-gradient(90deg, var(--accent) 0%, var(--accent-bright) 100%);
    transition: width 0.2s ease;
}

/* Kritisch (letzte 20% LP, siehe js: aktualisiereHexenBalken/
   aktualisiereBossBalken) - Füllfarbe pulsiert, Tempo kommt live aus JS
   über --kritisch-tempo (wird dort mit sinkenden LP schneller), Fallback
   0.6s falls die Custom Property aus irgendeinem Grund fehlt. */
.level1-hexe-balken-fuellung--kritisch {
    animation-name: level1-boss-balken-pulsieren;
    animation-duration: var(--kritisch-tempo, 0.6s);
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
}

@keyframes level1-boss-balken-pulsieren {
    0%, 100% { filter: brightness(1); }
    50%      { filter: brightness(1.9); }
}

/* ===== Schwierigkeit-Umschalter (Settings-Panel) =====
   Textbuttons statt Farb-Swatches (kein sinnvolles Farbäquivalent für
   Normal/Schwer/Extrem) - Optik an .settings-musik-knopf angelehnt, Zustand
   (aria-pressed) wie .theme-swatch gehandhabt. */
.schwierigkeit-switch {
    display: flex;
    gap: 0.4rem;
}

.schwierigkeit-swatch {
    font-size: 0.55rem;
    padding: 0.5rem 0.6rem;
    background: rgba(255, 255, 255, 0.06);
    border: 1px solid var(--panel-border);
    color: var(--text-dim);
    cursor: pointer;
    border-radius: 4px;
}

.schwierigkeit-swatch:hover {
    color: var(--text);
    border-color: var(--accent-bright);
}

.schwierigkeit-swatch[aria-pressed="true"] {
    border-color: var(--accent-bright);
    color: var(--accent-bright);
    box-shadow: 0 0 10px var(--accent);
}

/* ===== Gegner ===== */
/* Äußerer Wrapper: reine Positionierung + horizontale Bewegung (per
   Inline-Style `left`/`transition` aus js/level1-gameplay.js, damit jede
   Instanz ihre eigene Tiefe/Dauer bekommt). Quadratisch, da alle
   Gegner-SVGs 1000x1000px sind. */
.l1-feind {
    position: absolute;
    aspect-ratio: 1 / 1;
    /* Kein eigenes cursor:crosshair mehr - erbt das waffenabhängige
       Fadenkreuz von .level1-gameplay-aktiv (siehe dort). Ein eigener Wert
       hier würde beim Hover über einem Gegner den nativen Browser-Cursor
       zurückbringen und so mit dem SVG-Fadenkreuz des Elternelements
       kollidieren. */
}

/* Innerer Wrapper: trägt die Wackel-/Bob-Animation, getrennt vom äußeren
   `left`-Übergang, damit beide Bewegungen sich nicht gegenseitig
   überschreiben (unterschiedliche CSS-Eigenschaften: left vs. transform). */
.l1-feind-wackel {
    position: relative;
    width: 100%;
    height: 100%;
    transform-origin: center;
}

@keyframes l1-zombie-wackel {
    0%   { transform: rotate(-5deg); }
    25%  { transform: rotate(5deg); }
    50%  { transform: rotate(-5deg); }
    75%  { transform: rotate(5deg); }
    100% { transform: rotate(-5deg); }
}

.l1-feind--zombie.l1-feind--bewegt .l1-feind-wackel {
    animation: l1-zombie-wackel 0.6s ease-in-out infinite;
}

/* Treffer-Flash (Pumpgun trifft, Zombie überlebt den Schuss) - färbt die
   tatsächliche SVG-Fläche kurz dunkelrot ein statt nur einen Schein
   drumzulegen: CSS-fill auf dem injizierten <path> schlägt dessen
   fill="#000000"-Attribut (siehe img/level1/Enemy/Zombie*.svg). Re-Trigger
   über Remove+Reflow+Add wie bei verliereLebenMitBlitz (js/level1-gameplay.js). */
@keyframes l1-zombie-treffer-flash {
    0%   { fill: #000000; }
    25%  { fill: #8b0000; }
    100% { fill: #000000; }
}

.l1-feind--zombie.l1-feind--treffer-flash .l1-feind-svg svg path {
    animation: l1-zombie-treffer-flash 0.35s ease-out;
}

@keyframes l1-rabe-bob {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-6px); }
}

.l1-feind--rabe .l1-feind-wackel {
    animation: l1-rabe-bob 2s ease-in-out infinite;
}

/* Injiziertes SVG-Markup (siehe js/level1-gameplay.js: ladeSvgMarkup) -
   pointer-events:none auf der Wurzel, visiblePainted auf den Kind-Shapes:
   Klicks registrieren dadurch nur auf tatsächlich gefüllten Pixeln,
   transparente Bereiche lassen den Klick zum darunterliegenden Element
   durchfallen. Das ist die silhouettengenaue Basis-Trefferlogik. Sie liegt
   seit der Hitbox-Umstellung unter der gepolsterten .l1-feind-hitbox, die
   auf JEDEM Schwierigkeitsgrad erzeugt wird - relevant bleibt sie damit nur
   noch, falls dort einmal wieder kein Box-Element gesetzt wird. */
.l1-feind-svg {
    width: 100%;
    height: 100%;
}

.l1-feind-svg svg {
    display: block;
    width: 100%;
    height: 100%;
    pointer-events: none;
}

.l1-feind-svg svg * {
    pointer-events: visiblePainted;
}

/* Easter Egg "Durchfallmann" (js/level1-gameplay.js: spawneHexe) - PNG statt
   injiziertem SVG-Markup, deshalb hier pointer-events:auto direkt am <img>
   statt der visiblePainted-Kaskade oben (Browser können bei <img> keine
   Alpha-genaue Trefferprüfung, siehe Kommentar dort - die Trefferfläche ist
   dadurch das volle Rechteck statt der Hexen-Silhouette). */
.l1-feind-svg img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: contain;
    pointer-events: auto;
}

/* Dreistufige Trefferbox nach Schwierigkeit (Punkt 21/23: Normal=XL,
   Schwer=L, Extrem=S) - liegt sichtbar über dem SVG (spätere Stelle im DOM),
   fängt Klicks unabhängig von Transparenz ab. Die tatsächliche Größe
   kommt schwierigkeitsabhängig als Inline-Style aus js/level1-gameplay.js
   (KONFIG[schwierigkeit].hitboxInsetProzent) - der Wert hier ist nur ein
   Fallback, falls aus irgendeinem Grund kein Inline-Wert gesetzt wurde.
   Gilt seit der Hitbox-Umstellung für ALLE Grade (45/22/15%) und für ALLE
   Gegner inklusive Hexe/Durchfallmann - es gibt keinen Fall mehr, in dem
   dieses Element weggelassen wird.

   max(<Wert>%, 20px) sorgt für mindestens 20px echten Rand auch bei
   kleinen/entfernten Kreaturen (vor allem Raben auf hinten/mitte, nur
   55-90px groß) - ein rein prozentualer Rand wäre dort bei einem sich
   bewegenden, wippenden Ziel zu knapp zum zuverlässigen Treffen. */
.l1-feind-hitbox {
    position: absolute;
    inset: calc(-1 * max(22%, 20px));
    pointer-events: auto;
}

/* Debug-Sichtbarkeit der Trefferbox (?hitbox=1 in der URL, siehe
   js/level1-gameplay.js: HITBOX_DEBUG) - zeigt die tatsächliche Klickfläche
   grau/gestrichelt an, damit sich Trefferbox-Probleme visuell statt nur
   rechnerisch prüfen lassen. Nur zu Testzwecken, ohne den Parameter bleibt
   .l1-feind-hitbox wie gehabt unsichtbar. */
.l1-feind-hitbox--debug {
    background: rgba(160, 160, 160, 0.45);
    outline: 1px dashed rgba(255, 255, 255, 0.85);
}

/* LP-Debug-Anzeige (?hitbox=1): Styling jetzt gemeinsam in css/base.css:
   .feind-lp-debug (siehe dort) - js/level1-gameplay.js weist diese Klasse
   zusätzlich zu .l1-feind-lp-debug zu, das hier nur noch als
   querySelector-Hook dient (verarbeiteTreffer/treffeHexe), kein eigenes
   CSS mehr nötig. */

/* Hexe/Durchfallmann: benutzt seit der Hitbox-Umstellung dieselbe echte,
   gepolsterte .l1-feind-hitbox wie jeder andere Gegner (siehe
   js/level1-gameplay.js: spawneHexe) - die frühere Sonderregel
   "immer silhouettengenau" und die dazugehörige, absichtlich nicht
   klickbare Debug-Box (.l1-feind-hexe-hitbox-debug) sind damit entfallen.
   Im Debug-Modus (?hitbox=1) wird jetzt die echte Box eingefärbt. */
.l1-feind--hexe {
    z-index: 1;
}

/* ===== Fadenkreuz während des aktiven Gameplays =====
   Deckt die gesamte Level-1-Szene ab (nicht nur einzelne Gegner, siehe
   .l1-feind oben, das bleibt für den Hover-Fall unverändert) - Klasse wird
   von js/level1-gameplay.js exakt während laeuft===true gesetzt/entfernt
   (starte()/beende()/Sieg/Game Over).

   Paket 3: dieselbe Klasse/derselbe Zeitraum verhindert zusätzlich Text-/
   Bild-/SVG-Markierung und Drag beim schnellen/gehaltenen Klicken -
   ergänzt js/level1-gameplay.js (selectstart/dragstart preventDefault,
   nur als Sicherheitsnetz für Browser, die trotz dieser CSS-Eigenschaften
   bei sehr schnellen Klicks noch reagieren). Bewusst an dieselbe, bereits
   korrekt gescopte Klasse gehängt statt eine zweite einzuführen - gilt
   dadurch automatisch nur während des aktiven Gameplays, nicht in Menü/
   Namenseingabe/Seelenpfad.

   Styling jetzt gemeinsam mit Level 2/3 in css/base.css definiert (siehe
   dort, .level1-gameplay-aktiv). */

/* ===== Schuss-Lücke: oberste 20vh des Sichtbereichs (Bugfix) =====
   Die Kamera fährt zu Level 1 bewusst nur 80vh statt 100vh (siehe
   css/base.css: .story-track--level1) - der Himmel bleibt am oberen
   Bildrand sichtbar. Diese oberen 20vh gehören im Dokumentfluss aber noch
   zu #scene-himmel (nicht zu #scene-level1), obwohl sie während Level 1
   sichtbar/anklickbar wirken sollten - Fadenkreuz-Cursor UND Klick-Handler
   (an #level1-ebene-vorne gebunden) griffen dort bisher nicht, "Schießbar
   überall auf dem Screen" galt de facto nicht für diesen Streifen.
   .level1-schuss-luecke (siehe index.html, letztes Kind von
   #level1-ebene-vorne) deckt genau diesen Streifen ab - position:absolute
   mit festem top:-20vh (NICHT als Teil von #level1-ebene-vornes eigener
   Höhe/Prozent-Positionierung, die von den Grabstein-/Baum-%-Werten aus
   js/level1-szene.js abhängt) und poppt dank #scene-level1{overflow:
   visible} (bereits für die Ebene-5-Äste vorhanden, css/level1.css) über
   den eigenen Szenen-Rand hinaus - liegt dadurch räumlich exakt über dem
   Ende von #scene-himmel und gewinnt den Stapel (spätere DOM-Reihenfolge,
   gleicher z-index:1 wie jede .scene). Komplett unsichtbar (kein
   background/border) - der durchscheinende Himmel-Hintergrund bleibt
   optisch unverändert, nur das Klick-/Cursor-Verhalten ändert sich.
   pointer-events bleibt AUSSERHALB des aktiven Gameplays bewusst none -
   sonst würde dieser Streifen (der bei translateY(0), also VOR
   Levelstart, noch im unteren Fünftel des Startbildschirms sichtbar ist)
   Klicks auf Highscore/Settings/Seelenpfad/Spielwerte dort abfangen. */
.level1-schuss-luecke {
    position: absolute;
    left: 0;
    width: 100%;
    top: calc(-20 * var(--uh));
    height: calc(20 * var(--uh));
    pointer-events: none;
}

.level1-gameplay-aktiv .level1-schuss-luecke {
    pointer-events: auto;
}

/* ===== Punkte-Popup bei Treffer ===== */
/* Erscheint an der tatsächlichen Trefferposition (Inline-left/top von
   js/level1-gameplay.js gesetzt, siehe positionUeberElement) - jede
   Instanz ist ein eigenes, kurzlebiges Element (entfernt sich selbst nach
   der Animation, siehe animationend-Listener), dadurch überschreiben sich
   mehrere gleichzeitige Treffer nicht gegenseitig. */
/* Styling jetzt gemeinsam mit Level 2/3 in css/base.css definiert (siehe
   dort, .l1-punkte-popup + @keyframes punkte-auf). */

/* ===== Hexe: Todesanimation (Sturzflug + Drehung) =====
   Nachbesserung: rotate() und translateY() DÜRFEN NICHT im selben
   Transform/auf demselben Element stehen - sonst dreht sich die
   "nach unten"-Richtung während der Rotation mit, die Hexe fällt dann
   spiralförmig immer weiter nach außen statt geradlinig nach unten
   (genau das war der Bug). Deshalb aufgeteilt auf zwei Ebenen:
   - äußerer Wrapper (dieses Element): NUR translateY - geradliniger,
     senkrechter Fall in normalen (nicht rotierten) Bildschirm-Koordinaten.
   - inneres .l1-feind-wackel (siehe unten): NUR rotate - dreht sich um die
     eigene Achse (transform-origin:center, siehe weiter oben), unabhängig
     von der Fallrichtung des äußeren Wrappers, wodurch das Ganze wie ein
     sich drehender Sturzflug statt einer Spirale wirkt.
   Dauer UND Drehwinkel kommen dynamisch aus js/level1-gameplay.js
   (--l1-hexe-tod-dauer/--l1-hexe-tod-grad, an die tatsächliche Länge des
   gewählten Todesschrei-Sounds gekoppelt, siehe dortiger Kommentar bei
   starteFallAnimation) - als CSS-Variablen auf dem Wrapper gesetzt, vererben
   sich aber automatisch an das Kind-Element weiter, keine zweite JS-Stelle
   nötig. linear statt easing: konstante Dreh-/Fallgeschwindigkeit, darf
   über die volle Dauer nicht sichtbar "langsamer werden". Position wird vor
   dem Hinzufügen dieser Klasse bereits eingefroren (px statt %, transition
   auf 'none' gesetzt), damit sie nicht gleichzeitig noch zu ihrem alten
   Kreuzungsziel weiterläuft. Bewusst OHNE Opacity-Fade - die Hexe bleibt
   während des gesamten Falls voll sichtbar, sie verschwindet einzig
   dadurch, dass sie den sichtbaren Bereich nach unten verlässt (#story hat
   overflow:hidden). */
.l1-feind--hexe-tod {
    transition: transform var(--l1-hexe-tod-dauer, 3s) linear;
    transform: translateY(calc(160 * var(--uh)));
}

.l1-feind--hexe-tod .l1-feind-wackel {
    transition: transform var(--l1-hexe-tod-dauer, 3s) linear;
    transform: rotate(var(--l1-hexe-tod-grad, 1080deg));
}

/* ===== Leben-Verlust-Blitz (Hexenphase-Timer) =====
   Deckt die ganze Level-1-Szene ab und legt kurz einen roten Rand-Schein
   darüber; pointer-events:none, blockiert also nie Klicks auf Gegner.
   Getriggert per Klassenwechsel einmal pro verlorenem Viertel der
   60-Sekunden-Hexenphase (siehe js/level1-gameplay.js:
   verliereLebenMitBlitz). */
.level1-lebenverlust-blitz {
    position: absolute;
    inset: 0;
    z-index: 7;
    pointer-events: none;
    opacity: 0;
}

.level1-lebenverlust-blitz--aktiv {
    animation: level1-lebenverlust-blitz-kf 0.4s ease-out;
}

@keyframes level1-lebenverlust-blitz-kf {
    0%   { opacity: 0; box-shadow: inset 0 0 0 0 var(--danger-color); }
    30%  { opacity: 1; box-shadow: inset 0 0 90px 26px var(--danger-color); }
    100% { opacity: 0; box-shadow: inset 0 0 0 0 var(--danger-color); }
}

/* ===== Game Over (Hexenphase-Timer abgelaufen) =====
   Liegt wie .level-einblendung/.countdown-overlay außerhalb von
   #story-track (siehe index.html) - Sichtbarkeit rein zeitgesteuert aus
   js/level1-gameplay.js (loeseGameOverAus/zeigeGameOverOverlay), egal wo
   die Kamera gerade steht. "Blut" läuft von oben herein (clip-path-
   Übergang), bei 50% der Dauer blendet der wiederverwendete
   Level-Einblendung-Textstil (siehe css/uebergang.css) ein. */
.level1-gameover-overlay {
    position: absolute;
    inset: 0;
    z-index: 20;
    pointer-events: none;
    overflow: hidden;
}

.level1-gameover-blut {
    position: absolute;
    inset: 0;
    background: linear-gradient(to bottom,
        rgba(120, 0, 0, 0.94) 0%,
        rgba(94, 0, 0, 0.85) 45%,
        rgba(60, 0, 0, 0.55) 75%,
        rgba(40, 0, 0, 0.15) 100%);
    clip-path: inset(0 0 100% 0);
    transition: clip-path 3s ease-in;
}

.level1-gameover-overlay.level1-gameover--aktiv .level1-gameover-blut {
    clip-path: inset(0 0 0% 0);
}

.level1-gameover-text {
    position: relative;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 0 1rem;
    opacity: 0;
    transition: opacity 0.9s ease;
}

.level1-gameover-overlay.level1-gameover--text-sichtbar .level1-gameover-text {
    opacity: 1;
}

/* ===== Durchfallmann: Silben-Bilder (Durch/Fall/Mann) =====
   Kurzer Fade-in/Fade-out - synchron zum Song eingeblendet (siehe
   js/level1-gameplay.js: zeigeSilbenBild/planeDurchfallmannSilbenBilder).
   left/top kommen als Inline-Style von dort (zufällig gestreut statt fest
   mittig) - max-width/max-height hier in % (nicht vh, damit sie zum selben
   Koordinatensystem wie left/top gehören) sind bewusst klein genug gewählt,
   dass sie zusammen mit dem dortigen Streubereich (20-80% / 18-58%) IMMER
   komplett innerhalb von #level1-spielbereich bleiben, egal wo der
   Zufallspunkt landet. pointer-events:none, damit die Einblendung nie
   Klicks auf den Boss blockiert. */
.l1-silben-bild {
    position: absolute;
    max-width: 34%;
    max-height: 30%;
    transform: translate(-50%, -50%);
    pointer-events: none;
    z-index: 7;
    filter: drop-shadow(0 0 18px rgba(0, 0, 0, 0.85));
    animation: l1-silben-flash 0.9s ease-out forwards;
}

@keyframes l1-silben-flash {
    0%   { opacity: 0; transform: translate(-50%, -50%) scale(0.7); }
    15%  { opacity: 1; transform: translate(-50%, -50%) scale(1.08); }
    25%  { opacity: 1; transform: translate(-50%, -50%) scale(1); }
    70%  { opacity: 1; }
    100% { opacity: 0; transform: translate(-50%, -50%) scale(1); }
}

/* ===== Spinnen-Animation (Outro nach dem Hexensieg) =====
   Rein atmosphärisches Vordergrund-Element, ausgelöst einmalig aus
   js/level1-gameplay.js (starteSpinnenAnimation). Liegt über ALLEM,
   auch über der Dialogbox (z-index:5, siehe css/dialog.css) und dem
   Game-Over-Overlay (z-index:20) - soll wirken, als würde eine große
   Spinne direkt vor dem Bildschirm/Betrachter vorbeikrabbeln.
   Drei Ebenen, siehe Kommentar in index.html:
   - .level1-spinne-pfad: NUR translate (krummer Laufweg, von JS per
     CSS-Variablen zufällig gesetzt)
   - .level1-spinne-dreh: NUR rotate (Blickrichtung je gerader Wegetappe,
     dieselbe Herleitung wie beim Level-2-Endgegner - ebenfalls von JS
     gesetzt, siehe --l1-spinne-blick1/2/3)
   - .level1-spinne-bild: Unschärfe + kontinuierliches, sehr feines
     Beinzittern (eigene rotate-Oszillation), rein CSS, läuft nur
     während das Overlay sichtbar ist. */
.level1-spinne-overlay {
    position: absolute;
    inset: 0;
    z-index: 25;
    overflow: hidden;
    pointer-events: none;
}

.level1-spinne-pfad {
    position: absolute;
    top: 0;
    left: 0;
    width: var(--l1-spinne-groesse, calc(26 * var(--uh)));
    height: var(--l1-spinne-groesse, calc(26 * var(--uh)));
    opacity: 0;
    will-change: transform;
}

.level1-spinne-pfad--lauf {
    animation: l1-spinne-weg var(--l1-spinne-dauer, 12s) linear forwards;
}

@keyframes l1-spinne-weg {
    0%   { transform: translate(var(--l1-spinne-start-x, calc(70 * var(--uw))), var(--l1-spinne-start-y, calc(-18 * var(--uh)))); opacity: 0; }
    8%   { opacity: 1; }
    38%  { transform: translate(var(--l1-spinne-biegung1-x, calc(45 * var(--uw))), var(--l1-spinne-biegung1-y, calc(32 * var(--uh)))); }
    70%  { transform: translate(var(--l1-spinne-biegung2-x, calc(15 * var(--uw))), var(--l1-spinne-biegung2-y, calc(68 * var(--uh)))); }
    92%  { opacity: 1; }
    100% { transform: translate(var(--l1-spinne-ziel-x, calc(5 * var(--uw))), var(--l1-spinne-ziel-y, calc(118 * var(--uh)))); opacity: 0; }
}

.level1-spinne-dreh {
    width: 100%;
    height: 100%;
    transform-origin: 50% 50%;
}

.level1-spinne-pfad--lauf .level1-spinne-dreh {
    animation: l1-spinne-blickrichtung var(--l1-spinne-dauer, 12s) ease-in-out forwards;
}

/* Blickrichtung folgt den drei geraden Wegetappen aus l1-spinne-weg oben
   (0-38%, 38-70%, 70-100%) - Vorgabe: "die Unterkante des Bildes soll
   immer in Laufrichtung zeigen", wie beim Level-2-Endgegner
   (js/level2-gameplay.js: spinnenBlickrichtungGrad). Winkel bleibt
   innerhalb jeder Etappe konstant und dreht nur in einem kurzen Fenster
   um den jeweiligen Biegepunkt (36-40%, 68-72%) auf den neuen Wert - exakt
   dieselbe "kurzer Dreh am Etappenwechsel, sonst konstant"-Optik wie
   Level 2s SPINNE_DREH_UEBERGANG_S (dort 0.6s CSS-transition statt
   Keyframe-Fenster, hier wegen des rein deklarativen Weges als
   Keyframe-Fenster nachgebildet). */
@keyframes l1-spinne-blickrichtung {
    0%   { transform: rotate(var(--l1-spinne-blick1, 0deg)); }
    36%  { transform: rotate(var(--l1-spinne-blick1, 0deg)); }
    40%  { transform: rotate(var(--l1-spinne-blick2, 0deg)); }
    68%  { transform: rotate(var(--l1-spinne-blick2, 0deg)); }
    72%  { transform: rotate(var(--l1-spinne-blick3, 0deg)); }
    100% { transform: rotate(var(--l1-spinne-blick3, 0deg)); }
}

.level1-spinne-bild {
    display: block;
    width: 100%;
    height: 100%;
    filter: blur(4px);
    transform-origin: 50% 50%;
    animation: l1-spinne-beine 0.4s ease-in-out infinite alternate;
}

@keyframes l1-spinne-beine {
    0%   { transform: rotate(-1.3deg); }
    100% { transform: rotate(1.3deg); }
}
