// ============================================================
// RENDERER.JS — Изометрический рендерер с частицами
// ============================================================

const Renderer = {
    canvas: null,
    ctx: null,
    TW: 64,   // ширина тайла
    TH: 32,   // высота тайла
    TD: 18,   // глубина тайла (боковые грани)
    OY: 85,   // смещение по Y от верха

    particles: [],
    floatingTexts: [],
    camera: { x: 0, y: 0 },
    lightCanvas: null,
    lightCtx: null,
    shake: { x: 0, y: 0, power: 0 },
    patterns: {},
    _flash: null,
    _currentMapId: 'village',

    // ──────────────────────────────────
    // Типы тайлов
    // ──────────────────────────────────
    TILES: {
        0:  { name: 'Трава',     top: '#3d7a3c', l: '#2d5a2c', r: '#1d4020', pat: 'grass' },
        1:  { name: 'Вода',      top: '#2a5a8c', l: '#1a4a7c', r: '#0d3560', anim: true },
        2:  { name: 'Камень',    top: '#5a5a5a', l: '#484848', r: '#383838', pat: 'stone' },
        3:  { name: 'Песок',     top: '#c2a55e', l: '#b09550', r: '#9e8540', pat: 'sand' },
        4:  { name: 'Стена',     top: '#4a3828', l: '#3a2818', r: '#2a1808', pat: 'brick', solid: true },
        5:  { name: 'Дерево',    top: '#7a5010', l: '#6a4000', r: '#5a3000', pat: 'wood' },
        6:  { name: 'Лава',      top: '#cc4400', l: '#bb3300', r: '#aa2200', anim: true },
        7:  { name: 'Снег',      top: '#dde0ee', l: '#cdd0de', r: '#bdc0ce', pat: 'snow' },
        8:  { name: 'Земля',     top: '#7a4a20', l: '#6a3a12', r: '#5a2a08', pat: 'dirt' },
        9:  { name: 'Булыжник',  top: '#606060', l: '#505050', r: '#404040', pat: 'cobble' },
        10: { name: 'Болото',    top: '#3e5a30', l: '#2e4a20', r: '#1e3a10' },
        11: { name: 'Лёд',       top: '#90b8d8', l: '#80a8c8', r: '#7098b8' },
        12: { name: 'Бездна',    top: '#060008', l: '#040006', r: '#020004', pat: 'void' },
    },

    // ──────────────────────────────────
    // Инициализация
    // ──────────────────────────────────
    init(canvasId) {
        this.canvas = document.getElementById(canvasId);
        this.ctx = this.canvas.getContext('2d');
        this.ctx.imageSmoothingEnabled = false;
        this.buildPatterns();
        this.initLightCanvas();
    },

    // ──────────────────────────────────
    // Координатные преобразования
    // ──────────────────────────────────
    toIso(gx, gy) {
        return {
            x: (gx - gy) * (this.TW / 2) + this.canvas.width / 2 + this.shake.x + this.camera.x,
            y: (gx + gy) * (this.TH / 2) + this.OY + this.shake.y + this.camera.y
        };
    },
    fromIso(sx, sy) {
        const ax = sx - this.canvas.width / 2 - this.shake.x - this.camera.x;
        const ay = sy - this.OY - this.shake.y - this.camera.y;
        const hw = this.TW / 2, hh = this.TH / 2;
        return {
            x: Math.floor((ax / hw + ay / hh) / 2),
            y: Math.floor((ay / hh - ax / hw) / 2)
        };
    },

    // ──────────────────────────────────
    // Процедурные текстуры
    // ──────────────────────────────────
    initLightCanvas() {
        this.lightCanvas = document.createElement('canvas');
        this.lightCanvas.width  = this.canvas.width;
        this.lightCanvas.height = this.canvas.height;
        this.lightCtx = this.lightCanvas.getContext('2d');
    },

    buildPatterns() {
        this.patterns.grass = this._makeGrass();
        this.patterns.stone  = this._makeStone();
        this.patterns.sand   = this._makeSand();
        this.patterns.brick  = this._makeBrick();
        this.patterns.wood   = this._makeWood();
        this.patterns.snow   = this._makeSnow();
        this.patterns.dirt   = this._makeDirt();
        this.patterns.cobble = this._makeCobble();
        this.patterns.void   = this._makeVoid();
    },
    _pat(w, h, fn) {
        const c = document.createElement('canvas'); c.width = w; c.height = h;
        const x = c.getContext('2d'); fn(x, w, h);
        return this.ctx.createPattern(c, 'repeat');
    },
    _makeGrass() {
        return this._pat(32, 32, (p) => {
            p.fillStyle = '#3d7a3c'; p.fillRect(0,0,32,32);
            p.strokeStyle = '#4a9048'; p.lineWidth = 1;
            for (let i=0;i<18;i++) {
                const x=Math.random()*32, y=Math.random()*32, h=3+Math.random()*5;
                p.beginPath(); p.moveTo(x,y); p.lineTo(x+(Math.random()*4-2),y-h); p.stroke();
            }
            p.fillStyle = '#2d5a2c';
            for (let i=0;i<4;i++) { p.beginPath(); p.arc(Math.random()*32,Math.random()*32,1+Math.random()*2,0,Math.PI*2); p.fill(); }
        });
    },
    _makeStone() {
        return this._pat(32, 32, (p) => {
            p.fillStyle = '#5a5a5a'; p.fillRect(0,0,32,32);
            p.strokeStyle = '#484848'; p.lineWidth = 1;
            p.strokeRect(0,0,16,16); p.strokeRect(16,0,16,16);
            p.strokeRect(0,16,16,16); p.strokeRect(16,16,16,16);
            p.fillStyle = '#4a4a4a';
            p.fillRect(4,4,3,2); p.fillRect(20,9,2,3); p.fillRect(7,22,4,2);
        });
    },
    _makeSand() {
        return this._pat(32, 32, (p) => {
            p.fillStyle = '#c2a55e'; p.fillRect(0,0,32,32);
            p.fillStyle = '#d4b870';
            for (let i=0;i<30;i++) p.fillRect(Math.random()*32,Math.random()*32,1,1);
            p.fillStyle = '#b09550';
            for (let i=0;i<20;i++) p.fillRect(Math.random()*32,Math.random()*32,1,1);
        });
    },
    _makeBrick() {
        return this._pat(32, 32, (p) => {
            p.fillStyle = '#4a3828'; p.fillRect(0,0,32,32);
            p.strokeStyle = '#2a1808'; p.lineWidth = 2;
            p.beginPath();
            p.moveTo(0,8); p.lineTo(32,8); p.moveTo(0,24); p.lineTo(32,24);
            p.moveTo(16,0); p.lineTo(16,8); p.moveTo(8,8); p.lineTo(8,24);
            p.moveTo(24,8); p.lineTo(24,24); p.moveTo(16,24); p.lineTo(16,32);
            p.stroke();
        });
    },
    _makeWood() {
        return this._pat(32, 32, (p) => {
            p.fillStyle = '#7a5010'; p.fillRect(0,0,32,32);
            p.strokeStyle = '#6a4000'; p.lineWidth = 1;
            for (let i=0;i<8;i++) { p.beginPath(); p.moveTo(i*4,0); p.lineTo(i*4,32); p.stroke(); }
        });
    },
    _makeSnow() {
        return this._pat(32, 32, (p) => {
            p.fillStyle = '#dde0ee'; p.fillRect(0,0,32,32);
            p.fillStyle = '#c8cce0';
            for (let i=0;i<12;i++) { p.beginPath(); p.arc(Math.random()*32,Math.random()*32,1+Math.random()*1.5,0,Math.PI*2); p.fill(); }
        });
    },
    _makeDirt() {
        return this._pat(32, 32, (p) => {
            p.fillStyle = '#7a4a20'; p.fillRect(0,0,32,32);
            p.fillStyle = '#6a3a12';
            for (let i=0;i<12;i++) { p.beginPath(); p.arc(Math.random()*32,Math.random()*32,1+Math.random()*2,0,Math.PI*2); p.fill(); }
        });
    },
    _makeCobble() {
        return this._pat(32, 32, (p) => {
            p.fillStyle = '#606060'; p.fillRect(0,0,32,32);
            const stones = [[8,8,7],[24,8,6],[8,24,6],[24,24,7],[16,16,5]];
            p.fillStyle = '#505050';
            stones.forEach(([x,y,r]) => { p.beginPath(); p.arc(x,y,r,0,Math.PI*2); p.fill(); });
            p.strokeStyle = '#383838'; p.lineWidth = 1;
            stones.forEach(([x,y,r]) => { p.beginPath(); p.arc(x,y,r,0,Math.PI*2); p.stroke(); });
        });
    },
    _makeVoid() {
        return this._pat(16, 16, (p) => {
            p.fillStyle = '#060008'; p.fillRect(0,0,16,16);
            p.fillStyle = '#1a0028';
            [[3,3],[11,7],[6,12],[13,2],[1,10]].forEach(([px,py]) => {
                p.beginPath(); p.arc(px,py,1.2,0,Math.PI*2); p.fill();
            });
            p.fillStyle = '#0d0015';
            [[8,4],[4,11],[12,9]].forEach(([px,py]) => {
                p.beginPath(); p.arc(px,py,0.8,0,Math.PI*2); p.fill();
            });
        });
    },

    // ──────────────────────────────────
    // Рисование тайла
    // ──────────────────────────────────
    drawTile(gx, gy, type, hover, time) {
        const p = this.toIso(gx, gy);
        const t = this.TILES[type] || this.TILES[0];
        const hw = this.TW / 2, hh = this.TH / 2;

        let topColor = t.top;
        if (t.anim) {
            const wave = Math.sin(time / 500 + gx + gy) * 12;
            topColor = this._adj(t.top, wave);
        }

        // Верхняя грань
        this.ctx.beginPath();
        this.ctx.moveTo(p.x,      p.y - hh);
        this.ctx.lineTo(p.x + hw, p.y);
        this.ctx.lineTo(p.x,      p.y + hh);
        this.ctx.lineTo(p.x - hw, p.y);
        this.ctx.closePath();

        if (t.pat && this.patterns[t.pat]) {
            this.ctx.save();
            this.ctx.clip();
            this.ctx.save();
            this.ctx.translate(p.x, p.y);
            this.ctx.scale(1, 0.5);
            this.ctx.rotate(Math.PI / 4);
            this.ctx.fillStyle = this.patterns[t.pat];
            this.ctx.fillRect(-60, -60, 120, 120);
            this.ctx.restore();
            this.ctx.restore();
        } else {
            this.ctx.fillStyle = topColor;
            this.ctx.fill();
        }

        this.ctx.strokeStyle = hover ? 'rgba(255,255,255,0.7)' : 'rgba(0,0,0,0.35)';
        this.ctx.lineWidth = hover ? 2 : 0.8;
        this.ctx.beginPath();
        this.ctx.moveTo(p.x,      p.y - hh);
        this.ctx.lineTo(p.x + hw, p.y);
        this.ctx.lineTo(p.x,      p.y + hh);
        this.ctx.lineTo(p.x - hw, p.y);
        this.ctx.closePath();
        this.ctx.stroke();

        // Левая грань
        this.ctx.beginPath();
        this.ctx.moveTo(p.x - hw, p.y);
        this.ctx.lineTo(p.x,      p.y + hh);
        this.ctx.lineTo(p.x,      p.y + hh + this.TD);
        this.ctx.lineTo(p.x - hw, p.y + this.TD);
        this.ctx.closePath();
        this.ctx.fillStyle = t.l;
        this.ctx.fill();
        this.ctx.strokeStyle = 'rgba(0,0,0,0.4)';
        this.ctx.lineWidth = 0.8;
        this.ctx.stroke();

        // Правая грань
        this.ctx.beginPath();
        this.ctx.moveTo(p.x + hw, p.y);
        this.ctx.lineTo(p.x,      p.y + hh);
        this.ctx.lineTo(p.x,      p.y + hh + this.TD);
        this.ctx.lineTo(p.x + hw, p.y + this.TD);
        this.ctx.closePath();
        this.ctx.fillStyle = t.r;
        this.ctx.fill();
        this.ctx.stroke();

        // Украшения
        this._tileDeco(gx, gy, type, p, time);

        if (hover) {
            this.ctx.fillStyle = 'rgba(255,255,255,0.7)';
            this.ctx.font = '10px Arial';
            this.ctx.textAlign = 'center';
            this.ctx.fillText(t.name, p.x, p.y + 4);
        }
    },

    _tileDeco(gx, gy, type, p, time) {
        const seed = (gx * 7 + gy * 13) % 10;
        if (type === 0 && seed < 2) this._drawTree(p.x, p.y, 0.55 + seed * 0.12);
        if (type === 0 && seed >= 2 && seed < 4) this._drawFlower(p.x, p.y, seed);
        if (type === 1) { // вода — рябь
            const ctx = this.ctx;
            const phase = time/300 + gx*0.9 + gy*1.1;
            // первое кольцо ряби
            const ox1 = Math.sin(phase)*4;
            ctx.fillStyle = `rgba(255,255,255,${0.07 + 0.05*Math.sin(phase)})`;
            ctx.beginPath(); ctx.ellipse(p.x + ox1, p.y, 8, 3, 0, 0, Math.PI*2); ctx.fill();
            // второе кольцо (сдвинуто по фазе и позиции)
            const phase2 = time/240 + gx*1.3 + gy*0.7 + 2.1;
            const ox2 = Math.cos(phase2)*3;
            ctx.fillStyle = `rgba(180,220,255,${0.05 + 0.04*Math.abs(Math.sin(phase2))})`;
            ctx.beginPath(); ctx.ellipse(p.x + ox2, p.y - 2, 5, 2, 0, 0, Math.PI*2); ctx.fill();
            // блик-искра
            if (seed < 3) {
                const sparkA = 0.3 + 0.3*Math.abs(Math.sin(time/180 + gx*2.5));
                ctx.fillStyle = `rgba(255,255,255,${sparkA})`;
                ctx.beginPath(); ctx.arc(p.x + (seed-1)*5, p.y - 1, 1.2, 0, Math.PI*2); ctx.fill();
            }
        }
        if (type === 6) { // лава — пузыри + свечение + дрожание
            const ctx = this.ctx;
            // тепловое свечение (halo)
            const glow = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, 14);
            glow.addColorStop(0, `rgba(255,80,0,${0.18 + 0.08*Math.abs(Math.sin(time/350+gx))})`);
            glow.addColorStop(1, 'rgba(255,80,0,0)');
            ctx.fillStyle = glow;
            ctx.beginPath(); ctx.ellipse(p.x, p.y, 14, 6, 0, 0, Math.PI*2); ctx.fill();
            // несколько пузырей по детерминированным смещениям
            for (let b = 0; b < 3; b++) {
                const bPhase = time/200 + gx*3.1 + gy*2.3 + b*2.09;
                const bx = p.x + (seed%3)*5 - 4 + b*4;
                const by = p.y - 4 + Math.sin(bPhase)*3;
                const br = 1.5 + Math.abs(Math.sin(bPhase*1.3))*1.5;
                const ba = 0.35 + 0.3*Math.abs(Math.sin(bPhase));
                if (Math.abs(Math.sin(bPhase)) > 0.4) { // пузырь виден часть цикла
                    ctx.fillStyle = `rgba(255,${120 + Math.floor(60*Math.abs(Math.sin(bPhase)))},0,${ba})`;
                    ctx.beginPath(); ctx.arc(bx, by, br, 0, Math.PI*2); ctx.fill();
                }
            }
        }
    },

    _drawTree(x, y, s = 1) {
        const th = 14 * s, cr = 18 * s;
        this.ctx.fillStyle = '#4a2808';
        this.ctx.fillRect(x - 3*s, y - th, 6*s, th + 4);
        this.ctx.fillStyle = '#1a4818';
        this.ctx.beginPath();
        this.ctx.moveTo(x, y - th - cr);
        this.ctx.lineTo(x - cr*0.8, y - th*0.4);
        this.ctx.lineTo(x + cr*0.8, y - th*0.4);
        this.ctx.closePath();
        this.ctx.fill();
        this.ctx.fillStyle = '#2a6028';
        this.ctx.beginPath();
        this.ctx.moveTo(x, y - th - cr*1.2);
        this.ctx.lineTo(x - cr*0.6, y - th - cr*0.3);
        this.ctx.lineTo(x + cr*0.6, y - th - cr*0.3);
        this.ctx.closePath();
        this.ctx.fill();
    },

    _drawFlower(x, y, seed) {
        const cols = ['#ff5555','#ffff44','#ff55ff','#55ffff'];
        this.ctx.strokeStyle = '#2a4a2a'; this.ctx.lineWidth = 1;
        this.ctx.beginPath(); this.ctx.moveTo(x,y); this.ctx.lineTo(x,y-8); this.ctx.stroke();
        this.ctx.fillStyle = cols[seed % cols.length];
        for (let i=0;i<5;i++) {
            const a = i/5*Math.PI*2;
            this.ctx.beginPath(); this.ctx.arc(x+Math.cos(a)*3, y-8+Math.sin(a)*3, 2, 0, Math.PI*2); this.ctx.fill();
        }
        this.ctx.fillStyle = '#ffff00';
        this.ctx.beginPath(); this.ctx.arc(x,y-8,1.5,0,Math.PI*2); this.ctx.fill();
    },

    // ──────────────────────────────────
    // Рисование всей карты
    // ──────────────────────────────────
    drawMap(map, hoverTile, time) {
        const tiles = [];
        for (let y=0; y<map.length; y++)
            for (let x=0; x<map[y].length; x++)
                tiles.push({x, y, t: map[y][x]});
        tiles.sort((a,b) => (a.x+a.y)-(b.x+b.y));
        tiles.forEach(tile => {
            const hover = hoverTile && hoverTile.x===tile.x && hoverTile.y===tile.y;
            this.drawTile(tile.x, tile.y, tile.t, hover, time);
        });
    },

    // ──────────────────────────────────
    // Игрок (спрайтовая анимация)
    // ──────────────────────────────────
    drawPlayer(player, time) {
        // ИСПРАВЛЕНО: mp_move (прогресс шага 0→1), а НЕ mp (мана)
        const wx = player.isMoving
            ? player.x + (player.tx - player.x) * player.mp_move
            : player.x;
        const wy = player.isMoving
            ? player.y + (player.ty - player.y) * player.mp_move
            : player.y;
        const p = this.toIso(wx, wy);

        // Анимация ходьбы
        const wc       = player.isMoving ? time / 130 : 0;
        const legSwing = Math.sin(wc) * 5;           // левая нога вперёд → правая назад
        const armSwing = -Math.sin(wc) * 6;          // руки противофазны ногам
        const bodyRise = player.isMoving ? Math.abs(Math.sin(wc)) * 2 : 0;   // подъём тела при шаге
        const breathe  = player.isMoving ? 0 : Math.sin(time / 2200) * 1.2; // дыхание в покое

        const CLASS_COLORS = {
            warrior:'#e74c3c', mage:'#3498db', archer:'#27ae60',
            paladin:'#f1c40f', necromancer:'#8e44ad', berserker:'#e67e22', druid:'#2ecc71'
        };
        const bodyCol = CLASS_COLORS[player.class] || '#e74c3c';
        const darkCol = this._adj(bodyCol, -35);
        const bx = p.x;
        const by = p.y + bodyRise;  // Y тела с учётом шага
        const hb = breathe;        // смещение головы (дыхание)

        // ── ТЕНЬ ──
        this.ctx.beginPath();
        this.ctx.ellipse(bx, p.y + 8, 18, 9, 0, 0, Math.PI * 2);
        this.ctx.fillStyle = 'rgba(0,0,0,0.28)';
        this.ctx.fill();

        // ── ЛЕВАЯ НОГА ──
        this.ctx.fillStyle = darkCol;
        this.ctx.fillRect(bx - 7, by - 4 + legSwing, 5, 13);
        this.ctx.fillStyle = '#2a1808';
        this.ctx.fillRect(bx - 8, by + 7 + legSwing, 7, 4);

        // ── ПРАВАЯ НОГА ──
        this.ctx.fillStyle = darkCol;
        this.ctx.fillRect(bx + 2, by - 4 - legSwing, 5, 13);
        this.ctx.fillStyle = '#2a1808';
        this.ctx.fillRect(bx + 1, by + 7 - legSwing, 7, 4);

        // ── ТЕЛО ──
        this.ctx.fillStyle = bodyCol;
        this.ctx.fillRect(bx - 9, by - 24 + hb, 18, 20);
        this.ctx.fillStyle = this._adj(darkCol, -10);
        this.ctx.fillRect(bx - 9, by - 8 + hb, 18, 3);   // пояс
        this.ctx.strokeStyle = darkCol;
        this.ctx.lineWidth = 1.5;
        this.ctx.strokeRect(bx - 9, by - 24 + hb, 18, 20);

        // ── ЛЕВАЯ РУКА ──
        this.ctx.fillStyle = this._adj(bodyCol, -15);
        this.ctx.fillRect(bx - 14, by - 23 + hb - armSwing, 5, 12);
        this.ctx.fillStyle = '#ffcc99';
        this.ctx.fillRect(bx - 14, by - 13 + hb - armSwing, 5, 5);

        // ── ПРАВАЯ РУКА (оружие) ──
        this.ctx.fillStyle = this._adj(bodyCol, -15);
        this.ctx.fillRect(bx + 9, by - 23 + hb + armSwing, 5, 12);
        this.ctx.fillStyle = '#ffcc99';
        this.ctx.fillRect(bx + 9, by - 13 + hb + armSwing, 5, 5);

        // ── ОРУЖИЕ В РУКЕ (по классу) ──
        this._drawPlayerWeapon(bx, by + hb, player.class, armSwing, time);

        // ── ГОЛОВА ──
        const hy = by - 38 + hb;
        this.ctx.beginPath();
        this.ctx.arc(bx, hy, 10, 0, Math.PI * 2);
        this.ctx.fillStyle = '#ffcc99';
        this.ctx.fill();
        this.ctx.strokeStyle = '#cc9966';
        this.ctx.lineWidth = 1.5;
        this.ctx.stroke();

        // ── ГОЛОВНОЙ УБОР / ПРИЧЁСКА (зависит от класса) ──
        this._drawPlayerHead(bx, hy, player.class, bodyCol, player.hairColor || '#3a2510', time);

        // ── ГЛАЗА (смотрят в сторону последнего движения) ──
        const facing = player.facing || 'down';
        const eox = facing === 'right' ? 2 : facing === 'left' ? -2 : 0;
        this.ctx.fillStyle = '#1a1a2a';
        this.ctx.beginPath();
        this.ctx.arc(bx - 3.5 + eox, hy + 1, 1.8, 0, Math.PI * 2);
        this.ctx.arc(bx + 3.5 + eox, hy + 1, 1.8, 0, Math.PI * 2);
        this.ctx.fill();
        this.ctx.fillStyle = 'rgba(255,255,255,0.7)';
        this.ctx.beginPath();
        this.ctx.arc(bx - 2.5 + eox, hy, 0.7, 0, Math.PI * 2);
        this.ctx.arc(bx + 4.5 + eox, hy, 0.7, 0, Math.PI * 2);
        this.ctx.fill();

        // ── УРОВЕНЬ ──
        this.ctx.fillStyle = '#ffd700';
        this.ctx.font = 'bold 10px Arial';
        this.ctx.textAlign = 'center';
        this.ctx.fillText('Lv.' + player.level, bx, by - 53 + hb);

        // ── АУРА (маг / некромант) ──
        if (player.class === 'mage' || player.class === 'necromancer') {
            const auraCol = player.class === 'mage' ? 'rgba(52,152,219,0.35)' : 'rgba(142,68,173,0.35)';
            this.ctx.strokeStyle = auraCol;
            this.ctx.lineWidth = 2;
            this.ctx.beginPath();
            this.ctx.arc(bx, by - 30 + hb, 18 + Math.sin(time / 400) * 2, 0, Math.PI * 2);
            this.ctx.stroke();
        }

        // ── HP БАР ──
        const barW = 28;
        const hpPct = player.hp / player.maxHp;
        this.ctx.fillStyle = '#222';
        this.ctx.fillRect(bx - barW / 2, by - 60 + hb, barW, 4);
        this.ctx.fillStyle = hpPct > 0.5 ? '#27ae60' : hpPct > 0.25 ? '#e67e22' : '#e74c3c';
        this.ctx.fillRect(bx - barW / 2, by - 60 + hb, barW * hpPct, 4);
    },

    // Головные уборы / причёски по классу
    _drawPlayerHead(bx, hy, cls, bodyCol, hairColor, time) {
        const ctx = this.ctx;
        switch (cls) {
            case 'warrior':
                ctx.fillStyle = '#909090';
                ctx.beginPath(); ctx.arc(bx, hy - 2, 11, Math.PI, 0); ctx.fill();
                ctx.fillStyle = '#707070';
                ctx.fillRect(bx - 11, hy - 2, 22, 4);
                ctx.strokeStyle = '#505050'; ctx.lineWidth = 1;
                ctx.strokeRect(bx - 11, hy - 2, 22, 4);
                ctx.fillStyle = '#b8b8b8';
                ctx.fillRect(bx - 7, hy, 14, 2);   // забрало
                break;
            case 'mage':
                ctx.fillStyle = bodyCol;
                ctx.beginPath();
                ctx.moveTo(bx, hy - 27); ctx.lineTo(bx - 11, hy - 3); ctx.lineTo(bx + 11, hy - 3);
                ctx.closePath(); ctx.fill();
                ctx.strokeStyle = this._adj(bodyCol, -25); ctx.lineWidth = 1.2; ctx.stroke();
                ctx.fillStyle = this._adj(bodyCol, -15);
                ctx.fillRect(bx - 13, hy - 5, 26, 5);  // ободок
                ctx.fillStyle = `rgba(255,220,50,${0.7 + 0.3 * Math.sin(time / 300)})`;
                ctx.font = 'bold 9px Arial'; ctx.textAlign = 'center';
                ctx.fillText('✦', bx, hy - 12);
                break;
            case 'archer':
                ctx.fillStyle = bodyCol;
                ctx.beginPath(); ctx.arc(bx, hy - 1, 12, Math.PI * 1.08, Math.PI * 1.92); ctx.fill();
                ctx.fillStyle = this._adj(bodyCol, -15);
                ctx.fillRect(bx - 12, hy - 1, 24, 4);
                break;
            case 'paladin':
                ctx.fillStyle = '#c8a810';
                ctx.beginPath(); ctx.arc(bx, hy - 2, 11, Math.PI, 0); ctx.fill();
                ctx.fillStyle = '#a88808'; ctx.fillRect(bx - 11, hy - 2, 22, 4);
                ctx.fillStyle = '#ffffff';  // крест
                ctx.fillRect(bx - 1.5, hy - 14, 3, 14);
                ctx.fillRect(bx - 6, hy - 9, 12, 3);
                break;
            case 'necromancer':
                ctx.fillStyle = '#1a0a2a';
                ctx.beginPath();
                ctx.moveTo(bx, hy - 28); ctx.lineTo(bx - 12, hy - 2); ctx.lineTo(bx + 12, hy - 2);
                ctx.closePath(); ctx.fill();
                ctx.beginPath(); ctx.arc(bx, hy, 13, Math.PI * 1.03, Math.PI * 1.97); ctx.fill();
                ctx.fillStyle = `rgba(142,68,173,${0.22 + 0.18 * Math.sin(time / 400)})`;
                ctx.beginPath(); ctx.arc(bx, hy, 11, 0, Math.PI * 2); ctx.fill();
                break;
            case 'berserker':
                ctx.fillStyle = '#5a3a20';
                ctx.beginPath(); ctx.arc(bx, hy - 2, 11, Math.PI, 0); ctx.fill();
                ctx.fillStyle = '#4a2a10'; ctx.fillRect(bx - 11, hy - 2, 22, 4);
                ctx.fillStyle = '#c8b090';  // рога
                ctx.beginPath(); ctx.moveTo(bx - 8, hy - 9); ctx.lineTo(bx - 16, hy - 25); ctx.lineTo(bx - 4, hy - 9); ctx.closePath(); ctx.fill();
                ctx.beginPath(); ctx.moveTo(bx + 8, hy - 9); ctx.lineTo(bx + 16, hy - 25); ctx.lineTo(bx + 4, hy - 9); ctx.closePath(); ctx.fill();
                break;
            case 'druid':
                ctx.fillStyle = hairColor;
                ctx.beginPath(); ctx.arc(bx, hy - 3, 9, Math.PI, 0); ctx.fill();
                for (let i = 0; i < 7; i++) {
                    const a = (i / 7) * Math.PI + Math.PI;
                    ctx.fillStyle = ['#2ecc71','#27ae60','#1abc9c'][i % 3];
                    ctx.save();
                    ctx.translate(bx + Math.cos(a) * 10, hy - 3 + Math.sin(a) * 5);
                    ctx.rotate(a + Math.PI / 2);
                    ctx.beginPath(); ctx.ellipse(0, 0, 4, 2.5, 0, 0, Math.PI * 2); ctx.fill();
                    ctx.restore();
                }
                break;
            default:
                ctx.fillStyle = hairColor;
                ctx.beginPath(); ctx.arc(bx, hy - 4, 9, Math.PI, 0); ctx.fill();
        }
    },

    // Оружие в правой руке (по классу)
    _drawPlayerWeapon(bx, by, cls, armSwing, time) {
        const ctx = this.ctx;
        ctx.save();
        ctx.translate(bx + 14, by - 20 + armSwing);
        switch (cls) {
            case 'warrior':
            case 'paladin':
                ctx.rotate(-0.25);
                ctx.fillStyle = '#c8c8d8'; ctx.fillRect(-2, -22, 4, 24);  // клинок
                ctx.fillStyle = '#c8a810'; ctx.fillRect(-6, 0, 12, 3);    // гарда
                ctx.fillStyle = '#5a3010'; ctx.fillRect(-2, 3, 4, 8);     // рукоять
                ctx.fillStyle = 'rgba(255,255,255,0.45)'; ctx.fillRect(0, -20, 1.5, 17);  // блик
                break;
            case 'mage': {
                ctx.rotate(-0.1);
                ctx.fillStyle = '#7a5010'; ctx.fillRect(-2, -34, 4, 40);  // посох
                const hue = (time / 25) % 360;
                ctx.fillStyle = `hsl(${hue},85%,65%)`;
                ctx.beginPath(); ctx.arc(0, -35, 5, 0, Math.PI * 2); ctx.fill();
                ctx.strokeStyle = 'rgba(255,255,255,0.7)'; ctx.lineWidth = 1; ctx.stroke();
                ctx.fillStyle = `hsla(${hue},85%,75%,${0.15 + 0.1 * Math.sin(time / 200)})`;
                ctx.beginPath(); ctx.arc(0, -35, 12, 0, Math.PI * 2); ctx.fill();
                break;
            }
            case 'archer':
                ctx.rotate(0.1);
                ctx.strokeStyle = '#7a5010'; ctx.lineWidth = 3;
                ctx.beginPath(); ctx.arc(0, -10, 14, -0.9, 0.9); ctx.stroke();
                ctx.strokeStyle = '#ddd'; ctx.lineWidth = 1;
                ctx.beginPath();
                ctx.moveTo(Math.cos(-0.9) * 14, Math.sin(-0.9) * 14 - 10);
                ctx.lineTo(Math.cos(0.9) * 14, Math.sin(0.9) * 14 - 10);
                ctx.stroke();
                break;
            case 'berserker':
                ctx.rotate(0.3);
                ctx.fillStyle = '#5a3010'; ctx.fillRect(-2.5, -28, 5, 32);
                ctx.fillStyle = '#acacac';
                ctx.beginPath();
                ctx.moveTo(2, -24); ctx.lineTo(15, -17); ctx.lineTo(15, -7); ctx.lineTo(2, -4);
                ctx.closePath(); ctx.fill();
                ctx.strokeStyle = '#888'; ctx.lineWidth = 1; ctx.stroke();
                break;
            case 'necromancer': {
                ctx.rotate(-0.1);
                ctx.fillStyle = '#1a0a2a'; ctx.fillRect(-2, -34, 4, 40);
                ctx.fillStyle = '#d0d0c0';
                ctx.beginPath(); ctx.arc(0, -35, 5.5, 0, Math.PI * 2); ctx.fill();
                ctx.fillStyle = '#1a0a2a';
                ctx.fillRect(-2.5, -32, 2, 3); ctx.fillRect(0.5, -32, 2, 3);
                const glow = 0.3 + 0.2 * Math.sin(time / 300);
                ctx.fillStyle = `rgba(142,68,173,${glow})`;
                ctx.beginPath(); ctx.arc(0, -35, 9, 0, Math.PI * 2); ctx.fill();
                break;
            }
            case 'druid':
                ctx.rotate(-0.1);
                ctx.fillStyle = '#5a3a10'; ctx.fillRect(-2, -32, 4, 38);
                ctx.fillStyle = '#2ecc71';
                ctx.beginPath(); ctx.arc(0, -33, 4.5, 0, Math.PI * 2); ctx.fill();
                ctx.strokeStyle = '#27ae60'; ctx.lineWidth = 1; ctx.stroke();
                ctx.fillStyle = `rgba(46,204,113,${0.2 + 0.15 * Math.sin(time / 400)})`;
                ctx.beginPath(); ctx.arc(0, -33, 10, 0, Math.PI * 2); ctx.fill();
                break;
        }
        ctx.restore();
    },

    // ──────────────────────────────────
    // Враг
    // ──────────────────────────────────
    drawEnemy(enemy, time) {
        const p = this.toIso(enemy.x, enemy.y);
        const bob = Math.sin(time/200) * 2;
        const atk = enemy.isAtk ? Math.sin(time/60) * 6 : 0;

        const CFG = {
            goblin:    { body:'#3a6a2a', head:'#4a7a3a', eye:'#ff2200', h:40 },
            orc:       { body:'#4a5a2a', head:'#5a6a3a', eye:'#ff4400', h:44 },
            skeleton:  { body:'#c8c8b0', head:'#dcdcc8', eye:'#00ff44', h:42 },
            slime:     { body:'#00aa55', head:'#00cc66', eye:'#fff',    h:28 },
            bandit:    { body:'#6a5540', head:'#7a6550', eye:'#ff6600', h:42 },
            wolf:      { body:'#5a4840', head:'#6a5850', eye:'#ffcc00', h:36 },
            spider:    { body:'#1a1a2a', head:'#2a2a3a', eye:'#ff0000', h:34 },
            troll:     { body:'#4a5a3a', head:'#5a6a4a', eye:'#ff3300', h:50 },
            dragon:    { body:'#8b0000', head:'#a00000', eye:'#ffff00', h:55 },
            zombie:    { body:'#3a5a30', head:'#4a6a40', eye:'#88ff44', h:42 },
            bat:       { body:'#2a1a3a', head:'#3a2a4a', eye:'#ff44ff', h:30 },
            yeti:      { body:'#ccccdd', head:'#ddddee', eye:'#00ccff', h:52 },
            witch:     { body:'#2a1a4a', head:'#3a2a5a', eye:'#ff00ff', h:44 },
            golem:     { body:'#606050', head:'#707060', eye:'#ff6600', h:56 },
            ghost:      { body:'rgba(160,200,255,0.55)', head:'rgba(180,220,255,0.65)', eye:'#aaddff', h:44 },
            wyvern:     { body:'#2a5a30', head:'#3a7a40', eye:'#ffee00', h:50 },
            chaos_lord: { body:'#1a0020', head:'#2e0040', eye:'#cc00ff', h:62 },
        };
        const cfg = CFG[enemy.type] || CFG.goblin;
        const dy = p.y + atk;

        // Тень
        this.ctx.beginPath();
        this.ctx.ellipse(p.x, dy + 8, 16, 8, 0, 0, Math.PI*2);
        this.ctx.fillStyle = 'rgba(0,0,0,0.25)';
        this.ctx.fill();

        if (enemy.type === 'slime') {
            // Слизень — каплевидная форма
            this.ctx.beginPath();
            this.ctx.ellipse(p.x, dy - 10 + bob, 14, 10, 0, 0, Math.PI*2);
            this.ctx.fillStyle = cfg.body; this.ctx.fill();
            this.ctx.strokeStyle = '#00885a'; this.ctx.lineWidth = 1.5; this.ctx.stroke();
            this.ctx.fillStyle = '#fff'; // глаза
            this.ctx.beginPath(); this.ctx.arc(p.x-4, dy-12+bob, 3, 0, Math.PI*2); this.ctx.fill();
            this.ctx.beginPath(); this.ctx.arc(p.x+4, dy-12+bob, 3, 0, Math.PI*2); this.ctx.fill();
            this.ctx.fillStyle = '#000';
            this.ctx.beginPath(); this.ctx.arc(p.x-4, dy-12+bob, 1.5, 0, Math.PI*2); this.ctx.fill();
            this.ctx.beginPath(); this.ctx.arc(p.x+4, dy-12+bob, 1.5, 0, Math.PI*2); this.ctx.fill();
        } else if (enemy.type === 'bat') {
            // Летучая мышь
            this.ctx.fillStyle = cfg.body;
            this.ctx.beginPath();
            const wingFlap = Math.sin(time/80) * 8;
            this.ctx.ellipse(p.x, dy - 15 + bob, 7, 5, 0, 0, Math.PI*2); this.ctx.fill();
            this.ctx.beginPath();
            this.ctx.moveTo(p.x-6, dy-15+bob); this.ctx.lineTo(p.x-18, dy-20+wingFlap); this.ctx.lineTo(p.x-8, dy-13+bob); this.ctx.fill();
            this.ctx.beginPath();
            this.ctx.moveTo(p.x+6, dy-15+bob); this.ctx.lineTo(p.x+18, dy-20+wingFlap); this.ctx.lineTo(p.x+8, dy-13+bob); this.ctx.fill();
        } else if (enemy.type === 'ghost') {
            // Призрак — полупрозрачная парящая фигура
            const glow = 0.3 + 0.2 * Math.sin(time / 400);
            this.ctx.shadowColor = '#88ccff'; this.ctx.shadowBlur = 14;
            this.ctx.globalAlpha = 0.55 + 0.15 * Math.sin(time / 500);
            // Мантия / тело
            this.ctx.fillStyle = cfg.body;
            this.ctx.beginPath();
            this.ctx.arc(p.x, dy - 28 + bob, 10, Math.PI, 0); // верх
            this.ctx.lineTo(p.x + 14, dy - 8 + bob);
            // рваный низ
            for (let i = 3; i >= 0; i--) {
                const wx = p.x + 14 - i * 7;
                this.ctx.lineTo(wx, dy - 8 + bob + (i % 2 === 0 ? 8 : 0));
            }
            this.ctx.closePath(); this.ctx.fill();
            // Голова
            this.ctx.beginPath();
            this.ctx.arc(p.x, dy - 38 + bob, 10, 0, Math.PI * 2);
            this.ctx.fillStyle = cfg.head; this.ctx.fill();
            // Глаза — светящиеся
            this.ctx.fillStyle = '#aaddff';
            this.ctx.shadowBlur = 10;
            this.ctx.beginPath(); this.ctx.ellipse(p.x - 3.5, dy - 39 + bob, 3, 2, 0, 0, Math.PI * 2); this.ctx.fill();
            this.ctx.beginPath(); this.ctx.ellipse(p.x + 3.5, dy - 39 + bob, 3, 2, 0, 0, Math.PI * 2); this.ctx.fill();
            this.ctx.globalAlpha = 1; this.ctx.shadowBlur = 0;
        } else if (enemy.type === 'wyvern') {
            // Виверна — дракон с крыльями
            const wf = Math.sin(time / 110) * 10;
            // Крылья
            this.ctx.fillStyle = 'rgba(30,80,40,0.75)';
            this.ctx.beginPath();
            this.ctx.moveTo(p.x - 7, dy - 28 + bob); this.ctx.lineTo(p.x - 30, dy - 48 + wf); this.ctx.lineTo(p.x - 7, dy - 10 + bob); this.ctx.fill();
            this.ctx.beginPath();
            this.ctx.moveTo(p.x + 7, dy - 28 + bob); this.ctx.lineTo(p.x + 30, dy - 48 + wf); this.ctx.lineTo(p.x + 7, dy - 10 + bob); this.ctx.fill();
            // Тело
            this.ctx.fillStyle = cfg.body;
            this.ctx.fillRect(p.x - 7, dy - cfg.h * 0.4 + bob, 14, cfg.h * 0.45);
            this.ctx.strokeStyle = '#1a4a20'; this.ctx.lineWidth = 1.5;
            this.ctx.strokeRect(p.x - 7, dy - cfg.h * 0.4 + bob, 14, cfg.h * 0.45);
            // Хвост
            this.ctx.beginPath();
            this.ctx.moveTo(p.x + 7, dy - 15 + bob); this.ctx.quadraticCurveTo(p.x + 22, dy - 5 + bob, p.x + 18, dy + 8 + bob);
            this.ctx.strokeStyle = cfg.body; this.ctx.lineWidth = 4; this.ctx.stroke();
            // Голова
            this.ctx.beginPath(); this.ctx.arc(p.x, dy - cfg.h + bob, 10, 0, Math.PI * 2);
            this.ctx.fillStyle = cfg.head; this.ctx.fill();
            this.ctx.strokeStyle = '#1a4a20'; this.ctx.lineWidth = 1.5; this.ctx.stroke();
            // Глаза
            this.ctx.fillStyle = cfg.eye;
            this.ctx.beginPath(); this.ctx.arc(p.x - 3, dy - cfg.h - 1 + bob, 2.5, 0, Math.PI * 2); this.ctx.fill();
            this.ctx.beginPath(); this.ctx.arc(p.x + 3, dy - cfg.h - 1 + bob, 2.5, 0, Math.PI * 2); this.ctx.fill();
        } else {
            // Стандартная гуманоидная фигура
            this.ctx.fillStyle = cfg.body;
            this.ctx.fillRect(p.x-7, dy - cfg.h*0.4 + bob, 14, cfg.h*0.45);
            this.ctx.strokeStyle = '#000'; this.ctx.lineWidth = 1.5;
            this.ctx.strokeRect(p.x-7, dy - cfg.h*0.4 + bob, 14, cfg.h*0.45);
            // Ноги
            this.ctx.fillRect(p.x-6, dy - cfg.h*0.02 + bob, 5, 12);
            this.ctx.fillRect(p.x+1, dy - cfg.h*0.02 + bob, 5, 12);
            // Голова
            this.ctx.beginPath();
            this.ctx.arc(p.x, dy - cfg.h + bob, 10, 0, Math.PI*2);
            this.ctx.fillStyle = cfg.head; this.ctx.fill();
            this.ctx.strokeStyle = '#000'; this.ctx.lineWidth = 1.5; this.ctx.stroke();
            // Глаза
            this.ctx.fillStyle = cfg.eye;
            this.ctx.beginPath(); this.ctx.arc(p.x-3, dy-cfg.h-1+bob, 2.5, 0, Math.PI*2); this.ctx.fill();
            this.ctx.beginPath(); this.ctx.arc(p.x+3, dy-cfg.h-1+bob, 2.5, 0, Math.PI*2); this.ctx.fill();
            // Клыки у орков/гоблинов
            if (enemy.type==='orc'||enemy.type==='goblin') {
                this.ctx.fillStyle = '#fff';
                this.ctx.beginPath(); this.ctx.moveTo(p.x-2,dy-cfg.h+5+bob); this.ctx.lineTo(p.x-1,dy-cfg.h+9+bob); this.ctx.lineTo(p.x,dy-cfg.h+5+bob); this.ctx.fill();
                this.ctx.beginPath(); this.ctx.moveTo(p.x+2,dy-cfg.h+5+bob); this.ctx.lineTo(p.x+3,dy-cfg.h+9+bob); this.ctx.lineTo(p.x+4,dy-cfg.h+5+bob); this.ctx.fill();
            }
            // Дракон — крылья
            if (enemy.type==='dragon') {
                this.ctx.fillStyle = 'rgba(100,0,0,0.6)';
                this.ctx.beginPath(); this.ctx.moveTo(p.x-7, dy-cfg.h*0.3+bob); this.ctx.lineTo(p.x-28, dy-cfg.h*0.55+bob); this.ctx.lineTo(p.x-7, dy-cfg.h*0.05+bob); this.ctx.fill();
                this.ctx.beginPath(); this.ctx.moveTo(p.x+7, dy-cfg.h*0.3+bob); this.ctx.lineTo(p.x+28, dy-cfg.h*0.55+bob); this.ctx.lineTo(p.x+7, dy-cfg.h*0.05+bob); this.ctx.fill();
            }
        }

        // Аура босса
        if (enemy.isBoss) {
            this.ctx.strokeStyle = `rgba(220,0,0,${0.3+Math.sin(time/200)*0.15})`;
            this.ctx.lineWidth = 2;
            this.ctx.beginPath();
            this.ctx.arc(p.x, dy - cfg.h*0.5, 26, 0, Math.PI*2);
            this.ctx.stroke();
        }

        // Статус-эффект: кольцо вокруг врага
        if (enemy.status) {
            const statusCols = {
                poison: 'rgba(30,230,80,',
                burn:   'rgba(255,110,0,',
                slow:   'rgba(80,160,255,',
            };
            const sc = statusCols[enemy.status] || 'rgba(220,220,220,';
            const pulse = 0.5 + 0.35 * Math.sin(time / 180);
            this.ctx.strokeStyle = sc + pulse + ')';
            this.ctx.lineWidth = 2.5;
            this.ctx.beginPath();
            this.ctx.arc(p.x, dy - cfg.h * 0.52, 22, 0, Math.PI * 2);
            this.ctx.stroke();
            // Мерцающие точки по окружности
            for (let i = 0; i < 4; i++) {
                const a = (time / 600 + i / 4) * Math.PI * 2;
                const dotAlpha = 0.4 + 0.5 * Math.abs(Math.sin(time / 200 + i));
                this.ctx.fillStyle = sc + dotAlpha + ')';
                this.ctx.beginPath();
                this.ctx.arc(p.x + Math.cos(a) * 22, dy - cfg.h * 0.52 + Math.sin(a) * 22, 2.5, 0, Math.PI * 2);
                this.ctx.fill();
            }
        }

        // HP бар
        const barW = 32, hp = enemy.hp / enemy.maxHp;
        this.ctx.fillStyle = '#1a1a1a';
        this.ctx.fillRect(p.x-barW/2, dy - cfg.h - 18 + bob, barW, 5);
        this.ctx.fillStyle = hp > 0.5 ? '#27ae60' : hp > 0.25 ? '#e67e22' : '#e74c3c';
        this.ctx.fillRect(p.x-barW/2, dy - cfg.h - 18 + bob, barW*hp, 5);
        this.ctx.strokeStyle = '#000'; this.ctx.lineWidth = 0.5;
        this.ctx.strokeRect(p.x-barW/2, dy - cfg.h - 18 + bob, barW, 5);

        // Имя
        this.ctx.fillStyle = enemy.isBoss ? '#ff4444' : '#dddddd';
        this.ctx.font = (enemy.isBoss ? 'bold ' : '') + '9px Arial';
        this.ctx.textAlign = 'center';
        this.ctx.fillText(enemy.name, p.x, dy - cfg.h - 22 + bob);
    },

    // ──────────────────────────────────
    // NPC
    // ──────────────────────────────────
    drawNPC(npc, time) {
        const p = this.toIso(npc.x, npc.y);
        const bob = Math.sin(time/300) * 2;
        const c = npc.color || '#8b6914';

        this.ctx.beginPath();
        this.ctx.ellipse(p.x, p.y+8, 16, 8, 0, 0, Math.PI*2);
        this.ctx.fillStyle = 'rgba(0,0,0,0.22)';
        this.ctx.fill();

        // Тело
        this.ctx.fillStyle = c;
        this.ctx.fillRect(p.x-7, p.y-28+bob, 14, 18);
        this.ctx.fillRect(p.x-5, p.y-10+bob, 4, 10);
        this.ctx.fillRect(p.x+1, p.y-10+bob, 4, 10);

        // Голова
        this.ctx.beginPath();
        this.ctx.arc(p.x, p.y-40+bob, 10, 0, Math.PI*2);
        this.ctx.fillStyle = '#ffcc99'; this.ctx.fill();
        this.ctx.strokeStyle = '#cc9966'; this.ctx.lineWidth = 1.5; this.ctx.stroke();

        // Индикатор диалога
        const bounce2 = Math.sin(time/180) * 4;
        this.ctx.fillStyle = '#ffd700';
        this.ctx.font = 'bold 14px Arial';
        this.ctx.textAlign = 'center';
        this.ctx.fillText('💬', p.x, p.y - 55 + bounce2);

        // Имя
        this.ctx.fillStyle = '#88ffaa';
        this.ctx.font = 'bold 10px Arial';
        this.ctx.fillText(npc.name, p.x, p.y - 70);
    },

    // ──────────────────────────────────
    // Предметы на земле
    // ──────────────────────────────────
    drawGroundItem(item, time) {
        const p = this.toIso(item.x, item.y);
        const bounce = Math.sin(time/300) * 4;

        // Свечение редких предметов
        const RGLOW = {
            uncommon:  'rgba(39,174,96,',
            rare:      'rgba(41,128,185,',
            epic:      'rgba(142,68,173,',
            legendary: 'rgba(230,126,34,',
        };
        const gc = RGLOW[item.rarity];
        if (gc) {
            const pulse = 0.22 + 0.18 * Math.sin(time / 350 + item.x);
            const gr = this.ctx.createRadialGradient(p.x, p.y - 12, 0, p.x, p.y - 12, 24);
            gr.addColorStop(0, gc + (pulse * 1.4) + ')');
            gr.addColorStop(1, gc + '0)');
            this.ctx.beginPath();
            this.ctx.arc(p.x, p.y - 12, 24, 0, Math.PI * 2);
            this.ctx.fillStyle = gr;
            this.ctx.fill();
            // Дополнительный ореол для легендарных
            if (item.rarity === 'legendary') {
                this.ctx.strokeStyle = gc + (0.5 + 0.4 * Math.sin(time / 200)) + ')';
                this.ctx.lineWidth = 1.5;
                this.ctx.beginPath();
                this.ctx.arc(p.x, p.y - 12 - bounce, 14, 0, Math.PI * 2);
                this.ctx.stroke();
            }
        }

        if (item.type === 'gold') {
            this.ctx.save();
            this.ctx.translate(p.x, p.y - 12 - bounce);
            this.ctx.beginPath(); this.ctx.arc(0,0,8,0,Math.PI*2);
            this.ctx.fillStyle = '#ffd700'; this.ctx.fill();
            this.ctx.strokeStyle = '#aa8800'; this.ctx.lineWidth = 1.5; this.ctx.stroke();
            this.ctx.fillStyle = '#aa8800'; this.ctx.font = 'bold 9px Arial'; this.ctx.textAlign = 'center';
            this.ctx.fillText('$', 0, 3);
            for (let i=0;i<3;i++) {
                const a = time/200+i*2;
                this.ctx.fillStyle = '#fff'; this.ctx.fillRect(Math.cos(a)*10, Math.sin(a)*10, 2, 2);
            }
            this.ctx.restore();
        } else if (item.type === 'potion') {
            const col = item.healAmount ? '#e74c3c' : '#3498db';
            this._drawPotionIcon(p.x, p.y - 12 - bounce, col);
        } else if (item.type === 'weapon') {
            this.ctx.save();
            this.ctx.translate(p.x, p.y - 14 - bounce);
            this.ctx.rotate(Math.PI/4);
            this.ctx.fillStyle = '#c0c0c0';
            this.ctx.fillRect(-2, -12, 4, 18);
            this.ctx.fillStyle = '#8b4513';
            this.ctx.fillRect(-2, 6, 4, 6);
            this.ctx.fillStyle = '#ffd700';
            this.ctx.fillRect(-6, 4, 12, 3);
            this.ctx.restore();
        } else if (item.type === 'armor') {
            this.ctx.save();
            this.ctx.translate(p.x, p.y - 14 - bounce);
            this.ctx.beginPath(); this.ctx.arc(0,0,9,0,Math.PI*2);
            this.ctx.fillStyle = '#4a4a6a'; this.ctx.fill();
            this.ctx.strokeStyle = '#6a6a9a'; this.ctx.lineWidth = 1.5; this.ctx.stroke();
            this.ctx.restore();
        } else {
            // Квестовый / неизвестный
            this.ctx.fillStyle = '#ff44ff';
            this.ctx.font = '16px Arial';
            this.ctx.textAlign = 'center';
            this.ctx.fillText('❓', p.x, p.y - 10 - bounce);
        }
    },

    drawLoreNote(note, time) {
        const p = this.toIso(note.gx, note.gy);
        const ctx = this.ctx;
        const bounce = Math.sin(time / 280) * 3;
        const pulse  = 0.5 + 0.4 * Math.abs(Math.sin(time / 500 + note.gx));
        // мягкое свечение
        const glow = ctx.createRadialGradient(p.x, p.y - 14, 0, p.x, p.y - 14, 20);
        glow.addColorStop(0, `rgba(140,120,255,${pulse * 0.4})`);
        glow.addColorStop(1, 'rgba(140,120,255,0)');
        ctx.fillStyle = glow;
        ctx.beginPath(); ctx.arc(p.x, p.y - 14, 20, 0, Math.PI * 2); ctx.fill();
        // пергамент
        ctx.save();
        ctx.translate(p.x, p.y - 16 - bounce);
        ctx.fillStyle = '#d4c49a';
        ctx.fillRect(-7, -9, 14, 16);
        ctx.strokeStyle = '#8a6a20'; ctx.lineWidth = 1.2; ctx.strokeRect(-7, -9, 14, 16);
        // строчки
        ctx.strokeStyle = '#8a6a3080'; ctx.lineWidth = 1;
        for (let i = 0; i < 3; i++) {
            ctx.beginPath(); ctx.moveTo(-5, -4 + i*4); ctx.lineTo(5, -4 + i*4); ctx.stroke();
        }
        ctx.restore();
        // иконка сверху
        ctx.font = '11px Arial'; ctx.textAlign = 'center';
        ctx.fillText('📜', p.x, p.y - 26 - bounce);
    },

    _drawPotionIcon(x, y, color) {
        this.ctx.fillStyle = '#4a2a10';
        this.ctx.fillRect(x-3, y-18, 6, 5);
        this.ctx.beginPath();
        this.ctx.moveTo(x, y-13); this.ctx.lineTo(x-7, y+3); this.ctx.lineTo(x+7, y+3); this.ctx.closePath();
        this.ctx.fillStyle = color; this.ctx.fill();
        this.ctx.strokeStyle = this._adj(color,-30); this.ctx.lineWidth = 1.5; this.ctx.stroke();
        this.ctx.fillStyle = 'rgba(255,255,255,0.3)';
        this.ctx.beginPath(); this.ctx.ellipse(x-2, y-6, 2, 4, 0, 0, Math.PI*2); this.ctx.fill();
    },

    // ──────────────────────────────────
    // Декорации
    // ──────────────────────────────────
    drawDecoration(dec, time) {
        const p = this.toIso(dec.x, dec.y);
        switch(dec.type) {
            case 'portal':  this._drawPortal(p, dec, time); break;
            case 'tree':    this._drawTree(p.x, p.y, 0.8); break;
            case 'house':   this._drawHouse(p); break;
            case 'tavern':  this._drawTavern(p, dec); break;
            case 'table':   this._drawTable(p); break;
            case 'torch':   this._drawTorch(p, time); break;
            case 'crystal': this._drawCrystal(p, time); break;
            case 'pillar':  this._drawPillar(p); break;
            case 'rock':    this._drawRock(p); break;
            case 'well':    this._drawWell(p); break;
            case 'fountain':this._drawFountain(p, time); break;
        }
    },

    _drawPortal(p, dec, time) {
        const isVoid = dec.destination === 'abyss' || this._currentMapId === 'abyss';
        const pulse  = Math.sin(time/200)*4;
        const ctx    = this.ctx;
        ctx.beginPath();
        ctx.ellipse(p.x, p.y-20, 14+pulse/2, 22+pulse, 0, 0, Math.PI*2);
        const g = ctx.createRadialGradient(p.x,p.y-20,0,p.x,p.y-20,24);
        if (isVoid) {
            g.addColorStop(0,'rgba(180,0,255,0.95)');
            g.addColorStop(0.4,'rgba(60,0,120,0.7)');
            g.addColorStop(1,'rgba(10,0,30,0.2)');
            ctx.fillStyle = g; ctx.fill();
            ctx.strokeStyle = '#6600aa'; ctx.lineWidth = 2.5; ctx.stroke();
            // Вращающийся ореол из частиц
            const rot = time/1200;
            for (let i=0;i<6;i++) {
                const a = rot + i/6*Math.PI*2;
                ctx.beginPath();
                ctx.arc(p.x+Math.cos(a)*18, p.y-20+Math.sin(a)*26, 2.5, 0, Math.PI*2);
                ctx.fillStyle = `rgba(${100+Math.floor(Math.sin(a+time/400)*50)},0,255,0.7)`;
                ctx.fill();
            }
            ctx.fillStyle = '#cc00ff';
        } else {
            g.addColorStop(0,'rgba(255,255,255,0.9)');
            g.addColorStop(0.4,'rgba(150,0,255,0.7)');
            g.addColorStop(1,'rgba(50,0,150,0.2)');
            ctx.fillStyle = g; ctx.fill();
            ctx.strokeStyle = '#cc88ff'; ctx.lineWidth = 2; ctx.stroke();
            ctx.fillStyle = '#ffd700';
        }
        ctx.font = 'bold 9px Arial'; ctx.textAlign = 'center';
        ctx.fillText(dec.name || '?', p.x, p.y - 46);
    },

    _drawHouse(p) {
        const ctx = this.ctx;
        ctx.fillStyle = '#8b6914'; ctx.fillRect(p.x-18, p.y-28, 36, 28);
        ctx.strokeStyle = '#5a4000'; ctx.lineWidth = 1.5; ctx.strokeRect(p.x-18, p.y-28, 36, 28);
        ctx.fillStyle = '#c0392b';
        ctx.beginPath(); ctx.moveTo(p.x-20, p.y-28); ctx.lineTo(p.x, p.y-50); ctx.lineTo(p.x+20, p.y-28); ctx.closePath(); ctx.fill();
        ctx.strokeStyle = '#922b21'; ctx.stroke();
        ctx.fillStyle = '#4a2a0a'; ctx.fillRect(p.x-5, p.y-18, 10, 18);
        ctx.fillStyle = '#88ccff'; ctx.fillRect(p.x-14, p.y-24, 10, 8);
        ctx.strokeStyle = '#aaddff'; ctx.lineWidth = 1; ctx.strokeRect(p.x-14, p.y-24, 10, 8);
    },

    _drawTavern(p, dec) {
        const ctx = this.ctx;
        // Стены (тёплый коричневый, шире обычного дома)
        ctx.fillStyle = '#5a3a1a'; ctx.fillRect(p.x-22, p.y-32, 44, 32);
        ctx.strokeStyle = '#3a2010'; ctx.lineWidth = 1.5; ctx.strokeRect(p.x-22, p.y-32, 44, 32);
        // Крыша (тёмно-коричневая)
        ctx.fillStyle = '#8B4513';
        ctx.beginPath(); ctx.moveTo(p.x-24, p.y-32); ctx.lineTo(p.x, p.y-58); ctx.lineTo(p.x+24, p.y-32); ctx.closePath(); ctx.fill();
        ctx.strokeStyle = '#5a2d0c'; ctx.lineWidth = 1; ctx.stroke();
        // Дверь (двойная)
        ctx.fillStyle = '#2a1a08'; ctx.fillRect(p.x-7, p.y-22, 14, 22);
        ctx.strokeStyle = '#4a3018'; ctx.lineWidth = 1; ctx.strokeRect(p.x-7, p.y-22, 14, 22);
        ctx.strokeStyle = '#3a2010'; ctx.beginPath(); ctx.moveTo(p.x, p.y-22); ctx.lineTo(p.x, p.y); ctx.stroke();
        // Два окна
        ctx.fillStyle = '#ffddaa'; ctx.fillRect(p.x-20, p.y-26, 9, 7);
        ctx.fillStyle = '#ffddaa'; ctx.fillRect(p.x+11, p.y-26, 9, 7);
        ctx.strokeStyle = '#8b6914'; ctx.lineWidth = 1;
        ctx.strokeRect(p.x-20, p.y-26, 9, 7); ctx.strokeRect(p.x+11, p.y-26, 9, 7);
        // Вывеска
        ctx.fillStyle = '#c8a020'; ctx.fillRect(p.x-18, p.y-52, 36, 14);
        ctx.strokeStyle = '#7a6010'; ctx.lineWidth = 1; ctx.strokeRect(p.x-18, p.y-52, 36, 14);
        ctx.font = '10px serif'; ctx.textAlign = 'center'; ctx.fillStyle = '#2a1a00';
        ctx.fillText('🍺', p.x, p.y - 41);
        // Название
        ctx.fillStyle = '#ffd700'; ctx.font = 'bold 9px Arial';
        ctx.fillText(dec && dec.name ? dec.name : 'Таверна', p.x, p.y - 64);
    },

    _drawTable(p) {
        const ctx = this.ctx;
        // Столешница
        ctx.fillStyle = '#8B5A2B'; ctx.fillRect(p.x-12, p.y-12, 24, 12);
        ctx.strokeStyle = '#5a3a10'; ctx.lineWidth = 1; ctx.strokeRect(p.x-12, p.y-12, 24, 12);
        // Верхний кант
        ctx.fillStyle = '#a06030'; ctx.fillRect(p.x-12, p.y-14, 24, 4);
        ctx.strokeStyle = '#6a4020'; ctx.strokeRect(p.x-12, p.y-14, 24, 4);
        // Кружка
        ctx.font = '10px serif'; ctx.textAlign = 'center';
        ctx.fillText('🍺', p.x, p.y - 9);
    },

    _drawTorch(p, time) {
        const ctx = this.ctx;
        ctx.fillStyle = '#5a3000'; ctx.fillRect(p.x-2, p.y-20, 4, 20);
        // составное мерцание из двух частот
        const flicker = Math.sin(time/80)*2 + Math.cos(time/55)*1;
        const radius  = 11 + Math.abs(Math.sin(time/120))*2;
        const cx = p.x + Math.sin(time/95)*1.2;
        const cy = p.y - 24 + flicker;
        // внешнее свечение
        const outer = ctx.createRadialGradient(cx, cy, 0, cx, cy, radius*2.2);
        outer.addColorStop(0,'rgba(255,150,0,0.18)');
        outer.addColorStop(1,'rgba(255,50,0,0)');
        ctx.fillStyle = outer;
        ctx.beginPath(); ctx.arc(cx, cy, radius*2.2, 0, Math.PI*2); ctx.fill();
        // основное пламя
        const g = ctx.createRadialGradient(cx, cy, 0, cx, cy, radius);
        g.addColorStop(0,'rgba(255,220,60,0.95)');
        g.addColorStop(0.55,'rgba(255,110,0,0.6)');
        g.addColorStop(1,'rgba(255,40,0,0)');
        ctx.fillStyle = g;
        ctx.beginPath(); ctx.arc(cx, cy, radius, 0, Math.PI*2); ctx.fill();
        // искра (одна, летит вверх)
        const sparkPhase = (time/600) % 1;
        if (sparkPhase < 0.55) {
            const sy = cy - sparkPhase * 18;
            const sa = 0.9 - sparkPhase * 1.6;
            ctx.fillStyle = `rgba(255,220,80,${Math.max(0,sa)})`;
            ctx.beginPath(); ctx.arc(cx + Math.sin(sparkPhase*8)*2, sy, 1.2, 0, Math.PI*2); ctx.fill();
        }
    },

    _drawCrystal(p, time) {
        const ctx = this.ctx;
        const pulse = Math.sin(time/400)*3;
        const hue = (time/30)%360;
        ctx.fillStyle = `hsla(${hue},80%,60%,0.8)`;
        ctx.beginPath();
        ctx.moveTo(p.x, p.y-26-pulse); ctx.lineTo(p.x-8, p.y-14); ctx.lineTo(p.x, p.y-4); ctx.lineTo(p.x+8, p.y-14); ctx.closePath();
        ctx.fill();
        ctx.strokeStyle = `hsla(${hue},100%,80%,0.6)`; ctx.lineWidth = 1.5; ctx.stroke();
    },

    _drawPillar(p) {
        const ctx = this.ctx;
        const isAbyss = this._currentMapId === 'abyss';
        ctx.fillStyle = isAbyss ? '#1a0028' : '#909090'; ctx.fillRect(p.x-6, p.y-30, 12, 30);
        ctx.fillStyle = isAbyss ? '#110018' : '#808080'; ctx.fillRect(p.x-8, p.y-32, 16, 6);
        ctx.fillStyle = isAbyss ? '#220033' : '#a0a0a0'; ctx.fillRect(p.x-8, p.y-4, 16, 6);
        ctx.strokeStyle = isAbyss ? '#330044' : '#606060'; ctx.lineWidth = 1;
        ctx.strokeRect(p.x-6, p.y-30, 12, 30);
        if (isAbyss) {
            ctx.shadowColor = '#6600aa'; ctx.shadowBlur = 10;
            ctx.strokeStyle = '#440066'; ctx.lineWidth = 2;
            ctx.strokeRect(p.x-5, p.y-29, 10, 28);
            ctx.shadowBlur = 0;
        }
    },

    _drawRock(p) {
        const ctx = this.ctx;
        ctx.fillStyle = '#555'; ctx.beginPath(); ctx.ellipse(p.x, p.y-8, 12, 7, 0, 0, Math.PI*2); ctx.fill();
        ctx.fillStyle = '#666'; ctx.beginPath(); ctx.ellipse(p.x-2, p.y-10, 7, 4, 0, 0, Math.PI*2); ctx.fill();
    },

    _drawWell(p) {
        const ctx = this.ctx;
        ctx.fillStyle = '#7a7a7a'; ctx.fillRect(p.x-10, p.y-16, 20, 16);
        ctx.fillStyle = '#3a3a5a'; ctx.beginPath(); ctx.arc(p.x, p.y-16, 10, 0, Math.PI*2); ctx.fill();
        ctx.strokeStyle = '#5a5a8a'; ctx.lineWidth = 1.5; ctx.stroke();
        ctx.fillStyle = '#5a3a10'; ctx.fillRect(p.x-2, p.y-28, 4, 14); ctx.fillRect(p.x-12, p.y-28, 4, 8); ctx.fillRect(p.x+8, p.y-28, 4, 8);
        ctx.strokeStyle = '#3a2000'; ctx.lineWidth = 1; ctx.strokeRect(p.x-12, p.y-28, 24, 4);
    },

    _drawFountain(p, time) {
        const ctx = this.ctx;
        ctx.fillStyle = '#7a7a9a'; ctx.beginPath(); ctx.arc(p.x, p.y, 14, 0, Math.PI*2); ctx.fill();
        ctx.fillStyle = '#2a5a8c'; ctx.beginPath(); ctx.arc(p.x, p.y, 10, 0, Math.PI*2); ctx.fill();
        const spray = Math.sin(time/200)*2;
        ctx.strokeStyle = 'rgba(100,180,255,0.7)'; ctx.lineWidth = 1.5;
        for (let i=0;i<5;i++) {
            const a = i/5*Math.PI*2;
            ctx.beginPath(); ctx.moveTo(p.x, p.y-8); ctx.lineTo(p.x+Math.cos(a)*10+spray, p.y-18+Math.sin(a)*4); ctx.stroke();
        }
    },

    // ──────────────────────────────────
    // Частицы
    // ──────────────────────────────────
    addParticle(worldX, worldY, type, count) {
        count = count || 6;
        const pos = this.toIso(worldX, worldY);
        const palettes = {
            hit:    ['#ff4444','#ff8800','#ffcc00'],
            magic:  ['#4488ff','#aa44ff','#ffffff'],
            heal:   ['#44ff88','#88ff44','#ffffff'],
            fire:   ['#ff6600','#ff9900','#ffcc00'],
            ice:    ['#88ccff','#aaddff','#ffffff'],
            poison: ['#44cc44','#88dd44','#ccff44'],
            gold:   ['#ffd700','#ffaa00','#ffffaa'],
            death:  ['#666','#888','#aaa'],
            holy:   ['#ffee44','#ffffff','#fff0aa'],
            void:   ['#4a0080','#6600aa','#330055'],
        };
        const cols = palettes[type] || palettes.hit;
        for (let i = 0; i < count; i++) {
            this.particles.push({
                x: pos.x + (Math.random()-0.5)*20,
                y: pos.y - 15 + (Math.random()-0.5)*20,
                vx: (Math.random()-0.5)*3.5,
                vy: -1.5 - Math.random()*3,
                life: 1,
                decay: 0.025 + Math.random()*0.03,
                size: 2 + Math.random()*3,
                col: cols[Math.floor(Math.random()*cols.length)]
            });
        }
    },

    updateParticles(dt) {
        this.particles.forEach(p => {
            p.x  += p.vx;
            p.y  += p.vy;
            p.vy += 0.12;
            p.life -= p.decay;
        });
        this.particles = this.particles.filter(p => p.life > 0);
    },

    drawParticles() {
        this.particles.forEach(p => {
            this.ctx.save();
            this.ctx.globalAlpha = p.life;
            this.ctx.fillStyle = p.col;
            this.ctx.beginPath();
            this.ctx.arc(p.x, p.y, p.size * p.life, 0, Math.PI*2);
            this.ctx.fill();
            this.ctx.restore();
        });
    },

    // ──────────────────────────────────
    // Встряска экрана
    // ──────────────────────────────────
    shakeScreen(power) {
        this.shake.power = Math.max(this.shake.power, power);
    },
    updateShake() {
        if (this.shake.power > 0.1) {
            this.shake.x = (Math.random()-0.5) * this.shake.power;
            this.shake.y = (Math.random()-0.5) * this.shake.power;
            this.shake.power *= 0.82;
        } else {
            this.shake.power = 0;
            this.shake.x = 0;
            this.shake.y = 0;
        }
    },

    // ──────────────────────────────────
    // Вспышка экрана
    // ──────────────────────────────────
    flashScreen(color, alpha, dur) {
        this._flash = { color: color||'#ff0000', alpha: alpha||0.30, life: 1, speed: 1/(dur||7) };
    },
    drawFlash() {
        if (!this._flash || this._flash.life <= 0) return;
        this.ctx.save();
        this.ctx.globalAlpha = this._flash.life * this._flash.alpha;
        this.ctx.fillStyle = this._flash.color;
        this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
        this.ctx.restore();
        this._flash.life -= this._flash.speed;
    },

    // ──────────────────────────────────
    // Атмосфера Бездны
    // ──────────────────────────────────
    drawAbyssAtmosphere(time) {
        const ctx = this.ctx;
        const pulse = Math.sin(time / 1400) * 0.04;
        ctx.save();
        ctx.globalAlpha = 0.25 + pulse;
        const g = ctx.createRadialGradient(
            this.canvas.width*0.5, this.canvas.height*0.4, 0,
            this.canvas.width*0.5, this.canvas.height*0.4, this.canvas.width*0.75
        );
        g.addColorStop(0, 'rgba(20,0,40,0)');
        g.addColorStop(0.5,'rgba(10,0,28,0.5)');
        g.addColorStop(1,  'rgba(0,0,8,0.95)');
        ctx.fillStyle = g;
        ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
        // Полосы тумана
        ctx.globalAlpha = 0.07 + Math.sin(time/900)*0.03;
        for (let i=0;i<3;i++) {
            const fy = ((time/3200 + i*0.33) % 1) * this.canvas.height;
            const fg = ctx.createLinearGradient(0, fy-22, 0, fy+22);
            fg.addColorStop(0,'transparent');
            fg.addColorStop(0.5,'rgba(40,0,70,0.55)');
            fg.addColorStop(1,'transparent');
            ctx.fillStyle = fg;
            ctx.fillRect(0, fy-22, this.canvas.width, 44);
        }
        ctx.restore();
    },

    // ──────────────────────────────────
    // Всплывающие числа урона/лечения
    // ──────────────────────────────────
    addFloatingText(worldX, worldY, text, color, size) {
        const pos = this.toIso(worldX, worldY);
        this.floatingTexts.push({
            x:     pos.x,
            y:     pos.y - 30,
            text:  String(text),
            color: color || '#ff4444',
            size:  size  || 16,
            life:  1,
            decay: 0.016,
            vy:    -1.1,
        });
    },

    updateFloatingTexts(dt) {
        this.floatingTexts.forEach(t => {
            t.y   += t.vy;
            t.vy  += 0.025;   // замедление подъёма
            t.life -= t.decay;
        });
        this.floatingTexts = this.floatingTexts.filter(t => t.life > 0);
    },

    drawFloatingTexts() {
        const ctx = this.ctx;
        this.floatingTexts.forEach(t => {
            ctx.save();
            ctx.globalAlpha = Math.min(1, t.life * 2.2);
            ctx.font = `bold ${t.size}px Arial`;
            ctx.textAlign = 'center';
            // Тень
            ctx.fillStyle = 'rgba(0,0,0,0.7)';
            ctx.fillText(t.text, t.x + 1, t.y + 1);
            // Текст
            ctx.fillStyle = t.color;
            ctx.fillText(t.text, t.x, t.y);
            ctx.restore();
        });
    },

    // ──────────────────────────────────
    // Миникарта
    // ──────────────────────────────────
    drawMinimap(map, player, enemies, questDots) {
        const ctx = this.ctx;
        const mx = this.canvas.width - 110, my = 52, ms = 95;
        const mw = map[0].length, mh = map.length;
        const tw = ms / mw, th = ms / mh;

        // Фон
        ctx.fillStyle = 'rgba(4,4,12,0.82)';
        ctx.fillRect(mx-2, my-2, ms+4, ms+4);
        ctx.strokeStyle = '#1e1e38'; ctx.lineWidth = 1;
        ctx.strokeRect(mx-2, my-2, ms+4, ms+4);

        const MCOLS = { 0:'#2d5a1a',1:'#1a4a7c',2:'#4a4a4a',3:'#8a7a4a',
                        4:'#2a1808',5:'#5a4020',6:'#8a3a00',7:'#b0b0c0',
                        8:'#5a3a1a',9:'#505050',10:'#2a4a2a',11:'#7090b0' };
        for (let y=0; y<mh; y++)
            for (let x=0; x<mw; x++) {
                ctx.fillStyle = MCOLS[map[y][x]] || '#333';
                ctx.fillRect(mx + x*tw, my + y*th, Math.ceil(tw), Math.ceil(th));
            }

        // Маркеры квестов на миникарте
        if (questDots && questDots.length) {
            questDots.forEach(d => {
                const col = d.type === 'give'    ? '#ffd700' :
                            d.type === 'advance' ? '#ffaa00' :
                            d.type === 'complete'? '#27ae60' :
                            d.type === 'target'  ? '#88aaff' : '#fff';
                const r = d.type === 'target' ? tw * 1.6 : tw * 1.2;
                ctx.fillStyle = col + '88';
                ctx.strokeStyle = col;
                ctx.lineWidth = 0.8;
                ctx.beginPath();
                ctx.arc(mx + d.x * tw + tw/2, my + d.y * th + th/2, r, 0, Math.PI * 2);
                ctx.fill();
                ctx.stroke();
            });
        }

        // Враги
        enemies.forEach(e => {
            ctx.fillStyle = '#e74c3c';
            ctx.fillRect(mx + e.x*tw, my + e.y*th, tw+1, th+1);
        });

        // Игрок
        const px = Math.round(player.x), py = Math.round(player.y);
        ctx.fillStyle = '#ffffff';
        ctx.fillRect(mx + px*tw - 1, my + py*th - 1, tw+2, th+2);
    },

    // ──────────────────────────────────
    // Маркеры квестов над NPC
    // ──────────────────────────────────
    drawQuestMarkers(npcs, questData, time) {
        if (!questData || !npcs || !npcs.length) return;
        const ctx = this.ctx;
        const bounce = Math.sin(time / 300) * 3;

        npcs.forEach(npc => {
            const mtype = questData[npc.name];
            if (!mtype) return;

            const p  = this.toIso(npc.x, npc.y);
            const cx = p.x;
            const cy = p.y - 80 + bounce;
            const r  = 9;

            ctx.save();

            if (mtype === 'give') {
                // Жёлтый "!" — новый квест
                ctx.fillStyle = 'rgba(255,215,0,0.18)';
                ctx.strokeStyle = '#ffd700';
                ctx.lineWidth = 1.5;
                ctx.beginPath(); ctx.arc(cx, cy, r, 0, Math.PI*2); ctx.fill(); ctx.stroke();
                ctx.fillStyle = '#ffd700';
                ctx.font = 'bold 13px Arial'; ctx.textAlign = 'center';
                ctx.fillText('!', cx, cy + 5);

            } else if (mtype === 'advance') {
                // Мигающий оранжевый "?" — нужно отчитаться
                const pulse = 0.55 + 0.45 * Math.sin(time / 180);
                ctx.globalAlpha = pulse;
                ctx.fillStyle = 'rgba(255,170,0,0.22)';
                ctx.strokeStyle = '#ffaa00';
                ctx.lineWidth = 2;
                ctx.beginPath(); ctx.arc(cx, cy, r, 0, Math.PI*2); ctx.fill(); ctx.stroke();
                ctx.fillStyle = '#ffaa00';
                ctx.font = 'bold 12px Arial'; ctx.textAlign = 'center';
                ctx.fillText('?', cx, cy + 4);

            } else if (mtype === 'complete') {
                // Зелёный "✓"
                ctx.fillStyle = 'rgba(39,174,96,0.18)';
                ctx.strokeStyle = '#27ae60';
                ctx.lineWidth = 1.5;
                ctx.beginPath(); ctx.arc(cx, cy, r, 0, Math.PI*2); ctx.fill(); ctx.stroke();
                ctx.fillStyle = '#27ae60';
                ctx.font = 'bold 11px Arial'; ctx.textAlign = 'center';
                ctx.fillText('✓', cx, cy + 4);
            }

            ctx.restore();
        });
    },

    // ──────────────────────────────────
    // Очистка и наложение день/ночь
    // ──────────────────────────────────
    clear(brightness) {
        const ctx = this.ctx;
        ctx.fillStyle = '#07070f';
        ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
        const grad = ctx.createRadialGradient(450, 300, 0, 450, 300, 500);
        grad.addColorStop(0, '#12122a');
        grad.addColorStop(1, '#07070f');
        ctx.fillStyle = grad;
        ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
    },

    // Динамическое освещение: тьма с "дырками" от источников света
    drawLightMask(brightness, lights, time) {
        if (brightness >= 1) return;
        const lc = this.lightCtx;
        const darkness = Math.max(0, 1 - brightness) * 0.80;

        lc.clearRect(0, 0, this.lightCanvas.width, this.lightCanvas.height);
        lc.fillStyle = `rgba(0,0,40,${darkness})`;
        lc.fillRect(0, 0, this.lightCanvas.width, this.lightCanvas.height);

        if (lights && lights.length > 0) {
            lc.globalCompositeOperation = 'destination-out';
            lights.forEach(light => {
                const pos = this.toIso(light.x, light.y);
                const flicker = light.flicker ? Math.sin(time / 80 + (light.x || 0) * 3.3) * 9 : 0;
                const r = (light.radius || 90) + flicker;
                const cy = pos.y - 18;
                const g = lc.createRadialGradient(pos.x, cy, 0, pos.x, cy, r);
                g.addColorStop(0,    'rgba(0,0,0,0.90)');
                g.addColorStop(0.45, 'rgba(0,0,0,0.55)');
                g.addColorStop(0.80, 'rgba(0,0,0,0.15)');
                g.addColorStop(1,    'rgba(0,0,0,0)');
                lc.fillStyle = g;
                lc.beginPath();
                lc.arc(pos.x, cy, r, 0, Math.PI * 2);
                lc.fill();
            });
            lc.globalCompositeOperation = 'source-over';
        }

        this.ctx.drawImage(this.lightCanvas, 0, 0);
    },

    // Дождь
    drawRain(particles) {
        const ctx = this.ctx;
        ctx.strokeStyle = 'rgba(130,160,255,0.45)';
        ctx.lineWidth = 1;
        particles.forEach(p => {
            ctx.beginPath();
            ctx.moveTo(p.x, p.y);
            ctx.lineTo(p.x - 2, p.y + 10);
            ctx.stroke();
        });
    },

    // Снег
    drawSnow(particles) {
        const ctx = this.ctx;
        ctx.fillStyle = 'rgba(220,220,255,0.6)';
        particles.forEach(p => {
            ctx.beginPath();
            ctx.arc(p.x, p.y, p.r, 0, Math.PI*2);
            ctx.fill();
        });
    },

    // Туман
    drawFog(time) {
        const ctx = this.ctx;
        ctx.fillStyle = `rgba(180,190,200,${0.08+0.04*Math.sin(time/2000)})`;
        ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
    },

    // Звёздное небо (ночью)
    drawStars(time, brightness) {
        if (brightness > 0.6) return;
        const alpha = (1 - brightness / 0.6) * 0.7;
        const ctx = this.ctx;
        ctx.fillStyle = `rgba(255,255,255,${alpha})`;
        // Постоянный seed для позиций
        for (let i = 0; i < 60; i++) {
            const sx = (((i * 1619 + 7) * 9301 + 49297) % 233280) / 233280 * 900;
            const sy = (((i * 3491 + 13) * 9301 + 49297) % 233280) / 233280 * 120;
            const twinkle = 0.3 + 0.7 * Math.abs(Math.sin(time/800 + i));
            const r = 0.5 + (i%3)*0.4;
            ctx.globalAlpha = alpha * twinkle;
            ctx.beginPath(); ctx.arc(sx, sy, r, 0, Math.PI*2); ctx.fill();
        }
        ctx.globalAlpha = 1;
    },

    // ──────────────────────────────────
    // Утилиты
    // ──────────────────────────────────
    _adj(hex, amt) {
        const n = parseInt(hex.replace('#',''), 16);
        const R = Math.max(0, Math.min(255, (n>>16)+amt));
        const G = Math.max(0, Math.min(255, ((n>>8)&0xff)+amt));
        const B = Math.max(0, Math.min(255, (n&0xff)+amt));
        return '#'+(0x1000000+R*0x10000+G*0x100+B).toString(16).slice(1);
    },

    drawText(text, x, y, color, size='13px', align='left') {
        this.ctx.font = `${size} Arial`;
        this.ctx.textAlign = align;
        this.ctx.fillStyle = '#000'; this.ctx.fillText(text, x+1, y+1);
        this.ctx.fillStyle = color; this.ctx.fillText(text, x, y);
    },

    // ══════════════════════════════════════════
    // ПОРТРЕТЫ — отдельный canvas для боя
    // ══════════════════════════════════════════
    drawPlayerPortrait(player, canvas) {
        if (!canvas) return;
        const c = canvas.getContext('2d');
        const W = canvas.width, H = canvas.height;
        c.clearRect(0, 0, W, H);
        // фон
        c.fillStyle = '#06060e';
        c.fillRect(0, 0, W, H);

        const cls = player.cls || 'warrior';
        const cx = W / 2;

        // ── Базовое тело (общее) ──────────────────
        const _body = (torsoColor, shoulderColor) => {
            // тело
            c.fillStyle = torsoColor;
            c.fillRect(cx - 14, 58, 28, 26);
            // плечи
            c.fillStyle = shoulderColor;
            c.fillRect(cx - 19, 55, 10, 10);
            c.fillRect(cx + 9, 55, 10, 10);
            // руки
            c.fillStyle = torsoColor;
            c.fillRect(cx - 21, 65, 8, 14);
            c.fillRect(cx + 13, 65, 8, 14);
        };

        const _head = (faceColor, eyeColor, pupilColor) => {
            // голова
            c.fillStyle = faceColor;
            c.beginPath(); c.arc(cx, 40, 14, 0, Math.PI * 2); c.fill();
            // глаза
            c.fillStyle = eyeColor;
            c.beginPath(); c.arc(cx - 5, 38, 3.5, 0, Math.PI * 2); c.fill();
            c.beginPath(); c.arc(cx + 5, 38, 3.5, 0, Math.PI * 2); c.fill();
            // зрачки
            c.fillStyle = pupilColor;
            c.beginPath(); c.arc(cx - 5, 38, 1.5, 0, Math.PI * 2); c.fill();
            c.beginPath(); c.arc(cx + 5, 38, 1.5, 0, Math.PI * 2); c.fill();
            // рот
            c.strokeStyle = '#8b5e3c'; c.lineWidth = 1.5;
            c.beginPath(); c.arc(cx, 44, 4, 0.15 * Math.PI, 0.85 * Math.PI); c.stroke();
        };

        switch (cls) {
            case 'warrior': {
                _body('#4a6080', '#607090');
                // стальной шлем
                c.fillStyle = '#7080a0';
                c.fillRect(cx - 14, 24, 28, 22);
                c.beginPath(); c.arc(cx, 26, 14, Math.PI, 0); c.fill();
                // визор
                c.fillStyle = '#30404a';
                c.fillRect(cx - 10, 34, 20, 8);
                // красный плащ
                c.fillStyle = '#8a1a1a';
                c.beginPath(); c.moveTo(cx - 16, 60); c.lineTo(cx - 22, 90); c.lineTo(cx + 22, 90); c.lineTo(cx + 16, 60); c.fill();
                break;
            }
            case 'mage': {
                _body('#2a2a6a', '#1a1a5a');
                _head('#c8a882', '#88aaff', '#2233aa');
                // синяя роба
                c.fillStyle = '#1a1a6a';
                c.fillRect(cx - 14, 58, 28, 30);
                // остроконечная шляпа
                c.fillStyle = '#1a1a8a';
                c.beginPath(); c.moveTo(cx, 2); c.lineTo(cx - 18, 38); c.lineTo(cx + 18, 38); c.fill();
                c.fillStyle = '#2828aa';
                c.fillRect(cx - 20, 36, 40, 6);
                // светящиеся глаза
                c.fillStyle = '#88aaff'; c.shadowColor = '#88aaff'; c.shadowBlur = 8;
                c.beginPath(); c.arc(cx - 5, 38, 3, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 5, 38, 3, 0, Math.PI * 2); c.fill();
                c.shadowBlur = 0;
                break;
            }
            case 'archer': {
                _body('#2a4a1a', '#3a5a28');
                _head('#c8a882', '#8a6a2a', '#2a1a00');
                // зелёный капюшон
                c.fillStyle = '#2a4a1a';
                c.beginPath(); c.arc(cx, 36, 18, Math.PI, 0); c.fill();
                c.fillRect(cx - 18, 36, 36, 12);
                c.fillStyle = '#3a5a28';
                c.fillRect(cx - 10, 26, 20, 14);
                // лук за спиной
                c.strokeStyle = '#6a4a1a'; c.lineWidth = 3;
                c.beginPath(); c.arc(cx + 22, 55, 20, -0.7 * Math.PI, 0.4 * Math.PI); c.stroke();
                c.strokeStyle = '#b8a060'; c.lineWidth = 1;
                c.beginPath(); c.moveTo(cx + 22, 41); c.lineTo(cx + 22, 82); c.stroke();
                break;
            }
            case 'paladin': {
                _body('#b8902a', '#d4a832');
                _head('#c8a882', '#3a3a8a', '#0a0a3a');
                // золотой шлем
                c.fillStyle = '#c8a020';
                c.beginPath(); c.arc(cx, 28, 15, Math.PI, 0); c.fill();
                c.fillRect(cx - 15, 28, 30, 18);
                // крест на шлеме
                c.fillStyle = '#ffffff';
                c.fillRect(cx - 2, 20, 4, 14);
                c.fillRect(cx - 8, 26, 16, 4);
                // белый плащ
                c.fillStyle = '#e0e0d0';
                c.beginPath(); c.moveTo(cx - 16, 60); c.lineTo(cx - 22, 90); c.lineTo(cx + 22, 90); c.lineTo(cx + 16, 60); c.fill();
                break;
            }
            case 'necromancer': {
                _body('#181828', '#0e0e1e');
                _head('#9098a8', '#aa44cc', '#5500aa');
                // тёмный капюшон
                c.fillStyle = '#0e0e22';
                c.beginPath(); c.arc(cx, 36, 19, Math.PI, 0); c.fill();
                c.fillRect(cx - 19, 36, 38, 14);
                c.beginPath(); c.moveTo(cx, 4); c.lineTo(cx - 16, 38); c.lineTo(cx + 16, 38); c.fill();
                // пурпурные глаза
                c.fillStyle = '#cc44ff'; c.shadowColor = '#aa00ff'; c.shadowBlur = 10;
                c.beginPath(); c.arc(cx - 5, 38, 3.5, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 5, 38, 3.5, 0, Math.PI * 2); c.fill();
                c.shadowBlur = 0;
                break;
            }
            case 'berserker': {
                _body('#5a3020', '#6a3828');
                _head('#c8a078', '#cc4422', '#660000');
                // кожаный шлем с рогами
                c.fillStyle = '#4a2810';
                c.beginPath(); c.arc(cx, 34, 15, Math.PI, 0); c.fill();
                c.fillRect(cx - 15, 34, 30, 10);
                // рога
                c.fillStyle = '#8a7050';
                c.beginPath(); c.moveTo(cx - 14, 26); c.lineTo(cx - 22, 10); c.lineTo(cx - 8, 28); c.fill();
                c.beginPath(); c.moveTo(cx + 14, 26); c.lineTo(cx + 22, 10); c.lineTo(cx + 8, 28); c.fill();
                // шрамы
                c.strokeStyle = '#8a4030'; c.lineWidth = 1.5;
                c.beginPath(); c.moveTo(cx - 8, 35); c.lineTo(cx - 2, 42); c.stroke();
                c.beginPath(); c.moveTo(cx + 4, 34); c.lineTo(cx + 8, 43); c.stroke();
                break;
            }
            case 'druid': {
                _body('#2a4a18', '#1e3810');
                _head('#c8a882', '#3a7a20', '#0a3a00');
                // венок из листьев
                c.fillStyle = '#2a6a10';
                c.beginPath(); c.arc(cx, 34, 17, Math.PI, 0); c.fill();
                c.fillRect(cx - 17, 34, 34, 6);
                // листочки
                [cx - 16, cx - 8, cx, cx + 8, cx + 16].forEach((lx, i) => {
                    c.fillStyle = i % 2 === 0 ? '#2a8020' : '#3a6a18';
                    c.beginPath(); c.ellipse(lx, 26, 5, 8, (i - 2) * 0.3, 0, Math.PI * 2); c.fill();
                });
                // зелёное одеяние
                c.fillStyle = '#1a3a10';
                c.fillRect(cx - 14, 58, 28, 30);
                break;
            }
            default: {
                _body('#4a4a6a', '#5a5a7a');
                _head('#c8a882', '#888888', '#333333');
            }
        }
    },

    drawEnemyPortrait(enemy, canvas) {
        if (!canvas || !enemy) return;
        const c = canvas.getContext('2d');
        const W = canvas.width, H = canvas.height;
        c.clearRect(0, 0, W, H);
        c.fillStyle = '#06060e';
        c.fillRect(0, 0, W, H);

        const type = enemy.type || 'goblin';
        const cx = W / 2;

        switch (type) {
            case 'goblin': {
                // голова
                c.fillStyle = '#4a7a2a';
                c.beginPath(); c.arc(cx, 42, 18, 0, Math.PI * 2); c.fill();
                // уши
                c.beginPath(); c.arc(cx - 17, 38, 7, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 17, 38, 7, 0, Math.PI * 2); c.fill();
                // глаза
                c.fillStyle = '#ff4400';
                c.beginPath(); c.arc(cx - 6, 40, 4, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 6, 40, 4, 0, Math.PI * 2); c.fill();
                c.fillStyle = '#000';
                c.beginPath(); c.arc(cx - 6, 40, 1.5, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 6, 40, 1.5, 0, Math.PI * 2); c.fill();
                // нос
                c.fillStyle = '#3a6a1a';
                c.beginPath(); c.ellipse(cx, 47, 3, 2.5, 0, 0, Math.PI * 2); c.fill();
                // зубы
                c.fillStyle = '#f0e890';
                c.fillRect(cx - 6, 52, 4, 5);
                c.fillRect(cx + 2, 52, 4, 5);
                // тело
                c.fillStyle = '#3a6018';
                c.fillRect(cx - 12, 60, 24, 22);
                break;
            }
            case 'slime': {
                c.fillStyle = '#30c060';
                c.beginPath(); c.ellipse(cx, 62, 28, 22, 0, 0, Math.PI * 2); c.fill();
                // пузырьки
                c.fillStyle = '#50e880';
                c.beginPath(); c.arc(cx - 8, 55, 6, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 6, 52, 4, 0, Math.PI * 2); c.fill();
                // глаза
                c.fillStyle = '#fff';
                c.beginPath(); c.arc(cx - 7, 62, 5, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 7, 62, 5, 0, Math.PI * 2); c.fill();
                c.fillStyle = '#000';
                c.beginPath(); c.arc(cx - 7, 62, 2.5, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 7, 62, 2.5, 0, Math.PI * 2); c.fill();
                break;
            }
            case 'bat': {
                // крылья
                c.fillStyle = '#3a1a4a';
                c.beginPath(); c.moveTo(cx, 50); c.lineTo(cx - 40, 30); c.lineTo(cx - 30, 60); c.fill();
                c.beginPath(); c.moveTo(cx, 50); c.lineTo(cx + 40, 30); c.lineTo(cx + 30, 60); c.fill();
                // тело
                c.fillStyle = '#2a1a3a';
                c.beginPath(); c.ellipse(cx, 55, 14, 18, 0, 0, Math.PI * 2); c.fill();
                // голова
                c.beginPath(); c.arc(cx, 38, 12, 0, Math.PI * 2); c.fill();
                // уши
                c.beginPath(); c.moveTo(cx - 9, 30); c.lineTo(cx - 14, 14); c.lineTo(cx - 2, 28); c.fill();
                c.beginPath(); c.moveTo(cx + 9, 30); c.lineTo(cx + 14, 14); c.lineTo(cx + 2, 28); c.fill();
                // глаза
                c.fillStyle = '#ff2222'; c.shadowColor = '#ff0000'; c.shadowBlur = 6;
                c.beginPath(); c.arc(cx - 5, 37, 3, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 5, 37, 3, 0, Math.PI * 2); c.fill();
                c.shadowBlur = 0;
                break;
            }
            case 'wolf': {
                // туловище
                c.fillStyle = '#606060';
                c.beginPath(); c.ellipse(cx, 68, 22, 14, 0, 0, Math.PI * 2); c.fill();
                // голова
                c.beginPath(); c.ellipse(cx - 6, 44, 16, 13, -0.3, 0, Math.PI * 2); c.fill();
                // морда
                c.fillStyle = '#888';
                c.beginPath(); c.ellipse(cx - 18, 48, 9, 6, -0.4, 0, Math.PI * 2); c.fill();
                // уши
                c.fillStyle = '#505050';
                c.beginPath(); c.moveTo(cx - 4, 34); c.lineTo(cx - 12, 20); c.lineTo(cx + 2, 32); c.fill();
                c.beginPath(); c.moveTo(cx + 4, 34); c.lineTo(cx + 10, 20); c.lineTo(cx + 8, 33); c.fill();
                // глаза
                c.fillStyle = '#ffaa00';
                c.beginPath(); c.arc(cx - 9, 42, 3, 0, Math.PI * 2); c.fill();
                c.fillStyle = '#000';
                c.beginPath(); c.arc(cx - 9, 42, 1.5, 0, Math.PI * 2); c.fill();
                // нос
                c.fillStyle = '#222';
                c.beginPath(); c.ellipse(cx - 22, 47, 4, 2.5, 0, 0, Math.PI * 2); c.fill();
                break;
            }
            case 'spider': {
                // тело
                c.fillStyle = '#2a1a0a';
                c.beginPath(); c.ellipse(cx, 60, 16, 20, 0, 0, Math.PI * 2); c.fill();
                // голова
                c.beginPath(); c.arc(cx, 38, 12, 0, Math.PI * 2); c.fill();
                // ноги (8 штук)
                c.strokeStyle = '#1a0a00'; c.lineWidth = 2.5;
                [[-1, -35, -1, -55], [1, -30, 1, -50], [-1, -20, -1, -42], [1, -15, 1, -38]].forEach(([sx, sy, ex, ey], i) => {
                    const side = i % 2 === 0 ? -1 : 1;
                    c.beginPath(); c.moveTo(cx + side * 15, 58); c.lineTo(cx + side * (15 + Math.abs(sx) * 18), 58 + sy); c.stroke();
                    c.beginPath(); c.moveTo(cx + side * 15, 65); c.lineTo(cx + side * (15 + Math.abs(sx) * 18), 65 + sy + 10); c.stroke();
                });
                // глаза
                c.fillStyle = '#ff4400';
                for (let i = 0; i < 4; i++) {
                    c.beginPath(); c.arc(cx - 9 + i * 6, 36, 2, 0, Math.PI * 2); c.fill();
                }
                break;
            }
            case 'bandit': {
                // тело
                c.fillStyle = '#3a3028';
                c.fillRect(cx - 13, 58, 26, 24);
                // голова
                c.fillStyle = '#c8a078';
                c.beginPath(); c.arc(cx, 42, 14, 0, Math.PI * 2); c.fill();
                // маска/повязка
                c.fillStyle = '#1a1010';
                c.fillRect(cx - 12, 38, 24, 8);
                // шляпа
                c.fillStyle = '#2a2018';
                c.fillRect(cx - 16, 26, 32, 4);
                c.fillRect(cx - 11, 16, 22, 14);
                // глаза
                c.fillStyle = '#cc8800';
                c.beginPath(); c.arc(cx - 5, 42, 2.5, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 5, 42, 2.5, 0, Math.PI * 2); c.fill();
                // кинжал
                c.strokeStyle = '#aaa'; c.lineWidth = 2;
                c.beginPath(); c.moveTo(cx + 18, 58); c.lineTo(cx + 18, 82); c.stroke();
                c.fillStyle = '#6a5030';
                c.fillRect(cx + 15, 58, 6, 5);
                break;
            }
            case 'skeleton': {
                // кости тела
                c.fillStyle = '#d0c8a0';
                c.fillRect(cx - 8, 58, 16, 28);
                c.fillStyle = '#e8e0b8';
                c.fillRect(cx - 3, 62, 6, 5);
                c.fillRect(cx - 3, 71, 6, 5);
                c.fillRect(cx - 3, 80, 6, 5);
                // руки-кости
                c.fillRect(cx - 20, 62, 8, 18);
                c.fillRect(cx + 12, 62, 8, 18);
                // череп
                c.beginPath(); c.arc(cx, 40, 16, 0, Math.PI * 2); c.fill();
                // глазницы
                c.fillStyle = '#1a1a0a';
                c.beginPath(); c.arc(cx - 6, 38, 5, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 6, 38, 5, 0, Math.PI * 2); c.fill();
                // нос
                c.beginPath(); c.arc(cx, 46, 2, 0, Math.PI * 2); c.fill();
                // зубы
                c.fillStyle = '#d0c8a0';
                for (let i = 0; i < 5; i++) c.fillRect(cx - 9 + i * 5, 50, 4, 4);
                break;
            }
            case 'orc': {
                // тело
                c.fillStyle = '#3a5a1a';
                c.fillRect(cx - 18, 56, 36, 30);
                // плечи
                c.beginPath(); c.arc(cx - 18, 58, 10, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 18, 58, 10, 0, Math.PI * 2); c.fill();
                // голова
                c.fillStyle = '#4a6a28';
                c.beginPath(); c.arc(cx, 38, 18, 0, Math.PI * 2); c.fill();
                // клыки
                c.fillStyle = '#e8e0a0';
                c.fillRect(cx - 8, 50, 5, 8);
                c.fillRect(cx + 3, 50, 5, 8);
                // глаза
                c.fillStyle = '#ff6600';
                c.beginPath(); c.arc(cx - 6, 36, 5, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 6, 36, 5, 0, Math.PI * 2); c.fill();
                c.fillStyle = '#000';
                c.beginPath(); c.arc(cx - 6, 36, 2, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 6, 36, 2, 0, Math.PI * 2); c.fill();
                break;
            }
            case 'zombie': {
                // тело (гниющее)
                c.fillStyle = '#3a5a28';
                c.fillRect(cx - 13, 58, 26, 28);
                // пятна гнили
                c.fillStyle = '#2a4018';
                c.beginPath(); c.arc(cx - 4, 65, 5, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 5, 74, 4, 0, Math.PI * 2); c.fill();
                // голова
                c.fillStyle = '#7a9a5a';
                c.beginPath(); c.arc(cx, 42, 15, 0, Math.PI * 2); c.fill();
                // раны
                c.fillStyle = '#4a0a0a';
                c.beginPath(); c.arc(cx + 6, 36, 4, 0, Math.PI * 2); c.fill();
                // глаза мёртвые
                c.fillStyle = '#b8c8a0';
                c.beginPath(); c.arc(cx - 5, 40, 4, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 5, 40, 4, 0, Math.PI * 2); c.fill();
                c.fillStyle = '#888a70';
                c.beginPath(); c.arc(cx - 5, 40, 2, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 5, 40, 2, 0, Math.PI * 2); c.fill();
                // рот открыт
                c.fillStyle = '#1a0a08';
                c.beginPath(); c.arc(cx, 48, 5, 0.1 * Math.PI, 0.9 * Math.PI); c.fill();
                break;
            }
            case 'troll': {
                // огромное тело
                c.fillStyle = '#4a6a30';
                c.beginPath(); c.ellipse(cx, 68, 28, 22, 0, 0, Math.PI * 2); c.fill();
                // плечи широкие
                c.beginPath(); c.arc(cx - 26, 60, 14, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 26, 60, 14, 0, Math.PI * 2); c.fill();
                // голова
                c.beginPath(); c.arc(cx, 38, 20, 0, Math.PI * 2); c.fill();
                // нос крупный
                c.fillStyle = '#3a5a20';
                c.beginPath(); c.ellipse(cx, 40, 7, 8, 0, 0, Math.PI * 2); c.fill();
                // глаза маленькие
                c.fillStyle = '#ff8800';
                c.beginPath(); c.arc(cx - 8, 34, 4, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 8, 34, 4, 0, Math.PI * 2); c.fill();
                break;
            }
            case 'yeti': {
                // белая шерсть
                c.fillStyle = '#d8e0e8';
                c.beginPath(); c.ellipse(cx, 66, 26, 22, 0, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx - 24, 58, 13, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 24, 58, 13, 0, Math.PI * 2); c.fill();
                // голова
                c.beginPath(); c.arc(cx, 38, 20, 0, Math.PI * 2); c.fill();
                // тёмная морда
                c.fillStyle = '#b0b8c0';
                c.beginPath(); c.ellipse(cx, 44, 12, 10, 0, 0, Math.PI * 2); c.fill();
                // нос чёрный
                c.fillStyle = '#202830';
                c.beginPath(); c.ellipse(cx, 42, 5, 3.5, 0, 0, Math.PI * 2); c.fill();
                // глаза
                c.fillStyle = '#88aacc';
                c.beginPath(); c.arc(cx - 9, 33, 4.5, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 9, 33, 4.5, 0, Math.PI * 2); c.fill();
                c.fillStyle = '#000';
                c.beginPath(); c.arc(cx - 9, 33, 2, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 9, 33, 2, 0, Math.PI * 2); c.fill();
                break;
            }
            case 'witch': {
                // тело в чёрном
                c.fillStyle = '#181820';
                c.fillRect(cx - 13, 58, 26, 28);
                // голова
                c.fillStyle = '#b0a080';
                c.beginPath(); c.arc(cx, 42, 14, 0, Math.PI * 2); c.fill();
                // шляпа
                c.fillStyle = '#101018';
                c.fillRect(cx - 18, 26, 36, 5);
                c.fillRect(cx - 10, 10, 20, 18);
                // зелёные глаза
                c.fillStyle = '#22cc44'; c.shadowColor = '#00ff44'; c.shadowBlur = 8;
                c.beginPath(); c.arc(cx - 5, 40, 3.5, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 5, 40, 3.5, 0, Math.PI * 2); c.fill();
                c.shadowBlur = 0;
                // нос крючковатый
                c.fillStyle = '#988060';
                c.beginPath(); c.moveTo(cx, 46); c.lineTo(cx - 5, 54); c.lineTo(cx + 2, 53); c.fill();
                break;
            }
            case 'golem': {
                // каменное тело
                c.fillStyle = '#606870';
                c.fillRect(cx - 20, 54, 40, 32);
                // детали камня
                c.fillStyle = '#505860';
                c.fillRect(cx - 18, 60, 14, 10);
                c.fillRect(cx + 4, 64, 14, 8);
                // плечи кубические
                c.fillRect(cx - 28, 50, 14, 14);
                c.fillRect(cx + 14, 50, 14, 14);
                // голова
                c.fillStyle = '#686e78';
                c.fillRect(cx - 16, 24, 32, 32);
                // кристалл в груди
                c.fillStyle = '#22aaff'; c.shadowColor = '#0088ff'; c.shadowBlur = 10;
                c.beginPath(); c.moveTo(cx, 58); c.lineTo(cx - 7, 68); c.lineTo(cx, 76); c.lineTo(cx + 7, 68); c.fill();
                c.shadowBlur = 0;
                // глаза-кристаллы
                c.fillStyle = '#44ccff'; c.shadowColor = '#0088ff'; c.shadowBlur = 8;
                c.fillRect(cx - 10, 32, 8, 6);
                c.fillRect(cx + 2, 32, 8, 6);
                c.shadowBlur = 0;
                break;
            }
            case 'dragon': {
                // туловище
                c.fillStyle = '#8a1a1a';
                c.beginPath(); c.ellipse(cx + 4, 66, 26, 18, 0.2, 0, Math.PI * 2); c.fill();
                // шея
                c.fillStyle = '#9a2020';
                c.fillRect(cx - 6, 44, 16, 24);
                // голова
                c.beginPath(); c.ellipse(cx - 2, 36, 18, 14, -0.3, 0, Math.PI * 2); c.fill();
                // морда
                c.beginPath(); c.ellipse(cx - 16, 40, 10, 7, -0.4, 0, Math.PI * 2); c.fill();
                // рога
                c.fillStyle = '#6a1010';
                c.beginPath(); c.moveTo(cx + 6, 26); c.lineTo(cx + 14, 8); c.lineTo(cx + 10, 28); c.fill();
                c.beginPath(); c.moveTo(cx - 2, 24); c.lineTo(cx + 4, 8); c.lineTo(cx + 2, 26); c.fill();
                // глаза огненные
                c.fillStyle = '#ffaa00'; c.shadowColor = '#ff6600'; c.shadowBlur = 10;
                c.beginPath(); c.arc(cx - 4, 34, 5, 0, Math.PI * 2); c.fill();
                c.shadowBlur = 0;
                // крыло
                c.fillStyle = '#6a1010';
                c.beginPath(); c.moveTo(cx + 18, 52); c.lineTo(cx + 42, 26); c.lineTo(cx + 40, 60); c.lineTo(cx + 22, 68); c.fill();
                break;
            }
            case 'lich': {
                // мантия
                c.fillStyle = '#0e0818';
                c.beginPath(); c.moveTo(cx - 20, 58); c.lineTo(cx - 28, 96); c.lineTo(cx + 28, 96); c.lineTo(cx + 20, 58); c.fill();
                c.fillRect(cx - 13, 56, 26, 8);
                // руки-кости
                c.fillStyle = '#c8c0a8';
                c.fillRect(cx - 22, 62, 6, 20);
                c.fillRect(cx + 16, 62, 6, 20);
                // череп
                c.beginPath(); c.arc(cx, 38, 17, 0, Math.PI * 2); c.fill();
                // глазницы с огнём
                c.fillStyle = '#0a0818';
                c.beginPath(); c.arc(cx - 6, 36, 6, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 6, 36, 6, 0, Math.PI * 2); c.fill();
                // пурпурный огонь в глазах
                c.fillStyle = '#cc22ff'; c.shadowColor = '#aa00ff'; c.shadowBlur = 12;
                c.beginPath(); c.arc(cx - 6, 36, 3.5, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.arc(cx + 6, 36, 3.5, 0, Math.PI * 2); c.fill();
                c.shadowBlur = 0;
                // зубы черепа
                c.fillStyle = '#c8c0a8';
                for (let i = 0; i < 5; i++) c.fillRect(cx - 9 + i * 5, 48, 4, 5);
                // корона тёмная
                c.fillStyle = '#3a0060';
                c.fillRect(cx - 14, 18, 28, 6);
                [cx - 12, cx - 4, cx + 4, cx + 12].forEach(kx => {
                    c.fillRect(kx - 2, 10, 5, 10);
                });
                // самоцветы
                c.fillStyle = '#cc22ff';
                [cx - 10, cx + 2, cx + 14].forEach(kx => {
                    c.beginPath(); c.arc(kx, 14, 2.5, 0, Math.PI * 2); c.fill();
                });
                break;
            }
            case 'ghost': {
                // Полупрозрачная фигура призрака
                c.globalAlpha = 0.75;
                // Свечение
                const grd = c.createRadialGradient(cx, 55, 0, cx, 55, 40);
                grd.addColorStop(0, 'rgba(140,200,255,0.5)');
                grd.addColorStop(1, 'rgba(80,140,255,0)');
                c.fillStyle = grd;
                c.beginPath(); c.arc(cx, 55, 40, 0, Math.PI * 2); c.fill();
                // Мантия-тело
                c.fillStyle = 'rgba(160,210,255,0.8)';
                c.beginPath();
                c.moveTo(cx - 14, 46); c.lineTo(cx - 18, 85); c.lineTo(cx - 8, 78);
                c.lineTo(cx, 85); c.lineTo(cx + 8, 78); c.lineTo(cx + 18, 85); c.lineTo(cx + 14, 46);
                c.closePath(); c.fill();
                // Голова
                c.fillStyle = 'rgba(200,230,255,0.9)';
                c.beginPath(); c.arc(cx, 36, 16, 0, Math.PI * 2); c.fill();
                // Светящиеся глаза
                c.fillStyle = '#88ccff'; c.shadowColor = '#66aaff'; c.shadowBlur = 12;
                c.beginPath(); c.ellipse(cx - 5, 35, 4.5, 3, 0, 0, Math.PI * 2); c.fill();
                c.beginPath(); c.ellipse(cx + 5, 35, 4.5, 3, 0, 0, Math.PI * 2); c.fill();
                c.shadowBlur = 0;
                c.globalAlpha = 1;
                break;
            }
            case 'wyvern': {
                // Виверна — небольшой дракон с крыльями
                // Крыло слева
                c.fillStyle = '#1a5028';
                c.beginPath(); c.moveTo(cx - 8, 52); c.lineTo(cx - 42, 30); c.lineTo(cx - 30, 60); c.lineTo(cx - 10, 68); c.fill();
                // Туловище
                c.fillStyle = '#2a6032';
                c.beginPath(); c.ellipse(cx + 2, 68, 22, 16, 0.15, 0, Math.PI * 2); c.fill();
                // Шея
                c.fillRect(cx - 5, 48, 14, 22);
                // Голова
                c.beginPath(); c.ellipse(cx, 36, 14, 11, -0.2, 0, Math.PI * 2); c.fill();
                // Морда
                c.beginPath(); c.ellipse(cx - 14, 40, 8, 5, -0.3, 0, Math.PI * 2); c.fill();
                // Хвост
                c.strokeStyle = '#2a6032'; c.lineWidth = 6;
                c.beginPath(); c.moveTo(cx + 20, 68); c.quadraticCurveTo(cx + 38, 72, cx + 40, 88); c.stroke();
                // Рог/гребень
                c.fillStyle = '#1a4020';
                c.beginPath(); c.moveTo(cx + 4, 28); c.lineTo(cx + 10, 14); c.lineTo(cx + 8, 30); c.fill();
                c.beginPath(); c.moveTo(cx - 2, 26); c.lineTo(cx + 2, 12); c.lineTo(cx + 2, 28); c.fill();
                // Глаза
                c.fillStyle = '#eecc00'; c.shadowColor = '#ffaa00'; c.shadowBlur = 8;
                c.beginPath(); c.arc(cx - 4, 35, 4, 0, Math.PI * 2); c.fill();
                c.shadowBlur = 0;
                break;
            }
            case 'chaos_lord': {
                // Тёмный аморфный силуэт — тело
                c.fillStyle = '#0d0018';
                c.beginPath(); c.ellipse(cx, 68, 26, 22, 0, 0, Math.PI * 2); c.fill();
                // Верхняя часть — голова-туман
                c.fillStyle = '#1a0028';
                c.beginPath(); c.ellipse(cx, 40, 22, 25, 0, 0, Math.PI * 2); c.fill();
                // Корона из тьмы
                c.fillStyle = '#3a0055';
                for (let i = 0; i < 5; i++) {
                    const px2 = cx - 20 + i * 10, spiky = i % 2 === 0 ? 14 : 8;
                    c.beginPath(); c.moveTo(px2 - 5, 26); c.lineTo(px2, 26 - spiky); c.lineTo(px2 + 5, 26); c.fill();
                }
                c.fillRect(cx - 22, 23, 44, 6);
                // Множество глаз
                const eyes = [[cx - 9, 38], [cx + 9, 38], [cx - 3, 45], [cx + 3, 45], [cx, 32]];
                eyes.forEach(([ex, ey]) => {
                    c.fillStyle = '#cc00ff'; c.shadowColor = '#ff00ff'; c.shadowBlur = 6;
                    c.beginPath(); c.arc(ex, ey, 2.5, 0, Math.PI * 2); c.fill();
                });
                c.shadowBlur = 0;
                // Щупальца внизу
                c.strokeStyle = '#1a0030'; c.lineWidth = 4;
                for (let i = -2; i <= 2; i++) {
                    c.beginPath();
                    c.moveTo(cx + i * 8, 82);
                    c.quadraticCurveTo(cx + i * 12, 92, cx + i * 6 + Math.sin(i) * 4, 100);
                    c.stroke();
                }
                break;
            }
        }
    },
};
