"""
╔══════════════════════════════════════════════════════════════╗
║         ARCHER DES ROYAUMES  —  RPG 2D Python/Tkinter        ║
║  ← → Déplacer | ↑ Sauter | 1 Arc | 2 Mêlée | 0 Attaquer    ║
║  . Ouvrir coffre | ESPACE Menu Pause                         ║
║  Traversez le PORTAIL (fin de map) pour changer de niveau    ║
╚══════════════════════════════════════════════════════════════╝
"""

import tkinter as tk
import math, random

# ═══════════════════════════════════════════════════════════════
#  CONFIG — modifiable
# ═══════════════════════════════════════════════════════════════
WIDTH, HEIGHT      = 980, 560
GROUND_Y           = 460
MAP_WIDTH          = 3600
PLAYER_W           = 26
PLAYER_H           = 38
SPEED              = 7
GRAVITY            = 1.5
JUMP_POWER         = -20
MAX_ARROWS         = 10
NB_RANDOM_LEVELS   = 10   # ← nombre de niveaux aléatoires avant le château

# ═══════════════════════════════════════════════════════════════
#  ARMES JOUEUR — organisées par tier (tier 1 = départ)
# ═══════════════════════════════════════════════════════════════
# tier = niveau minimum pour trouver l'arme dans un coffre (0 = toujours dispo)
WEAPONS = {
    # ── Armes de mêlée ──────────────────────────────────────────
    "epee_rouilee": {"name":"Épée Rouillée","icon":"⚔","cooldown":22,"damage":8,
                     "reach":38,"type":"melee","color":"#886644",
                     "desc":"Arme de départ — faible","tier":0},
    "dague":        {"name":"Dague",        "icon":"🗡","cooldown":9, "damage":14,
                     "reach":28,"type":"melee","color":"#AAAAFF",
                     "desc":"Rapide mais courte portée","tier":1},
    "epee":         {"name":"Épée",         "icon":"⚔","cooldown":18,"damage":22,
                     "reach":42,"type":"melee","color":"#C0C0C0",
                     "desc":"Équilibrée","tier":1},
    "lance":        {"name":"Lance",        "icon":"⚡","cooldown":26,"damage":28,
                     "reach":64,"type":"melee","color":"#D4C090",
                     "desc":"Longue portée","tier":2},
    "hache":        {"name":"Hache",        "icon":"🪓","cooldown":34,"damage":38,
                     "reach":40,"type":"melee","color":"#888844",
                     "desc":"Puissante","tier":2},
    "epee_acier":   {"name":"Épée d'Acier", "icon":"⚔","cooldown":16,"damage":32,
                     "reach":44,"type":"melee","color":"#88CCFF",
                     "desc":"Rapide et forte","tier":3},
    "marteau":      {"name":"Marteau de Guerre","icon":"🔨","cooldown":48,"damage":58,
                     "reach":34,"type":"melee","color":"#777777",
                     "desc":"Lent, dégâts massifs + fort recul","tier":3},
    "epee_feu":     {"name":"Épée de Feu",  "icon":"🔥","cooldown":20,"damage":65,
                     "reach":45,"type":"melee","color":"#FF6622",
                     "desc":"Brûle les ennemis","tier":4},
    # ── Arc ─────────────────────────────────────────────────────
    "arc":          {"name":"Arc",          "icon":"🏹","cooldown":22,"damage":25,
                     "reach":0, "type":"ranged","color":"#8B5E3C",
                     "desc":"Tir à distance (flèches limitées)","tier":0},
}

MELEE_WEAPONS = ["epee_rouilee","dague","epee","lance","hache","epee_acier","marteau","epee_feu"]

# ═══════════════════════════════════════════════════════════════
#  TYPES ENNEMIS
# ═══════════════════════════════════════════════════════════════
ENEMY_TYPES = {
    "goblin":    {"h":30,"base_hp":35, "base_spd":0.9,"base_dmg":5, "score":80,
                  "ai":"melee","aggro_range":220,"attack_range":34,"col":"#3a8a2a"},
    "soldat":    {"h":36,"base_hp":80, "base_spd":0.8,"base_dmg":10,"score":120,
                  "ai":"melee","aggro_range":250,"attack_range":36,"col":"#8B0000"},
    "archer_e":  {"h":36,"base_hp":60, "base_spd":0.6,"base_dmg":12,"score":150,
                  "ai":"ranged","aggro_range":380,"attack_range":0,"col":"#4a2244"},
    "goule":     {"h":34,"base_hp":65, "base_spd":1.0,"base_dmg":14,"score":140,
                  "ai":"rush","aggro_range":280,"attack_range":36,"col":"#3a6a10"},
    "sorcier":   {"h":40,"base_hp":55, "base_spd":0.4,"base_dmg":18,"score":200,
                  "ai":"magic","aggro_range":320,"attack_range":0,"col":"#220044"},
    "chevalier": {"h":40,"base_hp":160,"base_spd":0.7,"base_dmg":20,"score":260,
                  "ai":"melee","aggro_range":260,"attack_range":40,"col":"#404040"},
    "troll":     {"h":46,"base_hp":220,"base_spd":0.6,"base_dmg":25,"score":300,
                  "ai":"rush","aggro_range":240,"attack_range":50,"col":"#2a4a00"},
    "liche":     {"h":42,"base_hp":130,"base_spd":0.3,"base_dmg":28,"score":350,
                  "ai":"magic","aggro_range":340,"attack_range":0,"col":"#0a0022"},
    "assassin":  {"h":36,"base_hp":90, "base_spd":1.4,"base_dmg":18,"score":220,
                  "ai":"rush","aggro_range":300,"attack_range":34,"col":"#1a0a2a"},
    "dragon":    {"h":54,"base_hp":800,"base_spd":0.8,"base_dmg":35,"score":2000,
                  "ai":"boss","aggro_range":9999,"attack_range":60,"col":"#8B0000"},
}

# ═══════════════════════════════════════════════════════════════
#  THÈMES VISUELS
# ═══════════════════════════════════════════════════════════════
THEMES = [
    {"name":"Forêt Verte",     "sky_top":"#0d1f0d","sky_bot":"#2a5a2a",
     "ground_a":"#5a8a2a","ground_b":"#4a7a1a","dirt_a":"#6b4226","dirt_b":"#5a3820",
     "leaves":["#1a4d1a","#246b24","#2e8b2e","#1d6b1d","#155015"],"trunk":"#5C3A1E",
     "platform":"#4a7a1a","plat_top":"#5a9a2a","portal":"#22ff88"},
    {"name":"Marais Maudit",   "sky_top":"#0a0a1a","sky_bot":"#1a2a1a",
     "ground_a":"#3a5a2a","ground_b":"#2a4a1a","dirt_a":"#2a3a1a","dirt_b":"#1a2a0a",
     "leaves":["#0d3d0d","#1a5c0d","#0d4a1a","#1a3a0d","#0d2a0d"],"trunk":"#3C2A0E",
     "platform":"#2a4a1a","plat_top":"#3a6a2a","portal":"#88ff44"},
    {"name":"Toundra de Glace","sky_top":"#0a1a2a","sky_bot":"#1a3a5a",
     "ground_a":"#aaccee","ground_b":"#88aabb","dirt_a":"#6699aa","dirt_b":"#557788",
     "leaves":["#aaddff","#88ccee","#66bbdd","#44aacc","#3399bb"],"trunk":"#446677",
     "platform":"#88aabb","plat_top":"#cceeFF","portal":"#88ddff"},
    {"name":"Volcan Ardent",   "sky_top":"#1a0500","sky_bot":"#3a1000",
     "ground_a":"#5a2a00","ground_b":"#4a1a00","dirt_a":"#3a1500","dirt_b":"#2a0a00",
     "leaves":["#4a1500","#6a2000","#3a1000","#5a1800","#2a0800"],"trunk":"#2a1000",
     "platform":"#4a2200","plat_top":"#8a4400","portal":"#ff8822"},
    {"name":"Plaines Maudites","sky_top":"#1a1400","sky_bot":"#3a2a00",
     "ground_a":"#8a7a00","ground_b":"#7a6a00","dirt_a":"#5a4a00","dirt_b":"#4a3a00",
     "leaves":["#6a5a00","#8a7000","#5a4800","#7a6200","#4a3a00"],"trunk":"#4a3000",
     "platform":"#6a5a00","plat_top":"#aaaa00","portal":"#ffee44"},
    {"name":"Crypte Éternelle","sky_top":"#000000","sky_bot":"#0a000a",
     "ground_a":"#2a1a2a","ground_b":"#1a0a1a","dirt_a":"#1a0a1a","dirt_b":"#0a000a",
     "leaves":["#1a0a1a","#2a0a2a","#150a15","#1a0a10","#0a0510"],"trunk":"#1a0a0a",
     "platform":"#1a0a1a","plat_top":"#3a0a3a","portal":"#cc44ff"},
]
CHATEAU_THEME = {
    "name":"Château du Roi Mort","sky_top":"#050505","sky_bot":"#1a0a0a",
    "ground_a":"#3a2a2a","ground_b":"#2a1a1a","dirt_a":"#4a3a3a","dirt_b":"#3a2a2a",
    "leaves":["#1a0a0a","#2a1010","#1a0808","#0a0505","#2a0d0d"],"trunk":"#2C1A1A",
    "platform":"#2a1a1a","plat_top":"#4a2a2a","portal":"#ff2244",
}

