Destiny V3

Deadshot.io Cheat (AIMBOT, WALL HACKS) -- discord.gg/783Ve3Fd

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да инсталирате разширение, като например Tampermonkey .

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name         Destiny V3
// @namespace    http://tampermonkey.net/
// @version      3.0
// @description  Deadshot.io Cheat (AIMBOT, WALL HACKS) -- discord.gg/783Ve3Fd
// @match        *://*deadshot.io/*
// @grant        none
// @run-at       document-start
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';

    // =====================================================================
    // CONFIG
    // =====================================================================
    const STORAGE_KEY = 'destiny_v2_config';

    const defaultConfig = {
        // Aimbot
        aimbotEnabled: true,
        aimKey: 'RightClick',
        aimSmooth: 1.5,
        lockDist: 80,
        hitbox: 0,
        priority: 1,
        targetLock: false,
        predictionEnabled: true,
        predictionStrength: 2.0,
        velocityTracking: true,
        visibilityCheck: true,

        // TriggerBot
        triggerBot: false,
        triggerDelay: 50,
        triggerRadius: 12,

        // ESP / Visuals
        espEnabled: true,
        showDistance: true,
        showTracers: false,
        espThickness: 2,
        showFov: false,
        fov: 300,
        fovGradient: true,
        showCrosshair: false,
        showFPS: true,

        // Program detection
        autoDetect: true,
        manualTargetID: -1,

        // Combat
        crouchSpam: false,
        crouchSpamSpeed: 80,
        autoStrafe: false,
        autoStrafeSpeed: 100,

        // Hacks
        fovHack: false,
        fovHackScale: 1.0,

        // Misc
        antiAFK: false,
        performanceMode: false,
        blockFullscreen: false,
        debugOverlay: true,

        // Radar & Indicators
        radarEnabled: true,
        radarSize: 120,
        radarRange: 80,
        offScreenIndicators: true,

        // UI
        menuVisible: true,
        menuKey: 'Insert',
        accentColor: '#a855f7',
        x: 60,
        y: 60,
    };

    let config = { ...defaultConfig };
    try {
        const saved = localStorage.getItem(STORAGE_KEY);
        if (saved) config = { ...config, ...JSON.parse(saved) };
    } catch (e) {}

    let _saveTimer = null;
    function save() {
        if (_saveTimer) clearTimeout(_saveTimer);
        _saveTimer = setTimeout(saveImmediate, 200);
    }
    function saveImmediate() {
        if (_saveTimer) { clearTimeout(_saveTimer); _saveTimer = null; }
        try { localStorage.setItem(STORAGE_KEY, JSON.stringify(config)); } catch (e) {}
    }

    if (config.blockFullscreen) {
        const block = () => Promise.resolve();
        ['requestFullscreen', 'webkitRequestFullscreen', 'mozRequestFullScreen', 'msRequestFullscreen']
            .forEach(fn => { if (Element.prototype[fn]) Element.prototype[fn] = block; });
    }

    // =====================================================================
    // STATE
    // =====================================================================
    const state = {
        programCounter: 0,
        vpMatrices: [],
        matricesByProgram: new Map(),
        programScores: new Map(),
        detectedTargetID: -1,
        modelMatrices: [],
        lockedTarget: null,

        lastPositions: new Map(),
        velocities: new Map(),
        deadPositions: new Map(),

        lastMouseMove: Date.now(),
        lastTriggerFire: 0,
        lastCrouchToggle: 0,
        crouchDown: false,
        lastStrafeToggle: 0,
        strafeRight: false,

        input: { left: false, right: false, shift: false, alt: false },
        pointerLocked: false,
        rebindingField: null,
        keyJustRebound: false,

        accX: 0,
        accY: 0,

        fps: 0,
        frameCount: 0,
        lastFPSUpdate: Date.now(),
        totalTargets: 0,

        overlayCtx: null,
        baselineVP0: 0,
        currentZoom: 1.0,
    };

    // =====================================================================
    // INPUT
    // =====================================================================
    function aimKeyHeld() {
        switch (config.aimKey) {
            case 'RightClick': return state.input.right;
            case 'LeftClick':  return state.input.left;
            case 'ShiftLeft':  return state.input.shift;
            case 'AltLeft':    return state.input.alt;
            case 'Always':     return true;
            default:           return state.input.right;
        }
    }

    document.addEventListener('keydown', (e) => {
        if (state.rebindingField) {
            const field = state.rebindingField;
            state.rebindingField = null;
            state.keyJustRebound = true;
            config[field] = e.code;
            saveImmediate();
            refreshGUI();
            e.preventDefault();
            e.stopImmediatePropagation();
            return;
        }
        if (e.code === config.menuKey) {
            config.menuVisible = !config.menuVisible;
            const el = document.getElementById('d2-root');
            if (el) el.style.display = config.menuVisible ? 'flex' : 'none';
            saveImmediate();
            e.preventDefault();
            e.stopImmediatePropagation();
        }
        if (e.code === 'ArrowRight') {
            config.autoDetect = false;
            config.manualTargetID++;
            state.modelMatrices = [];
            save();
            refreshTargetBadge();
            e.preventDefault();
            e.stopImmediatePropagation();
        }
        if (e.code === 'ArrowLeft') {
            config.autoDetect = false;
            config.manualTargetID--;
            state.modelMatrices = [];
            save();
            refreshTargetBadge();
            e.preventDefault();
            e.stopImmediatePropagation();
        }
        if (e.code === 'ShiftLeft') state.input.shift = true;
        if (e.code === 'AltLeft')   state.input.alt = true;
    }, true);

    document.addEventListener('keyup', (e) => {
        if (e.code === 'ShiftLeft') state.input.shift = false;
        if (e.code === 'AltLeft')   state.input.alt = false;
    }, true);

    const onMouseDown = e => {
        if (e.button === 0) state.input.left = true;
        if (e.button === 2) state.input.right = true;
    };
    const onMouseUp = e => {
        if (e.button === 0) state.input.left = false;
        if (e.button === 2) state.input.right = false;
    };
    document.addEventListener('mousedown', onMouseDown, true);
    document.addEventListener('mouseup', onMouseUp, true);
    window.addEventListener('mousedown', onMouseDown);
    window.addEventListener('mouseup', onMouseUp);

    document.addEventListener('pointerlockchange', () => {
        const wasLocked = state.pointerLocked;
        state.pointerLocked = !!document.pointerLockElement;
        if (state.pointerLocked && !wasLocked) {
            state.lastPositions.clear();
            state.velocities.clear();
            state.deadPositions.clear();
            state.lockedTarget = null;
        }
    }, true);

    // Browser mouse input: dispatchEvent with Object.defineProperty for movementX/Y
    function mouseMove(dx, dy) {
        const evt = new MouseEvent('mousemove', { bubbles: true, cancelable: true });
        Object.defineProperty(evt, 'movementX', { value: dx });
        Object.defineProperty(evt, 'movementY', { value: dy });
        const canvas = document.pointerLockElement || document.querySelector('canvas');
        if (canvas) canvas.dispatchEvent(evt);
        const evt2 = new MouseEvent('mousemove', { bubbles: true, cancelable: true });
        Object.defineProperty(evt2, 'movementX', { value: dx });
        Object.defineProperty(evt2, 'movementY', { value: dy });
        window.dispatchEvent(evt2);
    }

    function mouseClick(isDown) {
        window.dispatchEvent(new MouseEvent(isDown ? 'mousedown' : 'mouseup', { button: 0, bubbles: true }));
    }

    // =====================================================================
    // WEBGL HOOK
    // =====================================================================
    const originalGetContext = HTMLCanvasElement.prototype.getContext;
    const proxyCache = new WeakMap();
    const programMap = new WeakMap();

    function spoof(fake, real) {
        Object.defineProperty(fake, 'name', { value: real.name, configurable: true });
        Object.defineProperty(fake, 'toString', { value: () => real.toString(), configurable: true });
        return fake;
    }

    function currentTargetID() {
        return config.autoDetect ? state.detectedTargetID : config.manualTargetID;
    }

    HTMLCanvasElement.prototype.getContext = spoof(function (type, options) {
        const ctx = originalGetContext.call(this, type, options);
        if (!ctx || (type !== 'webgl' && type !== 'webgl2')) return ctx;
        if (proxyCache.has(ctx)) return proxyCache.get(ctx);

        const handler = {
            get(target, prop) {
                const val = target[prop];
                if (typeof val !== 'function') return val;

                if (prop === 'uniformMatrix4fv') {
                    return function (loc, transpose, value) {
                        if (value && value.length === 16) {
                            if (Math.abs(value[11] + 1) < 0.1 && Math.abs(value[15]) < 0.1) {
                                if (state.vpMatrices.length > 3) state.vpMatrices.shift();
                                state.vpMatrices.push(new Float32Array(value));

                                if (config.fovHack && config.fovHackScale !== 1.0) {
                                    const modified = new Float32Array(value);
                                    modified[0] *= config.fovHackScale;
                                    modified[5] *= config.fovHackScale;
                                    arguments[2] = modified;
                                }
                            }
                            else if (Math.abs(value[3]) < 1e-6 &&
                                     Math.abs(value[7]) < 1e-6 &&
                                     Math.abs(value[15] - 1) < 1e-6) {
                                const gl = target;
                                const pid = programMap.get(gl.getParameter(gl.CURRENT_PROGRAM));
                                if (pid !== undefined) {
                                    let arr = state.matricesByProgram.get(pid);
                                    if (!arr) { arr = []; state.matricesByProgram.set(pid, arr); }
                                    if (arr.length < 64) arr.push(new Float32Array(value));
                                }
                            }
                        }
                        return val.apply(target, arguments);
                    };
                }
                if (prop === 'useProgram') {
                    return function (program) {
                        if (program && !programMap.has(program)) {
                            programMap.set(program, state.programCounter++);
                        }
                        return val.apply(target, arguments);
                    };
                }
                if (prop === 'drawElements') {
                    return function () {
                        const gl = target;
                        const pid = programMap.get(gl.getParameter(gl.CURRENT_PROGRAM));
                        const tgt = currentTargetID();
                        const espActive = config.aimbotEnabled && config.espEnabled && pid === tgt && tgt >= 0;
                        if (espActive) gl.disable(gl.DEPTH_TEST);
                        const res = val.apply(target, arguments);
                        if (espActive) gl.enable(gl.DEPTH_TEST);
                        return res;
                    };
                }
                return val.bind(target);
            },
        };
        const proxied = new Proxy(ctx, handler);
        proxyCache.set(ctx, proxied);
        return proxied;
    }, originalGetContext);

    // =====================================================================
    // AUTO-DETECT
    // =====================================================================
    function scoreProgramsThisFrame() {
        if (!config.autoDetect) return;
        const now = Date.now();
        for (const [pid, mats] of state.matricesByProgram.entries()) {
            const n = mats.length;
            if (n < 2 || n > 40) { decay(pid, now); continue; }
            let sumX = 0, sumZ = 0, minY = Infinity, maxY = -Infinity;
            for (let i = 0; i < n; i++) {
                const m = mats[i];
                sumX += m[12]; sumZ += m[14];
                if (m[13] < minY) minY = m[13];
                if (m[13] > maxY) maxY = m[13];
            }
            const meanX = sumX / n, meanZ = sumZ / n;
            let varXZ = 0;
            for (let i = 0; i < n; i++) {
                const m = mats[i];
                const dx = m[12] - meanX, dz = m[14] - meanZ;
                varXZ += dx * dx + dz * dz;
            }
            varXZ /= n;
            const spread = Math.sqrt(varXZ);
            if (spread < 0.8) { decay(pid, now); continue; }
            if (maxY - minY > 200) { decay(pid, now); continue; }
            const countScore = n <= 3 ? n / 3 : n <= 12 ? 1.0 : Math.max(0, 1 - (n - 12) / 28);
            const spreadScore = Math.min(1, spread / 10);
            const frameScore = countScore * 0.6 + spreadScore * 0.4;
            const prev = state.programScores.get(pid) || { score: 0, lastSeen: 0 };
            const alpha = 0.25;
            prev.score = prev.score * (1 - alpha) + frameScore * alpha;
            prev.lastSeen = now;
            prev.matrixCount = n;
            prev.spread = spread;
            state.programScores.set(pid, prev);
        }
        for (const [pid, data] of state.programScores.entries()) {
            if (!state.matricesByProgram.has(pid)) decay(pid, now);
            if (now - data.lastSeen > 5000) state.programScores.delete(pid);
        }
        let best = -1, bestScore = 0.15;
        for (const [pid, data] of state.programScores.entries()) {
            if (data.score > bestScore) { best = pid; bestScore = data.score; }
        }
        if (best !== state.detectedTargetID) {
            state.detectedTargetID = best;
            refreshTargetBadge();
        }
    }

    function decay(pid, now) {
        const prev = state.programScores.get(pid);
        if (!prev) return;
        prev.score *= 0.85;
        prev.lastSeen = now;
    }

    // =====================================================================
    // CANVAS & UTILITIES
    // =====================================================================
    let overlayCanvas = null;

    function setupCanvas() {
        if (overlayCanvas) return;
        overlayCanvas = document.createElement('canvas');
        overlayCanvas.id = 'd2-overlay';
        overlayCanvas.style.cssText = 'position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:2147483645;pointer-events:none;';
        (document.body || document.documentElement).appendChild(overlayCanvas);

        const resize = () => {
            overlayCanvas.width = window.innerWidth;
            overlayCanvas.height = window.innerHeight;
        };
        window.addEventListener('resize', resize);
        document.addEventListener('fullscreenchange', () => setTimeout(resize, 50));
        document.addEventListener('webkitfullscreenchange', () => setTimeout(resize, 50));
        resize();

        (function loop() { render(); requestAnimationFrame(loop); })();
        setInterval(() => { if (!document.getElementById('d2-root')) createGUI(); }, 2000);
    }

    function getBoneOffset() {
        return config.hitbox === 0 ? 2.15 : config.hitbox === 1 ? 1.5 : 0.8;
    }

    function calculateVelocity(posKey, pos) {
        const last = state.lastPositions.get(posKey);
        const now = Date.now();
        if (last) {
            const dt = (now - last.time) / 1000;
            if (dt > 0.001 && dt < 0.5) {
                const vx = (pos.x - last.x) / dt;
                const vy = (pos.y - last.y) / dt;
                const vz = (pos.z - last.z) / dt;
                const prev = state.velocities.get(posKey);
                const blend = 0.85;
                if (prev) {
                    state.velocities.set(posKey, {
                        vx: vx * blend + prev.vx * (1 - blend),
                        vy: vy * blend + prev.vy * (1 - blend),
                        vz: vz * blend + prev.vz * (1 - blend),
                        time: now,
                    });
                } else {
                    state.velocities.set(posKey, { vx, vy, vz, time: now });
                }
            }
        }
        state.lastPositions.set(posKey, { x: pos.x, y: pos.y, z: pos.z, time: now });
    }

    function project(vp, x, y, z, w, h) {
        const X = x*vp[0] + y*vp[4] + z*vp[8]  + vp[12];
        const Y = x*vp[1] + y*vp[5] + z*vp[9]  + vp[13];
        const W = x*vp[3] + y*vp[7] + z*vp[11] + vp[15];
        if (W < 0.1) return null;
        return { x: (X/W + 1) * w * 0.5, y: (-Y/W + 1) * h * 0.5, w: W };
    }

    function easeOutQuart(x) { return 1 - Math.pow(1 - x, 4); }
    function easeInOutCubic(x) { return x < 0.5 ? 4*x*x*x : 1 - Math.pow(-2*x+2, 3) / 2; }

    function applySmoothCurve(value) {
        return value < 0.5 ? 4*value*value*value : 1 - Math.pow(-2*value+2, 3) / 2;
    }

    // =====================================================================
    // RENDER LOOP
    // =====================================================================
    function render() {
        if (!overlayCanvas) return;
        if (!state.overlayCtx) state.overlayCtx = overlayCanvas.getContext('2d');
        const ctx = state.overlayCtx;
        const w = overlayCanvas.width;
        const h = overlayCanvas.height;
        const cx = w / 2, cy = h / 2;
        ctx.clearRect(0, 0, w, h);

        state.frameCount++;
        const now = Date.now();
        if (now - state.lastFPSUpdate > 1000) {
            state.fps = state.frameCount;
            state.frameCount = 0;
            state.lastFPSUpdate = now;
            updateStatusBar();
        }

        scoreProgramsThisFrame();
        const tgt = currentTargetID();
        state.modelMatrices = (tgt >= 0 && state.matricesByProgram.get(tgt)) || [];

        if (config.debugOverlay) {
            ctx.font = '10px monospace';
            let dy = 10;
            const sorted = [...state.programScores.entries()].sort((a,b) => b[1].score - a[1].score);
            for (let i = 0; i < Math.min(sorted.length, 6); i++) {
                const [pid, data] = sorted[i];
                const mats = state.matricesByProgram.get(pid);
                const n = mats ? mats.length : 0;
                ctx.fillStyle = pid === tgt ? '#0f0' : '#888';
                ctx.fillText(`pid:${pid} score:${data.score.toFixed(3)} mats:${n} spread:${(data.spread||0).toFixed(1)}`, 10, dy);
                dy += 12;
            }
        }

        if (config.showFPS) {
            ctx.font = 'bold 14px Segoe UI, system-ui';
            ctx.fillStyle = config.accentColor;
            ctx.fillText(`${state.fps} fps`, 10, 24);
        }

        if (config.debugOverlay) {
            ctx.font = '11px monospace';
            ctx.fillStyle = state.pointerLocked ? '#0f0' : '#f77';
            const keyLbl = aimKeyHeld() ? 'FIRE' : 'idle';
            ctx.fillText(`ptr:${state.pointerLocked?'lock':'free'}  key:${keyLbl}  tgt:${tgt}  mats:${state.modelMatrices.length}  zoom:${state.currentZoom.toFixed(2)}`, 10, h - 10);
        }

        if (config.showCrosshair) {
            const s = 10, g = 4;
            ctx.strokeStyle = config.accentColor;
            ctx.lineWidth = 2;
            ctx.beginPath();
            ctx.moveTo(cx, cy-g-s); ctx.lineTo(cx, cy-g);
            ctx.moveTo(cx, cy+g);   ctx.lineTo(cx, cy+g+s);
            ctx.moveTo(cx-g-s, cy); ctx.lineTo(cx-g, cy);
            ctx.moveTo(cx+g, cy);   ctx.lineTo(cx+g+s, cy);
            ctx.stroke();
            ctx.fillStyle = config.accentColor;
            ctx.fillRect(cx-1, cy-1, 2, 2);
        }

        if (config.showFov) {
            ctx.beginPath();
            ctx.arc(cx, cy, config.fov, 0, Math.PI * 2);
            if (config.fovGradient && !config.performanceMode) {
                const grad = ctx.createRadialGradient(cx, cy, 0, cx, cy, config.fov);
                grad.addColorStop(0, 'transparent');
                grad.addColorStop(0.8, 'transparent');
                grad.addColorStop(1, config.accentColor + '40');
                ctx.fillStyle = grad;
                ctx.fill();
            }
            ctx.strokeStyle = config.accentColor;
            ctx.lineWidth = 1.5;
            ctx.stroke();
        }

        if (state.vpMatrices.length === 0) { clearFrameBuffers(); return; }

        const vp = state.vpMatrices[state.vpMatrices.length - 1];
        let bestTarget = null;
        let bestScore = Infinity;
        let bestLockData = null;
        state.totalTargets = 0;

        const MIN_DIST_SQ = 0.25;
        const processed = [];

        for (let i = 0; i < state.modelMatrices.length; i++) {
            const mat = state.modelMatrices[i];
            const wx = mat[12], wy = mat[13], wz = mat[14];

            let dup = false;
            for (let j = 0; j < processed.length; j++) {
                const p = processed[j];
                const ddx = wx-p.x, ddy = wy-p.y, ddz = wz-p.z;
                if (ddx*ddx+ddy*ddy+ddz*ddz < MIN_DIST_SQ) { dup = true; break; }
            }
            if (dup) continue;
            if (processed.length < 24) processed.push({ x: wx, y: wy, z: wz });

            const posKey = `${Math.round(wx*10)}_${Math.round(wy*10)}_${Math.round(wz*10)}`;
            if (config.velocityTracking && config.predictionEnabled) {
                calculateVelocity(posKey, { x: wx, y: wy, z: wz });
            }

            const boneY = getBoneOffset();
            const head = project(vp, wx, wy + boneY, wz, w, h);
            const foot = project(vp, wx, wy, wz, w, h);
            if (!head || !foot) continue;

            const boxH = foot.y - head.y;
            const boxW = boxH * 0.6;
            if (boxH < 30 || boxH > 400) continue;
            if (boxW < 15 || boxW > 250) continue;
            const aspect = boxW / boxH;
            if (aspect < 0.3 || aspect > 1.0) continue;
            if (head.x < -100 || head.x > w + 100) continue;
            if (head.y < -100 || head.y > h + 100) continue;

            let px = wx, py = wy + boneY, pz = wz;
            if (config.predictionEnabled && config.velocityTracking) {
                const vel = state.velocities.get(posKey);
                if (vel && now - vel.time < 200) {
                    const dt = config.predictionStrength * 0.05;
                    px += vel.vx * dt;
                    py += vel.vy * dt;
                    pz += vel.vz * dt;
                }
            }

            const curVel = state.velocities.get(posKey);
            if (!curVel || Math.abs(curVel.vx) > 0.2 || Math.abs(curVel.vy) > 0.5 || Math.abs(curVel.vz) > 0.2) {
                state.deadPositions.set(posKey, now);
            } else if (!state.deadPositions.has(posKey)) {
                state.deadPositions.set(posKey, now);
            }

            const depthRatio = head.w / (foot.w + 0.001);
            const isOccluded = depthRatio < 0.3 || depthRatio > 3.0;

            const lastMoving = state.deadPositions.get(posKey);
            const velCheck = state.velocities.get(posKey);
            const isCurrentlyStill = velCheck && Math.abs(velCheck.vx) < 0.1 && Math.abs(velCheck.vy) < 0.3 && Math.abs(velCheck.vz) < 0.1;
            const isDead = isCurrentlyStill && lastMoving && (now - lastMoving > 3000);

            state.totalTargets++;
            const dist3D = Math.sqrt(wx*wx + wy*wy + wz*wz);
            const dist2D = Math.hypot(head.x - cx, head.y - cy);

            // ── ESP Drawing ──
            if (config.espEnabled) {
                const inFov = dist2D <= config.fov;
                const bx = head.x - boxW / 2;
                const by = head.y;
                const cornerLen = Math.min(boxW, boxH) * 0.25;
                const alpha = isDead ? '40' : isOccluded ? '60' : 'ff';
                const baseColor = inFov ? config.accentColor : '#888888';
                const color = baseColor + alpha;

                ctx.strokeStyle = color;
                ctx.lineWidth = config.espThickness;
                ctx.beginPath();
                ctx.moveTo(bx, by+cornerLen); ctx.lineTo(bx, by); ctx.lineTo(bx+cornerLen, by);
                ctx.moveTo(bx+boxW-cornerLen, by); ctx.lineTo(bx+boxW, by); ctx.lineTo(bx+boxW, by+cornerLen);
                ctx.moveTo(bx, by+boxH-cornerLen); ctx.lineTo(bx, by+boxH); ctx.lineTo(bx+cornerLen, by+boxH);
                ctx.moveTo(bx+boxW-cornerLen, by+boxH); ctx.lineTo(bx+boxW, by+boxH); ctx.lineTo(bx+boxW, by+boxH-cornerLen);
                ctx.stroke();

                if (!config.performanceMode) {
                    const barW = 3, barX = bx - barW - 3;
                    const hpGrad = ctx.createLinearGradient(barX, by, barX, by + boxH);
                    hpGrad.addColorStop(0, '#00e676' + alpha);
                    hpGrad.addColorStop(1, '#ff1744' + alpha);
                    ctx.fillStyle = '#00000060';
                    ctx.fillRect(barX-1, by-1, barW+2, boxH+2);
                    ctx.fillStyle = hpGrad;
                    ctx.fillRect(barX, by, barW, boxH);

                    if (config.showDistance) {
                        const distText = `${Math.round(dist3D)}m`;
                        ctx.font = 'bold 10px "Segoe UI", system-ui';
                        const tw = ctx.measureText(distText).width;
                        const pillX = head.x - tw/2 - 4, pillY = by - 18;
                        ctx.fillStyle = '#00000090';
                        ctx.beginPath();
                        ctx.roundRect(pillX, pillY, tw+8, 14, 4);
                        ctx.fill();
                        ctx.fillStyle = '#ffffff' + alpha;
                        ctx.fillText(distText, pillX+4, pillY+11);
                    }

                    if (isDead) {
                        ctx.font = 'bold 9px "Segoe UI", system-ui';
                        ctx.fillStyle = '#ff5555';
                        ctx.fillText('DEAD', head.x - 14, by + boxH + 12);
                    }

                    if (config.showTracers) {
                        ctx.beginPath();
                        ctx.moveTo(cx, h);
                        ctx.lineTo(foot.x, foot.y);
                        ctx.strokeStyle = baseColor + '40';
                        ctx.lineWidth = 1;
                        ctx.setLineDash([4,4]);
                        ctx.stroke();
                        ctx.setLineDash([]);
                    }
                }
            }

            if (dist2D > config.fov) continue;

            if (config.visibilityCheck) {
                if (head.w < 0.01 || head.w > 100) continue;
                if (dist3D / (dist2D + 1) > 50) continue;
            }

            if (isOccluded) continue;
            if (isDead) continue;

            const score = config.priority === 1 ? dist2D : head.w;
            if (score < bestScore) {
                bestScore = score;
                const pred = project(vp, px, py, pz, w, h);
                bestTarget = pred || head;
                bestLockData = { wx, wy, wz, boneY, posKey };
            }
        }

        // Target lock
        if (config.targetLock) {
            if (state.lockedTarget) {
                const lt = state.lockedTarget;
                let lx = lt.wx, ly = lt.wy + lt.boneY, lz = lt.wz;
                if (config.predictionEnabled && config.velocityTracking) {
                    const vel = state.velocities.get(lt.posKey);
                    if (vel && now - vel.time < 200) {
                        const dt = config.predictionStrength * 0.05;
                        lx += vel.vx * dt; ly += vel.vy * dt; lz += vel.vz * dt;
                    }
                }
                const locked = project(vp, lx, ly, lz, w, h);
                const lastSeen = state.lastPositions.get(lt.posKey);
                if (locked && lastSeen && now - lastSeen.time < 500) {
                    bestTarget = locked;
                } else {
                    state.lockedTarget = null;
                }
            }
            if (!state.lockedTarget && bestLockData) state.lockedTarget = bestLockData;
        } else if (state.lockedTarget) {
            state.lockedTarget = null;
        }

        // Aim target highlight
        if (config.aimbotEnabled && bestTarget) {
            const pulse = 0.6 + Math.sin(now * 0.008) * 0.4;
            const glowSize = 12 + pulse * 6;
            ctx.beginPath();
            ctx.arc(bestTarget.x, bestTarget.y, glowSize, 0, Math.PI * 2);
            const glow = ctx.createRadialGradient(bestTarget.x, bestTarget.y, 0, bestTarget.x, bestTarget.y, glowSize);
            glow.addColorStop(0, `rgba(255, 50, 50, ${0.5 * pulse})`);
            glow.addColorStop(1, 'rgba(255, 50, 50, 0)');
            ctx.fillStyle = glow;
            ctx.fill();

            ctx.beginPath();
            ctx.arc(bestTarget.x, bestTarget.y, 4, 0, Math.PI * 2);
            ctx.fillStyle = '#ff3232';
            ctx.fill();

            if (config.debugOverlay) {
                ctx.beginPath();
                ctx.moveTo(cx, cy);
                ctx.lineTo(bestTarget.x, bestTarget.y);
                const lineGrad = ctx.createLinearGradient(cx, cy, bestTarget.x, bestTarget.y);
                lineGrad.addColorStop(0, 'rgba(255,255,0,0.1)');
                lineGrad.addColorStop(1, 'rgba(255,50,50,0.6)');
                ctx.strokeStyle = lineGrad;
                ctx.lineWidth = 1.5;
                ctx.stroke();
            }
        }

        // TriggerBot
        if (config.triggerBot && bestTarget) {
            const tdx = bestTarget.x - cx, tdy = bestTarget.y - cy;
            if (Math.hypot(tdx, tdy) < config.triggerRadius && now - state.lastTriggerFire > config.triggerDelay) {
                mouseClick(true);
                setTimeout(() => mouseClick(false), 50);
                state.lastTriggerFire = now;
            }
        }

        // ── AIMBOT (browser smooth approach) ──
        const shouldAim = config.aimbotEnabled && bestTarget && state.pointerLocked && aimKeyHeld();

        // Zoom detection
        if (vp) {
            const vpScale = Math.abs(vp[0]);
            if (vpScale > 0.5 && vpScale < 20) {
                if (state.baselineVP0 === 0) {
                    state.baselineVP0 = vpScale;
                } else if (vpScale < state.baselineVP0 * 1.1) {
                    state.baselineVP0 = state.baselineVP0 * 0.95 + vpScale * 0.05;
                }
                state.currentZoom = state.baselineVP0 > 0 ? vpScale / state.baselineVP0 : 1.0;
            }
        }

        if (shouldAim) {
            const dx = bestTarget.x - cx;
            const dy = bestTarget.y - cy;
            const dist = Math.hypot(dx, dy);

            // Zoom compensation for scoped weapons
            const zoom = state.currentZoom;
            const zoomComp = zoom > 1.5 ? 1.0 / zoom : 1.0;

            const DEADZONE = 3;
            if (dist < DEADZONE) {
                state.accX *= 0.7;
                state.accY *= 0.7;
            } else {
                let smooth = config.aimSmooth;
                const distRatio = Math.min(1, dist / config.fov);

                if (dist < config.lockDist * 0.5) {
                    smooth *= 2.5;
                } else if (dist < config.lockDist) {
                    const closeRatio = (dist - config.lockDist * 0.5) / (config.lockDist * 0.5);
                    smooth *= 1.5 + easeOutQuart(closeRatio);
                } else if (dist < config.lockDist * 2) {
                    const midRatio = (dist - config.lockDist) / config.lockDist;
                    smooth *= 1.0 + (0.5 * easeInOutCubic(midRatio));
                }

                const easedProgress = applySmoothCurve(distRatio);
                smooth = smooth * (0.8 + easedProgress * 0.4);

                let tx = (dx / smooth) * zoomComp;
                let ty = (dy / smooth) * zoomComp;
                tx += state.accX * 0.85;
                ty += state.accY * 0.85;

                let mx = Math.round(tx);
                let my = Math.round(ty);
                state.accX = (tx - mx) * 0.9;
                state.accY = (ty - my) * 0.9;

                if (Math.abs(mx) >= 1 || Math.abs(my) >= 1) {
                    mouseMove(mx, my);
                    state.lastMouseMove = now;
                }
            }
        } else {
            state.accX *= 0.5;
            state.accY *= 0.5;
        }

        // Crouch spam
        if (config.crouchSpam && state.pointerLocked && state.input.left) {
            if (now - state.lastCrouchToggle > config.crouchSpamSpeed) {
                state.crouchDown = !state.crouchDown;
                document.dispatchEvent(new KeyboardEvent(state.crouchDown ? 'keydown' : 'keyup', {
                    code: 'ShiftLeft', key: 'Shift', keyCode: 16, which: 16, bubbles: true, cancelable: true
                }));
                state.lastCrouchToggle = now;
            }
        } else if (state.crouchDown) {
            document.dispatchEvent(new KeyboardEvent('keyup', {
                code: 'ShiftLeft', key: 'Shift', keyCode: 16, which: 16, bubbles: true, cancelable: true
            }));
            state.crouchDown = false;
        }

        // Auto-strafe
        if (config.autoStrafe && state.pointerLocked && state.input.left) {
            if (now - state.lastStrafeToggle > config.autoStrafeSpeed) {
                const oldKey = state.strafeRight ? 'KeyD' : 'KeyA';
                document.dispatchEvent(new KeyboardEvent('keyup', { code: oldKey, key: state.strafeRight ? 'd' : 'a', bubbles: true }));
                state.strafeRight = !state.strafeRight;
                const newKey = state.strafeRight ? 'KeyD' : 'KeyA';
                document.dispatchEvent(new KeyboardEvent('keydown', { code: newKey, key: state.strafeRight ? 'd' : 'a', bubbles: true }));
                state.lastStrafeToggle = now;
            }
        } else if (state.lastStrafeToggle > 0) {
            document.dispatchEvent(new KeyboardEvent('keyup', { code: 'KeyA', key: 'a', bubbles: true }));
            document.dispatchEvent(new KeyboardEvent('keyup', { code: 'KeyD', key: 'd', bubbles: true }));
            state.lastStrafeToggle = 0;
        }

        // Minimap radar
        if (config.radarEnabled && state.vpMatrices.length > 0 && state.pointerLocked) {
            const rSize = config.radarSize;
            const rX = w - rSize - 15, rY = 15;
            const rCx = rX + rSize/2, rCy = rY + rSize/2;
            const rScale = (rSize / 2) / config.radarRange;

            ctx.beginPath();
            ctx.arc(rCx, rCy, rSize/2, 0, Math.PI * 2);
            ctx.fillStyle = 'rgba(0,0,0,0.55)';
            ctx.fill();
            ctx.strokeStyle = 'rgba(255,255,255,0.15)';
            ctx.lineWidth = 1;
            ctx.stroke();

            ctx.beginPath();
            ctx.moveTo(rCx, rY+4); ctx.lineTo(rCx, rY+rSize-4);
            ctx.moveTo(rX+4, rCy); ctx.lineTo(rX+rSize-4, rCy);
            ctx.strokeStyle = 'rgba(255,255,255,0.06)';
            ctx.stroke();

            ctx.beginPath();
            ctx.arc(rCx, rCy, 3, 0, Math.PI * 2);
            ctx.fillStyle = '#00e676';
            ctx.fill();

            const fwdX = -vp[2], fwdZ = -vp[10];
            const fwdLen = Math.sqrt(fwdX*fwdX + fwdZ*fwdZ) || 1;
            const cosA = fwdX/fwdLen, sinA = fwdZ/fwdLen;

            for (let i = 0; i < state.modelMatrices.length; i++) {
                const mat = state.modelMatrices[i];
                const rx = mat[12]*cosA + mat[14]*sinA;
                const rz = -mat[12]*sinA + mat[14]*cosA;
                const dotX = rCx + rx*rScale, dotY = rCy - rz*rScale;
                if (Math.hypot(dotX-rCx, dotY-rCy) > rSize/2 - 4) continue;
                ctx.beginPath();
                ctx.arc(dotX, dotY, 2.5, 0, Math.PI * 2);
                ctx.fillStyle = '#ff3232';
                ctx.fill();
            }
        }

        // Off-screen indicators
        if (config.offScreenIndicators && state.pointerLocked) {
            const margin = 30;
            for (let i = 0; i < state.modelMatrices.length; i++) {
                const mat = state.modelMatrices[i];
                const bY = getBoneOffset();
                const projected = project(vp, mat[12], mat[13]+bY, mat[14], w, h);
                if (!projected) continue;
                if (projected.x >= 0 && projected.x <= w && projected.y >= 0 && projected.y <= h) continue;
                const adx = projected.x - cx, ady = projected.y - cy;
                const angle = Math.atan2(ady, adx);
                const edgeX = Math.max(margin, Math.min(w-margin, cx + Math.cos(angle)*(w/2-margin)));
                const edgeY = Math.max(margin, Math.min(h-margin, cy + Math.sin(angle)*(h/2-margin)));
                ctx.save();
                ctx.translate(edgeX, edgeY);
                ctx.rotate(angle);
                ctx.beginPath();
                ctx.moveTo(10, 0); ctx.lineTo(-5, -6); ctx.lineTo(-5, 6);
                ctx.closePath();
                ctx.fillStyle = '#ff3232cc';
                ctx.fill();
                ctx.restore();
            }
        }

        if (config.antiAFK && now - state.lastMouseMove > 60000) {
            mouseMove(1, 0);
            state.lastMouseMove = now;
        }

        state.pointerLocked = !!document.pointerLockElement;

        if (now % 2000 < 16) {
            const cutoff = now - 3000;
            for (const [k,v] of state.lastPositions.entries()) if (v.time < cutoff) state.lastPositions.delete(k);
            for (const [k,v] of state.velocities.entries())    if (v.time < cutoff) state.velocities.delete(k);
            for (const [k,t] of state.deadPositions.entries()) if (t < cutoff)      state.deadPositions.delete(k);
        }

        clearFrameBuffers();
    }

    function clearFrameBuffers() { state.matricesByProgram.clear(); }

    // =====================================================================
    // GUI
    // =====================================================================
    const TABS = [
        { id: 'aim',    label: 'AIMBOT',  icon: '\u25CE' },
        { id: 'esp',    label: 'ESP',     icon: '\u25A3' },
        { id: 'combat', label: 'COMBAT',  icon: '\u2694' },
        { id: 'other',  label: 'OTHER',   icon: '\u2699' },
        { id: 'config', label: 'CONFIGS', icon: '\u25A1' },
    ];
    let currentTab = 'aim';

    const CSS = `
#d2-root *{box-sizing:border-box;margin:0;padding:0;font-family:'Segoe UI',system-ui,-apple-system,sans-serif}
#d2-root{position:fixed;display:flex;flex-direction:row;width:820px;height:540px;background:#0d0d11;border:1px solid rgba(255,255,255,.04);border-radius:10px;color:#c5c5cc;z-index:2147483646;user-select:none;box-shadow:0 30px 80px rgba(0,0,0,.85);overflow:hidden}
#d2-root .d2-sidebar{width:160px;background:#0a0a0e;display:flex;flex-direction:column;border-right:1px solid rgba(255,255,255,.04)}
#d2-root .d2-brand{padding:20px 12px 16px;text-align:center;overflow:hidden}
#d2-root .d2-brand-logo{font-size:22px;font-weight:900;letter-spacing:2px;color:#fff;line-height:1;white-space:nowrap}
#d2-root .d2-brand-logo span{color:var(--accent)}
#d2-root .d2-brand-sub{font-size:9px;color:#444;letter-spacing:4px;text-transform:uppercase;margin-top:2px}
#d2-root .d2-nav{flex:1;padding:8px;display:flex;flex-direction:column;gap:2px}
#d2-root .d2-nav-item{display:flex;align-items:center;gap:10px;padding:10px 14px;border-radius:6px;font-size:11px;font-weight:600;letter-spacing:1px;color:#555;cursor:pointer;transition:all .12s;position:relative}
#d2-root .d2-nav-item:hover{background:rgba(255,255,255,.025);color:#999}
#d2-root .d2-nav-item.active{color:var(--accent);background:rgba(168,85,247,.06)}
#d2-root .d2-nav-item.active::before{content:'';position:absolute;left:0;top:6px;bottom:6px;width:3px;background:var(--accent);border-radius:0 3px 3px 0}
#d2-root .d2-nav-icon{font-size:14px;width:18px;text-align:center;opacity:.8}
#d2-root .d2-status-box{margin:8px;padding:12px;background:rgba(255,255,255,.02);border:1px solid rgba(255,255,255,.04);border-radius:8px}
#d2-root .d2-status-name{display:flex;align-items:center;gap:6px;font-size:11px;font-weight:700;color:#ddd}
#d2-root .d2-status-dot{width:7px;height:7px;border-radius:50%;background:#00e676;box-shadow:0 0 6px #00e676}
#d2-root .d2-status-label{font-size:9px;color:#00e676;font-weight:700;letter-spacing:1px;margin-top:3px}
#d2-root .d2-status-ver{font-size:8px;color:#333;font-family:monospace;margin-top:6px}
#d2-root .d2-main{flex:1;display:flex;flex-direction:column;min-width:0}
#d2-root .d2-topbar{display:flex;align-items:center;justify-content:space-between;height:42px;padding:0 16px;background:#09090c;border-bottom:1px solid rgba(255,255,255,.04);cursor:move;flex-shrink:0}
#d2-root .d2-tab-pills{display:flex;gap:0;height:100%}
#d2-root .d2-tab-pill{display:flex;align-items:center;gap:6px;padding:0 16px;font-size:11px;font-weight:600;letter-spacing:1px;color:#555;cursor:pointer;border-bottom:2px solid transparent;transition:all .12s;height:100%}
#d2-root .d2-tab-pill:hover{color:#999}
#d2-root .d2-tab-pill.active{color:var(--accent);border-bottom-color:var(--accent)}
#d2-root .d2-tab-pill .tp-icon{font-size:12px;opacity:.7}
#d2-root .d2-win-btns{display:flex;gap:2px}
#d2-root .d2-win-btn{width:28px;height:28px;display:flex;align-items:center;justify-content:center;background:transparent;border:none;color:#444;cursor:pointer;border-radius:4px;font-size:14px;transition:all .12s}
#d2-root .d2-win-btn:hover{background:rgba(255,255,255,.05);color:#ccc}
#d2-root .d2-win-btn.close:hover{background:#c53030;color:#fff}
#d2-root .d2-body{flex:1;overflow-y:auto;overflow-x:hidden;padding:16px 18px;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.08) transparent}
#d2-root .d2-body::-webkit-scrollbar{width:4px}
#d2-root .d2-body::-webkit-scrollbar-thumb{background:rgba(255,255,255,.1);border-radius:4px}
#d2-root .d2-body::-webkit-scrollbar-track{background:transparent}
#d2-root .d2-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}
#d2-root .d2-grid .span-2{grid-column:span 2}
#d2-root .d2-card{background:rgba(255,255,255,.018);border:1px solid rgba(255,255,255,.04);border-radius:8px;padding:14px 16px;min-width:0}
#d2-root .d2-card-title{font-size:10px;font-weight:700;letter-spacing:2px;color:#666;text-transform:uppercase;margin-bottom:12px;padding-bottom:8px;border-bottom:1px solid rgba(255,255,255,.04)}
#d2-root .d2-row{display:flex;align-items:center;justify-content:space-between;padding:4px 0;min-height:28px}
#d2-root .d2-row>.label{font-size:12px;color:#bbb;white-space:nowrap}
#d2-root .d2-toggle{position:relative;width:36px;height:18px;cursor:pointer;display:inline-block;flex-shrink:0}
#d2-root .d2-toggle input{opacity:0;width:0;height:0;position:absolute}
#d2-root .d2-toggle .slider{position:absolute;inset:0;background:rgba(255,255,255,.07);border-radius:10px;transition:all .2s}
#d2-root .d2-toggle .slider:before{content:'';position:absolute;width:14px;height:14px;left:2px;top:2px;background:#666;border-radius:50%;transition:all .2s}
#d2-root .d2-toggle input:checked+.slider{background:color-mix(in srgb,var(--accent) 40%,transparent)}
#d2-root .d2-toggle input:checked+.slider:before{transform:translateX(18px);background:var(--accent);box-shadow:0 0 8px color-mix(in srgb,var(--accent) 60%,transparent)}
#d2-root .d2-slider{padding:5px 0}
#d2-root .d2-slider-label{display:flex;justify-content:space-between;font-size:11px;color:#888;margin-bottom:4px}
#d2-root .d2-slider-label .val{color:var(--accent);font-family:'Cascadia Code','Consolas',monospace;font-size:11px;font-weight:700}
#d2-root input[type=range]{-webkit-appearance:none;width:100%;height:4px;background:rgba(255,255,255,.06);border-radius:4px;outline:none;cursor:pointer}
#d2-root input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;width:14px;height:14px;background:var(--accent);border-radius:50%;cursor:pointer;border:2px solid #0d0d11;box-shadow:0 0 6px color-mix(in srgb,var(--accent) 50%,transparent)}
#d2-root .d2-select{padding:4px 0}
#d2-root .d2-select .label{font-size:11px;color:#777;margin-bottom:4px;display:block}
#d2-root select{width:100%;background:#111116;color:#ccc;border:1px solid rgba(255,255,255,.06);padding:7px 10px;border-radius:6px;font-size:11px;outline:none;cursor:pointer;font-family:inherit}
#d2-root select:hover{border-color:rgba(255,255,255,.12)}
#d2-root select:focus{border-color:var(--accent)}
#d2-root .d2-keybind{background:#111116;color:#ccc;border:1px solid rgba(255,255,255,.06);padding:5px 12px;border-radius:5px;font-size:10px;font-family:'Cascadia Code','Consolas',monospace;font-weight:600;cursor:pointer;min-width:72px;text-align:center;transition:all .12s}
#d2-root .d2-keybind:hover{border-color:var(--accent);color:var(--accent)}
#d2-root .d2-keybind.listening{background:var(--accent);color:#000;animation:d2Pulse 1s infinite}
@keyframes d2Pulse{0%,100%{opacity:1}50%{opacity:.5}}
#d2-root .d2-btn{width:100%;padding:9px;background:rgba(255,255,255,.025);color:var(--accent);border:1px solid rgba(255,255,255,.05);border-radius:6px;cursor:pointer;font-size:10px;font-weight:700;letter-spacing:1.2px;text-transform:uppercase;transition:all .15s;font-family:inherit}
#d2-root .d2-btn:hover{background:rgba(255,255,255,.05);border-color:var(--accent)}
#d2-root .d2-btn.danger{color:#ff5c5c}
#d2-root .d2-btn.danger:hover{border-color:#ff5c5c}
#d2-root .d2-stats{display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px}
#d2-root .d2-stat{background:rgba(255,255,255,.02);border:1px solid rgba(255,255,255,.04);border-radius:6px;padding:10px;text-align:center}
#d2-root .d2-stat-val{font-size:20px;font-weight:800;color:var(--accent);font-family:'Cascadia Code','Consolas',monospace}
#d2-root .d2-stat-lbl{font-size:7px;color:#444;text-transform:uppercase;letter-spacing:2px;margin-top:2px}
#d2-root .d2-badge{display:flex;align-items:center;justify-content:space-between;gap:8px;background:rgba(255,255,255,.02);border:1px solid rgba(255,255,255,.04);border-radius:6px;padding:10px 14px;margin-top:10px}
#d2-root .d2-badge .lbl{font-size:9px;color:#555;text-transform:uppercase;letter-spacing:2px}
#d2-root .d2-badge .val{font-size:16px;font-weight:800;color:var(--accent);font-family:'Cascadia Code','Consolas',monospace}
#d2-root .d2-badge .hint{font-size:9px;color:#444;font-family:monospace}
#d2-root .d2-color{width:28px;height:28px;border:1px solid rgba(255,255,255,.08);border-radius:6px;padding:0;background:var(--accent);cursor:pointer;flex-shrink:0}
#d2-root input[type=color]{opacity:0;width:0;height:0;position:absolute}
`;

    function row(label, inner) {
        return `<div class="d2-row"><span class="label">${label}</span>${inner}</div>`;
    }
    function toggle(id, checked) {
        return `<label class="d2-toggle"><input type="checkbox" id="${id}" ${checked ? 'checked' : ''}><span class="slider"></span></label>`;
    }
    function slider(id, label, val, min, max, step) {
        return `<div class="d2-slider"><div class="d2-slider-label"><span>${label}</span><span class="val" id="${id}-v">${val}</span></div><input type="range" id="${id}" min="${min}" max="${max}" step="${step}" value="${val}"></div>`;
    }
    function select(id, label, options, current) {
        const opts = options.map(o => `<option value="${o.v}" ${String(current)===String(o.v)?'selected':''}>${o.l}</option>`).join('');
        return `<div class="d2-select"><span class="label">${label}</span><select id="${id}">${opts}</select></div>`;
    }
    function card(title, content, extraClass) {
        return `<div class="d2-card ${extraClass||''}"><div class="d2-card-title">${title}</div>${content}</div>`;
    }
    function keybind(field, value) {
        return `<button class="d2-keybind" data-rebind="${field}">${value || '\u2014'}</button>`;
    }

    function aimTab() {
        return `<div class="d2-grid">` +
            card('General', [
                row('Aimbot', toggle('t-aim', config.aimbotEnabled)),
                row('Aim Key', keybind('aimKey', config.aimKey)),
                row('Visible Check', toggle('t-vis', config.visibilityCheck)),
                row('Target Lock', toggle('t-lock', config.targetLock)),
            ].join('')) +
            card('Target', [
                select('sel-prio','Selection',[{v:1,l:'Closest to Crosshair'},{v:0,l:'Closest Distance'}], config.priority),
                select('sel-bone','Hitbox',[{v:0,l:'Head'},{v:1,l:'Neck'},{v:2,l:'Body'}], config.hitbox),
                slider('s-lockd','Lock Distance', config.lockDist, 5, 200, 1),
                slider('s-smooth','Smoothing', config.aimSmooth, 1, 10, 0.1),
            ].join('')) +
            card('Prediction', [
                row('Enabled', toggle('t-pred', config.predictionEnabled)),
                row('Track Velocity', toggle('t-vel', config.velocityTracking)),
                slider('s-pred','Strength', config.predictionStrength, 0.5, 3, 0.1),
            ].join('')) +
            card('TriggerBot', [
                row('Enabled', toggle('t-trig', config.triggerBot)),
                slider('s-trigr','Trigger Radius', config.triggerRadius, 4, 30, 1),
                slider('s-trigd','Trigger Delay', config.triggerDelay, 0, 500, 10),
            ].join('')) +
            `<div class="d2-badge span-2"><span class="lbl">Target Program</span><span class="val" id="d2-target-val">${currentTargetID()}</span><span class="hint">${config.autoDetect?'AUTO':'MANUAL'}</span></div>` +
        `</div>`;
    }

    function espTab() {
        return `<div class="d2-grid">` +
            card('ESP', [
                row('Box ESP', toggle('t-esp', config.espEnabled)),
                row('Distance', toggle('t-dist', config.showDistance)),
                row('Tracers', toggle('t-tracers', config.showTracers)),
                slider('s-thick','Box Thickness', config.espThickness, 1, 5, 0.5),
            ].join('')) +
            card('Overlay', [
                row('FOV Circle', toggle('t-fov', config.showFov)),
                row('FOV Gradient', toggle('t-grad', config.fovGradient)),
                slider('s-fov','FOV Radius', config.fov, 50, 600, 10),
                row('Crosshair', toggle('t-cross', config.showCrosshair)),
            ].join('')) +
            card('Radar', [
                row('Minimap', toggle('t-radar', config.radarEnabled)),
                row('Off-Screen Arrows', toggle('t-offscreen', config.offScreenIndicators)),
                slider('s-rsize','Radar Size', config.radarSize, 80, 200, 10),
                slider('s-rrange','Radar Range', config.radarRange, 30, 200, 10),
            ].join('')) +
            card('Display', [
                row('Show FPS', toggle('t-fps', config.showFPS)),
                row('Debug Strip', toggle('t-dbg', config.debugOverlay)),
            ].join('')) +
        `</div>`;
    }

    function combatTab() {
        return `<div class="d2-grid">` +
            card('Crouch Spam', [
                row('Enabled', toggle('t-crouch', config.crouchSpam)),
                slider('s-crouchspd','Speed (ms)', config.crouchSpamSpeed, 20, 300, 10),
            ].join('')) +
            card('Auto Strafe', [
                row('Enabled', toggle('t-strafe', config.autoStrafe)),
                slider('s-strafespd','Speed (ms)', config.autoStrafeSpeed, 40, 300, 10),
            ].join('')) +
            card('Anti-AFK', [
                row('Enabled', toggle('t-afk', config.antiAFK)),
            ].join('')) +
            card('Performance', [
                row('Performance Mode', toggle('t-perf', config.performanceMode)),
                row('Block Fullscreen', toggle('t-blockfs', config.blockFullscreen)),
            ].join('')) +
        `</div>`;
    }

    function otherTab() {
        return `<div class="d2-grid">` +
            card('FOV Hack', [
                row('Enabled', toggle('t-fovhack', config.fovHack)),
                slider('s-fovscale','FOV Scale', config.fovHackScale, 0.3, 1.0, 0.05),
            ].join('')) +
            card('Stats', `
                <div class="d2-stats">
                    <div class="d2-stat"><div class="d2-stat-val" id="stat-fps">${state.fps}</div><div class="d2-stat-lbl">FPS</div></div>
                    <div class="d2-stat"><div class="d2-stat-val" id="stat-tgts">${state.totalTargets}</div><div class="d2-stat-lbl">Targets</div></div>
                    <div class="d2-stat"><div class="d2-stat-val" id="stat-prog">${state.programScores.size}</div><div class="d2-stat-lbl">Programs</div></div>
                </div>
            `) +
            card('Detection', [
                `<div style="display:flex;gap:8px"><button class="d2-btn" id="btn-auto">${config.autoDetect?'Auto Detect ON':'Enable Auto'}</button><button class="d2-btn" id="btn-reset-tgt">Reset Target</button></div>`,
            ].join(''), 'span-2') +
        `</div>`;
    }

    function configTab() {
        return `<div class="d2-grid">` +
            card('Interface', [
                row('Menu Key', keybind('menuKey', config.menuKey)),
                row('Accent Color', `<label class="d2-color" style="background:${config.accentColor}"><input type="color" id="c-accent" value="${config.accentColor}"></label>`),
            ].join('')) +
            card('Danger Zone', `
                <button class="d2-btn danger" id="btn-reset">Reset All Settings</button>
            `) +
        `</div>`;
    }

    function tabContent() {
        if (currentTab === 'aim')    return aimTab();
        if (currentTab === 'esp')    return espTab();
        if (currentTab === 'combat') return combatTab();
        if (currentTab === 'other')  return otherTab();
        if (currentTab === 'config') return configTab();
        return '';
    }

    function createGUI() {
        if (document.getElementById('d2-root')) return;
        if (!document.body) return;

        let style = document.getElementById('d2-style');
        if (!style) {
            style = document.createElement('style');
            style.id = 'd2-style';
            style.textContent = CSS;
            document.head.appendChild(style);
        }
        document.documentElement.style.setProperty('--accent', config.accentColor);

        const root = document.createElement('div');
        root.id = 'd2-root';
        root.style.left = config.x + 'px';
        root.style.top  = config.y + 'px';
        root.style.display = config.menuVisible ? 'flex' : 'none';

        root.innerHTML = `
            <div class="d2-sidebar">
                <div class="d2-brand">
                    <div class="d2-brand-logo"><span>D</span>ESTINY</div>
                    <div class="d2-brand-sub">DEADSHOT</div>
                </div>
                <div class="d2-nav">
                    ${TABS.map(t => `<div class="d2-nav-item ${t.id===currentTab?'active':''}" data-tab="${t.id}"><span class="d2-nav-icon">${t.icon}</span><span>${t.label}</span></div>`).join('')}
                </div>
                <div class="d2-status-box">
                    <div class="d2-status-name"><span class="d2-status-dot"></span> DESTINY</div>
                    <div class="d2-status-label">STATUS: UNDETECTED</div>
                    <div class="d2-status-ver">Version 3.0.0<br>destiny.menu</div>
                </div>
            </div>
            <div class="d2-main">
                <div class="d2-topbar" id="d2-header">
                    <div class="d2-tab-pills">
                        ${TABS.map(t => `<div class="d2-tab-pill ${t.id===currentTab?'active':''}" data-tab="${t.id}"><span class="tp-icon">${t.icon}</span><span>${t.label}</span></div>`).join('')}
                    </div>
                    <div class="d2-win-btns">
                        <button class="d2-win-btn close" id="d2-close" title="Close">\u00D7</button>
                    </div>
                </div>
                <div class="d2-body" id="d2-body">${tabContent()}</div>
            </div>
        `;
        document.body.appendChild(root);

        // Drag
        const header = document.getElementById('d2-header');
        let drag = false, ox = 0, oy = 0;
        header.addEventListener('mousedown', (e) => {
            drag = true; ox = e.clientX - root.offsetLeft; oy = e.clientY - root.offsetTop; e.preventDefault();
        });
        window.addEventListener('mousemove', (e) => {
            if (!drag) return;
            const x = Math.max(0, Math.min(window.innerWidth - root.offsetWidth, e.clientX - ox));
            const y = Math.max(0, Math.min(window.innerHeight - root.offsetHeight, e.clientY - oy));
            root.style.left = x + 'px'; root.style.top = y + 'px';
            config.x = x; config.y = y;
        });
        window.addEventListener('mouseup', () => { if (drag) save(); drag = false; });

        root.querySelectorAll('.d2-nav-item, .d2-tab-pill').forEach(el => {
            el.addEventListener('click', (e) => { e.stopPropagation(); currentTab = el.dataset.tab; refreshGUI(); });
        });
        document.getElementById('d2-close').addEventListener('click', () => {
            config.menuVisible = false; root.style.display = 'none'; saveImmediate();
        });

        attachHandlers();
    }

    function refreshGUI() {
        const root = document.getElementById('d2-root');
        if (!root) { createGUI(); return; }
        document.documentElement.style.setProperty('--accent', config.accentColor);
        root.querySelectorAll('.d2-nav-item').forEach(el => el.classList.toggle('active', el.dataset.tab === currentTab));
        root.querySelectorAll('.d2-tab-pill').forEach(el => el.classList.toggle('active', el.dataset.tab === currentTab));
        const body = document.getElementById('d2-body');
        if (body) body.innerHTML = tabContent();
        attachHandlers();
        refreshTargetBadge();
    }

    function bindToggle(id, field) {
        const el = document.getElementById(id);
        if (el) el.addEventListener('change', e => { config[field] = e.target.checked; save(); });
    }
    function bindSlider(id, field, parser = parseFloat) {
        const el = document.getElementById(id);
        const valEl = document.getElementById(id + '-v');
        if (el) el.addEventListener('input', e => {
            const v = parser(e.target.value);
            config[field] = v;
            if (valEl) valEl.textContent = v;
            save();
        });
    }
    function bindSelect(id, field, parser = (x => x)) {
        const el = document.getElementById(id);
        if (el) el.addEventListener('change', e => { config[field] = parser(e.target.value); save(); });
    }

    function attachHandlers() {
        bindToggle('t-aim',   'aimbotEnabled');
        bindToggle('t-pred',  'predictionEnabled');
        bindToggle('t-vel',   'velocityTracking');
        bindToggle('t-lock',  'targetLock');
        bindToggle('t-trig',  'triggerBot');
        bindToggle('t-crouch','crouchSpam');
        bindToggle('t-strafe','autoStrafe');
        bindSlider('s-crouchspd','crouchSpamSpeed', parseInt);
        bindSlider('s-strafespd','autoStrafeSpeed', parseInt);
        bindSlider('s-lockd', 'lockDist', parseInt);
        bindSlider('s-smooth','aimSmooth');
        bindSlider('s-pred',  'predictionStrength');
        bindSlider('s-trigr', 'triggerRadius', parseInt);
        bindSlider('s-trigd', 'triggerDelay', parseInt);
        bindSelect('sel-bone','hitbox', parseInt);
        bindSelect('sel-prio','priority', parseInt);

        const btnAuto = document.getElementById('btn-auto');
        if (btnAuto) btnAuto.addEventListener('click', () => { config.autoDetect = true; save(); refreshGUI(); });
        const btnResetTgt = document.getElementById('btn-reset-tgt');
        if (btnResetTgt) btnResetTgt.addEventListener('click', () => {
            config.autoDetect = true; config.manualTargetID = -1;
            state.detectedTargetID = -1; state.programScores.clear();
            save(); refreshGUI();
        });

        bindToggle('t-esp',     'espEnabled');
        bindToggle('t-dist',    'showDistance');
        bindToggle('t-tracers', 'showTracers');
        bindSlider('s-thick',   'espThickness');
        bindToggle('t-fov',     'showFov');
        bindToggle('t-grad',    'fovGradient');
        bindSlider('s-fov',     'fov', parseInt);
        bindToggle('t-cross',   'showCrosshair');
        bindToggle('t-fps',     'showFPS');
        bindToggle('t-dbg',     'debugOverlay');

        bindToggle('t-radar',    'radarEnabled');
        bindSlider('s-rsize',    'radarSize', parseInt);
        bindSlider('s-rrange',   'radarRange', parseInt);
        bindToggle('t-offscreen','offScreenIndicators');

        bindToggle('t-vis',     'visibilityCheck');
        bindToggle('t-perf',    'performanceMode');
        bindToggle('t-fovhack', 'fovHack');
        bindSlider('s-fovscale','fovHackScale');
        bindToggle('t-afk',     'antiAFK');
        const blockFs = document.getElementById('t-blockfs');
        if (blockFs) blockFs.addEventListener('change', e => {
            config.blockFullscreen = e.target.checked; saveImmediate();
            if (confirm('Reload to apply fullscreen setting?')) location.reload();
        });

        const accent = document.getElementById('c-accent');
        if (accent) accent.addEventListener('input', e => {
            config.accentColor = e.target.value;
            document.documentElement.style.setProperty('--accent', config.accentColor);
            const swatch = accent.parentElement;
            if (swatch) swatch.style.background = config.accentColor;
            save();
        });
        const reset = document.getElementById('btn-reset');
        if (reset) reset.addEventListener('click', () => {
            if (!confirm('Reset all settings?')) return;
            config = { ...defaultConfig };
            saveImmediate();
            refreshGUI();
        });

        document.querySelectorAll('#d2-root .d2-keybind').forEach(btn => {
            const field = btn.dataset.rebind;
            const aimKeyDropdown = field === 'aimKey';
            btn.addEventListener('click', () => {
                if (aimKeyDropdown) {
                    const opts = ['RightClick','LeftClick','ShiftLeft','AltLeft','Always'];
                    const idx = opts.indexOf(config.aimKey);
                    config.aimKey = opts[(idx+1)%opts.length];
                    saveImmediate(); refreshGUI();
                    return;
                }
                document.querySelectorAll('#d2-root .d2-keybind').forEach(b => b.classList.remove('listening'));
                btn.classList.add('listening');
                btn.textContent = '\u2026';
                state.rebindingField = field;
            });
        });
    }

    function refreshTargetBadge() {
        const tv = document.getElementById('d2-target-val');
        if (tv) tv.textContent = currentTargetID();
    }
    function updateStatusBar() {
        const c = document.getElementById('stat-fps');  if (c) c.textContent = state.fps;
        const d = document.getElementById('stat-tgts'); if (d) d.textContent = state.totalTargets;
        const e = document.getElementById('stat-prog'); if (e) e.textContent = state.programScores.size;
    }

    // =====================================================================
    // INIT
    // =====================================================================
    function init() {
        setupCanvas();
        createGUI();
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();