Emu's Chams GUI (Stats HUD)

Professional toggleable wallhack (chams) GUI for Kirka.io with advanced crosshairs and stats HUD

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

javascript:(function() {
    // ==UserScript==
    // @name         Emu's Chams GUI (Stats HUD)
    // @namespace    EmuChams
    // @version      1.9
    // @description  Professional toggleable wallhack (chams) GUI for Kirka.io with advanced crosshairs and stats HUD
    // @author       Emulation
    // @match        *://kirka.io/*
    // @run-at       document-start
    // @license      MIT
    // ==/UserScript==

    (function () {
        // Settings
        const settings = {
            enabled: localStorage.getItem('chamsEnabled') !== 'false',
            theme: localStorage.getItem('chamsTheme') || 'obsidian-black',
            menuPosition: JSON.parse(localStorage.getItem('menuPosition')) || { left: '120px', top: '120px' },
            menuVisible: true, // Always visible on load
            menuMinimized: localStorage.getItem('menuMinimized') === 'true',
            hudPosition: JSON.parse(localStorage.getItem('hudPosition')) || { left: '400px', top: '120px' },
            crosshairType: localStorage.getItem('crosshairType') || 'None',
            crosshairSize: parseInt(localStorage.getItem('crosshairSize')) || 20,
            crosshairThickness: parseInt(localStorage.getItem('crosshairThickness')) || 2,
            crosshairColor: localStorage.getItem('crosshairColor') || '#00f0ff',
            crosshairOutline: localStorage.getItem('crosshairOutline') === 'true',
            crosshairOutlineThickness: parseFloat(localStorage.getItem('crosshairOutlineThickness')) || 1,
            crosshairOpacity: parseFloat(localStorage.getItem('crosshairOpacity')) || 1,
            crosshairRotation: parseInt(localStorage.getItem('crosshairRotation')) || 0,
            showFPS: localStorage.getItem('showFPS') === 'true',
            showLatency: localStorage.getItem('showLatency') === 'true',
            showFPSGraph: localStorage.getItem('showFPSGraph') === 'true',
            showLatencyGraph: localStorage.getItem('showLatencyGraph') === 'true',
            menuOpacity: parseFloat(localStorage.getItem('menuOpacity')) || 1,
            menuScale: parseFloat(localStorage.getItem('menuScale')) || 1
        };
        const modifiedMaterials = new WeakSet();
        let notificationTimeout = null;
        const clientVersion = '1.9.0';
        let menuVisible = settings.menuVisible;
        const notifications = [];
        let crosshairCanvas, crosshairCtx, statsCanvas, statsCtx;
        let lastFrameTime = performance.now();
        let fps = 0, latency = 0;
        const fpsHistory = [], latencyHistory = [];
        const maxHistory = 60; // ~30s at 60fps

        // Save settings
        function saveSettings() {
            localStorage.setItem('chamsEnabled', settings.enabled);
            localStorage.setItem('chamsTheme', settings.theme);
            localStorage.setItem('menuPosition', JSON.stringify(settings.menuPosition));
            localStorage.setItem('menuVisible', menuVisible);
            localStorage.setItem('menuMinimized', settings.menuMinimized);
            localStorage.setItem('hudPosition', JSON.stringify(settings.hudPosition));
            localStorage.setItem('crosshairType', settings.crosshairType);
            localStorage.setItem('crosshairSize', settings.crosshairSize);
            localStorage.setItem('crosshairThickness', settings.crosshairThickness);
            localStorage.setItem('crosshairColor', settings.crosshairColor);
            localStorage.setItem('crosshairOutline', settings.crosshairOutline);
            localStorage.setItem('crosshairOutlineThickness', settings.crosshairOutlineThickness);
            localStorage.setItem('crosshairOpacity', settings.crosshairOpacity);
            localStorage.setItem('crosshairRotation', settings.crosshairRotation);
            localStorage.setItem('showFPS', settings.showFPS);
            localStorage.setItem('showLatency', settings.showLatency);
            localStorage.setItem('showFPSGraph', settings.showFPSGraph);
            localStorage.setItem('showLatencyGraph', settings.showLatencyGraph);
            localStorage.setItem('menuOpacity', settings.menuOpacity);
            localStorage.setItem('menuScale', settings.menuScale);
        }

        // Reset settings
        function resetSettings() {
            localStorage.clear();
            settings.enabled = true;
            settings.theme = 'obsidian-black';
            settings.menuPosition = { left: '120px', top: '120px' };
            settings.menuVisible = true;
            settings.menuMinimized = false;
            settings.hudPosition = { left: '400px', top: '120px' };
            settings.crosshairType = 'None';
            settings.crosshairSize = 20;
            settings.crosshairThickness = 2;
            settings.crosshairColor = '#00f0ff';
            settings.crosshairOutline = false;
            settings.crosshairOutlineThickness = 1;
            settings.crosshairOpacity = 1;
            settings.crosshairRotation = 0;
            settings.showFPS = false;
            settings.showLatency = false;
            settings.showFPSGraph = false;
            settings.showLatencyGraph = false;
            settings.menuOpacity = 1;
            settings.menuScale = 1;
            saveSettings();
            showNotification('Settings reset to default');
            location.reload();
        }

        // Show notification
        function showNotification(message) {
            const notification = document.createElement('div');
            notification.className = 'notification tooltip';
            notification.textContent = message;
            notification.style.position = 'fixed';
            notification.style.bottom = `${20 + notifications.length * 40}px`;
            notification.style.right = '20px';
            notification.style.background = 'var(--bg-gradient)';
            notification.style.border = '1px solid var(--accent-color)';
            notification.style.color = 'var(--text-color)';
            notification.style.padding = '6px 12px';
            notification.style.borderRadius = '5px';
            notification.style.boxShadow = '0 4px 15px var(--accent-shadow)';
            notification.style.opacity = '0';
            notification.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
            notification.style.transform = 'translateX(20px)';
            notification.style.zIndex = '999997';
            notification.style.fontFamily = '"Inter", sans-serif';
            notification.style.fontSize = '11px';
            notification.style.backdropFilter = 'blur(12px)';
            document.body.appendChild(notification);
            notifications.push(notification);

            setTimeout(() => {
                notification.style.opacity = '1';
                notification.style.transform = 'translateX(0)';
            }, 10);
            setTimeout(() => {
                notification.style.opacity = '0';
                notification.style.transform = 'translateX(20px)';
                setTimeout(() => {
                    notification.remove();
                    notifications.splice(notifications.indexOf(notification), 1);
                    notifications.forEach((n, i) => {
                        n.style.bottom = `${20 + i * 40}px`;
                    });
                }, 300);
            }, 2500);

            if (notificationTimeout) clearTimeout(notificationTimeout);
            notificationTimeout = setTimeout(() => {}, 100);
        }

        // Patch material for chams
        const patchMaterial = (material) => {
            if (!material || !material.map || !material.map.image) return;
            const isTarget = material.map.image.width === 64 && material.map.image.height === 64;
            if (!isTarget) return;

            if (settings.enabled && !modifiedMaterials.has(material)) {
                for (let key in material) {
                    if (material[key] === 3) {
                        material[key] = 1;
                        modifiedMaterials.add(material);
                    }
                }
            } else if (!settings.enabled && modifiedMaterials.has(material)) {
                for (let key in material) {
                    if (material[key] === 1) {
                        material[key] = 3;
                    }
                }
                modifiedMaterials.delete(material);
            }
        };

        // Hook Array.isArray to intercept material use
        const proxyHandler = {
            apply(target, thisArg, args) {
                patchMaterial(args[0]);
                return Reflect.apply(target, thisArg, args);
            }
        };
        const originalIsArray = Array.isArray;
        Array.isArray = new Proxy(originalIsArray, proxyHandler);

        // Force material patching on any new materials dynamically
        const observeMaterials = () => {
            const interval = setInterval(() => {
                if (window.THREE) {
                    const walk = (obj) => {
                        if (!obj || typeof obj !== "object") return;
                        if (obj.material) {
                            const mat = obj.material;
                            if (Array.isArray(mat)) mat.forEach(patchMaterial);
                            else patchMaterial(mat);
                        }
                        for (const key in obj) {
                            if (obj.hasOwnProperty(key)) walk(obj[key]);
                        }
                    };
                    walk(window);
                    clearInterval(interval);
                }
            }, 1000);
        };

        // Crosshair rendering
        function initCrosshairCanvas() {
            crosshairCanvas = document.createElement('canvas');
            crosshairCanvas.id = 'crosshair-canvas';
            crosshairCanvas.style.position = 'fixed';
            crosshairCanvas.style.top = '0';
            crosshairCanvas.style.left = '0';
            crosshairCanvas.style.width = '100%';
            crosshairCanvas.style.height = '100%';
            crosshairCanvas.style.zIndex = '999998';
            crosshairCanvas.style.pointerEvents = 'none';
            document.body.appendChild(crosshairCanvas);
            crosshairCtx = crosshairCanvas.getContext('2d');
            resizeCrosshair();
        }

        function resizeCrosshair() {
            if (!crosshairCanvas) return;
            crosshairCanvas.width = window.innerWidth;
            crosshairCanvas.height = window.innerHeight;
            drawCrosshair();
        }

        function drawCrosshair() {
            if (!crosshairCtx || !crosshairCanvas) return;
            crosshairCtx.clearRect(0, 0, crosshairCanvas.width, crosshairCanvas.height);
            if (settings.crosshairType === 'None') return;

            const centerX = crosshairCanvas.width / 2;
            const centerY = crosshairCanvas.height / 2;
            const size = settings.crosshairSize;
            const thickness = settings.crosshairThickness;
            const color = settings.crosshairColor;
            let rotation = settings.crosshairRotation * Math.PI / 180;
            if (settings.crosshairType === 'Dynamic Star') rotation += Date.now() / 1000;
            if (settings.crosshairType === 'Dynamic Circle') rotation = 0;

            crosshairCtx.save();
            crosshairCtx.translate(centerX, centerY);
            crosshairCtx.rotate(rotation);
            crosshairCtx.globalAlpha = settings.crosshairOpacity;

            if (settings.crosshairOutline) {
                crosshairCtx.strokeStyle = '#000000';
                crosshairCtx.lineWidth = thickness + settings.crosshairOutlineThickness * 2;
                drawCrosshairShape(true);
            }

            crosshairCtx.strokeStyle = color;
            crosshairCtx.fillStyle = color;
            crosshairCtx.lineWidth = thickness;
            drawCrosshairShape(false);

            crosshairCtx.restore();

            function drawCrosshairShape(isOutline) {
                const method = isOutline ? 'stroke' : settings.crosshairType.includes('Dot') || settings.crosshairType === 'Circle' || settings.crosshairType === 'Triangle' ? 'fill' : 'stroke';
                crosshairCtx.beginPath();
                switch (settings.crosshairType) {
                    case 'Dot':
                        crosshairCtx.arc(0, 0, size / 5, 0, Math.PI * 2);
                        break;
                    case 'Cross':
                        crosshairCtx.moveTo(-size / 2, 0); crosshairCtx.lineTo(-size / 4, 0);
                        crosshairCtx.moveTo(size / 4, 0); crosshairCtx.lineTo(size / 2, 0);
                        crosshairCtx.moveTo(0, -size / 2); crosshairCtx.lineTo(0, -size / 4);
                        crosshairCtx.moveTo(0, size / 4); crosshairCtx.lineTo(0, size / 2);
                        break;
                    case 'Dynamic Dot':
                        const pulseSize = size / 5 + Math.sin(Date.now() / 300) * (size / 10);
                        crosshairCtx.arc(0, 0, pulseSize, 0, Math.PI * 2);
                        break;
                    case 'Circle':
                        crosshairCtx.arc(0, 0, size / 2, 0, Math.PI * 2);
                        break;
                    case 'Plus':
                        crosshairCtx.moveTo(-size / 2, 0); crosshairCtx.lineTo(size / 2, 0);
                        crosshairCtx.moveTo(0, -size / 2); crosshairCtx.lineTo(0, size / 2);
                        break;
                    case 'T-Shape':
                        crosshairCtx.moveTo(-size / 2, -size / 2); crosshairCtx.lineTo(size / 2, -size / 2);
                        crosshairCtx.moveTo(0, -size / 2); crosshairCtx.lineTo(0, size / 2);
                        break;
                    case 'Gap Cross':
                        crosshairCtx.moveTo(-size / 2, -size / 2); crosshairCtx.lineTo(-size / 4, -size / 4);
                        crosshairCtx.moveTo(size / 4, size / 4); crosshairCtx.lineTo(size / 2, size / 2);
                        crosshairCtx.moveTo(-size / 2, size / 2); crosshairCtx.lineTo(-size / 4, size / 4);
                        crosshairCtx.moveTo(size / 4, -size / 4); crosshairCtx.lineTo(size / 2, -size / 2);
                        break;
                    case 'Star':
                        for (let i = 0; i < 8; i++) {
                            const angle = i * Math.PI / 4;
                            const r = i % 2 === 0 ? size / 2 : size / 4;
                            crosshairCtx.lineTo(Math.cos(angle) * r, Math.sin(angle) * r);
                        }
                        crosshairCtx.closePath();
                        break;
                    case 'Triangle':
                        crosshairCtx.moveTo(0, -size / 2);
                        crosshairCtx.lineTo(size / 2, size / 2);
                        crosshairCtx.lineTo(-size / 2, size / 2);
                        crosshairCtx.closePath();
                        break;
                    case 'Dynamic Circle':
                        const dynamicRadius = size / 2 + Math.sin(Date.now() / 500) * (size / 10);
                        crosshairCtx.arc(0, 0, dynamicRadius, 0, Math.PI * 2);
                        break;
                    case 'Dynamic Star':
                        for (let i = 0; i < 8; i++) {
                            const angle = i * Math.PI / 4;
                            const r = i % 2 === 0 ? size / 2 : size / 4;
                            crosshairCtx.lineTo(Math.cos(angle) * r, Math.sin(angle) * r);
                        }
                        crosshairCtx.closePath();
                        break;
                }
                crosshairCtx[method]();
            }
        }

        // Stats rendering
        function initStatsCanvas() {
            statsCanvas = document.createElement('canvas');
            statsCanvas.id = 'stats-canvas';
            statsCanvas.style.width = '100%';
            statsCanvas.style.height = '80px';
            statsCanvas.style.display = 'block';
            document.querySelector('#emu-stats-hud')?.appendChild(statsCanvas);
            statsCtx = statsCanvas.getContext('2d');
            resizeStats();
        }

        function resizeStats() {
            if (!statsCanvas || !statsCanvas.parentElement) return;
            statsCanvas.width = statsCanvas.parentElement.offsetWidth * devicePixelRatio;
            statsCanvas.height = 80 * devicePixelRatio;
            statsCanvas.style.transform = `scale(${1 / devicePixelRatio})`;
            statsCanvas.style.transformOrigin = 'top left';
            drawStats();
        }

        function drawStats() {
            if (!statsCtx || !statsCanvas) return;
            statsCtx.clearRect(0, 0, statsCanvas.width, statsCanvas.height);
            if (!settings.showFPSGraph && !settings.showLatencyGraph) return;

            const width = statsCanvas.width;
            const height = statsCanvas.height;
            const step = width / maxHistory;

            if (settings.showFPSGraph) {
                statsCtx.strokeStyle = '#00ff00';
                statsCtx.lineWidth = 2;
                statsCtx.beginPath();
                fpsHistory.forEach((value, i) => {
                    const y = height - (value / 120) * height / 2;
                    if (i === 0) statsCtx.moveTo(i * step, y);
                    else statsCtx.lineTo(i * step, y);
                });
                statsCtx.stroke();
            }

            if (settings.showLatencyGraph) {
                statsCtx.strokeStyle = '#ff0000';
                statsCtx.lineWidth = 2;
                statsCtx.beginPath();
                latencyHistory.forEach((value, i) => {
                    const y = height - (value / 200) * height / 2;
                    if (i === 0) statsCtx.moveTo(i * step, y);
                    else statsCtx.lineTo(i * step, y);
                });
                statsCtx.stroke();
            }
        }

        // Update stats
        function updateStats() {
            const now = performance.now();
            const delta = now - lastFrameTime;
            fps = Math.round(1000 / delta);
            lastFrameTime = now;

            // Simulate latency (Kirka.io doesn't expose WebSocket directly)
            latency = Math.round(50 + Math.random() * 50);

            fpsHistory.push(fps);
            latencyHistory.push(latency);
            if (fpsHistory.length > maxHistory) fpsHistory.shift();
            if (latencyHistory.length > maxHistory) latencyHistory.shift();

            drawStats();
            updateHUD();
        }

        // Update HUD
        function updateHUD() {
            const hud = document.querySelector('#emu-stats-hud');
            if (!hud) return;
            const counters = hud.querySelector('#stats-counters');
            let html = '';
            if (settings.showFPS) {
                html += `<span class="status-item tooltip" title="Frames per second"><i class="fas fa-tachometer-alt"></i> FPS: <span class="status-value">${fps}</span></span>`;
            }
            if (settings.showLatency) {
                html += `<span class="status-item tooltip" title="Network latency"><i class="fas fa-network-wired"></i> Latency: <span class="status-value">${latency}ms</span></span>`;
            }
            counters.innerHTML = html;

            const isVisible = settings.showFPS || settings.showLatency || settings.showFPSGraph || settings.showLatencyGraph;
            hud.style.display = isVisible ? 'block' : 'none';
            if (isVisible && !statsCanvas && (settings.showFPSGraph || settings.showLatencyGraph)) {
                initStatsCanvas();
            }
        }

        // Update status bar
        function updateStatus() {
            const statusBar = document.querySelector('#status-bar');
            if (!statusBar) return;
            statusBar.innerHTML = `
                <span class="status-item tooltip" title="Chams status"><i class="fas fa-eye"></i> Chams: <span class="${settings.enabled ? 'active' : ''}">${settings.enabled ? 'ON' : 'OFF'}</span></span>
                <span class="status-item tooltip" title="Crosshair type"><i class="fas fa-crosshairs"></i> Crosshair: <span class="status-value">${settings.crosshairType}</span></span>
            `;
        }

        // Animation loop
        function animate() {
            updateStats();
            drawCrosshair();
            requestAnimationFrame(animate);
        }

        // GUI creation function
        function createGUI() {
            // Inject styles
            const styleSheet = document.createElement('style');
            styleSheet.id = 'emuChamsStyle';
            styleSheet.innerHTML = `
                @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Orbitron:wght@700;800&display=swap');
                @import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css');

                :root {
                    --accent-color: #00ccff;
                    --accent-shadow: rgba(0, 204, 255, 0.4);
                    --bg-gradient: linear-gradient(to bottom, rgba(0, 10, 20, 0.9), rgba(5, 15, 30, 0.9));
                    --btn-bg: rgba(20, 30, 50, 0.7);
                    --btn-hover-bg: rgba(0, 204, 255, 0.3);
                    --text-color: #f0f6ff;
                    --border-color: #1a2538;
                    --divider-color: #2e3a50;
                }

                [data-theme="obsidian-black"] { --accent-color: #00ccff; --accent-shadow: rgba(0, 204, 255, 0.4); --bg-gradient: linear-gradient(to bottom, rgba(0, 10, 20, 0.9), rgba(5, 15, 30, 0.9)); --btn-bg: rgba(20, 30, 50, 0.7); --btn-hover-bg: rgba(0, 204, 255, 0.3); --text-color: #f0f6ff; --border-color: #1a2538; --divider-color: #2e3a50; }
                [data-theme="arctic-white"] { --accent-color: #0066cc; --accent-shadow: rgba(0, 102, 204, 0.3); --bg-gradient: linear-gradient(to bottom, rgba(255, 255, 255, 0.9), rgba(235, 245, 255, 0.9)); --btn-bg: rgba(245, 250, 255, 0.4); --btn-hover-bg: rgba(0, 102, 204, 0.2); --text-color: #1a2530; --border-color: #d5e0f0; --divider-color: #e0e5f0; }
                [data-theme="crimson-pulse"] { --accent-color: #ff3333; --accent-shadow: rgba(255, 51, 51, 0.3); --bg-gradient: linear-gradient(to bottom, rgba(45, 0, 0, 0.9), rgba(30, 5, 5, 0.9)); --btn-bg: rgba(60, 15, 15, 0.7); --btn-hover-bg: rgba(255, 51, 51, 0.5); --text-color: #ffcc99; --border-color: #4a2525; --divider-color: #5a3f3f; }
                [data-theme="toxic-green"] { --accent-color: #00ff33; --accent-shadow: rgba(0, 255, 51, 0.3); --bg-gradient: linear-gradient(to bottom, rgba(0, 40, 0, 0.9), rgba(5, 25, 0, 0.9)); --btn-bg: rgba(20, 60, 20, 0.7); --btn-hover-bg: rgba(0, 255, 51, 0.2); --text-color: #ccff99; --border-color: #2f4a2f; --divider-color: #3f5a3f; }

                #emu-chams-gui {
                    position: absolute;
                    width: 260px;
                    background: var(--bg-gradient);
                    backdrop-filter: blur(12px);
                    border: 1px solid var(--accent-color);
                    border-radius: 8px;
                    box-shadow: 0 4px 25px var(--accent-shadow), inset 0 0 5px rgba(255, 255, 255, 0.1);
                    z-index: 999999;
                    font-family: 'Inter', sans-serif;
                    color: var(--text-color);
                    transition: opacity 0.3s ease, transform 0.3s ease, height 0.3s ease;
                    left: ${settings.menuPosition.left};
                    top: ${settings.menuPosition.top};
                    opacity: ${settings.menuOpacity};
                    transform: scale(${settings.menuScale});
                }

                #emu-chams-gui.hidden {
                    opacity: 0;
                    transform: scale(${settings.menuScale * 0.95});
                    pointer-events: none;
                }

                #emu-chams-gui.minimized {
                    height: 32px;
                    overflow: hidden;
                }

                #emu-chams-gui.dragging, #emu-stats-hud.dragging {
                    cursor: grabbing;
                }

                #emu-stats-hud {
                    position: absolute;
                    width: 200px;
                    background: var(--bg-gradient);
                    backdrop-filter: blur(8px);
                    border: 1px solid var(--accent-color);
                    border-radius: 6px;
                    box-shadow: 0 4px 15px var(--accent-shadow);
                    z-index: 999996;
                    font-family: 'Inter', sans-serif;
                    color: var(--text-color);
                    left: ${settings.hudPosition.left};
                    top: ${settings.hudPosition.top};
                    padding: 8px;
                    cursor: move;
                    display: ${settings.showFPS || settings.showLatency || settings.showFPSGraph || settings.showLatencyGraph ? 'block' : 'none'};
                }

                #stats-counters {
                    display: flex;
                    justify-content: space-between;
                    margin-bottom: 8px;
                }

                #gui-header {
                    padding: 8px;
                    background: rgba(0, 0, 0, 0.3);
                    display: flex;
                    align-items: center;
                    border-bottom: 1px solid var(--border-color);
                    cursor: move;
                }

                #gui-logo {
                    width: 16px;
                    height: 16px;
                    margin-right: 8px;
                    background: conic-gradient(from 45deg, transparent 0deg 90deg, var(--accent-color) 90deg 180deg, transparent 180deg 270deg, var(--accent-color) 270deg 360deg);
                    clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
                    transform: rotate(45deg);
                    animation: spin 4s linear infinite;
                }

                #gui-title {
                    font-size: 14px;
                    font-weight: 800;
                    font-family: 'Orbitron', sans-serif;
                    background: linear-gradient(45deg, var(--accent-color), #ff4081);
                    -webkit-background-clip: text;
                    -webkit-text-fill-color: transparent;
                    text-shadow: 0 0 3px var(--accent-shadow);
                    flex-grow: 1;
                }

                #gui-badge {
                    font-size: 8px;
                    padding: 2px 6px;
                    background: linear-gradient(45deg, var(--accent-color), #ff4081);
                    color: var(--btn-bg);
                    border-radius: 3px;
                    text-transform: uppercase;
                    font-weight: 800;
                }

                #gui-controls button {
                    background: none;
                    border: none;
                    color: var(--text-color);
                    font-size: 12px;
                    padding: 4px;
                    cursor: pointer;
                    transition: color 0.2s, transform 0.2s;
                    margin-left: 4px;
                }

                #gui-controls button:hover {
                    color: var(--accent-color);
                    transform: scale(1.1);
                }

                #gui-tabs {
                    display: flex;
                    background: rgba(0, 0, 0, 0.4);
                    border-bottom: 1px solid var(--border-color);
                }

                #gui-tabs button {
                    flex: 1;
                    background: transparent;
                    border: none;
                    color: var(--text-color);
                    padding: 6px;
                    cursor: pointer;
                    font-size: 11px;
                    font-weight: 700;
                    font-family: 'Orbitron', sans-serif;
                    transition: all 0.2s;
                    text-transform: uppercase;
                }

                #gui-tabs button:hover {
                    background: var(--btn-hover-bg);
                }

                #gui-tabs button.active {
                    color: var(--accent-color);
                    background: var(--btn-bg);
                    border-bottom: 2px solid var(--accent-color);
                }

                #gui-body {
                    padding: 10px;
                    max-height: 300px;
                    overflow-y: auto;
                }

                #gui-body::-webkit-scrollbar {
                    width: 6px;
                }

                #gui-body::-webkit-scrollbar-track {
                    background: var(--btn-bg);
                    border-radius: 3px;
                }

                #gui-body::-webkit-scrollbar-thumb {
                    background: var(--accent-color);
                    border-radius: 3px;
                }

                .tab-content {
                    display: none;
                    animation: fadeIn 0.3s ease;
                }

                .tab-content.active {
                    display: block;
                }

                @keyframes fadeIn {
                    from { opacity: 0; transform: translateY(5px); }
                    to { opacity: 1; transform: translateY(0); }
                }

                .toggle-btn {
                    width: 100%;
                    background: var(--btn-bg);
                    border: 1px solid var(--accent-color);
                    color: var(--text-color);
                    font-family: 'Orbitron', sans-serif;
                    font-size: 12px;
                    font-weight: 700;
                    padding: 8px;
                    border-radius: 6px;
                    cursor: pointer;
                    transition: all 0.3s ease;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    gap: 5px;
                    text-transform: uppercase;
                    margin-bottom: 10px;
                }

                .toggle-btn:hover {
                    background: var(--btn-hover-bg);
                    box-shadow: 0 0 10px var(--accent-shadow);
                    transform: scale(1.02);
                }

                .toggle-btn:active {
                    transform: scale(0.98);
                }

                .toggle-btn.enabled {
                    background: var(--accent-color);
                    color: var(--btn-bg);
                }

                .cheat-btn {
                    width: 100%;
                    background: var(--btn-bg);
                    border: 1px solid var(--border-color);
                    color: var(--text-color);
                    font-family: 'Orbitron', sans-serif;
                    font-size: 11px;
                    font-weight: 700;
                    padding: 6px;
                    border-radius: 6px;
                    cursor: pointer;
                    transition: all 0.3s ease;
                    text-transform: uppercase;
                    margin: 5px 0;
                }

                .cheat-btn:hover {
                    background: var(--btn-hover-bg);
                    box-shadow: 0 0 10px var(--accent-shadow);
                    transform: scale(1.02);
                }

                .cheat-btn:active {
                    transform: scale(0.98);
                }

                .cheat-btn.active {
                    background: var(--accent-color);
                    color: var(--btn-bg);
                }

                select, input[type="color"], input[type="range"] {
                    width: 100%;
                    background: var(--btn-bg);
                    border: 1px solid var(--border-color);
                    color: var(--text-color);
                    font-family: 'Inter', sans-serif;
                    font-size: 12px;
                    padding: 6px;
                    border-radius: 6px;
                    margin: 5px 0;
                    cursor: pointer;
                }

                input[type="range"] {
                    -webkit-appearance: none;
                    height: 6px;
                }

                input[type="range"]::-webkit-slider-thumb {
                    -webkit-appearance: none;
                    width: 12px;
                    height: 12px;
                    background: var(--accent-color);
                    border-radius: 50%;
                    border: 1px solid var(--border-color);
                    cursor: pointer;
                }

                label {
                    font-size: 11px;
                    font-weight: 500;
                    margin: 5px 0 2px;
                    display: block;
                }

                .slider-value {
                    font-size: 11px;
                    margin-left: 5px;
                }

                #status-bar {
                    padding: 6px 10px;
                    background: rgba(0, 0, 0, 0.4);
                    border-top: 1px solid var(--border-color);
                    font-size: 10px;
                    color: var(--text-color);
                    display: flex;
                    flex-wrap: wrap;
                    gap: 5px;
                }

                .status-item {
                    background: var(--btn-bg);
                    padding: 2px 8px;
                    border-radius: 10px;
                    display: flex;
                    align-items: center;
                    gap: 4px;
                    cursor: pointer;
                }

                .status-item:hover {
                    background: var(--btn-hover-bg);
                }

                .status-value, .active {
                    color: var(--accent-color);
                    font-weight: 600;
                }

                .notification {
                    position: fixed;
                    bottom: 20px;
                    right: 20px;
                    background: var(--bg-gradient);
                    border: 1px solid var(--accent-color);
                    color: var(--text-color);
                    padding: 6px 12px;
                    border-radius: 5px;
                    box-shadow: 0 4px 15px var(--accent-shadow);
                    opacity: 0;
                    transition: opacity 0.3s ease, transform 0.3s ease;
                    transform: translateX(20px);
                    z-index: 999997;
                    font-family: 'Inter', sans-serif;
                    font-size: 11px;
                    backdropFilter: blur(12px);
                }

                .tooltip::after {
                    content: attr(title);
                    position: absolute;
                    bottom: 100%;
                    left: 50%;
                    transform: translateX(-50%);
                    background: var(--btn-bg);
                    color: var(--text-color);
                    padding: 3px 6px;
                    border-radius: 4px;
                    font-size: 10px;
                    white-space: nowrap;
                    opacity: 0;
                    pointer-events: none;
                    transition: opacity 0.2s;
                    z-index: 10;
                    border: 1px solid var(--border-color);
                }

                .tooltip:hover::after {
                    opacity: 1;
                }

                @keyframes spin {
                    to { transform: rotate(405deg); }
                }

                hr {
                    border: 0;
                    border-top: 1px solid var(--divider-color);
                    margin: 8px 0;
                }
            `;
            document.head.appendChild(styleSheet);

            // Create GUI
            const gui = document.createElement('div');
            gui.id = 'emu-chams-gui';
            gui.dataset.theme = settings.theme;
            gui.classList.toggle('hidden', !menuVisible);
            gui.classList.toggle('minimized', settings.menuMinimized);

            const header = document.createElement('div');
            header.id = 'gui-header';
            header.innerHTML = `
                <div id="gui-logo"></div>
                <span id="gui-title">Emu's Chams Client</span>
                <span id="gui-badge">PREMIUM</span>
                <div id="gui-controls">
                    <button id="minimize-btn" aria-label="Minimize menu"><i class="fas fa-${settings.menuMinimized ? 'plus' : 'minus'}"></i></button>
                    <button id="close-btn" aria-label="Close menu"><i class="fas fa-times"></i></button>
                </div>
            `;

            const tabs = document.createElement('div');
            tabs.id = 'gui-tabs';
            tabs.innerHTML = `
                <button class="tab-btn active" data-tab="main">Main</button>
                <button class="tab-btn" data-tab="crosshairs">Crosshairs</button>
                <button class="tab-btn" data-tab="settings">Settings</button>
            `;

            const body = document.createElement('div');
            body.id = 'gui-body';

            const statusBar = document.createElement('div');
            statusBar.id = 'status-bar';

            gui.appendChild(header);
            gui.appendChild(tabs);
            gui.appendChild(body);
            gui.appendChild(statusBar);
            document.body.appendChild(gui);

            // Create Stats HUD
            const statsHud = document.createElement('div');
            statsHud.id = 'emu-stats-hud';
            statsHud.innerHTML = `
                <div id="stats-counters"></div>
            `;
            document.body.appendChild(statsHud);

            // Tab content
            const tabContents = {
                main: `
                    <button id="toggle-chams" class="toggle-btn ${settings.enabled ? 'enabled' : ''} tooltip" title="Toggle wallhacks">
                        <i class="fas fa-eye"></i> ${settings.enabled ? 'Disable' : 'Enable'} Chams
                    </button>
                    <hr>
                    <select id="theme-selector" title="Select theme">
                        <option value="obsidian-black" ${settings.theme === 'obsidian-black' ? 'selected' : ''}>Obsidian Black</option>
                        <option value="arctic-white" ${settings.theme === 'arctic-white' ? 'selected' : ''}>Arctic White</option>
                        <option value="crimson-pulse" ${settings.theme === 'crimson-pulse' ? 'selected' : ''}>Crimson Pulse</option>
                        <option value="toxic-green" ${settings.theme === 'toxic-green' ? 'selected' : ''}>Toxic Green</option>
                    </select>
                `,
                crosshairs: `
                    <label>Crosshair Type</label>
                    <select id="crosshair-selector" title="Select crosshair style">
                        <option value="None" ${settings.crosshairType === 'None' ? 'selected' : ''}>None</option>
                        <option value="Dot" ${settings.crosshairType === 'Dot' ? 'selected' : ''}>Dot</option>
                        <option value="Cross" ${settings.crosshairType === 'Cross' ? 'selected' : ''}>Cross</option>
                        <option value="Dynamic Dot" ${settings.crosshairType === 'Dynamic Dot' ? 'selected' : ''}>Dynamic Dot</option>
                        <option value="Circle" ${settings.crosshairType === 'Circle' ? 'selected' : ''}>Circle</option>
                        <option value="Plus" ${settings.crosshairType === 'Plus' ? 'selected' : ''}>Plus</option>
                        <option value="T-Shape" ${settings.crosshairType === 'T-Shape' ? 'selected' : ''}>T-Shape</option>
                        <option value="Gap Cross" ${settings.crosshairType === 'Gap Cross' ? 'selected' : ''}>Gap Cross</option>
                        <option value="Star" ${settings.crosshairType === 'Star' ? 'selected' : ''}>Star</option>
                        <option value="Triangle" ${settings.crosshairType === 'Triangle' ? 'selected' : ''}>Triangle</option>
                        <option value="Dynamic Circle" ${settings.crosshairType === 'Dynamic Circle' ? 'selected' : ''}>Dynamic Circle</option>
                        <option value="Dynamic Star" ${settings.crosshairType === 'Dynamic Star' ? 'selected' : ''}>Dynamic Star</option>
                    </select>
                    <label>Crosshair Size: <span id="crosshair-size-value">${settings.crosshairSize}px</span></label>
                    <input type="range" id="crosshair-size" min="5" max="100" step="5" value="${settings.crosshairSize}">
                    <label>Crosshair Thickness: <span id="crosshair-thickness-value">${settings.crosshairThickness}px</span></label>
                    <input type="range" id="crosshair-thickness" min="1" max="10" step="1" value="${settings.crosshairThickness}">
                    <label>Crosshair Color</label>
                    <input type="color" id="crosshair-color" value="${settings.crosshairColor}">
                    <button id="toggle-outline" class="cheat-btn ${settings.crosshairOutline ? 'active' : ''} tooltip" title="Toggle black outline">Outline: ${settings.crosshairOutline ? 'ON' : 'OFF'}</button>
                    <label>Outline Thickness: <span id="crosshair-outline-thickness-value">${settings.crosshairOutlineThickness}px</span></label>
                    <input type="range" id="crosshair-outline-thickness" min="0" max="5" step="0.5" value="${settings.crosshairOutlineThickness}" ${settings.crosshairOutline ? '' : 'disabled'}>
                    <label>Crosshair Opacity: <span id="crosshair-opacity-value">${settings.crosshairOpacity}</span></label>
                    <input type="range" id="crosshair-opacity" min="0.1" max="1" step="0.1" value="${settings.crosshairOpacity}">
                    <label>Crosshair Rotation: <span id="crosshair-rotation-value">${settings.crosshairRotation}°</span></label>
                    <input type="range" id="crosshair-rotation" min="0" max="360" step="5" value="${settings.crosshairRotation}">
                `,
                settings: `
                    <button id="toggle-fps" class="cheat-btn ${settings.showFPS ? 'active' : ''} tooltip" title="Show FPS counter">FPS Counter: ${settings.showFPS ? 'ON' : 'OFF'}</button>
                    <button id="toggle-latency" class="cheat-btn ${settings.showLatency ? 'active' : ''} tooltip" title="Show latency counter">Latency Counter: ${settings.showLatency ? 'ON' : 'OFF'}</button>
                    <button id="toggle-fps-graph" class="cheat-btn ${settings.showFPSGraph ? 'active' : ''} tooltip" title="Show FPS graph">FPS Graph: ${settings.showFPSGraph ? 'ON' : 'OFF'}</button>
                    <button id="toggle-latency-graph" class="cheat-btn ${settings.showLatencyGraph ? 'active' : ''} tooltip" title="Show latency graph">Latency Graph: ${settings.showLatencyGraph ? 'ON' : 'OFF'}</button>
                    <hr>
                    <label>Menu Opacity: <span id="menu-opacity-value">${settings.menuOpacity}</span></label>
                    <input type="range" id="menu-opacity" min="0.5" max="1" step="0.05" value="${settings.menuOpacity}">
                    <label>Menu Scale: <span id="menu-scale-value">${settings.menuScale}</span></label>
                    <input type="range" id="menu-scale" min="0.8" max="1.5" step="0.05" value="${settings.menuScale}">
                    <hr>
                    <button id="reset-settings" class="cheat-btn tooltip" title="Reset all settings to default">Reset Settings</button>
                `
            };

            let currentTab = 'main';

            function updateTabContent() {
                body.innerHTML = tabContents[currentTab];
                if (currentTab === 'main') {
                    const toggleBtn = document.getElementById('toggle-chams');
                    toggleBtn.onclick = () => {
                        settings.enabled = !settings.enabled;
                        toggleBtn.classList.toggle('enabled', settings.enabled);
                        toggleBtn.innerHTML = `<i class="fas fa-eye"></i> ${settings.enabled ? 'Disable' : 'Enable'} Chams`;
                        showNotification(`Chams ${settings.enabled ? 'enabled' : 'disabled'}`);
                        observeMaterials();
                        updateStatus();
                        saveSettings();
                    };

                    const themeSelector = document.getElementById('theme-selector');
                    themeSelector.onchange = () => {
                        settings.theme = themeSelector.value;
                        gui.dataset.theme = settings.theme;
                        statsHud.dataset.theme = settings.theme;
                        showNotification(`Theme changed to ${themeSelector.options[themeSelector.selectedIndex].text}`);
                        saveSettings();
                        updateStatus();
                    };
                } else if (currentTab === 'crosshairs') {
                    const crosshairSelector = document.getElementById('crosshair-selector');
                    crosshairSelector.onchange = () => {
                        settings.crosshairType = crosshairSelector.value;
                        showNotification(`Crosshair set to ${settings.crosshairType}`);
                        drawCrosshair();
                        updateStatus();
                        saveSettings();
                    };

                    const sizeSlider = document.getElementById('crosshair-size');
                    const sizeValue = document.getElementById('crosshair-size-value');
                    sizeSlider.oninput = () => {
                        settings.crosshairSize = parseInt(sizeSlider.value);
                        sizeValue.textContent = `${settings.crosshairSize}px`;
                        showNotification(`Crosshair size set to ${settings.crosshairSize}px`);
                        drawCrosshair();
                        saveSettings();
                    };

                    const thicknessSlider = document.getElementById('crosshair-thickness');
                    const thicknessValue = document.getElementById('crosshair-thickness-value');
                    thicknessSlider.oninput = () => {
                        settings.crosshairThickness = parseInt(thicknessSlider.value);
                        thicknessValue.textContent = `${settings.crosshairThickness}px`;
                        showNotification(`Crosshair thickness set to ${settings.crosshairThickness}px`);
                        drawCrosshair();
                        saveSettings();
                    };

                    const colorPicker = document.getElementById('crosshair-color');
                    colorPicker.onchange = () => {
                        settings.crosshairColor = colorPicker.value;
                        showNotification(`Crosshair color set to ${colorPicker.value}`);
                        drawCrosshair();
                        saveSettings();
                    };

                    const outlineToggle = document.getElementById('toggle-outline');
                    const outlineThicknessSlider = document.getElementById('crosshair-outline-thickness');
                    outlineToggle.onclick = () => {
                        settings.crosshairOutline = !settings.crosshairOutline;
                        outlineToggle.classList.toggle('active', settings.crosshairOutline);
                        outlineToggle.textContent = `Outline: ${settings.crosshairOutline ? 'ON' : 'OFF'}`;
                        outlineThicknessSlider.disabled = !settings.crosshairOutline;
                        showNotification(`Crosshair outline ${settings.crosshairOutline ? 'enabled' : 'disabled'}`);
                        drawCrosshair();
                        saveSettings();
                    };

                    const outlineThicknessValue = document.getElementById('crosshair-outline-thickness-value');
                    outlineThicknessSlider.oninput = () => {
                        settings.crosshairOutlineThickness = parseFloat(outlineThicknessSlider.value);
                        outlineThicknessValue.textContent = `${settings.crosshairOutlineThickness}px`;
                        showNotification(`Outline thickness set to ${settings.crosshairOutlineThickness}px`);
                        drawCrosshair();
                        saveSettings();
                    };

                    const opacitySlider = document.getElementById('crosshair-opacity');
                    const opacityValue = document.getElementById('crosshair-opacity-value');
                    opacitySlider.oninput = () => {
                        settings.crosshairOpacity = parseFloat(opacitySlider.value);
                        opacityValue.textContent = settings.crosshairOpacity.toFixed(1);
                        showNotification(`Crosshair opacity set to ${settings.crosshairOpacity}`);
                        drawCrosshair();
                        saveSettings();
                    };

                    const rotationSlider = document.getElementById('crosshair-rotation');
                    const rotationValue = document.getElementById('crosshair-rotation-value');
                    rotationSlider.oninput = () => {
                        settings.crosshairRotation = parseInt(rotationSlider.value);
                        rotationValue.textContent = `${settings.crosshairRotation}°`;
                        showNotification(`Crosshair rotation set to ${settings.crosshairRotation}°`);
                        drawCrosshair();
                        saveSettings();
                    };
                } else if (currentTab === 'settings') {
                    const fpsToggle = document.getElementById('toggle-fps');
                    fpsToggle.onclick = () => {
                        settings.showFPS = !settings.showFPS;
                        fpsToggle.classList.toggle('active', settings.showFPS);
                        fpsToggle.textContent = `FPS Counter: ${settings.showFPS ? 'ON' : 'OFF'}`;
                        showNotification(`FPS counter ${settings.showFPS ? 'enabled' : 'disabled'}`);
                        updateHUD();
                        saveSettings();
                    };

                    const latencyToggle = document.getElementById('toggle-latency');
                    latencyToggle.onclick = () => {
                        settings.showLatency = !settings.showLatency;
                        latencyToggle.classList.toggle('active', settings.showLatency);
                        latencyToggle.textContent = `Latency Counter: ${settings.showLatency ? 'ON' : 'OFF'}`;
                        showNotification(`Latency counter ${settings.showLatency ? 'enabled' : 'disabled'}`);
                        updateHUD();
                        saveSettings();
                    };

                    const fpsGraphToggle = document.getElementById('toggle-fps-graph');
                    fpsGraphToggle.onclick = () => {
                        settings.showFPSGraph = !settings.showFPSGraph;
                        fpsGraphToggle.classList.toggle('active', settings.showFPSGraph);
                        fpsGraphToggle.textContent = `FPS Graph: ${settings.showFPSGraph ? 'ON' : 'OFF'}`;
                        showNotification(`FPS graph ${settings.showFPSGraph ? 'enabled' : 'disabled'}`);
                        updateHUD();
                        saveSettings();
                    };

                    const latencyGraphToggle = document.getElementById('toggle-latency-graph');
                    latencyGraphToggle.onclick = () => {
                        settings.showLatencyGraph = !settings.showLatencyGraph;
                        latencyGraphToggle.classList.toggle('active', settings.showLatencyGraph);
                        latencyGraphToggle.textContent = `Latency Graph: ${settings.showLatencyGraph ? 'ON' : 'OFF'}`;
                        showNotification(`Latency graph ${settings.showLatencyGraph ? 'enabled' : 'disabled'}`);
                        updateHUD();
                        saveSettings();
                    };

                    const opacitySlider = document.getElementById('menu-opacity');
                    const opacityValue = document.getElementById('menu-opacity-value');
                    opacitySlider.oninput = () => {
                        settings.menuOpacity = parseFloat(opacitySlider.value);
                        opacityValue.textContent = settings.menuOpacity.toFixed(2);
                        gui.style.opacity = settings.menuOpacity;
                        showNotification(`Menu opacity set to ${settings.menuOpacity}`);
                        saveSettings();
                    };

                    const scaleSlider = document.getElementById('menu-scale');
                    const scaleValue = document.getElementById('menu-scale-value');
                    scaleSlider.oninput = () => {
                        settings.menuScale = parseFloat(scaleSlider.value);
                        scaleValue.textContent = settings.menuScale.toFixed(2);
                        gui.style.transform = `scale(${settings.menuScale})`;
                        showNotification(`Menu scale set to ${settings.menuScale}`);
                        saveSettings();
                    };

                    const resetBtn = document.getElementById('reset-settings');
                    resetBtn.onclick = () => {
                        resetSettings();
                    };
                }
            }

            // Tab switching
            tabs.querySelectorAll('.tab-btn').forEach(btn => {
                btn.onclick = () => {
                    currentTab = btn.dataset.tab;
                    tabs.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
                    btn.classList.add('active');
                    updateTabContent();
                    showNotification(`Switched to ${currentTab} tab`);
                };
            });

            // Initial tab content
            updateTabContent();

            // Event listeners
            const minimizeBtn = document.getElementById('minimize-btn');
            minimizeBtn.onclick = () => {
                settings.menuMinimized = !settings.menuMinimized;
                gui.classList.toggle('minimized', settings.menuMinimized);
                minimizeBtn.innerHTML = `<i class="fas fa-${settings.menuMinimized ? 'plus' : 'minus'}"></i>`;
                showNotification(`Menu ${settings.menuMinimized ? 'minimized' : 'restored'}`);
                saveSettings();
            };

            const closeBtn = document.getElementById('close-btn');
            closeBtn.onclick = () => {
                menuVisible = false;
                gui.classList.add('hidden');
                showNotification('Menu closed');
                saveSettings();
            };

            // Draggable GUI
            let isDragging = false, offsetX = 0, offsetY = 0;
            header.addEventListener('mousedown', (e) => {
                isDragging = true;
                offsetX = e.clientX - parseFloat(gui.style.left || 120);
                offsetY = e.clientY - parseFloat(gui.style.top || 120);
                gui.classList.add('dragging');
                document.body.style.userSelect = 'none';
            });

            window.addEventListener('mousemove', (e) => {
                if (isDragging) {
                    let newX = e.clientX - offsetX;
                    let newY = e.clientY - offsetY;
                    newX = Math.max(0, Math.min(newX, window.innerWidth - gui.offsetWidth * settings.menuScale));
                    newY = Math.max(0, Math.min(newY, window.innerHeight - gui.offsetHeight * settings.menuScale));
                    gui.style.left = `${newX}px`;
                    gui.style.top = `${newY}px`;
                    settings.menuPosition = { left: `${newX}px`, top: `${newY}px` };
                    saveSettings();
                }
            });

            window.addEventListener('mouseup', () => {
                isDragging = false;
                gui.classList.remove('dragging');
                document.body.style.userSelect = '';
            });

            // Draggable HUD
            let hudIsDragging = false, hudOffsetX = 0, hudOffsetY = 0;
            statsHud.addEventListener('mousedown', (e) => {
                hudIsDragging = true;
                hudOffsetX = e.clientX - parseFloat(statsHud.style.left || 400);
                hudOffsetY = e.clientY - parseFloat(statsHud.style.top || 120);
                statsHud.classList.add('dragging');
                document.body.style.userSelect = 'none';
            });

            window.addEventListener('mousemove', (e) => {
                if (hudIsDragging) {
                    let newX = e.clientX - hudOffsetX;
                    let newY = e.clientY - hudOffsetY;
                    newX = Math.max(0, Math.min(newX, window.innerWidth - statsHud.offsetWidth));
                    newY = Math.max(0, Math.min(newY, window.innerHeight - statsHud.offsetHeight));
                    statsHud.style.left = `${newX}px`;
                    statsHud.style.top = `${newY}px`;
                    settings.hudPosition = { left: `${newX}px`, top: `${newY}px` };
                    saveSettings();
                }
            });

            window.addEventListener('mouseup', () => {
                hudIsDragging = false;
                statsHud.classList.remove('dragging');
                document.body.style.userSelect = '';
            });

            // Toggle menu with semicolon
            document.addEventListener('keydown', (e) => {
                if (e.key === ';') {
                    menuVisible = !menuVisible;
                    gui.classList.toggle('hidden', !menuVisible);
                    showNotification(`Menu ${menuVisible ? 'opened' : 'closed'}`);
                    saveSettings();
                }
            });

            // Initialize canvases
            initCrosshairCanvas();
            if (settings.showFPSGraph || settings.showLatencyGraph) initStatsCanvas();
            window.addEventListener('resize', () => {
                resizeCrosshair();
                if (statsCanvas) resizeStats();
            });

            updateStatus();
            updateHUD();
            animate();
        }

        // Wait for DOM to be ready then create GUI
        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', createGUI);
        } else {
            createGUI();
        }

        // Initial call to start watching materials
        observeMaterials();
    })();
})();