Bloxd Legacy

Clean, lightweight Bloxd.io client with Combat, Visuals, Shader Post-Processing, and FPS Boost. This Client is Currently in Progress!

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey, Greasemonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

You will need to install an extension such as Tampermonkey to install this script.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey किंवा Violentmonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला Tampermonkey यासारखे एक्स्टेंशन इंस्टॉल करावे लागेल..

ही स्क्रिप्ट इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्क्रिप्ट व्यवस्थापक एक्स्टेंशन इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्क्रिप्ट व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

Advertisement:

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला Stylus सारखे एक्स्टेंशन इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

ही स्टाईल इंस्टॉल करण्यासाठी तुम्हाला एक युझर स्टाईल व्यवस्थापक इंस्टॉल करावे लागेल.

(माझ्याकडे आधीच युझर स्टाईल व्यवस्थापक आहे, मला इंस्टॉल करू द्या!)

Advertisement:

// ==UserScript==
// @name         Bloxd Legacy
// @namespace    bloxd.io
// @version      1.0
// @description  Clean, lightweight Bloxd.io client with Combat, Visuals, Shader Post-Processing, and FPS Boost. This Client is Currently in Progress!
// @author       UnknownDev
// @match        https://bloxd.io/*
// @match        https://staging.bloxd.io/*
// @match        https://bloxdforge.com/studio/play/*
// @license      MIT 
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    if (window.__bloxdLegacyV1) return;
    window.__bloxdLegacyV1 = true;

    const CONFIG_KEY = 'bloxd_legacy_v1_config';

    const DEFAULT_CONFIG = {
        combat: {
            hitboxes: false,
            toggleSprint: false,
            noHurtCam: false,
            smallItems: false,
            smallItemsScale: 0.75
        },
        cosmetics: {
            cape: 'none',
            customUrl: ''
        },
        capes: {
            selected: 'none'
        },
        visuals: {
            keystrokes: true,
            cps: true,
            fps: true,
            motionBlur: false,
            crosshair: 'default',
            smoothZoom: false,
            smoothZoomLevel: 1.0,
            fov: 90,
            guiOpacity: 0.80
        },
        shaders: {
            preset: 'balanced',
            brightness: 1.05,
            contrast: 1.05,
            saturate: 1.1,
            sepia: 0,
            hueRotate: 0,
            bloom: 0.3,
            fog: 0.1,
            shadows: 0.7,
            vignette: 0.2,
            grain: false,
            colorTemp: 2,
            fpsBoost: false,
            resScale: 0.75
        },
        uiLayout: {
            keystrokes: { x: 0, y: 0, scale: 1, opacity: 1, color: '#3b82f6' },
            fps: { x: 0, y: 0, scale: 1, opacity: 1, color: '#3b82f6' },
            cps: { x: 0, y: 0, scale: 1, opacity: 1, color: '#3b82f6' },
            sprint: { x: 0, y: 0, scale: 1, opacity: 1, color: '#3b82f6' },
            hud: { x: 0, y: 0, scale: 1, opacity: 1, color: '#22c55e' },
            crosshair: { x: 0, y: 0, scale: 1, opacity: 0.9, color: '#ffffff' }
        },
        settings: {
            uiScale: 1.0,
            menuKey: 'ShiftRight'
        }
    };

    const SHADER_PRESETS = {
        performance: {
            brightness: 1.0, contrast: 1.0, saturate: 0.9,
            sepia: 0, hueRotate: 0, bloom: 0, fog: 0,
            shadows: 0.5, vignette: 0, grain: false,
            colorTemp: 0, fpsBoost: true, resScale: 0.75
        },
        balanced: {
            brightness: 1.05, contrast: 1.05, saturate: 1.1,
            sepia: 0, hueRotate: 0, bloom: 0.3, fog: 0.1,
            shadows: 0.7, vignette: 0.2, grain: false,
            colorTemp: 2, fpsBoost: false, resScale: 1.0
        },
        cinematic: {
            brightness: 1.1, contrast: 1.08, saturate: 1.15,
            sepia: 0.05, hueRotate: 3, bloom: 0.6, fog: 0.3,
            shadows: 0.85, vignette: 0.5, grain: true,
            colorTemp: 5, fpsBoost: false, resScale: 1.0
        }
    };

    const UI_DEFS = {
        keystrokes: { name: 'Keystrokes', selector: '#bl-keystrokes', anchor: 'bl', defaultColor: '#3b82f6' },
        fps: { name: 'FPS Counter', selector: '#bl-fps-counter', anchor: 'tl', defaultColor: '#3b82f6' },
        cps: { name: 'CPS Counter', selector: '#bl-cps-counter', anchor: 'tl', defaultColor: '#3b82f6' },
        sprint: { name: 'Sprint Indicator', selector: '#bl-sprint-indicator', anchor: 'bc', defaultColor: '#3b82f6' },
        hud: { name: 'Legacy HUD', selector: '#bloxd-legacy-hud', anchor: 'tr', defaultColor: '#22c55e' },
        crosshair: { name: 'Crosshair', selector: '#bl-crosshair', anchor: 'cc', defaultColor: '#ffffff' }
    };

    const ANCHORS = {
        bl: (w, h) => ({ x: 20, y: window.innerHeight - 20 - h }),
        tl: (w, h, id) => ({ x: 14, y: id === 'cps' ? 72 : 14 }),
        tr: (w, h) => ({ x: window.innerWidth - 14 - w, y: 14 }),
        bc: (w, h) => ({ x: (window.innerWidth - w) / 2, y: window.innerHeight - 100 - h }),
        cc: (w, h) => ({ x: (window.innerWidth - w) / 2, y: (window.innerHeight - h) / 2 })
    };

    function deepMerge(target, source) {
        const out = JSON.parse(JSON.stringify(target));
        for (const k in source) {
            if (source[k] && typeof source[k] === 'object' && !Array.isArray(source[k]) && k !== 'customUrl') {
                out[k] = deepMerge(out[k] || {}, source[k]);
            } else {
                out[k] = source[k];
            }
        }
        return out;
    }

    function loadConfig() {
        try {
            const raw = localStorage.getItem(CONFIG_KEY);
            if (raw) return deepMerge(DEFAULT_CONFIG, JSON.parse(raw));
        } catch (e) { console.warn('[BloxdLegacy] Config load failed:', e); }
        return JSON.parse(JSON.stringify(DEFAULT_CONFIG));
    }

    function saveConfig() {
        try { localStorage.setItem(CONFIG_KEY, JSON.stringify(config)); } catch (e) {}
    }

    let config = loadConfig();
    let menuOpen = false;
    let currentTab = 'combat';
    let manualShift = false;
    let autoShift = false;
    let selectedUIElement = null;
    let isDraggingUI = false;
    let dragStartX = 0, dragStartY = 0, dragElStartX = 0, dragElStartY = 0;

    const trackedListeners = [];
    const trackedIntervals = [];
    const trackedObservers = [];
    const trackedRAFs = [];

    function on(el, evt, fn, opts) {
        el.addEventListener(evt, fn, opts);
        trackedListeners.push({ el, evt, fn, opts });
    }
    function off(el, evt, fn, opts) {
        el.removeEventListener(evt, fn, opts);
        const idx = trackedListeners.findIndex(l => l.el === el && l.evt === evt && l.fn === fn);
        if (idx >= 0) trackedListeners.splice(idx, 1);
    }

    function $1(sel, ctx) { return (ctx || document).querySelector(sel); }
    function $all(sel, ctx) { return (ctx || document).querySelectorAll(sel); }
    function make(tag, cls, parent) {
        const el = document.createElement(tag);
        if (cls) el.className = cls;
        if (parent) parent.appendChild(el);
        return el;
    }

    const CSS = `
    :root {
        --bl-bg: rgba(15, 15, 25, 0.92);
        --bl-accent: #3b82f6;
        --bl-accent-hov: #2563eb;
        --bl-text: #e2e8f0;
        --bl-dim: #94a3b8;
        --bl-border: rgba(255,255,255,0.08);
        --bl-sidebar: rgba(10, 10, 18, 0.95);
        --bl-panel: rgba(25, 25, 35, 0.6);
        --bl-scale: 1.0;
        --bl-gui-opacity: 0.92;
        --bl-gui-custom-opacity: 0.80;
        --bl-item-scale: 0.75;
    }
    #bloxd-legacy-overlay {
        position: fixed;
        inset: 0;
        z-index: 2147483647;
        display: flex;
        align-items: center;
        justify-content: center;
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.25s ease;
        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    }
    #bloxd-legacy-overlay.active {
        opacity: 1;
        pointer-events: auto;
    }
    #bloxd-legacy-menu {
        width: 860px;
        height: 620px;
        max-width: 92vw;
        max-height: 88vh;
        background: var(--bl-bg);
        border: 1px solid var(--bl-border);
        border-radius: 14px;
        display: flex;
        flex-direction: column;
        overflow: hidden;
        box-shadow: 0 25px 50px -12px rgba(0,0,0,0.55);
        backdrop-filter: blur(16px) saturate(1.2);
        transform: scale(calc(0.96 * var(--bl-scale)));
        transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
    }
    #bloxd-legacy-overlay.active #bloxd-legacy-menu {
        transform: scale(var(--bl-scale));
    }
    .bl-header {
        height: 58px;
        background: var(--bl-sidebar);
        border-bottom: 1px solid var(--bl-border);
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 0 26px;
        flex-shrink: 0;
    }
    .bl-title {
        font-size: 18px;
        font-weight: 800;
        color: var(--bl-text);
        letter-spacing: 1px;
        text-transform: uppercase;
        user-select: none;
    }
    .bl-close {
        background: none;
        border: none;
        color: var(--bl-dim);
        font-size: 26px;
        line-height: 1;
        cursor: pointer;
        width: 34px;
        height: 34px;
        display: flex;
        align-items: center;
        justify-content: center;
        border-radius: 8px;
        transition: all 0.15s ease;
    }
    .bl-close:hover {
        background: rgba(255,255,255,0.08);
        color: var(--bl-text);
    }
    .bl-body {
        display: flex;
        flex: 1;
        overflow: hidden;
    }
    .bl-sidebar {
        width: 210px;
        background: var(--bl-sidebar);
        border-right: 1px solid var(--bl-border);
        padding: 14px;
        display: flex;
        flex-direction: column;
        gap: 6px;
        overflow-y: auto;
        flex-shrink: 0;
    }
    .bl-tab {
        background: transparent;
        border: none;
        color: var(--bl-dim);
        padding: 12px 16px;
        border-radius: 10px;
        text-align: left;
        font-size: 14px;
        font-weight: 600;
        cursor: pointer;
        transition: all 0.15s ease;
        position: relative;
        display: flex;
        align-items: center;
        gap: 12px;
        user-select: none;
    }
    .bl-tab:hover {
        background: rgba(255,255,255,0.04);
        color: var(--bl-text);
    }
    .bl-tab.active {
        background: rgba(59, 130, 246, 0.12);
        color: var(--bl-accent);
    }
    .bl-tab.active::before {
        content: '';
        position: absolute;
        left: 0;
        top: 50%;
        transform: translateY(-50%);
        width: 3px;
        height: 18px;
        background: var(--bl-accent);
        border-radius: 0 3px 3px 0;
    }
    .bl-content {
        flex: 1;
        padding: 26px;
        overflow-y: auto;
        color: var(--bl-text);
    }
    .bl-panel {
        display: none;
        animation: blFadeIn 0.2s ease;
    }
    .bl-panel.active {
        display: block;
    }
    @keyframes blFadeIn {
        from { opacity: 0; transform: translateY(6px); }
        to   { opacity: 1; transform: translateY(0); }
    }
    .bl-section-title {
        font-size: 20px;
        font-weight: 700;
        margin-bottom: 6px;
        color: var(--bl-text);
    }
    .bl-section-note {
        font-size: 12px;
        color: var(--bl-dim);
        margin-bottom: 18px;
        line-height: 1.5;
    }
    .bl-row {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 16px 0;
        border-bottom: 1px solid var(--bl-border);
        gap: 20px;
    }
    .bl-row-info {
        flex: 1;
        min-width: 0;
    }
    .bl-row-title {
        font-size: 14px;
        font-weight: 600;
        margin-bottom: 3px;
    }
    .bl-row-desc {
        font-size: 12px;
        color: var(--bl-dim);
        line-height: 1.4;
    }
    .bl-toggle {
        appearance: none;
        width: 46px;
        height: 26px;
        background: rgba(255,255,255,0.1);
        border-radius: 13px;
        position: relative;
        cursor: pointer;
        transition: background 0.2s ease;
        flex-shrink: 0;
    }
    .bl-toggle::after {
        content: '';
        position: absolute;
        top: 3px;
        left: 3px;
        width: 20px;
        height: 20px;
        background: #fff;
        border-radius: 50%;
        transition: transform 0.2s cubic-bezier(0.16, 1, 0.3, 1);
        box-shadow: 0 1px 3px rgba(0,0,0,0.3);
    }
    .bl-toggle:checked {
        background: var(--bl-accent);
    }
    .bl-toggle:checked::after {
        transform: translateX(20px);
    }
    .bl-slider-wrap {
        display: flex;
        align-items: center;
        gap: 14px;
        flex-shrink: 0;
    }
    .bl-slider {
        -webkit-appearance: none;
        width: 140px;
        height: 4px;
        background: rgba(255,255,255,0.1);
        border-radius: 2px;
        outline: none;
    }
    .bl-slider::-webkit-slider-thumb {
        -webkit-appearance: none;
        width: 16px;
        height: 16px;
        background: var(--bl-accent);
        border-radius: 50%;
        cursor: pointer;
        transition: transform 0.1s;
    }
    .bl-slider::-webkit-slider-thumb:hover {
        transform: scale(1.15);
    }
    .bl-slider-val {
        color: var(--bl-dim);
        font-size: 12px;
        min-width: 36px;
        text-align: right;
        font-variant-numeric: tabular-nums;
    }
    .bl-select {
        background: rgba(255,255,255,0.05);
        border: 1px solid var(--bl-border);
        color: var(--bl-text);
        padding: 8px 12px;
        border-radius: 8px;
        font-size: 13px;
        outline: none;
        cursor: pointer;
        min-width: 150px;
    }
    .bl-select:focus {
        border-color: var(--bl-accent);
    }
    .bl-input {
        background: rgba(255,255,255,0.05);
        border: 1px solid var(--bl-border);
        color: var(--bl-text);
        padding: 8px 12px;
        border-radius: 8px;
        font-size: 13px;
        outline: none;
        width: 220px;
    }
    .bl-input:focus {
        border-color: var(--bl-accent);
    }
    .bl-btn {
        background: var(--bl-accent);
        color: #fff;
        border: none;
        padding: 9px 18px;
        border-radius: 8px;
        font-size: 13px;
        font-weight: 600;
        cursor: pointer;
        transition: background 0.15s ease;
    }
    .bl-btn:hover {
        background: var(--bl-accent-hov);
    }
    .bl-btn.secondary {
        background: rgba(255,255,255,0.08);
        color: var(--bl-text);
    }
    .bl-btn.secondary:hover {
        background: rgba(255,255,255,0.14);
    }
    .bl-btn-row {
        display: flex;
        gap: 10px;
        padding-top: 8px;
        border-bottom: none !important;
    }
    .bl-cape-grid {
        display: grid;
        grid-template-columns: repeat(4, 1fr);
        gap: 14px;
        margin-top: 16px;
    }
    .bl-cape-item {
        aspect-ratio: 2 / 1;
        border-radius: 8px;
        border: 2px solid transparent;
        cursor: pointer;
        transition: all 0.15s ease;
        position: relative;
        overflow: hidden;
    }
    .bl-cape-item:hover {
        transform: translateY(-2px);
        box-shadow: 0 4px 12px rgba(0,0,0,0.3);
    }
    .bl-cape-item.active {
        border-color: var(--bl-accent);
        box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.25);
    }
    .bl-cape-label {
        position: absolute;
        bottom: 5px;
        left: 50%;
        transform: translateX(-50%);
        font-size: 11px;
        font-weight: 700;
        color: #fff;
        text-shadow: 0 1px 3px rgba(0,0,0,0.9);
        pointer-events: none;
        white-space: nowrap;
    }
    #bloxd-legacy-hud {
        position: fixed;
        top: 14px;
        right: 14px;
        z-index: 9997;
        background: rgba(15, 15, 25, 0.85);
        border: 1px solid var(--bl-border);
        border-radius: 10px;
        padding: 10px 16px;
        color: var(--bl-text);
        font-size: 12px;
        font-weight: 700;
        letter-spacing: 0.6px;
        text-transform: uppercase;
        backdrop-filter: blur(10px);
        pointer-events: none;
        user-select: none;
        display: flex;
        align-items: center;
        gap: 10px;
        opacity: 0;
        animation: blHudIn 0.6s ease 0.5s forwards;
        will-change: transform, opacity;
    }
    @keyframes blHudIn {
        to { opacity: 1; }
    }
    #bloxd-legacy-hud::before {
        content: '';
        width: 7px;
        height: 7px;
        background: #22c55e;
        border-radius: 50%;
        box-shadow: 0 0 8px #22c55e;
    }
    .bl-info-row {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 14px 0;
        border-bottom: 1px solid var(--bl-border);
    }
    #bl-hitbox-overlay {
        position: fixed;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 80px;
        height: 160px;
        border: 2px solid rgba(255, 50, 50, 0.55);
        background: rgba(255, 50, 50, 0.04);
        pointer-events: none;
        z-index: 9998;
        display: none;
        border-radius: 4px;
    }
    #bl-hitbox-overlay.active {
        display: block;
    }
    #bl-hitbox-overlay::before {
        content: 'HITBOX';
        position: absolute;
        top: -18px;
        left: 50%;
        transform: translateX(-50%);
        font-size: 9px;
        font-weight: 700;
        color: rgba(255, 50, 50, 0.7);
        letter-spacing: 1px;
        font-family: monospace;
    }
    .bl-feature-small-items .item,
    .bl-feature-small-items .SelectedItem {
        transform: scale(var(--bl-item-scale)) !important;
        transform-origin: bottom center !important;
    }
    .bl-feature-no-hurt-cam canvas {
        filter: saturate(0.75) contrast(0.95) !important;
    }
    .bl-player-highlight {
        outline: 2px solid rgba(255, 50, 50, 0.85) !important;
        outline-offset: 2px !important;
    }
    .bl-sprint-indicator {
        position: fixed;
        bottom: 100px;
        left: 50%;
        transform: translateX(-50%);
        background: rgba(15, 15, 25, 0.85);
        border: 1px solid var(--bl-border);
        color: var(--bl-accent);
        padding: 6px 14px;
        border-radius: 20px;
        font-size: 11px;
        font-weight: 700;
        letter-spacing: 0.8px;
        z-index: 9997;
        pointer-events: none;
        user-select: none;
        opacity: 0;
        transition: opacity 0.2s ease;
        will-change: transform, opacity;
    }
    .bl-sprint-indicator.active {
        opacity: 1;
    }
    .bl-keystrokes {
        position: fixed;
        bottom: 20px;
        left: 20px;
        z-index: 9997;
        display: grid;
        grid-template-columns: repeat(3, 42px);
        grid-template-rows: repeat(2, 42px);
        gap: 4px;
        pointer-events: none;
        user-select: none;
        will-change: transform, opacity;
    }
    .bl-keystrokes .ks-key {
        background: rgba(15, 15, 25, var(--bl-gui-opacity, 0.80));
        border: 1px solid var(--bl-border);
        border-radius: 6px;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 13px;
        font-weight: 700;
        color: var(--bl-text);
        transition: all 0.08s ease;
        will-change: transform, background;
    }
    .bl-keystrokes .ks-key.pressed {
        background: var(--bl-accent);
        border-color: var(--bl-accent);
        color: #fff;
        transform: scale(0.92);
    }
    .bl-keystrokes .ks-key:nth-child(1) { grid-column: 2; }
    .bl-keystrokes .ks-key:nth-child(2) { grid-column: 1; grid-row: 2; }
    .bl-keystrokes .ks-key:nth-child(3) { grid-column: 2; grid-row: 2; }
    .bl-keystrokes .ks-key:nth-child(4) { grid-column: 3; grid-row: 2; }
    .bl-counter {
        position: fixed;
        z-index: 9997;
        background: rgba(15, 15, 25, var(--bl-gui-opacity, 0.80));
        border: 1px solid var(--bl-border);
        border-radius: 8px;
        padding: 8px 14px;
        font-size: 13px;
        font-weight: 700;
        color: var(--bl-text);
        pointer-events: none;
        user-select: none;
        font-family: monospace;
        letter-spacing: 0.5px;
        will-change: transform, opacity;
    }
    .bl-counter .bl-counter-label {
        font-size: 10px;
        color: var(--bl-dim);
        text-transform: uppercase;
        letter-spacing: 1px;
        margin-bottom: 2px;
    }
    .bl-counter .bl-counter-val {
        font-size: 18px;
        font-weight: 800;
        color: var(--bl-accent);
    }
    #bl-fps-counter { top: 14px; left: 14px; }
    #bl-cps-counter { top: 72px; left: 14px; }
    .bl-crosshair {
        position: fixed;
        top: 50%;
        left: 50%;
        z-index: 9997;
        pointer-events: none;
        will-change: transform, opacity;
    }
    .bl-crosshair-default::before,
    .bl-crosshair-default::after {
        content: '';
        position: absolute;
        background: rgba(255,255,255,0.9);
    }
    .bl-crosshair-default::before {
        width: 2px;
        height: 24px;
        left: 50%;
        top: calc(50% - 12px);
        transform: translateX(-50%);
    }
    .bl-crosshair-default::after {
        height: 2px;
        width: 24px;
        top: 50%;
        left: calc(50% - 12px);
        transform: translateY(-50%);
    }
    .bl-crosshair-circle::before {
        content: '';
        position: absolute;
        width: 18px;
        height: 18px;
        border: 2px solid rgba(255,255,255,0.9);
        border-radius: 50%;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
    }
    .bl-crosshair-dot::before {
        content: '';
        position: absolute;
        width: 5px;
        height: 5px;
        background: rgba(255,255,255,0.9);
        border-radius: 50%;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
    }
    .bl-crosshair-cross::before,
    .bl-crosshair-cross::after {
        content: '';
        position: absolute;
        background: rgba(255,255,255,0.9);
    }
    .bl-crosshair-cross::before {
        width: 2px;
        height: 14px;
        left: 50%;
        top: calc(50% - 7px);
        transform: translateX(-50%);
    }
    .bl-crosshair-cross::after {
        height: 2px;
        width: 14px;
        top: 50%;
        left: calc(50% - 7px);
        transform: translateY(-50%);
    }
    .bl-motion-blur {
        filter: blur(0px) !important;
        transition: filter 0.15s ease-out;
    }
    .bl-motion-blur.active {
        filter: blur(2.5px) !important;
    }
    .bl-gui-transparent #bloxd-legacy-hud,
    .bl-gui-transparent .bl-counter,
    .bl-gui-transparent .bl-keystrokes .ks-key,
    .bl-gui-transparent .bl-sprint-indicator {
        --bl-gui-opacity: var(--bl-gui-custom-opacity, 0.80);
    }
    #bl-vignette {
        position: fixed;
        inset: 0;
        z-index: 9995;
        pointer-events: none;
        display: none;
    }
    #bl-fog {
        position: fixed;
        inset: 0;
        z-index: 9995;
        pointer-events: none;
        display: none;
    }
    #bl-grain {
        position: fixed;
        inset: 0;
        z-index: 9996;
        pointer-events: none;
        display: none;
        opacity: 0.06;
        background: repeating-radial-gradient(#000 0 0.0001%, #fff 0 0.0002%) 50% 0/2500px 2500px;
        animation: blGrain 0.2s steps(5) infinite;
    }
    @keyframes blGrain {
        0% { background-position: 0 0; }
        100% { background-position: 100px 100px; }
    }
    .bl-shader-sep {
        height: 1px;
        background: var(--bl-border);
        margin: 8px 0;
    }
    #bl-ui-editor {
        position: fixed;
        inset: 0;
        z-index: 2147483645;
        background: rgba(0,0,0,0.25);
        background-image:
            linear-gradient(rgba(255,255,255,0.04) 1px, transparent 1px),
            linear-gradient(90deg, rgba(255,255,255,0.04) 1px, transparent 1px);
        background-size: 24px 24px;
        display: none;
        pointer-events: auto;
    }
    #bl-ui-editor.active { display: block; }
    .bl-ui-editor-el {
        cursor: move !important;
        pointer-events: auto !important;
        outline: 2px dashed rgba(59, 130, 246, 0.5) !important;
        outline-offset: 6px !important;
        transition: none !important;
    }
    .bl-ui-editor-el.bl-ui-selected {
        outline: 2px solid #3b82f6 !important;
        outline-offset: 6px !important;
        z-index: 2147483646 !important;
    }
    #bl-ui-editor-panel {
        position: fixed;
        top: 24px;
        right: 24px;
        width: 300px;
        max-height: calc(100vh - 48px);
        overflow-y: auto;
        background: rgba(15, 15, 25, 0.96);
        border: 1px solid rgba(255,255,255,0.08);
        border-radius: 14px;
        padding: 22px;
        z-index: 2147483647;
        color: #e2e8f0;
        font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
        display: none;
        box-shadow: 0 25px 50px -12px rgba(0,0,0,0.6);
        backdrop-filter: blur(12px);
    }
    #bl-ui-editor-panel.active { display: block; }
    #bl-ui-editor-panel .bl-slider { width: 100%; }
    #bl-ui-editor-panel .bl-slider-val { min-width: 48px; text-align: right; }
    #bl-ui-editor-hint {
        position: fixed;
        bottom: 24px;
        left: 50%;
        transform: translateX(-50%);
        background: rgba(15,15,25,0.9);
        border: 1px solid rgba(255,255,255,0.08);
        border-radius: 20px;
        padding: 8px 20px;
        color: #94a3b8;
        font-size: 12px;
        z-index: 2147483647;
        pointer-events: none;
        display: none;
    }
    #bl-ui-editor-hint.active { display: block; }
    #bl-canvas-wrapper {
        position: fixed;
        inset: 0;
        z-index: 0;
        pointer-events: none;
        overflow: hidden;
    }
    `;

    let overlayEl, menuEl;

    function buildUI() {
        try {
            const style = make('style', '', document.head);
            style.textContent = CSS;

            const hudEl = make('div', '', document.body);
            hudEl.id = 'bloxd-legacy-hud';
            hudEl.textContent = 'Bloxd Legacy';

            const sprintInd = make('div', 'bl-sprint-indicator', document.body);
            sprintInd.id = 'bl-sprint-indicator';
            sprintInd.textContent = 'SPRINTING';

            const hitboxOverlay = make('div', '', document.body);
            hitboxOverlay.id = 'bl-hitbox-overlay';

            const fpsEl = make('div', 'bl-counter', document.body);
            fpsEl.id = 'bl-fps-counter';
            fpsEl.innerHTML = '<div class="bl-counter-label">FPS</div><div class="bl-counter-val" id="bl-fps-val">0</div>';

            const cpsEl = make('div', 'bl-counter', document.body);
            cpsEl.id = 'bl-cps-counter';
            cpsEl.innerHTML = '<div class="bl-counter-label">CPS</div><div class="bl-counter-val" id="bl-cps-val">0</div>';

            const ksEl = make('div', 'bl-keystrokes', document.body);
            ksEl.id = 'bl-keystrokes';
            ['W','A','S','D'].forEach(k => {
                const keyDiv = make('div', 'ks-key', ksEl);
                keyDiv.dataset.key = k;
                keyDiv.textContent = k;
            });

            const crosshairEl = make('div', 'bl-crosshair bl-crosshair-default', document.body);
            crosshairEl.id = 'bl-crosshair';

            const vignetteEl = make('div', '', document.body);
            vignetteEl.id = 'bl-vignette';

            const fogEl = make('div', '', document.body);
            fogEl.id = 'bl-fog';

            const grainEl = make('div', '', document.body);
            grainEl.id = 'bl-grain';

            const uiEditor = make('div', '', document.body);
            uiEditor.id = 'bl-ui-editor';
            on(uiEditor, 'mousedown', (e) => {
                if (e.target === uiEditor && selectedUIElement) {
                    const prev = $1(UI_DEFS[selectedUIElement]?.selector);
                    if (prev) prev.classList.remove('bl-ui-selected');
                    selectedUIElement = null;
                    refreshUIEditorPanel();
                }
            });

            const uiPanel = make('div', '', document.body);
            uiPanel.id = 'bl-ui-editor-panel';

            const uiHint = make('div', '', document.body);
            uiHint.id = 'bl-ui-editor-hint';
            uiHint.textContent = 'Click an element to select it. Drag to move. Use the panel to adjust properties.';

            overlayEl = make('div', '', document.body);
            overlayEl.id = 'bloxd-legacy-overlay';
            overlayEl.tabIndex = -1;

            menuEl = make('div', '', overlayEl);
            menuEl.id = 'bloxd-legacy-menu';

            const header = make('div', 'bl-header', menuEl);
            const title = make('span', 'bl-title', header);
            title.textContent = 'Bloxd Legacy';
            const closeBtn = make('button', 'bl-close', header);
            closeBtn.innerHTML = '&#10005;';
            closeBtn.addEventListener('click', closeMenu);

            const body = make('div', 'bl-body', menuEl);

            const sidebar = make('div', 'bl-sidebar', body);
            const tabs = [
                { id: 'combat', label: '[WIP] Combat', icon: '&#9876;' },
                { id: 'cosmetics',label: '[WIP] Cosmetics', icon: '&#128100;' },
                { id: 'capes', label: '[WIP] Capes', icon: '&#128081;' },
                { id: 'visuals', label: 'Visuals', icon: '&#128065;' },
                { id: 'shaders', label: '[WIP] Shaders', icon: '&#10024;' },
                { id: 'settings', label: 'Settings', icon: '&#9881;' }
            ];

            tabs.forEach(t => {
                const btn = make('button', 'bl-tab', sidebar);
                btn.innerHTML = '<span style="font-size:16px;width:20px;text-align:center;display:inline-block">' + t.icon + '</span> ' + t.label;
                btn.dataset.tab = t.id;
                if (t.id === currentTab) btn.classList.add('active');
                btn.addEventListener('click', () => switchTab(t.id));
            });

            const content = make('div', 'bl-content', body);

            const combat = createPanel(content, 'combat');
            make('div', 'bl-section-title', combat).textContent = 'Combat Modules';
            make('div', 'bl-section-note', combat).textContent =
                'Real combat enhancements. Hitboxes are a visual aid. Sprint is simulated via synthetic Shift events.';
            addToggle(combat, 'Player Hitboxes', 'combat', 'hitboxes', 'Visual hitbox overlay + player DOM highlighting');
            addToggle(combat, 'Toggle Sprint', 'combat', 'toggleSprint', 'Auto-hold Shift when W is pressed (7 BPS sprint)');
            addToggle(combat, 'No Hurt Cam', 'combat', 'noHurtCam', 'Dampens red damage flashes via canvas filter');
            addToggle(combat, 'Small Items', 'combat', 'smallItems', 'Shrinks hotbar item slots for cleaner PvP view');
            addSlider(combat, 'Item Scale', 'combat', 'smallItemsScale', 0.5, 1.0, 0.05, 'Hotbar slot scale multiplier');

            const cosmetics = createPanel(content, 'cosmetics');
            make('div', 'bl-section-title', cosmetics).textContent = 'Player Cosmetics';
            addSelect(cosmetics, 'Cape Style', 'cosmetics', 'cape', [
                { value: 'none', label: 'None' },
                { value: 'classic', label: 'Classic' },
                { value: 'mojang', label: 'Mojang' },
                { value: 'custom', label: 'Custom URL' }
            ], 'Choose a built-in cape or supply your own');
            addInput(cosmetics, 'Custom Cape URL', 'cosmetics', 'customUrl', 'https://example.com/cape.png', 'Direct link to a PNG image');

            const capes = createPanel(content, 'capes');
            make('div', 'bl-section-title', capes).textContent = 'Cape Gallery';
            const capeGrid = make('div', 'bl-cape-grid', capes);
            const capeDefs = [
                { id: 'none', color: '#334155', label: 'None' },
                { id: 'red', color: '#ef4444', label: 'Red' },
                { id: 'blue', color: '#3b82f6', label: 'Blue' },
                { id: 'green', color: '#22c55e', label: 'Green' },
                { id: 'yellow', color: '#eab308', label: 'Yellow' },
                { id: 'purple', color: '#a855f7', label: 'Purple' },
                { id: 'orange', color: '#f97316', label: 'Orange' },
                { id: 'cyan', color: '#06b6d4', label: 'Cyan' }
            ];
            capeDefs.forEach(c => {
                const item = make('div', 'bl-cape-item', capeGrid);
                item.style.background = c.color;
                item.dataset.cape = c.id;
                const lbl = make('span', 'bl-cape-label', item);
                lbl.textContent = c.label;
                item.addEventListener('click', () => {
                    config.capes.selected = c.id;
                    saveConfig();
                    refreshCapeGrid(capeGrid);
                });
            });
            refreshCapeGrid(capeGrid);

            const visuals = createPanel(content, 'visuals');
            make('div', 'bl-section-title', visuals).textContent = 'Visual Enhancements';
            make('div', 'bl-section-note', visuals).textContent =
                'HUD overlays, counters, crosshair styles, and viewport effects.';
            addToggle(visuals, 'Keystrokes Display', 'visuals', 'keystrokes', 'Shows W/A/S/D key states in bottom-left corner');
            addToggle(visuals, 'CPS Counter', 'visuals', 'cps', 'Clicks per second counter in top-left');
            addToggle(visuals, 'FPS Counter', 'visuals', 'fps', 'Frames per second counter in top-left');
            addToggle(visuals, 'Motion Blur', 'visuals', 'motionBlur', 'Simulated motion blur on fast camera movement');
            addSelect(visuals, '[WIP] Crosshair Style', 'visuals', 'crosshair', [
                { value: 'none', label: 'None (Game Default)' },
                { value: 'default', label: 'Default Cross' },
                { value: 'circle', label: 'Circle' },
                { value: 'dot', label: 'Dot' },
                { value: 'cross', label: 'Small Cross' }
            ], 'Replaces the in-game crosshair with a custom overlay');
            addToggle(visuals, 'Smooth Zoom', 'visuals', 'smoothZoom', 'Hold Z to smoothly zoom in; release to zoom out');
            addSlider(visuals, 'Zoom Level', 'visuals', 'smoothZoomLevel', 1.0, 3.0, 0.1, 'Maximum zoom multiplier when holding Z');
            addSlider(visuals, 'Field of View', 'visuals', 'fov', 60, 120, 1, 'Horizontal camera FOV (requires game rejoin to apply)');
            addSlider(visuals, 'GUI Opacity', 'visuals', 'guiOpacity', 0.3, 1.0, 0.05, 'Transparency of HUD overlays');

            make('div', 'bl-shader-sep', visuals);
            const editRow = make('div', 'bl-row', visuals);
            const editInfo = make('div', 'bl-row-info', editRow);
            make('div', 'bl-row-title', editInfo).textContent = 'Edit UI Layout';
            make('div', 'bl-row-desc', editInfo).textContent = 'Drag, resize, recolor, and reposition HUD overlays';
            const editBtn = make('button', 'bl-btn', editRow);
            editBtn.textContent = 'Open Editor';
            editBtn.addEventListener('click', () => {
                closeMenu();
                enterUIEditMode();
            });

            const shaders = createPanel(content, 'shaders');
            make('div', 'bl-section-title', shaders).textContent = 'Shader Post-Processing';
            make('div', 'bl-section-note', shaders).textContent =
                'GPU-accelerated CSS filter stack + overlay effects. True GLSL injection into Unity is not possible from a userscript. This is the closest working alternative.';

            const presetRow = make('div', 'bl-row', shaders);
            const presetInfo = make('div', 'bl-row-info', presetRow);
            make('div', 'bl-row-title', presetInfo).textContent = 'Shader Preset';
            make('div', 'bl-row-desc', presetInfo).textContent = 'Load a preset or customize manually';
            const presetSel = make('select', 'bl-select', presetRow);
            [
                { value: 'performance', label: 'Performance' },
                { value: 'balanced', label: 'Balanced' },
                { value: 'cinematic', label: 'Cinematic' },
                { value: 'custom', label: 'Custom' }
            ].forEach(o => {
                const opt = make('option', '', presetSel);
                opt.value = o.value;
                opt.textContent = o.label;
            });
            presetSel.value = config.shaders.preset;
            presetSel.addEventListener('change', () => {
                const name = presetSel.value;
                if (name !== 'custom' && SHADER_PRESETS[name]) {
                    Object.assign(config.shaders, SHADER_PRESETS[name]);
                    config.shaders.preset = name;
                    saveConfig();
                    updateShaderUI();
                    applyShaderFilters();
                } else {
                    config.shaders.preset = 'custom';
                    saveConfig();
                }
            });

            addShaderToggle(shaders, 'FPS Boost', 'fpsBoost', 'Lowers render resolution to boost frame rate on low-end PCs');
            addShaderSlider(shaders, 'Resolution Scale', 'resScale', 0.5, 1.0, 0.05);

            make('div', 'bl-shader-sep', shaders);

            addShaderSlider(shaders, 'Brightness', 'brightness', 0.5, 2.0, 0.05);
            addShaderSlider(shaders, 'Contrast', 'contrast', 0.5, 2.0, 0.05);
            addShaderSlider(shaders, 'Saturation', 'saturate', 0.0, 2.0, 0.05);
            addShaderSlider(shaders, 'Color Temp', 'hueRotate', -30, 30, 1);
            addShaderSlider(shaders, 'Bloom', 'bloom', 0, 1.0, 0.05);
            addShaderSlider(shaders, 'Fog', 'fog', 0, 1.0, 0.05);
            addShaderSlider(shaders, 'Shadows', 'shadows', 0, 1.0, 0.05);
            addShaderSlider(shaders, 'Vignette', 'vignette', 0, 1.0, 0.05);
            addShaderToggle(shaders, 'Film Grain', 'grain', 'Subtle noise overlay for cinematic look');

            const settings = createPanel(content, 'settings');
            make('div', 'bl-section-title', settings).textContent = 'Client Settings';
            addSlider(settings, 'UI Scale', 'settings', 'uiScale', 0.8, 1.5, 0.05, 'Resize the entire menu interface');
            addInfoRow(settings, 'Menu Keybind', 'Right Shift');

            const btnRow = make('div', 'bl-row bl-btn-row', settings);
            const resetBtn = make('button', 'bl-btn secondary', btnRow);
            resetBtn.textContent = 'Reset Defaults';
            resetBtn.addEventListener('click', () => {
                if (confirm('Reset all Bloxd Legacy settings to default?')) {
                    config = JSON.parse(JSON.stringify(DEFAULT_CONFIG));
                    saveConfig();
                    location.reload();
                }
            });
            const exportBtn = make('button', 'bl-btn', btnRow);
            exportBtn.textContent = 'Export Config';
            exportBtn.addEventListener('click', () => {
                const blob = new Blob([JSON.stringify(config, null, 2)], { type: 'application/json' });
                const url = URL.createObjectURL(blob);
                const a = document.createElement('a');
                a.href = url;
                a.download = 'bloxd-legacy-config.json';
                a.click();
                URL.revokeObjectURL(url);
            });

            applyUIScale();

            overlayEl.addEventListener('click', e => {
                if (e.target === overlayEl) closeMenu();
            });

            buildUIEditorPanel();
            initFeatureStates();
        } catch (e) {
            console.error('[BloxdLegacy] buildUI failed:', e);
        }
    }

    function createPanel(parent, id) {
        const p = make('div', 'bl-panel', parent);
        p.dataset.panel = id;
        if (id === currentTab) p.classList.add('active');
        return p;
    }

    function addToggle(parent, title, cat, key, desc) {
        const row = make('div', 'bl-row', parent);
        const info = make('div', 'bl-row-info', row);
        make('div', 'bl-row-title', info).textContent = title;
        make('div', 'bl-row-desc', info).textContent = desc;
        const t = make('input', 'bl-toggle', row);
        t.type = 'checkbox';
        t.checked = !!config[cat][key];
        t.addEventListener('change', () => {
            config[cat][key] = t.checked;
            saveConfig();
            applyFeatureState(cat, key, t.checked);
        });
    }

    function addSlider(parent, title, cat, key, min, max, step, desc) {
        const row = make('div', 'bl-row', parent);
        const info = make('div', 'bl-row-info', row);
        make('div', 'bl-row-title', info).textContent = title;
        make('div', 'bl-row-desc', info).textContent = desc;

        const wrap = make('div', 'bl-slider-wrap', row);
        const s = make('input', 'bl-slider', wrap);
        s.type = 'range';
        s.min = min; s.max = max; s.step = step;
        s.value = config[cat][key];

        const val = make('span', 'bl-slider-val', wrap);
        val.textContent = fmtSlider(config[cat][key], step);

        s.addEventListener('input', () => {
            const v = parseFloat(s.value);
            config[cat][key] = v;
            val.textContent = fmtSlider(v, step);
            saveConfig();
            if (cat === 'settings' && key === 'uiScale') applyUIScale();
            if (cat === 'combat' && key === 'smallItemsScale') applySmallItemsScale(v);
            if (cat === 'visuals' && key === 'guiOpacity') applyGUIOpacity(v);
            if (cat === 'visuals' && key === 'smoothZoomLevel') applyZoomLevel(v);
        });
    }

    function fmtSlider(v, step) {
        return step < 1 ? v.toFixed(2) : Math.round(v).toString();
    }

    function addSelect(parent, title, cat, key, opts, desc) {
        const row = make('div', 'bl-row', parent);
        const info = make('div', 'bl-row-info', row);
        make('div', 'bl-row-title', info).textContent = title;
        make('div', 'bl-row-desc', info).textContent = desc;
        const sel = make('select', 'bl-select', row);
        opts.forEach(o => {
            const opt = make('option', '', sel);
            opt.value = o.value;
            opt.textContent = o.label;
        });
        sel.value = config[cat][key];
        sel.addEventListener('change', () => {
            config[cat][key] = sel.value;
            saveConfig();
            if (cat === 'visuals' && key === 'crosshair') applyCrosshair(sel.value);
        });
    }

    function addInput(parent, title, cat, key, placeholder, desc) {
        const row = make('div', 'bl-row', parent);
        const info = make('div', 'bl-row-info', row);
        make('div', 'bl-row-title', info).textContent = title;
        make('div', 'bl-row-desc', info).textContent = desc;
        const inp = make('input', 'bl-input', row);
        inp.type = 'text';
        inp.placeholder = placeholder;
        inp.value = config[cat][key] || '';
        inp.addEventListener('input', () => {
            config[cat][key] = inp.value;
            saveConfig();
        });
    }

    function addInfoRow(parent, title, value) {
        const row = make('div', 'bl-info-row', parent);
        make('div', 'bl-row-title', row).textContent = title;
        const v = make('div', '', row);
        v.style.color = 'var(--bl-dim)';
        v.style.fontSize = '13px';
        v.textContent = value;
    }

    function addShaderToggle(parent, title, key, desc) {
        const row = make('div', 'bl-row', parent);
        const info = make('div', 'bl-row-info', row);
        make('div', 'bl-row-title', info).textContent = title;
        make('div', 'bl-row-desc', info).textContent = desc;
        const t = make('input', 'bl-toggle', row);
        t.type = 'checkbox';
        t.checked = !!config.shaders[key];
        t.dataset.shaderKey = key;
        t.addEventListener('change', () => {
            config.shaders[key] = t.checked;
            config.shaders.preset = 'custom';
            saveConfig();
            applyShaderFilters();
        });
    }

    function addShaderSlider(parent, title, key, min, max, step) {
        const row = make('div', 'bl-row', parent);
        const info = make('div', 'bl-row-info', row);
        make('div', 'bl-row-title', info).textContent = title;
        const wrap = make('div', 'bl-slider-wrap', row);
        const s = make('input', 'bl-slider', wrap);
        s.type = 'range';
        s.min = min; s.max = max; s.step = step;
        s.value = config.shaders[key];
        s.dataset.shaderKey = key;

        const val = make('span', 'bl-slider-val', wrap);
        val.textContent = fmtSlider(config.shaders[key], step);

        s.addEventListener('input', () => {
            const v = parseFloat(s.value);
            config.shaders[key] = v;
            config.shaders.preset = 'custom';
            val.textContent = fmtSlider(v, step);
            saveConfig();
            applyShaderFilters();
        });
    }

    function updateShaderUI() {
        document.querySelectorAll('[data-shader-key]').forEach(el => {
            const key = el.dataset.shaderKey;
            if (el.type === 'checkbox') {
                el.checked = !!config.shaders[key];
            } else if (el.type === 'range') {
                el.value = config.shaders[key];
                const valEl = el.parentElement.querySelector('.bl-slider-val');
                if (valEl) valEl.textContent = fmtSlider(config.shaders[key], parseFloat(el.step) || 0.05);
            }
        });
    }

    function refreshCapeGrid(grid) {
        $all('.bl-cape-item', grid).forEach(item => {
            item.classList.toggle('active', item.dataset.cape === config.capes.selected);
        });
    }

    function applyUIScale() {
        document.documentElement.style.setProperty('--bl-scale', config.settings.uiScale);
    }

    function initFeatureStates() {
        applyFeatureState('combat', 'hitboxes', config.combat.hitboxes);
        applyFeatureState('combat', 'toggleSprint', config.combat.toggleSprint);
        applyFeatureState('combat', 'noHurtCam', config.combat.noHurtCam);
        applyFeatureState('combat', 'smallItems', config.combat.smallItems);
        applySmallItemsScale(config.combat.smallItemsScale);

        applyFeatureState('visuals', 'keystrokes', config.visuals.keystrokes);
        applyFeatureState('visuals', 'cps', config.visuals.cps);
        applyFeatureState('visuals', 'fps', config.visuals.fps);
        applyFeatureState('visuals', 'motionBlur', config.visuals.motionBlur);
        applyCrosshair(config.visuals.crosshair);
        applyFeatureState('visuals', 'smoothZoom', config.visuals.smoothZoom);
        applyZoomLevel(config.visuals.smoothZoomLevel);
        applyGUIOpacity(config.visuals.guiOpacity);

        applyShaderFilters();
        applyUILayout();
    }

    function applyFeatureState(cat, key, enabled) {
        if (cat === 'combat') {
            switch (key) {
                case 'hitboxes': setHitboxes(enabled); break;
                case 'toggleSprint': break;
                case 'noHurtCam': setNoHurtCam(enabled); break;
                case 'smallItems': setSmallItems(enabled); break;
            }
        } else if (cat === 'visuals') {
            switch (key) {
                case 'keystrokes': setKeystrokes(enabled); break;
                case 'cps': setCPSCounter(enabled); break;
                case 'fps': setFPSCounter(enabled); break;
                case 'motionBlur': setMotionBlur(enabled); break;
                case 'smoothZoom': setSmoothZoom(enabled); break;
            }
        }
    }

    /* Player Hitboxes */
    let playerHighlightObserver = null;
    let highlightDebounce = null;

    function setHitboxes(enabled) {
        const overlay = document.getElementById('bl-hitbox-overlay');
        if (overlay) overlay.classList.toggle('active', enabled);
        if (enabled) startPlayerHighlighting();
        else stopPlayerHighlighting();
    }

    function startPlayerHighlighting() {
        const doHighlight = () => {
            const selectors = ['[class*="name"]','[class*="player"]','[class*="health"]','[class*="nametag"]','[class*="entity"]'];
            selectors.forEach(sel => {
                document.querySelectorAll(sel).forEach(el => {
                    const text = el.textContent?.toLowerCase() || '';
                    if (text.length > 0 && text.length < 30 && !el.dataset.blHighlighted) {
                        el.dataset.blHighlighted = 'true';
                        el.classList.add('bl-player-highlight');
                    }
                });
            });
        };
        doHighlight();
        playerHighlightObserver = new MutationObserver(() => {
            if (highlightDebounce) clearTimeout(highlightDebounce);
            highlightDebounce = setTimeout(doHighlight, 500);
        });
        trackedObservers.push(playerHighlightObserver);
        playerHighlightObserver.observe(document.body, { childList: true, subtree: true });
    }

    function stopPlayerHighlighting() {
        if (playerHighlightObserver) { playerHighlightObserver.disconnect(); playerHighlightObserver = null; }
        if (highlightDebounce) { clearTimeout(highlightDebounce); highlightDebounce = null; }
        document.querySelectorAll('.bl-player-highlight').forEach(el => {
            el.classList.remove('bl-player-highlight');
            delete el.dataset.blHighlighted;
        });
    }

    /* No Hurt Cam */
    function setNoHurtCam(enabled) {
        document.body.classList.toggle('bl-feature-no-hurt-cam', enabled);
    }

    /* Small Items */
    let itemMutationObserver = null;

    function setSmallItems(enabled) {
        document.body.classList.toggle('bl-feature-small-items', enabled);
        applySmallItemsToExisting(enabled);
        if (enabled) {
            if (!itemMutationObserver) {
                itemMutationObserver = new MutationObserver(mutations => {
                    if (!config.combat.smallItems) return;
                    mutations.forEach(mutation => {
                        mutation.addedNodes.forEach(node => {
                            if (node.nodeType !== 1) return;
                            if (node.classList?.contains('item') || node.classList?.contains('SelectedItem')) {
                                applySmallItemsToElement(node);
                            }
                            node.querySelectorAll?.('.item, .SelectedItem').forEach(applySmallItemsToElement);
                        });
                    });
                });
                trackedObservers.push(itemMutationObserver);
                itemMutationObserver.observe(document.body, { childList: true, subtree: true });
            }
        } else {
            if (itemMutationObserver) { itemMutationObserver.disconnect(); itemMutationObserver = null; }
            document.querySelectorAll('.item, .SelectedItem').forEach(el => {
                el.style.transform = '';
                el.style.transformOrigin = '';
            });
        }
    }

    function applySmallItemsToExisting(enabled) {
        document.querySelectorAll('.item, .SelectedItem').forEach(el => {
            if (enabled) applySmallItemsToElement(el);
            else { el.style.transform = ''; el.style.transformOrigin = ''; }
        });
    }

    function applySmallItemsToElement(el) {
        el.style.transform = 'scale(' + config.combat.smallItemsScale + ')';
        el.style.transformOrigin = 'bottom center';
    }

    function applySmallItemsScale(scale) {
        document.documentElement.style.setProperty('--bl-item-scale', scale);
        if (config.combat.smallItems) applySmallItemsToExisting(true);
    }

    /* Keystrokes */
    function setKeystrokes(enabled) {
        const el = document.getElementById('bl-keystrokes');
        if (el) el.style.display = enabled ? 'grid' : 'none';
    }

    on(document, 'keydown', function(e) {
        const keyMap = { 'KeyW': 'W', 'KeyA': 'A', 'KeyS': 'S', 'KeyD': 'D' };
        const mapped = keyMap[e.code];
        if (mapped) {
            const keyEl = document.querySelector('.bl-keystrokes .ks-key[data-key="' + mapped + '"]');
            if (keyEl) keyEl.classList.add('pressed');
        }
    }, { passive: true });

    on(document, 'keyup', function(e) {
        const keyMap = { 'KeyW': 'W', 'KeyA': 'A', 'KeyS': 'S', 'KeyD': 'D' };
        const mapped = keyMap[e.code];
        if (mapped) {
            const keyEl = document.querySelector('.bl-keystrokes .ks-key[data-key="' + mapped + '"]');
            if (keyEl) keyEl.classList.remove('pressed');
        }
    }, { passive: true });

    /* CPS Counter */
    let cpsInterval = null;
    const clickTimes = [];

    function setCPSCounter(enabled) {
        const el = document.getElementById('bl-cps-counter');
        if (el) el.style.display = enabled ? 'block' : 'none';
        if (enabled && !cpsInterval) {
            cpsInterval = setInterval(() => {
                const now = performance.now();
                const cutoff = now - 1000;
                let i = 0;
                while (i < clickTimes.length && clickTimes[i] < cutoff) i++;
                if (i > 0) clickTimes.splice(0, i);
                const valEl = document.getElementById('bl-cps-val');
                if (valEl) valEl.textContent = clickTimes.length;
            }, 100);
            trackedIntervals.push(cpsInterval);
        } else if (!enabled && cpsInterval) {
            clearInterval(cpsInterval);
            cpsInterval = null;
        }
    }

    on(document, 'mousedown', () => {
        if (config.visuals.cps) clickTimes.push(performance.now());
    }, { passive: true });

    /* FPS Counter */
    let fpsRaf = null;
    let frameCount = 0;
    let lastFpsTime = performance.now();

    function setFPSCounter(enabled) {
        const el = document.getElementById('bl-fps-counter');
        if (el) el.style.display = enabled ? 'block' : 'none';
        if (enabled && !fpsRaf) {
            const tick = () => {
                frameCount++;
                const now = performance.now();
                if (now - lastFpsTime >= 1000) {
                    const valEl = document.getElementById('bl-fps-val');
                    if (valEl) valEl.textContent = frameCount;
                    frameCount = 0;
                    lastFpsTime = now;
                }
                fpsRaf = requestAnimationFrame(tick);
            };
            fpsRaf = requestAnimationFrame(tick);
            trackedRAFs.push(fpsRaf);
        } else if (!enabled && fpsRaf) {
            cancelAnimationFrame(fpsRaf);
            fpsRaf = null;
        }
    }

    /*  Motion Blur */
    let motionBlurTimeout = null;
    let lastMouseX = 0;
    let lastMouseY = 0;
    let lastMouseMove = 0;

    function setMotionBlur(enabled) {
        const canvas = document.querySelector('canvas');
        if (!canvas) return;
        if (enabled) {
            canvas.classList.add('bl-motion-blur');
            on(document, 'mousemove', onMouseMoveForBlur, { passive: true });
        } else {
            canvas.classList.remove('bl-motion-blur', 'active');
            off(document, 'mousemove', onMouseMoveForBlur, { passive: true });
        }
    }

    function onMouseMoveForBlur(e) {
        const now = performance.now();
        if (now - lastMouseMove < 16) return;
        lastMouseMove = now;
        const dx = e.clientX - lastMouseX;
        const dy = e.clientY - lastMouseY;
        const dist = Math.sqrt(dx * dx + dy * dy);
        lastMouseX = e.clientX;
        lastMouseY = e.clientY;
        const canvas = document.querySelector('canvas');
        if (!canvas) return;
        if (dist > 8) {
            canvas.classList.add('active');
            if (motionBlurTimeout) clearTimeout(motionBlurTimeout);
            motionBlurTimeout = setTimeout(() => { canvas.classList.remove('active'); }, 120);
        }
    }

    /* Crosshair */
    function applyCrosshair(style) {
        const el = document.getElementById('bl-crosshair');
        if (!el) return;
        el.className = 'bl-crosshair';
        if (style === 'none') { el.style.display = 'none'; }
        else { el.style.display = 'block'; el.classList.add('bl-crosshair-' + style); }
    }

    /* Smooth Zoom */
    let zoomActive = false;
    let currentZoom = 1.0;
    let targetZoom = 1.0;
    let zoomRaf = null;

    function setSmoothZoom(enabled) {
        if (enabled) {
            on(document, 'keydown', onZoomKeyDown, { passive: true });
            on(document, 'keyup', onZoomKeyUp, { passive: true });
        } else {
            off(document, 'keydown', onZoomKeyDown, { passive: true });
            off(document, 'keyup', onZoomKeyUp, { passive: true });
            targetZoom = 1.0; currentZoom = 1.0;
            applyCanvasZoom(1.0);
            if (zoomRaf) { cancelAnimationFrame(zoomRaf); zoomRaf = null; }
        }
    }

    function onZoomKeyDown(e) {
        if (e.code === 'KeyZ' && !zoomActive && config.visuals.smoothZoom) {
            zoomActive = true;
            targetZoom = config.visuals.smoothZoomLevel;
            startZoomLoop();
        }
    }

    function onZoomKeyUp(e) {
        if (e.code === 'KeyZ' && zoomActive) { zoomActive = false; targetZoom = 1.0; }
    }

    function startZoomLoop() {
        if (zoomRaf) return;
        const loop = () => {
            const diff = targetZoom - currentZoom;
            if (Math.abs(diff) < 0.005) {
                currentZoom = targetZoom;
                applyCanvasZoom(currentZoom);
                if (targetZoom === 1.0) { zoomRaf = null; return; }
            } else {
                currentZoom += diff * 0.12;
                applyCanvasZoom(currentZoom);
            }
            zoomRaf = requestAnimationFrame(loop);
        };
        zoomRaf = requestAnimationFrame(loop);
        trackedRAFs.push(zoomRaf);
    }

    function applyCanvasZoom(zoom) {
        const canvas = document.querySelector('canvas');
        if (!canvas) return;
        if (zoom === 1.0) { canvas.style.transform = ''; canvas.style.transformOrigin = ''; }
        else { canvas.style.transform = 'scale(' + (1 / zoom) + ')'; canvas.style.transformOrigin = 'center center'; }
    }

    function applyZoomLevel(level) {}

    /*  GUI Opacity  */
    function applyGUIOpacity(opacity) {
        document.documentElement.style.setProperty('--bl-gui-custom-opacity', opacity);
        if (opacity < 1.0) document.body.classList.add('bl-gui-transparent');
        else document.body.classList.remove('bl-gui-transparent');
    }

    /* [WIP] Shader System */

    function applyShaderFilters() {
        const s = config.shaders;
        const canvas = document.querySelector('canvas');
        if (!canvas) return;

        const filters = [];
        filters.push('brightness(' + s.brightness + ')');
        filters.push('contrast(' + s.contrast + ')');
        filters.push('saturate(' + s.saturate + ')');
        if (s.sepia > 0) filters.push('sepia(' + s.sepia + ')');
        if (s.hueRotate !== 0) filters.push('hue-rotate(' + s.hueRotate + 'deg)');
        if (s.bloom > 0) {
            const bloomBright = 1 + (s.bloom * 0.3);
            filters.push('brightness(' + bloomBright + ')');
        }

        canvas.style.filter = filters.join(' ');

        const vignetteEl = document.getElementById('bl-vignette');
        if (vignetteEl) {
            if (s.vignette > 0) {
                vignetteEl.style.display = 'block';
                const opacity = s.vignette * 0.8;
                vignetteEl.style.background = 'radial-gradient(circle, transparent ' + (60 - s.vignette * 20) + '%, rgba(0,0,0,' + opacity + ') 100%)';
            } else {
                vignetteEl.style.display = 'none';
            }
        }

        const fogEl = document.getElementById('bl-fog');
        if (fogEl) {
            if (s.fog > 0) {
                fogEl.style.display = 'block';
                fogEl.style.background = 'linear-gradient(to bottom, rgba(200,210,230,0) 0%, rgba(200,210,230,' + (s.fog * 0.5) + ') 100%)';
            } else {
                fogEl.style.display = 'none';
            }
        }

        const grainEl = document.getElementById('bl-grain');
        if (grainEl) {
            grainEl.style.display = s.grain ? 'block' : 'none';
        }

        if (s.fpsBoost) {
            let wrapper = document.getElementById('bl-canvas-wrapper');
            if (!wrapper) {
                wrapper = document.createElement('div');
                wrapper.id = 'bl-canvas-wrapper';
                document.body.insertBefore(wrapper, document.body.firstChild);
            }
            if (canvas.parentElement !== wrapper) {
                wrapper.appendChild(canvas);
            }
            const scale = s.resScale;
            canvas.style.width = (window.innerWidth / scale) + 'px';
            canvas.style.height = (window.innerHeight / scale) + 'px';
            canvas.style.transform = 'scale(' + scale + ')';
            canvas.style.transformOrigin = 'top left';
        } else {
            let wrapper = document.getElementById('bl-canvas-wrapper');
            if (wrapper && canvas.parentElement === wrapper) {
                document.body.insertBefore(canvas, wrapper);
                wrapper.remove();
            }
            canvas.style.width = '';
            canvas.style.height = '';
            canvas.style.transform = '';
            canvas.style.transformOrigin = '';
        }
    }

    /* UI Editor System */

    function buildUIEditorPanel() {
        const panel = document.getElementById('bl-ui-editor-panel');
        if (!panel) return;
        panel.innerHTML = `
            <div style="font-size:16px;font-weight:700;margin-bottom:4px;" id="bl-ui-panel-title">Select an element</div>
            <div style="font-size:12px;color:#94a3b8;margin-bottom:16px;" id="bl-ui-panel-sub">Click a HUD element to edit it.</div>
            <div id="bl-ui-controls" style="display:none;">
                <div style="margin-bottom:12px;">
                    <div style="font-size:12px;font-weight:600;margin-bottom:6px;">Position X</div>
                    <div style="display:flex;align-items:center;gap:10px;">
                        <input type="range" class="bl-slider" id="bl-ui-x" min="-500" max="500" step="1" style="flex:1;">
                        <span class="bl-slider-val" id="bl-ui-x-val">0</span>
                    </div>
                </div>
                <div style="margin-bottom:12px;">
                    <div style="font-size:12px;font-weight:600;margin-bottom:6px;">Position Y</div>
                    <div style="display:flex;align-items:center;gap:10px;">
                        <input type="range" class="bl-slider" id="bl-ui-y" min="-500" max="500" step="1" style="flex:1;">
                        <span class="bl-slider-val" id="bl-ui-y-val">0</span>
                    </div>
                </div>
                <div style="margin-bottom:12px;">
                    <div style="font-size:12px;font-weight:600;margin-bottom:6px;">Scale</div>
                    <div style="display:flex;align-items:center;gap:10px;">
                        <input type="range" class="bl-slider" id="bl-ui-scale" min="0.5" max="2.0" step="0.05" style="flex:1;">
                        <span class="bl-slider-val" id="bl-ui-scale-val">1.00</span>
                    </div>
                </div>
                <div style="margin-bottom:12px;">
                    <div style="font-size:12px;font-weight:600;margin-bottom:6px;">Opacity</div>
                    <div style="display:flex;align-items:center;gap:10px;">
                        <input type="range" class="bl-slider" id="bl-ui-opacity" min="0.1" max="1.0" step="0.05" style="flex:1;">
                        <span class="bl-slider-val" id="bl-ui-opacity-val">100%</span>
                    </div>
                </div>
                <div style="margin-bottom:16px;">
                    <div style="font-size:12px;font-weight:600;margin-bottom:6px;">Accent Color</div>
                    <div style="display:flex;align-items:center;gap:10px;">
                        <input type="color" id="bl-ui-color" style="width:40px;height:32px;border:none;border-radius:6px;cursor:pointer;background:none;">
                        <span style="font-size:12px;color:#94a3b8;" id="bl-ui-color-val">#3b82f6</span>
                    </div>
                </div>
                <div style="display:flex;gap:8px;">
                    <button class="bl-btn secondary" style="flex:1;" id="bl-ui-reset">Reset</button>
                    <button class="bl-btn" style="flex:1;" id="bl-ui-done">Done</button>
                </div>
            </div>
        `;

        panel.querySelector('#bl-ui-x').addEventListener('input', (e) => {
            if (!selectedUIElement) return;
            const v = parseInt(e.target.value);
            config.uiLayout[selectedUIElement].x = v;
            document.getElementById('bl-ui-x-val').textContent = v;
            updateUIElementEditPos(selectedUIElement);
            saveConfig();
        });

        panel.querySelector('#bl-ui-y').addEventListener('input', (e) => {
            if (!selectedUIElement) return;
            const v = parseInt(e.target.value);
            config.uiLayout[selectedUIElement].y = v;
            document.getElementById('bl-ui-y-val').textContent = v;
            updateUIElementEditPos(selectedUIElement);
            saveConfig();
        });

        panel.querySelector('#bl-ui-scale').addEventListener('input', (e) => {
            if (!selectedUIElement) return;
            const v = parseFloat(e.target.value);
            config.uiLayout[selectedUIElement].scale = v;
            document.getElementById('bl-ui-scale-val').textContent = v.toFixed(2);
            applyUILayout();
            saveConfig();
        });

        panel.querySelector('#bl-ui-opacity').addEventListener('input', (e) => {
            if (!selectedUIElement) return;
            const v = parseFloat(e.target.value);
            config.uiLayout[selectedUIElement].opacity = v;
            document.getElementById('bl-ui-opacity-val').textContent = Math.round(v*100) + '%';
            applyUILayout();
            saveConfig();
        });

        panel.querySelector('#bl-ui-color').addEventListener('input', (e) => {
            if (!selectedUIElement) return;
            const v = e.target.value;
            config.uiLayout[selectedUIElement].color = v;
            document.getElementById('bl-ui-color-val').textContent = v;
            applyUILayout();
            saveConfig();
        });

        panel.querySelector('#bl-ui-reset').addEventListener('click', () => {
            if (!selectedUIElement) return;
            const def = UI_DEFS[selectedUIElement];
            config.uiLayout[selectedUIElement] = { x: 0, y: 0, scale: 1, opacity: 1, color: def.defaultColor };
            applyUILayout();
            saveConfig();
            refreshUIEditorPanel();
            const el = document.querySelector(def.selector);
            if (el) {
                const rect = el.getBoundingClientRect();
                const base = ANCHORS[def.anchor](rect.width, rect.height, selectedUIElement);
                el.style.left = base.x + 'px';
                el.style.top = base.y + 'px';
            }
        });

        panel.querySelector('#bl-ui-done').addEventListener('click', exitUIEditMode);
    }

    function refreshUIEditorPanel() {
        if (!selectedUIElement) {
            const title = document.getElementById('bl-ui-panel-title');
            const sub = document.getElementById('bl-ui-panel-sub');
            const controls = document.getElementById('bl-ui-controls');
            if (title) title.textContent = 'Select an element';
            if (sub) { sub.style.display = 'block'; sub.textContent = 'Click a HUD element to edit it.'; }
            if (controls) controls.style.display = 'none';
            return;
        }
        const def = UI_DEFS[selectedUIElement];
        const layout = config.uiLayout[selectedUIElement];
        const title = document.getElementById('bl-ui-panel-title');
        const sub = document.getElementById('bl-ui-panel-sub');
        const controls = document.getElementById('bl-ui-controls');
        if (title) title.textContent = def.name;
        if (sub) sub.style.display = 'none';
        if (controls) controls.style.display = 'block';

        const xSlider = document.getElementById('bl-ui-x');
        const xVal = document.getElementById('bl-ui-x-val');
        if (xSlider) xSlider.value = layout.x;
        if (xVal) xVal.textContent = layout.x;

        const ySlider = document.getElementById('bl-ui-y');
        const yVal = document.getElementById('bl-ui-y-val');
        if (ySlider) ySlider.value = layout.y;
        if (yVal) yVal.textContent = layout.y;

        const scaleSlider = document.getElementById('bl-ui-scale');
        const scaleVal = document.getElementById('bl-ui-scale-val');
        if (scaleSlider) scaleSlider.value = layout.scale;
        if (scaleVal) scaleVal.textContent = layout.scale.toFixed(2);

        const opSlider = document.getElementById('bl-ui-opacity');
        const opVal = document.getElementById('bl-ui-opacity-val');
        if (opSlider) opSlider.value = layout.opacity;
        if (opVal) opVal.textContent = Math.round(layout.opacity*100) + '%';

        const colorInp = document.getElementById('bl-ui-color');
        const colorVal = document.getElementById('bl-ui-color-val');
        if (colorInp) colorInp.value = layout.color;
        if (colorVal) colorVal.textContent = layout.color;
    }

    function enterUIEditMode() {
        const overlay = document.getElementById('bl-ui-editor');
        if (overlay) overlay.classList.add('active');
        const hint = document.getElementById('bl-ui-editor-hint');
        if (hint) hint.classList.add('active');

        Object.keys(UI_DEFS).forEach(id => {
            const def = UI_DEFS[id];
            const el = document.querySelector(def.selector);
            if (!el) return;

            const rect = el.getBoundingClientRect();
            el.style.left = rect.left + 'px';
            el.style.top = rect.top + 'px';
            el.style.right = 'auto';
            el.style.bottom = 'auto';
            el.style.transform = 'none';

            el.classList.add('bl-ui-editor-el');
            el.dataset.uiId = id;
            el.addEventListener('mousedown', onUIElementMouseDown);
        });

        const panel = document.getElementById('bl-ui-editor-panel');
        if (panel) panel.classList.add('active');
        selectUIElement('keystrokes');
    }

    function exitUIEditMode() {
        const overlay = document.getElementById('bl-ui-editor');
        if (overlay) overlay.classList.remove('active');
        const hint = document.getElementById('bl-ui-editor-hint');
        if (hint) hint.classList.remove('active');
        const panel = document.getElementById('bl-ui-editor-panel');
        if (panel) panel.classList.remove('active');

        Object.keys(UI_DEFS).forEach(id => {
            const def = UI_DEFS[id];
            const el = document.querySelector(def.selector);
            if (!el) return;
            el.classList.remove('bl-ui-editor-el', 'bl-ui-selected');
            el.removeEventListener('mousedown', onUIElementMouseDown);
            delete el.dataset.uiId;
        });

        selectedUIElement = null;
        isDraggingUI = false;
        applyUILayout();
    }

    function onUIElementMouseDown(e) {
        if (!e.currentTarget.dataset.uiId) return;
        e.stopPropagation();
        e.preventDefault();

        selectUIElement(e.currentTarget.dataset.uiId);

        isDraggingUI = true;
        dragStartX = e.clientX;
        dragStartY = e.clientY;
        const rect = e.currentTarget.getBoundingClientRect();
        dragElStartX = rect.left;
        dragElStartY = rect.top;

        on(document, 'mousemove', onUIElementMouseMove, { passive: true });
        on(document, 'mouseup', onUIElementMouseUp, { passive: true });
    }

    function onUIElementMouseMove(e) {
        if (!isDraggingUI || !selectedUIElement) return;
        const el = document.querySelector(UI_DEFS[selectedUIElement].selector);
        if (!el) return;

        const dx = e.clientX - dragStartX;
        const dy = e.clientY - dragStartY;
        el.style.left = (dragElStartX + dx) + 'px';
        el.style.top = (dragElStartY + dy) + 'px';

        updateUILayoutFromElement(selectedUIElement, el);

        const layout = config.uiLayout[selectedUIElement];
        const xVal = document.getElementById('bl-ui-x-val');
        const yVal = document.getElementById('bl-ui-y-val');
        const xSlider = document.getElementById('bl-ui-x');
        const ySlider = document.getElementById('bl-ui-y');
        if (xVal) xVal.textContent = layout.x;
        if (yVal) yVal.textContent = layout.y;
        if (xSlider) xSlider.value = layout.x;
        if (ySlider) ySlider.value = layout.y;
    }

    function onUIElementMouseUp() {
        isDraggingUI = false;
        off(document, 'mousemove', onUIElementMouseMove, { passive: true });
        off(document, 'mouseup', onUIElementMouseUp, { passive: true });
        saveConfig();
    }

    function updateUILayoutFromElement(id, el) {
        const def = UI_DEFS[id];
        const rect = el.getBoundingClientRect();
        const layout = config.uiLayout[id];
        const base = ANCHORS[def.anchor](rect.width, rect.height, id);

        if (def.anchor === 'tr') {
            layout.x = base.x - rect.left;
        } else {
            layout.x = rect.left - base.x;
        }
        layout.y = rect.top - base.y;
    }

    function selectUIElement(id) {
        if (selectedUIElement) {
            const prev = document.querySelector(UI_DEFS[selectedUIElement]?.selector);
            if (prev) prev.classList.remove('bl-ui-selected');
        }
        selectedUIElement = id;
        const el = document.querySelector(UI_DEFS[id].selector);
        if (el) el.classList.add('bl-ui-selected');
        refreshUIEditorPanel();
    }

    function updateUIElementEditPos(id) {
        const def = UI_DEFS[id];
        const el = document.querySelector(def.selector);
        if (!el) return;
        const layout = config.uiLayout[id];
        const rect = el.getBoundingClientRect();
        const base = ANCHORS[def.anchor](rect.width, rect.height, id);

        if (def.anchor === 'tr') {
            el.style.left = (base.x - layout.x) + 'px';
        } else {
            el.style.left = (base.x + layout.x) + 'px';
        }
        el.style.top = (base.y + layout.y) + 'px';
    }

    function applyUILayout() {
        const l = config.uiLayout;

        const ks = document.getElementById('bl-keystrokes');
        if (ks) {
            ks.style.transform = 'translate(' + l.keystrokes.x + 'px, ' + l.keystrokes.y + 'px) scale(' + l.keystrokes.scale + ')';
            ks.style.opacity = l.keystrokes.opacity;
        }

        const fps = document.getElementById('bl-fps-counter');
        if (fps) {
            fps.style.transform = 'translate(' + l.fps.x + 'px, ' + l.fps.y + 'px) scale(' + l.fps.scale + ')';
            fps.style.opacity = l.fps.opacity;
        }

        const cps = document.getElementById('bl-cps-counter');
        if (cps) {
            cps.style.transform = 'translate(' + l.cps.x + 'px, ' + l.cps.y + 'px) scale(' + l.cps.scale + ')';
            cps.style.opacity = l.cps.opacity;
        }

        const sprint = document.getElementById('bl-sprint-indicator');
        if (sprint) {
            sprint.style.transform = 'translate(calc(-50% + ' + l.sprint.x + 'px), ' + l.sprint.y + 'px) scale(' + l.sprint.scale + ')';
            sprint.style.opacity = l.sprint.opacity;
        }

        const hud = document.getElementById('bloxd-legacy-hud');
        if (hud) {
            hud.style.transform = 'translate(' + (-l.hud.x) + 'px, ' + l.hud.y + 'px) scale(' + l.hud.scale + ')';
            hud.style.opacity = l.hud.opacity;
        }

        const ch = document.getElementById('bl-crosshair');
        if (ch) {
            ch.style.transform = 'translate(calc(-50% + ' + l.crosshair.x + 'px), calc(-50% + ' + l.crosshair.y + 'px)) scale(' + l.crosshair.scale + ')';
            ch.style.opacity = l.crosshair.opacity;
        }

        applyUIColors();
    }

    function applyUIColors() {
        const l = config.uiLayout;
        let css = '';

        css += '#bl-keystrokes .ks-key { border-color: ' + l.keystrokes.color + '33 !important; color: ' + l.keystrokes.color + ' !important; }';
        css += '#bl-keystrokes .ks-key.pressed { background: ' + l.keystrokes.color + ' !important; border-color: ' + l.keystrokes.color + ' !important; color: #fff !important; }';
        css += '#bl-fps-counter .bl-counter-val { color: ' + l.fps.color + ' !important; }';
        css += '#bl-fps-counter .bl-counter-label { color: ' + l.fps.color + 'aa !important; }';
        css += '#bl-cps-counter .bl-counter-val { color: ' + l.cps.color + ' !important; }';
        css += '#bl-cps-counter .bl-counter-label { color: ' + l.cps.color + 'aa !important; }';
        css += '#bl-sprint-indicator { color: ' + l.sprint.color + ' !important; }';
        css += '#bloxd-legacy-hud { color: ' + l.hud.color + ' !important; }';
        css += '#bloxd-legacy-hud::before { background: ' + l.hud.color + ' !important; box-shadow: 0 0 8px ' + l.hud.color + ' !important; }';
        css += '#bl-crosshair.bl-crosshair-default::before, #bl-crosshair.bl-crosshair-default::after { background: ' + l.crosshair.color + ' !important; }';
        css += '#bl-crosshair.bl-crosshair-circle::before { border-color: ' + l.crosshair.color + ' !important; }';
        css += '#bl-crosshair.bl-crosshair-dot::before { background: ' + l.crosshair.color + ' !important; }';
        css += '#bl-crosshair.bl-crosshair-cross::before, #bl-crosshair.bl-crosshair-cross::after { background: ' + l.crosshair.color + ' !important; }';

        let style = document.getElementById('bl-ui-custom-colors');
        if (!style) {
            style = document.createElement('style');
            style.id = 'bl-ui-custom-colors';
            document.head.appendChild(style);
        }
        style.textContent = css;
    }

    /* Menu Control */

    function switchTab(tab) {
        currentTab = tab;
        $all('.bl-tab').forEach(b => b.classList.toggle('active', b.dataset.tab === tab));
        $all('.bl-panel').forEach(p => p.classList.toggle('active', p.dataset.panel === tab));
    }

    function openMenu() {
        menuOpen = true;
        overlayEl.classList.add('active');
        setTimeout(() => overlayEl.focus(), 30);
    }

    function closeMenu() {
        menuOpen = false;
        overlayEl.classList.remove('active');
    }

    function toggleMenu() {
        menuOpen ? closeMenu() : openMenu();
    }

    /* Input Handling */

    on(document, 'keydown', function(e) {
        if (e.code === 'ShiftRight') {
            e.preventDefault();
            e.stopImmediatePropagation();
            toggleMenu();
            return;
        }

        if (menuOpen && e.code === 'Escape') {
            e.preventDefault();
            e.stopImmediatePropagation();
            closeMenu();
            return;
        }

        if (e.code === 'ShiftLeft' || e.code === 'ShiftRight') {
            manualShift = true;
        }

        if (config.combat.toggleSprint && e.code === 'KeyW' && !e.repeat && !manualShift && !autoShift) {
            autoShift = true;
            const shiftEvent = new KeyboardEvent('keydown', {
                key: 'Shift',
                code: 'ShiftLeft',
                shiftKey: true,
                bubbles: true,
                cancelable: true
            });
            document.dispatchEvent(shiftEvent);

            const ind = document.getElementById('bl-sprint-indicator');
            if (ind) ind.classList.add('active');
        }

        const uiEditor = document.getElementById('bl-ui-editor');
        if (uiEditor && uiEditor.classList.contains('active') && e.code === 'Escape') {
            e.preventDefault();
            e.stopImmediatePropagation();
            exitUIEditMode();
            return;
        }

        if (menuOpen) {
            const isSystem = e.ctrlKey || e.metaKey || e.altKey || (e.key && e.key.startsWith('F'));
            if (!isSystem) {
                e.stopImmediatePropagation();
            }
        }
    }, true);

    on(document, 'keyup', function(e) {
        if (e.code === 'ShiftLeft' || e.code === 'ShiftRight') {
            manualShift = false;
        }

        if (config.combat.toggleSprint && e.code === 'KeyW' && autoShift && !manualShift) {
            autoShift = false;
            const shiftEvent = new KeyboardEvent('keyup', {
                key: 'Shift',
                code: 'ShiftLeft',
                shiftKey: false,
                bubbles: true,
                cancelable: true
            });
            document.dispatchEvent(shiftEvent);

            const ind = document.getElementById('bl-sprint-indicator');
            if (ind) ind.classList.remove('active');
        }

        if (menuOpen) {
            const isSystem = e.ctrlKey || e.metaKey || e.altKey || (e.key && e.key.startsWith('F'));
            if (!isSystem) {
                e.stopImmediatePropagation();
            }
        }
    }, true);

    /* INIT Config */

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

})();