# ═══════════════════════════════════════════════════════════════
#  GÉNÉRATION DE NIVEAU
# ═══════════════════════════════════════════════════════════════
def gen_level(idx, is_castle=False):
    rng   = random.Random(idx * 137 + 99)
    theme = CHATEAU_THEME if is_castle else THEMES[idx % len(THEMES)]
    scale = 1.0 + idx * 0.18

    if is_castle:
        pool = ["chevalier","chevalier","sorcier","liche","assassin"]
        nb   = 8
    elif idx == 0:
        pool = ["goblin","goblin","soldat"]
        nb   = 5
    elif idx <= 2:
        pool = ["goblin","soldat","archer_e","goule"]
        nb   = 6 + idx
    elif idx <= 4:
        pool = ["soldat","goule","sorcier","archer_e","chevalier"]
        nb   = 7 + idx
    else:
        pool = [k for k in ENEMY_TYPES if k != "dragon"]
        nb   = min(9 + idx, 16)

    enemies = []
    for i in range(nb):
        et  = rng.choice(pool)
        td  = ENEMY_TYPES[et]
        xpos = 500 + i * rng.randint(280, 380)
        hp   = int(td["base_hp"]  * scale * rng.uniform(0.85,1.2))
        spd  = td["base_spd"] * (1 + idx*0.05) * rng.uniform(0.9,1.1)
        dmg  = int(td["base_dmg"] * scale * rng.uniform(0.9,1.1))
        sc   = int(td["score"] * scale)
        enemies.append({"type":et,"x":float(xpos),"hp":hp,"max_hp":hp,
                        "speed":spd,"damage":dmg,"score":sc})

    if is_castle:
        enemies.append({"type":"dragon","x":float(MAP_WIDTH-500),
                        "hp":800,"max_hp":800,"speed":0.8,"damage":35,"score":2000})

    # Plateformes
    platforms = []
    px2 = 350
    while px2 < MAP_WIDTH - 500:
        pw  = rng.randint(90,220)
        py2 = GROUND_Y - rng.randint(80,200)
        platforms.append({"x":float(px2),"y":float(py2),"w":pw,"h":14})
        px2 += rng.randint(240,420)

    # Coffres — loot adapté au niveau
    chests = []
    for _ in range(rng.randint(3,6)):
        cx = float(rng.randint(400, MAP_WIDTH-400))
        chests.append({"x":cx,"y":float(GROUND_Y-22),"open":False})

    seed = idx*999 + (9999 if is_castle else 0)
    r2   = random.Random(seed)
    return {
        "name":      f"Niveau {idx+1} — {theme['name']}",
        "theme":     theme,
        "enemies":   enemies,
        "platforms": platforms,
        "chests":    chests,
        "portal_x":  float(MAP_WIDTH - 120),   # portail toujours à la fin
        "seed":      seed,
        "is_castle": is_castle,
        "tree_back":  sorted([r2.randint(50, MAP_WIDTH-50) for _ in range(22)]),
        "tree_front": sorted([r2.randint(50, MAP_WIDTH-50) for _ in range(18)]),
        "bushes":     sorted([r2.randint(50, MAP_WIDTH-50) for _ in range(28)]),
        "clouds":    [{"x":r2.randint(0,MAP_WIDTH),"y":r2.randint(20,110),
                       "w":r2.randint(50,120),"speed":0.1+r2.random()*0.25}
                      for _ in range(14)],
    }

# ═══════════════════════════════════════════════════════════════
#  BUTIN COFFRE (adapté au niveau)
# ═══════════════════════════════════════════════════════════════
def chest_loot(level_idx):
    """Génère le contenu d'un coffre selon le niveau actuel."""
    r = random.random()
    # Arme : pool selon le niveau
    weapon_pool = [w for w,d in WEAPONS.items()
                   if d["type"]=="melee" and d["tier"] <= max(1, level_idx)]
    # 30% chance arme, 25% flèches, 25% HP, 20% or
    if r < 0.30:
        wname = random.choice(weapon_pool)
        return {"type":"weapon","name":f"Arme : {WEAPONS[wname]['name']}",
                "weapon":wname,"color":"#aaddff","value":0}
    elif r < 0.55:
        v = random.choice([3,4,5])
        return {"type":"arrows","name":f"+{v} Flèches","value":v,"color":"#ffdd44"}
    elif r < 0.80:
        v = random.choice([1,1,2])
        return {"type":"hp","name":f"+{v} ♥","value":v,"color":"#ff4444"}
    else:
        v = random.choice([150,300,500])
        return {"type":"score","name":f"+{v} Or","value":v,"color":"#ffdd00"}

# ═══════════════════════════════════════════════════════════════
#  UTILITAIRE VITESSE
# ═══════════════════════════════════════════════════════════════
def speed_label(cd):
    if cd <= 10: return "Très rapide"
    if cd <= 20: return "Rapide"
    if cd <= 30: return "Moyen"
    if cd <= 45: return "Lent"
    return "Très lent"

