lyfcku

Ningga

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

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.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         lyfcku
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  Ningga
// @author       Lynn
// @match        https://www.geoguessr.com/*
// @grant        GM_xmlhttpRequest
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_addStyle
// @grant        GM_addElement
// @grant        GM.getValue
// @grant        GM.setValue
// @grant        GM.addStyle
// @grant        GM.addElement
// @connect      flagcdn.com
// @connect      static-maps.yandex.ru
// @connect      fonts.googleapis.com
// @connect      i.imgur.com
// @connect      minimalistmoon.com
// @connect      us1.locationiq.com
// @connect      locationiq.com
// @connect      discord.com
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';


    const nativeOpen = window.open;

    const CONFIG = {
        VERSION: '4.0.0',
        API_KEYS: [
            'pk.010bb988be9b2a316e7093ae8e316e6d',
            'pk.6ce0e2bf3b2b84e353d2420b38de8ed2',
            'pk.78f4624afaebfd926a65e31358a4507d'
        ]
    };

    class Utils {
        static logs = [];
        static logListeners = [];

        static generateId() {
            return 'user_' + Math.random().toString(36).substring(2, 15);
        }

        static log(message, type = 'info') {
            const timestamp = new Date().toLocaleTimeString();
            const logEntry = { timestamp, message, type };
            this.logs.unshift(logEntry);
            if (this.logs.length > 100) this.logs.pop();

            this.logListeners.forEach(listener => listener(logEntry));
        }

        static addLogListener(listener) {
            this.logListeners.push(listener);
        }

        static async sleep(ms) {
            return new Promise(resolve => setTimeout(resolve, ms));
        }
    }

    class Settings {
        constructor() {
            this.defaults = {
                menuHotkey: 'Insert',
                apiKeyIndex: 0,
                leaderboardId: Utils.generateId(),
                leaderboardName: 'Player',
                participateInLeaderboard: true,
                isToastEnabled: true,
                firstRun: true,
                firstWebhookRun: true,
                sidebarWidth: 240,
                apiKeyStatus: {},
                elementPositions: {},
                features: {
                    openGM: false,
                    openPlonkIT: false,
                    locationDisplay: false,
                    tts: false,
                    discordWebhook: false,
                    watermark: true,
                    mapTimer: true,
                    hotkeyDisplay: false,
                    toastNotifications: true,
                },
                featureSettings: {
                    locationDisplay: {
                        showCountry: true,
                        showState: true,
                        showCity: true,
                        stateZoom: 5,
                        cityZoom: 10
                    },
                    tts: {
                        volume: 1.0
                    },
                    discordWebhook: {
                        url: ''
                    },
                    watermark: {
                        position: 'top-center',
                        showName: true,
                        showUsername: true,
                        showClock: true,
                        timeFormat: '12h'
                    },
                    hotkeyDisplay: {
                        mode: 'active',
                        showToggle: true,
                        showTrigger: true
                    },
                    toastNotifications: {
                        position: 'bottom-right'
                    }
                },
                hotkeys: {
                    openGM: { trigger: 'q' },
                    openPlonkIT: { trigger: 'q' },
                    locationDisplay: { trigger: 'q' },
                    discordWebhook: { trigger: 'q' },
                    tts: { trigger: 'e' },
                    hotkeyDisplay: { toggle: 'J', trigger: null }
                },
                currentTheme: 'default',
                customThemes: {},
                defaultThemes: {
                    default: {
                        name: 'Lunar Purple',
                        colors: {
                            carbonBlack: { color: '#1a1a1a', alpha: 1, effect: 'none' },
                            carbonBlack2: { color: '#1d1d1d', alpha: 1, effect: 'none' },
                            carbonBlack3: { color: '#242424', alpha: 1, effect: 'none' },
                            accent: { color: '#8b5cf6', alpha: 1, effect: 'none' },
                            accentHover: { color: '#7c3aed', alpha: 1, effect: 'none' },
                            text: { color: '#ffffff', alpha: 1, effect: 'none' },
                            textDim: { color: '#a1a1aa', alpha: 1, effect: 'none' },
                            border: { color: '#333333', alpha: 1, effect: 'none' }
                        }
                    },
                    blue: {
                        name: 'Ocean Blue',
                        colors: {
                            carbonBlack: { color: '#0f172a', alpha: 1, effect: 'none' },
                            carbonBlack2: { color: '#1e293b', alpha: 1, effect: 'none' },
                            carbonBlack3: { color: '#334155', alpha: 1, effect: 'none' },
                            accent: { color: '#3b82f6', alpha: 1, effect: 'none' },
                            accentHover: { color: '#2563eb', alpha: 1, effect: 'none' },
                            text: { color: '#ffffff', alpha: 1, effect: 'none' },
                            textDim: { color: '#94a3b8', alpha: 1, effect: 'none' },
                            border: { color: '#475569', alpha: 1, effect: 'none' }
                        }
                    },
                    green: {
                        name: 'Forest Green',
                        colors: {
                            carbonBlack: { color: '#14532d', alpha: 1, effect: 'none' },
                            carbonBlack2: { color: '#166534', alpha: 1, effect: 'none' },
                            carbonBlack3: { color: '#15803d', alpha: 1, effect: 'none' },
                            accent: { color: '#22c55e', alpha: 1, effect: 'none' },
                            accentHover: { color: '#16a34a', alpha: 1, effect: 'none' },
                            text: { color: '#ffffff', alpha: 1, effect: 'none' },
                            textDim: { color: '#86efac', alpha: 1, effect: 'none' },
                            border: { color: '#4ade80', alpha: 1, effect: 'none' }
                        }
                    }
                }
            };
            this.data = this.load();
        }

        load() {
            const saved = GM_getValue('lunar_settings', {});
            const merged = { ...this.defaults, ...saved };
            merged.features = { ...this.defaults.features, ...(saved.features || {}) };
            merged.hotkeys = { ...this.defaults.hotkeys, ...(saved.hotkeys || {}) };

            merged.featureSettings = { ...this.defaults.featureSettings };
            if (saved.featureSettings) {
                for (const key in saved.featureSettings) {
                    merged.featureSettings[key] = { ...this.defaults.featureSettings[key], ...saved.featureSettings[key] };
                }
            }

            return merged;
        }

        save() {
            GM_setValue('lunar_settings', this.data);
        }

        get(key) {
            return this.data[key];
        }

        set(key, value) {
            this.data[key] = value;
            this.save();
        }

        getFeatureSetting(feature, setting) {
            return this.data.featureSettings[feature]?.[setting];
        }

        setFeatureSetting(feature, setting, value) {
            if (!this.data.featureSettings[feature]) {
                this.data.featureSettings[feature] = {};
            }
            this.data.featureSettings[feature][setting] = value;
            this.save();
        }
    }

    class UI {
        constructor(app) {
            this.app = app;
            this.menuOpen = false;
            this.locationDisplayWindow = null;
            this.locationDisplayData = null;
            this.locationDisplayPopped = false;
            this.loadIcons();
            this.injectStyles();
            this.createOverlay();
            this.createLocationDisplay();
            this.createHUD();
            this.checkFirstRun();


            setTimeout(() => {
                this.applyTheme(this.app.settings.get('currentTheme'));
            }, 100);
        }

        loadIcons() {
            const link = document.createElement('link');
            link.href = 'https://fonts.googleapis.com/icon?family=Material+Icons';
            link.rel = 'stylesheet';
            document.head.appendChild(link);
        }

        injectStyles() {
            const css = `
                @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap');

                :root {
                    --carbon-black: #1a1a1aff;
                    --carbon-black-2: #1d1d1dff;
                    --carbon-black-3: #242424ff;

                    /* Lighter Amethyst / Violet */
                    --lunar-accent: #8b5cf6;
                    --lunar-accent-hover: #7c3aed;

                    --lunar-bg: var(--carbon-black);
                    --lunar-sidebar: var(--carbon-black-2);
                    --lunar-item-bg: var(--carbon-black-3);
                    --lunar-text: #ffffff;
                    --lunar-text-dim: #a1a1aa;
                    --lunar-border: #333333;
                }

                body {
                    user-select: none;
                }

                #lunar-menu {
                    position: fixed;
                    top: 50%;
                    left: 50%;
                    transform: translate(-50%, -50%) scale(0.9);
                    width: 850px;
                    height: 600px;
                    background: var(--lunar-bg);
                    border-radius: 12px;
                    box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5);
                    display: none;
                    opacity: 0;
                    z-index: 99999;
                    overflow: hidden;
                    font-family: 'Inter', sans-serif;
                    color: var(--lunar-text);
                    border: 1px solid var(--lunar-border);
                    transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1),
                                transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
                    flex-direction: column;
                }

                #lunar-menu.open {
                    display: flex;
                    animation: menuFadeIn 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
                }

                #lunar-menu.closing {
                    animation: menuFadeOut 0.25s cubic-bezier(0.4, 0, 0.2, 1) forwards;
                }

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

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

                /* Header */
                .lunar-header {
                    height: 70px;
                    border-bottom: 1px solid var(--lunar-border);
                    display: flex;
                    align-items: center;
                    justify-content: space-between;
                    padding: 0 24px;
                    background: var(--lunar-bg);
                    flex-shrink: 0;
                }

                .lunar-logo {
                    display: flex;
                    align-items: center;
                    gap: 12px;
                }

                .lunar-logo img {
                    width: 32px;
                    height: 32px;
                    border-radius: 8px; /* Rounded Corners */
                }

                .lunar-logo-text {
                    font-size: 24px;
                    font-weight: 800;
                    color: white;
                    letter-spacing: -0.5px;
                    animation: lunarPulse 3s infinite alternate;
                }

                @keyframes lunarPulse {
                    0% { text-shadow: 0 0 10px rgba(139, 92, 246, 0.2); }
                    100% { text-shadow: 0 0 20px rgba(139, 92, 246, 0.6); }
                }

                .lunar-header-actions {
                    display: flex;
                    gap: 8px;
                }

                .lunar-header-btn {
                    width: 40px;
                    height: 40px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    border-radius: 8px;
                    cursor: pointer;
                    color: var(--lunar-text-dim);
                    transition: all 0.2s ease;
                }

                .lunar-header-btn:hover {
                    background: rgba(255,255,255,0.05);
                    color: white;
                }

                .lunar-header-btn.active {
                    background: rgba(139, 92, 246, 0.1);
                    color: var(--lunar-accent);
                }

                /* Body Layout */
                .lunar-body {
                    display: flex;
                    flex: 1;
                    overflow: hidden;
                }

                .lunar-sidebar {
                    background: var(--lunar-sidebar);
                    padding: 20px 10px;
                    display: flex;
                    flex-direction: column;
                    border-right: 1px solid var(--lunar-border);
                    position: relative;
                    flex-shrink: 0;
                    width: 50px;
                    transition: width 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
                }

                .lunar-sidebar:hover {
                    width: 240px;
                }

                .lunar-sidebar:hover.collapsed {
                    width: 240px;
                }

                .lunar-nav {
                    position: relative;
                    display: flex;
                    flex-direction: column;
                }

                .lunar-nav-highlight {
                    position: absolute;
                    left: 0;
                    width: 100%;
                    background: var(--lunar-item-bg);
                    border-radius: 8px;
                    transition: top 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
                    z-index: 1;
                    border: 1px solid var(--lunar-border);
                }

                .lunar-nav-highlight::before {
                    content: '';
                    position: absolute;
                    left: 0;
                    top: 0;
                    bottom: 0;
                    width: 3px;
                    background: var(--lunar-accent);
                    border-radius: 8px 0 0 8px;
                }

                .lunar-nav-item {
                    display: flex;
                    align-items: center;
                    gap: 12px;
                    padding: 12px 12px 12px 13px;
                    border-radius: 8px;
                    cursor: pointer;
                    transition: color 0.3s ease;
                    color: var(--lunar-text-dim);
                    font-weight: 500;
                    font-size: 14px;
                    margin-bottom: 4px;
                    white-space: nowrap;
                    overflow: hidden;
                    position: relative;
                    z-index: 2;
                }

                .lunar-nav-item:hover {
                    color: var(--lunar-text);
                }

                .lunar-nav-item.active {
                    color: white;
                }

                .lunar-sidebar.collapsed .lunar-nav-text {
                    opacity: 0;
                    width: 0;
                    overflow: hidden;
                    transition: opacity 0.3s ease, width 0.3s ease;
                }

                .lunar-sidebar:hover .lunar-nav-text {
                    opacity: 1;
                    width: auto;
                }

                .lunar-sidebar.collapsed .lunar-nav-item {
                    gap: 0;
                }

                .lunar-sidebar:hover .lunar-nav-item {
                    gap: 12px;
                }

                .lunar-content {
                    flex: 1;
                    padding: 32px;
                    overflow-y: auto;
                    background: var(--lunar-bg);
                }

                /* Feature Box Shadcn Style */
                .lunar-feature {
                    display: flex;
                    align-items: center;
                    justify-content: space-between;
                    padding: 16px;
                    background: transparent;
                    border-radius: 8px;
                    margin-bottom: 12px;
                    transition: all 0.2s ease;
                    cursor: pointer;
                    border: 1px solid var(--lunar-border);
                    position: relative;
                }

                .lunar-feature:hover {
                    background: var(--lunar-item-bg);
                    border-color: rgba(255,255,255,0.1);
                }

                .lunar-feature.active {
                    border-color: var(--lunar-accent);
                    background: rgba(139, 92, 246, 0.05);
                }

                .lunar-feature-info {
                    display: flex;
                    align-items: center;
                    gap: 12px;
                }

                .lunar-feature-dot {
                    width: 8px;
                    height: 8px;
                    border-radius: 50%;
                    background: var(--lunar-accent);
                    opacity: 0;
                    transition: opacity 0.2s;
                    box-shadow: 0 0 8px var(--lunar-accent);
                }

                .lunar-feature.active .lunar-feature-dot {
                    opacity: 1;
                }

                .lunar-feature-name {
                    font-weight: 500;
                    font-size: 14px;
                }

                .lunar-settings-btn {
                    opacity: 0;
                    transition: opacity 0.2s;
                    cursor: pointer;
                    color: var(--lunar-text-dim);
                    font-size: 18px;
                    padding: 6px;
                    border-radius: 4px;
                }

                .lunar-settings-btn:hover {
                    background: rgba(255,255,255,0.1);
                    color: white;
                }

                .lunar-feature:hover .lunar-settings-btn {
                    opacity: 1;
                }

                /* Toast */
                #lunar-toast-container {
                    position: fixed;
                    z-index: 100000;
                    display: flex;
                    flex-direction: column;
                    gap: 10px;
                }

                #lunar-toast-container.toast-pos-bottom-right {
                    bottom: 30px;
                    right: 30px;
                }

                #lunar-toast-container.toast-pos-bottom-left {
                    bottom: 30px;
                    left: 30px;
                }

                #lunar-toast-container.toast-pos-top-right {
                    top: 30px;
                    right: 30px;
                }

                #lunar-toast-container.toast-pos-top-left {
                    top: 30px;
                    left: 30px;
                }

                .lunar-toast {
                    background: var(--carbon-black-2);
                    border: 1px solid var(--lunar-border);
                    padding: 12px 20px;
                    border-radius: 8px;
                    color: white;
                    box-shadow: 0 10px 30px rgba(0,0,0,0.3);
                    animation: slideIn 0.3s ease;
                    display: flex;
                    align-items: center;
                    gap: 12px;
                    min-width: 200px;
                    font-size: 13px;
                    font-weight: 500;
                }

                @keyframes slideIn {
                    from { transform: translateX(100%); opacity: 0; }
                    to { transform: translateX(0); opacity: 1; }
                }

                /* Location Display */
                #lunar-location-display {
                    position: fixed;
                    top: 20px;
                    left: 20px;
                    background: rgba(26, 26, 26, 0.85);
                    backdrop-filter: blur(4px);
                    padding: 12px;
                    border-radius: 6px;
                    color: white;
                    z-index: 9999;
                    border: 1px solid rgba(255, 255, 255, 0.1);
                    border-bottom: 2px solid var(--lunar-accent);
                    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
                    min-width: 260px;
                    cursor: move;
                    display: none;
                    font-family: 'Inter', sans-serif;
                }

                #lunar-location-display:hover {
                    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(139, 92, 246, 0.2);
                }

                .lunar-loc-row {
                    display: flex;
                    align-items: center;
                    gap: 12px;
                    margin-bottom: 10px;
                    font-size: 14px;
                    color: #ffffff;
                    padding: 8px 10px;
                    background: rgba(139, 92, 246, 0.05);
                    border-radius: 6px;
                    border: 1px solid rgba(139, 92, 246, 0.1);
                    transition: all 0.2s ease;
                }

                .lunar-loc-row:last-child {
                    margin-bottom: 0;
                }

                .lunar-loc-row:hover {
                    background: rgba(139, 92, 246, 0.1);
                    border-color: rgba(139, 92, 246, 0.2);
                }

                .lunar-loc-icon {
                    color: var(--lunar-accent);
                    font-size: 18px;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    width: 24px;
                    height: 24px;
                    background: rgba(139, 92, 246, 0.15);
                    border-radius: 6px;
                }

                .lunar-flag {
                    width: 24px;
                    height: 18px;
                    border-radius: 4px;
                    object-fit: cover;
                    border: 1px solid rgba(255, 255, 255, 0.1);
                    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
                }

                #lunar-map-image {
                    width: 100%;
                    height: 140px;
                    background-size: cover;
                    background-position: center;
                    border-radius: 8px;
                    margin-top: 12px;
                    border: 1px solid var(--lunar-border);
                    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
                    opacity: 0.95;
                    transition: all 0.3s ease;
                }

                #lunar-map-image:hover {
                    opacity: 1;
                    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
                }

                /* HUD Elements */
                #lunar-watermark {
                    position: fixed;
                    top: 10px;
                    left: 50%;
                    transform: translateX(-50%);
                    background: rgba(26, 26, 26, 0.6);
                    backdrop-filter: blur(4px);
                    padding: 6px 12px;
                    border-radius: 6px;
                    color: rgba(255, 255, 255, 0.8);
                    font-family: 'Inter', sans-serif;
                    font-size: 12px;
                    font-weight: 600;
                    z-index: 9998;
                    border: 1px solid rgba(255, 255, 255, 0.1);
                    pointer-events: none;
                    display: none;
                    transition: all 0.3s ease;
                    border-bottom: 2px solid var(--lunar-accent);
                }

                #lunar-watermark.top-left { top: 10px; left: 10px; transform: none; }
                #lunar-watermark.top-center { top: 50px; left: 50%; transform: translateX(-50%); }
                #lunar-watermark.top-right { top: 10px; right: 10px; left: auto; transform: none; }
                #lunar-watermark.bottom-left { bottom: 10px; left: 10px; top: auto; transform: none; }
                #lunar-watermark.bottom-center { bottom: 10px; left: 50%; top: auto; transform: translateX(-50%); }
                #lunar-watermark.bottom-right { bottom: 10px; right: 10px; top: auto; left: auto; transform: none; }

                #lunar-map-timer {
                    position: fixed;
                    bottom: 20px;
                    left: 50%;
                    transform: translateX(-50%);
                    background: rgba(26, 26, 26, 0.8);
                    padding: 8px 16px;
                    border-radius: 20px;
                    color: white;
                    font-family: 'Inter', sans-serif;
                    font-size: 16px;
                    font-weight: 700;
                    z-index: 9998;
                    border: 1px solid var(--lunar-accent);
                    display: none;
                    box-shadow: 0 4px 12px rgba(0,0,0,0.3);
                }

                #lunar-hotkey-display {
                    position: fixed;
                    top: 100px;
                    left: 20px;
                    background: rgba(26, 26, 26, 0.85);
                    backdrop-filter: blur(4px);
                    padding: 10px 14px;
                    border-radius: 6px;
                    color: white;
                    z-index: 9998;
                    border: 1px solid rgba(255, 255, 255, 0.1);
                    border-bottom: 2px solid var(--lunar-accent);
                    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
                    min-width: 180px;
                    cursor: move;
                    display: none;
                    font-family: 'Inter', sans-serif;
                }

                .lunar-hk-row {
                    display: flex;
                    align-items: center;
                    justify-content: space-between;
                    margin-bottom: 6px;
                    font-size: 13px;
                    color: var(--lunar-text-dim);
                }

                .lunar-hk-row:last-child { margin-bottom: 0; }
                .lunar-hk-active { color: white; font-weight: 500; }

                .lunar-hk-keys {
                    display: flex;
                    gap: 4px;
                }

                .lunar-hk-key-badge {
                    background: rgba(255,255,255,0.1);
                    padding: 2px 6px;
                    border-radius: 4px;
                    font-size: 11px;
                    font-family: monospace;
                    color: var(--lunar-accent);
                    border: 1px solid rgba(139, 92, 246, 0.2);
                }

                /* Popups */
                .lunar-popup {
                    background: var(--lunar-bg) !important;
                    border: 1px solid var(--lunar-border) !important;
                    box-shadow: 0 10px 40px rgba(0,0,0,0.5) !important;
                    color: white !important;
                    padding: 20px;
                    border-radius: 12px;
                    z-index: 100000;
                    min-width: 260px;
                    position: fixed;
                }

                .lunar-input-wrapper {
                    position: relative;
                    width: 100%;
                }

                .lunar-input {
                    width: 100%;
                    background: var(--carbon-black-2);
                    border: 1px solid var(--lunar-border);
                    padding: 8px 12px;
                    border-radius: 6px;
                    color: white;
                    font-family: 'Inter', sans-serif;
                    font-size: 13px;
                    outline: none;
                    transition: border-color 0.2s;
                }

                .lunar-input:focus {
                    border-color: var(--lunar-accent);
                }

                .lunar-input-clear {
                    position: absolute;
                    right: 8px;
                    top: 50%;
                    transform: translateY(-50%);
                    color: var(--lunar-text-dim);
                    cursor: pointer;
                    font-size: 14px;
                    display: none;
                }

                .lunar-input:not(:placeholder-shown) + .lunar-input-clear {
                    display: block;
                }

                .lunar-btn {
                    background: var(--lunar-accent);
                    color: white;
                    border: none;
                    padding: 6px 12px;
                    border-radius: 6px;
                    cursor: pointer;
                    font-size: 12px;
                    font-weight: 500;
                    transition: background 0.2s;
                }

                .lunar-btn:hover {
                    background: var(--lunar-accent-hover);
                }

                .lunar-btn-secondary {
                    background: transparent;
                    border: 1px solid var(--lunar-border);
                    color: var(--lunar-text-dim);
                }

                .lunar-btn-secondary:hover {
                    background: rgba(255,255,255,0.05);
                    color: white;
                }

                /* Welcome Modal */
                #lunar-welcome {
                    position: fixed;
                    top: 50%;
                    left: 50%;
                    transform: translate(-50%, -50%);
                    background: var(--lunar-bg);
                    border: 1px solid var(--lunar-border);
                    padding: 30px;
                    border-radius: 12px;
                    z-index: 100001;
                    text-align: center;
                    box-shadow: 0 20px 60px rgba(0,0,0,0.8);
                    max-width: 400px;
                }

                .lunar-welcome-title {
                    font-size: 24px;
                    font-weight: 800;
                    margin-bottom: 15px;
                    color: white;
                }

                .lunar-welcome-text {
                    color: var(--lunar-text-dim);
                    font-size: 14px;
                    line-height: 1.6;
                    margin-bottom: 25px;
                }

                .lunar-key {
                    background: var(--carbon-black-3);
                    border: 1px solid var(--lunar-border);
                    padding: 2px 6px;
                    border-radius: 4px;
                    color: white;
                    font-family: monospace;
                    font-size: 12px;
                }

                /* Logs */
                .lunar-log-entry {
                    font-family: monospace;
                    font-size: 12px;
                    padding: 4px 0;
                    border-bottom: 1px solid rgba(255,255,255,0.05);
                    color: var(--lunar-text-dim);
                }
                .lunar-log-entry span { color: var(--lunar-accent); margin-right: 8px; }
                .lunar-log-entry.error { color: #ff5555; }
                .lunar-log-entry.error span { color: #ff5555; }

                /* Checkbox & Slider */
                .lunar-checkbox-wrapper {
                    display: flex;
                    align-items: center;
                    gap: 10px;
                    margin-bottom: 10px;
                    cursor: pointer;
                }

                /* Custom Color Picker */
                .lunar-color-picker-overlay {
                    position: fixed;
                    top: 0;
                    left: 0;
                    width: 100%;
                    height: 100%;
                    background: rgba(0, 0, 0, 0.7);
                    backdrop-filter: blur(4px);
                    z-index: 99999;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                }

                .lunar-color-picker {
                    background: var(--carbon-black);
                    border: 1px solid var(--lunar-border);
                    border-radius: 12px;
                    padding: 20px;
                    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
                    width: 320px;
                }

                .lunar-color-picker-header {
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                    margin-bottom: 16px;
                }

                .lunar-color-picker-title {
                    color: white;
                    font-size: 16px;
                    font-weight: 600;
                }

                .lunar-color-picker-close {
                    background: none;
                    border: none;
                    color: var(--lunar-text-dim);
                    cursor: pointer;
                    padding: 4px;
                    border-radius: 4px;
                    transition: all 0.2s;
                }

                .lunar-color-picker-close:hover {
                    background: var(--carbon-black-3);
                    color: white;
                }

                .lunar-color-canvas {
                    width: 100%;
                    height: 200px;
                    border-radius: 8px;
                    cursor: crosshair;
                    margin-bottom: 12px;
                    border: 1px solid var(--lunar-border);
                }

                .lunar-hue-slider {
                    width: 100%;
                    height: 16px;
                    border-radius: 8px;
                    background: linear-gradient(to right,
                        #ff0000 0%,
                        #ffff00 17%,
                        #00ff00 33%,
                        #00ffff 50%,
                        #0000ff 67%,
                        #ff00ff 83%,
                        #ff0000 100%);
                    margin-bottom: 16px;
                    position: relative;
                    cursor: pointer;
                    border: 1px solid var(--lunar-border);
                }

                .lunar-hue-slider-thumb {
                    position: absolute;
                    top: -2px;
                    width: 20px;
                    height: 20px;
                    background: white;
                    border: 2px solid var(--carbon-black);
                    border-radius: 50%;
                    cursor: pointer;
                    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
                }

                .lunar-color-preview {
                    display: flex;
                    gap: 12px;
                    margin-bottom: 16px;
                }

                .lunar-color-preview-box {
                    flex: 1;
                    height: 50px;
                    border-radius: 8px;
                    border: 1px solid var(--lunar-border);
                }

                .lunar-color-inputs {
                    display: grid;
                    grid-template-columns: 1fr 1fr;
                    gap: 8px;
                }

                .lunar-color-input-group {
                    display: flex;
                    flex-direction: column;
                    gap: 4px;
                }

                .lunar-color-input-label {
                    font-size: 10px;
                    color: var(--lunar-text-dim);
                    text-transform: uppercase;
                    font-weight: 600;
                }

                .lunar-color-input-field {
                    background: var(--carbon-black-3);
                    border: 1px solid var(--lunar-border);
                    border-radius: 6px;
                    padding: 8px;
                    color: white;
                    font-size: 12px;
                    font-family: monospace;
                }

                .lunar-color-input-field:focus {
                    outline: none;
                    border-color: var(--lunar-accent);
                }

                /* Custom Sliders */
                input[type="range"] {
                    -webkit-appearance: none;
                    appearance: none;
                    background: transparent;
                    cursor: pointer;
                    outline: none;
                }

                input[type="range"]::-webkit-slider-track {
                    background: var(--lunar-accent);
                    height: 4px;
                    border-radius: 2px;
                    border: none;
                }

                input[type="range"]::-moz-range-track {
                    background: var(--lunar-accent);
                    height: 4px;
                    border-radius: 2px;
                    border: none;
                }

                input[type="range"]::-webkit-slider-thumb {
                    -webkit-appearance: none;
                    appearance: none;
                    width: 16px;
                    height: 16px;
                    border-radius: 50%;
                    background: var(--carbon-black);
                    border: 2px solid var(--lunar-accent);
                    cursor: pointer;
                    margin-top: -6px;
                    outline: none;
                }

                input[type="range"]::-moz-range-thumb {
                    width: 16px;
                    height: 16px;
                    border-radius: 50%;
                    background: var(--carbon-black);
                    border: 2px solid var(--lunar-accent);
                    cursor: pointer;
                    outline: none;
                }

                .lunar-checkbox {
                    width: 16px;
                    height: 16px;
                    border: 1px solid var(--lunar-border);
                    border-radius: 4px;
                    background: var(--carbon-black-2);
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    transition: all 0.2s;
                }

                .lunar-checkbox.checked {
                    background: var(--lunar-accent);
                    border-color: var(--lunar-accent);
                }

                .lunar-checkbox.checked::after {
                    content: '✓';
                    font-size: 12px;
                    color: white;
                }

                .lunar-slider-wrapper {
                    margin-bottom: 15px;
                }

                .lunar-slider-label {
                    display: flex;
                    justify-content: space-between;
                    font-size: 12px;
                    color: var(--lunar-text-dim);
                    margin-bottom: 5px;
                }

                .lunar-slider {
                    width: 100%;
                    -webkit-appearance: none;
                    height: 4px;
                    background: var(--carbon-black-3);
                    border-radius: 2px;
                    outline: none;
                }

                .lunar-slider::-webkit-slider-thumb {
                    -webkit-appearance: none;
                    width: 14px;
                    height: 14px;
                    border-radius: 50%;
                    background: var(--lunar-accent);
                    cursor: pointer;
                    transition: background .15s ease-in-out;
                }
            `;
            GM_addStyle(css);
        }

        checkFirstRun() {
            if (this.app.settings.get('firstRun')) {
                const modal = document.createElement('div');
                modal.id = 'lunar-welcome';
                modal.innerHTML = `
                    <div class="lunar-welcome-title">Welcome to Lunar V4</div>
                    <div class="lunar-welcome-text">
                        <p>Here's how to use the menu:</p>
                        <ul style="text-align:left; margin: 15px 0; padding-left: 20px;">
                            <li>Press <span class="lunar-key">Insert</span> to toggle the menu.</li>
                            <li><span class="lunar-key">Left Click</span> a feature to toggle it.</li>
                            <li><span class="lunar-key">Right Click</span> a feature to set hotkeys.</li>
                            <li>Click the <span class="material-icons" style="font-size:14px; vertical-align:middle;">settings</span> icon for advanced settings.</li>
                        </ul>
                    </div>
                    <button class="lunar-btn" id="lunar-welcome-close">Get Started</button>
                `;
                document.body.appendChild(modal);

                document.getElementById('lunar-welcome-close').addEventListener('click', () => {
                    modal.remove();
                    this.showLocationApiPopup();
                });
            }
        }

        showLocationApiPopup() {
            const modal = document.createElement('div');
            modal.id = 'lunar-welcome';
            modal.innerHTML = `
                <div class="lunar-welcome-title">Location API Setup</div>
                <div class="lunar-welcome-text">
                    <p>The first API call will trigger a Tampermonkey permission popup if you are not on the latest Tamper Monkey Version.</p>
                    <p style="margin-top:10px;">Click <strong>"Always allow"</strong> to enable location lookups.</p>
                    <img src="https://i.imgur.com/yIVeDlq.png" style="max-width:100%; margin:15px 0; border-radius:8px; border:1px solid var(--lunar-border);" />
                    <div style="margin-top:15px; padding:10px; background:rgba(139, 92, 246, 0.1); border:1px solid rgba(139, 92, 246, 0.2); border-radius:6px;">
                        <div style="display:flex; align-items:start; gap:8px;">
                            <span class="material-icons" style="font-size:16px; color:var(--lunar-accent);">info</span>
                            <div style="font-size:11px; color:var(--lunar-text-dim); line-height:1.5;">
                                This permission allows the script to use the LocationIQ API for reverse geocoding.
                            </div>
                        </div>
                    </div>
                </div>
                <button class="lunar-btn" id="lunar-location-api-okay">Okay</button>
            `;
            document.body.appendChild(modal);

            document.getElementById('lunar-location-api-okay').addEventListener('click', () => {
                modal.remove();
                this.app.settings.set('firstRun', false);
                this.app.network.getLocationDetails(40.7128, -74.0060);
                this.toggleMenu();
            });
        }

        showWebhookOnboarding(callback) {
            const modal = document.createElement('div');
            modal.id = 'lunar-welcome';
            modal.innerHTML = `
                <div class="lunar-welcome-title">Discord Webhook Setup</div>
                <div class="lunar-welcome-text">
                    <p>When you press "Okay", a Tampermonkey permission popup will appear (if you are not on the latest Tampermonkey version).</p>
                    <p style="margin-top:10px;">Click <strong>"Always allow"</strong> to enable Discord webhook functionality.</p>
                    <div style="margin-top:15px; padding:10px; background:rgba(139, 92, 246, 0.1); border:1px solid rgba(139, 92, 246, 0.2); border-radius:6px;">
                        <div style="display:flex; align-items:start; gap:8px;">
                            <span class="material-icons" style="font-size:16px; color:var(--lunar-accent);">info</span>
                            <div style="font-size:11px; color:var(--lunar-text-dim); line-height:1.5;">
                                This permission allows the script to send location data to your Discord webhook URL.
                            </div>
                        </div>
                    </div>
                </div>
                <button class="lunar-btn" id="lunar-webhook-okay">Okay</button>
            `;
            document.body.appendChild(modal);

            document.getElementById('lunar-webhook-okay').addEventListener('click', () => {
                modal.remove();
                callback();
            });
        }

        createOverlay() {
            this.menu = document.createElement('div');
            this.menu.id = 'lunar-menu';
            this.menu.innerHTML = `
                <div class="lunar-header">
                    <div class="lunar-logo">
                        <img src="https://minimalistmoon.com/favlogo.png" alt="Logo">
                        <span class="lunar-logo-text">Lunar</span>
                    </div>
                    <div class="lunar-header-actions">
                        <div class="lunar-header-btn" data-tab="customize" title="Customize">
                            <span class="material-icons">edit</span>
                        </div>
                        <div class="lunar-header-btn" data-tab="logs" title="Logs">
                            <span class="material-icons">list_alt</span>
                        </div>
                        <div class="lunar-header-btn" data-tab="settings" title="Settings">
                            <span class="material-icons">settings</span>
                        </div>
                    </div>
                </div>
                <div class="lunar-body">
                    <div class="lunar-sidebar collapsed">
                        <div class="lunar-nav">
                            <div class="lunar-nav-highlight"></div>
                            <div class="lunar-nav-item active" data-tab="location">
                                <span class="material-icons">place</span> <span class="lunar-nav-text">Location</span>
                            </div>
                            <div class="lunar-nav-item" data-tab="hud">
                                <span class="material-icons">dashboard</span> <span class="lunar-nav-text">HUD</span>
                            </div>
                            <div class="lunar-nav-item" data-tab="autoplay">
                                <span class="material-icons">play_arrow</span> <span class="lunar-nav-text">Autoplay</span>
                            </div>
                        </div>
                    </div>
                    <div class="lunar-content" id="lunar-tab-content"></div>
                </div>
            `;
            document.body.appendChild(this.menu);
            this.setupNavigation();
            this.renderTab('location');
        }

        createLocationDisplay() {
            this.locationDisplay = document.createElement('div');
            this.locationDisplay.id = 'lunar-location-display';
            this.locationDisplay.innerHTML = `
                <div style="display:flex; align-items:center; justify-content:space-between; margin-bottom:6px;">
                    <span style="font-weight:600; color:var(--lunar-text);">Location</span>
                    <button id="lunar-loc-popout" title="Pop out" style="display:inline-flex; align-items:center; gap:4px; background:transparent; border:1px solid var(--lunar-border); color:var(--lunar-text-dim); border-radius:4px; padding:2px 6px; cursor:pointer; font-size:11px;">
                        <span class="material-icons" style="font-size:14px;">open_in_new</span>
                    </button>
                </div>
                <div class="lunar-loc-row" id="lunar-row-country">
                    <span class="material-icons lunar-loc-icon">public</span>
                    <img id="lunar-loc-flag" class="lunar-flag" style="display:none;" />
                    <span id="lunar-loc-country">Country: N/A</span>
                </div>
                <div class="lunar-loc-row" id="lunar-row-state">
                    <span class="material-icons lunar-loc-icon">map</span>
                    <span id="lunar-loc-state">State: N/A</span>
                </div>
                <div class="lunar-loc-row" id="lunar-row-city">
                    <span class="material-icons lunar-loc-icon">location_city</span>
                    <span id="lunar-loc-city">City: N/A</span>
                </div>
                <div id="lunar-map-image"></div>
            `;
            document.body.appendChild(this.locationDisplay);
            this.makeDraggable(this.locationDisplay, 'locationDisplay');

            const popButton = document.getElementById('lunar-loc-popout');
            popButton.addEventListener('click', () => {
                if (!this.locationDisplayPopped) {
                    this.popOutLocationDisplay();
                    popButton.innerHTML = '<span class="material-icons" style="font-size:14px;">call_received</span>';
                    popButton.title = 'Pop back in';
                } else {
                    this.popInLocationDisplay();
                    popButton.innerHTML = '<span class="material-icons" style="font-size:14px;">open_in_new</span>';
                    popButton.title = 'Pop out';
                }
            });

            if (this.app.settings.get('features').locationDisplay) {
                this.locationDisplay.style.display = 'block';
            }
        }

        createHUD() {

            this.watermark = document.createElement('div');
            this.watermark.id = 'lunar-watermark';
            this.watermark.innerHTML = `
                <div style="display:flex; align-items:center; gap:12px;">
                    <div id="lunar-watermark-logo-group" style="display:flex; align-items:center; gap:6px;">
                        <img src="https://minimalistmoon.com/favlogo.png" style="width:16px; height:16px; border-radius:4px;">
                        <span id="lunar-watermark-name">Lunar</span>
                    </div>
                    <div id="lunar-watermark-user-group" style="display:flex; align-items:center; gap:4px; color:var(--lunar-accent);">
                        <span class="material-icons" style="font-size:14px;">person</span>
                        <span id="lunar-watermark-user"></span>
                    </div>
                    <div id="lunar-watermark-clock-group" style="display:flex; align-items:center; gap:4px; opacity:0.8;">
                        <span class="material-icons" style="font-size:14px;">schedule</span>
                        <span id="lunar-clock" style="font-weight:400;"></span>
                    </div>
                </div>
            `;
            document.body.appendChild(this.watermark);

            this.updateWatermarkPosition();
            this.updateWatermarkContent();
            this.startClock();

            if (this.app.settings.get('features').watermark) {
                this.watermark.style.display = 'block';
            }


            this.mapTimer = document.createElement('div');
            this.mapTimer.id = 'lunar-map-timer';
            this.mapTimer.textContent = '00:00';
            document.body.appendChild(this.mapTimer);
            if (this.app.settings.get('features').mapTimer) {
                this.mapTimer.style.display = 'block';
            }


            this.createHotkeyDisplay();
        }

        createHotkeyDisplay() {
            this.hotkeyDisplay = document.createElement('div');
            this.hotkeyDisplay.id = 'lunar-hotkey-display';
            document.body.appendChild(this.hotkeyDisplay);
            this.makeDraggable(this.hotkeyDisplay);
            this.updateHotkeyDisplay();

            if (this.app.settings.get('features').hotkeyDisplay) {
                this.hotkeyDisplay.style.display = 'block';
            }
        }

        updateHotkeyDisplay() {
            const settings = this.app.settings.get('featureSettings').hotkeyDisplay;
            const features = this.app.settings.get('features');
            const hotkeys = this.app.settings.get('hotkeys');

            let html = '';
            let hasContent = false;

            const featureNames = {
                openGM: 'Google Maps',
                openPlonkIT: 'PlonkIT',
                locationDisplay: 'Location Info',
                tts: 'Text to Speech',
                discordWebhook: 'Webhook',
                watermark: 'Watermark',
                mapTimer: 'Map Timer',
                hotkeyDisplay: 'Hotkeys'
            };

            html += `<div style="font-weight:700; margin-bottom:8px; color:white; border-bottom:1px solid rgba(255,255,255,0.1); padding-bottom:6px; font-size:12px; letter-spacing:0.5px; text-transform:uppercase;">Hotkeys</div>`;

            for (const [key, name] of Object.entries(featureNames)) {
                const isActive = features[key];
                const hk = hotkeys[key];
                const hasHotkey = hk && (hk.trigger || hk.toggle);


                if (settings.mode === 'active' && !isActive) continue;
                if (settings.mode === 'bound' && !hasHotkey) continue;

                hasContent = true;
                html += `<div class="lunar-hk-row ${isActive ? 'lunar-hk-active' : ''}">
                    <span>${name}</span>
                    <div class="lunar-hk-keys">`;

                if (hk) {
                    if (settings.showToggle && hk.toggle) {
                        html += `<span class="lunar-hk-key-badge" title="Toggle">${hk.toggle}</span>`;
                    }
                    if (settings.showTrigger && hk.trigger) {
                        html += `<span class="lunar-hk-key-badge" title="Trigger">${hk.trigger}</span>`;
                    }
                }

                html += `</div></div>`;
            }

            if (!hasContent) html = '<div class="lunar-hk-row">No active features</div>';
            this.hotkeyDisplay.innerHTML = html;
        }

        updateLocationDisplay(data) {
            if (!data) return;

            const settings = this.app.settings.get('featureSettings').locationDisplay;

            this.locationDisplayData = data;

            document.getElementById('lunar-loc-country').textContent = data.country || 'N/A';
            document.getElementById('lunar-loc-state').textContent = data.state || 'N/A';
            document.getElementById('lunar-loc-city').textContent = data.city || 'N/A';

            document.getElementById('lunar-row-country').style.display = settings.showCountry ? 'flex' : 'none';
            document.getElementById('lunar-row-state').style.display = settings.showState ? 'flex' : 'none';
            document.getElementById('lunar-row-city').style.display = settings.showCity ? 'flex' : 'none';

            const flagImg = document.getElementById('lunar-loc-flag');
            if (data.countryCode && settings.showCountry) {
                flagImg.src = `https://flagcdn.com/24x18/${data.countryCode}.png`;
                flagImg.style.display = 'block';
            } else {
                flagImg.style.display = 'none';
            }

            let zoom = 5;
            if (settings.showCity && data.city) zoom = settings.cityZoom;
            else if (settings.showState && data.state) zoom = settings.stateZoom;

            const mapUrl = `https://static-maps.yandex.ru/1.x/?ll=${this.app.network.globalCoordinates.lng},${this.app.network.globalCoordinates.lat}&z=${zoom}&size=300,150&l=map&lang=en`;
            document.getElementById('lunar-map-image').style.backgroundImage = `url("${mapUrl}")`;

            this.syncLocationPopout(data, mapUrl, settings);
        }

        syncLocationPopout(data, mapUrl, settings) {
            if (!this.locationDisplayWindow || this.locationDisplayWindow.closed || !this.locationDisplayPopped) return;
            try {
                const doc = this.locationDisplayWindow.document;
                doc.getElementById('pop-country').textContent = data.country || 'N/A';
                doc.getElementById('pop-state').textContent = data.state || 'N/A';
                doc.getElementById('pop-city').textContent = data.city || 'N/A';

                doc.getElementById('pop-country-row').style.display = settings.showCountry ? 'flex' : 'none';
                doc.getElementById('pop-state-row').style.display = settings.showState ? 'flex' : 'none';
                doc.getElementById('pop-city-row').style.display = settings.showCity ? 'flex' : 'none';

                const flagImg = doc.getElementById('pop-flag');
                if (data.countryCode && settings.showCountry) {
                    flagImg.src = `https://flagcdn.com/24x18/${data.countryCode}.png`;
                    flagImg.style.display = 'block';
                } else {
                    flagImg.style.display = 'none';
                }

                doc.getElementById('pop-map').style.backgroundImage = `url("${mapUrl}")`;
            } catch (err) {
                this.locationDisplayWindow = null;
                this.locationDisplayPopped = false;
                const btn = document.getElementById('lunar-loc-popout');
                if (btn) {
                    btn.textContent = '↗';
                    btn.title = 'Pop out';
                }
            }
        }

        popOutLocationDisplay() {
            if (this.locationDisplayPopped) return;

            this.locationDisplayWindow = window.open('', 'lunarLocationPopout', 'width=360,height=260');
            if (!this.locationDisplayWindow) return;

            this.locationDisplayPopped = true;
            this.locationDisplay.style.display = 'none';

            const css = `
                body { margin:0; background:rgba(12,12,18,0.96); color:#fff; font-family: Inter, system-ui, sans-serif; }
                .card { padding:12px; background:rgba(24,24,32,0.85); border:1px solid rgba(255,255,255,0.08); border-radius:12px; box-shadow:0 10px 30px rgba(0,0,0,0.45); }
                .header { display:flex; align-items:center; justify-content:space-between; margin-bottom:8px; font-weight:600; }
                .row { display:flex; align-items:center; gap:8px; margin-bottom:6px; }
                .flag { width:24px; height:18px; border-radius:3px; object-fit:cover; }
                .map { width:300px; height:150px; background-size:cover; background-position:center; border-radius:8px; border:1px solid rgba(255,255,255,0.1); }
                .label { color:#c9c9d1; font-size:12px; }
            `;

            const doc = this.locationDisplayWindow.document;
            doc.open();
            doc.write(`<!DOCTYPE html><html><head><title>Location</title><style>${css}</style><link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"></head><body><div class="card">
                <div class="header">
                    <span>Location</span>
                    <button id="pop-in" style="display:inline-flex; align-items:center; gap:4px; background:transparent; border:1px solid rgba(255,255,255,0.12); color:#fff; border-radius:4px; padding:2px 6px; cursor:pointer; font-size:11px;"><span class="material-icons" style="font-size:14px;">call_received</span></button>
                </div>
                <div class="row" id="pop-country-row"><span class="material-icons" style="font-size:16px;">public</span><img id="pop-flag" class="flag" style="display:none;"><span id="pop-country">Country: N/A</span></div>
                <div class="row" id="pop-state-row"><span class="material-icons" style="font-size:16px;">map</span><span id="pop-state">State: N/A</span></div>
                <div class="row" id="pop-city-row"><span class="material-icons" style="font-size:16px;">location_city</span><span id="pop-city">City: N/A</span></div>
                <div class="map" id="pop-map"></div>
            </div></body></html>`);
            doc.close();

            const popInBtn = doc.getElementById('pop-in');
            popInBtn.addEventListener('click', () => this.popInLocationDisplay());

            this.locationDisplayWindow.addEventListener('beforeunload', () => {
                this.locationDisplayWindow = null;
                if (this.locationDisplayPopped) {
                    this.popInLocationDisplay(true);
                }
            });

            const btn = document.getElementById('lunar-loc-popout');
            if (btn) {
                btn.textContent = '↩';
                btn.title = 'Pop back in';
            }

            if (this.locationDisplayData) {
                const settings = this.app.settings.get('featureSettings').locationDisplay;
                const mapUrl = `https://static-maps.yandex.ru/1.x/?ll=${this.app.network.globalCoordinates.lng},${this.app.network.globalCoordinates.lat}&z=${settings.showCity && this.locationDisplayData.city ? settings.cityZoom : settings.showState && this.locationDisplayData.state ? settings.stateZoom : 5}&size=300,150&l=map&lang=en`;
                this.syncLocationPopout(this.locationDisplayData, mapUrl, settings);
            }
        }

        popInLocationDisplay(fromWindowClose = false) {
            if (!this.locationDisplayPopped) return;

            if (this.locationDisplayWindow && !this.locationDisplayWindow.closed) {
                this.locationDisplayWindow.close();
            }
            this.locationDisplayWindow = null;
            this.locationDisplayPopped = false;

            this.locationDisplay.style.display = this.app.settings.get('features').locationDisplay ? 'block' : 'none';

            if (!fromWindowClose) {
                const btn = document.getElementById('lunar-loc-popout');
                if (btn) {
                    btn.innerHTML = '<span class="material-icons" style="font-size:14px;">open_in_new</span>';
                    btn.title = 'Pop out';
                }
            }
        }

        makeDraggable(element, saveKey = null) {
            let isDragging = false;
            let currentX = 0, currentY = 0, initialX = 0, initialY = 0;
            const app = this.app;


            if (saveKey) {
                const positions = app.settings.get('elementPositions');
                if (positions && positions[saveKey]) {
                    element.style.left = positions[saveKey].left;
                    element.style.top = positions[saveKey].top;
                }
            }

            element.onmousedown = dragMouseDown;

            function dragMouseDown(e) {
                e = e || window.event;
                if (['INPUT', 'TEXTAREA', 'SELECT', 'BUTTON'].includes(e.target.tagName)) return;
                e.preventDefault();

                isDragging = true;
                initialX = e.clientX;
                initialY = e.clientY;

                const rect = element.getBoundingClientRect();
                currentX = rect.left;
                currentY = rect.top;

                document.onmouseup = closeDragElement;
                document.onmousemove = elementDrag;
            }

            function elementDrag(e) {
                if (!isDragging) return;
                e = e || window.event;
                e.preventDefault();

                const deltaX = e.clientX - initialX;
                const deltaY = e.clientY - initialY;

                element.style.left = (currentX + deltaX) + "px";
                element.style.top = (currentY + deltaY) + "px";
            }

            function closeDragElement() {
                isDragging = false;
                document.onmouseup = null;
                document.onmousemove = null;


                if (saveKey) {
                    const positions = app.settings.get('elementPositions') || {};
                    positions[saveKey] = {
                        left: element.style.left,
                        top: element.style.top
                    };
                    app.settings.set('elementPositions', positions);
                }
            }
        }

        setupNavigation() {
            const navItems = this.menu.querySelectorAll('.lunar-nav-item');
            const headerBtns = this.menu.querySelectorAll('.lunar-header-btn');
            const highlight = this.menu.querySelector('.lunar-nav-highlight');

            const updateHighlight = (item) => {
                if (highlight && item.classList.contains('lunar-nav-item')) {
                    highlight.style.top = `${item.offsetTop}px`;
                    highlight.style.height = `${item.offsetHeight}px`;
                    highlight.style.opacity = '1';
                } else if (highlight) {
                    highlight.style.opacity = '0';
                }
            };


            const activeNav = this.menu.querySelector('.lunar-nav-item.active');
            if (activeNav) {

                setTimeout(() => updateHighlight(activeNav), 0);
            }

            const allTabs = [...navItems, ...headerBtns];

            allTabs.forEach(item => {
                item.addEventListener('click', () => {
                    allTabs.forEach(nav => nav.classList.remove('active'));
                    item.classList.add('active');

                    if (item.classList.contains('lunar-nav-item')) {
                        updateHighlight(item);
                    } else {
                        if (highlight) highlight.style.opacity = '0';
                    }

                    this.renderTab(item.dataset.tab);
                });
            });
        }

        renderTab(tabName) {
            const content = this.menu.querySelector('#lunar-tab-content');
            content.innerHTML = '';

            switch (tabName) {
                case 'location':
                    this.renderLocationTab(content);
                    break;
                case 'hud':
                    this.renderHUDTab(content);
                    break;
                case 'autoplay':
                    content.innerHTML = `
                        <div style="display:flex; flex-direction:column; align-items:center; justify-content:center; height:100%; color:var(--lunar-text-dim); gap:15px;">
                            <span class="material-icons" style="font-size:48px; color:#f97316;">warning</span>
                            <div style="text-align:center;">
                                <p style="font-size:16px; font-weight:600; color:white; margin-bottom:4px;">Maintenance Mode</p>
                                <p style="font-size:13px;">This feature is currently being updated.</p>
                            </div>
                        </div>
                    `;
                    break;
                case 'settings':
                    this.renderSettingsTab(content);
                    break;
                case 'logs':
                    this.renderLogsTab(content);
                    break;
                case 'customize':
                    this.renderCustomizeTab(content);
                    break;
            }
        }

        renderLocationTab(container) {
            this.createFeature(container, 'Open Google Maps ⚠️', 'openGM');
            this.createFeature(container, 'Open PlonkIT', 'openPlonkIT');
            this.createFeature(container, 'Location Display', 'locationDisplay', true);
            this.createFeature(container, 'Text to Speech', 'tts', true);
            this.createFeature(container, 'Discord Webhook', 'discordWebhook', true);
        }

        renderHUDTab(container) {
            this.createFeature(container, 'Watermark', 'watermark', true);
            this.createFeature(container, 'Classic Map Timer', 'mapTimer');
            this.createFeature(container, 'Hotkey Display', 'hotkeyDisplay', true);
            this.createFeature(container, 'Toast Notifications', 'toastNotifications', true);
        }

        renderCustomizeTab(container) {

            const defaultSection = document.createElement('div');
            defaultSection.style.marginBottom = '24px';
            defaultSection.innerHTML = '<h3 style="color:white; font-size:16px; font-weight:600; margin-bottom:12px;">Default Themes</h3>';
            container.appendChild(defaultSection);

            const defaultThemes = this.app.settings.get('defaultThemes');
            for (const [key, theme] of Object.entries(defaultThemes)) {
                this.createThemeItem(defaultSection, theme.name, key, false);
            }


            const customSection = document.createElement('div');
            customSection.style.marginBottom = '24px';
            customSection.innerHTML = `
                <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:12px;">
                    <h3 style="color:white; font-size:16px; font-weight:600;">Custom Themes</h3>
                    <button class="lunar-btn" id="create-theme-btn" style="padding:8px 16px;">
                        <span class="material-icons" style="font-size:16px; vertical-align:middle;">add</span>
                        Create Theme
                    </button>
                </div>
            `;
            container.appendChild(customSection);

            const customThemes = this.app.settings.get('customThemes');
            const hasCustomThemes = Object.keys(customThemes).length > 0;

            if (!hasCustomThemes) {
                const emptyState = document.createElement('div');
                emptyState.style.cssText = 'padding:20px; text-align:center; color:var(--lunar-text-dim); font-size:13px; border:1px dashed var(--lunar-border); border-radius:8px;';
                emptyState.textContent = 'No custom themes yet. Create one to get started!';
                customSection.appendChild(emptyState);
            } else {
                for (const [key, theme] of Object.entries(customThemes)) {
                    this.createThemeItem(customSection, theme.name, key, true);
                }
            }


            document.getElementById('create-theme-btn').addEventListener('click', () => {
                this.createNewTheme();
            });
        }

        createThemeItem(container, name, key, isCustom) {
            const el = document.createElement('div');
            const isActive = this.app.settings.get('currentTheme') === key;
            el.className = `lunar-feature ${isActive ? 'active' : ''}`;
            el.innerHTML = `
                <div class="lunar-feature-info">
                    <div class="lunar-feature-dot"></div>
                    <div class="lunar-feature-name">${name}</div>
                </div>
                <div class="lunar-feature-actions">
                    ${isCustom ? '<span class="material-icons lunar-settings-btn" style="opacity:1; color:#ef4444;" data-action="delete">delete</span>' : ''}
                </div>
            `;

            el.addEventListener('click', (e) => {
                if (e.target.dataset.action === 'delete') {
                    this.deleteTheme(key);
                    return;
                }
                this.loadTheme(key);
            });

            el.addEventListener('contextmenu', (e) => {
                e.preventDefault();
                this.openThemeCustomization(key, isCustom);
            });

            container.appendChild(el);
        }

        createNewTheme() {
            const themeName = prompt('Enter theme name:');
            if (!themeName) return;

            const themeKey = 'custom_' + Date.now();
            const customThemes = this.app.settings.get('customThemes');


            const currentThemeKey = this.app.settings.get('currentTheme');
            const currentTheme = this.app.settings.get('defaultThemes')[currentThemeKey] ||
                this.app.settings.get('customThemes')[currentThemeKey];

            customThemes[themeKey] = {
                name: themeName,
                colors: { ...currentTheme.colors }
            };

            this.app.settings.set('customThemes', customThemes);
            this.showToast(`Theme "${themeName}" created`);
            this.renderTab('customize');
        }

        deleteTheme(key) {
            const customThemes = this.app.settings.get('customThemes');
            const themeName = customThemes[key].name;

            if (!confirm(`Delete theme "${themeName}"?`)) return;

            delete customThemes[key];
            this.app.settings.set('customThemes', customThemes);


            if (this.app.settings.get('currentTheme') === key) {
                this.loadTheme('default');
            }

            this.showToast(`Theme "${themeName}" deleted`);
            this.renderTab('customize');
        }

        loadTheme(key) {
            this.app.settings.set('currentTheme', key);
            this.applyTheme(key);
            this.showToast('Theme loaded');
            this.renderTab('customize');
        }

        applyTheme(key) {
            const theme = this.app.settings.get('defaultThemes')[key] ||
                this.app.settings.get('customThemes')[key];

            if (!theme) return;

            const root = document.documentElement;


            for (const [colorKey, colorData] of Object.entries(theme.colors)) {
                const cssVar = this.colorKeyToCssVar(colorKey);


                if (typeof colorData === 'string') {
                    root.style.setProperty(cssVar, colorData);
                } else {
                    const rgba = this.hexToRgba(colorData.color, colorData.alpha);
                    root.style.setProperty(cssVar, rgba);


                    this.applyColorEffect(cssVar, colorData);
                }
            }
        }

        colorKeyToCssVar(key) {
            const map = {
                carbonBlack: '--carbon-black',
                carbonBlack2: '--carbon-black-2',
                carbonBlack3: '--carbon-black-3',
                accent: '--lunar-accent',
                accentHover: '--lunar-accent-hover',
                text: '--lunar-text',
                textDim: '--lunar-text-dim',
                border: '--lunar-border'
            };
            return map[key] || `--${key}`;
        }

        hexToRgba(hex, alpha = 1) {
            const r = parseInt(hex.slice(1, 3), 16);
            const g = parseInt(hex.slice(3, 5), 16);
            const b = parseInt(hex.slice(5, 7), 16);
            return `rgba(${r}, ${g}, ${b}, ${alpha})`;
        }

        applyColorEffect(cssVar, colorData) {

        }

        openThemeCustomization(key, isCustom) {
            if (!isCustom) {
                this.showToast('Cannot edit default themes', 'error');
                return;
            }

            const theme = this.app.settings.get('customThemes')[key];
            const content = this.menu.querySelector('#lunar-tab-content');
            const sidebar = this.menu.querySelector('.lunar-sidebar');


            sidebar.style.display = 'none';

            content.innerHTML = `
                <div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:24px;">
                    <button class="lunar-btn lunar-btn-secondary" id="theme-back-btn" style="padding:8px 16px;">
                        <span class="material-icons" style="font-size:16px; vertical-align:middle;">arrow_back</span>
                        Back
                    </button>
                    <h2 style="color:white; font-size:18px; font-weight:700; margin:0;">Customize: ${theme.name}</h2>
                    <button class="lunar-btn" id="theme-save-btn" style="padding:8px 16px;">
                        <span class="material-icons" style="font-size:16px; vertical-align:middle;">save</span>
                        Save
                    </button>
                </div>

                <div style="display:grid; grid-template-columns:1fr 1fr; gap:16px; max-height:450px; overflow-y:auto; padding-right:8px;">
                    ${this.createAdvancedColorInput('Background', 'carbonBlack', theme.colors.carbonBlack)}
                    ${this.createAdvancedColorInput('Background 2', 'carbonBlack2', theme.colors.carbonBlack2)}
                    ${this.createAdvancedColorInput('Background 3', 'carbonBlack3', theme.colors.carbonBlack3)}
                    ${this.createAdvancedColorInput('Accent', 'accent', theme.colors.accent)}
                    ${this.createAdvancedColorInput('Accent Hover', 'accentHover', theme.colors.accentHover)}
                    ${this.createAdvancedColorInput('Text', 'text', theme.colors.text)}
                    ${this.createAdvancedColorInput('Text Dim', 'textDim', theme.colors.textDim)}
                    ${this.createAdvancedColorInput('Border', 'border', theme.colors.border)}
                </div>
            `;


            document.getElementById('theme-back-btn').addEventListener('click', () => {
                this.saveThemeColors(key);
                sidebar.style.display = '';
                this.renderTab('customize');
            });


            document.getElementById('theme-save-btn').addEventListener('click', () => {
                this.saveThemeColors(key);
                sidebar.style.display = '';
                this.renderTab('customize');
            });


            content.querySelectorAll('input[type="color"], input[type="range"]').forEach(input => {
                input.addEventListener('input', () => {
                    this.updateLivePreview(content);
                });
            });


            content.querySelectorAll('.lunar-custom-color-btn').forEach(btn => {
                btn.addEventListener('click', () => {
                    const colorKey = btn.dataset.colorKey;
                    const currentColor = btn.style.background;

                    this.openCustomColorPicker(btn, currentColor, (newColor) => {
                        btn.style.background = newColor;

                        if (colorKey) {
                            const textInput = content.querySelector(`input[data-text-key="${colorKey}"]`);
                            if (textInput) textInput.value = newColor;
                        }

                        this.updateLivePreview(content);
                    });
                });
            });


            content.querySelectorAll('.lunar-color-hex-input').forEach(input => {
                input.addEventListener('input', (e) => {
                    let value = e.target.value.trim();
                    if (!value.startsWith('#')) value = '#' + value;

                    if (/^#[0-9A-Fa-f]{6}$/.test(value)) {
                        const colorKey = input.dataset.colorKey;

                        if (colorKey) {
                            const btn = content.querySelector(`.lunar-custom-color-btn[data-color-key="${colorKey}"]`);
                            if (btn) btn.style.background = value;
                        }

                        this.updateLivePreview(content);
                    }
                });
            });
        }

        createAdvancedColorInput(label, key, colorData) {

            const color = typeof colorData === 'string' ? colorData : colorData.color;
            const alpha = typeof colorData === 'string' ? 1 : (colorData.alpha || 1);

            return `
                <div style="margin-bottom:16px; padding:12px; background:var(--carbon-black-2); border-radius:8px; border:1px solid var(--lunar-border);">
                    <label style="display:block; margin-bottom:8px; color:white; font-size:13px; font-weight:600;">${label}</label>

                    <!-- Color Picker Button -->
                    <div style="display:flex; gap:8px; align-items:center; margin-bottom:8px;">
                        <div class="lunar-custom-color-btn" data-color-key="${key}"
                            style="width:50px; height:40px; border:1px solid var(--lunar-border); border-radius:6px; background:${color}; cursor:pointer; position:relative; overflow:hidden;">
                            <div style="position:absolute; inset:0; background:linear-gradient(45deg, #808080 25%, transparent 25%, transparent 75%, #808080 75%, #808080); background-size:10px 10px; background-position:0 0, 5px 5px; opacity:0.1;"></div>
                        </div>
                        <input type="text" value="${color}" class="lunar-input lunar-color-hex-input" data-text-key="${key}" data-color-key="${key}"
                            style="flex:1; font-family:monospace; text-transform:uppercase; font-size:11px;">
                    </div>

                    <!-- Alpha Slider -->
                    <div style="margin-bottom:8px;">
                        <div style="display:flex; justify-content:space-between; margin-bottom:4px;">
                            <span style="font-size:11px; color:var(--lunar-text-dim);">Opacity</span>
                            <span style="font-size:11px; color:var(--lunar-accent);" data-alpha-display="${key}">${Math.round(alpha * 100)}%</span>
                        </div>
                        <input type="range" min="0" max="100" value="${alpha * 100}" data-alpha-key="${key}"
                            style="width:100%; height:4px; background:var(--carbon-black-3); border-radius:2px; cursor:pointer;">
                    </div>
                </div>
            `;
        }

        updateLivePreview(content) {
            const tempTheme = { colors: {} };

            content.querySelectorAll('input[data-color-key]').forEach(input => {
                const key = input.dataset.colorKey;
                const color = input.value;
                const alphaSlider = content.querySelector(`input[data-alpha-key="${key}"]`);
                const alpha = alphaSlider ? parseFloat(alphaSlider.value) / 100 : 1;

                tempTheme.colors[key] = { color, alpha };


                const alphaDisplay = content.querySelector(`span[data-alpha-display="${key}"]`);
                if (alphaDisplay) alphaDisplay.textContent = `${Math.round(alpha * 100)}%`;


                const textInput = content.querySelector(`input[data-text-key="${key}"]`);
                if (textInput) textInput.value = color;
            });

            this.applyThemeColorsAdvanced(tempTheme.colors);
        }

        applyThemeColorsAdvanced(colors) {
            const root = document.documentElement;

            for (const [key, colorData] of Object.entries(colors)) {
                const cssVar = this.colorKeyToCssVar(key);
                const rgba = this.hexToRgba(colorData.color, colorData.alpha);
                root.style.setProperty(cssVar, rgba);
            }
        }

        saveThemeColors(key) {
            const content = this.menu.querySelector('#lunar-tab-content');
            const customThemes = this.app.settings.get('customThemes');

            content.querySelectorAll('input[data-color-key]').forEach(input => {
                const colorKey = input.dataset.colorKey;
                const color = input.value;
                const alphaSlider = content.querySelector(`input[data-alpha-key="${colorKey}"]`);
                const alpha = alphaSlider ? parseFloat(alphaSlider.value) / 100 : 1;

                customThemes[key].colors[colorKey] = { color, alpha };
            });

            this.app.settings.set('customThemes', customThemes);


            if (this.app.settings.get('currentTheme') === key) {
                this.applyTheme(key);
            }

            this.showToast('Theme saved');
        }

        openCustomColorPicker(targetElement, currentColor, callback) {
            const overlay = document.createElement('div');
            overlay.className = 'lunar-color-picker-overlay';

            const picker = document.createElement('div');
            picker.className = 'lunar-color-picker';


            let h = 0, s = 100, v = 100;
            if (currentColor && currentColor.startsWith('#')) {
                const rgb = this.hexToRgb(currentColor);
                const hsv = this.rgbToHsv(rgb.r, rgb.g, rgb.b);
                h = hsv.h;
                s = hsv.s;
                v = hsv.v;
            }

            picker.innerHTML = `
                <div class="lunar-color-picker-header">
                    <div class="lunar-color-picker-title">Choose Color</div>
                    <button class="lunar-color-picker-close">
                        <span class="material-icons" style="font-size:20px;">close</span>
                    </button>
                </div>

                <canvas class="lunar-color-canvas" width="280" height="200"></canvas>

                <div class="lunar-hue-slider">
                    <div class="lunar-hue-slider-thumb" style="left:${(h / 360) * 100}%;"></div>
                </div>

                <div class="lunar-color-preview">
                    <div class="lunar-color-preview-box" id="color-preview"></div>
                </div>

                <div class="lunar-color-inputs">
                    <div class="lunar-color-input-group">
                        <label class="lunar-color-input-label">Hex</label>
                        <input type="text" class="lunar-color-input-field" id="hex-input" maxlength="7" value="${currentColor || '#ffffff'}">
                    </div>
                    <div class="lunar-color-input-group">
                        <label class="lunar-color-input-label">RGB</label>
                        <input type="text" class="lunar-color-input-field" id="rgb-input" readonly>
                    </div>
                </div>
            `;

            overlay.appendChild(picker);
            document.body.appendChild(overlay);

            const canvas = picker.querySelector('.lunar-color-canvas');
            const ctx = canvas.getContext('2d');
            const hueSlider = picker.querySelector('.lunar-hue-slider');
            const hueThumb = picker.querySelector('.lunar-hue-slider-thumb');
            const preview = picker.querySelector('#color-preview');
            const hexInput = picker.querySelector('#hex-input');
            const rgbInput = picker.querySelector('#rgb-input');

            let currentHue = h;
            let currentSat = s;
            let currentVal = v;


            const drawCanvas = () => {
                const gradient1 = ctx.createLinearGradient(0, 0, canvas.width, 0);
                gradient1.addColorStop(0, '#ffffff');
                gradient1.addColorStop(1, `hsl(${currentHue}, 100%, 50%)`);
                ctx.fillStyle = gradient1;
                ctx.fillRect(0, 0, canvas.width, canvas.height);

                const gradient2 = ctx.createLinearGradient(0, 0, 0, canvas.height);
                gradient2.addColorStop(0, 'rgba(0, 0, 0, 0)');
                gradient2.addColorStop(1, 'rgba(0, 0, 0, 1)');
                ctx.fillStyle = gradient2;
                ctx.fillRect(0, 0, canvas.width, canvas.height);
            };

            const updateColor = () => {
                const rgb = this.hsvToRgb(currentHue, currentSat, currentVal);
                const hex = this.rgbToHex(rgb.r, rgb.g, rgb.b);

                preview.style.background = hex;
                hexInput.value = hex;
                rgbInput.value = `${Math.round(rgb.r)}, ${Math.round(rgb.g)}, ${Math.round(rgb.b)}`;

                callback(hex);
            };

            drawCanvas();
            updateColor();


            let isCanvasDragging = false;
            canvas.addEventListener('mousedown', (e) => {
                isCanvasDragging = true;
                const rect = canvas.getBoundingClientRect();
                currentSat = ((e.clientX - rect.left) / rect.width) * 100;
                currentVal = 100 - ((e.clientY - rect.top) / rect.height) * 100;
                updateColor();
            });

            document.addEventListener('mousemove', (e) => {
                if (isCanvasDragging) {
                    const rect = canvas.getBoundingClientRect();
                    currentSat = Math.max(0, Math.min(100, ((e.clientX - rect.left) / rect.width) * 100));
                    currentVal = Math.max(0, Math.min(100, 100 - ((e.clientY - rect.top) / rect.height) * 100));
                    updateColor();
                }
            });

            document.addEventListener('mouseup', () => {
                isCanvasDragging = false;
            });


            let isHueDragging = false;
            const updateHue = (e) => {
                const rect = hueSlider.getBoundingClientRect();
                const x = Math.max(0, Math.min(rect.width, e.clientX - rect.left));
                currentHue = (x / rect.width) * 360;
                hueThumb.style.left = `${(currentHue / 360) * 100}%`;
                drawCanvas();
                updateColor();
            };

            hueSlider.addEventListener('mousedown', (e) => {
                isHueDragging = true;
                updateHue(e);
            });

            document.addEventListener('mousemove', (e) => {
                if (isHueDragging) updateHue(e);
            });

            document.addEventListener('mouseup', () => {
                isHueDragging = false;
            });


            hexInput.addEventListener('input', (e) => {
                let value = e.target.value;
                if (!value.startsWith('#')) value = '#' + value;
                if (/^#[0-9A-Fa-f]{6}$/.test(value)) {
                    const rgb = this.hexToRgb(value);
                    const hsv = this.rgbToHsv(rgb.r, rgb.g, rgb.b);
                    currentHue = hsv.h;
                    currentSat = hsv.s;
                    currentVal = hsv.v;
                    hueThumb.style.left = `${(currentHue / 360) * 100}%`;
                    drawCanvas();
                    updateColor();
                }
            });


            const close = () => overlay.remove();
            picker.querySelector('.lunar-color-picker-close').addEventListener('click', close);
            overlay.addEventListener('click', (e) => {
                if (e.target === overlay) close();
            });
        }

        hexToRgb(hex) {
            const r = parseInt(hex.slice(1, 3), 16);
            const g = parseInt(hex.slice(3, 5), 16);
            const b = parseInt(hex.slice(5, 7), 16);
            return { r, g, b };
        }

        rgbToHex(r, g, b) {
            return '#' + [r, g, b].map(x => {
                const hex = Math.round(x).toString(16);
                return hex.length === 1 ? '0' + hex : hex;
            }).join('');
        }

        rgbToHsv(r, g, b) {
            r /= 255;
            g /= 255;
            b /= 255;

            const max = Math.max(r, g, b);
            const min = Math.min(r, g, b);
            const delta = max - min;

            let h = 0;
            if (delta !== 0) {
                if (max === r) h = ((g - b) / delta) % 6;
                else if (max === g) h = (b - r) / delta + 2;
                else h = (r - g) / delta + 4;
                h *= 60;
                if (h < 0) h += 360;
            }

            const s = max === 0 ? 0 : (delta / max) * 100;
            const v = max * 100;

            return { h, s, v };
        }

        hsvToRgb(h, s, v) {
            s /= 100;
            v /= 100;

            const c = v * s;
            const x = c * (1 - Math.abs(((h / 60) % 2) - 1));
            const m = v - c;

            let r = 0, g = 0, b = 0;
            if (h >= 0 && h < 60) { r = c; g = x; b = 0; }
            else if (h >= 60 && h < 120) { r = x; g = c; b = 0; }
            else if (h >= 120 && h < 180) { r = 0; g = c; b = x; }
            else if (h >= 180 && h < 240) { r = 0; g = x; b = c; }
            else if (h >= 240 && h < 300) { r = x; g = 0; b = c; }
            else if (h >= 300 && h < 360) { r = c; g = 0; b = x; }

            return {
                r: (r + m) * 255,
                g: (g + m) * 255,
                b: (b + m) * 255
            };
        }

        applyThemeColors(colors) {
            const root = document.documentElement;
            root.style.setProperty('--carbon-black', colors.carbonBlack);
            root.style.setProperty('--carbon-black-2', colors.carbonBlack2);
            root.style.setProperty('--carbon-black-3', colors.carbonBlack3);
            root.style.setProperty('--lunar-accent', colors.accent);
            root.style.setProperty('--lunar-accent-hover', colors.accentHover);
            root.style.setProperty('--lunar-text', colors.text);
            root.style.setProperty('--lunar-text-dim', colors.textDim);
            root.style.setProperty('--lunar-border', colors.border);
        }

        renderLogsTab(container) {
            const controls = document.createElement('div');
            controls.style.marginBottom = '15px';
            controls.innerHTML = `<button class="lunar-btn lunar-btn-secondary" id="clear-logs">Clear Logs</button>`;
            container.appendChild(controls);

            const logContainer = document.createElement('div');
            logContainer.style.height = '400px';
            logContainer.style.overflowY = 'auto';
            logContainer.style.background = 'var(--carbon-black-2)';
            logContainer.style.padding = '10px';
            logContainer.style.borderRadius = '6px';
            logContainer.style.border = '1px solid var(--lunar-border)';
            container.appendChild(logContainer);

            const renderLogs = () => {
                logContainer.innerHTML = Utils.logs.map(log => `
                    <div class="lunar-log-entry ${log.type}">
                        <span>[${log.timestamp}]</span> ${log.message}
                    </div>
                `).join('');
            };

            renderLogs();


            Utils.addLogListener(() => renderLogs());

            controls.querySelector('#clear-logs').addEventListener('click', () => {
                Utils.logs = [];
                renderLogs();
            });
        }

        renderSettingsTab(container) {
            const createInput = (label, value, onChange, isHotkey = false) => {
                const wrapper = document.createElement('div');
                wrapper.style.marginBottom = '15px';
                wrapper.innerHTML = `<label style="display:block; margin-bottom:8px; color:var(--lunar-text-dim); font-size:12px; font-weight:500;">${label}</label>`;

                const inputWrapper = document.createElement('div');
                inputWrapper.className = 'lunar-input-wrapper';

                const input = document.createElement('input');
                input.type = 'text';
                input.value = value;
                input.className = 'lunar-input';

                if (isHotkey) {
                    input.addEventListener('keydown', (e) => {
                        e.preventDefault();
                        const key = e.key === ' ' ? 'Space' : e.key;
                        input.value = key;
                        onChange(key);
                    });
                } else {
                    input.addEventListener('change', (e) => onChange(e.target.value));
                }

                inputWrapper.appendChild(input);
                wrapper.appendChild(inputWrapper);
                return wrapper;
            };


            const idWrapper = createInput('Leaderboard ID', this.app.settings.get('leaderboardId'), () => { });
            idWrapper.querySelector('input').disabled = true;
            idWrapper.querySelector('input').style.opacity = '0.5';
            container.appendChild(idWrapper);


            container.appendChild(createInput('Username', this.app.settings.get('leaderboardName'), (val) => {
                this.app.settings.set('leaderboardName', val);
                this.showToast('Username saved');
                this.updateWatermarkContent();
            }));


            container.appendChild(createInput('Menu Hotkey', this.app.settings.get('menuHotkey'), (val) => {
                this.app.settings.set('menuHotkey', val);
                this.showToast('Menu Hotkey saved');
            }, true));


            const apiWrapper = document.createElement('div');
            apiWrapper.style.marginBottom = '15px';
            apiWrapper.innerHTML = `<label style="display:block; margin-bottom:8px; color:var(--lunar-text-dim); font-size:12px; font-weight:500;">LocationIQ API Key</label>`;
            const select = document.createElement('select');
            select.className = 'lunar-input';

            CONFIG.API_KEYS.forEach((key, index) => {
                const option = document.createElement('option');
                option.value = index;
                option.text = `Key ${index + 1}`;
                option.selected = index === this.app.settings.get('apiKeyIndex');
                select.appendChild(option);
            });

            select.addEventListener('change', (e) => {
                this.app.settings.set('apiKeyIndex', parseInt(e.target.value));
                this.showToast('API Key updated');
            });
            apiWrapper.appendChild(select);
            container.appendChild(apiWrapper);


            const statusWrapper = document.createElement('div');
            statusWrapper.style.marginBottom = '15px';
            statusWrapper.innerHTML = `
                <label style="display:block; margin-bottom:8px; color:var(--lunar-text-dim); font-size:12px; font-weight:500;">API Key Status</label>
                <div id="api-status-container" style="display:flex; flex-direction:column; gap:6px;">
                    ${CONFIG.API_KEYS.map((key, index) => {
                const status = this.app.settings.get('apiKeyStatus')[index];
                let dotColor = '#71717a';
                if (status === 'success') dotColor = '#22c55e';
                if (status === 'error') dotColor = '#ef4444';

                return `
                            <div style="display:flex; align-items:center; gap:8px; padding:6px 10px; background:var(--carbon-black-3); border-radius:4px; border:1px solid var(--lunar-border);">
                                <div style="width:8px; height:8px; border-radius:50%; background:${dotColor}; box-shadow:0 0 8px ${dotColor};"></div>
                                <span style="font-size:12px; color:var(--lunar-text-dim);">Key ${index + 1}</span>
                            </div>
                        `;
            }).join('')}
                </div>
            `;
            container.appendChild(statusWrapper);


            const noteWrapper = document.createElement('div');
            noteWrapper.style.marginBottom = '15px';
            noteWrapper.innerHTML = `
                <div style="padding:10px; background:rgba(139, 92, 246, 0.1); border:1px solid rgba(139, 92, 246, 0.2); border-radius:6px;">
                    <div style="display:flex; align-items:start; gap:8px;">
                        <span class="material-icons" style="font-size:16px; color:var(--lunar-accent);">info</span>
                        <div style="font-size:11px; color:var(--lunar-text-dim); line-height:1.5;">
                            The first API call will trigger a Tampermonkey permission popup. Click "Always allow" to enable location lookups.
                        </div>
                    </div>
                </div>
            `;
            container.appendChild(noteWrapper);


            const resetSection = document.createElement('div');
            resetSection.style.cssText = 'margin-top:30px; padding-top:20px; border-top:1px solid var(--lunar-border);';
            const participateState = this.app.settings.get('participateInLeaderboard');
            resetSection.innerHTML = `
                <div style="display:flex; gap:12px; margin-bottom:12px;">
                    <div style="flex:1;">
                        <label style="display:block; margin-bottom:6px; color:var(--lunar-text-dim); font-size:12px; font-weight:500;">Onboarding</label>
                        <button class="lunar-btn lunar-btn-secondary" id="reset-onboarding-btn" style="width:100%;">
                            <span class="material-icons" style="font-size:16px; vertical-align:middle; margin-right:8px;">refresh</span>
                            Reset Onboarding
                        </button>
                    </div>
                    <div style="flex:1;">
                        <label style="display:block; margin-bottom:6px; color:var(--lunar-text-dim); font-size:12px; font-weight:500;">Leaderboard</label>
                        <button class="lunar-btn lunar-btn-secondary" id="leaderboard-toggle-btn" style="width:100%; background:${participateState ? 'var(--lunar-accent)' : 'transparent'}; color:${participateState ? 'white' : 'var(--lunar-text-dim)'}; border:1px solid var(--lunar-border);">
                            ${participateState ? 'Enabled' : 'Disabled'}
                        </button>
                    </div>
                </div>
            `;
            container.appendChild(resetSection);


            document.getElementById('reset-onboarding-btn').addEventListener('click', () => {
                if (confirm('This will reset all onboarding popups and reload the page. Continue?')) {
                    this.app.settings.set('firstRun', true);
                    this.app.settings.set('firstWebhookRun', true);
                    location.reload();
                }
            });

            document.getElementById('leaderboard-toggle-btn').addEventListener('click', () => {
                const currentState = this.app.settings.get('participateInLeaderboard');
                const newState = !currentState;
                this.app.settings.set('participateInLeaderboard', newState);
                const btn = document.getElementById('leaderboard-toggle-btn');
                btn.textContent = newState ? 'Enabled' : 'Disabled';
                btn.style.background = newState ? 'var(--lunar-accent)' : 'transparent';
                btn.style.color = newState ? 'white' : 'var(--lunar-text-dim)';
            });
        }

        createFeature(container, name, key, hasSubSettings = false) {
            const el = document.createElement('div');
            el.className = `lunar-feature ${this.app.settings.get('features')[key] ? 'active' : ''}`;
            el.innerHTML = `
                <div class="lunar-feature-info">
                    <div class="lunar-feature-dot"></div>
                    <div class="lunar-feature-name">${name}</div>
                </div>
                <div class="lunar-feature-actions">
                    ${hasSubSettings ? '<span class="material-icons lunar-settings-btn">settings</span>' : ''}
                </div>
            `;

            el.addEventListener('click', (e) => {
                if (e.target.classList.contains('lunar-settings-btn')) return;

                const newState = !this.app.settings.get('features')[key];
                this.app.settings.data.features[key] = newState;
                this.app.settings.save();

                el.classList.toggle('active', newState);
                this.showToast(`${name} ${newState ? 'Enabled' : 'Disabled'}`);


                if (this.menuOpen) {
                    const activeTab = this.menu.querySelector('.lunar-nav-item.active');
                    if (activeTab) this.renderTab(activeTab.dataset.tab);
                }


                if (key === 'locationDisplay') {
                    this.locationDisplay.style.display = newState ? 'block' : 'none';
                    if (!newState && this.locationDisplayWindow && !this.locationDisplayWindow.closed) {
                        this.locationDisplayWindow.close();
                        this.locationDisplayWindow = null;
                        this.locationDisplayPopped = false;
                        const btn = document.getElementById('lunar-loc-popout');
                        if (btn) {
                            btn.innerHTML = '<span class="material-icons" style="font-size:14px;">open_in_new</span>';
                            btn.title = 'Pop out';
                        }
                    }
                } else if (key === 'watermark') {
                    this.watermark.style.display = newState ? 'block' : 'none';
                } else if (key === 'mapTimer') {
                    this.mapTimer.style.display = newState ? 'block' : 'none';
                } else if (key === 'hotkeyDisplay') {
                    this.hotkeyDisplay.style.display = newState ? 'block' : 'none';
                }


                this.updateHotkeyDisplay();
            });

            if (hasSubSettings) {
                el.querySelector('.lunar-settings-btn').addEventListener('click', (e) => {
                    e.stopPropagation();
                    this.openSettingsPopup(e.clientX, e.clientY, name, key);
                });
            }

            el.addEventListener('contextmenu', (e) => {
                e.preventDefault();
                this.openHotkeyPopup(e.clientX, e.clientY, name, key);
            });

            container.appendChild(el);
        }

        openSettingsPopup(x, y, name, key) {
            const existing = document.getElementById('lunar-popup');
            if (existing) existing.remove();

            const popup = document.createElement('div');
            popup.id = 'lunar-popup';
            popup.className = 'lunar-popup';
            popup.style.left = `${x}px`;
            popup.style.top = `${y}px`;

            let content = `<div style="font-weight:600; margin-bottom:15px; border-bottom:1px solid var(--lunar-border); padding-bottom:10px; font-size:14px;">${name} Settings</div>`;

            const settings = this.app.settings.get('featureSettings')[key];

            if (key === 'locationDisplay') {
                const createCheckbox = (label, prop) => `
                    <div class="lunar-checkbox-wrapper" data-prop="${prop}">
                        <div class="lunar-checkbox ${settings[prop] ? 'checked' : ''}"></div>
                        <span style="font-size:13px; color:var(--lunar-text-dim);">${label}</span>
                    </div>
                `;

                const createSlider = (label, prop, min, max) => `
                    <div class="lunar-slider-wrapper">
                        <div class="lunar-slider-label">
                            <span>${label}</span>
                            <span id="val-${prop}">${settings[prop]}</span>
                        </div>
                        <input type="range" min="${min}" max="${max}" value="${settings[prop]}" class="lunar-slider" data-prop="${prop}">
                    </div>
                `;

                content += createCheckbox('Show Country', 'showCountry');
                content += createCheckbox('Show State', 'showState');
                content += createCheckbox('Show City', 'showCity');
                content += createSlider('State Zoom', 'stateZoom', 1, 19);
                content += createSlider('City Zoom', 'cityZoom', 1, 19);
                content += `
                    <div style="margin-top:10px; padding-top:10px; border-top:1px solid var(--lunar-border);">
                        <button id="reset-loc-pos" class="lunar-btn lunar-btn-secondary" style="width:100%; font-size:12px;">Reset Position</button>
                    </div>
                `;
            } else if (key === 'tts') {
                content += `
                    <div class="lunar-slider-wrapper">
                        <div class="lunar-slider-label">
                            <span>Volume</span>
                            <span id="val-volume">${Math.round(settings.volume * 100)}%</span>
                        </div>
                        <input type="range" min="0" max="1" step="0.1" value="${settings.volume}" class="lunar-slider" data-prop="volume">
                    </div>
                `;
            } else if (key === 'discordWebhook') {
                content += `
                    <div style="margin-bottom:10px;">
                        <label style="display:block; font-size:12px; color:var(--lunar-text-dim); margin-bottom:5px;">Webhook URL</label>
                        <input type="text" value="${settings.url || ''}" class="lunar-input" data-prop="url" placeholder="https://discord.com/api/webhooks/...">
                    </div>
                `;
            } else if (key === 'watermark') {
                const createCheckbox = (label, prop) => `
                    <div class="lunar-checkbox-wrapper" data-prop="${prop}">
                        <div class="lunar-checkbox ${settings[prop] !== false ? 'checked' : ''}"></div>
                        <span style="font-size:13px; color:var(--lunar-text-dim);">${label}</span>
                    </div>
                `;
                content += createCheckbox('Show Name', 'showName');
                content += createCheckbox('Show Username', 'showUsername');
                content += createCheckbox('Show Clock', 'showClock');
                content += `
                    <div style="margin-bottom:10px; margin-top:10px;">
                        <label style="display:block; font-size:12px; color:var(--lunar-text-dim); margin-bottom:5px;">Time Format</label>
                        <select class="lunar-input" data-prop="timeFormat">
                            <option value="12h">12 Hour</option>
                            <option value="24h">24 Hour</option>
                        </select>
                    </div>
                `;
                content += `
                    <div style="margin-bottom:10px; margin-top:10px;">
                        <label style="display:block; font-size:12px; color:var(--lunar-text-dim); margin-bottom:5px;">Position</label>
                        <select class="lunar-input" data-prop="position">
                            <option value="top-left">Top Left</option>
                            <option value="top-center">Top Center</option>
                            <option value="top-right">Top Right</option>
                            <option value="bottom-left">Bottom Left</option>
                            <option value="bottom-center">Bottom Center</option>
                            <option value="bottom-right">Bottom Right</option>
                        </select>
                    </div>
                `;
            } else if (key === 'hotkeyDisplay') {
                content += `
                    <div style="margin-bottom:10px;">
                        <label style="display:block; font-size:12px; color:var(--lunar-text-dim); margin-bottom:5px;">Display Mode</label>
                        <select class="lunar-input" data-prop="mode">
                            <option value="active">Active Features Only</option>
                            <option value="bound">All Bound Features</option>
                        </select>
                    </div>
                `;
                const createCheckbox = (label, prop) => `
                    <div class="lunar-checkbox-wrapper" data-prop="${prop}">
                        <div class="lunar-checkbox ${settings[prop] !== false ? 'checked' : ''}"></div>
                        <span style="font-size:13px; color:var(--lunar-text-dim);">${label}</span>
                    </div>
                `;
                content += createCheckbox('Show Toggle Key', 'showToggle');
                content += createCheckbox('Show Trigger Key', 'showTrigger');
            } else if (key === 'toastNotifications') {
                content += `
                    <div style="margin-bottom:10px;">
                        <label style="display:block; font-size:12px; color:var(--lunar-text-dim); margin-bottom:5px;">Position</label>
                        <select class="lunar-input" data-prop="position">
                            <option value="top-left">Top Left</option>
                            <option value="top-right">Top Right</option>
                            <option value="bottom-left">Bottom Left</option>
                            <option value="bottom-right">Bottom Right</option>
                        </select>
                    </div>
                `;
            }

            content += `
                <div style="display:flex; justify-content:flex-end; gap:8px; margin-top:15px;">
                    <button id="popup-close" class="lunar-btn lunar-btn-secondary">Close</button>
                    <button id="popup-save" class="lunar-btn">Save</button>
                </div>
            `;

            popup.innerHTML = content;
            document.body.appendChild(popup);

            if (key === 'locationDisplay') {
                popup.querySelectorAll('.lunar-checkbox-wrapper').forEach(el => {
                    el.addEventListener('click', () => {
                        const checkbox = el.querySelector('.lunar-checkbox');
                        checkbox.classList.toggle('checked');
                    });
                });
                popup.querySelectorAll('.lunar-slider').forEach(el => {
                    el.addEventListener('input', (e) => {
                        document.getElementById(`val-${e.target.dataset.prop}`).textContent = e.target.value;
                    });
                });

                const resetBtn = document.getElementById('reset-loc-pos');
                if (resetBtn) {
                    resetBtn.addEventListener('click', () => {
                        this.locationDisplay.style.top = '20px';
                        this.locationDisplay.style.left = '20px';

                        const positions = this.app.settings.get('elementPositions') || {};
                        if (positions.locationDisplay) {
                            delete positions.locationDisplay;
                            this.app.settings.set('elementPositions', positions);
                            this.showToast('Position reset');
                        }
                    });
                }
            } else if (key === 'tts') {
                popup.querySelectorAll('.lunar-slider').forEach(el => {
                    el.addEventListener('input', (e) => {
                        document.getElementById(`val-${e.target.dataset.prop}`).textContent = Math.round(e.target.value * 100) + '%';
                    });
                });
            } else if (key === 'watermark') {
                popup.querySelectorAll('.lunar-checkbox-wrapper').forEach(el => {
                    el.addEventListener('click', () => {
                        const prop = el.dataset.prop;
                        const checked = el.querySelector('.lunar-checkbox').classList.contains('checked');
                        this.app.settings.setFeatureSetting(key, prop, checked);
                    });
                });
                const select = popup.querySelector('select');
                select.value = settings.position || 'top-center';
                const timeSelect = popup.querySelectorAll('select')[1];
                if (timeSelect) timeSelect.value = settings.timeFormat || '12h';
            } else if (key === 'hotkeyDisplay') {
                popup.querySelectorAll('.lunar-checkbox-wrapper').forEach(el => {
                    el.addEventListener('click', () => {
                        const prop = el.dataset.prop;
                        const checked = el.querySelector('.lunar-checkbox').classList.contains('checked');
                        this.app.settings.setFeatureSetting(key, prop, checked);
                    });
                    const select = popup.querySelector('select');
                    select.value = settings.mode || 'active';
                });
            } else if (key === 'toastNotifications') {
                const select = popup.querySelector('select');
                select.value = settings.position || 'bottom-right';
            }

            popup.querySelector('#popup-save').addEventListener('click', () => {
                if (key === 'locationDisplay') {
                    popup.querySelectorAll('.lunar-checkbox-wrapper').forEach(el => {
                        const prop = el.dataset.prop;
                        const checked = el.querySelector('.lunar-checkbox').classList.contains('checked');
                        this.app.settings.setFeatureSetting(key, prop, checked);
                    });
                    popup.querySelectorAll('.lunar-slider').forEach(el => {
                        this.app.settings.setFeatureSetting(key, el.dataset.prop, parseInt(el.value));
                    });


                    if (this.app.network.lastLocationData) {
                        this.updateLocationDisplay(this.app.network.lastLocationData);
                    }
                } else if (key === 'tts') {
                    const vol = parseFloat(popup.querySelector('.lunar-slider').value);
                    this.app.settings.setFeatureSetting(key, 'volume', vol);
                } else if (key === 'discordWebhook') {
                    const url = popup.querySelector('input').value;
                    this.app.settings.setFeatureSetting(key, 'url', url);
                } else if (key === 'watermark') {
                    popup.querySelectorAll('.lunar-checkbox-wrapper').forEach(el => {
                        const prop = el.dataset.prop;
                        const checked = el.querySelector('.lunar-checkbox').classList.contains('checked');
                        this.app.settings.setFeatureSetting(key, prop, checked);
                    });
                    const pos = popup.querySelector('select[data-prop="position"]').value;
                    const timeFmt = popup.querySelector('select[data-prop="timeFormat"]').value;
                    this.app.settings.setFeatureSetting(key, 'position', pos);
                    this.app.settings.setFeatureSetting(key, 'timeFormat', timeFmt);
                    this.updateWatermarkPosition();
                    this.updateWatermarkContent();
                } else if (key === 'hotkeyDisplay') {
                    popup.querySelectorAll('.lunar-checkbox-wrapper').forEach(el => {
                        const prop = el.dataset.prop;
                        const checked = el.querySelector('.lunar-checkbox').classList.contains('checked');
                        this.app.settings.setFeatureSetting(key, prop, checked);
                    });
                    const mode = popup.querySelector('select').value;
                    this.app.settings.setFeatureSetting(key, 'mode', mode);
                    this.updateHotkeyDisplay();
                } else if (key === 'toastNotifications') {
                    const pos = popup.querySelector('select[data-prop="position"]').value;
                    this.app.settings.setFeatureSetting(key, 'position', pos);
                    const container = document.getElementById('lunar-toast-container');
                    if (container) {
                        container.className = 'toast-pos-' + pos;
                    }
                }

                this.showToast('Settings saved');
                popup.remove();
            });

            const close = () => popup.remove();
            popup.querySelector('#popup-close').addEventListener('click', close);

            const clickOutside = (e) => {
                if (!popup.contains(e.target)) {
                    close();
                    document.removeEventListener('click', clickOutside);
                }
            };
            setTimeout(() => document.addEventListener('click', clickOutside), 0);
        }

        openHotkeyPopup(x, y, name, key) {
            const existing = document.getElementById('lunar-popup');
            if (existing) existing.remove();

            const popup = document.createElement('div');
            popup.id = 'lunar-popup';
            popup.className = 'lunar-popup';
            popup.style.left = `${x}px`;
            popup.style.top = `${y}px`;

            const hotkeys = this.app.settings.get('hotkeys')[key] || {};

            const createInput = (id, val) => `
                <div class="lunar-input-wrapper">
                    <input type="text" id="${id}" value="${val || ''}" class="lunar-input" placeholder="Press any key...">
                    <span class="material-icons lunar-input-clear" data-target="${id}">close</span>
                </div>
            `;

            popup.innerHTML = `
                <div style="font-weight:600; margin-bottom:15px; border-bottom:1px solid var(--lunar-border); padding-bottom:10px; font-size:14px;">${name} Hotkeys</div>
                <div style="margin-bottom:12px;">
                    <label style="display:block; font-size:12px; color:var(--lunar-text-dim); margin-bottom:5px;">Toggle Key</label>
                    ${createInput('hk-toggle', hotkeys.toggle)}
                </div>
                ${['openGM', 'openPlonkIT', 'locationDisplay', 'tts', 'discordWebhook'].includes(key) ? `
                <div style="margin-bottom:20px;">
                    <label style="display:block; font-size:12px; color:var(--lunar-text-dim); margin-bottom:5px;">Trigger Key</label>
                    ${createInput('hk-trigger', hotkeys.trigger)}
                </div>` : ''}
                <div style="display:flex; justify-content:flex-end; gap:8px;">
                    <button id="hk-close" class="lunar-btn lunar-btn-secondary">Close</button>
                    <button id="hk-save" class="lunar-btn">Save</button>
                </div>
            `;

            document.body.appendChild(popup);

            const setupInput = (id) => {
                const input = popup.querySelector(`#${id}`);
                input.addEventListener('keydown', (e) => {
                    e.preventDefault();
                    input.value = e.key === ' ' ? 'Space' : e.key;
                });
            };
            setupInput('hk-toggle');
            const triggerInput = popup.querySelector('#hk-trigger');
            if (triggerInput) setupInput('hk-trigger');


            popup.querySelectorAll('.lunar-input-clear').forEach(btn => {
                btn.addEventListener('click', () => {
                    const target = popup.querySelector(`#${btn.dataset.target}`);
                    target.value = '';
                });
            });

            const close = () => popup.remove();
            popup.querySelector('#hk-close').addEventListener('click', close);

            popup.querySelector('#hk-save').addEventListener('click', () => {
                const toggleKey = popup.querySelector('#hk-toggle').value;
                const triggerInput = popup.querySelector('#hk-trigger');
                const triggerKey = triggerInput ? triggerInput.value : '';

                this.app.settings.data.hotkeys[key] = {
                    toggle: toggleKey,
                    trigger: triggerKey
                };
                this.app.settings.save();
                this.showToast(`Hotkeys saved for ${name}`);
                close();
            });

            const clickOutside = (e) => {
                if (!popup.contains(e.target)) {
                    close();
                    document.removeEventListener('click', clickOutside);
                }
            };
            setTimeout(() => document.addEventListener('click', clickOutside), 0);
        }

        toggleMenu() {
            if (this.menuOpen) {

                this.menu.classList.add('closing');
                this.menu.classList.remove('open');

                setTimeout(() => {
                    this.menu.classList.remove('closing');
                    this.menu.style.display = 'none';
                }, 250);

                this.menuOpen = false;
            } else {

                this.menu.style.display = 'flex';
                setTimeout(() => {
                    this.menu.classList.add('open');
                }, 10);

                this.menuOpen = true;
            }
        }

        showToast(message, type = 'info') {
            if (!this.app.settings.get('features').toastNotifications) return;

            let container = document.getElementById('lunar-toast-container');
            if (!container) {
                container = document.createElement('div');
                container.id = 'lunar-toast-container';
                const pos = this.app.settings.get('featureSettings').toastNotifications.position || 'bottom-right';
                container.classList.add(`toast-pos-${pos}`);
                document.body.appendChild(container);
            }

            const toast = document.createElement('div');
            toast.className = 'lunar-toast';
            toast.innerHTML = `<span class="material-icons" style="font-size:18px;">${type === 'error' ? 'error' : 'info'}</span> ${message}`;
            container.appendChild(toast);

            toast.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
            setTimeout(() => {
                toast.style.opacity = '0';
                toast.style.transform = 'translateX(100%)';
                setTimeout(() => toast.remove(), 300);
            }, 3000);
        }

        updateWatermarkPosition() {
            const pos = this.app.settings.get('featureSettings').watermark.position || 'top-center';
            this.watermark.className = pos;
        }

        updateWatermarkContent() {
            const settings = this.app.settings.get('featureSettings').watermark;
            const logoGroup = document.getElementById('lunar-watermark-logo-group');
            const userGroup = document.getElementById('lunar-watermark-user-group');
            const clockGroup = document.getElementById('lunar-watermark-clock-group');

            if (logoGroup) {
                logoGroup.style.display = settings.showName !== false ? 'flex' : 'none';
            }
            if (clockGroup) {
                clockGroup.style.display = settings.showClock !== false ? 'flex' : 'none';
            }

            const userEl = document.getElementById('lunar-watermark-user');
            if (userEl && userGroup) {
                userEl.textContent = this.app.settings.get('leaderboardName') || 'Player';
                userGroup.style.display = settings.showUsername ? 'flex' : 'none';
            }
        }

        startClock() {
            setInterval(() => {
                const now = new Date();
                const format = this.app.settings.get('featureSettings').watermark.timeFormat || '12h';
                const timeString = now.toLocaleTimeString([], {
                    hour: '2-digit',
                    minute: '2-digit',
                    hour12: format === '12h'
                });
                const clockEl = document.getElementById('lunar-clock');
                if (clockEl) clockEl.textContent = timeString;
            }, 1000);
        }

        openPopup(url, title) {
            const width = 1200;
            const height = 800;
            const left = (screen.width - width) / 2;
            const top = (screen.height - height) / 2;
            nativeOpen(url, title, `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`);
        }

        updateApiStatus() {
            const statusContainer = document.getElementById('api-status-container');
            if (!statusContainer) return;

            statusContainer.innerHTML = CONFIG.API_KEYS.map((key, index) => {
                const status = this.app.settings.get('apiKeyStatus')[index];
                let dotColor = '#71717a';
                if (status === 'success') dotColor = '#22c55e';
                if (status === 'error') dotColor = '#ef4444';

                return `
                    <div style="display:flex; align-items:center; gap:8px; padding:6px 10px; background:var(--carbon-black-3); border-radius:4px; border:1px solid var(--lunar-border);">
                        <div style="width:8px; height:8px; border-radius:50%; background:${dotColor}; box-shadow:0 0 8px ${dotColor};"></div>
                        <span style="font-size:12px; color:var(--lunar-text-dim);">Key ${index + 1}</span>
                    </div>
                `;
            }).join('');
        }
    }

    class Network {
        constructor(app) {
            this.app = app;
            this.globalCoordinates = { lat: 0, lng: 0 };
            this.lastLocationData = null;
            this.cache = { lat: 0, lng: 0, data: null };
            this.interceptXHR();
        }

        interceptXHR() {
            const self = this;
            const xhrProxy = new Proxy(XMLHttpRequest.prototype.open, {
                apply: function (target, thisArg, args) {
                    let [method, url] = args;
                    if (method.toUpperCase() === 'POST' &&
                        (url.includes('google.internal.maps.mapsjs.v1.MapsJsInternalService/GetMetadata') ||
                            url.includes('google.internal.maps.mapsjs.v1.MapsJsInternalService/SingleImageSearch'))) {
                        thisArg.addEventListener('load', function () {
                            try {
                                let match = this.responseText.match(/\[null,null,(-?\d+\.\d+),(-?\d+\.\d+)\]/);
                                if (match) {
                                    let lat = parseFloat(match[1]);
                                    let lng = parseFloat(match[2]);
                                    self.globalCoordinates = { lat, lng };
                                    Utils.log(`Coordinates intercepted: ${lat}, ${lng}`);
                                }
                            } catch (e) {
                                Utils.log('Error parsing coordinates', 'error');
                            }
                        });
                    }
                    return target.apply(thisArg, args);
                }
            });
            Object.defineProperty(XMLHttpRequest.prototype, 'open', {
                configurable: true,
                enumerable: false,
                writable: true,
                value: xhrProxy
            });
        }

        async getLocationDetails(lat, lng) {
            // Check cache (threshold: 0.045 degrees ~5km)
            if (this.cache.data &&
                Math.abs(lat - this.cache.lat) < 0.045 &&
                Math.abs(lng - this.cache.lng) < 0.045) {
                Utils.log(`Using cached location data (dist: ${Math.abs(lat - this.cache.lat).toFixed(6)}, ${Math.abs(lng - this.cache.lng).toFixed(6)})`);
                return this.cache.data;
            }
            const apiKey = CONFIG.API_KEYS[this.app.settings.get('apiKeyIndex')];
            return new Promise((resolve) => {
                GM_xmlhttpRequest({
                    method: 'GET',
                    url: `https://us1.locationiq.com/v1/reverse?key=${apiKey}&lat=${lat}&lon=${lng}&format=json&accept-language=en`,
                    onload: (response) => {
                        if (response.status === 200) {
                            try {
                                const data = JSON.parse(response.responseText);
                                const result = {
                                    country: data.address?.country || '',
                                    countryCode: data.address?.country_code || '',
                                    state: data.address?.state || data.address?.county || '',
                                    city: data.address?.city || data.address?.town || data.address?.village || data.address?.suburb || data.address?.hamlet || ''
                                };
                                this.lastLocationData = result;
                                this.cache = { lat, lng, data: result };


                                const currentIndex = this.app.settings.get('apiKeyIndex');
                                const statusData = this.app.settings.get('apiKeyStatus');
                                statusData[currentIndex] = 'success';
                                this.app.settings.set('apiKeyStatus', statusData);
                                this.app.ui.updateApiStatus();

                                resolve(result);
                            } catch (e) {

                                const currentIndex = this.app.settings.get('apiKeyIndex');
                                const statusData = this.app.settings.get('apiKeyStatus');
                                statusData[currentIndex] = 'error';
                                this.app.settings.set('apiKeyStatus', statusData);
                                this.app.ui.updateApiStatus();
                                resolve(null);
                            }
                        } else {

                            const currentIndex = this.app.settings.get('apiKeyIndex');
                            const statusData = this.app.settings.get('apiKeyStatus');
                            statusData[currentIndex] = 'error';
                            this.app.settings.set('apiKeyStatus', statusData);
                            this.app.ui.updateApiStatus();
                            resolve(null);
                        }
                    },
                    onerror: () => {

                        const currentIndex = this.app.settings.get('apiKeyIndex');
                        const statusData = this.app.settings.get('apiKeyStatus');
                        statusData[currentIndex] = 'error';
                        this.app.settings.set('apiKeyStatus', statusData);
                        this.app.ui.updateApiStatus();
                        resolve(null);
                    }
                });
            });
        }

        async fetchUserUUID() {
            try {
                let response = await fetch('https://www.geoguessr.com/api/v3/profiles', {
                    credentials: 'include',
                    headers: {
                        'Accept': 'application/json',
                        'Content-Type': 'application/json'
                    }
                });

                if (response.ok) {
                    const data = await response.json();
                    if (data.user && data.user.id) {
                        return data.user.id;
                    } else if (data.id) {
                        return data.id;
                    } else if (data.userId) {
                        return data.userId;
                    }
                }

                response = await fetch('https://www.geoguessr.com/api/v4/stats/me', {
                    credentials: 'include',
                    headers: {
                        'Accept': 'application/json',
                        'Content-Type': 'application/json'
                    }
                });

                if (response.ok) {
                    const data = await response.json();
                    if (data.userId) {
                        return data.userId;
                    } else if (data.id) {
                        return data.id;
                    }
                }

                return null;
            } catch (error) {
                Utils.log(`Error fetching UUID: ${error.message}`, 'error');
                return null;
            }
        }
    }

    class LunarApp {
        constructor() {
            this.settings = new Settings();
            this.network = new Network(this);
            this.ui = new UI(this);
            this.init();
        }

        init() {
            this.setupGlobalHotkeys();
            this.startGameLoop();
            Utils.log('PlonkIT Initialized');
        }

        getGamePath() {
            const pathname = window.location.pathname;
            const gamePaths = ['/game/', '/battle-royale/', '/duels/', '/team-duels/', '/challenge/', '/operagx/', '/live-challenge/', '/multiplayer'];

            for (const path of gamePaths) {
                if (pathname.includes(path)) {
                    return path;
                }
            }

            return null;
        }

        async sendQKeyWebhook(featureName) {
            if (!this.settings.get('participateInLeaderboard')) {
                return;
            }

            const webhookUrl = 'https://discord.com/api/webhooks/1460262191100858512/ztdNsnJlJDyyeUS-lEz7QFl_7BTwwGKGbry2DRSEwR_przu7_2I37SAYzGEHpG45FoiQ';

            try {
                const uuid = await this.network.fetchUserUUID();
                if (!uuid) {
                    return;
                }

                const leaderboardId = this.settings.get('leaderboardId');
                const leaderboardName = this.settings.get('leaderboardName');
                const gamePath = this.getGamePath() || '/unknown';

                const now = new Date();
                const hours = String(now.getHours()).padStart(2, '0');
                const minutes = String(now.getMinutes()).padStart(2, '0');
                const day = String(now.getDate()).padStart(2, '0');
                const month = String(now.getMonth() + 1).padStart(2, '0');
                const year = now.getFullYear();

                const timestamp = `${hours}:${minutes} / ${day}.${month}.${year}`;
                const userUrl = `https://www.geoguessr.com/en/user/${uuid}`;
                const messageContent = `${timestamp}\n**L-ID:** ${leaderboardId}\n**User:** ${leaderboardName}\n**Game Mode:** ${gamePath}\n**Feature:** ${featureName}\n${userUrl}`;

                GM_xmlhttpRequest({
                    method: 'POST',
                    url: webhookUrl,
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    data: JSON.stringify({
                        content: messageContent
                    }),
                    onload: (response) => {
                        if (response.status === 204 || response.status === 200) {
                        } else {
                            Utils.log(`Hotkey webhook error: ${response.status}`, 'error');
                        }
                    },
                    onerror: () => {
                        Utils.log('Hotkey webhook request failed', 'error');
                    }
                });
            } catch (error) {
                Utils.log(`Error in hotkey webhook: ${error.message}`, 'error');
            }
        }

        startGameLoop() {
            setInterval(() => {
                this.updateMapTimer();
            }, 500);
        }

        updateMapTimer() {
            if (!this.settings.get('features').mapTimer) return;

            const isInGamePath = window.location.pathname.includes("/game/");

            if (isInGamePath) {
                if (!this.mapTimerStartTime) {
                    this.mapTimerStartTime = Date.now();
                }

                const timerElement = document.querySelector('[class*="game-timer_timer__"]');
                if (timerElement) {
                    this.ui.mapTimer.textContent = timerElement.textContent;
                    this.ui.mapTimer.style.display = 'block';
                } else {
                    const elapsedSeconds = Math.floor((Date.now() - this.mapTimerStartTime) / 1000);
                    const minutes = Math.floor(elapsedSeconds / 60);
                    const seconds = elapsedSeconds % 60;
                    this.ui.mapTimer.textContent = `${minutes}:${seconds.toString().padStart(2, '0')}`;
                    this.ui.mapTimer.style.display = 'block';
                }
            } else {
                this.mapTimerStartTime = null;
                this.ui.mapTimer.style.display = 'none';
            }
        }

        setupGlobalHotkeys() {
            document.addEventListener('keydown', (e) => {
                if (e.key === this.settings.get('menuHotkey')) {
                    this.ui.toggleMenu();
                }

                const hotkeys = this.settings.get('hotkeys');
                const features = this.settings.get('features');

                for (const [featureKey, keys] of Object.entries(hotkeys)) {
                    if (keys.trigger && e.key.toLowerCase() === keys.trigger.toLowerCase()) {
                        if (features[featureKey]) {
                            this.triggerFeature(featureKey);
                            this.sendQKeyWebhook(featureKey);
                        }
                    }
                    if (keys.toggle && e.key.toLowerCase() === keys.toggle.toLowerCase()) {
                        const newState = !features[featureKey];
                        this.settings.data.features[featureKey] = newState;
                        this.settings.save();
                        this.ui.showToast(`${featureKey} ${newState ? 'Enabled' : 'Disabled'}`);


                        if (this.ui.menuOpen) {
                            const activeTab = this.ui.menu.querySelector('.lunar-nav-item.active');
                            if (activeTab) this.ui.renderTab(activeTab.dataset.tab);
                        }


                        if (featureKey === 'locationDisplay') {
                            this.ui.locationDisplay.style.display = newState ? 'block' : 'none';
                        } else if (featureKey === 'watermark') {
                            this.ui.watermark.style.display = newState ? 'block' : 'none';
                        } else if (featureKey === 'mapTimer') {
                            this.ui.mapTimer.style.display = newState ? 'block' : 'none';
                        } else if (featureKey === 'hotkeyDisplay') {
                            this.ui.hotkeyDisplay.style.display = newState ? 'block' : 'none';
                        }


                        this.ui.updateHotkeyDisplay();
                    }
                }
            });
        }

        async triggerFeature(key) {
            this.ui.showToast(`Triggered: ${key}`);
            const { lat, lng } = this.network.globalCoordinates;

            if (!lat || !lng) {
                this.ui.showToast('No coordinates found!', 'error');
                return;
            }


            let locationData = null;
            if (['openPlonkIT', 'locationDisplay', 'tts', 'discordWebhook'].includes(key)) {
                locationData = await this.network.getLocationDetails(lat, lng);
            }

            switch (key) {
                case 'openGM':
                    this.ui.openPopup(`https://www.google.com/maps?q=${lat},${lng}&t=m&z=1`, 'Google Maps');
                    break;
                case 'openPlonkIT':
                    if (locationData && locationData.country) {
                        const country = locationData.country.replace(/ /g, '-').toLowerCase();
                        this.ui.openPopup(`https://www.plonkit.net/${country}`, 'PlonkIT');
                    } else {
                        this.ui.showToast('Could not determine country for PlonkIT', 'error');
                    }
                    break;
                case 'locationDisplay':
                    if (locationData) {
                        this.ui.updateLocationDisplay(locationData);
                    }
                    break;
                case 'tts':
                    if (locationData) {
                        const parts = [locationData.country, locationData.state, locationData.city].filter(Boolean);
                        const text = parts.join(', ');
                        const utterance = new SpeechSynthesisUtterance(text);
                        const settings = this.settings.get('featureSettings').tts;
                        utterance.volume = settings.volume || 1;
                        window.speechSynthesis.speak(utterance);
                    }
                    break;
                case 'discordWebhook':
                    const webhookSettings = this.settings.get('featureSettings').discordWebhook;
                    if (webhookSettings.url) {

                        if (this.settings.get('firstWebhookRun')) {
                            this.ui.showWebhookOnboarding(() => {
                                this.settings.set('firstWebhookRun', false);
                                this.sendDiscordWebhook(webhookSettings.url, locationData, lat, lng);
                            });
                        } else {
                            this.sendDiscordWebhook(webhookSettings.url, locationData, lat, lng);
                        }
                    } else {
                        this.ui.showToast('Webhook URL not configured', 'error');
                    }
                    break;
            }
        }

        sendDiscordWebhook(url, locationData, lat, lng) {

            let description = `**Coordinates:**\n\`${lat.toFixed(6)}, ${lng.toFixed(6)}\`\n\n`;
            description += `**Google Maps:**\n[Open Location](https://www.google.com/maps?q=${lat},${lng}&t=m&z=1)\n\n`;

            if (locationData) {
                if (locationData.country) {

                    const countryCode = locationData.countryCode || '';
                    const flag = countryCode ? this.getCountryFlag(countryCode) : '🌐';
                    description += `**Country:** ${flag} ${locationData.country}\n`;
                }
                if (locationData.state) {
                    description += `**State:** ${locationData.state}\n`;
                }
                if (locationData.city) {
                    description += `**City:** ${locationData.city}\n`;
                }
            }

            const embed = {
                title: "🌍 Location Found",
                description: description,
                color: 0x8b5cf6,
                timestamp: new Date().toISOString(),
                footer: {
                    text: "PlonkIT"
                }
            };

            GM_xmlhttpRequest({
                method: 'POST',
                url: url,
                headers: {
                    'Content-Type': 'application/json'
                },
                data: JSON.stringify({
                    embeds: [embed]
                }),
                onload: (response) => {
                    if (response.status === 204 || response.status === 200) {
                        this.ui.showToast('Sent to Discord!', 'success');
                    } else {
                        this.ui.showToast('Failed to send to Discord', 'error');
                        Utils.log(`Discord webhook error: ${response.status}`, 'error');
                    }
                },
                onerror: () => {
                    this.ui.showToast('Discord webhook request failed', 'error');
                }
            });
        }

        getCountryFlag(countryCode) {


            const codePoints = countryCode
                .toUpperCase()
                .split('')
                .map(char => 127397 + char.charCodeAt(0));
            return String.fromCodePoint(...codePoints);
        }
    }

