# Pyxel Studio — Verbesserte Eishöhle-Grafik
import pyxel
import random
import math

SCREEN_W = 256
SCREEN_H = 192
GRAVITY = 0.28
WALK_SPEED = 1.8
JUMP_PWR = -5.8
WALL_JUMP_X = 4.2
WALL_JUMP_Y = -4.8
STAMINA_MAX = 100
COYOTE_TIME = 8
JUMP_BUFFER = 8


class Particle:
    def __init__(self, x=None, y=None, vx=0, vy=0, col=7, life=30, kind="dust"):
        self.x = x if x is not None else random.randint(0, SCREEN_W)
        self.y = y if y is not None else random.randint(0, SCREEN_H)
        self.vx = vx
        self.vy = vy
        self.col = col
        self.life = life
        self.max_life = life
        self.kind = kind

    def update(self, wind=0):
        if self.kind == "leaf":
            self.x += self.vx + wind * 1.5
            self.y += self.vy
            self.vx = math.sin(self.life * 0.3) * 0.6
            self.vy = min(self.vy + 0.05, 0.8)
            if self.x < -5: self.x = SCREEN_W + 5
            if self.x > SCREEN_W + 5: self.x = -5
            if self.y > SCREEN_H + 5: self.y = -5
        elif self.kind == "snow":
            self.x += self.vx + wind * 2 + math.sin(self.life * 0.1) * 0.3
            self.y += self.vy
            if self.x > SCREEN_W + 5: self.x = -5
            if self.x < -5: self.x = SCREEN_W + 5
            if self.y > SCREEN_H + 5: self.y = -5
        elif self.kind == "ice_drip":
            self.x += self.vx
            self.y += self.vy
            self.vy = min(self.vy + 0.04, 1.5)
            if self.y > SCREEN_H + 5:
                self.life = 0
        elif self.kind == "rain":
            self.x += self.vx + wind * 1.2
            self.y += self.vy
            if self.y > SCREEN_H + 5:
                self.y = -5
                self.x = random.randint(0, SCREEN_W)
        elif self.kind == "ember":
            self.x += self.vx + math.sin(self.life * 0.2) * 0.4
            self.y += self.vy
            self.vy -= 0.025
            if self.y < -5:
                self.y = SCREEN_H + 5
                self.x = random.randint(0, SCREEN_W)
        elif self.kind == "cloud_wisp":
            self.x += self.vx + wind * 0.5
            self.y += self.vy
            if self.x > SCREEN_W + 20: self.x = -20
            if self.x < -20: self.x = SCREEN_W + 20
        else:
            self.x += self.vx
            self.y += self.vy
            self.vy += 0.12
            self.vx *= 0.92
        self.life -= 1

    def is_alive(self):
        return self.life > 0


class Platform:
    def __init__(self, x, y, w, h, p_type, move_range=0, move_speed=0, move_vert=False):
        self.x = x
        self.ox = x
        self.y = y
        self.oy = y
        self.w = w
        self.h = h
        self.p_type = p_type
        self.move_range = move_range
        self.move_speed = move_speed
        self.move_vert = move_vert
        self.phase = random.uniform(0, math.pi * 2)

    def update(self, t):
        if self.move_range:
            if self.move_vert:
                self.y = self.oy + math.sin(t * self.move_speed + self.phase) * self.move_range
            else:
                self.x = self.ox + math.sin(t * self.move_speed + self.phase) * self.move_range


class Item:
    def __init__(self, x, y, kind="nut"):
        self.x = x
        self.y = y
        self.kind = kind
        self.alive = True
        self.bob = random.uniform(0, math.pi * 2)

    def update(self):
        self.bob += 0.08

    def screen_y(self):
        return self.y + math.sin(self.bob) * 2