# ═══════════════════════════════════════════════════════════════
#  CLASSE JEU
# ═══════════════════════════════════════════════════════════════
class Game:
    def __init__(self, root):
        self.root   = root
        self.root.title("Archer des Royaumes — RPG 2D")
        self.root.resizable(False, False)
        self.canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT,
                                bg="black", highlightthickness=0)
        self.canvas.pack()
        self.keys = {}
        self.root.bind("<KeyPress>",   self.on_kp)
        self.root.bind("<KeyRelease>", self.on_kr)

        self.nb_random   = NB_RANDOM_LEVELS
        self.total_lvls  = self.nb_random + 1
        self.level_idx   = 0
        self.total_score = 0
        self.melee_weapon = "epee_rouilee"   # arme de départ
        self.frame        = 0
        self.state        = "start"
        self.pause_sel    = 0
        self.loot_msg     = ""
        self.loot_timer   = 0
        self.portal_anim  = 0

        self.loop()

    # ───────────────────────────────────────────
    #  CHARGEMENT NIVEAU
    # ───────────────────────────────────────────
    def load_level(self, idx):
        is_castle = (idx == self.total_lvls - 1)
        self.lvl   = gen_level(idx, is_castle)
        self.theme = self.lvl["theme"]

        # Position joueur
        self.cam_x     = 0.0
        self.px        = 120.0
        self.py        = float(GROUND_Y - PLAYER_H)
        self.vy        = 0.0
        self.on_ground = True
        self.facing    = 1

        # Stats (on conserve les HP max si bonus de niveau précédent)
        if idx == 0:
            self.player_hp     = 1000
            self.player_max_hp = 1000
        # else: on garde les HP actuels (mais on les remplit pas)

        self.arrows_proj  = []
        self.enemy_proj   = []
        self.particles    = []
        self.drops        = []
        self.swing_anim   = 0
        self.attack_cd    = 0
        self.invincible   = 0
        self.frame        = 0
        self.state        = "playing"
        self.loot_msg     = ""
        self.loot_timer   = 0
        self.portal_active = False   # le portail s'active quand tous les ennemis sont morts
        self.portal_anim  = 0

        # Arme courante
        self.current_weapon = "arc"
        self.arrow_count    = MAX_ARROWS

        # Ennemis
        self.enemies = []
        for ed in self.lvl["enemies"]:
            et  = ed["type"]
            td  = ENEMY_TYPES[et]
            self.enemies.append({
                "type":       et,
                "x":          ed["x"],
                "y":          float(GROUND_Y - td["h"]),
                "hp":         ed["hp"],
                "max_hp":     ed["max_hp"],
                "speed":      ed["speed"],
                "damage":     ed["damage"],
                "score":      ed["score"],
                "ai":         td["ai"],
                "aggro_range":td["aggro_range"],
                "attack_range":td["attack_range"],
                "alive":      True,
                "dir":        -1,
                "hit_flash":  0,
                "attack_cd":  0,
                "shoot_cd":   0,
                "swing":      0,
                "knockback":  0.0,   # recul en cours
                "phase":      1,
                "alerted":    False, # a-t-il détecté le joueur ?
            })

    # ───────────────────────────────────────────
    #  INPUT
    # ───────────────────────────────────────────
    def on_kp(self, event):
        sym = event.keysym; ch = event.char
        self.keys[sym] = True

        if self.state == "start":
            if sym in ("Return","space"):
                self.level_idx = 0; self.total_score = 0
                self.melee_weapon = "epee_rouilee"
                self.player_hp = 5; self.player_max_hp = 5
                self.load_level(0)
            return

        if self.state in ("dead","victory") and sym in ("r","R"):
            self.level_idx = 0; self.total_score = 0
            self.melee_weapon = "epee_rouilee"
            self.player_hp = 5; self.player_max_hp = 5
            self.load_level(0)
            return

        if self.state == "pause":
            if sym in ("Escape","space"):
                self.state = "playing"
            elif sym in ("Up","z","w"):
                self.pause_sel = (self.pause_sel-1) % self._nb_melee_owned()
            elif sym in ("Down","s"):
                self.pause_sel = (self.pause_sel+1) % self._nb_melee_owned()
            elif sym == "Return":
                owned = self._owned_melee()
                if owned:
                    self.melee_weapon = owned[self.pause_sel]
                    if self.current_weapon not in ("arc", self.melee_weapon):
                        self.current_weapon = self.melee_weapon
                self.state = "playing"
            return

        if self.state == "playing":
            if sym == "space":
                self.state = "pause"
                owned = self._owned_melee()
                self.pause_sel = owned.index(self.melee_weapon) if self.melee_weapon in owned else 0
                return
            if ch == "1": self.current_weapon = "arc"
            if ch == "2": self.current_weapon = self.melee_weapon
            if ch == "0": self.do_attack()
            if ch in (".",",") or sym == "period": self.try_open_chest()

    def on_kr(self, event):
        self.keys[event.keysym] = False

    def _key(self, *names):
        return any(self.keys.get(n) for n in names)

    def _owned_melee(self):
        return list(self.melee_owned) if hasattr(self,"melee_owned") else [self.melee_weapon]

    def _nb_melee_owned(self):
        return max(1, len(self._owned_melee()))

    # ───────────────────────────────────────────
    #  COFFRE
    # ───────────────────────────────────────────
    def try_open_chest(self):
        for ch in self.lvl["chests"]:
            if ch["open"]: continue
            if abs(ch["x"] - self.px) < 40 and abs(ch["y"] - self.py) < 55:
                ch["open"] = True
                loot = chest_loot(self.level_idx)
                self._apply_loot(loot, ch["x"])
                return

    def _apply_loot(self, loot, x):
        sx = x - self.cam_x
        if loot["type"] == "weapon":
            wname = loot["weapon"]
            if not hasattr(self,"melee_owned"):
                self.melee_owned = {self.melee_weapon}
            self.melee_owned.add(wname)
            # Équipe automatiquement si meilleure que l'arme actuelle
            if WEAPONS[wname]["damage"] > WEAPONS[self.melee_weapon]["damage"]:
                old = self.melee_weapon
                self.melee_weapon = wname
                self.loot_msg = f"🗡 {WEAPONS[wname]['name']} ({WEAPONS[wname]['damage']} dmg) !"
            else:
                self.loot_msg = f"🗡 {WEAPONS[wname]['name']} trouvée !"
            self._particles(sx+10, GROUND_Y-30, "#aaddff", 16)
        elif loot["type"] == "arrows":
            self.arrow_count = min(MAX_ARROWS, self.arrow_count + loot["value"])
            self.loot_msg = f"+{loot['value']} flèches !"
            self._particles(sx+10, GROUND_Y-30, "#ffdd44", 12)
        elif loot["type"] == "hp":
            self.player_hp = min(self.player_max_hp, self.player_hp + loot["value"])
            self.loot_msg = f"+{loot['value']} ♥ !"
            self._particles(sx+10, GROUND_Y-30, "#ff4444", 12)
        elif loot["type"] == "score":
            self.total_score += loot["value"]
            self.loot_msg = f"+{loot['value']} pièces d'or !"
            self._particles(sx+10, GROUND_Y-30, "#ffdd00", 12)
        self.loot_timer = 130

    # ───────────────────────────────────────────
    #  ATTAQUE
    # ───────────────────────────────────────────
    def do_attack(self):
        wp = WEAPONS[self.current_weapon]
        if self.attack_cd > 0: return
        self.attack_cd = wp["cooldown"]

        if wp["type"] == "ranged":
            if self.arrow_count <= 0: return
            self.arrow_count -= 1
            self.arrows_proj.append({
                "x":  self.px + (PLAYER_W+2 if self.facing==1 else -4),
                "y":  self.py + 14,
                "vx": self.facing * 12.0,
                "vy": -0.5,
                "dmg":wp["damage"],
                "alive":True,
            })
        else:
            self.swing_anim = 14
            reach = wp["reach"]
            x1 = self.px + (PLAYER_W if self.facing==1 else -reach)
            x2 = x1 + reach
            kb_force = 8 if wp["name"]=="Marteau de Guerre" else 5
            for e in self.enemies:
                if not e["alive"]: continue
                eh = ENEMY_TYPES[e["type"]]["h"]
                if x1 < e["x"]+30 and x2 > e["x"] and \
                   self.py < e["y"]+eh and self.py+PLAYER_H > e["y"]:
                    e["hp"] -= wp["damage"]
                    e["hit_flash"] = 12
                    # Recul ennemi
                    e["knockback"] = self.facing * kb_force
                    self._particles(e["x"]+14-self.cam_x, e["y"]+14, "#ff4422", 8)
                    if e["hp"] <= 0:
                        e["alive"] = False
                        self._enemy_die(e)

    def _enemy_die(self, e):
        # Chance de drop flèches
        if random.random() < 0.40:
            n = random.randint(1,3)
            self.drops.append({"x":e["x"]+8,"y":e["y"],"count":n,"life":340})

    def _level_score(self):
        return sum(e["score"] for e in self.enemies if not e["alive"])

    # ───────────────────────────────────────────
    #  PHYSIQUE PLATEFORMES
    # ───────────────────────────────────────────
    def _on_platform(self):
        for p in self.lvl["platforms"]:
            if (p["x"] <= self.px+PLAYER_W and self.px <= p["x"]+p["w"] and
                p["y"] <= self.py+PLAYER_H <= p["y"]+p["h"]+10 and self.vy >= 0):
                return p
        return None

    # ───────────────────────────────────────────
    #  UPDATE
    # ───────────────────────────────────────────
    def update(self):
        if self.state != "playing": return
        self.frame     += 1
        self.attack_cd  = max(0, self.attack_cd-1)
        self.invincible = max(0, self.invincible-1)
        self.swing_anim = max(0, self.swing_anim-1)
        self.loot_timer = max(0, self.loot_timer-1)
        self.portal_anim = (self.portal_anim+1) % 60

        # ── Portail : s'active quand tous les ennemis sont morts
        all_dead = all(not e["alive"] for e in self.enemies)
        if all_dead and not self.portal_active:
            self.portal_active = True
            self._particles(self.lvl["portal_x"]-self.cam_x+20, GROUND_Y-60,
                            self.theme.get("portal","#22ff88"), 30)

        # ── Mouvement joueur
        if self._key("Left","a"):  self.px -= SPEED; self.facing = -1
        if self._key("Right","d"): self.px += SPEED; self.facing = 1
        if self._key("Up","w") and self.on_ground:
            self.vy = JUMP_POWER; self.on_ground = False

        self.vy += GRAVITY
        self.py += self.vy

        # Sol + plateformes
        self.on_ground = False
        if self.py >= GROUND_Y - PLAYER_H:
            self.py = GROUND_Y - PLAYER_H
            self.vy = 0; self.on_ground = True
        else:
            plat = self._on_platform()
            if plat:
                self.py = plat["y"] - PLAYER_H
                self.vy = 0; self.on_ground = True

        self.px = max(0.0, min(MAP_WIDTH-PLAYER_W, self.px))
        self.cam_x = max(0.0, min(MAP_WIDTH-WIDTH, self.px - WIDTH//2 + PLAYER_W//2))

        # ── Portail — traverser pour changer de niveau
        if self.portal_active:
            px2 = self.lvl["portal_x"]
            if abs(self.px - px2) < 50 and abs(self.py - (GROUND_Y-PLAYER_H)) < 60:
                # Transition !
                self.total_score += self._level_score()
                next_idx = self.level_idx + 1
                if next_idx >= self.total_lvls:
                    self.state = "victory"
                else:
                    self.level_idx = next_idx
                    self.load_level(self.level_idx)
                return

        # ── Flèches joueur
        for a in self.arrows_proj:
            a["x"]+=a["vx"]; a["y"]+=a["vy"]; a["vy"]+=0.18
            if a["x"]<0 or a["x"]>MAP_WIDTH or a["y"]>GROUND_Y:
                a["alive"]=False; continue
            for e in self.enemies:
                if not e["alive"]: continue
                eh = ENEMY_TYPES[e["type"]]["h"]
                if e["x"] < a["x"] < e["x"]+32 and e["y"] < a["y"] < e["y"]+eh:
                    a["alive"]=False; e["hp"]-=a["dmg"]; e["hit_flash"]=10
                    e["knockback"] = (1 if a["vx"]>0 else -1) * 4
                    self._particles(a["x"]-self.cam_x, a["y"], "#cc2222", 8)
                    if e["hp"]<=0:
                        e["alive"]=False; self._enemy_die(e)
        self.arrows_proj = [a for a in self.arrows_proj if a["alive"]]

        # ── IA ennemis — zone d'aggro
        for e in self.enemies:
            if not e["alive"]: continue
            e["hit_flash"]  = max(0, e["hit_flash"]-1)
            e["attack_cd"]  = max(0, e["attack_cd"]-1)
            e["shoot_cd"]   = max(0, e["shoot_cd"]-1)
            e["swing"]      = max(0, e["swing"]-1)

            # Recul
            if abs(e["knockback"]) > 0.1:
                e["x"] += e["knockback"]
                e["knockback"] *= 0.7  # friction
            else:
                e["knockback"] = 0.0

            dx   = self.px - e["x"]
            dist = abs(dx)
            e["dir"] = 1 if dx > 0 else -1

            # Détection joueur (zone d'aggro)
            if dist < e["aggro_range"]:
                e["alerted"] = True
            # Si touché, toujours alerté
            if e["hit_flash"] > 0:
                e["alerted"] = True

            if not e["alerted"]:
                # Patrouille lente sur place
                if self.frame % 120 < 60:
                    e["x"] += 0.3
                else:
                    e["x"] -= 0.3
                e["x"] = max(50.0, min(MAP_WIDTH-80, e["x"]))
                continue

            ai = e["ai"]

            if ai in ("melee","rush"):
                spd = e["speed"] * (1.3 if ai=="rush" else 1.0)
                e["x"] += e["dir"] * spd
                if dist < e["attack_range"] and e["attack_cd"]==0:
                    e["attack_cd"] = 52 if ai=="melee" else 40
                    e["swing"]     = 12
                    if self.invincible == 0:
                        self.player_hp -= 1
                        self.invincible = 50
                        self._particles(self.px+12-self.cam_x, self.py+18, "#4488ff", 6)

            elif ai == "ranged":
                # Recule si trop proche, avance si trop loin
                if dist < 160:
                    e["x"] -= e["dir"] * e["speed"]
                elif dist > 350:
                    e["x"] += e["dir"] * e["speed"] * 0.5
                if e["shoot_cd"]==0 and dist < 400:
                    e["shoot_cd"] = 95
                    self.enemy_proj.append({
                        "x":e["x"]+14,"y":e["y"]+16,
                        "vx":e["dir"]*7,"vy":-0.6,
                        "dmg":e["damage"],"kind":"arrow","alive":True,
                    })

            elif ai == "magic":
                if dist < 140:
                    e["x"] -= e["dir"] * e["speed"]
                elif dist > 280:
                    e["x"] += e["dir"] * e["speed"] * 0.4
                if e["shoot_cd"]==0 and dist < 340:
                    e["shoot_cd"] = 105
                    self.enemy_proj.append({
                        "x":e["x"]+14,"y":e["y"]+18,
                        "vx":e["dir"]*5.5,"vy":-1.0,
                        "dmg":e["damage"],"kind":"magic","alive":True,
                    })

            elif ai == "boss":
                ratio = e["hp"]/e["max_hp"]
                if ratio < 0.5 and e["phase"]==1:
                    e["phase"]=2; e["speed"]*=1.4
                    self._particles(e["x"]+25-self.cam_x, e["y"]+20, "#ff4400", 30)
                e["x"] += e["dir"] * e["speed"]
                if dist < e["attack_range"] and e["attack_cd"]==0:
                    e["attack_cd"]=32; e["swing"]=14
                    if self.invincible==0:
                        self.player_hp -= 2; self.invincible=32
                        self._particles(self.px+12-self.cam_x, self.py+18, "#ff4400", 10)
                if e["shoot_cd"]==0:
                    e["shoot_cd"] = 50 if e["phase"]==1 else 28
                    for ang in ([0] if e["phase"]==1 else [-18,0,18]):
                        rad=math.radians(ang)
                        vx=e["dir"]*8*math.cos(rad); vy=-1.2+6*math.sin(rad)
                        self.enemy_proj.append({
                            "x":e["x"]+30,"y":e["y"]+22,
                            "vx":vx,"vy":vy,"dmg":e["damage"],"kind":"fire","alive":True,
                        })

            e["x"] = max(50.0, min(MAP_WIDTH-80, e["x"]))

        # ── Projectiles ennemis
        for p in self.enemy_proj:
            p["x"]+=p["vx"]; p["y"]+=p["vy"]; p["vy"]+=0.1
            if p["x"]<0 or p["x"]>MAP_WIDTH or p["y"]>GROUND_Y:
                p["alive"]=False; continue
            # Collision STRICTE : boîte réduite pour éviter les faux positifs
            if (self.px+4 < p["x"] < self.px+PLAYER_W-4 and
                self.py+4 < p["y"] < self.py+PLAYER_H-4):
                p["alive"]=False
                if self.invincible==0:
                    self.player_hp -= 1; self.invincible=45
                    col={"magic":"#aa44ff","fire":"#ff4400"}.get(p["kind"],"#ff8822")
                    self._particles(p["x"]-self.cam_x, p["y"], col, 7)
        self.enemy_proj = [p for p in self.enemy_proj if p["alive"]]

        # ── Drops flèches
        for d in self.drops:
            d["life"] -= 1
            if (abs(self.px+PLAYER_W//2-(d["x"]+8)) < 26 and
                abs(self.py+PLAYER_H//2-(d["y"]+8)) < 30):
                self.arrow_count = min(MAX_ARROWS, self.arrow_count+d["count"])
                self._particles(d["x"]-self.cam_x, d["y"], "#ffdd44", 10)
                self.loot_msg = f"+{d['count']} flèches !"; self.loot_timer=80
                d["life"]=0
        self.drops = [d for d in self.drops if d["life"]>0]

        # ── Particules
        for p in self.particles:
            p["x"]+=p["vx"]; p["y"]+=p["vy"]; p["vy"]+=0.15; p["life"]-=1
        self.particles = [p for p in self.particles if p["life"]>0]

        # ── Nuages
        for cl in self.lvl["clouds"]:
            cl["x"] += cl["speed"]

        # ── Mort
        if self.player_hp <= 0:
            self.player_hp=0; self.state="dead"

    # ───────────────────────────────────────────
    def _particles(self, sx, sy, color, n=6):
        for _ in range(n):
            self.particles.append({
                "x":sx,"y":sy,
                "vx":random.uniform(-3,3),"vy":random.uniform(-4,-0.5),
                "life":random.randint(12,22),"color":color,
            })

    # ═══════════════════════════════════════════
    #  RENDU
    # ═══════════════════════════════════════════
    def draw(self):
        c = self.canvas
        c.delete("all")

        if self.state == "start":
            self._draw_start(c); return

        th = self.theme

        # Ciel
        for i in range(12):
            t=i/12; col=self._lerp(th["sky_top"],th["sky_bot"],t)
            c.create_rectangle(0,int(i*HEIGHT/12),WIDTH,int((i+1)*HEIGHT/12),fill=col,outline="")

        # Nuages
        for cl in self.lvl["clouds"]:
            cx=cl["x"]-self.cam_x
            if -130<cx<WIDTH+130:
                c.create_rectangle(cx,cl["y"],cx+cl["w"],cl["y"]+10,
                                   fill="#b0c8b0",outline="",stipple="gray25")

        # Arbres
        for tx in self.lvl["tree_back"]:
            self._draw_tree(c, tx-self.cam_x*0.4, th, 0.65)
        for tx in self.lvl["tree_front"]:
            self._draw_tree(c, tx-self.cam_x*0.78, th, 1.0)

        # Sol
        for gx in range(0,MAP_WIDTH,16):
            sx=gx-self.cam_x
            if sx<-16 or sx>WIDTH+16: continue
            c.create_rectangle(sx,GROUND_Y,sx+16,GROUND_Y+4,
                fill=th["ground_a"] if (gx//16)%2==0 else th["ground_b"],outline="")
            c.create_rectangle(sx,GROUND_Y+4,sx+16,HEIGHT,
                fill=th["dirt_a"] if (gx//16)%3==0 else th["dirt_b"],outline="")

        # Buissons
        for bx in self.lvl["bushes"]:
            sx=bx-self.cam_x
            if -50<sx<WIDTH+50: self._draw_bush(c,sx,th)

        # Plateformes
        for p in self.lvl["platforms"]:
            sx=p["x"]-self.cam_x
            if -p["w"]<sx<WIDTH+p["w"]:
                c.create_rectangle(sx,p["y"],sx+p["w"],p["y"]+p["h"],
                                   fill=th["platform"],outline="")
                c.create_rectangle(sx,p["y"],sx+p["w"],p["y"]+4,
                                   fill=th.get("plat_top","#aaa"),outline="")

        # Portail
        self._draw_portal(c)

        # Coffres
        for ch in self.lvl["chests"]:
            sx=ch["x"]-self.cam_x
            if -40<sx<WIDTH+40:
                self._draw_chest(c,sx,ch["y"],ch["open"])
                if not ch["open"] and abs(ch["x"]-self.px)<44:
                    c.create_text(sx+10,ch["y"]-16,text="[.] Ouvrir",
                                  fill="#ffdd44",font=("Courier",8,"bold"))

        # Ennemis
        for e in self.enemies:
            if not e["alive"]: continue
            sx=e["x"]-self.cam_x
            if -80<sx<WIDTH+80:
                self._draw_enemy(c,e,int(sx))
                eh=ENEMY_TYPES[e["type"]]["h"]
                bw=60 if e["type"]=="dragon" else 40
                self._draw_hp_bar(c,sx,e["y"]-14,e["hp"],e["max_hp"],bw)
                # Indicateur d'aggro
                if not e["alerted"]:
                    c.create_text(sx+14,e["y"]-20,text="?",
                                  fill="#ffdd44",font=("Courier",10,"bold"))
                if e["type"]=="dragon":
                    c.create_text(sx+28,e["y"]-28,text="★ BOSS DRAGON ★",
                                  fill="#ff4400",font=("Courier",9,"bold"))

        # Projectiles ennemis
        for p in self.enemy_proj:
            sx=p["x"]-self.cam_x
            if 0<sx<WIDTH:
                if p["kind"]=="magic":
                    c.create_oval(sx-6,p["y"]-6,sx+6,p["y"]+6,fill="#cc44ff",outline="#fff")
                    c.create_oval(sx-3,p["y"]-3,sx+3,p["y"]+3,fill="#fff",outline="")
                elif p["kind"]=="fire":
                    c.create_oval(sx-7,p["y"]-7,sx+7,p["y"]+7,fill="#ff4400",outline="#ffdd00")
                    c.create_oval(sx-4,p["y"]-4,sx+4,p["y"]+4,fill="#ffaa00",outline="")
                else:
                    ang=math.degrees(math.atan2(p["vy"],p["vx"]))
                    self._draw_arrow(c,sx,p["y"],ang,"#cc4400")

        # Flèches joueur
        for a in self.arrows_proj:
            sx=a["x"]-self.cam_x
            if 0<sx<WIDTH:
                ang=math.degrees(math.atan2(a["vy"],a["vx"]))
                self._draw_arrow(c,sx,a["y"],ang,"#8B6914")

        # Drops
        for d in self.drops:
            sx=d["x"]-self.cam_x
            if 0<sx<WIDTH:
                pulse=1 if (self.frame//6)%2==0 else 0
                c.create_rectangle(sx-2+pulse,d["y"]-2+pulse,sx+14+pulse,d["y"]+14+pulse,
                                   fill="#442200",outline="#ffdd44",width=1)
                c.create_line(sx,d["y"]+7,sx+12,d["y"]+7,fill="#8B6914",width=2)
                c.create_text(sx+6,d["y"]+4,text=f"+{d['count']}",
                              fill="#ffdd44",font=("Courier",7,"bold"))

        # Joueur
        psx=int(self.px-self.cam_x)
        if self.invincible==0 or self.frame%4<2:
            self._draw_player(c,psx,int(self.py))
        if self.swing_anim>0 and WEAPONS[self.current_weapon]["type"]=="melee":
            self._draw_swing(c,psx,int(self.py))

        # Particules
        for p in self.particles:
            al=p["life"]/22.0
            r,g,b=self._hex_rgb(p["color"])
            col=f"#{int(r*al):02x}{int(g*al):02x}{int(b*al):02x}"
            c.create_rectangle(p["x"]-3,p["y"]-3,p["x"]+3,p["y"]+3,fill=col,outline="")

        # Message loot
        if self.loot_timer>0:
            c.create_text(WIDTH//2,HEIGHT//2-90,text=self.loot_msg,
                          fill="#ffdd44",font=("Courier",16,"bold"))

        # HUD
        self._draw_hud(c)

        # Écrans
        if self.state=="pause":     self._draw_pause(c)
        elif self.state=="dead":
            self._overlay(c,"VOUS ÊTES MORT","#cc2222",
                f"Score : {self.total_score}","[R] Recommencer depuis le début")
        elif self.state=="victory":
            self._overlay(c,"✦ VICTOIRE TOTALE ✦","#ffcc00",
                f"Score final : {self.total_score}","[R] Rejouer")

    # ───────────────────────────────────────────
    #  PORTAIL
    # ───────────────────────────────────────────
    def _draw_portal(self, c):
        px2 = self.lvl["portal_x"] - self.cam_x
        if px2 < -60 or px2 > WIDTH+60: return
        col = self.theme.get("portal","#22ff88")

        if not self.portal_active:
            # Portail fermé : silhouette grise
            c.create_oval(px2+2,GROUND_Y-90,px2+38,GROUND_Y+2,
                          fill="#222222",outline="#444444",width=2)
            c.create_text(px2+20,GROUND_Y-100,text="Portail\n(fermé)",
                          fill="#555555",font=("Courier",8),justify="center")
            return

        # Portail actif : animation pulsante
        t   = math.sin(self.portal_anim * 0.2)
        glow= int(60 + 40*t)
        r2,g2,b2 = self._hex_rgb(col)
        pulse_col = f"#{min(255,r2+glow):02x}{min(255,g2+glow):02x}{min(255,b2+glow):02x}"

        # Halo extérieur
        for i in range(4):
            alpha_r = 1.0 - i*0.2
            ex = int(6+i*4); ey = int(6+i*4)
            glow_col2=f"#{int(r2*alpha_r):02x}{int(g2*alpha_r):02x}{int(b2*alpha_r):02x}"
            c.create_oval(px2-ex,GROUND_Y-95-ey,px2+40+ex,GROUND_Y+4+ey,
                          fill="",outline=glow_col2,width=2)

        # Corps du portail
        c.create_oval(px2,GROUND_Y-90,px2+40,GROUND_Y+2,
                      fill="#000000",outline=pulse_col,width=3)
        # Spirale intérieure
        for i in range(8):
            ang = self.portal_anim*6 + i*45
            rad = math.radians(ang)
            rx=int(14*math.cos(rad)); ry=int(30*math.sin(rad))
            c.create_oval(px2+20+rx-3,GROUND_Y-44+ry-3,
                          px2+20+rx+3,GROUND_Y-44+ry+3,
                          fill=pulse_col,outline="")

        c.create_text(px2+20,GROUND_Y-104,text="▶ PORTAIL ◀",
                      fill=pulse_col,font=("Courier",9,"bold"))

    # ───────────────────────────────────────────
    #  ÉCRAN TITRE
    # ───────────────────────────────────────────
    def _draw_start(self, c):
        for i in range(10):
            t=i/10; col=self._lerp("#0d1f0d","#2a5a2a",t)
            c.create_rectangle(0,int(i*HEIGHT/10),WIDTH,int((i+1)*HEIGHT/10),fill=col,outline="")
        c.create_text(WIDTH//2,70,text="⚔  ARCHER DES ROYAUMES  ⚔",
                      fill="#ffdd44",font=("Courier",26,"bold"))
        c.create_text(WIDTH//2,118,text="RPG 2D — Aventure Pixel Art",
                      fill="#D4C090",font=("Courier",14))
        lines=[
            ("═"*52,"#4a3a00"),
            ("CONTRÔLES","#88ccff"),
            ("← → : Déplacer          ↑ : Sauter","#ffffff"),
            ("1 : Équiper l'Arc        2 : Équiper Mêlée","#ffffff"),
            ("0 : Attaquer / Tirer     . : Ouvrir coffre","#ffffff"),
            ("ESPACE : Pause / Menu armes de mêlée","#ffffff"),
            ("═"*52,"#4a3a00"),
            ("PROGRESSION","#88ccff"),
            ("Partez avec une Épée Rouillée — améliorez-la dans les coffres !","#ffaa44"),
            (f"Traversez le portail (fin de carte) pour avancer","#88ff88"),
            (f"Le portail s'ouvre quand tous les ennemis sont vaincus","#88ff88"),
            (f"{self.nb_random} niveaux aléatoires + Château Final avec Boss Dragon","#ff4444"),
        ]
        y=162
        for txt,col in lines:
            c.create_text(WIDTH//2,y,text=txt,fill=col,font=("Courier",11)); y+=28
        if (self.frame//30)%2==0:
            c.create_text(WIDTH//2,HEIGHT-38,text="▶  Appuyez sur ENTRÉE pour commencer  ◀",
                          fill="#ffdd44",font=("Courier",14,"bold"))

    # ───────────────────────────────────────────
    #  MENU PAUSE
    # ───────────────────────────────────────────
    def _draw_pause(self, c):
        c.create_rectangle(WIDTH//2-240,HEIGHT//2-200,WIDTH//2+240,HEIGHT//2+200,
                           fill="#000000",stipple="gray75",outline="")
        c.create_rectangle(WIDTH//2-240,HEIGHT//2-200,WIDTH//2+240,HEIGHT//2+200,
                           outline="#6a5a20",fill="")
        c.create_text(WIDTH//2,HEIGHT//2-172,text="⚙  PAUSE — ARMES DISPONIBLES",
                      fill="#ffdd44",font=("Courier",13,"bold"))
        c.create_text(WIDTH//2,HEIGHT//2-148,text="↑↓ Naviguer   Entrée Confirmer   Espace Fermer",
                      fill="#555555",font=("Courier",9))

        owned = self._owned_melee()
        if not owned:
            c.create_text(WIDTH//2,HEIGHT//2,text="Aucune arme trouvée encore",
                          fill="#666666",font=("Courier",12))
            return

        start_y = HEIGHT//2 - 120
        for i,wname in enumerate(owned):
            wp  = WEAPONS[wname]
            sel = (i==self.pause_sel)
            is_eq = (wname==self.melee_weapon)
            y   = start_y + i*52

            bg  = "#221100" if sel else "#110800"
            brd = "#ffdd44" if sel else ("#88ccff" if is_eq else "#443300")
            c.create_rectangle(WIDTH//2-200,y-20,WIDTH//2+200,y+26,
                               fill=bg,outline=brd,width=2)
            mark = " [Équipée]" if is_eq else ""
            c.create_text(WIDTH//2-185,y-4,
                text=f"{wp['icon']} {wp['name']}{mark}",
                anchor="w",fill="#ffdd44" if sel else "#D4C090",
                font=("Courier",11,"bold" if sel else "normal"))
            c.create_text(WIDTH//2+195,y-10,
                text=f"⚔ {wp['damage']} dmg",
                anchor="e",fill="#ff8888",font=("Courier",9))
            c.create_text(WIDTH//2+195,y+6,
                text=f"⚡ {speed_label(wp['cooldown'])}",
                anchor="e",fill="#88ccff",font=("Courier",9))
            c.create_text(WIDTH//2,y+18,text=wp["desc"],
                fill="#666666",font=("Courier",8))

    # ───────────────────────────────────────────
    #  HUD
    # ───────────────────────────────────────────
    def _draw_hud(self, c):
        # Panneau gauche
        c.create_rectangle(4,4,290,90,fill="#000000",stipple="gray50",outline="#4a3a00")
        c.create_rectangle(4,4,290,90,outline="#6a5a20",fill="")
        c.create_text(12,17,text=self.lvl["name"],anchor="w",
                      fill="#D4C090",font=("Courier",10,"bold"))
        # Coeurs
        c.create_text(12,35,text="VIE :",anchor="w",fill="#aaaaaa",font=("Courier",9))
        for i in range(self.player_max_hp):
            self._draw_heart(c,52+i*20,27,
                             "#cc2222" if i<self.player_hp else "#442222")
        # Flèches
        ac = self.arrow_count
        arrow_col="#ffdd44" if ac>0 else "#883300"
        c.create_text(12,54,text=f"🏹 {'▶'*ac}{'○'*(MAX_ARROWS-ac)}",
                      anchor="w",fill=arrow_col,font=("Courier",9))
        # Ennemis restants
        alive=sum(1 for e in self.enemies if e["alive"])
        c.create_text(12,70,
                      text=f"Ennemis : {alive}/{len(self.enemies)}" +
                           ("  ◀ PORTAIL OUVERT !" if self.portal_active else ""),
                      anchor="w",
                      fill="#22ff88" if self.portal_active else "#cc8888",
                      font=("Courier",9,"bold" if self.portal_active else "normal"))

        # Score + niveau
        score_now = self.total_score + self._level_score()
        c.create_text(WIDTH-8,12,text=f"Score : {score_now}",
                      anchor="e",fill="#D4C090",font=("Courier",12,"bold"))
        c.create_text(WIDTH-8,30,text=f"Niveau {self.level_idx+1}/{self.total_lvls}",
                      anchor="e",fill="#aaaaaa",font=("Courier",10))

        # Barre armes bas
        bx=WIDTH//2-160; by=HEIGHT-50
        c.create_rectangle(bx,by,bx+320,HEIGHT-4,fill="#000000",stipple="gray50",outline="#4a3a00")
        c.create_rectangle(bx,by,bx+320,HEIGHT-4,outline="#6a5a20",fill="")

        for wkey,label,cx in [("arc","[1] Arc",bx+80),(self.melee_weapon,f"[2] {WEAPONS[self.melee_weapon]['name']}",bx+240)]:
            sel = self.current_weapon==wkey
            c.create_rectangle(cx-74,by+3,cx+74,HEIGHT-7,
                fill="#221100" if sel else "#110800",
                outline="#ffdd44" if sel else "#443300")
            c.create_text(cx,by+14,text=label,
                fill="#ffdd44" if sel else "#886622",font=("Courier",9,"bold"))
            if wkey=="arc":
                c.create_text(cx,by+28,text=f"{self.arrow_count}/{MAX_ARROWS} flèches",
                    fill="#ffdd44" if sel else "#664400",font=("Courier",8))
            else:
                wp2=WEAPONS[wkey]
                c.create_text(cx,by+28,text=f"{wp2['damage']}dmg · {speed_label(wp2['cooldown'])}",
                    fill="#88ccff" if sel else "#336688",font=("Courier",8))

        # Touche [0] + cooldown
        wpc=WEAPONS[self.current_weapon]; cd=self.attack_cd; mcd=wpc["cooldown"]
        ready=cd==0
        c.create_rectangle(WIDTH//2-14,by+3,WIDTH//2+14,HEIGHT-7,
            fill="#002200" if ready else "#220000",
            outline="#44ff44" if ready else "#883333")
        c.create_text(WIDTH//2,by+14,text="[0]",
            fill="#44ff44" if ready else "#883333",font=("Courier",9,"bold"))
        if cd>0:
            bh=int(28*(cd/mcd))
            c.create_rectangle(WIDTH//2-11,HEIGHT-9-bh,WIDTH//2+11,HEIGHT-9,
                                fill="#882222",outline="")

        c.create_text(WIDTH//2,HEIGHT-1,text="ESPACE : Pause / Menu armes",
                      fill="#444444",font=("Courier",7))

    # ───────────────────────────────────────────
    #  DESSIN ARBRE
    # ───────────────────────────────────────────
    def _draw_tree(self, c, x, th, scale=1.0):
        x=int(x)
        if x<-100 or x>WIDTH+100: return
        off=int(15*scale); tw=int(10*scale)
        c.create_rectangle(x+off,GROUND_Y-int(55*scale),x+off+tw,GROUND_Y,
                           fill=th["trunk"],outline="")
        lv=th["leaves"]
        for i in range(5):
            lw=int((16+i*10)*scale); lh=int(13*scale)
            lx=x+int(20*scale)-lw//2; ly=GROUND_Y-int((112-i*14)*scale)
            c.create_rectangle(lx,ly,lx+lw,ly+lh,fill=lv[i%len(lv)],outline="")
        c.create_rectangle(x+off+1,GROUND_Y-int(125*scale),
                           x+off+tw-1,GROUND_Y-int(110*scale),fill=lv[0],outline="")

    def _draw_bush(self, c, x, th):
        lv=th["leaves"]
        c.create_rectangle(x,GROUND_Y-14,x+32,GROUND_Y,fill=lv[1],outline="")
        c.create_rectangle(x+4,GROUND_Y-21,x+28,GROUND_Y-14,fill=lv[2],outline="")
        c.create_rectangle(x+9,GROUND_Y-26,x+23,GROUND_Y-21,fill=lv[3],outline="")

    def _draw_chest(self, c, x, y, opened):
        x=int(x); y=int(y)
        if opened:
            c.create_rectangle(x,y+10,x+20,y+20,fill="#5a3820",outline="#8B6914")
            c.create_rectangle(x,y+10,x+20,y+14,fill="#3a2010",outline="")
            c.create_text(x+10,y+2,text="○",fill="#554400",font=("Courier",10))
        else:
            c.create_rectangle(x,y,x+20,y+20,fill="#8B6914",outline="#aa8800",width=2)
            c.create_rectangle(x,y,x+20,y+8,fill="#6a4a00",outline="")
            c.create_rectangle(x+7,y+7,x+13,y+14,fill="#ffdd44",outline="#aa8800")
            c.create_rectangle(x+9,y+9,x+11,y+12,fill="#aa6600",outline="")

    def _draw_heart(self, c, x, y, color):
        pts=[(x+2,y),(x+4,y),(x+5,y+1),(x+6,y),(x+8,y),
             (x+9,y+1),(x+10,y+2),(x+10,y+4),(x+7,y+7),(x+5,y+10),
             (x+3,y+7),(x+0,y+4),(x+0,y+2),(x+1,y+1)]
        flat=[v for pt in pts for v in pt]
        c.create_polygon(flat,fill=color,outline="#880000")

    def _draw_arrow(self, c, x, y, angle_deg, shaft):
        rad=math.radians(angle_deg)
        cos=math.cos(rad); sin=math.sin(rad)
        x1=x-cos*10; y1=y-sin*10; x2=x+cos*10; y2=y+sin*10
        c.create_line(x1,y1,x2,y2,fill=shaft,width=3)
        c.create_line(x2,y2,x2+cos*5,y2+sin*5,fill="#C0C0C0",width=3)
        c.create_line(x1,y1,x1-cos*3+sin*3,y1-sin*3-cos*3,fill="#D4C090",width=2)
        c.create_line(x1,y1,x1-cos*3-sin*3,y1-sin*3+cos*3,fill="#D4C090",width=2)

    def _draw_hp_bar(self, c, x, y, hp, max_hp, w=40):
        c.create_rectangle(x,y,x+w,y+5,fill="#2a0a0a",outline="")
        ratio=max(0,hp/max_hp)
        col="#22aa44" if ratio>0.5 else "#aaaa22" if ratio>0.25 else "#aa2222"
        c.create_rectangle(x,y,x+int(w*ratio),y+5,fill=col,outline="")
        c.create_rectangle(x,y,x+w,y+5,outline="#111",fill="")

    def _draw_swing(self, c, x, y):
        wp=WEAPONS[self.current_weapon]; reach=wp["reach"]
        x1=x+PLAYER_W if self.facing==1 else x-reach; x2=x1+reach
        col="#ffdd88" if self.swing_anim>7 else "#aa6622"
        c.create_rectangle(x1,y+8,x2,y+28,fill="",outline=col,width=2)
        c.create_line(x1,y+18,x2,y+18,fill=col,width=2,dash=(4,3))

    # ───────────────────────────────────────────
    #  JOUEUR
    # ───────────────────────────────────────────
    def _draw_player(self, c, x, y):
        f=self.facing; wp=WEAPONS[self.current_weapon]
        # Corps
        c.create_rectangle(x+4,y+30,x+10,y+38,fill="#1A0E00",outline="")
        c.create_rectangle(x+16,y+30,x+22,y+38,fill="#1A0E00",outline="")
        c.create_rectangle(x+4,y+22,x+10,y+31,fill="#3E2A0E",outline="")
        c.create_rectangle(x+16,y+22,x+22,y+31,fill="#2E1A00",outline="")
        cx2=x+(1 if f==1 else 18)
        c.create_rectangle(cx2,y+10,cx2+5,y+28,fill="#6B0A0A",outline="")
        c.create_rectangle(x+4,y+10,x+22,y+24,fill="#2E5E8E",outline="")
        c.create_rectangle(x+4,y+21,x+22,y+26,fill="#1E4E7E",outline="")
        bx1=x+22 if f==1 else x-2
        c.create_rectangle(bx1,y+12,bx1+3,y+23,fill="#F5CBA7",outline="")
        bx2=x+1 if f==1 else x+21
        c.create_rectangle(bx2,y+12,bx2+3,y+23,fill="#F5CBA7",outline="")
        c.create_rectangle(x+6,y+2,x+20,y+12,fill="#F5CBA7",outline="")
        # Chapeau archer
        c.create_rectangle(x+4,y+0,x+22,y+4,fill="#3D5A00",outline="")
        c.create_rectangle(x+6,y-4,x+18,y+2,fill="#4a7a00",outline="")
        c.create_rectangle(x+16,y-8,x+19,y+0,fill="#3D5A00",outline="")
        c.create_line(x+16,y-8,x+20,y-16,fill="#ffffff",width=2)
        # Yeux
        ex=x+8 if f==1 else x+13
        c.create_rectangle(ex,y+5,ex+2,y+7,fill="#222",outline="")
        c.create_rectangle(ex+5,y+5,ex+7,y+7,fill="#222",outline="")
        # Arme
        if wp["type"]=="ranged":
            ax=x+24 if f==1 else x-4
            c.create_arc(ax-9,y+6,ax+9,y+28,start=(270 if f==1 else 90),extent=180,
                         style="arc",outline="#8B5E3C",width=3)
            c.create_line(ax,y+7,ax,y+27,fill="#D4C090",width=1)
        else:
            self._draw_melee(c,x,y,self.current_weapon,f)

    def _draw_melee(self, c, x, y, wname, f):
        wp=WEAPONS[wname]; col=wp["color"]
        wx=x+26 if f==1 else x-6
        sw=self.swing_anim>0; so=-10 if (sw and f==1) else (10 if sw else 0)

        if wname in ("epee_rouilee","epee","epee_acier","epee_feu"):
            ec = col
            c.create_line(wx,y+24+so,wx,y+4+so,fill=ec,width=4)
            c.create_line(wx-4,y+14+so,wx+4,y+14+so,fill="#aa8800",width=3)
            c.create_rectangle(wx-2,y+22,wx+2,y+26,fill="#aa8800",outline="")
            if wname=="epee_feu" and self.frame%4<2:
                c.create_oval(wx-3,y+3+so,wx+3,y+9+so,fill="#ff6600",outline="#ffdd00")
        elif wname=="dague":
            c.create_line(wx,y+22+so,wx,y+10+so,fill=col,width=3)
            c.create_line(wx-3,y+15+so,wx+3,y+15+so,fill="#aa8800",width=2)
            c.create_polygon(wx-1,y+8+so,wx,y+4+so,wx+1,y+8+so,fill=col,outline="")
        elif wname=="hache":
            c.create_line(wx,y+26,wx,y+8,fill="#8B6914",width=3)
            if f==1:
                c.create_polygon(wx,y+8+so,wx+14,y+4+so,wx+14,y+18+so,fill=col,outline="#888")
            else:
                c.create_polygon(wx,y+8+so,wx-14,y+4+so,wx-14,y+18+so,fill=col,outline="#888")
        elif wname=="marteau":
            c.create_line(wx,y+28,wx,y+10,fill="#8B6914",width=3)
            hw=14; hx2=wx-hw//2
            c.create_rectangle(hx2,y+6+so,hx2+hw,y+16+so,fill=col,outline="#555")
        elif wname=="lance":
            tip=wx+(18 if f==1 else -18)
            c.create_line(wx,y+20,tip,y+10,fill="#8B6914",width=3)
            if f==1:
                c.create_polygon(tip,y+10,tip+12,y+6,tip+8,y+14,fill=col,outline="")
            else:
                c.create_polygon(tip,y+10,tip-12,y+6,tip-8,y+14,fill=col,outline="")

    # ───────────────────────────────────────────
    #  ENNEMIS
    # ───────────────────────────────────────────
    def _draw_enemy(self, c, e, sx):
        et=e["type"]; y=int(e["y"]); fl=e["hit_flash"]>0; d=e["dir"]; sw=e["swing"]>0
        def fc(n,f2="#FF4444"): return f2 if fl else n

        if et=="goblin":
            sk=fc("#7acc44","#ffaa88")
            c.create_rectangle(sx+4,y+22,sx+8,y+30,fill="#1a3a00",outline="")
            c.create_rectangle(sx+14,y+22,sx+18,y+30,fill="#1a3a00",outline="")
            c.create_rectangle(sx+3,y+10,sx+19,y+22,fill=fc("#2a6a10"),outline="")
            c.create_rectangle(sx+1,y+13,sx+4,y+21,fill=fc("#2a6a10"),outline="")
            c.create_rectangle(sx+18,y+13,sx+21,y+21,fill=fc("#2a6a10"),outline="")
            c.create_rectangle(sx+6,y+2,sx+16,y+11,fill=sk,outline="")
            c.create_rectangle(sx+5,y-2,sx+17,y+3,fill=fc("#1a4a00"),outline="")
            c.create_rectangle(sx+5,y-5,sx+8,y+0,fill=fc("#1a4a00"),outline="")
            c.create_rectangle(sx+14,y-5,sx+17,y+0,fill=fc("#1a4a00"),outline="")
            c.create_rectangle(sx+7,y+4,sx+10,y+7,fill=fc("#ff4400","#ff8888"),outline="")
            c.create_rectangle(sx+12,y+4,sx+15,y+7,fill=fc("#ff4400","#ff8888"),outline="")
            so=-6 if sw else 0
            wx=sx+19 if d==1 else sx+1
            c.create_line(wx,y+10+so,wx+(4 if d==1 else -4),y+20+so,fill="#8B8B00",width=3)

        elif et=="soldat":
            sk=fc("#C8956C","#FF8888"); arm=fc("#8B0000","#FF2222"); hl=fc("#5a0a0a","#FF0000")
            c.create_rectangle(sx+4,y+26,sx+9,y+34,fill="#200808",outline="")
            c.create_rectangle(sx+15,y+26,sx+20,y+34,fill="#200808",outline="")
            c.create_rectangle(sx+4,y+18,sx+9,y+27,fill="#3E2020",outline="")
            c.create_rectangle(sx+15,y+18,sx+20,y+27,fill="#3E2020",outline="")
            c.create_rectangle(sx+3,y+8,sx+21,y+20,fill=arm,outline="")
            c.create_rectangle(sx+3,y+18,sx+21,y+23,fill=fc("#6B0000"),outline="")
            c.create_rectangle(sx+1,y+12,sx+4,y+20,fill=arm,outline="")
            c.create_rectangle(sx+19,y+12,sx+22,y+20,fill=arm,outline="")
            c.create_rectangle(sx+6,y+2,sx+18,y+12,fill=sk,outline="")
            c.create_rectangle(sx+4,y+0,sx+20,y+5,fill=hl,outline="")
            c.create_rectangle(sx+4,y+4,sx+7,y+8,fill=hl,outline="")
            c.create_rectangle(sx+17,y+4,sx+20,y+8,fill=hl,outline="")
            c.create_rectangle(sx+6,y+6,sx+9,y+9,fill="#111",outline="")
            c.create_rectangle(sx+13,y+6,sx+16,y+9,fill="#111",outline="")
            so=-8 if sw else 0
            wx=sx+22 if d==1 else sx-2
            c.create_line(wx,y+8+so,wx,y+22,fill="#CCCCCC",width=3)
            c.create_line(wx-3,y+14+so//2,wx+3,y+14+so//2,fill="#aa8800",width=2)

        elif et=="archer_e":
            sk=fc("#D4A574","#FF9999"); tn=fc("#4a2244","#FF4444")
            c.create_rectangle(sx+4,y+28,sx+9,y+36,fill="#1A0E00",outline="")
            c.create_rectangle(sx+15,y+28,sx+20,y+36,fill="#1A0E00",outline="")
            c.create_rectangle(sx+4,y+22,sx+9,y+29,fill=fc("#2e1020"),outline="")
            c.create_rectangle(sx+15,y+22,sx+20,y+29,fill=fc("#2e1020"),outline="")
            c.create_rectangle(sx+3,y+10,sx+21,y+23,fill=tn,outline="")
            c.create_rectangle(sx+6,y+2,sx+18,y+12,fill=sk,outline="")
            c.create_rectangle(sx+4,y+0,sx+20,y+4,fill=fc("#2a0a00"),outline="")
            c.create_rectangle(sx+6,y-4,sx+16,y+2,fill=fc("#3d1400"),outline="")
            c.create_rectangle(sx+7,y+5,sx+10,y+8,fill="#222",outline="")
            c.create_rectangle(sx+13,y+5,sx+16,y+8,fill="#222",outline="")
            ax=sx+23 if d==1 else sx-3
            c.create_arc(ax-9,y+6,ax+9,y+27,start=(270 if d==1 else 90),extent=180,
                         style="arc",outline=fc("#8B3A3C"),width=3)
            c.create_line(ax,y+7,ax,y+26,fill="#C4A070",width=1)

        elif et=="goule":
            sk=fc("#5a8a2a","#88FF88")
            c.create_rectangle(sx+3,y+22,sx+8,y+32,fill="#1a1a00",outline="")
            c.create_rectangle(sx+16,y+22,sx+21,y+32,fill="#1a1a00",outline="")
            c.create_rectangle(sx+3,y+10,sx+21,y+23,fill=sk,outline="")
            c.create_rectangle(sx+0,y+12,sx+4,y+22,fill=sk,outline="")
            c.create_rectangle(sx+19,y+12,sx+23,y+22,fill=sk,outline="")
            c.create_rectangle(sx+6,y+1,sx+18,y+11,fill=fc("#3a6a0a"),outline="")
            c.create_rectangle(sx+5,y+0,sx+9,y+5,fill=fc("#2a4a00"),outline="")
            c.create_rectangle(sx+15,y+0,sx+19,y+5,fill=fc("#2a4a00"),outline="")
            c.create_rectangle(sx+7,y+3,sx+10,y+6,fill=fc("#ff4400","#FF0000"),outline="")
            c.create_rectangle(sx+13,y+3,sx+16,y+6,fill=fc("#ff4400","#FF0000"),outline="")
            for gox in [-2,0,2]:
                gx2=sx+(20+gox if d==1 else gox)
                c.create_line(gx2,y+16,gx2+(4 if d==1 else -4),y+21,fill=fc("#2a4a00"),width=2)

        elif et=="sorcier":
            sk=fc("#8888cc","#AAAAFF"); rb=fc("#1a0044","#FF4444")
            c.create_rectangle(sx+3,y+28,sx+21,y+40,fill=rb,outline="")
            c.create_rectangle(sx+3,y+10,sx+21,y+30,fill=rb,outline="")
            c.create_rectangle(sx+0,y+14,sx+4,y+26,fill=rb,outline="")
            c.create_rectangle(sx+19,y+14,sx+23,y+26,fill=rb,outline="")
            c.create_rectangle(sx+6,y+2,sx+18,y+12,fill=sk,outline="")
            c.create_rectangle(sx+5,y+0,sx+19,y+4,fill=fc("#220044"),outline="")
            c.create_polygon(sx+12,y-10,sx+5,y+2,sx+19,y+2,fill=fc("#220044"),outline="")
            c.create_rectangle(sx+7,y+4,sx+10,y+7,fill=fc("#aa88ff","#FFFFFF"),outline="")
            c.create_rectangle(sx+12,y+4,sx+15,y+7,fill=fc("#aa88ff","#FFFFFF"),outline="")
            bsx=sx+22 if d==1 else sx-2
            c.create_line(bsx,y+10,bsx,y+38,fill="#8B6914",width=3)
            c.create_oval(bsx-6,y+4,bsx+6,y+16,fill=fc("#cc44ff","#ff44ff"),outline="#fff")

        elif et=="chevalier":
            mt=fc("#808080","#FFFFFF"); dk=fc("#404040","#FF2222")
            c.create_rectangle(sx+3,y+28,sx+9,y+38,fill="#111",outline="")
            c.create_rectangle(sx+15,y+28,sx+21,y+38,fill="#111",outline="")
            c.create_rectangle(sx+3,y+18,sx+9,y+30,fill=dk,outline="")
            c.create_rectangle(sx+15,y+18,sx+21,y+30,fill=dk,outline="")
            c.create_rectangle(sx+2,y+8,sx+22,y+20,fill=mt,outline="")
            c.create_rectangle(sx+2,y+18,sx+22,y+25,fill=dk,outline="")
            c.create_rectangle(sx+0,y+12,sx+4,y+22,fill=mt,outline="")
            c.create_rectangle(sx+19,y+12,sx+23,y+22,fill=mt,outline="")
            c.create_rectangle(sx+5,y+0,sx+19,y+10,fill=mt,outline="")
            c.create_rectangle(sx+5,y+0,sx+19,y+3,fill=dk,outline="")
            c.create_rectangle(sx+6,y+4,sx+16,y+8,fill="#222",outline="")
            c.create_rectangle(sx+7,y+5,sx+10,y+8,fill=fc("#ffaa00","#FFFFFF"),outline="")
            c.create_rectangle(sx+13,y+5,sx+16,y+8,fill=fc("#ffaa00","#FFFFFF"),outline="")
            so=-10 if sw else 0
            wx=sx+24 if d==1 else sx-2
            c.create_rectangle(wx,y+2+so,wx+(3 if d==1 else -3),y+32,fill="#cccccc",outline="")
            c.create_rectangle(wx-2,y+16+so//2,wx+5,y+19+so//2,fill="#aa8800",outline="")

        elif et=="troll":
            sk=fc("#4a6a20","#88FF44")
            c.create_rectangle(sx+2,y+32,sx+10,y+46,fill="#1a2a00",outline="")
            c.create_rectangle(sx+18,y+32,sx+26,y+46,fill="#1a2a00",outline="")
            c.create_rectangle(sx+2,y+14,sx+26,y+34,fill=sk,outline="")
            c.create_rectangle(sx+0,y+16,sx+4,y+30,fill=sk,outline="")
            c.create_rectangle(sx+24,y+16,sx+28,y+30,fill=sk,outline="")
            c.create_rectangle(sx+5,y+2,sx+23,y+15,fill=fc("#3a5a10"),outline="")
            c.create_rectangle(sx+3,y+0,sx+8,y+6,fill=fc("#2a4a00"),outline="")
            c.create_rectangle(sx+20,y+0,sx+25,y+6,fill=fc("#2a4a00"),outline="")
            c.create_rectangle(sx+7,y+5,sx+11,y+9,fill=fc("#ff2200","#FF8888"),outline="")
            c.create_rectangle(sx+17,y+5,sx+21,y+9,fill=fc("#ff2200","#FF8888"),outline="")
            so=-12 if sw else 0
            wx=sx+28 if d==1 else sx-6
            c.create_rectangle(wx,y+10+so,wx+(5 if d==1 else -5),y+32,fill="#888",outline="#555")
            c.create_rectangle(wx-3,y+18+so//2,wx+8,y+22+so//2,fill="#666",outline="")

        elif et=="liche":
            rb=fc("#0a0022","#4400AA"); sk=fc("#7788aa","#aabbff")
            c.create_rectangle(sx+3,y+28,sx+21,y+42,fill=rb,outline="")
            c.create_rectangle(sx+3,y+10,sx+21,y+30,fill=rb,outline="")
            c.create_rectangle(sx+0,y+14,sx+4,y+26,fill=rb,outline="")
            c.create_rectangle(sx+19,y+14,sx+23,y+26,fill=rb,outline="")
            c.create_rectangle(sx+6,y+2,sx+18,y+12,fill=sk,outline="")
            cr=fc("#1a0055","#6600ff")
            c.create_rectangle(sx+4,y-2,sx+20,y+4,fill=cr,outline="")
            c.create_polygon(sx+7,y-8,sx+5,y-2,sx+9,y-2,fill=cr,outline="")
            c.create_polygon(sx+12,y-10,sx+10,y-2,sx+14,y-2,fill=cr,outline="")
            c.create_polygon(sx+17,y-8,sx+15,y-2,sx+19,y-2,fill=cr,outline="")
            c.create_oval(sx+7,y+4,sx+11,y+8,fill=fc("#8800ff","#FFFFFF"),outline="")
            c.create_oval(sx+13,y+4,sx+17,y+8,fill=fc("#8800ff","#FFFFFF"),outline="")
            bsx=sx+23 if d==1 else sx-3
            c.create_line(bsx,y+8,bsx,y+36,fill="#4400aa",width=3)
            c.create_oval(bsx-7,y+2,bsx+7,y+16,fill=fc("#4400ff","#8800ff"),outline="#ccccff")

        elif et=="assassin":
            sk=fc("#C8956C","#FFCCAA"); ms=fc("#1a0a2a","#440044")
            c.create_rectangle(sx+4,y+28,sx+9,y+36,fill="#0a0010",outline="")
            c.create_rectangle(sx+15,y+28,sx+20,y+36,fill="#0a0010",outline="")
            c.create_rectangle(sx+4,y+22,sx+9,y+29,fill=fc("#1a0a2a"),outline="")
            c.create_rectangle(sx+15,y+22,sx+20,y+29,fill=fc("#1a0a2a"),outline="")
            c.create_rectangle(sx+3,y+10,sx+21,y+23,fill=fc("#2a0a3a"),outline="")
            c.create_rectangle(sx+6,y+2,sx+18,y+12,fill=sk,outline="")
            c.create_rectangle(sx+5,y+5,sx+19,y+11,fill=ms,outline="")
            c.create_rectangle(sx+4,y+0,sx+20,y+5,fill=fc("#1a0a2a"),outline="")
            c.create_rectangle(sx+7,y+6,sx+10,y+9,fill=fc("#cc00cc","#FF44FF"),outline="")
            c.create_rectangle(sx+13,y+6,sx+16,y+9,fill=fc("#cc00cc","#FF44FF"),outline="")
            so1=-10 if sw else 0; so2=6 if sw else 0
            d1x=sx+22 if d==1 else sx-2; d2x=sx+20 if d==1 else sx
            c.create_line(d1x,y+12+so1,d1x,y+24+so1,fill="#AAAAFF",width=3)
            c.create_line(d2x,y+16+so2,d2x,y+26+so2,fill="#8888DD",width=2)

        elif et=="dragon":
            sk=fc("#8B0000","#FF4444"); dk=fc("#5a0000","#CC0000"); bel=fc("#aa4400","#FF8844")
            c.create_oval(sx+5,y+10,sx+55,y+50,fill=sk,outline=dk,width=2)
            c.create_oval(sx+10,y+22,sx+48,y+46,fill=bel,outline="")
            hx=sx+(30 if d==1 else -4)
            c.create_oval(hx,y+0,hx+28,y+28,fill=sk,outline=dk)
            hcx=hx+14
            c.create_oval(hcx-4,y+0,hcx+4,y+10,fill=dk,outline="")
            c.create_oval(hcx+6,y-2,hcx+14,y+8,fill=dk,outline="")
            ex2=hcx+6 if d==1 else hcx-4
            c.create_oval(ex2,y+8,ex2+8,y+16,fill=fc("#ff4400","#ffff00"),outline="")
            c.create_oval(ex2+2,y+10,ex2+6,y+14,fill="#000",outline="")
            if d==1:
                c.create_polygon(sx+20,y+14,sx-20,y-20,sx+5,y+30,
                                 fill=fc("#6B0000","#FF2222"),outline="")
            else:
                c.create_polygon(sx+40,y+14,sx+80,y-20,sx+55,y+30,
                                 fill=fc("#6B0000","#FF2222"),outline="")
            c.create_line(sx+5,y+40,sx-20,y+55,fill=sk,width=6)
            c.create_rectangle(sx+12,y+46,sx+22,y+56,fill=dk,outline="")
            c.create_rectangle(sx+35,y+46,sx+45,y+56,fill=dk,outline="")
            if e.get("phase",1)==2 and self.frame%4<2:
                for fx,fy in [(hx+24,y+14),(hx+28,y+20),(hx+22,y+10)]:
                    c.create_oval(fx-5,fy-5,fx+5,fy+5,fill="#ff8800",outline="#ffdd00")

    # ───────────────────────────────────────────
    #  OVERLAY
    # ───────────────────────────────────────────
    def _overlay(self, c, title, tcol, sub, hint):
        c.create_rectangle(WIDTH//2-300,HEIGHT//2-100,WIDTH//2+300,HEIGHT//2+100,
                           fill="#000000",stipple="gray75",outline="")
        c.create_rectangle(WIDTH//2-300,HEIGHT//2-100,WIDTH//2+300,HEIGHT//2+100,
                           outline="#6a5a20",fill="")
        c.create_text(WIDTH//2,HEIGHT//2-50,text=title,fill=tcol,font=("Courier",26,"bold"))
        c.create_text(WIDTH//2,HEIGHT//2+2, text=sub, fill="#D4C090",font=("Courier",14))
        c.create_text(WIDTH//2,HEIGHT//2+44,text=hint,fill="#aaaaaa",font=("Courier",11))

    # ───────────────────────────────────────────
    #  COULEURS
    # ───────────────────────────────────────────
    def _lerp(self, c1, c2, t):
        r1,g1,b1=self._hex_rgb(c1); r2,g2,b2=self._hex_rgb(c2)
        return f"#{int(r1+(r2-r1)*t):02x}{int(g1+(g2-g1)*t):02x}{int(b1+(b2-b1)*t):02x}"

    def _hex_rgb(self, h):
        h=h.lstrip("#")
        return int(h[0:2],16),int(h[2:4],16),int(h[4:6],16)

    # ───────────────────────────────────────────
    #  BOUCLE
    # ───────────────────────────────────────────
    def loop(self):
        if self.state=="start": self.frame+=1
        self.update()
        self.draw()
        self.root.after(16, self.loop)


# ═══════════════════════════════════════════════════════════════
#  LANCEMENT
# ═══════════════════════════════════════════════════════════════
if __name__=="__main__":
    root=tk.Tk()
    Game(root)
    root.mainloop()
