Emu's Chams GUI (Stats HUD)

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

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();
    })();
})();