class Enemy:
    def __init__(self, x, y, kind="patrol"):
        self.x = x
        self.y = y
        self.kind = kind
        self.vx = 0.8
        self.vy = 0.0
        self.alive = True
        self.timer = 0
        self.start_x = x
        self.start_y = y
        self.anim = 0

    def update(self, px, py):
        self.timer += 1
        self.anim = (self.timer // 8) % 4
        if self.kind == "patrol":
            self.x += self.vx
            if abs(self.x - self.start_x) > 40:
                self.vx *= -1
        elif self.kind == "chase":
            dx = px - self.x
            dy = py - self.y
            dist = math.sqrt(dx * dx + dy * dy)
            if dist < 1: dist = 1
            if dist < 90:
                self.x += (dx / dist) * 0.85
                self.y += (dy / dist) * 0.5
        elif self.kind == "jumper":
            self.x += self.vx
            if abs(self.x - self.start_x) > 30:
                self.vx *= -1
            if self.timer % 60 == 0:
                self.vy = -3.5
            self.vy += 0.2
            self.y += self.vy
            if self.y >= self.start_y:
                self.y = self.start_y
                self.vy = 0
        elif self.kind == "flyer":
            self.x = self.start_x + math.sin(self.timer * 0.04) * 50
            self.y = self.start_y + math.sin(self.timer * 0.07) * 25


class Game:
    def __init__(self):
        pyxel.init(SCREEN_W, SCREEN_H, title="Nuss-Mission DELUXE")
        self._init_sounds()
        self._init_music()
        self.lvl_idx = 0
        self.hi_score = 0
        self.bg_particles = []
        self.fx_particles = []
        self.state = "TITLE"
        self.title_t = 0
        self.t = 0
        self._current_music = -1
        self._spawn_bg_particles()
        self._play_music(6)  # Titel-Musik
        pyxel.run(self.update, self.draw)

    # ═══════════════════════════════════════
    #               SOUNDS & MUSIK
    # ═══════════════════════════════════════

    def _init_sounds(self):
        # SFX 0–4: Spieler-Effekte
        pyxel.sound(0).set("a2", "p", "3", "n", 6)    # Sprung
        pyxel.sound(1).set("c3", "t", "6", "n", 5)    # Item sammeln
        pyxel.sound(2).set("f1", "n", "4", "f", 8)    # Schaden
        pyxel.sound(3).set("g3", "t", "5", "n", 8)    # Level gewonnen
        pyxel.sound(4).set("a1", "n", "2", "f", 4)    # Dash

    def _init_music(self):
        # ──────────────────────────────────────────────────────────────────
        # MUSIK-SYSTEM:
        # Sounds 10–59 = Musiknoten (SFX 0–4 bleiben frei für Spieleffekte)
        # pyxel.music(track).set(ch0_list, ch1_list, ch2_list, ch3_list)
        # Jeder Kanal bekommt eine Liste von Sound-Slot-Nummern zum Abspielen.
        #
        # Struktur pro Biom: 4 Sounds = Melodie(10-19), Bass(20-29),
        #                    Arpeggio(30-39), Percussion(40-49)
        # Titel: Sounds 50-53
        # ──────────────────────────────────────────────────────────────────

        # ── LVL 0: Herbst-Wald – fröhlich, hüpfend (C-Dur) ──────────────
        # Melodie A
        pyxel.sound(10).set(
            "e3e3g3g3 a3a3g3r  e3e3d3d3 c3c3c3r",
            "t", "5554 5554 5554 5554", "nnnn nnnn nnnn nnnn", 12)
        # Melodie B
        pyxel.sound(11).set(
            "d3d3f3f3 g3g3f3r  d3d3c3c3 b2b2b2r",
            "t", "5554 5554 5554 5554", "nnnn nnnn nnnn nnnn", 12)
        # Bass
        pyxel.sound(20).set(
            "c2g2c2g2 c2g2c2g2 f2c3f2c3 g2d3g2d3",
            "s", "3333 3333 3333 3333", "nnnn nnnn nnnn nnnn", 12)
        # Arpeggio
        pyxel.sound(30).set(
            "c3e3g3c4 c3e3g3c4 f3a3c4f4 g3b3d4g4",
            "p", "2222 2222 2222 2222", "nnnn nnnn nnnn nnnn", 6)
        # Percussion (Noise-Kicks)
        pyxel.sound(40).set(
            "c1r  c1r  c1r  c1r",
            "n", "4040 4040 4040 4040", "ffff ffff ffff ffff", 8)

        # ── LVL 1: Eishöhle – kristallin, mystisch (a-Moll) ─────────────
        # Melodie A
        pyxel.sound(12).set(
            "a3r  c4r  e4r  a3r  g3r  e3r  f3r  e3r",
            "t", "6040 6040 6040 6040 6040 6040 6040 6040", "nfnf nfnf nfnf nfnf nfnf nfnf nfnf nfnf", 18)
        # Melodie B
        pyxel.sound(13).set(
            "e4r  d4r  c4r  b3r  a3r  b3r  c4r  d4r",
            "t", "5030 5030 5030 5030 5030 5030 5030 5030", "nfnf nfnf nfnf nfnf nfnf nfnf nfnf nfnf", 18)
        # Bass (tief, langsam)
        pyxel.sound(21).set(
            "a1r  r  r  e2r  r  r  f2r  r  r  e2r  r  r",
            "s", "5000 5000 5000 5000", "nfff nfff nfff nfff", 20)
        # Arpeggio (Glockenklang)
        pyxel.sound(31).set(
            "a3c4e4a4 e4c4a3e3 f3a3c4f4 e3g3b3e4",
            "p", "3333 3333 3333 3333", "ffff ffff ffff ffff", 8)
        # Percussion (sehr leise, nur Snare-Akzent)
        pyxel.sound(41).set(
            "r  r  c1r  r  r  r  c1r  r",
            "n", "0030 0030 0030 0030", "ffff ffff ffff ffff", 12)

        # ── LVL 2: Lava-Tempel – dunkel, treibend (d-Moll) ──────────────
        # Melodie A
        pyxel.sound(14).set(
            "d3r  f3r  a3r  d4r  c4r  a3r  g3r  f3r",
            "t", "6050 6050 6050 6050 6050 6050 6050 6050", "nnnn nnnn nnnn nnnn", 14)
        # Melodie B
        pyxel.sound(15).set(
            "a3a3 bb3r  c4c4 bb3r  a3g3 f3e3 d3r  r  r",
            "t", "5555 5050 5555 5050 5555 5555 5050 0000", "nnnn nfnn nnnn nfnn nnnn nnnn nfnn nnnn", 10)
        # Bass (stampfend)
        pyxel.sound(22).set(
            "d2d2 d2r  f2f2 f2r  g2g2 g2r  a2a2 a2r",
            "s", "5544 5540 5544 5540 5544 5540 5544 5540", "nnff nnff nnff nnff nnff nnff nnff nnff", 10)
        # Arpeggio (aggressiv)
        pyxel.sound(32).set(
            "d3f3a3d4 d3f3a3d4 f3a3c4f4 g3bb3d4g4",
            "s", "3333 3333 3333 3333", "nnnn nnnn nnnn nnnn", 6)
        # Percussion (starker Beat)
        pyxel.sound(42).set(
            "c1r  r  r  c1r  c1r  r  c1r  r",
            "n", "6040 6040 6040 6040", "ffff ffff ffff ffff", 8)

        # ── LVL 3: Wolkengipfel – hell, leicht, schwebend (F-Dur) ────────
        # Melodie A
        pyxel.sound(16).set(
            "f3a3c4f4 e4c4a3e3 g3bb3d4g4 f4d4bb3f3",
            "t", "4444 4444 4444 4444", "nnnn nnnn nnnn nnnn", 10)
        # Melodie B
        pyxel.sound(17).set(
            "c4c4d4e4 f4e4d4c4 d4d4e4f4 g4f4e4d4",
            "t", "5555 5555 5555 5555", "nnnn nnnn nnnn nnnn", 10)
        # Bass
        pyxel.sound(23).set(
            "f2c3f2c3 g2d3g2d3 bb2f3bb2f3 c3g3c3g3",
            "s", "3333 3333 3333 3333", "nnnn nnnn nnnn nnnn", 10)
        # Arpeggio (hoch, glitzernd)
        pyxel.sound(33).set(
            "f4a4c5f5 e5c5a4e4 g4bb4d5g5 f5d5bb4f4",
            "p", "2222 2222 2222 2222", "ffff ffff ffff ffff", 5)
        # Percussion (leicht)
        pyxel.sound(43).set(
            "c1r  c1r  c1c1 c1r",
            "n", "3030 3030 3030 3030", "ffff ffff ffff ffff", 10)

        # ── LVL 4: Geistertürme – unheimlich, chromatisch (e-Moll) ──────
        # Melodie A
        pyxel.sound(18).set(
            "e3r  r  d3r  r  c3r  r  b2r  r",
            "t", "6000 6000 6000 6000 6000 6000 6000 6000", "nfff nfff nfff nfff nfff nfff nfff nfff", 20)
        # Melodie B (Geister-Tremolo)
        pyxel.sound(19).set(
            "g3f3e3d3 c3b2bb2a2 g2r  r  r  r  r  r",
            "t", "4444 4444 4000 0000", "nnnn nnnn nfff ffff", 14)
        # Bass (grummelnd)
        pyxel.sound(24).set(
            "e1r  r  r  e1r  r  r  g1r  r  r  b1r  r  r",
            "s", "5000 5000 5000 5000", "nfff nfff nfff nfff", 22)
        # Arpeggio (dissonant)
        pyxel.sound(34).set(
            "e3g3b3e4 d3f3a3d4 c3e3g3c4 b2d3f3b3",
            "p", "2222 2222 2222 2222", "ffff ffff ffff ffff", 7)
        # Percussion (unregelmäßig)
        pyxel.sound(44).set(
            "r  c1r  r  r  c1c1 r  r  c1",
            "n", "0040 0040 0040 0040", "ffff ffff ffff ffff", 14)

        # ── LVL 5: Inferno-Gipfel – episch, schnell, final (d-Moll) ─────
        # Melodie A (schnell und aggressiv)
        pyxel.sound(50).set(
            "d4f4a4d5 c5a4f4c4 bb3d4f4bb4 a4f4d4a3",
            "t", "6666 6666 6666 6666", "nnnn nnnn nnnn nnnn", 8)
        # Melodie B
        pyxel.sound(51).set(
            "d4e4f4g4 a4g4f4e4 f4g4a4bb4 c5bb4a4g4",
            "t", "5555 5555 5555 5555", "nnnn nnnn nnnn nnnn", 8)
        # Bass (stampfend)
        pyxel.sound(52).set(
            "d2d2 a2r  d2d2 f2r  bb1bb1 f2r  a1a1 e2r",
            "s", "6644 6640 6644 6640 6644 6640 6644 6640", "nnff nnff nnff nnff nnff nnff nnff nnff", 8)
        # Arpeggio (wild)
        pyxel.sound(53).set(
            "d3f3a3d4 f4a4d5f5 e3g3bb3e4 f3a3c4f4",
            "s", "4444 4444 4444 4444", "nnnn nnnn nnnn nnnn", 5)
        # Percussion (voller Beat)
        pyxel.sound(54).set(
            "c1r  c1r  c1c1 c1r  c1r  c1r  c1c1 c1r",
            "n", "7050 7050 7050 7050 7050 7050 7050 7050", "ffff ffff ffff ffff ffff ffff ffff ffff", 6)

        # ── TITEL-MUSIK – einladend, verspielt ───────────────────────────
        pyxel.sound(55).set(
            "c3e3g3c4 e4c4g3e3 f3a3c4f4 g3b3d4g4",
            "t", "5555 5555 5555 5555", "nnnn nnnn nnnn nnnn", 10)
        pyxel.sound(56).set(
            "c2g2c3g3 f2c3f3c4 g2d3g3d4 c2g2c3g3",
            "s", "4444 4444 4444 4444", "nnnn nnnn nnnn nnnn", 10)
        pyxel.sound(57).set(
            "c4e4g4c5 g5e5c5g4 a4c5e5a5 g4b4d5g5",
            "p", "3333 3333 3333 3333", "nnnn nnnn nnnn nnnn", 5)
        pyxel.sound(58).set(
            "c1r  c1r  c1c1 c1r",
            "n", "3030 3030 3030 3030", "ffff ffff ffff ffff", 10)

        # ── MUSIK-TRACKS konfigurieren ────────────────────────────────────
        # Music(track).set(sounds_ch0, sounds_ch1, sounds_ch2, sounds_ch3)

        # Track 0: Herbst-Wald
        pyxel.music(0).set([10, 11, 10, 11], [20, 20], [30, 30], [40, 40])
        # Track 1: Eishöhle
        pyxel.music(1).set([12, 13, 12, 13], [21, 21], [31, 31], [41, 41])
        # Track 2: Lava-Tempel
        pyxel.music(2).set([14, 15, 14, 15], [22, 22], [32, 32], [42, 42])
        # Track 3: Wolkengipfel
        pyxel.music(3).set([16, 17, 16, 17], [23, 23], [33, 33], [43, 43])
        # Track 4: Geistertürme
        pyxel.music(4).set([18, 19, 18, 19], [24, 24], [34, 34], [44, 44])
        # Track 5: Inferno-Gipfel
        pyxel.music(5).set([50, 51, 50, 51], [52, 52], [53, 53], [54, 54])
        # Track 6: Titel
        pyxel.music(6).set([55, 55], [56, 56], [57, 57], [58, 58])

    def _play_music(self, track):
        """Spielt Musik-Track, nur wenn sich der Track ändert."""
        if self._current_music != track:
            self._current_music = track
            pyxel.playm(track, loop=True)

    def _stop_music(self):
        self._current_music = -1
        pyxel.stop()

    def _spawn_bg_particles(self):
        self.bg_particles = []
        self.fx_particles = []
        idx = self.lvl_idx
        if idx == 0:   # Herbst-Wald: Blätter
            for _ in range(28):
                c = random.choice([3, 9, 10, 4])
                self.bg_particles.append(Particle(
                    x=random.randint(0, SCREEN_W), y=random.randint(0, SCREEN_H),
                    vx=random.uniform(-0.4, 0.4), vy=random.uniform(0.3, 0.9),
                    col=c, life=9999, kind="leaf"))
        elif idx == 1:  # Eishöhle: Schnee + Eistropfen
            for _ in range(30):
                c = random.choice([6, 7, 12, 13])
                self.bg_particles.append(Particle(
                    x=random.randint(0, SCREEN_W), y=random.randint(0, SCREEN_H),
                    vx=random.uniform(-0.3, 0.3), vy=random.uniform(0.4, 1.0),
                    col=c, life=9999, kind="snow"))
            self._spawn_ice_drips()
        elif idx == 2:  # Lava-Tempel: Embers
            for _ in range(22):
                c = random.choice([8, 9, 10, 4])
                self.bg_particles.append(Particle(
                    x=random.randint(0, SCREEN_W), y=random.randint(0, SCREEN_H),
                    vx=random.uniform(-0.5, 0.5), vy=random.uniform(-1.5, -0.4),
                    col=c, life=9999, kind="ember"))
        elif idx == 3:  # Wolkengipfel: Wispwolken
            for _ in range(18):
                c = random.choice([6, 7, 12, 13])
                self.bg_particles.append(Particle(
                    x=random.randint(0, SCREEN_W), y=random.randint(10, 100),
                    vx=random.uniform(0.2, 0.8), vy=random.uniform(-0.1, 0.1),
                    col=c, life=9999, kind="cloud_wisp"))
        elif idx == 4:  # Geistertürme: Regen
            for _ in range(40):
                c = random.choice([5, 6, 1])
                self.bg_particles.append(Particle(
                    x=random.randint(0, SCREEN_W), y=random.randint(0, SCREEN_H),
                    vx=random.uniform(-0.5, -0.1), vy=random.uniform(4.0, 6.0),
                    col=c, life=9999, kind="rain"))
        else:           # Inferno: Embers dicht
            for _ in range(30):
                c = random.choice([8, 9, 10, 2])
                self.bg_particles.append(Particle(
                    x=random.randint(0, SCREEN_W), y=random.randint(0, SCREEN_H),
                    vx=random.uniform(-0.6, 0.6), vy=random.uniform(-2.0, -0.5),
                    col=c, life=9999, kind="ember"))

    def _spawn_ice_drips(self):
        for _ in range(14):
            self.bg_particles.append(Particle(
                x=random.randint(0, SCREEN_W), y=random.randint(0, 30),
                vx=random.uniform(-0.1, 0.1), vy=random.uniform(0.3, 0.8),
                col=random.choice([6, 7, 12]), life=random.randint(80, 200),
                kind="ice_drip"))

    def init_lvl(self):
        self.px = 20
        self.py = 140
        self.vx = 0
        self.vy = 0
        self.stamina = STAMINA_MAX
        self.cam_x = 0
        self.score = 0
        self.facing = 1
        self.lock_timer = 0
        self.coyote = 0
        self.jump_buffer = 0
        self.state = "PLAY"
        self.wind = 0
        self.t = 0
        self.anim_frame = 0
        self.on_wall = False
        self.on_ceil = False
        self.dash_timer = 0
        self.dash_cd = 0
        self.hurt_timer = 0
        self.lives = 3
        self.enemies = []
        self._spawn_bg_particles()
        self._build_level(self.lvl_idx)
        self._play_music(self.lvl_idx)  # Biom-Musik starten

    def _build_level(self, idx):
        if idx == 0:
            self.bg_col = (1, 2)
            self.goal_x = 680
            self.plats = [
                Platform(0,160,120,32,0), Platform(110,0,20,192,1),
                Platform(130,10,100,14,0), Platform(150,80,50,10,0),
                Platform(215,0,16,192,1), Platform(231,140,80,20,0),
                Platform(300,60,30,10,0,25,0.04), Platform(360,5,16,192,1),
                Platform(376,140,90,20,0), Platform(420,70,50,10,0),
                Platform(490,0,16,192,1), Platform(506,140,130,20,0),
                Platform(560,90,30,10,0,20,0.05),
            ]
            self.items = [
                Item(145,60,"nut"), Item(240,110,"nut"), Item(310,40,"gem"),
                Item(380,110,"nut"), Item(430,50,"star"), Item(570,70,"nut"),
            ]
            self.enemies = [Enemy(250,130,"patrol"), Enemy(400,130,"patrol")]

        elif idx == 1:
            self.bg_col = (5, 1)
            self.goal_x = 760
            self.plats = [
                Platform(0,160,80,32,0), Platform(80,0,16,192,2),
                Platform(96,5,100,12,0), Platform(96,160,50,32,0),
                Platform(160,80,35,10,0,30,0.04), Platform(200,0,16,192,2),
                Platform(216,140,110,30,0), Platform(290,50,30,10,0,35,0.05),
                Platform(360,0,16,192,2), Platform(376,160,55,32,0),
                Platform(415,70,35,10,0,25,0.06), Platform(460,0,16,192,2),
                Platform(476,140,80,30,0), Platform(530,60,40,10,0,20,0.07),
                Platform(600,140,120,30,0), Platform(640,90,30,10,0,30,0.04),
            ]
            self.items = [
                Item(130,145,"nut"), Item(230,110,"nut"), Item(295,30,"gem"),
                Item(390,140,"nut"), Item(540,40,"star"), Item(620,110,"gem"),
            ]
            self.enemies = [
                Enemy(250,130,"patrol"), Enemy(500,130,"chase"), Enemy(640,130,"patrol"),
            ]

        elif idx == 2:
            self.bg_col = (2, 8)
            self.goal_x = 880
            self.plats = [
                Platform(0,160,70,32,0), Platform(70,0,16,192,1),
                Platform(86,10,90,12,4), Platform(86,150,60,40,3),
                Platform(160,90,35,10,0), Platform(200,0,16,192,1),
                Platform(216,140,80,30,0), Platform(275,50,30,10,0,40,0.05),
                Platform(350,0,16,192,2), Platform(366,150,45,40,3),
                Platform(400,80,35,10,0,0,0.06,True), Platform(450,0,16,192,1),
                Platform(466,140,90,30,0), Platform(530,40,40,10,0,30,0.07),
                Platform(600,0,16,192,2), Platform(616,140,55,30,0),
                Platform(655,65,35,10,0,25,0.08), Platform(710,150,80,30,0),
                Platform(760,80,30,10,0,35,0.05),
            ]
            self.items = [
                Item(120,5,"nut"), Item(240,110,"gem"), Item(285,30,"star"),
                Item(420,60,"nut"), Item(540,20,"gem"), Item(660,45,"star"), Item(730,60,"star"),
            ]
            self.enemies = [
                Enemy(240,130,"patrol"), Enemy(480,130,"chase"),
                Enemy(650,130,"chase"), Enemy(760,120,"jumper"),
            ]

        elif idx == 3:
            self.bg_col = (12, 6)
            self.goal_x = 980
            self.plats = [
                Platform(0,165,60,32,0), Platform(60,0,16,192,1),
                Platform(76,150,160,15,0), Platform(105,75,35,10,0,45,0.035),
                Platform(185,20,35,10,0,35,0.06), Platform(256,0,16,192,2),
                Platform(272,140,110,30,0), Platform(325,60,35,10,0,55,0.045),
                Platform(405,100,25,10,0,25,0.08), Platform(455,0,16,192,1),
                Platform(471,150,90,30,0), Platform(525,50,30,10,0,40,0.065),
                Platform(600,0,16,192,2), Platform(616,145,75,30,0),
                Platform(670,70,40,10,0,35,0.07), Platform(760,145,100,30,0),
                Platform(810,80,30,10,0,30,0.09),
            ]
            self.items = [
                Item(115,55,"star"), Item(200,0,"gem"), Item(295,110,"star"),
                Item(340,40,"star"), Item(415,80,"gem"), Item(540,30,"star"),
                Item(685,50,"star"), Item(820,60,"star"),
            ]
            self.enemies = [
                Enemy(295,130,"chase"), Enemy(500,130,"chase"),
                Enemy(665,130,"chase"), Enemy(820,100,"flyer"),
            ]

        elif idx == 4:
            self.bg_col = (5, 2)
            self.goal_x = 1100
            self.plats = [
                Platform(0,165,55,32,0), Platform(55,0,14,192,2),
                Platform(69,155,70,20,0), Platform(100,80,28,10,0,30,0.06,True),
                Platform(170,30,28,10,0,40,0.07), Platform(230,0,14,192,1),
                Platform(244,145,100,30,0), Platform(290,70,28,10,0,50,0.06,True),
                Platform(370,30,28,10,0,30,0.09), Platform(420,0,14,192,2),
                Platform(434,155,80,30,0), Platform(480,80,28,10,0,35,0.07,True),
                Platform(555,40,28,10,0,45,0.08), Platform(610,0,14,192,1),
                Platform(624,145,90,30,0), Platform(665,75,28,10,0,40,0.09),
                Platform(740,0,14,192,2), Platform(754,155,70,30,0),
                Platform(800,65,28,10,0,35,0.1), Platform(870,145,100,30,0),
                Platform(920,80,28,10,0,25,0.11), Platform(970,150,80,30,0),
            ]
            self.items = [
                Item(110,60,"star"), Item(255,120,"gem"), Item(295,50,"star"),
                Item(375,10,"star"), Item(490,60,"gem"), Item(560,20,"star"),
                Item(680,55,"gem"), Item(810,45,"star"), Item(930,60,"star"),
            ]
            self.enemies = [
                Enemy(260,130,"patrol"), Enemy(450,130,"chase"),
                Enemy(640,130,"chase"), Enemy(780,130,"jumper"), Enemy(900,110,"flyer"),
            ]

        else:
            self.bg_col = (8, 2)
            self.goal_x = 1240
            self.plats = [
                Platform(0,165,50,32,0), Platform(50,0,14,192,1),
                Platform(64,155,60,20,3), Platform(80,85,24,10,0,30,0.08),
                Platform(145,35,24,10,0,40,0.1), Platform(210,0,14,192,2),
                Platform(224,145,90,30,0), Platform(265,75,24,10,0,50,0.08,True),
                Platform(350,30,24,10,0,40,0.12), Platform(410,0,14,192,1),
                Platform(424,155,65,20,3), Platform(455,85,24,10,0,35,0.09,True),
                Platform(525,40,24,10,0,45,0.11), Platform(590,0,14,192,2),
                Platform(604,145,80,30,0), Platform(640,75,24,10,0,40,0.1),
                Platform(715,0,14,192,1), Platform(729,155,60,30,0),
                Platform(770,65,24,10,0,45,0.12,True), Platform(840,145,80,30,0),
                Platform(885,80,24,10,0,35,0.13), Platform(950,0,14,192,2),
                Platform(964,155,60,20,3), Platform(1000,75,24,10,0,40,0.1),
                Platform(1070,145,80,30,0), Platform(1110,65,24,10,0,30,0.14),
                Platform(1160,150,90,30,0),
            ]
            self.items = [
                Item(90,65,"star"), Item(150,15,"gem"), Item(240,120,"star"),
                Item(355,10,"star"), Item(465,65,"gem"), Item(535,20,"star"),
                Item(650,55,"gem"), Item(780,45,"star"), Item(895,60,"star"),
                Item(1010,55,"star"), Item(1120,45,"gem"),
            ]
            self.enemies = [
                Enemy(235,130,"chase"), Enemy(440,130,"chase"),
                Enemy(615,130,"chase"), Enemy(750,120,"jumper"),
                Enemy(870,100,"flyer"), Enemy(990,130,"chase"), Enemy(1090,100,"flyer"),
            ]

    # ─────────── UPDATE ───────────

    def update(self):
        self.t += 1
        if self.state == "TITLE":
            self.title_t += 1
            for p in self.bg_particles:
                p.update()
            if pyxel.btnp(pyxel.KEY_SPACE) or pyxel.btnp(pyxel.KEY_RETURN):
                self.lvl_idx = 0
                self.hi_score = 0
                self.init_lvl()
        elif self.state == "PLAY":
            self._update_play()
        elif self.state in ("LOSE", "WIN", "GAMEOVER"):
            for p in self.bg_particles:
                p.update()
            self.fx_particles = [p for p in self.fx_particles if p.is_alive()]
            for p in self.fx_particles:
                p.update()
            if pyxel.btnp(pyxel.KEY_SPACE) or pyxel.btnp(pyxel.KEY_RETURN):
                if self.state == "WIN" and self.lvl_idx >= 5:
                    self._play_music(6)
                    self.state = "TITLE"
                elif self.state == "WIN":
                    self.lvl_idx += 1
                    self.hi_score = max(self.hi_score, self.score)
                    self.init_lvl()
                elif self.state == "GAMEOVER":
                    self._play_music(6)
                    self.state = "TITLE"
                else:
                    self.init_lvl()

    def _update_play(self):
        for p in self.bg_particles:
            p.update(self.wind)

        # Eishöhle: neue Tropfen spawnen
        if self.lvl_idx == 1 and self.t % 40 == 0:
            self.bg_particles.append(Particle(
                x=random.randint(0, SCREEN_W), y=random.randint(0, 10),
                vx=random.uniform(-0.1, 0.1), vy=random.uniform(0.4, 0.9),
                col=random.choice([6, 7, 12]), life=random.randint(60, 160),
                kind="ice_drip"))
        self.bg_particles = [p for p in self.bg_particles if p.is_alive() or p.life == 9999]

        new_fx = [p for p in self.fx_particles if p.is_alive()]
        for p in new_fx:
            p.update()
        self.fx_particles = new_fx

        for pl in self.plats:
            pl.update(self.t)
        for e in self.enemies:
            if e.alive:
                e.update(self.px, self.py)
                if abs(self.px - e.x) < 9 and abs(self.py - e.y) < 9:
                    self._hurt()
        if self.t % 180 == 0:
            self.wind = random.uniform(-0.9, 1.2) if random.random() > 0.6 else 0

        for it in self.items:
            if it.alive:
                it.update()
                if abs(self.px + 4 - it.x) < 10 and abs(self.py + 4 - it.screen_y()) < 10:
                    it.alive = False
                    pts = {"nut": 100, "gem": 250, "star": 500}
                    self.score += pts.get(it.kind, 100)
                    pyxel.play(1, 1)
                    self._burst(it.x - self.cam_x, it.screen_y(), it.kind)

        for pl in self.plats:
            if pl.p_type == 3:
                if (self.px + 7 > pl.x and self.px < pl.x + pl.w and
                        self.py + 8 >= pl.y and self.py + 8 <= pl.y + 10):
                    self._hurt()

        self._update_player()
        if abs(self.vx) > 0.3:
            if self.t % 8 == 0:
                self.anim_frame = (self.anim_frame + 1) % 4
        else:
            self.anim_frame = 0

    def _hurt(self):
        if self.hurt_timer > 0:
            return
        self.lives -= 1
        self.hurt_timer = 60
        pyxel.play(2, 2)
        self._burst(self.px - self.cam_x + 4, self.py + 4, "hurt")
        if self.lives <= 0:
            self.state = "GAMEOVER"

    def _burst(self, x, y, kind="nut"):
        cols = {"nut": [9, 10, 4], "gem": [12, 7, 6], "star": [10, 9, 7], "hurt": [8, 2, 3]}
        c_list = cols.get(kind, [7, 13, 6])
        for _ in range(18):
            a = random.uniform(0, math.pi * 2)
            sp = random.uniform(0.5, 3.0)
            self.fx_particles.append(Particle(
                x=x, y=y,
                vx=math.cos(a) * sp, vy=math.sin(a) * sp - 1,
                col=random.choice(c_list),
                life=random.randint(20, 40), kind="spark"))

    def _update_player(self):
        if self.hurt_timer > 0: self.hurt_timer -= 1
        if self.dash_cd > 0: self.dash_cd -= 1
        if self.dash_timer > 0:
            self.dash_timer -= 1
            return
        if self.lock_timer > 0:
            self.lock_timer -= 1
        else:
            if pyxel.btn(pyxel.KEY_A) or pyxel.btn(pyxel.KEY_LEFT):
                self.vx = -WALK_SPEED; self.facing = -1
            elif pyxel.btn(pyxel.KEY_D) or pyxel.btn(pyxel.KEY_RIGHT):
                self.vx = WALK_SPEED; self.facing = 1
            else:
                self.vx *= 0.75

        dash_pressed = False
        try:
            if pyxel.btnp(pyxel.KEY_LSHIFT): dash_pressed = True
        except Exception:
            pass
        if pyxel.btnp(pyxel.KEY_Z): dash_pressed = True
        if dash_pressed and self.dash_cd == 0:
            self.vx = self.facing * 6
            self.vy = 0
            self.dash_timer = 8
            self.dash_cd = 40
            pyxel.play(1, 4)
            self._burst(self.px - self.cam_x + 4, self.py + 4, "gem")
            return

        self.vx += self.wind * 0.04
        on_ground = self._check_floor()
        at_ceiling = self._check_ceiling()
        wall = self._get_wall()

        if on_ground: self.coyote = COYOTE_TIME
        else: self.coyote = max(0, self.coyote - 1)

        jump_pressed = (pyxel.btnp(pyxel.KEY_SPACE) or
                        pyxel.btnp(pyxel.KEY_W) or
                        pyxel.btnp(pyxel.KEY_UP))
        if jump_pressed: self.jump_buffer = JUMP_BUFFER
        else: self.jump_buffer = max(0, self.jump_buffer - 1)

        self.on_wall = False
        self.on_ceil = False
        climb_held = pyxel.btn(pyxel.KEY_W) or pyxel.btn(pyxel.KEY_UP)

        if wall and not on_ground:
            self.on_wall = True
            if climb_held and self.stamina > 0:
                self.vy = -1.2 if wall.p_type == 1 else -0.5
                self.stamina -= 0.8
            else:
                self.vy = min(self.vy + 0.1, 1.0)
            if self.jump_buffer > 0:
                pyxel.play(0, 0)
                self.vy = WALL_JUMP_Y
                self.vx = -self.facing * WALL_JUMP_X
                self.lock_timer = 12
                self.stamina -= 5
                self.facing *= -1
                self.jump_buffer = 0
                self._dust_puff()
        elif at_ceiling and climb_held and self.stamina > 0:
            self.on_ceil = True
            self.vy = 0
            self.stamina -= 0.6
            if self.jump_buffer > 0:
                self.vy = 1.5
                self.jump_buffer = 0
        else:
            self.vy += GRAVITY
            if on_ground:
                self.stamina = min(STAMINA_MAX, self.stamina + 1.5)
                if self.jump_buffer > 0:
                    pyxel.play(0, 0)
                    self.vy = JUMP_PWR
                    self.jump_buffer = 0
                    self._dust_puff()
            elif self.coyote > 0 and self.jump_buffer > 0:
                pyxel.play(0, 0)
                self.vy = JUMP_PWR
                self.coyote = 0
                self.jump_buffer = 0
                self._dust_puff()

        self.px += self.vx
        self.py += self.vy
        target_cam = self.px - SCREEN_W * 0.35
        self.cam_x += (target_cam - self.cam_x) * 0.12
        if self.cam_x < 0: self.cam_x = 0

        if self.py > SCREEN_H + 30:
            self._hurt()
            self.py = 140
            self.vy = 0
        if self.px > self.goal_x:
            self.score += self.lives * 500
            pyxel.play(3, 3)
            self.state = "WIN"

    def _dust_puff(self):
        for _ in range(7):
            a = random.uniform(math.pi, math.pi * 2)
            sp = random.uniform(0.3, 1.5)
            self.fx_particles.append(Particle(
                x=self.px - self.cam_x + 4, y=self.py + 8,
                vx=math.cos(a) * sp, vy=math.sin(a) * sp,
                col=7, life=22, kind="spark"))

    def _check_floor(self):
        for p in self.plats:
            if p.p_type in (0, 3, 4):
                if self.px + 7 > p.x and self.px + 1 < p.x + p.w:
                    if self.py + 8 >= p.y and self.py + 8 <= p.y + 7 and self.vy >= 0:
                        self.py = p.y - 8
                        self.vy = 0
                        return True
        return False

    def _check_ceiling(self):
        for p in self.plats:
            if p.p_type in (0, 4):
                if self.px + 7 > p.x and self.px + 1 < p.x + p.w:
                    if self.py <= p.y + p.h and self.py >= p.y + p.h - 5 and self.vy <= 0:
                        self.py = p.y + p.h
                        self.vy = 0
                        return True
        return False

    def _get_wall(self):
        test_x = self.px + 7 if self.facing == 1 else self.px
        for p in self.plats:
            if p.p_type in (1, 2):
                if test_x > p.x and test_x < p.x + p.w:
                    if self.py + 7 > p.y and self.py < p.y + p.h:
                        return p
        return None

    # ═══════════════════════════════════════
    #               DRAWING
    # ═══════════════════════════════════════

    def draw(self):
        if self.state == "TITLE":
            self._draw_title()
        elif self.state == "PLAY":
            self._draw_play()
        elif self.state == "WIN":
            self._draw_play()
            won_all = self.lvl_idx >= 5
            self._draw_overlay("NUSS GEFUNDEN!", "Weiter: SPACE" if not won_all else "ENDE! SPACE", 10)
        elif self.state == "GAMEOVER":
            self._draw_play()
            self._draw_overlay("SPIEL VORBEI", "Neu: SPACE", 8)
        elif self.state == "LOSE":
            self._draw_play()
            self._draw_overlay("ABGESTUERZT!", "Nochmal: SPACE", 8)

    # ─── TITLE ───

    def _draw_title(self):
        for row in range(SCREEN_H):
            if row < 70:   c = 1
            elif row < 120: c = 5
            elif row < 160: c = 2
            else:           c = 3
            pyxel.line(0, row, SCREEN_W, row, c)
        # Stars
        for i in range(24):
            sx = (i * 41 + 7) % SCREEN_W
            sy = (i * 19 + 5) % 70
            if (self.title_t // 18 + i) % 3 != 0:
                pyxel.pset(sx, sy, 7)
        # Parallax mountains
        for col, h, factor in [(2, 35, 0.03), (5, 55, 0.08), (3, 40, 0.15)]:
            offset = int(self.title_t * factor * 0.4)
            for i in range(5):
                mx = (i * 110 - offset) % (SCREEN_W + 110) - 20
                pyxel.tri(mx, SCREEN_H, mx + 55, SCREEN_H - h, mx + 110, SCREEN_H, col)
        for p in self.bg_particles:
            pyxel.pset(int(p.x), int(p.y), p.col)
        # Title box
        lx = SCREEN_W // 2 - 70
        ly = 28
        pyxel.rect(lx - 5, ly - 5, 144, 30, 0)
        pyxel.rectb(lx - 5, ly - 5, 144, 30, 9)
        pyxel.rectb(lx - 4, ly - 4, 142, 28, 5)
        pyxel.text(lx + 6, ly + 9, "NUSS-MISSION DELUXE", 0)
        pyxel.text(lx + 5, ly + 8, "NUSS-MISSION DELUXE", 2)
        pyxel.text(lx + 4, ly + 7, "NUSS-MISSION DELUXE", 10)
        pyxel.text(lx + 4, ly + 6, "NUSS-MISSION", 9)
        sq_x = SCREEN_W // 2 - 4 + int(math.sin(self.title_t * 0.05) * 22)
        self._draw_squirrel_at(sq_x, 74, 1, int(self.title_t * 0.3) % 4)
        if (self.title_t // 22) % 2 == 0:
            pyxel.rect(SCREEN_W // 2 - 44, 106, 88, 10, 0)
            pyxel.text(SCREEN_W // 2 - 40, 108, "SPACE zum Starten", 7)
        pyxel.rect(SCREEN_W // 2 - 26, 120, 52, 10, 5)
        pyxel.rectb(SCREEN_W // 2 - 26, 120, 52, 10, 9)
        pyxel.text(SCREEN_W // 2 - 22, 122, "6 WELTEN!", 10)
        pyxel.rect(0, SCREEN_H - 20, SCREEN_W, 20, 0)
        pyxel.line(0, SCREEN_H - 20, SCREEN_W, SCREEN_H - 20, 5)
        pyxel.text(4, SCREEN_H - 16, "A/D bewegen  W klettern  SPACE springen  Z Dash", 13)
        if self.hi_score > 0:
            pyxel.text(4, 4, "BESTPUNKTZAHL: " + str(self.hi_score), 9)

    # ─── MAIN PLAY DRAW ───

    def _draw_play(self):
        idx = self.lvl_idx
        if   idx == 0: self._draw_biome_forest()
        elif idx == 1: self._draw_biome_ice()
        elif idx == 2: self._draw_biome_lava()
        elif idx == 3: self._draw_biome_cloud()
        elif idx == 4: self._draw_biome_ghost()
        else:          self._draw_biome_inferno()

        # Particles
        for p in self.bg_particles:
            if p.kind == "ice_drip":
                px2 = int(p.x); py2 = int(p.y)
                if 0 <= py2 < SCREEN_H:
                    pyxel.pset(px2, py2, p.col)
                    if py2 > 1: pyxel.pset(px2, py2 - 1, 1 if p.col == 12 else 6)
            elif p.kind == "cloud_wisp":
                px2 = int(p.x); py2 = int(p.y)
                pyxel.pset(px2, py2, p.col)
                pyxel.pset(px2 + 1, py2, 13 if p.col == 7 else p.col)
                pyxel.pset(px2 - 1, py2, 6)
            elif p.kind == "rain":
                px2 = int(p.x); py2 = int(p.y)
                pyxel.line(px2, py2, px2 - 1, py2 - 3, p.col)
            else:
                pyxel.pset(int(p.x), int(p.y), p.col)

        for pl in self.plats:
            self._draw_platform(pl)

        self._draw_goal()
        self._draw_items()
        self._draw_enemies()

        for p in self.fx_particles:
            alpha = p.life / p.max_life if p.max_life > 0 else 0
            if alpha > 0.5:   pyxel.pset(int(p.x), int(p.y), p.col)
            elif alpha > 0.2: pyxel.pset(int(p.x), int(p.y), 13)

        inv = self.hurt_timer > 0 and (self.t // 4) % 2 == 0
        if not inv:
            self._draw_squirrel_at(
                int(self.px - self.cam_x), int(self.py),
                self.facing, self.anim_frame, self.on_wall, self.on_ceil)

        self._draw_hud()

    # ═══════════════════════════════════════
    #       BIOME BACKGROUNDS
    # ═══════════════════════════════════════

    def _draw_biome_forest(self):
        for row in range(SCREEN_H):
            if row < 14:    c = 0
            elif row < 40:  c = 2
            elif row < 80:  c = 9
            elif row < 120: c = 10
            elif row < 155: c = 4
            else:           c = 3
            pyxel.line(0, row, SCREEN_W, row, c)
        off1 = int(self.cam_x * 0.05)
        for i in range(5):
            mx = (i * 120 - off1) % (SCREEN_W + 120) - 30
            pyxel.tri(mx, SCREEN_H, mx + 70, SCREEN_H - 60, mx + 140, SCREEN_H, 2)
        off2 = int(self.cam_x * 0.12)
        for i in range(7):
            tx = (i * 85 - off2) % (SCREEN_W + 85) - 10
            th = 35 + (i * 17) % 30
            tw = 12 + (i * 5) % 10
            pyxel.rect(tx + tw // 2 - 2, SCREEN_H - 20, 4, 20, 0)
            for layer in range(3):
                ly2 = SCREEN_H - th + layer * 10
                lw = tw - layer * 2
                pyxel.tri(tx + tw // 2, ly2 - 12, tx, ly2 + 8, tx + tw, ly2 + 8, 0)
                pyxel.line(tx + tw // 2, ly2 - 12, tx, ly2 + 8, 2)
        off3 = int(self.cam_x * 0.25)
        for i in range(8):
            bx = (i * 70 - off3) % (SCREEN_W + 70) - 10
            pyxel.tri(bx, SCREEN_H, bx + 25, SCREEN_H - 20, bx + 50, SCREEN_H, 3)
            pyxel.tri(bx + 10, SCREEN_H, bx + 30, SCREEN_H - 28, bx + 50, SCREEN_H, 0)

    def _draw_biome_ice(self):
        for row in range(SCREEN_H):
            if row < 14:    c = 0
            elif row < 30:  c = 1
            elif row < 65:  c = 5
            elif row < 105: c = 1
            elif row < 145: c = 5
            elif row < 165: c = 6
            else:           c = 12
            pyxel.line(0, row, SCREEN_W, row, c)
        off_bg = int(self.cam_x * 0.04)
        for i in range(14):
            bx = (i * 70 - off_bg) % (SCREEN_W + 70) - 10
            bh = 20 + (i * 19) % 35
            pyxel.rect(bx + 12, SCREEN_H - bh, 14, bh, 1)
            pyxel.rect(bx + 13, SCREEN_H - bh, 2, bh, 5)
            pyxel.line(bx + 12, SCREEN_H - bh, bx + 19, SCREEN_H - bh - 6, 6)
        off_mid = int(self.cam_x * 0.11)
        for i in range(9):
            bx = (i * 90 + 40 - off_mid) % (SCREEN_W + 90) - 15
            bh = 35 + (i * 23) % 45
            by = SCREEN_H - bh
            pyxel.tri(bx + 8, SCREEN_H, bx + 18, by, bx + 28, SCREEN_H, 5)
            pyxel.line(bx + 8, SCREEN_H, bx + 18, by, 6)
            pyxel.line(bx + 12, SCREEN_H - 6, bx + 17, by + 4, 12)
            pyxel.pset(bx + 18, by, 7)
        off_stl = int(self.cam_x * 0.20)
        for i in range(11):
            sx = (i * 78 - off_stl) % (SCREEN_W + 78) - 8
            sh = 18 + (i * 21) % 38
            sw = 5 + (i * 7) % 9
            sy0 = 14
            pyxel.tri(sx, sy0, sx + sw, sy0, sx + sw // 2, sy0 + sh, 1)
            pyxel.line(sx, sy0, sx + sw // 2, sy0 + sh, 6)
            pyxel.line(sx + sw, sy0, sx + sw // 2, sy0 + sh, 5)
            pyxel.pset(sx + sw // 2, sy0 + sh, 7)
            if sw > 6:
                pyxel.line(sx + 2, sy0 + 3, sx + sw // 2 - 1, sy0 + sh - 4, 12)
            drip_phase = (self.t + i * 22) % 90
            if drip_phase < 45:
                dy = sy0 + sh + drip_phase // 4
                if dy < SCREEN_H:
                    pyxel.pset(sx + sw // 2, dy, 12)
        for i in range(15):
            sx = (i * 58 + 28 - off_stl) % (SCREEN_W + 58) - 5
            sh = 7 + (i * 9) % 14
            sw = 3 + (i * 4) % 4
            sy0 = 14
            pyxel.tri(sx, sy0, sx + sw, sy0, sx + sw // 2, sy0 + sh, 5)
            pyxel.line(sx, sy0, sx + sw // 2, sy0 + sh, 6)
            pyxel.pset(sx + sw // 2, sy0 + sh, 12)
        off_glow = int(self.cam_x * 0.14)
        for i in range(16):
            gx = (i * 65 + 12 - off_glow) % (SCREEN_W + 65) - 5
            gy = 22 + (i * 27) % 130
            phase = (self.t * 2 + i * 33) % 120
            c = 7 if phase < 50 else (12 if phase < 85 else 6)
            pyxel.pset(gx, gy, c)
            if c == 7:
                pyxel.pset(gx + 1, gy, 12)
                pyxel.pset(gx - 1, gy, 12)
                pyxel.pset(gx, gy + 1, 12)
                pyxel.pset(gx, gy - 1, 12)
        off_vein = int(self.cam_x * 0.17)
        for i in range(6):
            vx = (i * 100 + 18 - off_vein) % (SCREEN_W + 100) - 10
            py2 = 20
            for seg in range(7):
                ny = py2 + 14 + seg * 5 % 8
                nx = vx + math.sin((self.t * 0.005 + i + seg) * 2.2) * 2.5
                c = 12 if (self.t // 28 + i + seg) % 3 == 0 else 6
                pyxel.line(int(nx), py2, int(nx), ny, c)
                py2 = ny
                if py2 > SCREEN_H - 20: break
        floor_y = 163
        pyxel.rect(0, floor_y, SCREEN_W, 4, 6)
        pyxel.rect(0, floor_y + 1, SCREEN_W, 1, 12)
        off_ref = int(self.cam_x * 0.32)
        for i in range(22):
            rx = (i * 28 - off_ref) % SCREEN_W
            rw = 3 + i % 6
            c = 7 if (self.t * 3 + i * 17) % 38 < 8 else 6
            pyxel.rect(rx, floor_y + 2, rw, 1, c)

    def _draw_biome_lava(self):
        for row in range(SCREEN_H):
            if row < 14:    c = 0
            elif row < 40:  c = 0
            elif row < 80:  c = 2
            elif row < 120: c = 8
            elif row < 155: c = 9
            else:           c = 2
            pyxel.line(0, row, SCREEN_W, row, c)
        off1 = int(self.cam_x * 0.05)
        for i in range(5):
            rx = (i * 130 - off1) % (SCREEN_W + 130) - 20
            rh = 50 + (i * 19) % 40
            rw = 20 + (i * 11) % 15
            pyxel.rect(rx, SCREEN_H - rh, rw, rh, 0)
            for z in range(rw // 6):
                pyxel.rect(rx + z * 6, SCREEN_H - rh - 6, 4, 6, 0)
            pyxel.line(rx, SCREEN_H - rh, rx + rw - 1, SCREEN_H - rh, 2)
        off2 = int(self.cam_x * 0.10)
        for i in range(7):
            lx = (i * 80 - off2) % (SCREEN_W + 80) - 10
            lava_y = 150 + int(math.sin((self.t * 0.04) + i * 1.1) * 4)
            pyxel.rect(lx, lava_y, 60, SCREEN_H - lava_y, 2)
            pyxel.rect(lx, lava_y, 60, 3, 9)
            pyxel.rect(lx, lava_y + 1, 60, 1, 10)
        off3 = int(self.cam_x * 0.22)
        for i in range(6):
            cx = (i * 100 + 25 - off3) % (SCREEN_W + 100) - 10
            ch = 55 + (i * 13) % 30
            pyxel.rect(cx, SCREEN_H - ch, 10, ch, 2)
            pyxel.line(cx, SCREEN_H - ch, cx + 9, SCREEN_H - ch, 8)
            flame_h = 4 + int(math.sin(self.t * 0.1 + i) * 3)
            pyxel.tri(cx + 2, SCREEN_H - ch, cx + 5, SCREEN_H - ch - flame_h, cx + 8, SCREEN_H - ch, 9)
        lava_base = 165
        for row in range(lava_base, SCREEN_H):
            c = 9 if (row + self.t // 4) % 6 < 3 else 8
            pyxel.line(0, row, SCREEN_W, row, c)
        pyxel.rect(0, lava_base, SCREEN_W, 2, 10)

    def _draw_biome_cloud(self):
        for row in range(SCREEN_H):
            if row < 14:    c = 1
            elif row < 50:  c = 6
            elif row < 100: c = 12
            elif row < 145: c = 7
            else:           c = 6
            pyxel.line(0, row, SCREEN_W, row, c)
        off1 = int(self.cam_x * 0.04)
        for i in range(5):
            mx = (i * 140 - off1) % (SCREEN_W + 140) - 30
            mh = 70 + (i * 23) % 50
            pyxel.tri(mx, SCREEN_H, mx + 80, SCREEN_H - mh, mx + 160, SCREEN_H, 6)
            snow_w = 20 + (i * 7) % 20
            pyxel.tri(mx + 80 - snow_w // 2, SCREEN_H - mh + snow_w // 3,
                      mx + 80, SCREEN_H - mh,
                      mx + 80 + snow_w // 2, SCREEN_H - mh + snow_w // 3, 7)
        off2 = int(self.cam_x * 0.08)
        for i in range(6):
            cx = (i * 110 - off2) % (SCREEN_W + 110) - 20
            cy = 30 + (i * 17) % 60
            cw = 50 + (i * 19) % 40
            ch = 10 + (i * 7) % 14
            pyxel.rect(cx, cy, cw, ch, 7)
            pyxel.circ(cx + 8, cy - 3, 8, 7)
            pyxel.circ(cx + cw - 8, cy - 3, 6, 7)
            pyxel.circ(cx + cw // 2, cy - 6, 10, 7)
            pyxel.rect(cx + 3, cy + ch - 2, cw - 6, 2, 13)
        off3 = int(self.cam_x * 0.18)
        for i in range(4):
            cx = (i * 160 + 50 - off3) % (SCREEN_W + 160) - 20
            cy = 100 + (i * 11) % 30
            pyxel.rect(cx, cy, 80, 12, 7)
            pyxel.circ(cx + 12, cy - 5, 10, 7)
            pyxel.circ(cx + 35, cy - 8, 13, 7)
            pyxel.circ(cx + 58, cy - 5, 9, 7)
            pyxel.rect(cx + 5, cy + 10, 70, 3, 13)
        off4 = int(self.cam_x * 0.25)
        for i in range(4):
            bx = (i * 200 + 30 - off4) % (SCREEN_W + 200)
            by = 25 + (i * 13) % 30
            wing = int(math.sin(self.t * 0.08 + i) * 2)
            pyxel.line(bx - 4, by - wing, bx, by, 1)
            pyxel.line(bx, by, bx + 4, by - wing, 1)

    def _draw_biome_ghost(self):
        for row in range(SCREEN_H):
            if row < 14:    c = 0
            elif row < 45:  c = 1
            elif row < 90:  c = 5
            elif row < 130: c = 2
            elif row < 160: c = 1
            else:           c = 0
            pyxel.line(0, row, SCREEN_W, row, c)
        moon_x = 180 + int(math.sin(self.t * 0.003) * 20)
        moon_y = 35
        pyxel.circ(moon_x, moon_y, 12, 7)
        pyxel.circ(moon_x, moon_y, 10, 13)
        pyxel.circ(moon_x + 3, moon_y - 3, 4, 7)
        for r in range(14, 19, 2):
            alpha_col = 6 if r < 16 else 1
            pyxel.circb(moon_x, moon_y, r, alpha_col)
        off1 = int(self.cam_x * 0.05)
        for i in range(5):
            tx = (i * 120 - off1) % (SCREEN_W + 120) - 15
            th = 60 + (i * 21) % 50
            tw = 14 + (i * 7) % 10
            pyxel.rect(tx, SCREEN_H - th, tw, th, 1)
            pyxel.tri(tx - 2, SCREEN_H - th, tx + tw // 2, SCREEN_H - th - 20, tx + tw + 2, SCREEN_H - th, 0)
            win_col = 9 if (self.t // 30 + i) % 4 != 0 else 0
            pyxel.pset(tx + 3, SCREEN_H - th + 15, win_col)
            pyxel.pset(tx + tw - 4, SCREEN_H - th + 15, win_col)
            pyxel.pset(tx + tw // 2, SCREEN_H - th + 30, win_col)
        off2 = int(self.cam_x * 0.14)
        for i in range(7):
            bx = (i * 85 + 20 - off2) % (SCREEN_W + 85) - 10
            bh = 40 + (i * 13) % 30
            pyxel.line(bx + 5, SCREEN_H, bx + 5, SCREEN_H - bh, 0)
            pyxel.line(bx + 5, SCREEN_H - bh, bx - 8, SCREEN_H - bh - 10, 0)
            pyxel.line(bx + 5, SCREEN_H - bh, bx + 18, SCREEN_H - bh - 12, 0)
            pyxel.line(bx + 5, SCREEN_H - bh + 10, bx - 5, SCREEN_H - bh, 0)
            pyxel.line(bx + 5, SCREEN_H - bh + 10, bx + 12, SCREEN_H - bh + 2, 0)
            pyxel.line(bx + 6, SCREEN_H, bx + 6, SCREEN_H - bh, 5)

    def _draw_biome_inferno(self):
        for row in range(SCREEN_H):
            if row < 14:    c = 0
            elif row < 35:  c = 0
            elif row < 70:  c = 2
            elif row < 110: c = 8
            elif row < 145: c = 9
            else:           c = 10
            pyxel.line(0, row, SCREEN_W, row, c)
        off1 = int(self.cam_x * 0.05)
        for i in range(5):
            rx = (i * 130 - off1) % (SCREEN_W + 130) - 20
            rh = 60 + (i * 17) % 50
            pyxel.tri(rx, SCREEN_H, rx + 75, SCREEN_H - rh, rx + 150, SCREEN_H, 2)
            pyxel.line(rx, SCREEN_H, rx + 75, SCREEN_H - rh, 8)
            pyxel.line(rx + 75, SCREEN_H - rh, rx + 150, SCREEN_H, 9)
        off2 = int(self.cam_x * 0.13)
        for i in range(8):
            mx = (i * 95 + 30 - off2) % (SCREEN_W + 95) - 10
            mag_y = SCREEN_H - 20 + int(math.sin(self.t * 0.06 + i) * 5)
            pyxel.rect(mx, mag_y, 8, SCREEN_H - mag_y, 8)
            pyxel.rect(mx + 1, mag_y, 6, 2, 10)
            pyxel.rect(mx + 2, mag_y + 1, 4, 1, 7)
        off3 = int(self.cam_x * 0.22)
        for i in range(5):
            gx = (i * 120 + 50 - off3) % (SCREEN_W + 120) - 10
            geyser_h = 20 + int(math.sin(self.t * 0.07 + i * 1.4) * 15)
            gy = SCREEN_H - geyser_h
            pyxel.tri(gx, SCREEN_H, gx + 8, gy, gx + 16, SCREEN_H, 9)
            pyxel.tri(gx + 3, SCREEN_H, gx + 8, gy + 5, gx + 13, SCREEN_H, 10)
            pyxel.pset(gx + 8, gy, 7)
        for row in range(165, SCREEN_H):
            c = 9 if (row + self.t // 3) % 5 < 2 else 8
            pyxel.line(0, row, SCREEN_W, row, c)
        pyxel.rect(0, 165, SCREEN_W, 2, 10)

    # ─── PLATFORMS ───

    def _draw_platform(self, pl):
        x = int(pl.x - self.cam_x)
        y = int(pl.y)
        w = pl.w
        h = pl.h
        idx = self.lvl_idx

        if pl.p_type == 0:
            if idx == 1:   self._draw_plat_ice(x, y, w, h)
            elif idx == 2: self._draw_plat_lava_ground(x, y, w, h)
            elif idx == 3: self._draw_plat_cloud_ground(x, y, w, h)
            elif idx == 4: self._draw_plat_ghost_ground(x, y, w, h)
            elif idx == 5: self._draw_plat_inferno_ground(x, y, w, h)
            else:          self._draw_plat_forest_ground(x, y, w, h)

        elif pl.p_type == 1:
            if idx == 1:   self._draw_wall_ice(x, y, w, h)
            elif idx == 2: self._draw_wall_lava(x, y, w, h)
            else:          self._draw_wall_bark(x, y, w, h)

        elif pl.p_type == 2:
            if idx == 1:   self._draw_wall_ice(x, y, w, h)
            else:          self._draw_wall_stone(x, y, w, h)

        elif pl.p_type == 3:
            col1 = 8 if (self.t // 6) % 2 == 0 else 9
            col2 = 10 if (self.t // 6) % 2 == 0 else 8
            pyxel.rect(x, y, w, h, col1)
            tip_off = (self.t // 5) % 3
            i = 0
            while i < w:
                tip_x = x + i + tip_off
                pyxel.tri(tip_x, y, tip_x + 4, y, tip_x + 2, y - 5, col2)
                i += 8

        elif pl.p_type == 4:
            if idx == 1:
                pyxel.rect(x, y, w, h, 1)
                pyxel.rect(x, y + h - 3, w, 3, 6)
                pyxel.rect(x, y + h - 1, w, 1, 12)
                i = 0
                while i < w:
                    dh = 2 + (i * 5) % 4
                    pyxel.rect(x + i, y + h, 2, dh, 6)
                    pyxel.pset(x + i + 1, y + h + dh, 12)
                    i += 9
            else:
                pyxel.rect(x, y, w, h, 4)
                pyxel.rect(x, y + h - 3, w, 3, 11)
                i = 0
                while i < w:
                    pyxel.line(x + i, y + h, x + i + 2, y + h + 4, 11)
                    pyxel.line(x + i + 3, y + h, x + i + 3, y + h + 3, 3)
                    i += 7

    def _draw_plat_forest_ground(self, x, y, w, h):
        pyxel.rect(x, y, w, h, 4)
        pyxel.rect(x, y, w, 3, 5)
        pyxel.rect(x, y + 3, w, 2, 11)
        i = 0
        while i < w:
            pyxel.rect(x + i, y + 6, 10, 3, 3)
            pyxel.rect(x + i + 5, y + 10, 10, 3, 3)
            i += 14
        pyxel.pset(x, y, 7)
        pyxel.pset(x + w - 1, y, 7)

    def _draw_plat_ice(self, x, y, w, h):
        pyxel.rect(x, y, w, h, 1)
        pyxel.rect(x, y, w, 3, 6)
        pyxel.rect(x, y, w, 1, 12)
        pyxel.rect(x, y + 4, w, 2, 5)
        crack_off = int(self.cam_x * 0.5)
        i = 0
        while i < w:
            cx = x + i + (crack_off % 8)
            pyxel.line(cx, y + 2, cx + 3, y + 6, 1)
            pyxel.line(cx + 7, y + 1, cx + 5, y + 5, 5)
            i += 18
        pyxel.pset(x, y, 7)
        pyxel.pset(x + w - 1, y, 7)
        i = 0
        while i < w:
            dh = 3 + (i * 7 + int(self.cam_x)) % 5
            pyxel.rect(x + i, y + h, 2, dh, 6)
            pyxel.pset(x + i + 1, y + h + dh, 12)
            i += 10

    def _draw_plat_lava_ground(self, x, y, w, h):
        pyxel.rect(x, y, w, h, 2)
        pyxel.rect(x, y, w, 2, 0)
        pyxel.rect(x, y + 2, w, 2, 2)
        i = 0
        while i < w:
            crack_y = y + 4 + (i * 3) % 4
            c = 8 if (self.t // 8 + i) % 3 != 2 else 9
            pyxel.pset(x + i, crack_y, c)
            i += 6
        pyxel.pset(x, y, 8)
        pyxel.pset(x + w - 1, y, 8)

    def _draw_plat_cloud_ground(self, x, y, w, h):
        pyxel.rect(x, y, w, h, 7)
        pyxel.rect(x, y, w, 2, 13)
        i = 0
        while i < w:
            pyxel.circ(x + i + 5, y - 3, 5, 7)
            i += 10
        pyxel.rect(x + 2, y + h - 2, w - 4, 2, 13)

    def _draw_plat_ghost_ground(self, x, y, w, h):
        pyxel.rect(x, y, w, h, 5)
        pyxel.rect(x, y, w, 2, 0)
        i = 0
        while i < w:
            pyxel.line(x + i, y + 3, x + i + 1, y + h - 2, 1)
            i += 5
        pyxel.pset(x, y, 6)
        pyxel.pset(x + w - 1, y, 6)

    def _draw_plat_inferno_ground(self, x, y, w, h):
        pyxel.rect(x, y, w, h, 0)
        pyxel.rect(x, y, w, 2, 2)
        glow_c = 9 if (self.t // 6) % 2 == 0 else 8
        pyxel.rect(x, y, w, 1, glow_c)
        pyxel.pset(x, y, 10)
        pyxel.pset(x + w - 1, y, 10)
        i = 0
        while i < w:
            bub_phase = (self.t // 4 + i * 3) % 20
            if bub_phase < 8:
                pyxel.pset(x + i, y + 3 + bub_phase % 4, 9)
            i += 9

    def _draw_wall_bark(self, x, y, w, h):
        pyxel.rect(x, y, w, h, 4)
        i = 0
        while i < h:
            pyxel.rect(x, y + i, w, 1, 9)
            i += 10
        pyxel.rect(x, y, 3, h, 5)
        pyxel.rect(x + w - 2, y, 2, h, 3)

    def _draw_wall_stone(self, x, y, w, h):
        pyxel.rect(x, y, w, h, 6)
        i = 0
        while i < h:
            pyxel.rect(x, y + i, w, 1, 7)
            i += 8
        for di in range(0, h, 14):
            pyxel.pset(x + 3, y + di + 4, 7)
            pyxel.pset(x + w - 4, y + di + 10, 12)

    def _draw_wall_ice(self, x, y, w, h):
        pyxel.rect(x, y, w, h, 1)
        i = 0
        while i < h:
            lc = 5 if (i // 12) % 2 == 0 else 1
            pyxel.rect(x, y + i, w, min(12, h - i), lc)
            i += 12
        pyxel.rect(x, y, 2, h, 6)
        pyxel.rect(x, y, 1, h, 12)
        pyxel.rect(x + w - 2, y, 2, h, 1)
        for di in range(0, h, 16):
            pyxel.pset(x + 4, y + di + 5, 7)
            pyxel.pset(x + 3, y + di + 6, 12)
            pyxel.pset(x + 5, y + di + 6, 12)
            pyxel.pset(x + 4, y + di + 7, 6)
            if w > 10:
                pyxel.pset(x + w - 5, y + di + 8, 12)
                pyxel.pset(x + w - 5, y + di + 9, 7)
        for di in range(0, h, 24):
            shimmer = (self.t // 8 + di) % 24
            if shimmer < 6:
                pyxel.pset(x + 6, y + di + shimmer, 7)

    def _draw_wall_lava(self, x, y, w, h):
        pyxel.rect(x, y, w, h, 0)
        i = 0
        while i < h:
            c = 8 if (self.t // 12 + i) % 3 == 0 else 2
            pyxel.rect(x, y + i, w, 1, c)
            i += 12
        pyxel.rect(x, y, 2, h, 2)
        pyxel.rect(x + w - 2, y, 2, h, 8)

    # ─── GOAL ───

    def _draw_goal(self):
        gx = int(self.goal_x - self.cam_x)
        gy = 128
        glow_r = 9 + (self.t // 8) % 3
        pyxel.circ(gx, gy, glow_r, self.bg_col[1])
        pyxel.circ(gx, gy, 8, 9)
        pyxel.circ(gx, gy, 6, 10)
        pyxel.circ(gx, gy, 3, 7)
        pyxel.pset(gx - 1, gy - 1, 7)
        if (self.t // 8) % 2 == 0:
            pyxel.circb(gx, gy, 10, 9)
        else:
            pyxel.circb(gx, gy, 10, 10)
        pyxel.text(gx - 7, gy - 18, "ZIEL!", 10)

    # ─── ITEMS ───

    def _draw_items(self):
        idx = self.lvl_idx
        for it in self.items:
            if not it.alive:
                continue
            ix = int(it.x - self.cam_x)
            iy = int(it.screen_y())
            if it.kind == "nut":
                pyxel.circ(ix, iy, 4, 4)
                pyxel.circ(ix, iy, 3, 9)
                pyxel.circ(ix, iy, 2, 10)
                pyxel.pset(ix - 1, iy - 1, 7)
            elif it.kind == "gem":
                if idx == 1:
                    pyxel.tri(ix, iy - 5, ix - 4, iy, ix + 4, iy, 6)
                    pyxel.tri(ix - 4, iy, ix + 4, iy, ix, iy + 3, 12)
                    pyxel.line(ix - 2, iy - 3, ix, iy - 5, 7)
                    if (self.t // 6) % 3 == 0:
                        pyxel.pset(ix + 2, iy - 4, 7)
                else:
                    pyxel.tri(ix, iy - 5, ix - 4, iy, ix + 4, iy, 12)
                    pyxel.tri(ix - 4, iy, ix + 4, iy, ix, iy + 3, 6)
                    pyxel.line(ix - 2, iy - 3, ix, iy - 5, 7)
            else:
                for a in range(5):
                    ang = a * math.pi * 2 / 5 - math.pi / 2
                    ang2 = ang + math.pi / 5
                    ex2 = int(ix + math.cos(ang) * 5)
                    ey2 = int(iy + math.sin(ang) * 5)
                    mx2 = int(ix + math.cos(ang2) * 2)
                    my2 = int(iy + math.sin(ang2) * 2)
                    pyxel.tri(ix, iy, ex2, ey2, mx2, my2, 10)
                pyxel.pset(ix, iy, 9)

    # ─── ENEMIES ───

    def _draw_enemies(self):
        for e in self.enemies:
            if not e.alive:
                continue
            ex = int(e.x - self.cam_x)
            ey = int(e.y)
            if e.kind == "patrol":
                col = 8
                pyxel.rect(ex - 5, ey - 7, 10, 9, col)
                pyxel.rect(ex - 3, ey - 9, 6, 4, col)
                eye_off = 1 if e.vx > 0 else -1
                pyxel.pset(ex + eye_off * 2, ey - 5, 0)
                pyxel.pset(ex + eye_off * 2, ey - 4, 7)
                leg_a = (e.anim % 2) * 2
                pyxel.pset(ex - 2 + leg_a, ey + 2, col)
                pyxel.pset(ex + 2 - leg_a, ey + 2, col)
                pyxel.line(ex - 3, ey - 8, ex - 1, ey - 7, 2)
                pyxel.line(ex + 1, ey - 7, ex + 3, ey - 8, 2)
            elif e.kind == "chase":
                col = 2
                pyxel.rect(ex - 5, ey - 7, 10, 9, col)
                pyxel.rect(ex - 3, ey - 10, 6, 4, col)
                pyxel.pset(ex - 2, ey - 12, col)
                pyxel.pset(ex, ey - 13, col)
                pyxel.pset(ex + 2, ey - 12, col)
                ec = 9 if (e.timer // 10) % 2 else 10
                pyxel.pset(ex - 2, ey - 5, ec)
                pyxel.pset(ex + 2, ey - 5, ec)
            elif e.kind == "jumper":
                col = 3
                bob = int(math.sin(e.timer * 0.2) * 2)
                pyxel.circ(ex, ey - 5 + bob, 6, col)
                pyxel.circ(ex, ey - 5 + bob, 4, 11)
                pyxel.pset(ex - 2, ey - 6 + bob, 0)
                pyxel.pset(ex + 2, ey - 6 + bob, 0)
                pyxel.line(ex - 3, ey + 1, ex - 4, ey + 3 + bob, col)
                pyxel.line(ex + 3, ey + 1, ex + 4, ey + 3 + bob, col)
            elif e.kind == "flyer":
                col = 5
                wing = int(math.sin(e.timer * 0.3) * 4)
                pyxel.rect(ex - 4, ey - 5, 8, 7, col)
                pyxel.tri(ex - 4, ey - 3, ex - 10, ey - 3 - wing, ex - 4, ey + 1, 6)
                pyxel.tri(ex + 4, ey - 3, ex + 10, ey - 3 - wing, ex + 4, ey + 1, 6)
                pyxel.pset(ex - 1, ey - 3, 0)
                pyxel.pset(ex + 1, ey - 3, 0)

    # ─── SQUIRREL ───

    def _draw_squirrel_at(self, x, y, facing, frame, wall=False, ceil=False):
        body_col = 8
        tail_col = 9
        if wall:
            pyxel.rect(x + 1, y, 6, 8, body_col)
            pyxel.rect(x + 1, y, 6, 2, 9)
            claw_x = x + 7 if facing == 1 else x
            pyxel.pset(claw_x, y + 2, 7)
            pyxel.pset(claw_x, y + 5, 7)
            for tx2, ty2 in [(x - 2, y + 2), (x - 3, y + 4), (x - 2, y + 6)]:
                pyxel.pset(tx2, ty2, tail_col)
        elif ceil:
            pyxel.rect(x + 1, y, 6, 8, body_col)
            pyxel.pset(x + 2, y, 7)
            pyxel.pset(x + 5, y, 7)
            for ti in range(4):
                pyxel.pset(x + 3, y + 9 + ti, tail_col)
        else:
            bobs = [0, -1, 0, -1]
            bob = bobs[frame]
            py2 = y + bob
            tail_pts = ([(x-2,py2+1,tail_col),(x-3,py2+3,tail_col),(x-3,py2+5,10),(x-2,py2+6,tail_col)]
                        if facing == 1 else
                        [(x+8,py2+1,tail_col),(x+9,py2+3,tail_col),(x+9,py2+5,10),(x+8,py2+6,tail_col)])
            for tx2, ty2, tc in tail_pts:
                pyxel.pset(tx2, ty2, tc)
            pyxel.rect(x + 1, py2, 6, 7, body_col)
            pyxel.rect(x + 2, py2 + 2, 3, 3, 4)
            legs = [(2, 5), (3, 4), (2, 5), (1, 6)]
            la, lb = legs[frame]
            pyxel.pset(x + la, py2 + 7, body_col)
            pyxel.pset(x + lb, py2 + 7, body_col)
        tx = x - 4 if facing == 1 else x + 8
        pyxel.rect(tx, y + 1, 5, 5, 9)
        pyxel.pset(tx if facing == 1 else tx + 4, y + 4, 10)
        ex2 = x + 5 if facing == 1 else x + 1
        for ey2 in range(y - 2, y + 1):
            pyxel.pset(ex2, ey2, tail_col)
        eye_x = x + 4 if facing == 1 else x + 2
        pyxel.pset(eye_x, y + 2, 0)
        pyxel.pset(eye_x + (1 if facing == 1 else -1), y + 2, 7)
        nose_x = x + 7 if facing == 1 else x
        pyxel.pset(nose_x, y + 4, 4)
        pyxel.pset(nose_x, y + 5, 8)

    # ─── HUD ───

    def _draw_hud(self):
        pyxel.rect(0, 0, SCREEN_W, 13, 0)
        pyxel.line(0, 13, SCREEN_W, 13, 5)
        pyxel.rect(0, 12, SCREEN_W, 1, 9)
        names = ["Herbst-Wald", "Eishoehle", "Lava-Tempel", "Wolkengipfel",
                 "Geistertuerme", "Inferno-Gipfel"]
        pyxel.text(3, 3, "LVL" + str(self.lvl_idx + 1) + " " + names[self.lvl_idx], 7)
        sc_str = "SCORE:" + str(self.score)
        sc_x = SCREEN_W // 2 - len(sc_str) * 2
        pyxel.text(sc_x + 1, 4, sc_str, 0)
        pyxel.text(sc_x, 3, sc_str, 10)
        for i in range(self.lives):
            self._draw_heart(SCREEN_W - 10 - i * 12, 3)
        bar_x, bar_y = 3, SCREEN_H - 9
        pyxel.rect(bar_x, bar_y, 52, 6, 0)
        bar_w = int(self.stamina / STAMINA_MAX * 50)
        col = 11 if self.stamina > 60 else (9 if self.stamina > 25 else 8)
        pyxel.rect(bar_x + 1, bar_y + 1, bar_w, 4, col)
        if bar_w > 2:
            pyxel.rect(bar_x + 1, bar_y + 1, bar_w, 1, 7)
        pyxel.rectb(bar_x, bar_y, 52, 6, 5)
        pyxel.text(bar_x + 54, bar_y + 1, "STM", 13)
        if abs(self.wind) > 0.2:
            arrows = ">>" if self.wind > 0 else "<<"
            pyxel.text(SCREEN_W - 22, SCREEN_H - 9, arrows, 12 if self.wind > 0 else 6)
        if self.dash_cd > 0:
            fill = int((1 - self.dash_cd / 40) * 20)
            pyxel.rect(60, SCREEN_H - 9, fill, 6, 6)
            if fill > 1:
                pyxel.rect(60, SCREEN_H - 9, fill, 1, 7)
            pyxel.rectb(60, SCREEN_H - 9, 20, 6, 5)
            pyxel.text(82, SCREEN_H - 8, "DASH", 13)
        if self.hurt_timer > 50:
            for ry in range(0, SCREEN_H, 2):
                pyxel.line(0, ry, SCREEN_W, ry, 8)

    def _draw_heart(self, x, y):
        pyxel.pset(x + 1, y, 8); pyxel.pset(x + 3, y, 8)
        pyxel.rect(x, y + 1, 5, 2, 8)
        pyxel.pset(x + 1, y + 3, 8); pyxel.pset(x + 3, y + 3, 8)
        pyxel.pset(x + 2, y + 4, 8)
        pyxel.pset(x + 1, y + 1, 4)

    def _draw_overlay(self, title, subtitle, col):
        ox = SCREEN_W // 2 - 58
        oy = SCREEN_H // 2 - 20
        pyxel.rect(ox, oy + 2, 120, 44, 0)
        pyxel.rect(ox - 2, oy - 2, 120, 44, 0)
        pyxel.rectb(ox - 2, oy - 2, 120, 44, col)
        pyxel.rectb(ox - 3, oy - 3, 122, 46, 5)
        pyxel.rectb(ox - 1, oy - 1, 118, 42, col)
        pyxel.text(ox + 6, oy + 6, title, 0)
        pyxel.text(ox + 5, oy + 5, title, col)
        pyxel.text(ox + 5, oy + 14, subtitle, 7)
        pyxel.text(ox + 5, oy + 23, "SCORE: " + str(self.score), 10)
        if self.hi_score > 0:
            pyxel.text(ox + 5, oy + 31, "BEST:  " + str(self.hi_score), 9)


Game()