🎉 欢迎访问GreasyFork.Org 镜像站!本镜像站由公众号【爱吃馍】搭建,用于分享脚本。联系邮箱📮

Greasy fork 爱吃馍镜像

Greasy Fork is available in English.

📂 缓存分发状态(共享加速已生效)
🕒 页面同步时间:2026/01/24 01:14:58
🔄 下次更新时间:2026/01/24 02:14:58
手动刷新缓存

Null Client

Null Client — #2 Best Bloxd.io Client! 100+ Installs! v1.2 Launched!

Aby zainstalować ten skrypt, wymagana jest instalacje jednego z następujących rozszerzeń: Tampermonkey, Greasemonkey lub Violentmonkey.

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

Aby zainstalować ten skrypt, wymagana jest instalacje jednego z następujących rozszerzeń: Tampermonkey, Violentmonkey.

Aby zainstalować ten skrypt, wymagana będzie instalacja rozszerzenia Tampermonkey lub Userscripts.

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

Aby zainstalować ten skrypt, musisz zainstalować rozszerzenie menedżera skryptów użytkownika.

(Mam już menedżera skryptów użytkownika, pozwól mi to zainstalować!)

🚀 安装遇到问题?关注公众号获取帮助

公众号二维码

扫码关注【爱吃馍】

回复【脚本】获取最新教程和防失联地址

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

Będziesz musiał zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

Będziesz musiał zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

Musisz zainstalować rozszerzenie menedżera stylów użytkownika, aby zainstalować ten styl.

(Mam już menedżera stylów użytkownika, pozwól mi to zainstalować!)

🚀 安装遇到问题?关注公众号获取帮助

公众号二维码

扫码关注【爱吃馍】

回复【脚本】获取最新教程和防失联地址

// ==UserScript==
// @name         Null Client
// @namespace    null.client
// @version      1.2
// @match        https://bloxd.io/*
// @match        https://staging.bloxd.io/*
// @match        https://www.bloxdforge.com/studio/play/*
// @match        https://www.crazygames.com/game/bloxdhop-io/*
// @description  Null Client — #2 Best Bloxd.io Client! 100+ Installs! v1.2 Launched!
// @author       Nullscape
// @icon         https://i.postimg.cc/xjzYxS0R/Null-Client.png
// @run-at       document-start
// @grant        none
// ==/UserScript==