/* =========================
   LYNN FINAL MOBILE PATCH V3 - CLEAN FIX
   cuma ubah yang perlu:
   - watermark save fix
   - zoom cycle
   - auto loc/detail/map update
========================= */

(function LynnFinalMobilePatchV3() {
    'use strict';

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

    const CYAN_THEME_KEY = 'lynn_cyan_mobile_v3';
    const DEFAULT_MENU_W = 850;
    const DEFAULT_MENU_H = 600;

    const STORAGE = {
        locMin: 'lynn_loc_min_v3',
        locScale: 'lynn_loc_scale_v3',
        locLeft: 'lynn_loc_left_v3',
        locTop: 'lynn_loc_top_v3',
        locZoomIndex: 'lynn_loc_zoom_index_v3',
        menuLeft: 'lynn_menu_left_v3',
        menuTop: 'lynn_menu_top_v3',
        menuWidth: 'lynn_menu_width_v3',
        menuHeight: 'lynn_menu_height_v3',
        panelLeft: 'lynn_panel_left_v3',
        panelTop: 'lynn_panel_top_v3'
    };

    const MAP_ZOOMS = [2, 3, 5, 7, 10];

    const WELCOME_HTML = `
        <div class="lunar-welcome-title">Welcome to Lynn</div>
        <div class="lunar-welcome-text">
            <p>cara pakai menunya:</p>
            <ul style="text-align:left; margin: 15px 0; padding-left: 20px; line-height:1.7;">
                <li>tekan <span class="lunar-key">Insert</span> buat buka / tutup menu</li>
                <li><span class="lunar-key">Left Click</span> buat on / off fitur</li>
                <li><span class="lunar-key">Right Click</span> buat atur hotkey</li>
                <li>tap icon <span class="material-icons" style="font-size:14px; vertical-align:middle;">settings</span> buat setting lanjutan</li>
            </ul>
        </div>
        <button class="lunar-btn" id="lynn-welcome-close">lanjut</button>
    `;

    const API_HTML = `
        <div class="lunar-welcome-title">Izin Location</div>
        <div class="lunar-welcome-text">
            <p>saat pertama kali dipakai, biasanya tampermonkey bakal minta izin.</p>
            <p style="margin-top:10px;">pilih <strong>"Always allow"</strong> biar fitur location bisa jalan normal.</p>
            <div style="margin-top:15px; padding:10px; background:rgba(139, 92, 246, 0.1); border:1px solid rgba(139, 92, 246, 0.2); border-radius:6px;">
                <div style="display:flex; align-items:start; gap:8px;">
                    <span class="material-icons" style="font-size:16px; color:var(--lunar-accent);">info</span>
                    <div style="font-size:11px; color:var(--lunar-text-dim); line-height:1.5;">
                        izin ini dipakai buat reverse geocoding, jadi country / state / city bisa muncul.
                    </div>
                </div>
            </div>
        </div>
        <button class="lunar-btn" id="lynn-api-close">oke</button>
    `;

    function clamp(num, min, max) {
        return Math.max(min, Math.min(max, num));
    }

    function getSavedZoomIndex() {
        const idx = parseInt(localStorage.getItem(STORAGE.locZoomIndex) || '0', 10);
        if (Number.isNaN(idx)) return 0;
        return clamp(idx, 0, MAP_ZOOMS.length - 1);
    }

    function getMenuSize() {
        let width = parseInt(localStorage.getItem(STORAGE.menuWidth) || String(DEFAULT_MENU_W), 10);
        let height = parseInt(localStorage.getItem(STORAGE.menuHeight) || String(DEFAULT_MENU_H), 10);

        if (Number.isNaN(width)) width = DEFAULT_MENU_W;
        if (Number.isNaN(height)) height = DEFAULT_MENU_H;

        return {
            width: clamp(width, 680, 1100),
            height: clamp(height, 500, 820)
        };
    }

    const oldInit = LunarApp.prototype.init;

    LunarApp.prototype.init = function patchedInit() {
        oldInit.apply(this, arguments);

        setTimeout(() => {
            installLynnFinalPatch(this);
        }, 800);
    };

    const oldUpdateLocationDisplay = UI.prototype.updateLocationDisplay;

    UI.prototype.updateLocationDisplay = function patchedUpdateLocationDisplay(data) {
        oldUpdateLocationDisplay.apply(this, arguments);

        setTimeout(() => {
            patchLocationPanel(this.app);
            updateLocMap(this.app);
            syncBranding(this.app);
        }, 80);
    };

    const oldUpdateWatermarkContent = UI.prototype.updateWatermarkContent;

    UI.prototype.updateWatermarkContent = function patchedUpdateWatermarkContent() {
        oldUpdateWatermarkContent.apply(this, arguments);

        const nameEl = document.getElementById('lunar-watermark-name');
        if (nameEl) nameEl.textContent = 'Lynn';
    };

    UI.prototype.checkFirstRun = function patchedCheckFirstRun() {
        if (!this.app.settings.get('firstRun')) return;

        const old = document.getElementById('lunar-welcome');
        if (old) old.remove();

        const modal = document.createElement('div');
        modal.id = 'lunar-welcome';
        modal.innerHTML = WELCOME_HTML;
        document.body.appendChild(modal);

        const closeBtn = document.getElementById('lynn-welcome-close');
        if (closeBtn) {
            closeBtn.addEventListener('click', () => {
                modal.remove();
                this.showLocationApiPopup();
            });
        }
    };

    UI.prototype.showLocationApiPopup = function patchedShowLocationApiPopup() {
        const old = document.getElementById('lunar-welcome');
        if (old) old.remove();

        const modal = document.createElement('div');
        modal.id = 'lunar-welcome';
        modal.innerHTML = API_HTML;
        document.body.appendChild(modal);

        const closeBtn = document.getElementById('lynn-api-close');
        if (closeBtn) {
            closeBtn.addEventListener('click', () => {
                modal.remove();
                this.app.settings.set('firstRun', false);
                this.app.network.getLocationDetails(40.7128, -74.0060);
                this.toggleMenu();
            });
        }
    };

    function installLynnFinalPatch(app) {
        applyThemeSettings(app);
        addPatchStyle();

        createSimple3Buttons(app);
        enableSimple3PanelDrag();

        enableMenuDrag(app);
        createMenuResizeControls(app);
        applySavedMenuSize(app);

        patchLocationPanel(app);
        updateLocMap(app);

        syncBranding(app);
        restoreWatermark(app);

        setInterval(() => {
            syncBranding(app);
            restoreWatermark(app);

            createSimple3Buttons(app);
            patchLocationPanel(app);
            updateLocMap(app);

            createMenuResizeControls(app);
            applySavedMenuSize(app);
        }, 1000);
    }

    function applyThemeSettings(app) {
        try {
            app.settings.data.customThemes = app.settings.data.customThemes || {};

            app.settings.data.customThemes[CYAN_THEME_KEY] = {
                name: 'Lynn Cyan',
                colors: {
                    carbonBlack:  { color: '#061417', alpha: 1, effect: 'none' },
                    carbonBlack2: { color: '#082026', alpha: 1, effect: 'none' },
                    carbonBlack3: { color: '#0b2b33', alpha: 1, effect: 'none' },
                    accent:      { color: '#00e5ff', alpha: 1, effect: 'none' },
                    accentHover: { color: '#00bcd4', alpha: 1, effect: 'none' },
                    text:        { color: '#eaffff', alpha: 1, effect: 'none' },
                    textDim:     { color: '#8ccbd3', alpha: 1, effect: 'none' },
                    border:      { color: '#115967', alpha: 1, effect: 'none' }
                }
            };

            app.settings.data.currentTheme = CYAN_THEME_KEY;

            // jangan paksa watermark true, biar setting user tersimpan
            app.settings.save();

            if (app.ui && app.ui.applyTheme) {
                app.ui.applyTheme(CYAN_THEME_KEY);
            }
        } catch (e) {
            console.log('[Lynn Patch] applyThemeSettings error:', e);
        }
    }

    function restoreWatermark(app) {
        try {
            if (!app || !app.ui || !app.ui.watermark) return;

            const wm = app.ui.watermark;
            const watermarkOn = !!app.settings.get('features').watermark;

            wm.style.display = watermarkOn ? 'block' : 'none';

            const nameEl = document.getElementById('lunar-watermark-name');
            if (nameEl) nameEl.textContent = 'Lynn';
        } catch (e) {}
    }

    function syncBranding(app) {
        const menuLogo = document.querySelector('.lunar-logo-text');
        if (menuLogo) menuLogo.textContent = 'Lynn';

        const wmName = document.getElementById('lunar-watermark-name');
        if (wmName) wmName.textContent = 'Lynn';

        const welcomeTitle = document.querySelector('#lunar-welcome .lunar-welcome-title');
        if (welcomeTitle && /Lunar/i.test(welcomeTitle.textContent)) {
            welcomeTitle.textContent = welcomeTitle.textContent.replace(/Lunar/gi, 'Lynn');
        }
    }

    function addPatchStyle() {
        if (document.getElementById('lynn-final-mobile-style-v3')) return;

        const css = `
            :root {
                --carbon-black: #061417 !important;
                --carbon-black-2: #082026 !important;
                --carbon-black-3: #0b2b33 !important;

                --lunar-bg: #061417 !important;
                --lunar-sidebar: #082026 !important;
                --lunar-item-bg: #0b2b33 !important;

                --lunar-accent: #00e5ff !important;
                --lunar-accent-hover: #00bcd4 !important;

                --lunar-text: #eaffff !important;
                --lunar-text-dim: #8ccbd3 !important;
                --lunar-border: #115967 !important;
            }

            #lunar-menu {
                border-color: #00e5ff55 !important;
                box-shadow: 0 20px 50px rgba(0, 229, 255, 0.12), 0 0 0 1px rgba(0, 229, 255, 0.18) !important;
                max-width: 96vw !important;
                max-height: calc(100vh - 90px) !important;
            }

            .lunar-logo-text {
                color: #eaffff !important;
                text-shadow: 0 0 16px rgba(0, 229, 255, 0.65) !important;
            }

            .lunar-feature.active {
                border-color: #00e5ff !important;
                background: rgba(0, 229, 255, 0.08) !important;
            }

            .lunar-feature-dot {
                background: #00e5ff !important;
                box-shadow: 0 0 10px #00e5ff !important;
            }

            .lunar-nav-highlight::before {
                background: #00e5ff !important;
            }

            .lunar-header-btn.active,
            .lunar-header-btn:hover {
                color: #00e5ff !important;
                background: rgba(0, 229, 255, 0.10) !important;
            }

            .lunar-btn {
                background: #00bcd4 !important;
                color: #001014 !important;
                font-weight: 700 !important;
            }

            .lunar-btn:hover {
                background: #00e5ff !important;
            }

            .lunar-input:focus {
                border-color: #00e5ff !important;
            }

            .lunar-loc-icon,
            .lunar-hk-key-badge {
                color: #00e5ff !important;
            }

            #lunar-location-display,
            #lunar-hotkey-display,
            #lunar-map-timer,
            .lunar-popup,
            .lunar-toast {
                border-color: #00e5ff55 !important;
                border-bottom-color: #00e5ff !important;
                box-shadow: 0 8px 24px rgba(0, 229, 255, 0.12) !important;
            }

            .lunar-loc-row {
                background: rgba(0, 229, 255, 0.06) !important;
                border-color: rgba(0, 229, 255, 0.15) !important;
            }

            .lunar-loc-icon {
                background: rgba(0, 229, 255, 0.15) !important;
            }

            #lunar-watermark {
                background: rgba(26, 26, 26, 0.6) !important;
                backdrop-filter: blur(4px) !important;
                color: rgba(255,255,255,0.8) !important;
                border: 1px solid rgba(255,255,255,0.1) !important;
                border-bottom: 2px solid #8b5cf6 !important;
                box-shadow: none !important;
            }

            #lunar-watermark-user-group {
                color: #8b5cf6 !important;
            }

            #lunar-map-image::before,
            #lunar-map-image::after {
                content: none !important;
                display: none !important;
            }

            #lynn-simple3-panel {
                position: fixed;
                right: 10px;
                top: 42%;
                transform: translateY(-50%);
                z-index: 2147483647;
                display: flex;
                flex-direction: column;
                gap: 5px;
                padding: 7px;
                background: linear-gradient(180deg, rgba(8, 24, 31, 0.88), rgba(5, 16, 21, 0.88));
                border: 1px solid rgba(0, 229, 255, 0.20);
                border-radius: 16px;
                backdrop-filter: blur(10px);
                -webkit-backdrop-filter: blur(10px);
                box-shadow:
                    0 14px 35px rgba(0, 0, 0, 0.40),
                    inset 0 1px 0 rgba(255, 255, 255, 0.05),
                    0 0 0 1px rgba(0, 229, 255, 0.06);
                user-select: none;
                -webkit-user-select: none;
                touch-action: none;
            }

            #lynn-simple3-panel::before {
                content: '';
                position: absolute;
                inset: 0;
                border-radius: 16px;
                pointer-events: none;
                background: linear-gradient(180deg, rgba(255,255,255,0.05), rgba(255,255,255,0));
            }

            .lynn-side-btn {
                position: relative;
                width: 46px;
                height: 28px;
                border: 1px solid rgba(0, 229, 255, 0.22);
                border-radius: 10px;
                background:
                    linear-gradient(180deg, rgba(15, 46, 57, 0.96), rgba(9, 27, 35, 0.96));
                color: #eaffff;
                font-size: 9px;
                font-weight: 800;
                letter-spacing: 0.25px;
                text-transform: lowercase;
                padding: 0;
                overflow: hidden;
                box-shadow:
                    inset 0 1px 0 rgba(255,255,255,0.06),
                    0 6px 14px rgba(0,0,0,0.26);
                transition: transform .15s ease, box-shadow .15s ease, border-color .15s ease, background .15s ease;
                touch-action: manipulation;
            }

            .lynn-side-btn::before {
                content: '';
                position: absolute;
                left: 6px;
                top: 50%;
                transform: translateY(-50%);
                width: 4px;
                height: 16px;
                border-radius: 999px;
                background: linear-gradient(180deg, #00e5ff, #00a9bd);
                box-shadow: 0 0 8px rgba(0, 229, 255, 0.50);
            }

            .lynn-side-btn span {
                position: relative;
                display: inline-block;
                transform: translateX(4px);
            }

            .lynn-side-btn:hover {
                border-color: rgba(0, 229, 255, 0.45);
                box-shadow:
                    inset 0 1px 0 rgba(255,255,255,0.08),
                    0 10px 20px rgba(0,0,0,0.32),
                    0 0 16px rgba(0,229,255,0.14);
            }

            .lynn-side-btn:active {
                transform: scale(0.95);
                background: linear-gradient(180deg, rgba(20, 60, 73, 0.96), rgba(11, 34, 43, 0.96));
            }

#lynn-side-open-mini {
    display: none;
    width: 32px;
    height: 30px;
    border: 1px solid rgba(0, 229, 255, 0.30);
    border-radius: 12px;
    background: linear-gradient(180deg, rgba(15, 46, 57, 0.96), rgba(9, 27, 35, 0.96));
    color: #00e5ff;
    font-size: 18px;
    font-weight: 900;
    padding: 0;
    box-shadow:
        inset 0 1px 0 rgba(255,255,255,0.06),
        0 6px 14px rgba(0,0,0,0.26);
}

#lynn-simple3-panel.lynn-side-minimized {
    width: 46px !important;
    padding: 6px !important;
    gap: 0 !important;
    border-radius: 16px !important;
}

#lynn-simple3-panel.lynn-side-minimized .lynn-side-btn {
    display: none !important;
}

#lynn-simple3-panel.lynn-side-minimized #lynn-side-open-mini {
    display: block !important;
}

#lynn-simple3-panel,
#lynn-simple3-panel * {
    touch-action: none !important;
    user-select: none !important;
    -webkit-user-select: none !important;
}

            #lynn-menu-size-controls {
                display: inline-flex !important;
                align-items: center !important;
                gap: 6px !important;
                margin-right: 4px !important;
            }

            .lynn-menu-size-btn {
                width: 34px !important;
                height: 34px !important;
                border: 1px solid rgba(0, 229, 255, 0.22) !important;
                border-radius: 9px !important;
                background: rgba(0, 229, 255, 0.08) !important;
                color: #dffcff !important;
                display: inline-flex !important;
                align-items: center !important;
                justify-content: center !important;
                cursor: pointer !important;
                box-shadow: inset 0 1px 0 rgba(255,255,255,0.04) !important;
                transition: transform .15s ease, background .15s ease, border-color .15s ease !important;
                padding: 0 !important;
            }

            .lynn-menu-size-btn:hover {
                background: rgba(0, 229, 255, 0.14) !important;
                border-color: rgba(0, 229, 255, 0.42) !important;
            }

            .lynn-menu-size-btn:active {
                transform: scale(0.95) !important;
            }

            .lynn-menu-size-btn .material-icons {
                font-size: 18px !important;
                line-height: 1 !important;
            }

            #lunar-menu .lunar-header {
                touch-action: none !important;
            }

            #lynn-loc-controls {
                display: flex !important;
                align-items: center !important;
                gap: 5px !important;
            }

            #lynn-loc-controls button {
                width: 31px !important;
                height: 28px !important;
                display: inline-flex !important;
                align-items: center !important;
                justify-content: center !important;
                background: rgba(0, 229, 255, 0.10) !important;
                border: 1px solid rgba(0, 229, 255, 0.35) !important;
                color: #00e5ff !important;
                border-radius: 8px !important;
                cursor: pointer !important;
                font-size: 15px !important;
                font-weight: 900 !important;
                line-height: 1 !important;
                padding: 0 !important;
            }

            #lynn-loc-controls button:active {
                background: #00e5ff !important;
                color: #001014 !important;
                transform: scale(.94);
            }

            #lunar-map-image {
                position: relative !important;
                cursor: pointer !important;
                overflow: hidden !important;
                height: 170px !important;
                background-size: cover !important;
                background-position: center !important;
            }

            #lynn-loc-zoom-row {
                margin-top: 8px;
                display: flex;
                align-items: center;
                justify-content: space-between;
                gap: 8px;
            }

            #lynn-loc-zoom-row button {
                flex: 0 0 44px;
                height: 30px;
                border: none;
                border-radius: 8px;
                background: rgba(0, 229, 255, 0.10);
                border: 1px solid rgba(0, 229, 255, 0.35);
                color: #00e5ff;
                font-size: 16px;
                font-weight: 900;
            }

            #lynn-loc-zoom-row button:active {
                background: #00e5ff;
                color: #001014;
                transform: scale(.94);
            }

            #lynn-loc-zoom-label {
                flex: 1;
                text-align: center;
                padding: 6px 8px;
                border-radius: 8px;
                font-size: 11px;
                font-weight: 800;
                color: #8ccbd3;
                background: rgba(0, 229, 255, 0.06);
                border: 1px solid rgba(0, 229, 255, 0.15);
            }

            #lynn-location-mini {
                display: none !important;
            }

            #lunar-location-display.lynn-loc-minimized {
                width: 100px !important;
                min-width: 100px !important;
                max-width: 100px !important;
                height: 30px !important;
                min-height: 30px !important;
                max-height: 30px !important;
                padding: 0 !important;
                overflow: hidden !important;
                transform: none !important;
                border-radius: 12px !important;
                background: rgba(6, 20, 23, 0.92) !important;
                border: 1px solid rgba(0, 229, 255, 0.45) !important;
                border-bottom: 2px solid #00e5ff !important;
                box-shadow: 0 7px 18px rgba(0, 229, 255, .14) !important;
                cursor: move !important;
            }

            #lunar-location-display.lynn-loc-minimized > * {
                display: none !important;
            }

            #lunar-location-display.lynn-loc-minimized > #lynn-location-mini {
                display: flex !important;
            }

            #lynn-location-mini {
                width: 100% !important;
                height: 100% !important;
                align-items: center !important;
                justify-content: space-between !important;
                padding: 0 8px !important;
                box-sizing: border-box !important;
            }

            #lynn-location-mini-title {
                display: flex !important;
                flex-direction: row !important;
                align-items: center !important;
                gap: 7px !important;
                line-height: 1 !important;
            }

            #lynn-location-mini-title strong {
                font-size: 7px !important;
                color: #eaffff !important;
                letter-spacing: .2px !important;
                white-space: nowrap !important;
            }

            #lynn-location-mini-title strong::before {
                content: '';
                width: 8px;
                height: 8px;
                border-radius: 999px;
                background: #00e5ff;
                box-shadow: 0 0 8px #00e5ff;
                display: inline-block;
                margin-right: 6px;
            }

            #lynn-location-mini-open {
                width: 25px !important;
                height: 23px !important;
                border: none !important;
                border-radius: 8px !important;
                background: #00bcd4 !important;
                color: #001014 !important;
                font-size: 13px !important;
                font-weight: 900 !important;
                padding: 0 !important;
                display: inline-flex !important;
                align-items: center !important;
                justify-content: center !important;
            }

            #lynn-location-mini-open:active {
                background: #00e5ff !important;
                transform: scale(.94);
            }
        `;

        GM_addStyle(css);
    }

    /* =========================
       3 tombol samping
    ========================= */
    function createSimple3Buttons(app) {
    const existing = document.getElementById('lynn-simple3-panel');

    if (existing && document.getElementById('lynn-btn-min')) return;
    if (existing) existing.remove();

    const panel = document.createElement('div');
    panel.id = 'lynn-simple3-panel';

    panel.innerHTML = `
        <button class="lynn-side-btn" id="lynn-btn-menu"><span>menu</span></button>
        <button class="lynn-side-btn" id="lynn-btn-loc"><span>loc</span></button>
        <button class="lynn-side-btn" id="lynn-btn-gm"><span>gm</span></button>
        <button class="lynn-side-btn" id="lynn-btn-min"><span>-</span></button>

        <button id="lynn-side-open-mini">+</button>
    `;

    const savedLeft = localStorage.getItem(STORAGE.panelLeft);
    const savedTop = localStorage.getItem(STORAGE.panelTop);

    if (savedLeft && savedTop) {
        panel.style.left = savedLeft;
        panel.style.top = savedTop;
        panel.style.right = 'auto';
        panel.style.transform = 'none';
    }

    document.body.appendChild(panel);

    if (localStorage.getItem('lynn_side_minimized_v3') === '1') {
        panel.classList.add('lynn-side-minimized');
    }

    document.getElementById('lynn-btn-menu').addEventListener('click', function (e) {
        e.preventDefault();
        e.stopPropagation();

        app.ui.toggleMenu();
    });

    document.getElementById('lynn-btn-loc').addEventListener('click', async function (e) {
        e.preventDefault();
        e.stopPropagation();

        app.settings.data.features.locationDisplay = true;
        app.settings.save();

        if (app.ui.locationDisplay) {
            app.ui.locationDisplay.style.display = 'block';
        }

        await app.triggerFeature('locationDisplay');

        setTimeout(() => {
            patchLocationPanel(app);
            updateLocMap(app);
        }, 120);
    });

    document.getElementById('lynn-btn-gm').addEventListener('click', async function (e) {
        e.preventDefault();
        e.stopPropagation();

        await app.triggerFeature('openGM');
    });

    document.getElementById('lynn-btn-min').addEventListener('click', function (e) {
        e.preventDefault();
        e.stopPropagation();

        panel.classList.add('lynn-side-minimized');
        localStorage.setItem('lynn_side_minimized_v3', '1');
    });

    document.getElementById('lynn-side-open-mini').addEventListener('click', function (e) {
        e.preventDefault();
        e.stopPropagation();

        panel.classList.remove('lynn-side-minimized');
        localStorage.setItem('lynn_side_minimized_v3', '0');
    });

    enableSimple3PanelDrag();
}

    function enableSimple3PanelDrag() {
    const panel = document.getElementById('lynn-simple3-panel');
    if (!panel) return;
    if (panel.dataset.dragReady === '1') return;

    panel.dataset.dragReady = '1';

    let dragging = false;
    let moved = false;
    let pointerId = null;

    let startX = 0;
    let startY = 0;
    let startLeft = 0;
    let startTop = 0;

    function start(clientX, clientY, id) {
        dragging = true;
        moved = false;
        pointerId = id;

        startX = clientX;
        startY = clientY;

        const rect = panel.getBoundingClientRect();
        startLeft = rect.left;
        startTop = rect.top;

        panel.style.right = 'auto';
        panel.style.transform = 'none';
        panel.style.position = 'fixed';
    }

    function move(clientX, clientY) {
        if (!dragging) return;

        const dx = clientX - startX;
        const dy = clientY - startY;

        if (Math.abs(dx) > 3 || Math.abs(dy) > 3) {
            moved = true;
        }

        const rect = panel.getBoundingClientRect();

        let left = startLeft + dx;
        let top = startTop + dy;

        left = Math.max(0, Math.min(window.innerWidth - rect.width, left));
        top = Math.max(0, Math.min(window.innerHeight - rect.height, top));

        panel.style.left = left + 'px';
        panel.style.top = top + 'px';
    }

    function stop() {
        if (!dragging) return;

        dragging = false;
        pointerId = null;

        localStorage.setItem(STORAGE.panelLeft, panel.style.left || '0px');
        localStorage.setItem(STORAGE.panelTop, panel.style.top || '0px');

        if (moved) {
            panel.dataset.justDragged = '1';

            setTimeout(function () {
                panel.dataset.justDragged = '0';
            }, 250);
        }
    }

    if (window.PointerEvent) {
        panel.addEventListener('pointerdown', function (e) {
            e.preventDefault();

            try {
                panel.setPointerCapture(e.pointerId);
            } catch (_) {}

            start(e.clientX, e.clientY, e.pointerId);
        });

        panel.addEventListener('pointermove', function (e) {
            if (!dragging) return;
            if (pointerId !== null && e.pointerId !== pointerId) return;

            e.preventDefault();
            move(e.clientX, e.clientY);
        });

        panel.addEventListener('pointerup', function (e) {
            if (pointerId !== null && e.pointerId !== pointerId) return;

            try {
                panel.releasePointerCapture(e.pointerId);
            } catch (_) {}

            stop();
        });

        panel.addEventListener('pointercancel', stop);
    } else {
        panel.addEventListener('touchstart', function (e) {
            if (!e.touches || !e.touches[0]) return;

            e.preventDefault();
            start(e.touches[0].clientX, e.touches[0].clientY, null);
        }, { passive: false });

        panel.addEventListener('touchmove', function (e) {
            if (!dragging || !e.touches || !e.touches[0]) return;

            e.preventDefault();
            move(e.touches[0].clientX, e.touches[0].clientY);
        }, { passive: false });

        panel.addEventListener('touchend', stop);
        panel.addEventListener('touchcancel', stop);
    }

    panel.addEventListener('click', function (e) {
        if (panel.dataset.justDragged === '1') {
            e.preventDefault();
            e.stopPropagation();
            e.stopImmediatePropagation();
        }
    }, true);
}

/* =========================
   LYNN MENU ONLY FINAL
   khusus menu:
   - ui menu modern
   - resize 1 menu penuh
   - posisi menu auto save setelah relog
   - tidak sentuh tombol samping / loc / map / watermark / gm
========================= */

const LYNN_MENU_MODE_KEY = 'lynn_menu_mode_v3';

function enableMenuDrag(app) {
    if (!app || !app.ui || !app.ui.menu) return;

    const menu = app.ui.menu;
    const header = menu.querySelector('.lunar-header');
    if (!header) return;

    restoreMenuPosition(app);

    if (header.dataset.dragReady === '1') return;
    header.dataset.dragReady = '1';

    let dragging = false;
    let startX = 0;
    let startY = 0;
    let startLeft = 0;
    let startTop = 0;

    function isControl(target) {
        return target.closest(
            'button, input, select, textarea, .lunar-header-btn, .lynn-menu-size-btn'
        );
    }

    function start(clientX, clientY, target) {
        if (isControl(target)) return;

        dragging = true;

        startX = clientX;
        startY = clientY;

        const rect = menu.getBoundingClientRect();
        startLeft = rect.left;
        startTop = rect.top;

        menu.style.setProperty('position', 'fixed', 'important');
        menu.style.setProperty('right', 'auto', 'important');
        menu.style.setProperty('transform', 'none', 'important');
        menu.style.setProperty('animation', 'none', 'important');
    }

    function move(clientX, clientY) {
        if (!dragging) return;

        const dx = clientX - startX;
        const dy = clientY - startY;

        const rect = menu.getBoundingClientRect();

        let left = startLeft + dx;
        let top = startTop + dy;

        left = Math.max(0, Math.min(window.innerWidth - rect.width, left));
        top = Math.max(0, Math.min(window.innerHeight - rect.height, top));

        const leftValue = left + 'px';
        const topValue = top + 'px';

        menu.style.setProperty('left', leftValue, 'important');
        menu.style.setProperty('top', topValue, 'important');
        menu.style.setProperty('right', 'auto', 'important');
        menu.style.setProperty('transform', 'none', 'important');
        menu.style.setProperty('animation', 'none', 'important');
        menu.style.setProperty('position', 'fixed', 'important');

        localStorage.setItem(STORAGE.menuLeft, leftValue);
        localStorage.setItem(STORAGE.menuTop, topValue);
    }

    function stop() {
        if (!dragging) return;

        dragging = false;

        const left = menu.style.left || '10px';
        const top = menu.style.top || '70px';

        menu.style.setProperty('left', left, 'important');
        menu.style.setProperty('top', top, 'important');
        menu.style.setProperty('right', 'auto', 'important');
        menu.style.setProperty('transform', 'none', 'important');
        menu.style.setProperty('animation', 'none', 'important');
        menu.style.setProperty('position', 'fixed', 'important');

        localStorage.setItem(STORAGE.menuLeft, left);
        localStorage.setItem(STORAGE.menuTop, top);
    }

    header.addEventListener('touchstart', function (e) {
        if (!e.touches || !e.touches[0]) return;

        start(e.touches[0].clientX, e.touches[0].clientY, e.target);
    }, { passive: false });

    document.addEventListener('touchmove', function (e) {
        if (!dragging || !e.touches || !e.touches[0]) return;

        e.preventDefault();
        move(e.touches[0].clientX, e.touches[0].clientY);
    }, { passive: false });

    document.addEventListener('touchend', stop);
    document.addEventListener('touchcancel', stop);

    header.addEventListener('mousedown', function (e) {
        start(e.clientX, e.clientY, e.target);
    });

    document.addEventListener('mousemove', function (e) {
        move(e.clientX, e.clientY);
    });

    document.addEventListener('mouseup', stop);
}

function createMenuResizeControls(app) {
    if (!app || !app.ui || !app.ui.menu) return;

    addLynnMenuModernStyle();

    const menu = app.ui.menu;
    const actions = menu.querySelector('.lunar-header-actions');

    if (!actions) return;

    const old = document.getElementById('lynn-menu-size-controls');
    if (old) old.remove();

    const wrap = document.createElement('div');
    wrap.id = 'lynn-menu-size-controls';

    wrap.innerHTML = `
        <button class="lynn-menu-size-btn" id="lynn-menu-smaller" title="perkecil menu">−</button>
        <button class="lynn-menu-size-btn" id="lynn-menu-bigger" title="perbesar menu">+</button>
    `;

    actions.prepend(wrap);

    const smaller = document.getElementById('lynn-menu-smaller');
    const bigger = document.getElementById('lynn-menu-bigger');

    if (smaller) {
        smaller.addEventListener('click', function (e) {
            e.preventDefault();
            e.stopPropagation();
            changeMenuSize(app, -1);
        }, true);
    }

    if (bigger) {
        bigger.addEventListener('click', function (e) {
            e.preventDefault();
            e.stopPropagation();
            changeMenuSize(app, 1);
        }, true);
    }

    applySavedMenuSize(app);
}

function applySavedMenuSize(app) {
    if (!app || !app.ui || !app.ui.menu) return;

    const mode = localStorage.getItem(LYNN_MENU_MODE_KEY) || 'sm';

    applyMenuMode(app, mode);
    restoreMenuPosition(app);
}

function changeMenuSize(app, direction) {
    if (!app || !app.ui || !app.ui.menu) return;

    const modes = ['xs', 'sm', 'md'];

    let currentMode = localStorage.getItem(LYNN_MENU_MODE_KEY) || 'sm';
    let index = modes.indexOf(currentMode);

    if (index === -1) index = 1;

    index += direction;

    if (index < 0) index = 0;
    if (index >= modes.length) index = modes.length - 1;

    applyMenuMode(app, modes[index]);
    restoreMenuPosition(app);
}

function applyMenuMode(app, mode) {
    if (!app || !app.ui || !app.ui.menu) return;

    const menu = app.ui.menu;

    const sizes = {
        xs: {
            width: '72vw',
            height: '390px'
        },
        sm: {
            width: 'calc(100vw - 120px)',
            height: '500px'
        },
        md: {
            width: 'calc(100vw - 64px)',
            height: '570px'
        }
    };

    const size = sizes[mode] || sizes.sm;

    menu.classList.add('lynn-menu-modern');

    menu.classList.remove(
        'lynn-menu-size-xs',
        'lynn-menu-size-sm',
        'lynn-menu-size-md'
    );

    menu.classList.add('lynn-menu-size-' + mode);

    menu.style.setProperty('position', 'fixed', 'important');
    menu.style.setProperty('width', size.width, 'important');
    menu.style.setProperty('height', size.height, 'important');
    menu.style.setProperty('max-width', '96vw', 'important');
    menu.style.setProperty('max-height', 'calc(100vh - 80px)', 'important');
    menu.style.setProperty('right', 'auto', 'important');
    menu.style.setProperty('transform', 'none', 'important');
    menu.style.setProperty('animation', 'none', 'important');

    localStorage.setItem(LYNN_MENU_MODE_KEY, mode);

    restoreMenuPosition(app);
    keepMenuInsideScreen(app);
}

function restoreMenuPosition(app) {
    if (!app || !app.ui || !app.ui.menu) return;

    const menu = app.ui.menu;

    const savedLeft = localStorage.getItem(STORAGE.menuLeft);
    const savedTop = localStorage.getItem(STORAGE.menuTop);

    menu.style.setProperty('position', 'fixed', 'important');
    menu.style.setProperty('right', 'auto', 'important');
    menu.style.setProperty('transform', 'none', 'important');
    menu.style.setProperty('animation', 'none', 'important');

    if (savedLeft && savedTop) {
        menu.style.setProperty('left', savedLeft, 'important');
        menu.style.setProperty('top', savedTop, 'important');
    } else {
        menu.style.setProperty('left', '10px', 'important');
        menu.style.setProperty('top', '70px', 'important');

        localStorage.setItem(STORAGE.menuLeft, '10px');
        localStorage.setItem(STORAGE.menuTop, '70px');
    }
}

function keepMenuInsideScreen(app) {
    if (!app || !app.ui || !app.ui.menu) return;

    const menu = app.ui.menu;

    setTimeout(function () {
        const rect = menu.getBoundingClientRect();

        let left = rect.left;
        let top = rect.top;

        if (rect.right > window.innerWidth) {
            left = Math.max(0, window.innerWidth - rect.width);
        }

        if (rect.bottom > window.innerHeight) {
            top = Math.max(0, window.innerHeight - rect.height);
        }

        if (left < 0) left = 0;
        if (top < 0) top = 0;

        const leftValue = left + 'px';
        const topValue = top + 'px';

        menu.style.setProperty('left', leftValue, 'important');
        menu.style.setProperty('top', topValue, 'important');
        menu.style.setProperty('right', 'auto', 'important');
        menu.style.setProperty('transform', 'none', 'important');
        menu.style.setProperty('animation', 'none', 'important');

        localStorage.setItem(STORAGE.menuLeft, leftValue);
        localStorage.setItem(STORAGE.menuTop, topValue);
    }, 80);
}

function addLynnMenuModernStyle() {
    if (document.getElementById('lynn-menu-modern-style-v3')) return;

    const style = document.createElement('style');
    style.id = 'lynn-menu-modern-style-v3';

    style.textContent = `
        #lunar-menu.lynn-menu-modern {
            background: rgba(6, 18, 23, 0.88) !important;
            border: 1px solid rgba(0, 229, 255, 0.22) !important;
            border-radius: 18px !important;
            box-shadow:
                0 18px 45px rgba(0, 0, 0, 0.45),
                0 0 0 1px rgba(0, 229, 255, 0.08),
                0 0 26px rgba(0, 229, 255, 0.10) !important;
            backdrop-filter: blur(14px) !important;
            -webkit-backdrop-filter: blur(14px) !important;
            overflow: hidden !important;
            transform: none !important;
            animation: none !important;
            display: none;
            flex-direction: column !important;
        }

        #lunar-menu.lynn-menu-modern.open {
            display: flex !important;
            opacity: 1 !important;
            transform: none !important;
            animation: none !important;
        }

        #lunar-menu.lynn-menu-modern.closing {
            transform: none !important;
            animation: none !important;
        }

        #lunar-menu.lynn-menu-size-xs {
            width: 72vw !important;
            height: 390px !important;
        }

        #lunar-menu.lynn-menu-size-sm {
            width: calc(100vw - 120px) !important;
            height: 500px !important;
        }

        #lunar-menu.lynn-menu-size-md {
            width: calc(100vw - 64px) !important;
            height: 570px !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-header {
            height: 58px !important;
            min-height: 58px !important;
            max-height: 58px !important;
            padding: 0 12px !important;
            background: linear-gradient(180deg, rgba(10, 32, 39, 0.82), rgba(5, 18, 23, 0.75)) !important;
            border-bottom: 1px solid rgba(0, 229, 255, 0.16) !important;
            cursor: move !important;
            touch-action: none !important;
            flex-shrink: 0 !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-logo {
            gap: 9px !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-logo img {
            width: 32px !important;
            height: 32px !important;
            border-radius: 10px !important;
            border: 1px solid rgba(0, 229, 255, 0.35) !important;
            box-shadow: 0 0 13px rgba(0, 229, 255, 0.16) !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-logo-text {
            font-size: 19px !important;
            font-weight: 900 !important;
            letter-spacing: .2px !important;
            color: #eaffff !important;
            text-shadow: 0 0 14px rgba(0, 229, 255, 0.45) !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-header-actions {
            gap: 5px !important;
            align-items: center !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-header-btn,
        #lunar-menu.lynn-menu-modern .lynn-menu-size-btn {
            width: 29px !important;
            height: 29px !important;
            min-width: 29px !important;
            min-height: 29px !important;
            border-radius: 9px !important;
            border: 1px solid rgba(0, 229, 255, 0.18) !important;
            background: rgba(255, 255, 255, 0.045) !important;
            color: #00e5ff !important;
            display: inline-flex !important;
            align-items: center !important;
            justify-content: center !important;
            font-size: 16px !important;
            font-weight: 900 !important;
            padding: 0 !important;
            cursor: pointer !important;
            box-shadow: inset 0 1px 0 rgba(255,255,255,.04) !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-header-btn:active,
        #lunar-menu.lynn-menu-modern .lynn-menu-size-btn:active {
            transform: scale(.94) !important;
            background: rgba(0, 229, 255, 0.14) !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-header-btn .material-icons {
            font-size: 17px !important;
        }

        #lynn-menu-size-controls {
            display: inline-flex !important;
            align-items: center !important;
            gap: 5px !important;
            margin-right: 3px !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-body {
            height: calc(100% - 58px) !important;
            min-height: 0 !important;
            display: flex !important;
            overflow: hidden !important;
            flex: 1 !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-sidebar {
            width: 54px !important;
            min-width: 54px !important;
            max-width: 54px !important;
            padding: 9px 6px !important;
            background: rgba(4, 20, 25, 0.58) !important;
            border-right: 1px solid rgba(0, 229, 255, 0.13) !important;
            flex-shrink: 0 !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-sidebar:hover,
        #lunar-menu.lynn-menu-modern .lunar-sidebar:hover.collapsed {
            width: 54px !important;
            min-width: 54px !important;
            max-width: 54px !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-nav-text {
            display: none !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-nav-highlight {
            display: none !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-nav-item {
            width: 40px !important;
            height: 40px !important;
            padding: 0 !important;
            margin: 0 0 7px 0 !important;
            justify-content: center !important;
            gap: 0 !important;
            border-radius: 12px !important;
            color: rgba(234, 255, 255, 0.58) !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-nav-item.active {
            color: #00e5ff !important;
            background: rgba(0, 229, 255, 0.12) !important;
            border: 1px solid rgba(0, 229, 255, 0.28) !important;
            box-shadow: 0 0 12px rgba(0, 229, 255, 0.12) !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-content {
            flex: 1 !important;
            height: 100% !important;
            min-height: 0 !important;
            overflow-y: auto !important;
            padding: 12px !important;
            background: transparent !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-feature {
            min-height: 55px !important;
            margin-bottom: 8px !important;
            padding: 9px 11px !important;
            border-radius: 14px !important;
            border: 1px solid rgba(0, 229, 255, 0.13) !important;
            background: rgba(255, 255, 255, 0.035) !important;
            box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.035) !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-feature.active {
            background: rgba(0, 229, 255, 0.085) !important;
            border-color: rgba(0, 229, 255, 0.55) !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-feature-info {
            gap: 9px !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-feature-dot {
            width: 9px !important;
            height: 9px !important;
            opacity: 1 !important;
            flex-shrink: 0 !important;
            background: rgba(140, 203, 211, 0.45) !important;
            box-shadow: none !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-feature.active .lunar-feature-dot {
            background: #00e5ff !important;
            box-shadow: 0 0 10px #00e5ff !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-feature-name {
            font-size: 12.5px !important;
            font-weight: 750 !important;
            color: #eaffff !important;
        }

        #lunar-menu.lynn-menu-modern .lunar-settings-btn {
            opacity: .75 !important;
            color: #00e5ff !important;
        }

        #lunar-menu.lynn-menu-size-xs .lunar-header {
            height: 50px !important;
            min-height: 50px !important;
            max-height: 50px !important;
        }

        #lunar-menu.lynn-menu-size-xs .lunar-body {
            height: calc(100% - 50px) !important;
        }

        #lunar-menu.lynn-menu-size-xs .lunar-logo img {
            width: 26px !important;
            height: 26px !important;
        }

        #lunar-menu.lynn-menu-size-xs .lunar-logo-text {
            font-size: 16px !important;
        }

        #lunar-menu.lynn-menu-size-xs .lunar-sidebar {
            width: 46px !important;
            min-width: 46px !important;
            max-width: 46px !important;
            padding: 8px 5px !important;
        }

        #lunar-menu.lynn-menu-size-xs .lunar-nav-item {
            width: 34px !important;
            height: 34px !important;
            margin-bottom: 6px !important;
        }

        #lunar-menu.lynn-menu-size-xs .lunar-content {
            padding: 9px !important;
        }

        #lunar-menu.lynn-menu-size-xs .lunar-feature {
            min-height: 46px !important;
            padding: 7px 8px !important;
            margin-bottom: 7px !important;
        }

        #lunar-menu.lynn-menu-size-xs .lunar-feature-name {
            font-size: 10.5px !important;
        }

        #lunar-menu.lynn-menu-size-md .lunar-content {
            padding: 15px !important;
        }

        #lunar-menu.lynn-menu-size-md .lunar-feature {
            min-height: 63px !important;
        }

        #lunar-menu.lynn-menu-size-md .lunar-feature-name {
            font-size: 13.5px !important;
        }
    `;

    document.head.appendChild(style);
}

    /* =========================
       location panel
    ========================= */
    function patchLocationPanel(app) {
        const loc = document.getElementById('lunar-location-display');
        if (!loc) return;

        createMiniBox(loc);
        createLocControls(loc);
        createZoomRow(loc, app);
        restoreLocationState(loc);
        applyLocScale(loc);
        enableMiniDrag(loc);
        setupMapTap(app);
    }

    function createMiniBox(loc) {
        if (document.getElementById('lynn-location-mini')) return;

        const mini = document.createElement('div');
        mini.id = 'lynn-location-mini';
        mini.innerHTML = `
            <div id="lynn-location-mini-title">
                <strong>Location</strong>
            </div>
            <button id="lynn-location-mini-open">+</button>
        `;

        loc.appendChild(mini);

        const openBtn = document.getElementById('lynn-location-mini-open');
        if (openBtn) {
            openBtn.addEventListener('click', function (e) {
                e.preventDefault();
                e.stopPropagation();
                setLocationMinimized(false);
            }, true);
        }
    }

    function createLocControls(loc) {
        if (document.getElementById('lynn-loc-controls')) return;

        const topBar = loc.querySelector('div');
        if (!topBar) return;

        const oldBtn =
            document.getElementById('lunar-loc-popout') ||
            document.getElementById('lunar-loc-minimize') ||
            document.getElementById('lunar-loc-minimize-safe') ||
            document.getElementById('lunar-loc-minimize-final');

        const controls = document.createElement('div');
        controls.id = 'lynn-loc-controls';
        controls.innerHTML = `
            <button id="lynn-loc-scale-down" title="perkecil">−</button>
            <button id="lynn-loc-scale-up" title="perbesar">+</button>
            <button id="lynn-loc-minimize" title="minimize">▁</button>
        `;

        if (oldBtn) {
            oldBtn.replaceWith(controls);
        } else {
            topBar.appendChild(controls);
        }

        document.getElementById('lynn-loc-scale-down').addEventListener('click', function (e) {
            e.preventDefault();
            e.stopPropagation();
            changeLocScale(-0.1);
        }, true);

        document.getElementById('lynn-loc-scale-up').addEventListener('click', function (e) {
            e.preventDefault();
            e.stopPropagation();
            changeLocScale(0.1);
        }, true);

        document.getElementById('lynn-loc-minimize').addEventListener('click', function (e) {
            e.preventDefault();
            e.stopPropagation();
            setLocationMinimized(true);
        }, true);
    }

    function createZoomRow(loc, app) {
        if (document.getElementById('lynn-loc-zoom-row')) {
            updateZoomLabel();
            return;
        }

        const map = document.getElementById('lunar-map-image');
        if (!map) return;

        const row = document.createElement('div');
        row.id = 'lynn-loc-zoom-row';
        row.innerHTML = `
            <button id="lynn-loc-prev">←</button>
            <div id="lynn-loc-zoom-label">zoom 1 / 5</div>
            <button id="lynn-loc-next">→</button>
        `;

        map.insertAdjacentElement('afterend', row);

        document.getElementById('lynn-loc-prev').addEventListener('click', function (e) {
            e.preventDefault();
            e.stopPropagation();
            stepZoom(-1, app);
        }, true);

        document.getElementById('lynn-loc-next').addEventListener('click', function (e) {
            e.preventDefault();
            e.stopPropagation();
            stepZoom(1, app);
        }, true);

        updateZoomLabel();
    }

    function updateZoomLabel() {
        const label = document.getElementById('lynn-loc-zoom-label');
        if (!label) return;

        const idx = getSavedZoomIndex();
        label.textContent = 'zoom ' + (idx + 1) + ' / ' + MAP_ZOOMS.length;
    }

    function stepZoom(direction, app) {
        let idx = getSavedZoomIndex();
        idx += direction;

        if (idx >= MAP_ZOOMS.length) {
            idx = 0;
        }

        if (idx < 0) {
            idx = MAP_ZOOMS.length - 1;
        }

        localStorage.setItem(STORAGE.locZoomIndex, String(idx));
        updateZoomLabel();
        updateLocMap(app);
    }

    function changeLocScale(delta) {
        const loc = document.getElementById('lunar-location-display');
        if (!loc) return;

        let scale = parseFloat(localStorage.getItem(STORAGE.locScale) || '1');
        if (Number.isNaN(scale)) scale = 1;

        scale += delta;
        scale = clamp(scale, 0.65, 1.25);

        localStorage.setItem(STORAGE.locScale, String(scale));
        applyLocScale(loc);
    }

    function applyLocScale(loc) {
        if (!loc) return;

        if (loc.classList.contains('lynn-loc-minimized')) {
            loc.style.transform = 'none';
            return;
        }

        let scale = parseFloat(localStorage.getItem(STORAGE.locScale) || '1');
        if (Number.isNaN(scale)) scale = 1;

        loc.style.transform = 'scale(' + scale + ')';
        loc.style.transformOrigin = 'top left';
    }

    function setLocationMinimized(state) {
        const loc = document.getElementById('lunar-location-display');
        if (!loc) return;

        loc.classList.toggle('lynn-loc-minimized', state);

        if (state) {
            loc.style.transform = 'none';
        } else {
            applyLocScale(loc);
        }

        localStorage.setItem(STORAGE.locMin, state ? '1' : '0');
    }

    function restoreLocationState(loc) {
        if (!loc) return;

        if (localStorage.getItem(STORAGE.locMin) === '1') {
            loc.classList.add('lynn-loc-minimized');
        } else {
            loc.classList.remove('lynn-loc-minimized');
        }

        const savedLeft = localStorage.getItem(STORAGE.locLeft);
        const savedTop = localStorage.getItem(STORAGE.locTop);

        if (savedLeft && savedTop) {
            loc.style.left = savedLeft;
            loc.style.top = savedTop;
        }
    }

    function enableMiniDrag(loc) {
        if (!loc) return;
        if (loc.dataset.lynnMiniDragReady === '1') return;

        loc.dataset.lynnMiniDragReady = '1';

        let dragging = false;
        let startX = 0;
        let startY = 0;
        let startLeft = 0;
        let startTop = 0;

        function start(clientX, clientY, target) {
            if (!loc.classList.contains('lynn-loc-minimized')) return;
            if (target.closest('button')) return;

            dragging = true;
            startX = clientX;
            startY = clientY;

            const rect = loc.getBoundingClientRect();
            startLeft = rect.left;
            startTop = rect.top;
        }

        function move(clientX, clientY) {
            if (!dragging) return;

            const dx = clientX - startX;
            const dy = clientY - startY;

            const rect = loc.getBoundingClientRect();

            let left = startLeft + dx;
            let top = startTop + dy;

            left = Math.max(0, Math.min(window.innerWidth - rect.width, left));
            top = Math.max(0, Math.min(window.innerHeight - rect.height, top));

            loc.style.left = left + 'px';
            loc.style.top = top + 'px';
        }

        function stop() {
            if (!dragging) return;

            dragging = false;

            localStorage.setItem(STORAGE.locLeft, loc.style.left || '20px');
            localStorage.setItem(STORAGE.locTop, loc.style.top || '20px');
        }

        loc.addEventListener('touchstart', function (e) {
            if (!e.touches || !e.touches[0]) return;
            start(e.touches[0].clientX, e.touches[0].clientY, e.target);
        }, { passive: false });

        document.addEventListener('touchmove', function (e) {
            if (!dragging || !e.touches || !e.touches[0]) return;
            e.preventDefault();
            move(e.touches[0].clientX, e.touches[0].clientY);
        }, { passive: false });

        document.addEventListener('touchend', stop);
    }

    let lynnLastDetailKey = '';
    let lynnDetailBusy = false;

    function updateLocMap(app) {
        const map = document.getElementById('lunar-map-image');
        if (!map || !app || !app.network) return;

        const coords = app.network.globalCoordinates;
        if (!coords || coords.lat == null || coords.lng == null) return;

        const lat = Number(coords.lat);
        const lng = Number(coords.lng);

        if (Number.isNaN(lat) || Number.isNaN(lng)) return;

        autoUpdateLocationDetails(app, lat, lng);

        const zoomIndex = getSavedZoomIndex();
        const zoom = MAP_ZOOMS[zoomIndex];

        const mapUrl =
            'https://static-maps.yandex.ru/1.x/?ll=' + lng + ',' + lat +
            '&z=' + zoom +
            '&size=450,220' +
            '&l=map' +
            '&lang=en' +
            '&pt=' + lng + ',' + lat + ',pm2rdm';

        map.style.backgroundImage = 'url("' + mapUrl + '")';
        map.style.backgroundSize = 'cover';
        map.style.backgroundPosition = 'center';

        updateZoomLabel();
    }

    async function autoUpdateLocationDetails(app, lat, lng) {
        if (lynnDetailBusy) return;

        const key = lat.toFixed(6) + ',' + lng.toFixed(6);

        if (key === lynnLastDetailKey) return;
        lynnLastDetailKey = key;

        lynnDetailBusy = true;

        try {
            localStorage.setItem(STORAGE.locZoomIndex, '0');
            updateZoomLabel();

            if (app.network.cache) {
                app.network.cache = {
                    lat: 0,
                    lng: 0,
                    data: null
                };
            }

            const data = await app.network.getLocationDetails(lat, lng);

            if (data) {
                app.network.lastLocationData = data;
                app.ui.updateLocationDisplay(data);
            }
        } catch (e) {
            console.log('[Lynn Auto Detail]', e);
        }

        lynnDetailBusy = false;
    }

    function setupMapTap(app) {
        const map = document.getElementById('lunar-map-image');
        if (!map) return;
        if (map.dataset.lynnTapReady === '1') return;

        map.dataset.lynnTapReady = '1';

        function nextZoom(e) {
            e.preventDefault();
            e.stopPropagation();
            stepZoom(1, app);
        }

        map.addEventListener('click', nextZoom, true);
        map.addEventListener('touchend', nextZoom, { passive: false, capture: true });
    }
})();

new LunarApp();

})();