(function () {
  'use strict';

  const STORAGE_KEY = "null_client_v1.2_state";
  const DEFAULT_STATE = {
    version: "1.2",
    keystrokes: false,
    keystrokeMode: "wasd",
    cps: false,
    ping: false,
    armor: false,
    fps_display: false,
    coords: false,
    speedometer: false,
    cape: null,
    customCapes: [],
    locked: true,
    positions: {
      keystrokes: { bottom: 18, left: 18 },
      cps: { bottom: 66, left: 18 },
      ping: { bottom: 98, left: 18 },
      armor: { top: 18, right: 18 },
      fps_display: { top: 18, left: 18 },
      coords: { top: 50, left: 18 },
      speedometer: { top: 82, left: 18 },
      capeOverlay: { top: 54, right: 40 }
    },
    texture: "",
    fps: {
      scale: 1,
      pauseAnimations: false,
      removeBackgrounds: false
    },
    armorImage: null,
    keystrokeColors: {
      active: "#1f6feb",
      inactive: "#0c0d0e",
      text: "#ffffff",
      textInactive: "#cfe7ff"
    },
    zoom: 100,
    fov: 90,
    fullbright: false,
    noFire: false,
    noPumpkinBlur: false,
    lowFire: false,
    smoothZoom: false,
    noAds: true
  };

  let state = loadState();

  function loadState() {
    try {
      const raw = localStorage.getItem(STORAGE_KEY);
      if (!raw) return JSON.parse(JSON.stringify(DEFAULT_STATE));
      const parsed = JSON.parse(raw);
      return Object.assign(JSON.parse(JSON.stringify(DEFAULT_STATE)), parsed);
    } catch (e) {
      return JSON.parse(JSON.stringify(DEFAULT_STATE));
    }
  }

  function saveState() {
    try {
      localStorage.setItem(STORAGE_KEY, JSON.stringify(state));
    } catch (e) {
      console.error("Failed to save state:", e);
    }
  }

  // Remove advertisements
  function removeAds() {
    const adSelectors = [
      'iframe[src*="ads"]',
      'div[class*="ad-"]',
      'div[id*="ad-"]',
      'div[class*="advertisement"]',
      'div[id*="advertisement"]',
      '.afs_ads',
      '[data-ad-slot]',
      'ins.adsbygoogle',
      'div[class*="sponsor"]',
      'div[id*="sponsor"]'
    ];

    const style = document.createElement('style');
    style.textContent = adSelectors.join(',') + ' { display: none !important; visibility: hidden !important; }';
    (document.head || document.documentElement).appendChild(style);

    const observer = new MutationObserver(() => {
      adSelectors.forEach(selector => {
        document.querySelectorAll(selector).forEach(el => {
          el.style.display = 'none';
          el.remove();
        });
      });
    });

    observer.observe(document.body || document.documentElement, {
      childList: true,
      subtree: true
    });
  }

  // Replace Bloxd branding with Null Client
  function replaceBranding() {
    const observer = new MutationObserver(() => {
      // Replace logo images
      document.querySelectorAll('img[src*="bloxd"], img[alt*="bloxd"], img[alt*="Bloxd"]').forEach(img => {
        img.src = 'https://i.postimg.cc/xjzYxS0R/Null-Client.png';
        img.alt = 'Null Client';
      });

      // Replace text
      document.querySelectorAll('h1, h2, .logo, [class*="logo"]').forEach(el => {
        if (el.textContent.toLowerCase().includes('bloxd')) {
          el.textContent = el.textContent.replace(/bloxd/gi, 'Null Client');
        }
      });
    });

    observer.observe(document.body || document.documentElement, {
      childList: true,
      subtree: true
    });
  }

  // Custom loading screen
  function replaceLoadingScreen() {
    const style = document.createElement('style');
    style.textContent = `
      .loading-screen, [class*="loading"], [id*="loading"] {
        background: url('https://i.postimg.cc/ZnX3Fd5Y/68686868.png') center/cover no-repeat !important;
      }
    `;
    (document.head || document.documentElement).appendChild(style);

    const observer = new MutationObserver(() => {
      document.querySelectorAll('.loading-screen, [class*="loading"], [id*="loading"]').forEach(el => {
        el.style.background = "url('https://i.postimg.cc/ZnX3Fd5Y/68686868.png') center/cover no-repeat";
      });
    });

    observer.observe(document.body || document.documentElement, {
      childList: true,
      subtree: true
    });
  }

  // Smooth Zoom Implementation
  let currentZoom = 1;
  let targetZoom = 1;
  let isZooming = false;

  function smoothZoom() {
    if (!state.smoothZoom) return;

    const zoomSpeed = 0.15;
    const diff = targetZoom - currentZoom;

    if (Math.abs(diff) > 0.001) {
      currentZoom += diff * zoomSpeed;
      applyZoomToCamera(currentZoom);
      requestAnimationFrame(smoothZoom);
    } else {
      currentZoom = targetZoom;
      isZooming = false;
    }
  }

  function applyZoomToCamera(zoom) {
    try {
      const fov = 90 / zoom;
      if (window.camera && window.camera.fov !== undefined) {
        window.camera.fov = fov;
        if (window.camera.updateProjectionMatrix) {
          window.camera.updateProjectionMatrix();
        }
      } else if (window.game && window.game.camera) {
        window.game.camera.fov = fov;
        if (window.game.camera.updateProjectionMatrix) {
          window.game.camera.updateProjectionMatrix();
        }
      }
    } catch (e) {}
  }

  document.addEventListener('keydown', (e) => {
    if (!state.smoothZoom) return;

    if (e.code === 'KeyZ') {
      targetZoom = 2;
      if (!isZooming) {
        isZooming = true;
        smoothZoom();
      }
    } else if (e.code === 'KeyX') {
      targetZoom = 0.5;
      if (!isZooming) {
        isZooming = true;
        smoothZoom();
      }
    }
  });

  document.addEventListener('keyup', (e) => {
    if (!state.smoothZoom) return;

    if (e.code === 'KeyZ' || e.code === 'KeyX') {
      targetZoom = 1;
      if (!isZooming) {
        isZooming = true;
        smoothZoom();
      }
    }
  });

  let uiRoot = null;
  let uiOpen = false;

  document.addEventListener("keydown", e => {
    if (e.code === "ShiftRight") {
      e.preventDefault();
      uiOpen = !uiOpen;
      if (uiOpen) showUI();
      else hideUI();
    }
  });

  function showUI() {
    if (!uiRoot) createUI();
    uiRoot.style.display = "block";
  }

  function hideUI() {
    if (uiRoot) uiRoot.style.display = "none";
  }

  let createUICalled = false;

  function createUI() {
    if (createUICalled) return;
    createUICalled = true;
    if (!document.body) {
      document.addEventListener("DOMContentLoaded", createUI, { once: true });
      return;
    }

    uiRoot = document.createElement("div");
    uiRoot.style.cssText = "position:fixed; inset:0; z-index:2147483646; display:none; backdrop-filter: blur(2px);";
    document.body.appendChild(uiRoot);

    const shadow = uiRoot.attachShadow({ mode: "open" });

    shadow.innerHTML = `
      <style>
        :host { all: initial; }
        * { box-sizing: border-box; font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif; margin: 0; padding: 0; }

        .frame {
          position: absolute;
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
          width: 900px;
          height: 580px;
          background: linear-gradient(135deg, #0f1113 0%, #0b0c0d 100%);
          border-radius: 16px;
          display: flex;
          color: #e7eef6;
          box-shadow: 0 20px 60px rgba(0, 0, 0, 0.8), 0 0 0 1px rgba(255,255,255,0.05);
          overflow: hidden;
          animation: slideIn 0.3s ease-out;
        }

        @keyframes slideIn {
          from { opacity: 0; transform: translate(-50%, -48%) scale(0.96); }
          to { opacity: 1; transform: translate(-50%, -50%) scale(1); }
        }

        .sidebar {
          width: 190px;
          background: linear-gradient(180deg, #0b0c0d 0%, #08090a 100%);
          padding: 18px 14px;
          display: flex;
          flex-direction: column;
          gap: 12px;
          border-right: 1px solid rgba(255,255,255,0.03);
        }

        .logo {
          display: flex;
          align-items: center;
          gap: 12px;
          padding-bottom: 12px;
          border-bottom: 1px solid rgba(255,255,255,0.04);
        }

        .logo img {
          width: 38px;
          height: 38px;
          border-radius: 8px;
          box-shadow: 0 4px 12px rgba(0,0,0,0.4);
        }

        .brand {
          font-weight: 700;
          font-size: 15px;
          letter-spacing: 0.5px;
          background: linear-gradient(135deg, #fff 0%, #a0b5c9 100%);
          -webkit-background-clip: text;
          -webkit-text-fill-color: transparent;
        }

        .version {
          font-size: 11px;
          color: #6b7680;
        }

        .nav {
          margin-top: 6px;
          display: flex;
          flex-direction: column;
          gap: 4px;
        }

        .nav button {
          background: transparent;
          border: 1px solid transparent;
          color: #9ca8b3;
          text-align: left;
          padding: 10px 12px;
          border-radius: 10px;
          cursor: pointer;
          font-size: 13px;
          font-weight: 500;
          transition: all 0.15s ease;
        }

        .nav button:hover {
          background: rgba(255,255,255,0.03);
          color: #d4dfe8;
        }

        .nav button.active {
          background: linear-gradient(135deg, #1a1d20 0%, #141618 100%);
          border-color: rgba(255,255,255,0.06);
          color: #fff;
          box-shadow: 0 2px 8px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.03);
        }

        .nav .spacer {
          flex: 1;
          min-height: 20px;
        }

        .main {
          flex: 1;
          padding: 24px;
          display: flex;
          flex-direction: column;
          overflow-y: auto;
        }

        .main::-webkit-scrollbar {
          width: 8px;
        }

        .main::-webkit-scrollbar-track {
          background: transparent;
        }

        .main::-webkit-scrollbar-thumb {
          background: rgba(255,255,255,0.1);
          border-radius: 4px;
        }

        .header {
          display: flex;
          justify-content: space-between;
          align-items: center;
          margin-bottom: 20px;
        }

        .title {
          font-weight: 700;
          font-size: 18px;
          letter-spacing: 0.3px;
        }

        .subtitle {
          color: #7d8b98;
          font-size: 13px;
          margin-top: 2px;
        }

        .grid {
          display: grid;
          grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
          gap: 14px;
          margin-bottom: 20px;
        }

        .card {
          background: linear-gradient(135deg, #0e1012 0%, #0a0b0c 100%);
          border-radius: 12px;
          padding: 16px;
          border: 1px solid rgba(255,255,255,0.04);
          box-shadow: 0 4px 16px rgba(0,0,0,0.4);
          transition: all 0.2s ease;
        }

        .card:hover {
          border-color: rgba(255,255,255,0.08);
          box-shadow: 0 6px 20px rgba(0,0,0,0.5);
        }

        .card-title {
          font-weight: 700;
          margin-bottom: 6px;
          font-size: 14px;
          color: #e8f1f9;
        }

        .card-desc {
          color: #8793a0;
          font-size: 12px;
          margin-bottom: 12px;
          line-height: 1.4;
        }

        .toggle-row {
          display: flex;
          align-items: center;
          justify-content: space-between;
          background: linear-gradient(135deg, #0a0b0c 0%, #08090a 100%);
          padding: 10px 12px;
          border-radius: 10px;
          border: 1px solid rgba(255,255,255,0.03);
        }

        .toggle-row .label {
          font-size: 13px;
          color: #d4e1ed;
          font-weight: 500;
        }

        .switch {
          width: 48px;
          height: 26px;
          border-radius: 13px;
          background: #1a1d20;
          position: relative;
          cursor: pointer;
          border: 1px solid rgba(255,255,255,0.05);
          transition: all 0.2s ease;
        }

        .switch:hover {
          border-color: rgba(255,255,255,0.1);
        }

        .switch.on {
          background: linear-gradient(90deg, #2b9aff 0%, #1fb1ff 100%);
          box-shadow: 0 0 12px rgba(43,154,255,0.4);
        }

        .knob {
          width: 22px;
          height: 22px;
          border-radius: 11px;
          background: #fff;
          position: absolute;
          top: 2px;
          left: 2px;
          transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
          box-shadow: 0 2px 6px rgba(0,0,0,0.3);
        }

        .switch.on .knob {
          left: 24px;
        }

        .small {
          font-size: 12px;
          color: #8a96a3;
        }

        .footer {
          margin-top: auto;
          padding-top: 16px;
          border-top: 1px solid rgba(255,255,255,0.04);
          display: flex;
          justify-content: space-between;
          align-items: center;
          color: #7d8b98;
          font-size: 12px;
        }

        .btn {
          padding: 8px 14px;
          border-radius: 10px;
          background: linear-gradient(135deg, #1c1f22 0%, #181b1d 100%);
          border: 1px solid rgba(255,255,255,0.06);
          color: #e7eef6;
          cursor: pointer;
          font-size: 13px;
          font-weight: 500;
          transition: all 0.15s ease;
        }

        .btn:hover {
          background: linear-gradient(135deg, #242729 0%, #1f2224 100%);
          border-color: rgba(255,255,255,0.12);
          transform: translateY(-1px);
        }

        .btn:active {
          transform: translateY(0);
        }

        .btn-primary {
          background: linear-gradient(135deg, #2b9aff 0%, #1fb1ff 100%);
          border-color: rgba(255,255,255,0.1);
          box-shadow: 0 4px 12px rgba(43,154,255,0.25);
        }

        .btn-primary:hover {
          background: linear-gradient(135deg, #3da8ff 0%, #2fbdff 100%);
          box-shadow: 0 6px 16px rgba(43,154,255,0.35);
        }

        .color-picker {
          width: 44px;
          height: 32px;
          border-radius: 8px;
          cursor: pointer;
          border: 2px solid rgba(255,255,255,0.15);
          transition: all 0.2s ease;
        }

        .color-picker:hover {
          border-color: rgba(255,255,255,0.3);
          transform: scale(1.05);
        }

        input[type="color"] {
          opacity: 0;
          position: absolute;
          width: 0;
          height: 0;
        }

        input[type="text"],
        input[type="url"],
        input[type="number"],
        select {
          padding: 8px 12px;
          border-radius: 8px;
          background: #0a0b0c;
          color: #dfe8ef;
          border: 1px solid rgba(255,255,255,0.06);
          font-size: 13px;
          transition: all 0.2s ease;
        }

        input[type="text"]:focus,
        input[type="url"]:focus,
        input[type="number"]:focus,
        select:focus {
          outline: none;
          border-color: #2b9aff;
          box-shadow: 0 0 0 3px rgba(43,154,255,0.1);
        }

        .divider {
          height: 1px;
          background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.06) 50%, transparent 100%);
          margin: 12px 0;
        }

        .feature-group {
          margin-top: 12px;
          padding-top: 12px;
          border-top: 1px solid rgba(255,255,255,0.04);
        }

        .feature-group-title {
          font-size: 12px;
          color: #7d8b98;
          font-weight: 600;
          margin-bottom: 8px;
          text-transform: uppercase;
          letter-spacing: 0.5px;
        }

        .slider-container {
          margin-top: 10px;
        }

        .slider {
          width: 100%;
          height: 4px;
          border-radius: 2px;
          background: #1a1d20;
          outline: none;
          -webkit-appearance: none;
        }

        .slider::-webkit-slider-thumb {
          -webkit-appearance: none;
          appearance: none;
          width: 16px;
          height: 16px;
          border-radius: 50%;
          background: linear-gradient(135deg, #2b9aff 0%, #1fb1ff 100%);
          cursor: pointer;
          box-shadow: 0 2px 6px rgba(43,154,255,0.4);
        }

        .slider::-moz-range-thumb {
          width: 16px;
          height: 16px;
          border-radius: 50%;
          background: linear-gradient(135deg, #2b9aff 0%, #1fb1ff 100%);
          cursor: pointer;
          border: none;
          box-shadow: 0 2px 6px rgba(43,154,255,0.4);
        }
      </style>

      <div class="frame" id="frame">
        <div class="sidebar">
          <div class="logo">
            <img src="https://i.postimg.cc/xjzYxS0R/Null-Client.png" alt="logo">
            <div>
              <div class="brand">Null Client</div>
              <div class="version">v1.2</div>
            </div>
          </div>
          <div class="nav" id="nav">
            <button data-tab="player" class="active">🎮Player</button>
            <button data-tab="accessories">✨Accessories</button>
            <button data-tab="visual">🎨Visual</button>
            <button data-tab="extra">⚡Extra Client Features</button>
            <button data-tab="combat">⚔️Combat</button>
            <div class="spacer"></div>
            <button data-tab="settings">⚙️Settings</button>
            <button id="closeBtn">❌Exit</button>
          </div>
        </div>

        <div class="main">
          <div class="header">
            <div>
              <div class="title" id="mainTitle">Player Widgets</div>
              <div class="subtitle" id="mainSub">Client-side overlays and HUD elements</div>
            </div>
            <div>
              <button class="btn" id="lockToggle">🔒Locked</button>
            </div>
          </div>

          <div class="grid" id="gridArea"></div>

          <div class="footer">
            <div>Press <strong>Right Shift</strong> to toggle menu</div>
            <div class="small">All features are client-side only • Made by Nullscape</div>
          </div>
        </div>
      </div>
    `;

    const lockBtn = shadow.getElementById("lockToggle");
    lockBtn.textContent = state.locked ? "🔒Locked" : "🔓Unlocked";
    lockBtn.onclick = () => {
      state.locked = !state.locked;
      lockBtn.textContent = state.locked ? "🔒Locked" : "🔓Unlocked";
      saveState();
      updateLockState();
      showToast(state.locked ? "Widgets locked" : "Widgets unlocked - drag to reposition");
    };

    const nav = shadow.getElementById("nav");
    nav.addEventListener("click", e => {
      const btn = e.target.closest("button");
      if (!btn) return;
      if (btn.id === "closeBtn") {
        uiOpen = false;
        hideUI();
        return;
      }
      for (const b of nav.querySelectorAll("button")) b.classList.remove("active");
      btn.classList.add("active");
      const tab = btn.dataset.tab;
      const title = shadow.getElementById("mainTitle");
      const sub = shadow.getElementById("mainSub");
      const grid = shadow.getElementById("gridArea");
      grid.innerHTML = "";

      if (tab === "player") {
        title.textContent = "Player Widgets";
        sub.textContent = "Keystrokes, CPS, Ping, Armor, FPS, Coords & Speed";
        renderPlayerGrid(grid);
      } else if (tab === "accessories") {
        title.textContent = "Accessories";
        sub.textContent = "Client capes with realistic physics";
        renderAccessoriesGrid(grid);
      } else if (tab === "visual") {
        title.textContent = "Visual Enhancements";
        sub.textContent = "Texture packs, FPS boost & rendering options";
        renderVisualGrid(grid);
      } else if (tab === "extra") {
        title.textContent = "Extra Client Features";
        sub.textContent = "Advanced Bloxd.io enhancements";
        renderExtraGrid(grid);
      } else if (tab === "combat") {
        title.textContent = "Combat";
        sub.textContent = "Cosmetic combat tools (no cheats)";
        renderCombatGrid(grid);
      } else if (tab === "settings") {
        title.textContent = "Settings";
        sub.textContent = "Persistence, widget management & reset";
        renderSettingsGrid(grid);
      }
    });

    const initialGrid = shadow.getElementById("gridArea");
    renderPlayerGrid(initialGrid);
  }

  function makeToggleCard(title, desc, stateKey, onChange) {
    const el = document.createElement("div");
    el.className = "card";
    el.innerHTML = `
      <div class="card-title">${title}</div>
      <div class="card-desc">${desc}</div>
      <div class="toggle-row">
        <div class="label small">Enable</div>
        <div class="switch ${state[stateKey] ? "on" : ""}" data-key="${stateKey}">
          <div class="knob"></div>
        </div>
      </div>
    `;
    const sw = el.querySelector(".switch");
    sw.addEventListener("click", () => {
      const key = sw.dataset.key;
      state[key] = !state[key];
      saveState();
      sw.classList.toggle("on", !!state[key]);
      if (typeof onChange === "function") onChange(state[key]);

      if (key === "keystrokes") toggleKeystrokes(state[key]);
      if (key === "cps") toggleCPS(state[key]);
      if (key === "ping") togglePing(state[key]);
      if (key === "armor") toggleArmor(state[key]);
      if (key === "fps_display") toggleFPSDisplay(state[key]);
      if (key === "coords") toggleCoords(state[key]);
      if (key === "speedometer") toggleSpeedometer(state[key]);
      if (key === "fullbright") applyFullbright(state[key]);
      if (key === "noFire") applyNoFire(state[key]);
      if (key === "noPumpkinBlur") applyNoPumpkinBlur(state[key]);
      if (key === "lowFire") applyLowFire(state[key]);
      if (key === "smoothZoom") {
        if (state[key]) {
          showToast("Smooth Zoom enabled - Press Z/X to zoom");
        } else {
          showToast("Smooth Zoom disabled");
          currentZoom = 1;
          targetZoom = 1;
          applyZoomToCamera(1);
        }
      }
    });
    return el;
  }

  function renderPlayerGrid(container) {
    container.appendChild(makeToggleCard(
      "CPS Counter",
      "Counts left and right mouse clicks per second (Format: L | R)",
      "cps"
    ));

    container.appendChild(makeToggleCard(
      "Ping Display",
      "Shows your estimated network latency in milliseconds",
      "ping"
    ));

    container.appendChild(makeToggleCard(
      "FPS Counter",
      "Real-time frames per second display",
      "fps_display"
    ));

    container.appendChild(makeToggleCard(
      "Coordinates",
      "Shows your current X, Y, Z position in the world",
      "coords"
    ));

    container.appendChild(makeToggleCard(
      "Speedometer",
      "Displays your current movement speed (blocks/sec)",
      "speedometer"
    ));

    const ksCard = makeToggleCard(
      "Keystrokes Display",
      "Shows keyboard input with customizable colors and modes",
      "keystrokes"
    );

    const ksExtras = document.createElement("div");
    ksExtras.className = "feature-group";
    ksExtras.innerHTML = `
      <div class="feature-group-title">Keystroke Mode</div>
      <select id="ks-mode" style="width:100%; margin-bottom:10px;">
        <option value="wasd" ${state.keystrokeMode === "wasd" ? "selected" : ""}>WASD Keys</option>
        <option value="arrows" ${state.keystrokeMode === "arrows" ? "selected" : ""}>Arrow Keys</option>
      </select>
      <div class="feature-group-title">Color Customization</div>
      <div style="display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-top:8px;">
        <div>
          <label class="small" style="display:block; margin-bottom:4px;">Active Color</label>
          <div class="color-picker" style="background:${state.keystrokeColors.active};" id="ks-active"></div>
        </div>
        <div>
          <label class="small" style="display:block; margin-bottom:4px;">Inactive Color</label>
          <div class="color-picker" style="background:${state.keystrokeColors.inactive};" id="ks-inactive"></div>
        </div>
      </div>
    `;
    ksCard.appendChild(ksExtras);

    ksCard.querySelector("#ks-mode").onchange = (e) => {
      state.keystrokeMode = e.target.value;
      saveState();
      if (keyUI) {
        toggleKeystrokes(false);
        toggleKeystrokes(true);
      }
      showToast(`Keystroke mode: ${e.target.value.toUpperCase()}`);
    };

    ksCard.querySelector("#ks-active").onclick = () => {
      const input = document.createElement("input");
      input.type = "color";
      input.value = state.keystrokeColors.active;
      input.onchange = (e) => {
        state.keystrokeColors.active = e.target.value;
        saveState();
        ksCard.querySelector("#ks-active").style.background = e.target.value;
        refreshKeyUI();
      };
      input.click();
    };

    ksCard.querySelector("#ks-inactive").onclick = () => {
      const input = document.createElement("input");
      input.type = "color";
      input.value = state.keystrokeColors.inactive;
      input.onchange = (e) => {
        state.keystrokeColors.inactive = e.target.value;
        saveState();
        ksCard.querySelector("#ks-inactive").style.background = e.target.value;
        refreshKeyUI();
      };
      input.click();
    };

    container.appendChild(ksCard);

    container.appendChild(makeToggleCard(
      "Armor Display",
      "Shows your current armor equipment (syncs with game state)",
      "armor"
    ));
  }

  function renderAccessoriesGrid(container) {
    const card = document.createElement("div");
    card.className = "card";
    card.style.gridColumn = "1 / -1";
    card.innerHTML = `
      <div class="card-title">🎭Client Capes with Physics</div>
      <div class="card-desc">Only you can see these capes • Now with realistic Optifine-style physics!</div>

      <div style="display:flex; gap:8px; margin-top:12px; flex-wrap:wrap;">
        <button id="cape-none" class="btn">No Cape</button>
        <button id="cape-gray" class="btn">Gray Cape</button>
        <button id="cape-dark" class="btn">Dark Cape</button>
        <button id="cape-rainbow" class="btn">Rainbow Cape</button>
      </div>

      <div class="divider"></div>

      <div class="feature-group-title">Add Custom Cape</div>
      <div style="display:grid; grid-template-columns:1fr auto; gap:8px; margin-top:8px;">
        <input id="capeUrl" type="url" placeholder="Paste image URL here..." style="width:100%;">
        <button id="addUrl" class="btn btn-primary">Add URL</button>
      </div>

      <div style="margin-top:8px;">
        <input id="capeFile" type="file" accept="image/*" style="color:#dfe8ef; font-size:12px;">
        <button id="addFile" class="btn" style="margin-top:6px;">Upload Image</button>
      </div>

      <div class="divider"></div>

      <div class="feature-group-title">Your Custom Capes</div>
      <div id="customCapesList" style="max-height:150px; overflow-y:auto; margin-top:8px;"></div>
    `;
    container.appendChild(card);

    function updateList() {
      const list = card.querySelector("#customCapesList");
      list.innerHTML = "";
      if (!state.customCapes || state.customCapes.length === 0) {
        const p = document.createElement("div");
        p.className = "small";
        p.textContent = "No custom capes added yet.";
        p.style.padding = "12px";
        p.style.textAlign = "center";
        p.style.color = "#6b7680";
        list.appendChild(p);
        return;
      }
      state.customCapes.forEach((c, i) => {
        const row = document.createElement("div");
        row.style.display = "flex";
        row.style.alignItems = "center";
        row.style.gap = "10px";
        row.style.marginBottom = "8px";
        row.style.padding = "8px";
        row.style.background = "rgba(255,255,255,0.02)";
        row.style.borderRadius = "8px";

        const thumb = document.createElement("div");
        thumb.style.width = "80px";
        thumb.style.height = "50px";
        thumb.style.background = c.dataUrl ? `url(${c.dataUrl}) center/cover no-repeat` : "#0f0f0f";
        thumb.style.borderRadius = "6px";
        thumb.style.border = "1px solid rgba(255,255,255,0.1)";

        const name = document.createElement("div");
        name.textContent = c.name || ("Custom Cape " + (i + 1));
        name.style.color = "#dfe8ef";
        name.style.flex = "1";
        name.style.fontSize = "13px";

        const sel = document.createElement("button");
        sel.textContent = "Select";
        sel.className = "btn";
        sel.style.fontSize = "12px";
        sel.onclick = () => {
          state.cape = "custom:" + i;
          saveState();
          applyCape(state.cape);
          showToast("Custom cape selected!");
        };

        const rem = document.createElement("button");
        rem.textContent = "Remove";
        rem.className = "btn";
        rem.style.fontSize = "12px";
        rem.onclick = () => {
          if (!confirm("Remove this custom cape?")) return;
          state.customCapes.splice(i, 1);
          if ((state.cape || "").startsWith("custom:")) {
            const cur = parseInt(state.cape.split(":")[1], 10);
            if (cur === i) state.cape = null;
            else if (cur > i) state.cape = "custom:" + (cur - 1);
          }
          saveState();
          updateList();
          applyCape(state.cape);
        };

        row.appendChild(thumb);
        row.appendChild(name);
        row.appendChild(sel);
        row.appendChild(rem);
        list.appendChild(row);
      });
    }

    card.querySelector("#cape-none").onclick = () => {
      state.cape = null;
      saveState();
      applyCape(null);
      showToast("Cape disabled");
    };
    card.querySelector("#cape-gray").onclick = () => {
      state.cape = "gray";
      saveState();
      applyCape("gray");
      showToast("Gray cape enabled");
    };
    card.querySelector("#cape-dark").onclick = () => {
      state.cape = "dark";
      saveState();
      applyCape("dark");
      showToast("Dark cape enabled");
    };
    card.querySelector("#cape-rainbow").onclick = () => {
      state.cape = "rainbow";
      saveState();
      applyCape("rainbow");
      showToast("Rainbow cape enabled");
    };

    card.querySelector("#addUrl").onclick = () => {
      const url = (card.querySelector("#capeUrl").value || "").trim();
      if (!url) {
        alert("Please paste an image URL.");
        return;
      }
      state.customCapes.push({
        name: url.split("/").pop() || "custom",
        dataUrl: url
      });
      saveState();
      updateList();
      showToast("Custom cape added!");
      card.querySelector("#capeUrl").value = "";
    };

    card.querySelector("#addFile").onclick = () => {
      const f = card.querySelector("#capeFile").files[0];
      if (!f) {
        alert("Choose a file first.");
        return;
      }
      const r = new FileReader();
      r.onload = () => {
        state.customCapes.push({
          name: f.name,
          dataUrl: r.result
        });
        saveState();
        updateList();
        showToast("Custom cape uploaded!");
      };
      r.readAsDataURL(f);
    };

    updateList();
  }

  function renderVisualGrid(container) {
    const textureCard = document.createElement("div");
    textureCard.className = "card";
    textureCard.innerHTML = `
      <div class="card-title">🎨Texture Pack</div>
      <div class="card-desc">Client-side visual filters for different aesthetics</div>
      <div style="display:flex; gap:8px; margin-top:10px; flex-wrap:wrap;">
        <button id="texReset" class="btn">Reset</button>
        <button id="texMono" class="btn">Monochrome</button>
        <button id="texHigh" class="btn">High Contrast</button>
      </div>
    `;
    container.appendChild(textureCard);

    textureCard.querySelector("#texReset").onclick = () => {
      state.texture = "";
      applyTexture("");
      saveState();
      showToast("Texture reset");
    };
    textureCard.querySelector("#texMono").onclick = () => {
      state.texture = "mono";
      applyTexture("mono");
      saveState();
      showToast("Monochrome texture applied");
    };
    textureCard.querySelector("#texHigh").onclick = () => {
      state.texture = "highcontrast";
      applyTexture("highcontrast");
      saveState();
      showToast("High contrast texture applied");
    };

    const fpsCard = document.createElement("div");
    fpsCard.className = "card";
    fpsCard.innerHTML = `
      <div class="card-title">⚡ FPS Boost</div>
      <div class="card-desc">Optimize rendering for better performance</div>
      <div style="display:flex; gap:8px; margin-top:10px; flex-wrap:wrap;">
        <button id="fpsReset" class="btn">Reset (1.0x)</button>
        <button id="fps075" class="btn">Scale 0.75x</button>
        <button id="fps05" class="btn">Scale 0.5x</button>
      </div>
      <div class="feature-group">
        <label class="small" style="display:block; margin-bottom:6px;">
          <input id="fpsPause" type="checkbox" style="margin-right:6px;">
          Pause CSS animations
        </label>
        <label class="small" style="display:block;">
          <input id="fpsBg" type="checkbox" style="margin-right:6px;">
          Remove background images
        </label>
      </div>
    `;
    container.appendChild(fpsCard);

    fpsCard.querySelector("#fps075").onclick = () => {
      state.fps.scale = 0.75;
      applyFPSState();
      saveState();
      showToast("Canvas scaled to 0.75x");
    };
    fpsCard.querySelector("#fps05").onclick = () => {
      state.fps.scale = 0.5;
      applyFPSState();
      saveState();
      showToast("Canvas scaled to 0.5x");
    };
    fpsCard.querySelector("#fpsReset").onclick = () => {
      state.fps.scale = 1;
      state.fps.pauseAnimations = false;
      state.fps.removeBackgrounds = false;
      fpsCard.querySelector("#fpsPause").checked = false;
      fpsCard.querySelector("#fpsBg").checked = false;
      applyFPSState();
      saveState();
      showToast("FPS settings reset");
    };

    fpsCard.querySelector("#fpsPause").checked = !!state.fps.pauseAnimations;
    fpsCard.querySelector("#fpsBg").checked = !!state.fps.removeBackgrounds;
    fpsCard.querySelector("#fpsPause").onchange = (e) => {
      state.fps.pauseAnimations = e.target.checked;
      applyFPSState();
      saveState();
    };
    fpsCard.querySelector("#fpsBg").onchange = (e) => {
      state.fps.removeBackgrounds = e.target.checked;
      applyFPSState();
      saveState();
    };
  }

  function renderExtraGrid(container) {
    container.appendChild(makeToggleCard(
      "💡Fullbright",
      "Maximum brightness - see everything clearly in dark areas",
      "fullbright"
    ));

    container.appendChild(makeToggleCard(
      "🔥No Fire Overlay",
      "Removes fire overlay when burning for better visibility",
      "noFire"
    ));

    container.appendChild(makeToggleCard(
      "🔻Low Fire",
      "Lowers fire overlay height for improved view",
      "lowFire"
    ));

    container.appendChild(makeToggleCard(
      "🎃No Pumpkin Blur",
      "Removes pumpkin helmet overlay blur effect",
      "noPumpkinBlur"
    ));

    container.appendChild(makeToggleCard(
      "🔍Smooth Zoom",
      "Smooth zoom in/out with Z and X keys for better gameplay",
      "smoothZoom"
    ));

    const zoomCard = document.createElement("div");
    zoomCard.className = "card";
    zoomCard.innerHTML = `
      <div class="card-title">🎯FOV Adjuster</div>
      <div class="card-desc">Customize your field of view (30° - 110°)</div>
      <div class="slider-container">
        <div style="display:flex; justify-content:space-between; margin-bottom:6px;">
          <span class="small">FOV:</span>
          <span class="small" id="fovValue">${state.fov}°</span>
        </div>
        <input type="range" min="30" max="110" value="${state.fov}" class="slider" id="fovSlider">
      </div>
      <div style="display:flex; gap:8px; margin-top:10px;">
        <button id="fovDefault" class="btn">Default (90°)</button>
        <button id="fovZoom" class="btn">Wide (110°)</button>
      </div>
    `;
    container.appendChild(zoomCard);

    const fovSlider = zoomCard.querySelector("#fovSlider");
    const fovValue = zoomCard.querySelector("#fovValue");

    fovSlider.oninput = (e) => {
      const val = parseInt(e.target.value);
      fovValue.textContent = val + "°";
      state.fov = val;
      applyFOV(val);
      saveState();
    };

    zoomCard.querySelector("#fovDefault").onclick = () => {
      state.fov = 90;
      fovSlider.value = 90;
      fovValue.textContent = "90°";
      applyFOV(90);
      saveState();
      showToast("FOV reset to 90°");
    };

    zoomCard.querySelector("#fovZoom").onclick = () => {
      state.fov = 110;
      fovSlider.value = 110;
      fovValue.textContent = "110°";
      applyFOV(110);
      saveState();
      showToast("Wide FOV activated (110°)");
    };
  }

  function renderCombatGrid(container) {
    const card = document.createElement("div");
    card.className = "card";
    card.innerHTML = `
      <div class="card-title">⚔️ Combat (Cosmetic Only)</div>
      <div class="card-desc">These features are purely visual and do not provide gameplay advantages.</div>
      <div style="margin-top:12px;">
        <div class="toggle-row">
          <div class="label small">Local target outline</div>
          <div class="switch" data-key="outline"><div class="knob"></div></div>
        </div>
        <div style="height:10px"></div>
        <div class="toggle-row">
          <div class="label small">Local auto-hotbar visuals</div>
          <div class="switch" data-key="hotbar"><div class="knob"></div></div>
        </div>
      </div>
      <div style="margin-top:12px; padding:10px; background:rgba(255,200,100,0.05); border-radius:8px; border:1px solid rgba(255,200,100,0.1);">
        <div class="small" style="color:#ffc864;">⚠️Note: These are cosmetic-only features that do not affect actual gameplay or give any competitive advantage.</div>
      </div>
    `;
    container.appendChild(card);

    card.querySelectorAll(".switch").forEach(s => {
      s.addEventListener("click", () => {
        s.classList.toggle("on");
        showToast("This is cosmetic-only");
      });
    });
  }

  function renderSettingsGrid(container) {
    const card = document.createElement("div");
    card.className = "card";
    card.style.gridColumn = "1 / -1";
    card.innerHTML = `
      <div class="card-title">⚙️Client Settings</div>
      <div class="card-desc">Manage your Null Client configuration</div>

      <div class="feature-group">
        <div class="feature-group-title">Widget Management</div>
        <div style="padding:12px; background:rgba(255,255,255,0.02); border-radius:8px; margin-top:8px;">
          <div class="small" style="margin-bottom:8px;">
            • Click the <strong>🔒 Lock/Unlock</strong> button in the header to enable widget dragging<br>
            • When unlocked, drag widgets to reposition them<br>
            • Single-click any widget to toggle it on/off<br>
            • All positions are automatically saved
          </div>
        </div>
      </div>

      <div class="feature-group">
        <div class="feature-group-title">Reset Options</div>
        <div style="display:flex; gap:8px; margin-top:8px;">
          <button id="resetPositions" class="btn">Reset Widget Positions</button>
          <button id="resetAll" class="btn" style="background:linear-gradient(135deg,#ff4444,#cc0000); border-color:rgba(255,255,255,0.1);">Reset All Settings</button>
        </div>
      </div>

      <div class="feature-group">
        <div class="feature-group-title">About</div>
        <div style="padding:12px; background:rgba(255,255,255,0.02); border-radius:8px; margin-top:8px;">
          <div class="small">
            <strong>Null Client v1.2</strong><br>
            Created by Nullscape<br><br>
            Features:<br>
            • 10+ HUD widgets with full customization<br>
            • Capes with realistic physics<br>
            • Smooth zoom & FOV control<br>
            • Ad-free experience<br>
            • FPS optimization tools<br>
            • All features are client-side only<br><br>
            Compatible with Tampermonkey 5.4.1 and latest Bloxd.io version
          </div>
        </div>
      </div>
    `;
    container.appendChild(card);

    card.querySelector("#resetPositions").onclick = () => {
      if (!confirm("Reset all widget positions to default?")) return;
      state.positions = JSON.parse(JSON.stringify(DEFAULT_STATE.positions));
      saveState();
      showToast("Widget positions reset");
      setTimeout(() => location.reload(), 1000);
    };

    card.querySelector("#resetAll").onclick = () => {
      if (!confirm("⚠️Reset ALL Null Client settings?\n\nThis will:\n• Remove all custom capes\n• Reset widget positions\n• Reset all preferences\n• Clear all saved data\n\nThis cannot be undone!")) return;
      localStorage.removeItem(STORAGE_KEY);
      state = loadState();
      showToast("Settings reset - reloading...");
      setTimeout(() => location.reload(), 1000);
    };
  }

  // Widget implementations (keystrokes, CPS, ping, etc.)
  let keyUI = null;
  const keyState = { key1: false, key2: false, key3: false, key4: false };

  function toggleKeystrokes(on) {
    if (on && !keyUI) {
      keyUI = document.createElement("div");
      keyUI.style.cssText = widgetStyle("keystrokes") + "display:flex;gap:6px;align-items:center;justify-content:center;padding:8px 10px;font-size:13px;backdrop-filter:blur(4px);";

      const keys = state.keystrokeMode === "wasd" ? ["W", "A", "S", "D"] : ["↑", "←", "↓", "→"];
      const keyCodes = state.keystrokeMode === "wasd" ? ["w", "a", "s", "d"] : ["ArrowUp", "ArrowLeft", "ArrowDown", "ArrowRight"];

      keys.forEach((k, i) => {
        const b = document.createElement("div");
        b.textContent = k;
        b.dataset.keyindex = i;
        Object.assign(b.style, {
          padding: "8px 10px",
          background: state.keystrokeColors.inactive,
          borderRadius: "8px",
          color: state.keystrokeColors.textInactive,
          border: "1px solid rgba(255,255,255,0.08)",
          minWidth: "28px",
          textAlign: "center",
          transition: "all 0.1s ease",
          fontWeight: "600",
          boxShadow: "0 2px 4px rgba(0,0,0,0.2)"
        });
        keyUI.appendChild(b);
      });

      const ctrl = document.createElement("div");
      ctrl.style.display = "flex";
      ctrl.style.flexDirection = "column";
      ctrl.style.marginLeft = "10px";
      ctrl.style.gap = "4px";

      const lmb = document.createElement("div");
      lmb.textContent = "LMB";
      lmb.style.fontSize = "10px";
      lmb.style.color = "#8fa5b8";
      lmb.style.opacity = "0.7";
      lmb.style.fontWeight = "600";
      lmb.dataset.btn = "lmb";

      const rmb = document.createElement("div");
      rmb.textContent = "RMB";
      rmb.style.fontSize = "10px";
      rmb.style.color = "#8fa5b8";
      rmb.style.opacity = "0.7";
      rmb.style.fontWeight = "600";
      rmb.dataset.btn = "rmb";

      ctrl.appendChild(lmb);
      ctrl.appendChild(rmb);
      keyUI.appendChild(ctrl);

      document.body.appendChild(keyUI);
      positionWidget(keyUI, "keystrokes");
      attachWidgetClickToggle(keyUI, "keystrokes");
      if (!state.locked) makeDraggable(keyUI, "keystrokes");

      window.addEventListener("keydown", keyDownHandler);
      window.addEventListener("keyup", keyUpHandler);
      window.addEventListener("mousedown", mouseDownHandlerForKeys);
      window.addEventListener("mouseup", mouseUpHandlerForKeys);
    } else if (!on && keyUI) {
      keyUI.remove();
      keyUI = null;
      window.removeEventListener("keydown", keyDownHandler);
      window.removeEventListener("keyup", keyUpHandler);
      window.removeEventListener("mousedown", mouseDownHandlerForKeys);
      window.removeEventListener("mouseup", mouseUpHandlerForKeys);
    }
  }

  function keyDownHandler(e) {
    const keyCodes = state.keystrokeMode === "wasd" ? ["w", "a", "s", "d"] : ["ArrowUp", "ArrowLeft", "ArrowDown", "ArrowRight"];
    const k = e.key.toLowerCase();
    const idx = keyCodes.findIndex(code => code.toLowerCase() === k || code.toLowerCase() === e.key || code === e.key);
    if (idx !== -1) {
      keyState["key" + (idx + 1)] = true;
      refreshKeyUI();
    }
  }

  function keyUpHandler(e) {
    const keyCodes = state.keystrokeMode === "wasd" ? ["w", "a", "s", "d"] : ["ArrowUp", "ArrowLeft", "ArrowDown", "ArrowRight"];
    const k = e.key.toLowerCase();
    const idx = keyCodes.findIndex(code => code.toLowerCase() === k || code.toLowerCase() === e.key || code === e.key);
    if (idx !== -1) {
      keyState["key" + (idx + 1)] = false;
      refreshKeyUI();
    }
  }

  function refreshKeyUI() {
    if (!keyUI) return;
    for (const child of keyUI.children) {
      const idx = child.dataset && child.dataset.keyindex;
      if (idx === undefined) continue;
      const keyNum = parseInt(idx) + 1;
      if (keyState["key" + keyNum]) {
        child.style.background = state.keystrokeColors.active;
        child.style.color = state.keystrokeColors.text;
        child.style.transform = "translateY(-2px)";
        child.style.boxShadow = "0 4px 8px rgba(0,0,0,0.3)";
      } else {
        child.style.background = state.keystrokeColors.inactive;
        child.style.color = state.keystrokeColors.textInactive;
        child.style.transform = "";
        child.style.boxShadow = "0 2px 4px rgba(0,0,0,0.2)";
      }
    }
  }

  function mouseDownHandlerForKeys(e) {
    if (!keyUI) return;
    const l = keyUI.querySelector("[data-btn='lmb']");
    const r = keyUI.querySelector("[data-btn='rmb']");
    if (e.button === 0 && l) {
      l.style.opacity = "1";
      l.style.color = state.keystrokeColors.active;
    }
    if (e.button === 2 && r) {
      r.style.opacity = "1";
      r.style.color = state.keystrokeColors.active;
    }
  }

  function mouseUpHandlerForKeys(e) {
    if (!keyUI) return;
    const l = keyUI.querySelector("[data-btn='lmb']");
    const r = keyUI.querySelector("[data-btn='rmb']");
    if (e.button === 0 && l) {
      l.style.opacity = "0.7";
      l.style.color = "#8fa5b8";
    }
    if (e.button === 2 && r) {
      r.style.opacity = "0.7";
      r.style.color = "#8fa5b8";
    }
  }

  // CPS Widget
  let cpsUI = null;
  let leftClicks = 0;
  let rightClicks = 0;

  document.addEventListener("mousedown", e => {
    if (e.button === 0) leftClicks++;
    else if (e.button === 2) rightClicks++;
  });

  setInterval(() => {
    if (cpsUI) {
      cpsUI.textContent = leftClicks + " | " + rightClicks + " CPS";
      leftClicks = 0;
      rightClicks = 0;
    } else {
      leftClicks = 0;
      rightClicks = 0;
    }
  }, 1000);

  function toggleCPS(on) {
    if (on && !cpsUI) {
      cpsUI = document.createElement("div");
      cpsUI.style.cssText = widgetStyle("cps") + "width:110px;height:34px;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;";
      cpsUI.textContent = "0 | 0 CPS";
      document.body.appendChild(cpsUI);
      positionWidget(cpsUI, "cps");
      attachWidgetClickToggle(cpsUI, "cps");
      if (!state.locked) makeDraggable(cpsUI, "cps");
    } else if (!on && cpsUI) {
      cpsUI.remove();
      cpsUI = null;
    }
  }

  // Ping Widget
  let pingUI = null;
  let pingInterval = null;

  async function measurePing() {
    try {
      const url = location.origin + "/favicon.ico?t=" + Date.now();
      const start = performance.now();
      await fetch(url, { method: "HEAD", cache: "no-store" });
      const ms = Math.max(0, Math.round(performance.now() - start));
      if (pingUI) pingUI.textContent = ms + " ms";
    } catch (err) {
      if (pingUI) pingUI.textContent = "— ms";
    }
  }

  function togglePing(on) {
    if (on && !pingUI) {
      pingUI = document.createElement("div");
      pingUI.style.cssText = widgetStyle("ping") + "width:90px;height:32px;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:600;";
      pingUI.textContent = "... ms";
      document.body.appendChild(pingUI);
      positionWidget(pingUI, "ping");
      measurePing();
      pingInterval = setInterval(measurePing, 2500);
      attachWidgetClickToggle(pingUI, "ping");
      if (!state.locked) makeDraggable(pingUI, "ping");
    } else if (!on && pingUI) {
      clearInterval(pingInterval);
      pingInterval = null;
      pingUI.remove();
      pingUI = null;
    }
  }

  // FPS Display Widget
  let fpsUI = null;
  let lastTime = performance.now();
  let frames = 0;

  function updateFPS() {
    frames++;
    const currentTime = performance.now();
    if (currentTime >= lastTime + 1000) {
      const fps = Math.round((frames * 1000) / (currentTime - lastTime));
      if (fpsUI) fpsUI.textContent = fps + " FPS";
      frames = 0;
      lastTime = currentTime;
    }
    if (fpsUI) requestAnimationFrame(updateFPS);
  }

  function toggleFPSDisplay(on) {
    if (on && !fpsUI) {
      fpsUI = document.createElement("div");
      fpsUI.style.cssText = widgetStyle("fps_display") + "width:90px;height:32px;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:700;";
      fpsUI.textContent = "60 FPS";
      document.body.appendChild(fpsUI);
      positionWidget(fpsUI, "fps_display");
      attachWidgetClickToggle(fpsUI, "fps_display");
      if (!state.locked) makeDraggable(fpsUI, "fps_display");
      lastTime = performance.now();
      frames = 0;
      requestAnimationFrame(updateFPS);
    } else if (!on && fpsUI) {
      fpsUI.remove();
      fpsUI = null;
    }
  }

  // Coordinates Widget
  let coordsUI = null;
  let coordsInterval = null;

  function updateCoords() {
    try {
      let x = 0, y = 0, z = 0;
      if (window.player && window.player.position) {
        x = Math.round(window.player.position.x || 0);
        y = Math.round(window.player.position.y || 0);
        z = Math.round(window.player.position.z || 0);
      } else if (window.game && window.game.player && window.game.player.position) {
        x = Math.round(window.game.player.position.x || 0);
        y = Math.round(window.game.player.position.y || 0);
        z = Math.round(window.game.player.position.z || 0);
      }
      if (coordsUI) {
        coordsUI.innerHTML = `
          <div style="font-size:10px; color:#8fa5b8; margin-bottom:2px;">XYZ</div>
          <div style="font-size:12px; font-weight:600;">${x}, ${y}, ${z}</div>
        `;
      }
    } catch (err) {
      if (coordsUI) coordsUI.textContent = "X:0 Y:0 Z:0";
    }
  }

  function toggleCoords(on) {
    if (on && !coordsUI) {
      coordsUI = document.createElement("div");
      coordsUI.style.cssText = widgetStyle("coords") + "width:130px;height:42px;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:6px;";
      coordsUI.textContent = "Loading...";
      document.body.appendChild(coordsUI);
      positionWidget(coordsUI, "coords");
      updateCoords();
      coordsInterval = setInterval(updateCoords, 100);
      attachWidgetClickToggle(coordsUI, "coords");
      if (!state.locked) makeDraggable(coordsUI, "coords");
    } else if (!on && coordsUI) {
      clearInterval(coordsInterval);
      coordsInterval = null;
      coordsUI.remove();
      coordsUI = null;
    }
  }

  // Speedometer Widget
  let speedUI = null;
  let speedInterval = null;
  let lastPos = { x: 0, y: 0, z: 0, time: Date.now() };

  function updateSpeed() {
    try {
      let x = 0, y = 0, z = 0;
      if (window.player && window.player.position) {
        x = window.player.position.x || 0;
        y = window.player.position.y || 0;
        z = window.player.position.z || 0;
      } else if (window.game && window.game.player && window.game.player.position) {
        x = window.game.player.position.x || 0;
        y = window.game.player.position.y || 0;
        z = window.game.player.position.z || 0;
      }
      const now = Date.now();
      const dt = (now - lastPos.time) / 1000;
      if (dt > 0) {
        const dx = x - lastPos.x;
        const dz = z - lastPos.z;
        const dist = Math.sqrt(dx * dx + dz * dz);
        const speed = (dist / dt).toFixed(2);
        if (speedUI) {
          speedUI.innerHTML = `
            <div style="font-size:10px; color:#8fa5b8; margin-bottom:2px;">SPEED</div>
            <div style="font-size:13px; font-weight:700;">${speed} b/s</div>
          `;
        }
        lastPos = { x, y, z, time: now };
      }
    } catch (err) {
      if (speedUI) speedUI.textContent = "0.00 b/s";
    }
  }

  function toggleSpeedometer(on) {
    if (on && !speedUI) {
      speedUI = document.createElement("div");
      speedUI.style.cssText = widgetStyle("speedometer") + "width:100px;height:42px;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:6px;";
      speedUI.textContent = "0.00 b/s";
      document.body.appendChild(speedUI);
      positionWidget(speedUI, "speedometer");
      if (window.player && window.player.position) {
        lastPos = { x: window.player.position.x || 0, y: window.player.position.y || 0, z: window.player.position.z || 0, time: Date.now() };
      }
      speedInterval = setInterval(updateSpeed, 100);
      attachWidgetClickToggle(speedUI, "speedometer");
      if (!state.locked) makeDraggable(speedUI, "speedometer");
    } else if (!on && speedUI) {
      clearInterval(speedInterval);
      speedInterval = null;
      speedUI.remove();
      speedUI = null;
    }
  }

  // Armor View Widget
  let armorUI = null;
  let armorInterval = null;

  function updateArmorPreview() {
    if (!armorUI) return;
    const img = armorUI.querySelector("img");
    let found = null;
    try {
      if (window.player && window.player.armor) found = window.player.armor;
      else if (window.player && window.player.avatar && window.player.avatar.armorImage) found = window.player.avatar.armorImage;
      else if (window.game && window.game.player && window.game.player.armorUrl) found = window.game.player.armorUrl;
      else if (window.game && window.game.player && window.game.player.armor) found = window.game.player.armor;
    } catch (e) {}
    if (!found && state.armorImage) found = state.armorImage;
    if (found) {
      img.src = typeof found === 'string' ? found : (found.src || found.url || "");
      img.style.background = "";
      img.style.opacity = "1";
    } else {
      img.src = "";
      img.style.background = "linear-gradient(135deg, #1a1d20, #0f1113)";
      img.style.opacity = "0.5";
    }
  }

  function toggleArmor(on) {
    if (on && !armorUI) {
      armorUI = document.createElement("div");
      armorUI.style.cssText = widgetStyle("armor") + "width:150px;height:150px;display:flex;flex-direction:column;align-items:center;justify-content:center;padding:10px;";
      const title = document.createElement("div");
      title.textContent = "ARMOR";
      title.style.fontSize = "11px";
      title.style.color = "#8fa5b8";
      title.style.marginBottom = "8px";
      title.style.fontWeight = "700";
      title.style.letterSpacing = "1px";
      const img = document.createElement("img");
      img.style.width = "100px";
      img.style.height = "100px";
      img.style.objectFit = "contain";
      img.style.borderRadius = "10px";
      img.style.border = "2px solid rgba(255,255,255,0.1)";
      armorUI.appendChild(title);
      armorUI.appendChild(img);
      document.body.appendChild(armorUI);
      positionWidget(armorUI, "armor");
      updateArmorPreview();
      armorInterval = setInterval(updateArmorPreview, 500);
      attachWidgetClickToggle(armorUI, "armor");
      if (!state.locked) makeDraggable(armorUI, "armor");
    } else if (!on && armorUI) {
      clearInterval(armorInterval);
      armorInterval = null;
      armorUI.remove();
      armorUI = null;
    }
  }

  // Cape with Physics
  let capeOverlay = null;
  let capePhysics = { rotation: 0, velocity: 0, targetRotation: 0 };
  let capeAnimFrame = null;

  function applyCape(spec) {
    if (capeOverlay) {
      capeOverlay.remove();
      capeOverlay = null;
      if (capeAnimFrame) cancelAnimationFrame(capeAnimFrame);
    }
    if (!spec) return;
    capeOverlay = document.createElement("div");
    capeOverlay.style.position = "fixed";
    capeOverlay.style.width = "140px";
    capeOverlay.style.height = "200px";
    capeOverlay.style.pointerEvents = "none";
    capeOverlay.style.zIndex = "2147483645";
    capeOverlay.style.borderRadius = "8px";
    capeOverlay.style.boxShadow = "0 8px 24px rgba(0,0,0,0.6)";
    capeOverlay.style.transformOrigin = "top center";
    capeOverlay.style.transition = "none";
    const pos = state.positions.capeOverlay || { top: 54, right: 40 };
    capeOverlay.style.top = (pos.top || 54) + "px";
    capeOverlay.style.right = (pos.right || 40) + "px";
    if (spec === "gray") capeOverlay.style.background = "linear-gradient(180deg, #ddd, #888)";
    else if (spec === "dark") capeOverlay.style.background = "linear-gradient(180deg, #1a1a1a, #0a0a0a)";
    else if (spec === "rainbow") capeOverlay.style.background = "linear-gradient(135deg, #ff0080, #ff8c00, #40e0d0, #9d00ff)";
    else if (spec.startsWith("custom:")) {
      const i = parseInt(spec.split(":")[1], 10);
      const obj = state.customCapes[i];
      if (obj && obj.dataUrl) {
        capeOverlay.style.background = `url(${obj.dataUrl}) center/cover no-repeat`;
      } else {
        capeOverlay.style.background = "#0f0f0f";
      }
    } else {
      capeOverlay.style.background = "#0f0f0f";
    }
    document.body.appendChild(capeOverlay);
    attachWidgetClickToggle(capeOverlay, "cape");
    if (!state.locked) makeDraggable(capeOverlay, "capeOverlay", { storePositionAs: "capeOverlay" });
    animateCape();
  }

  function animateCape() {
    if (!capeOverlay) return;
    let speed = 0;
    try {
      if (window.player && window.player.velocity) {
        const v = window.player.velocity;
        speed = Math.sqrt((v.x || 0) ** 2 + (v.z || 0) ** 2);
      } else if (window.game && window.game.player && window.game.player.velocity) {
        const v = window.game.player.velocity;
        speed = Math.sqrt((v.x || 0) ** 2 + (v.z || 0) ** 2);
      }
    } catch (e) {}
    capePhysics.targetRotation = Math.min(speed * 3, 15) * (Math.random() > 0.5 ? 1 : -1);
    const diff = capePhysics.targetRotation - capePhysics.rotation;
    capePhysics.velocity += diff * 0.05;
    capePhysics.velocity *= 0.85;
    capePhysics.rotation += capePhysics.velocity;
    const wave = Math.sin(Date.now() / 500) * 2;
    capeOverlay.style.transform = `
      perspective(500px)
      rotateY(${capePhysics.rotation}deg)
      rotateX(${wave}deg)
      translateZ(-10px)
    `;
    capeAnimFrame = requestAnimationFrame(animateCape);
  }

  // Extra Client Features
  const FULLBRIGHT_STYLE_ID = "null-fullbright-style";

  function applyFullbright(on) {
    const old = document.getElementById(FULLBRIGHT_STYLE_ID);
    if (old) old.remove();
    if (on) {
      const css = `
        canvas, #gameCanvas, [id*="canvas"], [class*="canvas"] {
          filter: brightness(1.8) !important;
        }
        body {
          background: #1a1a1a !important;
        }
      `;
      const s = document.createElement("style");
      s.id = FULLBRIGHT_STYLE_ID;
      s.textContent = css;
      (document.head || document.documentElement).appendChild(s);
      showToast("Fullbright enabled");
    } else {
      showToast("Fullbright disabled");
    }
  }

  const NOFIRE_STYLE_ID = "null-nofire-style";

  function applyNoFire(on) {
    const old = document.getElementById(NOFIRE_STYLE_ID);
    if (old) old.remove();
    if (on) {
      const css = `
        [class*="fire"], [id*="fire"], .fire-overlay, #fireOverlay {
          display: none !important;
          opacity: 0 !important;
        }
      `;
      const s = document.createElement("style");
      s.id = NOFIRE_STYLE_ID;
      s.textContent = css;
      (document.head || document.documentElement).appendChild(s);
      showToast("No Fire enabled");
    } else {
      showToast("No Fire disabled");
    }
  }

  const LOWFIRE_STYLE_ID = "null-lowfire-style";

  function applyLowFire(on) {
    const old = document.getElementById(LOWFIRE_STYLE_ID);
    if (old) old.remove();
    if (on) {
      const css = `
        [class*="fire"], [id*="fire"], .fire-overlay, #fireOverlay {
          transform: scale(0.4) translateY(60%) !important;
          opacity: 0.6 !important;
        }
      `;
      const s = document.createElement("style");
      s.id = LOWFIRE_STYLE_ID;
      s.textContent = css;
      (document.head || document.documentElement).appendChild(s);
      showToast("Low Fire enabled");
    } else {
      showToast("Low Fire disabled");
    }
  }

  const NOPUMPKIN_STYLE_ID = "null-nopumpkin-style";

  function applyNoPumpkinBlur(on) {
    const old = document.getElementById(NOPUMPKIN_STYLE_ID);
    if (old) old.remove();
    if (on) {
      const css = `
        [class*="pumpkin"], [id*="pumpkin"], .pumpkin-blur, #pumpkinOverlay {
          display: none !important;
          opacity: 0 !important;
          filter: none !important;
        }
      `;
      const s = document.createElement("style");
      s.id = NOPUMPKIN_STYLE_ID;
      s.textContent = css;
      (document.head || document.documentElement).appendChild(s);
      showToast("No Pumpkin Blur enabled");
    } else {
      showToast("No Pumpkin Blur disabled");
    }
  }

  function applyFOV(value) {
    try {
      if (window.camera && window.camera.fov !== undefined) {
        window.camera.fov = value;
        if (window.camera.updateProjectionMatrix) {
          window.camera.updateProjectionMatrix();
        }
      } else if (window.game && window.game.camera) {
        window.game.camera.fov = value;
        if (window.game.camera.updateProjectionMatrix) {
          window.game.camera.updateProjectionMatrix();
        }
      }
    } catch (e) {
      console.log("FOV adjust:", e.message);
    }
  }

  const CLIENT_STYLE_ID = "null-client-style";

  function applyTexture(mode) {
    removeClientStyle();
    if (!mode) return;
    let css = "";
    if (mode === "mono") {
      css = `
        canvas, img, video, [data-game-canvas] {
          filter: grayscale(1) contrast(1.3) brightness(1.1) !important;
        }
        body {
          background: #0f0f0f !important;
        }
      `;
    } else if (mode === "highcontrast") {
      css = `
        canvas, img, video, [data-game-canvas] {
          filter: contrast(1.6) brightness(0.95) saturate(1.2) !important;
        }
        body {
          background: #0a0a0a !important;
        }
      `;
    }
    if (css) {
      const s = document.createElement("style");
      s.id = CLIENT_STYLE_ID;
      s.textContent = css;
      (document.head || document.documentElement).appendChild(s);
    }
  }

  function removeClientStyle() {
    const old = document.getElementById(CLIENT_STYLE_ID);
    if (old) old.remove();
  }

  const FPS_STYLE_ID = "null-client-fps-style";
  const canvasesScaled = new WeakMap();

  function applyFPSState() {
    const scale = (state.fps && state.fps.scale) ? state.fps.scale : 1;
    document.querySelectorAll("canvas").forEach(c => {
      try {
        const meta = canvasesScaled.get(c);
        if (meta) {
          if (scale === 1) {
            c.width = meta.origWidth;
            c.height = meta.origHeight;
            c.style.transform = meta.origTransform || "";
            c.style.imageRendering = meta.origImageRendering || "";
            canvasesScaled.delete(c);
          } else {
            c.width = Math.round(meta.origWidth * scale);
            c.height = Math.round(meta.origHeight * scale);
            c.style.transform = `scale(${1 / scale})`;
            c.style.transformOrigin = "0 0";
            c.style.imageRendering = "pixelated";
          }
        } else {
          if (scale !== 1) {
            const origW = c.width;
            const origH = c.height;
            canvasesScaled.set(c, {
              origWidth: origW,
              origHeight: origH,
              origTransform: c.style.transform || "",
              origImageRendering: c.style.imageRendering || ""
            });
            c.width = Math.round(origW * scale);
            c.height = Math.round(origH * scale);
            c.style.transform = `scale(${1 / scale})`;
            c.style.transformOrigin = "0 0";
            c.style.imageRendering = "pixelated";
          }
        }
      } catch (e) {}
    });
    const old = document.getElementById(FPS_STYLE_ID);
    if (old) old.remove();
    let css = "";
    if (state.fps.pauseAnimations) {
      css += `* { animation-play-state: paused !important; transition: none !important; }`;
    }
    if (state.fps.removeBackgrounds) {
      css += `body, [style*="background"], [style*="background-image"] { background-image: none !important; background: #0a0a0a !important; }`;
    }
    if (css) {
      const s = document.createElement("style");
      s.id = FPS_STYLE_ID;
      s.textContent = css;
      (document.head || document.documentElement).appendChild(s);
    }
  }

  function widgetStyle(key) {
    const pos = (state.positions && state.positions[key]) ? state.positions[key] : {};
    const pieces = [];
    if (pos.bottom !== undefined) pieces.push("bottom:" + pos.bottom + "px");
    if (pos.top !== undefined) pieces.push("top:" + pos.top + "px");
    if (pos.left !== undefined) pieces.push("left:" + pos.left + "px");
    if (pos.right !== undefined) pieces.push("right:" + pos.right + "px");
    pieces.push("position:fixed");
    pieces.push("background:rgba(10,11,12,0.88)");
    pieces.push("border-radius:10px");
    pieces.push("border:1px solid rgba(255,255,255,0.08)");
    pieces.push("color:#e8f3ff");
    pieces.push("padding:8px");
    pieces.push("box-shadow:0 4px 16px rgba(0,0,0,0.5)");
    pieces.push("backdrop-filter:blur(4px)");
    pieces.push("z-index:2147483644");
    return pieces.join(";") + ";";
  }

  function positionWidget(el, key) {
    const pos = (state.positions && state.positions[key]) ? state.positions[key] : {};
    if (pos.top !== undefined) el.style.top = pos.top + "px";
    if (pos.bottom !== undefined) el.style.bottom = pos.bottom + "px";
    if (pos.left !== undefined) el.style.left = pos.left + "px";
    if (pos.right !== undefined) el.style.right = pos.right + "px";
  }

  const DRAGMAP = new WeakMap();

  function makeDraggable(el, key, opts = {}) {
    removeDraggable(el);
    el.style.cursor = "move";
    const storeKey = opts.storePositionAs || key;
    let dragging = false;
    let startX = 0;
    let startY = 0;
    let startLeft = 0;
    let startTop = 0;
    const onDown = (ev) => {
      if (ev.button !== 0) return;
      ev.preventDefault();
      startX = ev.clientX;
      startY = ev.clientY;
      const rect = el.getBoundingClientRect();
      startLeft = rect.left;
      startTop = rect.top;
      const onMove = (mv) => {
        mv.preventDefault();
        const dx = mv.clientX - startX;
        const dy = mv.clientY - startY;
        if (!dragging && Math.hypot(dx, dy) > 6) dragging = true;
        if (dragging) {
          const newLeft = Math.max(0, Math.round(startLeft + dx));
          const newTop = Math.max(0, Math.round(startTop + dy));
          el.style.left = newLeft + "px";
          el.style.top = newTop + "px";
          el.style.right = "";
          el.style.bottom = "";
        }
      };
      const onUp = () => {
        window.removeEventListener("mousemove", onMove);
        window.removeEventListener("mouseup", onUp);
        if (dragging) {
          const b = el.getBoundingClientRect();
          state.positions = state.positions || {};
          state.positions[storeKey] = {
            top: Math.max(0, Math.round(b.top)),
            left: Math.max(0, Math.round(b.left))
          };
          saveState();
        }
        setTimeout(() => { dragging = false; }, 10);
      };
      window.addEventListener("mousemove", onMove);
      window.addEventListener("mouseup", onUp);
    };
    el.addEventListener("mousedown", onDown);
    DRAGMAP.set(el, onDown);
  }

  function removeDraggable(el) {
    const h = DRAGMAP.get(el);
    if (h) {
      el.removeEventListener("mousedown", h);
      DRAGMAP.delete(el);
    }
    el.style.cursor = "";
  }

  function updateLockState() {
    const keys = ["keystrokes", "cps", "ping", "armor", "fps_display", "coords", "speedometer", "capeOverlay"];
    for (const k of keys) {
      const el = getWidget(k);
      if (!el) continue;
      if (!state.locked) {
        makeDraggable(el, k, { storePositionAs: k === "capeOverlay" ? "capeOverlay" : k });
      } else {
        removeDraggable(el);
      }
    }
  }

  function getWidget(key) {
    if (key === "keystrokes") return keyUI;
    if (key === "cps") return cpsUI;
    if (key === "ping") return pingUI;
    if (key === "armor") return armorUI;
    if (key === "fps_display") return fpsUI;
    if (key === "coords") return coordsUI;
    if (key === "speedometer") return speedUI;
    if (key === "capeOverlay") return capeOverlay;
    return null;
  }

  function attachWidgetClickToggle(el, widgetKey) {
    if (!el) return;
    let down = null;
    const downHandler = (ev) => {
      if (ev.button !== 0) return;
      down = { x: ev.clientX, y: ev.clientY, t: Date.now() };
    };
    const upHandler = (ev) => {
      if (!down) return;
      const dx = ev.clientX - down.x;
      const dy = ev.clientY - down.y;
      if (Math.hypot(dx, dy) <= 6 && (Date.now() - down.t) < 500) {
        if (widgetKey === "keystrokes") {
          state.keystrokes = !state.keystrokes;
          toggleKeystrokes(state.keystrokes);
          saveState();
          showToast("Keystrokes " + (state.keystrokes ? "ON" : "OFF"));
        } else if (widgetKey === "cps") {
          state.cps = !state.cps;
          toggleCPS(state.cps);
          saveState();
          showToast("CPS " + (state.cps ? "ON" : "OFF"));
        } else if (widgetKey === "ping") {
          state.ping = !state.ping;
          togglePing(state.ping);
          saveState();
          showToast("Ping " + (state.ping ? "ON" : "OFF"));
        } else if (widgetKey === "armor") {
          state.armor = !state.armor;
          toggleArmor(state.armor);
          saveState();
          showToast("Armor " + (state.armor ? "ON" : "OFF"));
        } else if (widgetKey === "fps_display") {
          state.fps_display = !state.fps_display;
          toggleFPSDisplay(state.fps_display);
          saveState();
          showToast("FPS Display " + (state.fps_display ? "ON" : "OFF"));
        } else if (widgetKey === "coords") {
          state.coords = !state.coords;
          toggleCoords(state.coords);
          saveState();
          showToast("Coords " + (state.coords ? "ON" : "OFF"));
        } else if (widgetKey === "speedometer") {
          state.speedometer = !state.speedometer;
          toggleSpeedometer(state.speedometer);
          saveState();
          showToast("Speedometer " + (state.speedometer ? "ON" : "OFF"));
        } else if (widgetKey === "cape") {
          if (state.cape) {
            state.cape = null;
            applyCape(null);
            saveState();
            showToast("Cape disabled");
          } else {
            showToast("Select a cape from Accessories tab");
          }
        }
      }
      down = null;
    };
    el.addEventListener("mousedown", downHandler);
    el.addEventListener("mouseup", upHandler);
  }

  let toastEl = null;

  function showToast(msg, ms = 1500) {
    if (!toastEl) {
      toastEl = document.createElement("div");
      toastEl.style.cssText = `
        position:fixed;
        left:50%;
        bottom:30px;
        transform:translateX(-50%);
        background:linear-gradient(135deg, rgba(10,12,14,0.95), rgba(6,8,10,0.95));
        color:#e8f3ff;
        padding:12px 20px;
        border-radius:10px;
        z-index:2147483650;
        font-size:14px;
        font-weight:600;
        border:1px solid rgba(255,255,255,0.1);
        box-shadow:0 8px 24px rgba(0,0,0,0.6);
        backdrop-filter:blur(8px);
        pointer-events:none;
      `;
      document.body.appendChild(toastEl);
    }
    toastEl.textContent = msg;
    toastEl.style.opacity = "1";
    toastEl.style.transform = "translateX(-50%) translateY(0)";
    setTimeout(() => {
      if (toastEl) {
        toastEl.style.opacity = "0";
        toastEl.style.transform = "translateX(-50%) translateY(10px)";
      }
    }, ms);
  }

  window.addEventListener("beforeunload", saveState);

  // Initialize everything
  setTimeout(() => {
    console.log("🎮Null Client v1.2 Initialized");

    // Apply branding changes
    removeAds();
    replaceBranding();
    replaceLoadingScreen();

    // Restore widgets
    if (state.keystrokes) toggleKeystrokes(true);
    if (state.cps) toggleCPS(true);
    if (state.ping) togglePing(true);
    if (state.armor) toggleArmor(true);
    if (state.fps_display) toggleFPSDisplay(true);
    if (state.coords) toggleCoords(true);
    if (state.speedometer) toggleSpeedometer(true);

    // Restore cape
    if (state.cape) applyCape(state.cape);

    // Restore visual settings
    if (state.texture) applyTexture(state.texture);
    applyFPSState();

    // Restore features
    if (state.fullbright) applyFullbright(true);
    if (state.noFire) applyNoFire(true);
    if (state.lowFire) applyLowFire(true);
    if (state.noPumpkinBlur) applyNoPumpkinBlur(true);
    if (state.fov !== 90) applyFOV(state.fov);

    // Update lock state
    setTimeout(updateLockState, 400);

    showToast("🎮Null Client v1.2 Loaded!");
  }, 500);

})();