☰

hitlock awesome edition [FREE]

discord.gg/weedhook | dude wanted to trash talk me and try to scare me saying im ratted

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

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

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         hitlock awesome edition [FREE]
// @namespace    https://omoggle.com/
// @version      12.0.0
// @description  discord.gg/weedhook | dude wanted to trash talk me and try to scare me saying im ratted
// @match        https://omoggle.com/*
// @match        https://*.omoggle.com/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    const CONFIG = {
        enabled: true,
        myScoreBoost: 1.84,
        myFinalScore: "94000",
        oppFinalScore: "15000",
        frameCap: 99000,
        // Live boost mode: 'multiplier' | 'range'
        boostMode: 'multiplier',
        boostRangeMin: 1.0,
        boostRangeMax: 2.5,
        // Final score mode: 'fixed' | 'range'
        finalScoreMode: 'fixed',
        finalScoreRangeMin: 85000,
        finalScoreRangeMax: 97000,
        boostPercent: 50,
        boostRandom: 10,         // ± random variance percent
        boostDuration: 1000,
        holdBtnSize: 54,
        debug: true,
        wmAlpha: 20,
        wmFontSize: 9,
        wmPaddingH: 14,
        wmPaddingV: 6,
        wmBorder: true,
        wmBg: true
    };

    let playerMapping = null;
    let _isRanked = window.location.pathname.startsWith('/ranked');

    // Lock in ranked mode the moment we see a ranked frame or URL
    const _origPushState = history.pushState;
    history.pushState = function(...args) {
        _origPushState.apply(this, args);
        _isRanked = window.location.pathname.startsWith('/ranked');
    };
    window.addEventListener('popstate', () => {
        _isRanked = window.location.pathname.startsWith('/ranked');
    });


    function tryDecode(data) {
        try {
            const bytes = data instanceof ArrayBuffer ? new Uint8Array(data) : data;
            if (!(bytes instanceof Uint8Array)) return null;
            const text = new TextDecoder().decode(bytes);
            const jsonMatch = text.match(/\{[^}]+\}/);
            if (jsonMatch) return { json: JSON.parse(jsonMatch[0]), bytes, fullText: text };
        } catch (e) {}
        return null;
    }

    function rewriteBytes(originalBytes, oldJSON, newJSON) {
        const originalText = new TextDecoder().decode(originalBytes);
        const newText = originalText.replace(JSON.stringify(oldJSON), JSON.stringify(newJSON));
        return new TextEncoder().encode(newText);
    }

    // ── OUTGOING DataChannel — boost your q score for live display ────────────
    const originalSend = RTCDataChannel.prototype.send;
    RTCDataChannel.prototype.send = function (data) {
        const parsed = tryDecode(data);
        if (parsed?.json) {
            const { json, bytes } = parsed;

            const hasP = typeof json.p !== 'undefined';
            const hasQ = typeof json.q !== 'undefined';
            // Normal frame: {p, q} only — no m field, no type
            const isNormalFrame = hasP && hasQ && json.m === undefined && !json.type;
            // Ranked frame: {p, q, m} — m contains face metrics
            const isRankedFrame = hasP && hasQ && json.m !== undefined;

            // Use packet structure to lock in ranked detection
            if (isRankedFrame && !_isRanked) {
                _isRanked = true;
                log('🔒 Locked: RANKED mode (m field detected in frame)');
            }

            if (isNormalFrame || isRankedFrame) {
                if (!playerMapping && json.q > 0) {
                    playerMapping = { myKey: 'q' };
                    log(`📌 q confirmed as your score [${isRankedFrame ? 'RANKED' : 'NORMAL'} frame]`);
                }
                if (json.q > 0) {
                    const modified = { ...json };
                    let _liveBoost;
                    if (CONFIG.boostMode === 'range') {
                        _liveBoost = CONFIG.boostRangeMin + Math.random() * (CONFIG.boostRangeMax - CONFIG.boostRangeMin);
                    } else {
                        _liveBoost = CONFIG.myScoreBoost * _boostMultiplier;
                    }
                    modified.q = Math.min(Math.round(json.q * _liveBoost), CONFIG.frameCap);
                    // Preserve m field exactly — server cross-validates it
                    if (json.m !== undefined) modified.m = json.m;
                    if (json.type !== undefined) modified.type = json.type;

                    log(`📤 [${isRankedFrame ? 'RANKED' : 'NORMAL'}] frame=${json.p} q: ${json.q}→${modified.q} (${(json.q/10000).toFixed(2)}→${(modified.q/10000).toFixed(2)})`);
                    _lastSpoofedScore = modified.q / 10000;
                    spoofPanel();
                    return originalSend.call(this, rewriteBytes(bytes, json, modified));
                }
            }

            const isRankedScoreType = json.type === "RANKED_SCORE" && typeof json.score !== "undefined";
            if (isRankedScoreType) {
                const modified = { ...json };
                modified.score = Math.min(json.score * CONFIG.myScoreBoost, 10);
                _lastSpoofedScore = modified.score;
                log(`📤 [RANKED_SCORE type] score: ${json.score}→${modified.score}`);
                spoofPanel();
                return originalSend.call(this, rewriteBytes(bytes, json, modified));
            }
        }
        return originalSend.call(this, data);
    };

    // ── INCOMING DataChannel — pure passthrough, no modification ─────────────
    // Just log opponent scores, don't touch the bytes (avoids corruption/0.0 display)
    const origOnMessageDesc = Object.getOwnPropertyDescriptor(RTCDataChannel.prototype, 'onmessage');
    if (origOnMessageDesc) {
        Object.defineProperty(RTCDataChannel.prototype, 'onmessage', {
            set(fn) {
                origOnMessageDesc.set.call(this, function(event) {
                    const parsed = tryDecode(event.data);
                    if (parsed?.json) {
                        const { json } = parsed;
                        if (typeof json.p !== 'undefined' && typeof json.q !== 'undefined' && !json.type && json.q > 0) {
                            log(`📥 OPP frame=${json.p} score=${(json.q/10000).toFixed(2)}`);
                        }
                    }
                    return fn.call(this, event); // pass original event unchanged
                });
            },
            get: origOnMessageDesc.get,
            configurable: true
        });
    }

    const originalAEL = RTCDataChannel.prototype.addEventListener;
    RTCDataChannel.prototype.addEventListener = function (type, listener, options) {
        if (type !== 'message' || typeof listener !== 'function')
            return originalAEL.call(this, type, listener, options);

        const wrapped = function (event) {
            const parsed = tryDecode(event.data);
            if (parsed?.json) {
                const { json } = parsed;
                if (typeof json.p !== 'undefined' && typeof json.q !== 'undefined' && !json.type && json.q > 0) {
                    log(`📥 OPP (AEL) frame=${json.p} score=${(json.q/10000).toFixed(2)}`);
                }
            }
            return listener.call(this, event); // pass original event unchanged
        };
        return originalAEL.call(this, type, wrapped, options);
    };

    // ── Fetch intercept — finalize + Supabase profile ────────────────────────
    const origFetch = window.fetch;
    window.fetch = async function(url, options) {
        const urlStr = typeof url === 'string' ? url : (url?.url || '');

        // LOG EVERY REQUEST
        console.log('🔍 FETCH:', urlStr);

        // Handle finalize endpoints
        if (urlStr.includes('/api/match/finalize') || urlStr.includes('/api/ranked/finalize')) {
            if (options?.body) {
                try {
                    const body = JSON.parse(options.body);
                    log('📤 FINALIZE (original):', JSON.stringify(body).substring(0, 500));

                    const scoreObj = body.u || body.i;
                    if (scoreObj && scoreObj.e !== undefined) {
                        const realE = parseInt(scoreObj.e) || 0;
                        const realO = parseInt(scoreObj.o) || 0;

                        const _finalTarget = _getFinalTarget();
                        scoreObj.e = String(_finalTarget);

                        if (scoreObj.o !== undefined) {
                            scoreObj.o = String(Math.min(
                                Math.max(realO, 1000),
                                parseInt(CONFIG.oppFinalScore)
                            ));
                        }

                        if (body.i) _isRanked = true;
                        const whichMode = _isRanked ? 'RANKED body.i' : 'NORMAL body.u';
                        log(`🎯 [${whichMode}] score.e: ${realE} → ${scoreObj.e} | score.o: ${realO} → ${scoreObj.o}`);
                    }

                    options = { ...options, body: JSON.stringify(body) };
                    log('📤 FINALIZE REQUEST (modified):', JSON.stringify(body));
                } catch(e) {
                    log('⚠️ Could not parse finalize body:', e);
                }
            }

            const response = await origFetch.call(this, url, options);
            const clone = response.clone();
            clone.json().then(data => {
                log('📥 FINALIZE RESPONSE:', JSON.stringify(data));
                // Only reset lock after a successful finalize (not 409 retry)
                if (response.ok) {
                    _lockedFinalTarget = null;
                    _finalApplied = false;
                    _lastSpoofedScore = null;  // ← add this
                }
            }).catch(() => {});
            return response;
        }

        // ═══ PROFILE INTERCEPT (ALL ENDPOINTS) ═══════════════════════════════════
        const BOOSTED_STATS = {
            elo_rating: 95500,
            total_wins: 45000,
            is_dev: true,
            is_pro: true,
            current_win_streak: 5000,
            current_loss_streak: 0,
            public_appeal_sum: 95000,
            public_appeal_count: 100
        };

        // 1. Supabase direct endpoint (returns array)
        if (urlStr.includes('supabase.co/rest/v1/profiles')) {
            const response = await origFetch.call(this, url, options);
            const clone = response.clone();
            try {
                const data = await clone.json();
                log('📊 SUPABASE PROFILE (original):', JSON.stringify(data));

                if (Array.isArray(data) && data.length > 0) {
                    const modified = data.map(profile => ({
                        ...profile,
                        ...BOOSTED_STATS
                    }));
                    log('📊 SUPABASE PROFILE (modified):', JSON.stringify(modified));

                    // Clone headers and ensure content-type is set
                    const newHeaders = new Headers(response.headers);
                    newHeaders.set('content-type', 'application/json');

                    return new Response(JSON.stringify(modified), {
                        status: response.status,
                        statusText: response.statusText,
                        headers: newHeaders
                    });
                }
            } catch(e) {
                log('⚠️ Supabase intercept error:', e);
            }
            return response;
        }

        // 2. Omoggle public profile endpoint
        if (urlStr.includes('/api/profiles/public/')) {
            const response = await origFetch.call(this, url, options);
            const clone = response.clone();
            try {
                const data = await clone.json();
                console.log('📊 PUBLIC PROFILE ORIGINAL:', urlStr, JSON.stringify(data, null, 2));

                if (data && data.profile) {
                    const modified = {
                        ...data,
                        profile: {
                            ...data.profile,
                            elo_rating: 95500,
                            total_wins: 45000,
                            is_pro: true,
                            current_win_streak: 5000,
                            current_loss_streak: 0,
                            public_appeal_sum: 95000,
                            public_appeal_count: 100,
                            rank_tier: {
                                name: "GOD",
                                emoji: "👑",
                                hexColor: "#FFD700",
                                textShadow: "0 0 20px rgba(255,215,0,1)"
                            }
                        }
                    };
                    console.log('📊 PUBLIC PROFILE MODIFIED:', JSON.stringify(modified, null, 2));
                    return new Response(JSON.stringify(modified), {
                        status: response.status,
                        statusText: response.statusText,
                        headers: response.headers
                    });
                }
            } catch(e) {
                console.error('⚠️ PUBLIC PROFILE error:', e);
            }
            return response;
        }

        // 3. /api/profile/ranked-stats
        if (urlStr.includes('/api/profile/ranked-stats')) {
            const response = await origFetch.call(this, url, options);
            const clone = response.clone();
            try {
                const data = await clone.json();
                console.log('📊 RANKED-STATS ORIGINAL:', JSON.stringify(data, null, 2));

                const modified = {
                    ...data,
                    rating: 95500,           // Modify existing field
                    currentElo: 95500,       // Modify existing field
                    wins: 45000,             // Modify existing field
                    losses: 0,               // Modify existing field
                    matchesPlayed: 45000     // Update to match wins
                };
                console.log('📊 RANKED-STATS MODIFIED:', JSON.stringify(modified, null, 2));
                return new Response(JSON.stringify(modified), {
                    status: response.status,
                    statusText: response.statusText,
                    headers: response.headers
                });
            } catch(e) {
                console.error('⚠️ RANKED-STATS error:', e);
            }
            return response;
        }

        // 4. /api/profile/world-rank
        if (urlStr.includes('/api/profile/world-rank')) {
            const response = await origFetch.call(this, url, options);
            const clone = response.clone();
            try {
                const data = await clone.json();
                console.log('📊 WORLD-RANK ORIGINAL:', JSON.stringify(data, null, 2));

                const modified = {
                    ...data,
                    rank: 1,             // You're #1 in the world
                    elo: 95500,          // Modify existing elo field
                    percentile: 99.9
                };
                console.log('📊 WORLD-RANK MODIFIED:', JSON.stringify(modified, null, 2));
                return new Response(JSON.stringify(modified), {
                    status: response.status,
                    statusText: response.statusText,
                    headers: response.headers
                });
            } catch(e) {
                console.error('⚠️ WORLD-RANK error:', e);
            }
            return response;
        }

        // Add after the world-rank block, before the final return statement

        // 5. /api/profile/lobby-summary
        if (urlStr.includes('/api/profile/lobby-summary')) {
            const response = await origFetch.call(this, url, options);
            const clone = response.clone();
            try {
                const data = await clone.json();
                console.log('📊 LOBBY-SUMMARY ORIGINAL:', JSON.stringify(data, null, 2));

                if (data && typeof data === 'object') {
                    const modified = {
                        ...data,
                        elo_rating: 95500,
                        total_wins: 45000,
                        current_win_streak: 5000,
                        current_loss_streak: 0,
                        rank_tier: {
                            name: "GOD",
                            emoji: "👑",
                            hexColor: "#FFD700",
                            textShadow: "0 0 20px rgba(255,215,0,1)"
                        }
                    };
                    console.log('📊 LOBBY-SUMMARY MODIFIED:', JSON.stringify(modified, null, 2));
                    return new Response(JSON.stringify(modified), {
                        status: response.status,
                        statusText: response.statusText,
                        headers: response.headers
                    });
                }
            } catch(e) {
                console.error('⚠️ LOBBY-SUMMARY error:', e);
            }
            return response;
        }

        // 6. /api/profile (catch-all for remaining profile endpoints)
        if (urlStr === '/api/profile' || urlStr.endsWith('/api/profile')) {
            const response = await origFetch.call(this, url, options);
            const clone = response.clone();
            try {
                const data = await clone.json();
                console.log('📊 /api/profile ORIGINAL:', JSON.stringify(data, null, 2));

                if (data && data.profile) {
                    const modified = {
                        ...data,
                        profile: {
                            ...data.profile,
                            elo_rating: 95500,
                            total_wins: 45000,
                            rank_tier: {
                                name: "GOD",
                                emoji: "👑",
                                hexColor: "#FFD700",
                                textShadow: "0 0 20px rgba(255,215,0,1)"
                            }
                        }
                    };
                    console.log('📊 /api/profile MODIFIED:', JSON.stringify(modified, null, 2));
                    return new Response(JSON.stringify(modified), {
                        status: response.status,
                        statusText: response.statusText,
                        headers: response.headers
                    });
                }
            } catch(e) {
                console.error('⚠️ /api/profile error:', e);
            }
            return response;
        }

        return origFetch.call(this, url, options);
    };

    let _lockedFinalTarget = null;
    let _lastFinalMode = null;
    let _finalApplied = false;

    function _getFinalTarget() {
        // Re-lock if mode changed or no lock yet
        if (_lockedFinalTarget === null || _lastFinalMode !== CONFIG.finalScoreMode) {
            _finalApplied = false;
            _lastFinalMode = CONFIG.finalScoreMode;
            if (CONFIG.finalScoreMode === 'range') {
                _lockedFinalTarget = Math.round(CONFIG.finalScoreRangeMin + Math.random() * (CONFIG.finalScoreRangeMax - CONFIG.finalScoreRangeMin));
            } else {
                _lockedFinalTarget = parseInt(CONFIG.myFinalScore);
            }
            log(`🎯 _getFinalTarget locked: ${_lockedFinalTarget} (${CONFIG.finalScoreMode})`);
        }
        // In fixed mode always return current slider value (no lock needed)
        if (CONFIG.finalScoreMode === 'fixed') {
            return parseInt(CONFIG.myFinalScore);
        }
        return _lockedFinalTarget;
    }

    // ── Zustand store patch ───────────────────────────────────────────────────
    function patchZustandStore() {
        try {
            const wpChunk = window.webpackChunk_N_E || window.webpackChunknextjs_app || window.webpackChunk;
            if (!wpChunk) return false;
            const req = wpChunk.push([[Symbol()], {}, e => e]);
            const mod = req(16225);
            if (!mod) return false;
            const store = Object.values(mod).find(val =>
                                                  val && typeof val.getState === 'function' && 'myScore' in (val.getState() || {})
                                                 );
            if (!store) return false;
            return patchStore(store);
        } catch(e) {
            log('⚠️ patchZustandStore error:', e);
            return false;
        }
    }

    function patchStore(store) {
        try {
            const state = store.getState();

            // patch setMyScore
            // patch setMyScore — only override at end of match (high score = final result)
            const origSetMyScore = state.setMyScore;
            if (origSetMyScore && !origSetMyScore.__patched) {
                store.setState({
                    setMyScore: function(score) {
                        const cap = CONFIG.frameCap / 10000;
                        let boosted;
                        if (CONFIG.boostMode === 'range') {
                            const rangeMult = CONFIG.boostRangeMin + Math.random() * (CONFIG.boostRangeMax - CONFIG.boostRangeMin);
                            boosted = Math.min(score * rangeMult, cap);
                        } else {
                            boosted = Math.min(score * CONFIG.myScoreBoost * _boostMultiplier, cap);
                        }
                        log(`🎯 setMyScore: ${score.toFixed(2)} → ${boosted.toFixed(2)}`);
                        _lastSpoofedScore = boosted;
                        spoofPanel();
                        return origSetMyScore.call(this, boosted);
                    }
                });
                store.getState().setMyScore.__patched = true;
                log('✅ setMyScore patched');
            }

            // patch applyFinalScores
            const origApply = state.applyFinalScores;
            if (origApply && !origApply.__patched) {
                store.setState({
                    applyFinalScores: function(p1, p2, iAmPlayer1) {
                        log('🏁 applyFinalScores called — injecting final target');
                        const target = _getFinalTarget();
                        const myScore = target / 10000;
                        const oppScore = Math.max(parseInt(CONFIG.oppFinalScore), 1000) / 10000;
                        const newP1 = iAmPlayer1 ? myScore : oppScore;
                        const newP2 = iAmPlayer1 ? oppScore : myScore;
                        log(`🚀 applyFinalScores → p1=${newP1} p2=${newP2} iAmPlayer1=${iAmPlayer1}`);
                        _finalApplied = true;
                        _lastSpoofedScore = null;
                        // Do NOT set _lastSpoofedScore or call spoofPanel here —
                        // the results screen will render from Zustand naturally,
                        // and live panel keeps showing the real boosted frame score
                        return origApply.call(this, newP1, newP2, iAmPlayer1);
                    }
                });
                store.getState().applyFinalScores.__patched = true;
                log('✅ applyFinalScores patched');
                // Hold the final score in Zustand until the match screen clears
            }

            return true;
        } catch(e) {
            log('⚠️ patchStore error:', e);
            return false;
        }
    }

    let patchAttempts = 0;
    const patchPoll = setInterval(() => {
        patchAttempts++;
        if (patchZustandStore()) {
            clearInterval(patchPoll);
        } else if (patchAttempts % 50 === 0) {
            log(`⏳ Still looking for Zustand store... (attempt ${patchAttempts})`);
        }
    }, 200);

    // ── UI Panel spoof ────────────────────────────────────────────────────────
    const TIER_MAP = [
        { name: 'Adam',     emoji: '🍎', hexColor: '#ef4444', textShadow: '0 0 12px rgba(239,68,68,0.95)',    min: 9.7 },
        { name: 'Slayer',   emoji: '☠️', hexColor: '#f472b6', textShadow: '0 0 12px rgba(244,114,182,0.9)',   min: 9.5 },
        { name: 'Chad',     emoji: '👑', hexColor: '#fb923c', textShadow: '0 0 10px rgba(251,146,60,0.8)',    min: 8.9 },
        { name: 'Chadlite', emoji: '⚜️', hexColor: '#facc15', textShadow: '0 0 8px rgba(250,204,21,0.8)',     min: 8.3 },
        { name: 'HTN',      emoji: '🌟', hexColor: '#a3e635', textShadow: '0 0 8px rgba(163,230,53,0.8)',     min: 7.0 },
        { name: 'MTN',      emoji: '⭐', hexColor: '#86efac', textShadow: '0 0 6px rgba(134,239,172,0.7)',    min: 5.6 },
        { name: 'LTN',      emoji: '🌙', hexColor: '#34d399', textShadow: '0 0 6px rgba(52,211,153,0.6)',     min: 3.1 },
        { name: 'Sub3',     emoji: '🦀', hexColor: '#b45309', textShadow: '0 0 6px rgba(180,83,9,0.7)',       min: 0.1 },
    ];

    let _lastSpoofedScore = null;
    let _boostMultiplier = 1.0;      // live multiplier applied on top of myScoreBoost
    let _boostHeld = false;
    let _boostRampAF = null;         // requestAnimationFrame handle

    function rampBoost(toHeld) {
        if (_boostRampAF) { cancelAnimationFrame(_boostRampAF); _boostRampAF = null; }
        const start = _boostMultiplier;
        const targetMultiplier = toHeld
        ? 1 + (CONFIG.boostPercent / 100) * (1 + (Math.random() * 2 - 1) * CONFIG.boostRandom / 100)
        : 1.0;
        const startTime = performance.now();
        function step(now) {
            const t = Math.min(1, (now - startTime) / CONFIG.boostDuration);
            // ease in-out cubic
            const ease = t < 0.5 ? 4*t*t*t : 1 - Math.pow(-2*t+2,3)/2;
            _boostMultiplier = start + (targetMultiplier - start) * ease;
            if (t < 1) {
                _boostRampAF = requestAnimationFrame(step);
            } else {
                _boostMultiplier = targetMultiplier;
                _boostRampAF = null;
            }
        }
        _boostRampAF = requestAnimationFrame(step);
    }

    function getTierForScore(score) {
        for (const tier of TIER_MAP) {
            if (score >= tier.min) return tier;
        }
        return TIER_MAP[TIER_MAP.length - 1];
    }

    function spoofPanel() {
        if (_lastSpoofedScore === null) return;
        const displayScore = _lastSpoofedScore;
        const tier = getTierForScore(displayScore);

        // Try normal panel selectors first, then ranked-specific ones
        const myPanel = document.querySelector('.glass-panel.absolute.top-5') ||
              document.querySelector('.glass-panel.absolute.top-8') ||
              document.querySelector('[class*="glass-panel"][class*="absolute"][class*="left"]') ||
              document.querySelector('[class*="glass-panel"][class*="absolute"][class*="top"]') ||
              // Ranked mode uses a different panel structure
              document.querySelector('[class*="ranked"][class*="score"]') ||
              document.querySelector('[class*="player-score"]') ||
              document.querySelector('[class*="my-score"]') ||
              // Fallback: find any panel containing a font-mono score span
              (() => {
                  const allPanels = document.querySelectorAll('[class*="glass"], [class*="panel"], [class*="score-card"]');
                  for (const p of allPanels) {
                      const spans = p.querySelectorAll('span.font-mono');
                      for (const s of spans) {
                          if (/^\d+\.?\d*$/.test(s.textContent.trim())) return p;
                      }
                  }
                  return null;
              })();
        if (!myPanel) return;

        const allMono = myPanel.querySelectorAll('span.font-mono');
        let scoreSpan = null;
        for (const s of allMono) {
            if (/^\d+\.?\d*$/.test(s.textContent.trim())) {
                scoreSpan = s;
                break;
            }
        }
        if (!scoreSpan) return;

        // Fix score text only — do NOT touch its color or textShadow
        if (scoreSpan.textContent.trim() !== displayScore.toFixed(1)) {
            scoreSpan.textContent = displayScore.toFixed(1);
        }

        // Fix tier label span (next sibling after score)
        const tierSpan = scoreSpan.nextElementSibling;
        if (tierSpan) {
            const want = `${tier.emoji} ${tier.name}`;
            if (tierSpan.textContent !== want) {
                tierSpan.textContent = want;
            }
            if (tierSpan.style.color !== tier.hexColor) {
                tierSpan.style.color = tier.hexColor;
            }
            if (tierSpan.style.textShadow !== tier.textShadow) {
                tierSpan.style.textShadow = tier.textShadow;
            }
        }

        // Scan ALL spans — only recolor tier name spans, not the score span
        const allSpans = myPanel.querySelectorAll('span');
        for (const span of allSpans) {
            if (span === scoreSpan) continue; // skip the score number span entirely
            const t = span.textContent.trim();
            const tierNames = ['Adam','Slayer','Chad','Chadlite','HTN','MTN','LTN','Sub3'];
            if (tierNames.some(n => t.includes(n)) && !t.includes(tier.name)) {
                span.textContent = `${tier.emoji} ${tier.name}`;
                span.style.color = tier.hexColor;
                span.style.textShadow = tier.textShadow;
            }
            // Only recolor tier-colored spans that are NOT the score span
            if (span.style.color && span.style.color !== tier.hexColor) {
                const tierColors = ['#ef4444','#f472b6','#fb923c','#facc15','#a3e635','#86efac','#34d399','#b45309'];
                if (tierColors.includes(span.style.color)) {
                    span.style.color = tier.hexColor;
                    span.style.textShadow = tier.textShadow;
                }
            }
        }
    }

    // MutationObserver fires the moment React updates the DOM — no visible flash
    const _panelObserver = new MutationObserver(spoofPanel);
    let _observedPanel = null;

    function attachPanelObserver() {
        const myPanel = document.querySelector('.glass-panel.absolute.top-5') ||
              document.querySelector('.glass-panel.absolute.top-8') ||
              document.querySelector('[class*="glass-panel"][class*="absolute"][class*="left"]') ||
              document.querySelector('[class*="glass-panel"][class*="absolute"][class*="top"]') ||
              document.querySelector('[class*="ranked"][class*="score"]') ||
              document.querySelector('[class*="player-score"]') ||
              document.querySelector('[class*="my-score"]') ||
              (() => {
                  const allPanels = document.querySelectorAll('[class*="glass"], [class*="panel"], [class*="score-card"]');
                  for (const p of allPanels) {
                      const spans = p.querySelectorAll('span.font-mono');
                      for (const s of spans) {
                          if (/^\d+\.?\d*$/.test(s.textContent.trim())) return p;
                      }
                  }
                  return null;
              })();
        if (myPanel && myPanel !== _observedPanel) {
            if (_observedPanel) _panelObserver.disconnect();
            _panelObserver.observe(myPanel, { childList: true, subtree: true, characterData: true });
            _observedPanel = myPanel;
        }
    }

    setInterval(() => { attachPanelObserver(); spoofPanel(); }, 16);

    // ── WebSocket monitor ─────────────────────────────────────────────────────
    const OriginalWebSocket = window.WebSocket;
    window.WebSocket = function(...args) {
        const ws = new OriginalWebSocket(...args);
        ws.addEventListener('message', function(event) {
            if (typeof event.data === 'string') {
                if (event.data.includes('FINAL_SCORES') || event.data.includes('elo') || event.data.includes('score')) {
                    log('📡 WS TEXT:', event.data);
                }
                return;
            }
            const buf = event.data instanceof ArrayBuffer ? event.data : null;
            if (!buf) return;
            const bytes = new Uint8Array(buf);
            const size = bytes.length;
            const text = new TextDecoder('utf-8', { fatal: false }).decode(bytes);
            const strings = text.match(/[\x20-\x7E]{4,}/g) || [];
            if (size === 108 || size > 50) {
                log(`📡 WS RECV binary [${size} bytes] strings:`, strings);
                strings.forEach(s => {
                    if (/\d\.\d/.test(s) || s.includes('score') || s.includes('win') || s.includes('elo')) {
                        log('   ⚠️  Possible score string:', s);
                    }
                });
            }
        });
        return ws;
    };
    Object.setPrototypeOf(window.WebSocket, OriginalWebSocket);
    window.WebSocket.prototype = OriginalWebSocket.prototype;
    ['CONNECTING','OPEN','CLOSING','CLOSED'].forEach(k => {
        try {
            Object.defineProperty(window.WebSocket, k, {
                value: OriginalWebSocket[k],
                writable: false,
                configurable: true
            });
        } catch(e) {}
    });

    log('🚀 v12 — clean passthrough incoming | u.e/i.e finalize boost | outgoing q boost');

    // ── CAMERA PIPELINE DEBUG ─────────────────────────────────────────────────

    // 1. Intercept getUserMedia — see what constraints the game requests
    const _dbgGetUserMedia = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);
    navigator.mediaDevices.getUserMedia = async function(constraints) {
        console.log('🎥 getUserMedia called:', JSON.stringify(constraints));
        const stream = await _dbgGetUserMedia(constraints);
        console.log('🎥 getUserMedia returned stream:', stream.id,
                    '| video tracks:', stream.getVideoTracks().map(t => `${t.label} [${t.readyState}]`),
                    '| audio tracks:', stream.getAudioTracks().map(t => `${t.label} [${t.readyState}]`)
                   );
        // Log every time a track ends
        stream.getVideoTracks().forEach(t => {
            t.addEventListener('ended', () => console.log('🎥 VIDEO TRACK ENDED:', t.label));
            t.addEventListener('mute',  () => console.log('🎥 VIDEO TRACK MUTED:', t.label));
        });
        return stream;
    };

    // 2. Intercept RTCPeerConnection — see how video is added to the peer connection
    const _OrigRTCPC = window.RTCPeerConnection;
    window.RTCPeerConnection = function(...args) {
        const pc = new _OrigRTCPC(...args);
        console.log('📡 RTCPeerConnection created', args[0]?.iceServers?.length ? `(${args[0].iceServers.length} ice servers)` : '');

        const _origAddTrack = pc.addTrack.bind(pc);
        pc.addTrack = function(track, ...streams) {
            console.log(`📡 addTrack: kind=${track.kind} label="${track.label}" id=${track.id} readyState=${track.readyState}`);
            if (track.kind === 'video') {
                console.log('📡 VIDEO TRACK ADDED TO PEER CONNECTION — this is what opponent receives');
            }
            return _origAddTrack(track, ...streams);
        };

        const _origAddStream = pc.addStream?.bind(pc);
        if (_origAddStream) {
            pc.addStream = function(stream) {
                console.log('📡 addStream:', stream.id,
                            stream.getVideoTracks().map(t => t.label));
                return _origAddStream(stream);
            };
        }

        const _origSetLD = pc.setLocalDescription.bind(pc);
        pc.setLocalDescription = function(desc) {
            if (desc?.sdp) {
                const videoLines = desc.sdp.split('\n').filter(l =>
                                                               l.startsWith('m=video') || l.startsWith('a=rtpmap') || l.startsWith('a=msid')
                                                              );
                console.log('📡 setLocalDescription (video lines):', videoLines);
            }
            return _origSetLD(desc);
        };

        pc.addEventListener('track', e => {
            console.log(`📡 REMOTE TRACK received: kind=${e.track.kind} label="${e.track.label}"`,
                        '— this is what YOU receive from opponent');
        });

        pc.addEventListener('connectionstatechange', () => {
            console.log('📡 PC connectionState:', pc.connectionState);
        });

        return pc;
    };
    Object.setPrototypeOf(window.RTCPeerConnection, _OrigRTCPC);
    window.RTCPeerConnection.prototype = _OrigRTCPC.prototype;

    // 3. Watch the scanner-video element — see when/how the game assigns a stream to it
    function watchScannerVideo() {
        const scannerVideo = document.querySelector('video.scanner-video');
        if (scannerVideo) {
            console.log('🔍 scanner-video found, watching srcObject...');
            // Watch for srcObject being set
            const _origSrcObj = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'srcObject');
            Object.defineProperty(scannerVideo, 'srcObject', {
                get() { return _origSrcObj.get.call(this); },
                set(stream) {
                    if (stream) {
                        console.log('🔍 scanner-video.srcObject SET:', stream?.id,
                                    '| video:', stream?.getVideoTracks?.().map(t => `${t.label} [${t.readyState}]`),
                                    '| audio:', stream?.getAudioTracks?.().map(t => t.label)
                                   );
                        console.log('🔍 This stream feeds the face scanner — replacing this = camera spoof');
                    }
                    _origSrcObj.set.call(this, stream);
                },
                configurable: true
            });
        } else {
            // Not in DOM yet — observe
            const obs = new MutationObserver(() => {
                const v = document.querySelector('video.scanner-video');
                if (v) { obs.disconnect(); watchScannerVideo(); }
            });
            obs.observe(document.body, { childList: true, subtree: true });
        }
    }
    watchScannerVideo();

    // 4. Intercept HTMLVideoElement.srcObject globally — catch ALL video element stream assignments
    const _origSrcObjDesc = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'srcObject');
    Object.defineProperty(HTMLMediaElement.prototype, 'srcObject', {
        get() { return _origSrcObjDesc.get.call(this); },
        set(stream) {
            if (this.tagName === 'VIDEO' && stream) {
                const classes = this.className || '(no class)';
                const tracks = stream?.getVideoTracks?.() || [];
                console.log(`🎞 video.srcObject SET [class="${classes}"]`,
                            `stream=${stream?.id}`,
                            `videoTracks:`, tracks.map(t => `${t.label} [${t.readyState}]`)
                           );
                if (classes.includes('scanner')) {
                    console.log('🎞 ↑ THIS IS THE SCANNER VIDEO — intercept here to replace camera feed');
                }
            }
            _origSrcObjDesc.set.call(this, stream);
        },
        configurable: true
    });

    // ── MENU ─────────────────────────────────────────────────────────────────
    function buildMenu() {
        if (document.getElementById('mog-root')) return;

        const style = document.createElement('style');
        const fontFaces = [
            ['Ebisu-Light', 300],
            ['Ebisu', 400],
            ['Ebisu-Bold', 700]
        ].map(([name, weight]) =>
              '@font-face{font-family:"Ebisu";src:url("https://github.com/sevkabevka/sevkabevka.github.io/raw/refs/heads/main/' + name + '.ttf") format("truetype");font-weight:' + weight + ';}'
             ).join('');
        style.textContent = fontFaces + `
            :root {
                --mog-accent: #80FF00;
                --mog-accent-rgb: 128,255,0;
            }
            #mog-btn {
                position: fixed; bottom: 20px; right: 20px; z-index: 999999;
                background: #050716; border: 2px solid #434464;
                color: var(--mog-accent); font-size: 11px; font-weight: 900; font-family: monospace;
                padding: 7px 13px; border-radius: 10px; cursor: pointer;
                letter-spacing: 0.12em; text-transform: uppercase;
                box-shadow: 0 0 18px rgba(67,68,100,0.4);
                backdrop-filter: blur(10px); transition: all 0.2s; user-select: none;
            }
            #mog-btn:hover { background: rgba(67,68,100,0.25); }
          #mog-root {
                position: fixed; bottom: auto; right: auto; top: 50%; left: 50%;
                transform: translate(-50%, -50%);
                z-index: 999999;
                width: 300px;
                background: #444782;
                border-radius: 16px;
                font-family: 'Ebisu', monospace; font-size: 11px; color: #e2d9f3;
                backdrop-filter: blur(20px); display: none; overflow: hidden;
                border: 2px solid #434464;
                box-shadow:
                    0 0 40px rgba(0,0,0,0.9),
                    0 12px 40px rgba(0,0,0,0.8);
            }
            #mog-root::before {
                content: '';
                position: absolute;
                top: 0;
                left: 0;
                width: 220px;
                height: 220px;
                border-radius: 0 0 100% 0;
                background: radial-gradient(circle at top left, rgba(37,38,63,1) 0%, rgba(37,38,63,0.5) 35%, transparent 70%);
                pointer-events: none;
                z-index: 0;
                overflow: hidden;
            }
            #mog-root::after {
                content: '';
                position: absolute;
                inset: 0;
                border-radius: 14px;
                background: #0d0f1e;
                z-index: -1;
                pointer-events: none;
            }
            #mog-header {
                padding: 12px 16px 0;
                background: transparent;
                border-bottom: none;
                border-radius: 14px 14px 0 0;
                position: relative; z-index: 1;
            }
            @keyframes mog-pulse {
                0%, 100% { opacity: 1; text-shadow: 0 0 8px var(--mog-accent), 0 0 18px var(--mog-accent), 0 0 32px rgba(var(--mog-accent-rgb),0.5); }
                50%       { opacity: 0.45; text-shadow: 0 0 4px var(--mog-accent), 0 0 8px rgba(var(--mog-accent-rgb),0.3); }
            }
            @keyframes mog-dot-pulse {
                0%, 100% { opacity: 1; box-shadow: 0 0 6px var(--mog-accent), 0 0 14px rgba(var(--mog-accent-rgb),0.6); }
                50%       { opacity: 0.35; box-shadow: 0 0 3px var(--mog-accent); }
            }
            #mog-title {
                font-size: 12px; font-weight: 900; letter-spacing: 0.2em;
                text-transform: uppercase;
                margin-bottom: 10px;
                display: flex;
                align-items: center;
                display: flex; align-items: center; gap: 7px;
                color: #ffffff;
                text-shadow: 0 0 6px rgba(255,255,255,0.15);
            }
            #mog-title .mog-lock {
                color: var(--mog-accent);
                animation: mog-pulse 2s ease-in-out infinite;
                display: inline;
                margin-left: auto;
                text-align: right;
            }
            #mog-title::before {
                content: '';
                display: inline-block;
                width: 8px; height: 8px;
                border-radius: 50%;
                background: var(--mog-accent);
                animation: mog-dot-pulse 2s ease-in-out infinite;
                flex-shrink: 0;
            }
            #mog-tabs-bar {
    background: #101426;
    border: 1px solid #434464;
    border-radius: 20px;
    display: flex;
    gap: 0px;
    padding: 5px 5px;
    margin-bottom: 12px;
    width: calc(100% + 16px);
    margin-left: -11px;
}
            #mog-tabs {
                display: contents;
            }
            .mog-tab {
                padding: 4px 10px; border-radius: 16px; font-size: 9px;
                font-weight: 900; text-transform: uppercase; letter-spacing: 0.15em;
                cursor: pointer; color: #878AA2;
                border: 1px solid transparent;
                transition: all 0.15s; background: transparent;
                flex: 1; text-align: center;
            }
            .mog-tab.active {
                color: #ffffff; background: #1D1E37;
                border-color: #433F74;
                border-radius: 16px;
            }
            .mog-tab:hover:not(.active) { color: rgba(255,255,255,0.7); }
            #mog-body {
                padding: 14px 16px 16px;
                display: grid;
                grid-template-rows: 1fr;
                position: relative; z-index: 1;
            }
            .mog-panel {
                display: none;
                opacity: 0;
                transform: translateY(6px);
            }
            .mog-panel.active {
                display: block;
            }
            #mog-root {
                transition: height 0.25s cubic-bezier(0.4,0,0.2,1),
                            opacity 0.2s ease,
                            transform 0.2s cubic-bezier(0.34,1.56,0.64,1);
            }
            .mog-label {
                font-size: 9px; font-weight: 900; text-transform: uppercase;
                letter-spacing: 0.18em; color: rgba(255,255,255,0.4); margin-bottom: 5px;
            }
            .mog-row {
                display: flex; align-items: center; justify-content: space-between;
                margin-bottom: 10px; gap: 8px;
            }
            .mog-row span {
                font-size: 10px; color: #c4b5fd; min-width: 40px; text-align: right;
            }
            .mog-slider {
                -webkit-appearance: none; flex: 1; height: 3px; border-radius: 2px;
                background: rgba(255,255,255,0.15); outline: none; cursor: pointer;
            }
            .mog-slider::-webkit-slider-thumb {
                -webkit-appearance: none; width: 12px; height: 12px;
                border-radius: 50%; background: #a78bfa; cursor: pointer;
                box-shadow: 0 0 6px rgba(167,139,250,0.8);
            }
            .mog-sep {
                border: none; border-top: 1px solid #434464;
                margin: 10px 0;
            }w
            .mog-status-row {
                display: flex; align-items: center; justify-content: space-between;
                margin-bottom: 6px;
            }
            .mog-badge {
                font-size: 9px; font-weight: 900; text-transform: uppercase;
                letter-spacing: 0.15em; padding: 3px 8px; border-radius: 6px;
            }
            .mog-badge.ranked { background: rgba(168,85,247,0.2); color: #d8b4fe; border: 1px solid rgba(168,85,247,0.4); }
            .mog-badge.normal { background: rgba(59,130,246,0.2); color: #93c5fd; border: 1px solid rgba(59,130,246,0.3); }
            .mog-badge.on { background: rgba(34,197,94,0.2); color: #86efac; border: 1px solid rgba(34,197,94,0.4); }
            .mog-badge.off { background: rgba(239,68,68,0.2); color: #fca5a5; border: 1px solid rgba(239,68,68,0.4); }
            .mog-score-preview {
                background: #12162B; border: 1px solid #434464;
                border-radius: 10px; padding: 10px 12px; margin-bottom: 10px;
            }
            .mog-score-big {
                font-size: 22px; font-weight: 900; letter-spacing: 0.05em;
            }
            .mog-score-tier {
                font-size: 9px; font-weight: 900; text-transform: uppercase;
                letter-spacing: 0.2em; margin-top: 2px;
            }
            .mog-toggle-row {
                display: flex; align-items: center; justify-content: space-between;
                margin-bottom: 8px;
            }
            .mog-toggle-label { font-size: 10px; color: #c4b5fd; }
            .mog-switch {
                position: relative; width: 32px; height: 18px; cursor: pointer;
            }
            .mog-switch input { opacity: 0; width: 0; height: 0; }
            .mog-switch-track {
                position: absolute; inset: 0; border-radius: 9px;
                background: rgba(255,255,255,0.12);
                transition: background 0.25s cubic-bezier(0.4,0,0.2,1),
                            box-shadow 0.25s ease;
            }
.mog-switch input:checked + .mog-switch-track {
                background: var(--mog-accent);
                box-shadow: 0 0 10px rgba(var(--mog-accent-rgb),0.6);
            }
            .mog-switch-thumb {
                position: absolute; top: 3px; left: 3px; width: 12px; height: 12px;
                border-radius: 50%; background: white;
                box-shadow: 0 1px 4px rgba(0,0,0,0.4);
                transition: left 0.25s cubic-bezier(0.34,1.56,0.64,1),
                            transform 0.2s ease;
            }
            .mog-switch input:checked ~ .mog-switch-thumb {
                left: 17px;
                transform: scale(1.1);
            }
            .mog-switch:hover .mog-switch-thumb { transform: scale(1.15); }
            .mog-switch input:checked:hover ~ .mog-switch-thumb { transform: scale(1.25); }
            .mog-feature-box {
                background: #12162B; border: 1px solid #434464;
                border-radius: 10px; margin-bottom: 12px; overflow: hidden;
            }
            .mog-feature-box-title {
                font-size: 9px; font-weight: 900; text-transform: uppercase;
                letter-spacing: 0.18em; color: #7C81A5; margin-bottom: 6px;
            }
            .mog-feature-row {
                display: flex; align-items: center; justify-content: space-between;
                padding: 8px 12px;
            }
            .mog-feature-row .mog-slider {
                max-width: 110px;
            }
            .mog-feature-box > .mog-feature-row:not(:last-child) {
                border-bottom: 1px solid #434464;
            }
            [data-panel="score"] .mog-slider::-webkit-slider-thumb {
                background: var(--mog-accent);
                box-shadow: 0 0 8px var(--mog-accent), 0 0 18px rgba(var(--mog-accent-rgb),0.5);
            }
            [data-panel="score"] .mog-feature-row div[style*="background:#181b30"] {
                border-color: #434464 !important;
            }
            [data-panel="fun"] .mog-slider::-webkit-slider-thumb {
                background: var(--mog-accent);
                box-shadow: 0 0 8px var(--mog-accent), 0 0 18px rgba(var(--mog-accent-rgb),0.5);
            }
            [data-panel="fun"] .mog-feature-row span.val {
                color: var(--mog-accent) !important;
                text-shadow: 0 0 8px var(--mog-accent), 0 0 18px rgba(var(--mog-accent-rgb),0.5);
            }
            [data-panel="misc"] .mog-slider::-webkit-slider-thumb {
                background: var(--mog-accent);
                box-shadow: 0 0 8px var(--mog-accent), 0 0 18px rgba(var(--mog-accent-rgb),0.5);
            }

            /* ── Panel alignment */
            .mog-panel {
                width: 100%;
                box-sizing: border-box;
            }
            .mog-feature-box {
                width: 100%;
                box-sizing: border-box;
            }
            .mog-feature-box-title {
                width: 100%;
                box-sizing: border-box;
            }

            /* ── Scrollable panels */
            [data-panel="fun"],
            [data-panel="misc"],
            [data-panel="score"] {
                max-height: 420px;
                overflow-y: auto;
                overflow-x: hidden;
                padding-right: 2px;
            }
            [data-panel="fun"]::-webkit-scrollbar,
            [data-panel="misc"]::-webkit-scrollbar,
            [data-panel="score"]::-webkit-scrollbar {
                width: 3px;
            }
            [data-panel="fun"]::-webkit-scrollbar-track,
            [data-panel="misc"]::-webkit-scrollbar-track,
            [data-panel="score"]::-webkit-scrollbar-track {
                background: transparent;
            }
            [data-panel="fun"]::-webkit-scrollbar-thumb,
            [data-panel="misc"]::-webkit-scrollbar-thumb,
            [data-panel="score"]::-webkit-scrollbar-thumb {
                background: rgba(var(--mog-accent-rgb),0.35);
                border-radius: 2px;
            }
            [data-panel="fun"]::-webkit-scrollbar-thumb:hover,
            [data-panel="misc"]::-webkit-scrollbar-thumb:hover,
            [data-panel="score"]::-webkit-scrollbar-thumb:hover {
                background: rgba(var(--mog-accent-rgb),0.65);
            }
        `;
        document.head.appendChild(style);

        // Toggle button
        const btn = document.createElement('button');
        btn.id = 'mog-btn';
        btn.textContent = 'hitlock | weedhook x jacobhook edition';
        document.body.appendChild(btn);

        // Menu root
        const root = document.createElement('div');
        root.id = 'mog-root';
        root.innerHTML = `
            <div id="mog-header">
                <div id="mog-title">HITLOCK<span class="mog-lock">weedhook x jacob edition</span></div>
                <div id="mog-tabs-bar">
                    <div id="mog-tabs" style="display:flex;gap:2px;width:100%;">
                        <div class="mog-tab active" data-tab="status">Status</div>
                        <div class="mog-tab" data-tab="score">Score</div>
                        <div class="mog-tab" data-tab="fun">Fun</div>
                        <div class="mog-tab" data-tab="misc">Misc</div>
                    </div>
                </div>
            </div>
            <hr style="border:none; border-top: 1px solid #433F74; margin: 0 0 0px 0;">
            <div id="mog-body">

                <!-- STATUS TAB -->
<div class="mog-panel active" data-panel="status">

    <div class="mog-feature-box-title">Live Score</div>
    <div class="mog-feature-box" style="padding:10px 12px;">
        <div class="mog-score-big" id="mog-live-score">—</div>
        <div class="mog-score-tier" id="mog-live-tier">Waiting for match...</div>
    </div>

    <div class="mog-feature-box-title">Status</div>
    <div class="mog-feature-box">
        <div class="mog-feature-row">
            <span class="mog-label" style="margin:0">Mode</span>
            <span id="mog-mode-badge" style="font-size:9px;font-weight:900;text-transform:uppercase;letter-spacing:0.15em;color:#93c5fd;">NORMAL</span>
        </div>
        <div class="mog-feature-row">
            <span class="mog-label" style="margin:0">Script</span>
            <span id="mog-enabled-badge" style="font-size:9px;font-weight:900;text-transform:uppercase;letter-spacing:0.15em;color:#86efac;">ENABLED</span>
        </div>
        <div class="mog-feature-row">
            <span class="mog-label" style="margin:0">Zustand</span>
            <span id="mog-zustand-badge" style="font-size:9px;font-weight:900;text-transform:uppercase;letter-spacing:0.15em;color:#fca5a5;">NOT PATCHED</span>
        </div>
    </div>

    <hr class="mog-sep">
    <div class="mog-toggle-row">
        <span class="mog-toggle-label">Enable script</span>
        <label class="mog-switch">
            <input type="checkbox" id="mog-enable-toggle" checked>
            <div class="mog-switch-track"></div>
            <div class="mog-switch-thumb"></div>
        </label>
    </div>
</div>

                <!-- SCORE TAB -->
                <div class="mog-panel" data-panel="score">
                    <div class="mog-feature-box-title">Live Boost</div>
                    <div class="mog-feature-box">
                        <!-- Mode selector -->
                        <div class="mog-feature-row">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Mode</span>
                            <div style="display:flex;gap:4px;">
                                <button class="mog-boost-mode-btn active" data-bmode="multiplier" style="padding:3px 8px;border-radius:6px;font-family:monospace;font-size:8px;font-weight:900;text-transform:uppercase;cursor:pointer;transition:all 0.2s;background:rgba(var(--mog-accent-rgb),0.15);color:var(--mog-accent);border:1px solid rgba(var(--mog-accent-rgb),0.4);">Mult</button>
                                <button class="mog-boost-mode-btn" data-bmode="range" style="padding:3px 8px;border-radius:6px;font-family:monospace;font-size:8px;font-weight:900;text-transform:uppercase;cursor:pointer;transition:all 0.2s;background:rgba(255,255,255,0.04);color:rgba(255,255,255,0.4);border:1px solid rgba(255,255,255,0.1);">Range</button>
                            </div>
                        </div>
                        <!-- Multiplier mode -->
                        <div id="mog-boost-mult-section">
                            <div class="mog-feature-row" style="gap:8px;">
                                <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Boost</span>
                                <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                                    <input type="range" class="mog-slider" id="mog-boost-slider" min="1.0" max="3.0" step="0.05" value="1.84" style="width:100%;margin:0;">
                                </div>
                                <span id="mog-boost-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">1.84x</span>
                            </div>
                        </div>
                        <!-- Range mode -->
                        <div id="mog-boost-range-section" style="display:none;">
                            <div class="mog-feature-row" style="gap:8px;">
                                <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Min</span>
                                <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                                    <input type="range" class="mog-slider" id="mog-boost-range-min" min="1.0" max="3.0" step="0.05" value="1.0" style="width:100%;margin:0;">
                                </div>
                                <span id="mog-boost-range-min-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">1.0x</span>
                            </div>
                            <div class="mog-feature-row" style="gap:8px;">
                                <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Max</span>
                                <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                                    <input type="range" class="mog-slider" id="mog-boost-range-max" min="1.0" max="3.0" step="0.05" value="2.5" style="width:100%;margin:0;">
                                </div>
                                <span id="mog-boost-range-max-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">2.5x</span>
                            </div>
                        </div>
                        <div class="mog-feature-row" style="gap:8px;">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Frame Cap</span>
                            <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                                <input type="range" class="mog-slider" id="mog-cap-slider" min="10000" max="99000" step="1000" value="99000" style="width:100%;margin:0;">
                            </div>
                            <span id="mog-cap-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">9.9</span>
                        </div>
                    </div>

                    <div class="mog-feature-box-title">Final Score</div>
                    <div class="mog-feature-box">
                        <!-- Mode selector -->
                        <!-- Mode selector -->
                        <div class="mog-feature-row">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Mode</span>
                            <div style="display:flex;gap:4px;">
                                <button class="mog-final-mode-btn active" data-fmode="fixed" style="padding:3px 7px;border-radius:6px;font-family:monospace;font-size:8px;font-weight:900;text-transform:uppercase;cursor:pointer;transition:all 0.2s;background:rgba(var(--mog-accent-rgb),0.15);color:var(--mog-accent);border:1px solid rgba(var(--mog-accent-rgb),0.4);">Fixed</button>
                                <button class="mog-final-mode-btn" data-fmode="range" style="padding:3px 7px;border-radius:6px;font-family:monospace;font-size:8px;font-weight:900;text-transform:uppercase;cursor:pointer;transition:all 0.2s;background:rgba(255,255,255,0.04);color:rgba(255,255,255,0.4);border:1px solid rgba(255,255,255,0.1);">Range</button>
                            </div>
                        </div>
                        <!-- Fixed mode -->
                        <div id="mog-final-fixed-section">
                            <div class="mog-feature-row" style="gap:8px;">
                                <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">My Score</span>
                                <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                                    <input type="range" class="mog-slider" id="mog-final-score" min="50000" max="99000" step="1000" value="94000" style="width:100%;margin:0;">
                                </div>
                                <span id="mog-final-score-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">9.4</span>
                            </div>
                        </div>
                        <!-- Range mode -->
                        <div id="mog-final-range-section" style="display:none;">
                            <div class="mog-feature-row" style="gap:8px;">
                                <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Min</span>
                                <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                                    <input type="range" class="mog-slider" id="mog-final-range-min" min="50000" max="99000" step="1000" value="85000" style="width:100%;margin:0;">
                                </div>
                                <span id="mog-final-range-min-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">8.5</span>
                            </div>
                            <div class="mog-feature-row" style="gap:8px;">
                                <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Max</span>
                                <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                                    <input type="range" class="mog-slider" id="mog-final-range-max" min="50000" max="99000" step="1000" value="97000" style="width:100%;margin:0;">
                                </div>
                                <span id="mog-final-range-max-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">9.7</span>
                            </div>
                        </div>
                        <div class="mog-feature-row" style="gap:8px;">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Opp Cap</span>
                            <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                                <input type="range" class="mog-slider" id="mog-opp-score" min="1000" max="50000" step="1000" value="15000" style="width:100%;margin:0;">
                            </div>
                            <span id="mog-opp-score-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">1.5</span>
                        </div>
                    </div>

                    <div class="mog-feature-box-title">Preview</div>
                    <div class="mog-feature-box" style="padding:10px 12px;">
                        <div class="mog-score-big" id="mog-score-preview-num" style="color:#ef4444">9.4</div>
                        <div class="mog-score-tier" id="mog-score-preview-tier" style="color:#ef4444">🍎 Adam</div>
                    </div>
                </div>

               <!-- FUN TAB -->
                <div class="mog-panel" data-panel="fun">

                    <div class="mog-feature-box-title">Camera Spoof</div>
                    <div class="mog-feature-box">
                        <div class="mog-feature-row">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Enable</span>
                            <label class="mog-switch">
                                <input type="checkbox" id="mog-camspoof-toggle">
                                <div class="mog-switch-track"></div>
                                <div class="mog-switch-thumb"></div>
                            </label>
                        </div>
                        <div class="mog-feature-row">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Source</span>
                            <div style="display:flex;gap:4px;">
                               <button class="mog-src-btn active" data-src="video" style="padding:3px 10px;border-radius:6px;font-family:monospace;font-size:8px;font-weight:900;text-transform:uppercase;letter-spacing:0.1em;cursor:pointer;transition:all 0.2s;background:rgba(var(--mog-accent-rgb),0.15);color:var(--mog-accent);border:1px solid rgba(var(--mog-accent-rgb),0.4);">Video</button>
<button class="mog-src-btn" data-src="image" style="padding:3px 10px;border-radius:6px;font-family:monospace;font-size:8px;font-weight:900;text-transform:uppercase;letter-spacing:0.1em;cursor:pointer;transition:all 0.2s;background:rgba(255,255,255,0.04);color:rgba(255,255,255,0.4);border:1px solid rgba(255,255,255,0.1);">Image</button>
                            </div>
                        </div>
                        <div class="mog-feature-row" id="mog-src-video-section">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">File</span>
                            <div id="mog-video-pick-btn" style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;cursor:pointer;overflow:hidden;">
                                <span id="mog-video-name" style="font-size:9px;color:rgba(255,255,255,0.35);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">📂 No file selected</span>
                            </div>
                            <input type="file" id="mog-video-input" accept="video/*" style="display:none">
                        </div>
                        <div class="mog-feature-row" id="mog-src-image-section" style="display:none;">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">File</span>
                            <div id="mog-image-pick-btn" style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;cursor:pointer;overflow:hidden;">
                                <span id="mog-image-name" style="font-size:9px;color:rgba(255,255,255,0.35);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;">📂 No file selected</span>
                            </div>
                            <input type="file" id="mog-image-input" accept="image/*" style="display:none">
                        </div>
                        <div class="mog-feature-row" style="gap:8px;">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Speed</span>
                            <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                                <input type="range" class="mog-slider" id="mog-camspeed" min="0.25" max="3.0" step="0.25" value="1.0" style="width:100%;margin:0;">
                            </div>
                            <span id="mog-camspeed-val" class="val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">1.0x</span>
                        </div>
                        <div class="mog-feature-row">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Loop</span>
                            <label class="mog-switch">
                                <input type="checkbox" id="mog-camloop-toggle" checked>
                                <div class="mog-switch-track"></div>
                                <div class="mog-switch-thumb"></div>
                            </label>
                        </div>
                        <div class="mog-feature-row">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Mirror</span>
                            <label class="mog-switch">
                                <input type="checkbox" id="mog-cammirror-toggle">
                                <div class="mog-switch-track"></div>
                                <div class="mog-switch-thumb"></div>
                            </label>
                        </div>
                    </div>

                    <div class="mog-feature-box-title">Overlays</div>
                    <div class="mog-feature-box">
                        <div class="mog-feature-row">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Ban</span>
                            <label class="mog-switch">
                                <input type="checkbox" id="mog-ban-overlay-toggle">
                                <div class="mog-switch-track"></div>
                                <div class="mog-switch-thumb"></div>
                            </label>
                        </div>
                        <div class="mog-feature-row">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Loading</span>
                            <label class="mog-switch">
                                <input type="checkbox" id="mog-loading-overlay-toggle">
                                <div class="mog-switch-track"></div>
                                <div class="mog-switch-thumb"></div>
                            </label>
                        </div>
                    </div>

                    <div class="mog-feature-box-title">Status</div>
                    <div class="mog-feature-box" style="padding:10px 12px;" id="mog-overlay-status">
                        <div style="font-size:9px;font-weight:900;text-transform:uppercase;letter-spacing:0.18em;color:#7C81A5;margin-bottom:4px;">Active overlay</div>
                        <div id="mog-overlay-status-text" style="font-size:14px;font-weight:900;color:rgba(255,255,255,0.3);">None active</div>
                    </div>
                    <div class="mog-feature-box-title">Particles</div>
                    <div class="mog-feature-box">
                        <div class="mog-feature-row">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Enable</span>
                            <label class="mog-switch">
                                <input type="checkbox" id="mog-particles-toggle">
                                <div class="mog-switch-track"></div>
                                <div class="mog-switch-thumb"></div>
                            </label>
                        </div>
                        <div class="mog-feature-row" style="gap:8px;">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Count</span>
                            <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                                <input type="range" class="mog-slider" id="mog-particles-count" min="10" max="300" step="10" value="80" style="width:100%;margin:0;">
                            </div>
                            <span id="mog-particles-count-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">80</span>
                        </div>
                        <div class="mog-feature-row" style="gap:8px;">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Size</span>
                            <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                                <input type="range" class="mog-slider" id="mog-particles-size" min="1" max="20" step="1" value="5" style="width:100%;margin:0;">
                            </div>
                            <span id="mog-particles-size-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">5px</span>
                        </div>
                        <div class="mog-feature-row" style="gap:8px;">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Speed</span>
                            <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                                <input type="range" class="mog-slider" id="mog-particles-speed" min="0.2" max="5.0" step="0.2" value="1.0" style="width:100%;margin:0;">
                            </div>
                            <span id="mog-particles-speed-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">1.0x</span>
                        </div>
                        <div class="mog-feature-row" style="gap:8px;">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Drift</span>
                            <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                                <input type="range" class="mog-slider" id="mog-particles-drift" min="0" max="3.0" step="0.1" value="0.5" style="width:100%;margin:0;">
                            </div>
                            <span id="mog-particles-drift-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">0.5</span>
                        </div>
                        <div class="mog-feature-row" style="gap:8px;">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Opacity</span>
                            <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                                <input type="range" class="mog-slider" id="mog-particles-opacity" min="5" max="100" step="5" value="70" style="width:100%;margin:0;">
                            </div>
                            <span id="mog-particles-opacity-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">70%</span>
                        </div>
                        <div class="mog-feature-row" style="gap:8px;">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Color</span>
                            <input type="color" id="mog-particles-color" value="#ffffff" style="width:28px;height:20px;border:none;background:none;cursor:pointer;border-radius:4px;">
                            <span class="mog-label" style="margin:0 0 0 8px;white-space:nowrap;">Rainbow</span>
                            <label class="mog-switch" style="margin-left:4px;">
                                <input type="checkbox" id="mog-particles-rainbow">
                                <div class="mog-switch-track"></div>
                                <div class="mog-switch-thumb"></div>
                            </label>
                        </div>
                        <div class="mog-feature-row" style="gap:8px;">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Shape</span>
                            <div style="display:flex;gap:4px;flex-wrap:wrap;">
                                <button class="mog-shape-btn active" data-shape="circle" style="padding:3px 7px;border-radius:6px;font-family:monospace;font-size:8px;font-weight:900;text-transform:uppercase;cursor:pointer;transition:all 0.2s;background:rgba(var(--mog-accent-rgb),0.15);color:var(--mog-accent);border:1px solid rgba(var(--mog-accent-rgb),0.4);">●</button>
                                <button class="mog-shape-btn" data-shape="star" style="padding:3px 7px;border-radius:6px;font-family:monospace;font-size:8px;font-weight:900;text-transform:uppercase;cursor:pointer;transition:all 0.2s;background:rgba(255,255,255,0.04);color:rgba(255,255,255,0.4);border:1px solid rgba(255,255,255,0.1);">★</button>
                                <button class="mog-shape-btn" data-shape="square" style="padding:3px 7px;border-radius:6px;font-family:monospace;font-size:8px;font-weight:900;text-transform:uppercase;cursor:pointer;transition:all 0.2s;background:rgba(255,255,255,0.04);color:rgba(255,255,255,0.4);border:1px solid rgba(255,255,255,0.1);">■</button>
                                <button class="mog-shape-btn" data-shape="heart" style="padding:3px 7px;border-radius:6px;font-family:monospace;font-size:8px;font-weight:900;text-transform:uppercase;cursor:pointer;transition:all 0.2s;background:rgba(255,255,255,0.04);color:rgba(255,255,255,0.4);border:1px solid rgba(255,255,255,0.1);">♥</button>
                            </div>
                        </div>
                        <div class="mog-feature-row" style="gap:8px;">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Glow</span>
                            <label class="mog-switch">
                                <input type="checkbox" id="mog-particles-glow" checked>
                                <div class="mog-switch-track"></div>
                                <div class="mog-switch-thumb"></div>
                            </label>
                            <span class="mog-label" style="margin:0 0 0 10px;white-space:nowrap;">Wobble</span>
                            <label class="mog-switch" style="margin-left:4px;">
                                <input type="checkbox" id="mog-particles-wobble" checked>
                                <div class="mog-switch-track"></div>
                                <div class="mog-switch-thumb"></div>
                            </label>
                        </div>
                    </div>

                </div>

                <!-- MISC TAB -->
                <div class="mog-panel" data-panel="misc">

                    <div class="mog-feature-box-title">Boost</div>
<div class="mog-feature-box">
    <div class="mog-feature-row">
        <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Mode</span>
        <div style="display:flex;gap:4px;">
            <button class="mog-mode-btn active" data-mode="button" style="padding:3px 10px;border-radius:6px;font-family:'Ebisu',monospace;font-size:8px;font-weight:900;text-transform:uppercase;letter-spacing:0.1em;cursor:pointer;transition:all 0.2s;background:rgba(var(--mog-accent-rgb),0.15);color:var(--mog-accent);border:1px solid rgba(var(--mog-accent-rgb),0.4);">🖱 Button</button>
            <button class="mog-mode-btn" data-mode="bind" style="padding:3px 10px;border-radius:6px;font-family:'Ebisu',monospace;font-size:8px;font-weight:900;text-transform:uppercase;letter-spacing:0.1em;cursor:pointer;transition:all 0.2s;background:rgba(255,255,255,0.04);color:rgba(255,255,255,0.4);border:1px solid rgba(255,255,255,0.1);">⌨ Bind</button>
        </div>
    </div>
    <div id="mog-hold-btn-settings">
        <div class="mog-feature-row">
            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Color</span>
            <input type="color" id="mog-holdcolor" value="#7c3aed" style="width:28px;height:20px;border:none;background:none;cursor:pointer;border-radius:4px;">
            <span class="mog-label" style="margin:0 4px 0 8px;">Alpha</span>
            <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                <input type="range" class="mog-slider" id="mog-holdalpha" min="10" max="100" step="5" value="80" style="width:100%;margin:0;">
            </div>
            <span id="mog-holdalpha-val" style="font-size:10px;color:var(--mog-accent);min-width:32px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">80%</span>
        </div>
        <div class="mog-feature-row" style="gap:8px;">
            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Size</span>
            <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                <input type="range" class="mog-slider" id="mog-holdsize" min="30" max="120" step="2" value="54" style="width:100%;margin:0;">
            </div>
            <span id="mog-holdsize-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">54px</span>
        </div>
    </div>
    <div id="mog-hold-bind-settings" style="display:none;">
        <div class="mog-feature-row" style="gap:8px;">
            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Key</span>
            <input type="text" id="mog-holdkey" placeholder="Click then press key..." style="flex:1;background:#181b30;border:1px solid #1a3a28;border-radius:6px;padding:2px 8px;color:#c4b5fd;font-family:'Ebisu',monospace;font-size:10px;outline:none;transition:border-color 0.2s;height:22px;">
            <button id="mog-holdkey-clear" style="margin-left:4px;padding:2px 8px;background:rgba(239,68,68,0.15);border:1px solid rgba(239,68,68,0.3);border-radius:6px;color:#fca5a5;font-family:'Ebisu',monospace;font-size:9px;cursor:pointer;">CLR</button>
        </div>
    </div>
    <div class="mog-feature-row" style="gap:8px;">
        <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Boost %</span>
        <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
            <input type="range" class="mog-slider" id="mog-holdpct" min="5" max="200" step="5" value="50" style="width:100%;margin:0;">
        </div>
        <span id="mog-holdpct-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">+50%</span>
    </div>
    <div class="mog-feature-row" style="gap:8px;">
        <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Random ±</span>
        <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
            <input type="range" class="mog-slider" id="mog-holdrand" min="0" max="50" step="1" value="10" style="width:100%;margin:0;">
        </div>
        <span id="mog-holdrand-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">±10%</span>
    </div>
    <div class="mog-feature-row" style="gap:8px;">
        <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Ramp ms</span>
        <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
            <input type="range" class="mog-slider" id="mog-holddur" min="100" max="3000" step="100" value="1000" style="width:100%;margin:0;">
        </div>
        <span id="mog-holddur-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">1000ms</span>
    </div>
</div>



                    <div class="mog-feature-box-title">Toggles</div>
                    <div class="mog-feature-box">
                        <div class="mog-feature-row">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Frames</span>
                            <label class="mog-switch">
                                <input type="checkbox" id="mog-boost-toggle" checked>
                                <div class="mog-switch-track"></div>
                                <div class="mog-switch-thumb"></div>
                            </label>
                        </div>
                        <div class="mog-feature-row">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Finalize</span>
                            <label class="mog-switch">
                                <input type="checkbox" id="mog-finalize-toggle" checked>
                                <div class="mog-switch-track"></div>
                                <div class="mog-switch-thumb"></div>
                            </label>
                        </div>
                        <div class="mog-feature-row">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Debug</span>
                            <label class="mog-switch">
                                <input type="checkbox" id="mog-debug-toggle" checked>
                                <div class="mog-switch-track"></div>
                                <div class="mog-switch-thumb"></div>
                            </label>
                        </div>
                    </div>
<div class="mog-feature-box-title">Appearance</div>
                    <div class="mog-feature-box">
                        <div class="mog-feature-row">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Accent</span>
                            <input type="color" id="mog-accent-color" value="#80FF00" style="width:28px;height:20px;border:none;background:none;cursor:pointer;border-radius:4px;">
                            <span class="mog-label" style="margin:0 0 0 10px;white-space:nowrap;min-width:48px;">Preview</span>
                            <span id="mog-accent-preview" style="font-size:9px;font-weight:900;letter-spacing:0.15em;color:var(--mog-accent);text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">●  ACTIVE</span>
                        </div>
                    </div>

                    <div class="mog-feature-box-title">Watermark</div>
                    <div class="mog-feature-box">
                        <div class="mog-feature-row">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Show</span>
                            <label class="mog-switch">
                                <input type="checkbox" id="mog-wm-show" checked>
                                <div class="mog-switch-track"></div>
                                <div class="mog-switch-thumb"></div>
                            </label>
                        </div>
                        <div class="mog-feature-row" style="gap:8px;">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Alpha</span>
                            <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                                <input type="range" class="mog-slider" id="mog-wm-alpha" min="0" max="100" step="5" value="20" style="width:100%;margin:0;">
                            </div>
                            <span id="mog-wm-alpha-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">20%</span>
                        </div>
                        <div class="mog-feature-row" style="gap:8px;">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Font Size</span>
                            <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                                <input type="range" class="mog-slider" id="mog-wm-size" min="7" max="18" step="1" value="9" style="width:100%;margin:0;">
                            </div>
                            <span id="mog-wm-size-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">9px</span>
                        </div>
                        <div class="mog-feature-row" style="gap:8px;">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Padding</span>
                            <div style="flex:1;background:#181b30;border-radius:6px;padding:0 8px;height:22px;display:flex;align-items:center;border:1px solid #1a3a28;">
                                <input type="range" class="mog-slider" id="mog-wm-padding" min="2" max="20" step="1" value="14" style="width:100%;margin:0;">
                            </div>
                            <span id="mog-wm-padding-val" style="font-size:10px;color:var(--mog-accent);min-width:36px;text-align:right;text-shadow:0 0 8px rgba(var(--mog-accent-rgb),0.6);">14px</span>
                        </div>
                        <div class="mog-feature-row">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Background</span>
                            <label class="mog-switch">
                                <input type="checkbox" id="mog-wm-bg" checked>
                                <div class="mog-switch-track"></div>
                                <div class="mog-switch-thumb"></div>
                            </label>
                            <span class="mog-label" style="margin:0 0 0 10px;white-space:nowrap;">Border</span>
                            <label class="mog-switch" style="margin-left:4px;">
                                <input type="checkbox" id="mog-wm-border" checked>
                                <div class="mog-switch-track"></div>
                                <div class="mog-switch-thumb"></div>
                            </label>
                        </div>
                    </div>
                    <div class="mog-feature-box-title">Menu Keybind</div>
                    <div class="mog-feature-box">
                        <div class="mog-feature-row" style="gap:8px;">
                            <span class="mog-label" style="margin:0;white-space:nowrap;min-width:72px;">Toggle Key</span>
                            <input type="text" id="mog-menukey" placeholder="key..." value="h" style="width:38px;flex:none;background:#181b30;border:1px solid #1a3a28;border-radius:6px;padding:2px 8px;color:#c4b5fd;font-family:'Ebisu',monospace;font-size:10px;outline:none;transition:border-color 0.2s;height:22px;text-align:center;">
                            <button id="mog-menukey-clear" style="margin-left:4px;padding:2px 8px;background:rgba(239,68,68,0.15);border:1px solid rgba(239,68,68,0.3);border-radius:6px;color:#fca5a5;font-family:'Ebisu',monospace;font-size:9px;cursor:pointer;flex-shrink:0;">CLR</button>
                        </div>
                    </div>


            </div>

        `;
        document.body.appendChild(root);

        // Fix initial panel opacity — CSS sets opacity:0 on all panels including active
        const initialPanel = root.querySelector('.mog-panel.active');
        if (initialPanel) {
            initialPanel.style.opacity = '1';
            initialPanel.style.transform = 'translateY(0)';
        }

        // ── Wire up toggle button
        root.style.transition = 'opacity 0.2s ease, transform 0.2s cubic-bezier(0.34,1.56,0.64,1)';
        root.style.transformOrigin = 'center center';

        // Center on screen by default
        root.style.display = 'block';
        root.style.bottom = 'auto';
        root.style.right = 'auto';
        root.style.top = '50%';
        root.style.left = '50%';
        root.style.transform = 'translate(-50%, -50%) scale(1)';
        root.style.opacity = '1';
        root.style.transformOrigin = 'center center';

        // ── Menu drag ─────────────────────────────────────────────────────────
        let _menuDragging = false, _menuDragOffX = 0, _menuDragOffY = 0;
        // Use header as drag handle
        const _menuHeader = root.querySelector('#mog-header');
        _menuHeader.style.cursor = 'grab';
        _menuHeader.addEventListener('mousedown', function(e) {
            if (e.target.matches('input, button, label, .mog-tab')) return;
            _menuDragging = true;
            const rect = root.getBoundingClientRect();
            _menuDragOffX = e.clientX - rect.left;
            _menuDragOffY = e.clientY - rect.top;
            root.style.transition = 'opacity 0.2s ease';
            e.preventDefault();
        });
        document.addEventListener('mousemove', function(e) {
            if (!_menuDragging) return;
            const x = e.clientX - _menuDragOffX;
            const y = e.clientY - _menuDragOffY;
            root.style.left = x + 'px';
            root.style.top = y + 'px';
            root.style.transform = 'none';
        });
        document.addEventListener('mouseup', function() {
            if (_menuDragging) {
                _menuDragging = false;
                _menuHeader.style.cursor = 'grab';
            }
        });
        _menuHeader.addEventListener('touchstart', function(e) {
            if (e.target.matches('input, button, label, .mog-tab')) return;
            _menuDragging = true;
            const rect = root.getBoundingClientRect();
            _menuDragOffX = e.touches[0].clientX - rect.left;
            _menuDragOffY = e.touches[0].clientY - rect.top;
        }, { passive: true });
        document.addEventListener('touchmove', function(e) {
            if (!_menuDragging) return;
            const x = e.touches[0].clientX - _menuDragOffX;
            const y = e.touches[0].clientY - _menuDragOffY;
            root.style.left = x + 'px';
            root.style.top = y + 'px';
            root.style.transform = 'none';
        }, { passive: true });
        document.addEventListener('touchend', function() { _menuDragging = false; });

        function _toggleMenu() {
            const _wasDragged = root.style.transform === 'none';
            if (root.style.display === 'none' || root.style.display === '') {
                root.style.display = 'block';
                root.style.opacity = '0';
                if (!_wasDragged) root.style.transform = 'translate(-50%, -50%) scale(0.92)';
                requestAnimationFrame(() => {
                    root.style.opacity = '1';
                    if (!_wasDragged) root.style.transform = 'translate(-50%, -50%) scale(1)';
                });
            } else {
                root.style.opacity = '0';
                setTimeout(() => { root.style.display = 'none'; }, 200);
            }
        }

        btn.addEventListener('click', _toggleMenu);

        // H-key toggle (default), configurable
        let _menuKey = 'KeyH';
        document.addEventListener('keydown', function(e) {
            if (e.code === _menuKey && !e.target.matches('input[type="text"], input[type="search"], textarea')) {
                _toggleMenu();
            }
        });

        // Add transition style to panels
        let _tabSwitching = false;

        function measureHeight(panel) {
            const prevDisplay = panel.style.display;
            const prevVisibility = panel.style.visibility;
            const prevPosition = panel.style.position;
            panel.style.display = 'block';
            panel.style.visibility = 'hidden';
            panel.style.position = 'relative';
            const h = panel.offsetHeight;
            panel.style.display = prevDisplay;
            panel.style.visibility = prevVisibility;
            panel.style.position = prevPosition;
            return h;
        }

        function switchTab(tabName) {
            if (_tabSwitching) return;
            const current = root.querySelector('.mog-panel.active');
            const next = root.querySelector(`[data-panel="${tabName}"]`);
            if (!next || current === next) return;

            _tabSwitching = true;

            const body = document.getElementById('mog-body');
            const currentH = current ? current.offsetHeight : 0;

            // Update tab active state immediately
            root.querySelectorAll('.mog-tab').forEach(t => t.classList.remove('active'));
            root.querySelector(`.mog-tab[data-tab="${tabName}"]`).classList.add('active');

            // Phase 1: fade current out
            if (current) {
                current.style.transition = 'opacity 0.15s ease, transform 0.15s ease';
                current.style.opacity = '0';
                current.style.transform = 'translateY(-5px)';
            }

            // Lock body height at current value
            body.style.height = currentH + 'px';
            body.style.overflow = 'hidden';
            body.style.transition = 'none';

            setTimeout(() => {
                // Hide current
                if (current) {
                    current.classList.remove('active');
                    current.style.display = 'none';
                }

                // Show next hidden
                next.style.display = 'block';
                next.style.visibility = 'hidden';
                next.style.opacity = '0';
                next.style.transform = 'translateY(5px)';
                next.style.transition = 'none';
                next.classList.add('active');

                // Release body to auto so it adopts natural height including padding
                body.style.transition = 'none';
                body.style.overflow = 'visible';
                body.style.height = 'auto';

                // Measure the body's true natural height
                void body.offsetHeight;
                const targetH = body.offsetHeight;

                // Re-lock to currentH before animating
                body.style.overflow = 'hidden';
                body.style.height = currentH + 'px';
                void body.offsetHeight;

                next.style.visibility = '';

                // Animate body height to exact natural value
                body.style.transition = 'height 0.25s cubic-bezier(0.4,0,0.2,1)';
                body.style.height = targetH + 'px';

                // Fade next in
                setTimeout(() => {
                    next.style.transition = 'opacity 0.18s ease, transform 0.18s ease';
                    next.style.opacity = '1';
                    next.style.transform = 'translateY(0)';
                }, 60);

                // Cleanup — auto matches targetH exactly so no jump
                setTimeout(() => {
                    body.style.transition = 'none';
                    body.style.overflow = '';
                    body.style.height = 'auto';
                    _tabSwitching = false;
                }, 280);

            }, 160);
        }

        root.querySelectorAll('.mog-tab').forEach(tab => {
            tab.addEventListener('click', () => switchTab(tab.dataset.tab));
        });

        // ── Enable toggle
        document.getElementById('mog-enable-toggle').addEventListener('change', function() {
            CONFIG.enabled = this.checked;
            document.getElementById('mog-enabled-badge').textContent = this.checked ? 'ENABLED' : 'DISABLED';
            document.getElementById('mog-enabled-badge').style.color = this.checked ? '#86efac' : '#fca5a5';
        });

        // ── Final score slider
        document.getElementById('mog-final-score').addEventListener('input', function() {
            CONFIG.myFinalScore = this.value;
            const v = (parseInt(this.value) / 10000).toFixed(1);
            document.getElementById('mog-final-score-val').textContent = v;
            updateScorePreview();
        });

        // ── Hold tab sliders
        document.getElementById('mog-holdpct').addEventListener('input', function() {
            CONFIG.boostPercent = parseInt(this.value);
            document.getElementById('mog-holdpct-val').textContent = '+' + this.value + '%';
        });
        document.getElementById('mog-holdrand').addEventListener('input', function() {
            CONFIG.boostRandom = parseInt(this.value);
            document.getElementById('mog-holdrand-val').textContent = '±' + this.value + '%';
        });
        document.getElementById('mog-holddur').addEventListener('input', function() {
            CONFIG.boostDuration = parseInt(this.value);
            document.getElementById('mog-holddur-val').textContent = this.value + 'ms';
        });

        // ── Mode toggle (button vs bind)
        let _holdMode = 'button'; // 'button' | 'bind'
        document.querySelectorAll('.mog-mode-btn').forEach(btn => {
            btn.addEventListener('click', function() {
                _holdMode = this.dataset.mode;
                document.querySelectorAll('.mog-mode-btn').forEach(b => {
                    const isActive = b.dataset.mode === _holdMode;
                    b.style.background = isActive ? 'rgba(var(--mog-accent-rgb),0.15)' : 'rgba(255,255,255,0.04)';
                    b.style.color = isActive ? 'var(--mog-accent)' : 'rgba(255,255,255,0.4)';
                    b.style.borderColor = isActive ? 'rgba(var(--mog-accent-rgb),0.4)' : 'rgba(255,255,255,0.1)';
                });
                const btnSettings = document.getElementById('mog-hold-btn-settings');
                const bindSettings = document.getElementById('mog-hold-bind-settings');
                if (_holdMode === 'button') {
                    holdBtn.style.opacity = '1';
                    holdBtn.style.pointerEvents = 'auto';
                    holdBtn.style.transform = 'scale(1)';
                    btnSettings.style.maxHeight = '200px';
                    btnSettings.style.opacity = '1';
                    bindSettings.style.maxHeight = '0';
                    bindSettings.style.opacity = '0';
                    setTimeout(() => { bindSettings.style.display = 'none'; btnSettings.style.display = 'block'; }, 200);
                } else {
                    holdBtn.style.opacity = '0';
                    holdBtn.style.pointerEvents = 'none';
                    holdBtn.style.transform = 'scale(0.8)';
                    bindSettings.style.display = 'block';
                    btnSettings.style.maxHeight = '0';
                    btnSettings.style.opacity = '0';
                    setTimeout(() => {
                        btnSettings.style.display = 'none';
                        bindSettings.style.maxHeight = '200px';
                        bindSettings.style.opacity = '1';
                    }, 10);
                }
            });
        });

        // Animate the settings sections
        const btnSettingsEl = document.getElementById('mog-hold-btn-settings');
        const bindSettingsEl = document.getElementById('mog-hold-bind-settings');
        btnSettingsEl.style.cssText += 'max-height:200px;opacity:1;overflow:hidden;transition:max-height 0.25s ease,opacity 0.2s ease;';
        bindSettingsEl.style.cssText += 'max-height:0;opacity:0;overflow:hidden;transition:max-height 0.25s ease,opacity 0.2s ease;';

        // ── Draggable hold button
        let _holdBtnColor = '#7c3aed';
        let _holdBtnAlpha = 0.8;
        let _holdKey = null;

        const holdBtn = document.createElement('div');
        holdBtn.id = 'mog-hold-btn';
        holdBtn.textContent = '📈';
        holdBtn.style.cssText = `
            position: fixed; bottom: 20px; left: 20px; z-index: 999998;
            width: ${CONFIG.holdBtnSize}px; height: ${CONFIG.holdBtnSize}px;
            border-radius: ${Math.round(CONFIG.holdBtnSize * 0.26)}px;
            background: rgba(124,58,237,0.8);
            border: 1px solid rgba(255,255,255,0.2);
            box-shadow: 0 0 20px rgba(124,58,237,0.4);
            display: flex; align-items: center; justify-content: center;
            font-size: ${Math.round(CONFIG.holdBtnSize * 0.4)}px;
            cursor: pointer; user-select: none;
            backdrop-filter: blur(10px);
            transition: box-shadow 0.3s ease, transform 0.3s cubic-bezier(0.34,1.56,0.64,1), opacity 0.3s ease, width 0.2s ease, height 0.2s ease, border-radius 0.2s ease, font-size 0.2s ease;
        `;
        document.body.appendChild(holdBtn);

        // ── WATERMARK ─────────────────────────────────────────────────────────
        const _wm = document.createElement('div');
        _wm.id = 'mog-watermark';
        _wm.textContent = 'hitlock client | cracked by @42pz (left github open)';
        function applyWmStyle() {
            const rect = _wm ? _wm.getBoundingClientRect() : null;
            const hasDragged = _wm && _wm.style.left !== '' && _wm.style.left !== 'auto';
            _wm.style.cssText = `
                position: fixed;
                ${hasDragged
                    ? `left: ${rect.left}px; top: ${rect.top}px;`
                    : 'bottom: 80px; right: 20px;'}
                z-index: 999997;
                padding: ${CONFIG.wmPaddingV}px ${CONFIG.wmPaddingH}px;
                border-radius: 10px;
                background: ${CONFIG.wmBg ? `rgba(var(--mog-accent-rgb),${CONFIG.wmAlpha / 100})` : 'transparent'};
                border: ${CONFIG.wmBorder ? '1px solid rgba(var(--mog-accent-rgb),0.3)' : 'none'};
                backdrop-filter: blur(10px);
                -webkit-backdrop-filter: blur(10px);
                color: rgba(255,255,255,0.35);
                font-family: monospace;
                font-size: ${CONFIG.wmFontSize}px;
                font-weight: 700;
                letter-spacing: 0.1em;
                white-space: nowrap;
                cursor: grab;
                user-select: none;
                pointer-events: auto;
            `;
        }
        applyWmStyle();
        document.body.appendChild(_wm);

        // Watermark drag
        let _wmDragging = false, _wmDragOffX = 0, _wmDragOffY = 0;
        _wm.addEventListener('mousedown', function(e) {
            _wmDragging = true;
            _wmDragOffX = e.clientX - _wm.getBoundingClientRect().left;
            _wmDragOffY = e.clientY - _wm.getBoundingClientRect().top;
            _wm.style.cursor = 'grabbing';
            e.preventDefault();
        });
        document.addEventListener('mousemove', function(e) {
            if (!_wmDragging) return;
            _wm.style.left = (e.clientX - _wmDragOffX) + 'px';
            _wm.style.top = (e.clientY - _wmDragOffY) + 'px';
            _wm.style.bottom = 'auto';
            _wm.style.right = 'auto';
        });
        document.addEventListener('mouseup', function() {
            if (_wmDragging) { _wmDragging = false; _wm.style.cursor = 'grab'; }
        });
        _wm.addEventListener('touchstart', function(e) {
            _wmDragging = true;
            _wmDragOffX = e.touches[0].clientX - _wm.getBoundingClientRect().left;
            _wmDragOffY = e.touches[0].clientY - _wm.getBoundingClientRect().top;
        }, { passive: true });
        document.addEventListener('touchmove', function(e) {
            if (!_wmDragging) return;
            _wm.style.left = (e.touches[0].clientX - _wmDragOffX) + 'px';
            _wm.style.top = (e.touches[0].clientY - _wmDragOffY) + 'px';
            _wm.style.bottom = 'auto';
            _wm.style.right = 'auto';
        }, { passive: true });
        document.addEventListener('touchend', function() { _wmDragging = false; });

        function updateHoldBtnStyle() {
            const r = parseInt(_holdBtnColor.slice(1,3),16);
            const g = parseInt(_holdBtnColor.slice(3,5),16);
            const b = parseInt(_holdBtnColor.slice(5,7),16);
            holdBtn.style.background = `rgba(${r},${g},${b},${_holdBtnAlpha})`;
            holdBtn.style.boxShadow = _boostHeld
                ? `0 0 45px rgba(${r},${g},${b},0.95), 0 0 15px rgba(${r},${g},${b},0.6)`
            : `0 0 20px rgba(${r},${g},${b},0.4)`;
        }

        document.getElementById('mog-holdcolor').addEventListener('input', function() {
            _holdBtnColor = this.value;
            updateHoldBtnStyle();
        });
        document.getElementById('mog-holdalpha').addEventListener('input', function() {
            _holdBtnAlpha = parseInt(this.value) / 100;
            document.getElementById('mog-holdalpha-val').textContent = this.value + '%';
            updateHoldBtnStyle();
        });
        document.getElementById('mog-holdsize').addEventListener('input', function() {
            const sz = parseInt(this.value);
            CONFIG.holdBtnSize = sz;
            document.getElementById('mog-holdsize-val').textContent = sz + 'px';
            holdBtn.style.width = sz + 'px';
            holdBtn.style.height = sz + 'px';
            holdBtn.style.borderRadius = Math.round(sz * 0.26) + 'px';
            holdBtn.style.fontSize = Math.round(sz * 0.4) + 'px';
        });

        // Drag logic
        let _dragging = false, _dragOffX = 0, _dragOffY = 0, _dragMoved = false;
        holdBtn.addEventListener('mousedown', function(e) {
            _dragging = true; _dragMoved = false;
            _dragOffX = e.clientX - holdBtn.getBoundingClientRect().left;
            _dragOffY = e.clientY - holdBtn.getBoundingClientRect().top;
            e.preventDefault();
        });
        document.addEventListener('mousemove', function(e) {
            if (!_dragging) return;
            _dragMoved = true;
            holdBtn.style.left = (e.clientX - _dragOffX) + 'px';
            holdBtn.style.top  = (e.clientY - _dragOffY) + 'px';
            holdBtn.style.bottom = 'auto';
        });
        document.addEventListener('mouseup', function() { _dragging = false; });

        holdBtn.addEventListener('touchstart', function(e) {
            _dragging = true; _dragMoved = false;
            const t = e.touches[0];
            _dragOffX = t.clientX - holdBtn.getBoundingClientRect().left;
            _dragOffY = t.clientY - holdBtn.getBoundingClientRect().top;
        }, { passive: true });
        document.addEventListener('touchmove', function(e) {
            if (!_dragging) return;
            _dragMoved = true;
            const t = e.touches[0];
            holdBtn.style.left = (t.clientX - _dragOffX) + 'px';
            holdBtn.style.top  = (t.clientY - _dragOffY) + 'px';
            holdBtn.style.bottom = 'auto';
        }, { passive: true });
        document.addEventListener('touchend', function() { _dragging = false; });

        // Hold press logic
        function startHold() {
            if (_boostHeld) return;
            _boostHeld = true;
            holdBtn.style.transform = 'scale(0.88)';
            updateHoldBtnStyle();
            rampBoost(true);
        }
        function endHold() {
            if (!_boostHeld) return;
            _boostHeld = false;
            holdBtn.style.transform = 'scale(1)';
            updateHoldBtnStyle();
            rampBoost(false);
        }

        holdBtn.addEventListener('mousedown', function(e) {
            setTimeout(() => { if (!_dragMoved) startHold(); }, 80);
        });
        document.addEventListener('mouseup', function() {
            if (_boostHeld && _holdMode === 'button') endHold();
        });
        holdBtn.addEventListener('touchstart', function() {
            setTimeout(() => { if (!_dragMoved) startHold(); }, 80);
        }, { passive: true });
        document.addEventListener('touchend', function() {
            if (_boostHeld && _holdMode === 'button') endHold();
        });

        // ── Key bind
        const keyInput = document.getElementById('mog-holdkey');
        let _listeningForKey = false;
        keyInput.addEventListener('focus', function() {
            _listeningForKey = true;
            this.value = '— press a key —';
            this.style.borderColor = '#c084fc';
            this.style.color = '#c084fc';
        });
        keyInput.addEventListener('keydown', function(e) {
            if (!_listeningForKey) return;
            e.preventDefault();
            _holdKey = e.code;
            this.value = e.key === ' ' ? 'Space' : e.key;
            this.style.borderColor = 'rgba(34,197,94,0.5)';
            this.style.color = '#86efac';
            _listeningForKey = false;
            this.blur();
        });
        document.getElementById('mog-holdkey-clear').addEventListener('click', function() {
            _holdKey = null;
            keyInput.value = '';
            keyInput.style.borderColor = 'rgba(255,255,255,0.12)';
            keyInput.style.color = '#c4b5fd';
        });
        document.addEventListener('keydown', function(e) {
            if (_holdMode === 'bind' && _holdKey && e.code === _holdKey && !e.repeat) startHold();
        });
        document.addEventListener('keyup', function(e) {
            if (_holdMode === 'bind' && _holdKey && e.code === _holdKey) endHold();
        });

        // ── Opp score slider
        document.getElementById('mog-opp-score').addEventListener('input', function() {
            CONFIG.oppFinalScore = this.value;
            document.getElementById('mog-opp-score-val').textContent = (parseInt(this.value) / 10000).toFixed(2);
        });

        // ── Boost slider
        document.getElementById('mog-boost-slider').addEventListener('input', function() {
            CONFIG.myScoreBoost = parseFloat(this.value);
            document.getElementById('mog-boost-val').textContent = CONFIG.myScoreBoost.toFixed(2) + 'x';
        });

        // ── Live boost mode toggle
        function setBoostModeUI(mode) {
            CONFIG.boostMode = mode;
            document.querySelectorAll('.mog-boost-mode-btn').forEach(b => {
                const on = b.dataset.bmode === mode;
                b.style.background = on ? 'rgba(var(--mog-accent-rgb),0.15)' : 'rgba(255,255,255,0.04)';
                b.style.color = on ? 'var(--mog-accent)' : 'rgba(255,255,255,0.4)';
                b.style.borderColor = on ? 'rgba(var(--mog-accent-rgb),0.4)' : 'rgba(255,255,255,0.1)';
            });
            const multSec = document.getElementById('mog-boost-mult-section');
            const rangeSec = document.getElementById('mog-boost-range-section');
            if (mode === 'multiplier') {
                multSec.style.display = 'block'; rangeSec.style.display = 'none';
            } else {
                multSec.style.display = 'none'; rangeSec.style.display = 'block';
            }
        }
        document.querySelectorAll('.mog-boost-mode-btn').forEach(b => {
            b.addEventListener('click', function() { setBoostModeUI(this.dataset.bmode); });
        });
        document.getElementById('mog-boost-range-min').addEventListener('input', function() {
            CONFIG.boostRangeMin = parseFloat(this.value);
            document.getElementById('mog-boost-range-min-val').textContent = CONFIG.boostRangeMin.toFixed(2) + 'x';
        });
        document.getElementById('mog-boost-range-max').addEventListener('input', function() {
            CONFIG.boostRangeMax = parseFloat(this.value);
            document.getElementById('mog-boost-range-max-val').textContent = CONFIG.boostRangeMax.toFixed(2) + 'x';
        });

        // ── Final score mode toggle
        function setFinalModeUI(mode) {
            CONFIG.finalScoreMode = mode;
            document.querySelectorAll('.mog-final-mode-btn').forEach(b => {
                const on = b.dataset.fmode === mode;
                b.style.background = on ? 'rgba(var(--mog-accent-rgb),0.15)' : 'rgba(255,255,255,0.04)';
                b.style.color = on ? 'var(--mog-accent)' : 'rgba(255,255,255,0.4)';
                b.style.borderColor = on ? 'rgba(var(--mog-accent-rgb),0.4)' : 'rgba(255,255,255,0.1)';
            });
            document.getElementById('mog-final-fixed-section').style.display = mode === 'fixed' ? 'block' : 'none';
            document.getElementById('mog-final-range-section').style.display = mode === 'range' ? 'block' : 'none';
            updateScorePreview();
        }
        document.querySelectorAll('.mog-final-mode-btn').forEach(b => {
            b.addEventListener('click', function() { setFinalModeUI(this.dataset.fmode); });
        });
        document.getElementById('mog-final-range-min').addEventListener('input', function() {
            CONFIG.finalScoreRangeMin = parseInt(this.value);
            document.getElementById('mog-final-range-min-val').textContent = (CONFIG.finalScoreRangeMin / 10000).toFixed(1);
            updateScorePreview();
        });
        document.getElementById('mog-final-range-max').addEventListener('input', function() {
            CONFIG.finalScoreRangeMax = parseInt(this.value);
            document.getElementById('mog-final-range-max-val').textContent = (CONFIG.finalScoreRangeMax / 10000).toFixed(1);
            updateScorePreview();
        });
        // Range preview randomizer — fires every 2s when in range mode
        setInterval(() => {
            if (CONFIG.finalScoreMode === 'range') updateScorePreview();
        }, 2000);

        // ── Cap slider
        // ── Cap slider — writes directly to CONFIG so send intercept reads it
        document.getElementById('mog-cap-slider').addEventListener('input', function() {
            CONFIG.frameCap = parseInt(this.value);
            document.getElementById('mog-cap-val').textContent = (CONFIG.frameCap / 10000).toFixed(1);
            // Force Zustand setMyScore to re-read the new cap immediately
            _lockedFinalTarget = null;
        });

        // ── Boost frame toggle
        let _boostFrames = true;
        document.getElementById('mog-boost-toggle').addEventListener('change', function() {
            _boostFrames = this.checked;
        });

        // ── Finalize toggle
        let _boostFinalize = true;
        document.getElementById('mog-finalize-toggle').addEventListener('change', function() {
            _boostFinalize = this.checked;
        });

        // ── Debug toggle
        document.getElementById('mog-debug-toggle').addEventListener('change', function() {
            CONFIG.debug = this.checked;
        });

        // ── Menu keybind
        const menuKeyInput = document.getElementById('mog-menukey');
        let _menuKeyListening = false;
        menuKeyInput.addEventListener('focus', function() {
            _menuKeyListening = true;
            this.value = '— press a key —';
            this.style.borderColor = '#c084fc';
            this.style.color = '#c084fc';
        });
        menuKeyInput.addEventListener('keydown', function(e) {
            if (!_menuKeyListening) return;
            e.preventDefault();
            _menuKey = e.code;
            this.value = e.key === ' ' ? 'Space' : e.key;
            this.style.borderColor = 'rgba(34,197,94,0.5)';
            this.style.color = '#86efac';
            _menuKeyListening = false;
            this.blur();
        });
        // ── Accent color picker
        function setAccentColor(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);
            document.documentElement.style.setProperty('--mog-accent', hex);
            document.documentElement.style.setProperty('--mog-accent-rgb', `${r},${g},${b}`);
            // also update mog-btn green text
            const mogBtn = document.getElementById('mog-btn');
            if (mogBtn) mogBtn.style.color = hex;
        }
        document.getElementById('mog-accent-color').addEventListener('input', function() {
            setAccentColor(this.value);
        });

        // ── Watermark controls
        document.getElementById('mog-wm-show').addEventListener('change', function() {
            _wm.style.display = this.checked ? 'block' : 'none';
        });
        document.getElementById('mog-wm-alpha').addEventListener('input', function() {
            CONFIG.wmAlpha = parseInt(this.value);
            document.getElementById('mog-wm-alpha-val').textContent = this.value + '%';
            applyWmStyle();
        });
        document.getElementById('mog-wm-size').addEventListener('input', function() {
            CONFIG.wmFontSize = parseInt(this.value);
            document.getElementById('mog-wm-size-val').textContent = this.value + 'px';
            applyWmStyle();
        });
        document.getElementById('mog-wm-padding').addEventListener('input', function() {
            CONFIG.wmPaddingH = parseInt(this.value);
            CONFIG.wmPaddingV = Math.max(2, Math.round(parseInt(this.value) * 0.43));
            document.getElementById('mog-wm-padding-val').textContent = this.value + 'px';
            applyWmStyle();
        });
        document.getElementById('mog-wm-bg').addEventListener('change', function() {
            CONFIG.wmBg = this.checked;
            applyWmStyle();
        });
        document.getElementById('mog-wm-border').addEventListener('change', function() {
            CONFIG.wmBorder = this.checked;
            applyWmStyle();
        });
        document.getElementById('mog-menukey-clear').addEventListener('click', function() {
            _menuKey = null;
            menuKeyInput.value = '';
            menuKeyInput.style.borderColor = 'rgba(255,255,255,0.12)';
            menuKeyInput.style.color = '#c4b5fd';
        });

        // ── Score preview updater
        function updateScorePreview() {
            let score;
            if (CONFIG.finalScoreMode === 'range') {
                score = Math.round(CONFIG.finalScoreRangeMin + Math.random() * (CONFIG.finalScoreRangeMax - CONFIG.finalScoreRangeMin)) / 10000;
            } else {
                score = parseInt(CONFIG.myFinalScore) / 10000;
            }
            const tier = getTierForScore(score);
            const numEl = document.getElementById('mog-score-preview-num');
            const tierEl = document.getElementById('mog-score-preview-tier');
            numEl.textContent = score.toFixed(1);
            numEl.style.color = tier.hexColor;
            numEl.style.textShadow = tier.textShadow;
            tierEl.textContent = `${tier.emoji} ${tier.name}`;
            tierEl.style.color = tier.hexColor;
            tierEl.style.textShadow = tier.textShadow;
        }
        updateScorePreview();

        // ── Sync all slider display values on init
        document.getElementById('mog-final-score-val').textContent = (parseInt(CONFIG.myFinalScore) / 10000).toFixed(1);
        document.getElementById('mog-opp-score-val').textContent = (parseInt(CONFIG.oppFinalScore) / 10000).toFixed(2);
        document.getElementById('mog-boost-val').textContent = CONFIG.myScoreBoost.toFixed(2) + 'x';
        document.getElementById('mog-cap-val').textContent = (CONFIG.frameCap / 10000).toFixed(1);
        document.getElementById('mog-holdpct-val').textContent = '+' + CONFIG.boostPercent + '%';
        document.getElementById('mog-holdrand-val').textContent = '±' + CONFIG.boostRandom + '%';
        document.getElementById('mog-holddur-val').textContent = CONFIG.boostDuration + 'ms';

        // ── Hold tab sliders

        // ── Live status updater (runs every 200ms)
        setInterval(() => {
            // Mode badge
            const modeBadge = document.getElementById('mog-mode-badge');
            if (modeBadge) {
                modeBadge.textContent = _isRanked ? 'RANKED' : 'NORMAL';
                modeBadge.style.color = _isRanked ? '#d8b4fe' : '#93c5fd';
            }

            // Live score display
            // Hold multiplier status
            const multEl = document.getElementById('mog-hold-mult');
            if (multEl) multEl.textContent = _boostMultiplier.toFixed(3) + 'x';

            // Live score display
            if (_lastSpoofedScore !== null) {
                const tier = getTierForScore(_lastSpoofedScore);
                const liveScore = document.getElementById('mog-live-score');
                const liveTier = document.getElementById('mog-live-tier');
                if (liveScore) {
                    liveScore.textContent = _lastSpoofedScore.toFixed(2);
                    liveScore.style.color = tier.hexColor;
                    liveScore.style.textShadow = tier.textShadow;
                }
                if (liveTier) {
                    liveTier.textContent = `${tier.emoji} ${tier.name}`;
                    liveTier.style.color = tier.hexColor;
                }
            }
        }, 200);

        // ── Patch lastFinalize and lastFrame display — hook into existing log
        window._mogUpdateDebug = function(type, text) {
            // debug panel removed — no-op
        };

        // ── Camera spoof ──────────────────────────────────────────────────────
        let _camSpoofActive = false;
        let _camSrcType = 'video';
        let _origAddTrack = null;
        let _camSrcObjPatch = null;

        // Track all RTCPeerConnections so we can replaceTrack on them
        window._mogPCs = window._mogPCs || [];
        const _OrigPC2 = window.RTCPeerConnection;
        window.RTCPeerConnection = function(...args) {
            const pc = new _OrigPC2(...args);
            window._mogPCs.push(pc);
            pc.addEventListener('connectionstatechange', () => {
                if (pc.connectionState === 'closed') {
                    const idx = window._mogPCs.indexOf(pc);
                    if (idx > -1) window._mogPCs.splice(idx, 1);
                }
            });
            return pc;
        };
        Object.setPrototypeOf(window.RTCPeerConnection, _OrigPC2);
        window.RTCPeerConnection.prototype = _OrigPC2.prototype;
        let _camVideoFile = null;
        let _camImageFile = null;
        let _camMirror = false;
        let _camLoop = true;
        let _camSpeed = 1.0;
        let _camStream = null;
        let _camVideoEl = null;
        let _camCanvasEl = null;
        let _origGetUserMedia = null;

        // Source type toggle
        document.querySelectorAll('.mog-src-btn').forEach(b => {
            b.addEventListener('click', function() {
                _camSrcType = this.dataset.src;
                document.querySelectorAll('.mog-src-btn').forEach(x => {
                    const on = x.dataset.src === _camSrcType;
                    x.style.background = on ? 'rgba(var(--mog-accent-rgb),0.15)' : 'rgba(255,255,255,0.04)';
                    x.style.color = on ? 'var(--mog-accent)' : 'rgba(255,255,255,0.4)';
                    x.style.borderColor = on ? 'rgba(var(--mog-accent-rgb),0.4)' : 'rgba(255,255,255,0.1)';
                });
                const vs = document.getElementById('mog-src-video-section');
                const is = document.getElementById('mog-src-image-section');
                if (_camSrcType === 'video') {
                    vs.style.display = 'flex'; is.style.display = 'none';
                } else {
                    vs.style.display = 'none'; is.style.display = 'flex';
                }
            });
        });

        // File pickers
        document.getElementById('mog-video-pick-btn').addEventListener('click', () => {
            document.getElementById('mog-video-input').click();
        });
        document.getElementById('mog-video-input').addEventListener('change', function() {
            if (this.files[0]) {
                _camVideoFile = this.files[0];
                const nameEl = document.getElementById('mog-video-name');
                const fn = this.files[0].name;
                nameEl.textContent = fn.slice(0, 5) + (fn.length > 5 ? '...' : '');
                nameEl.style.color = '#86efac';
            }
        });
        document.getElementById('mog-image-pick-btn').addEventListener('click', () => {
            document.getElementById('mog-image-input').click();
        });
        document.getElementById('mog-image-input').addEventListener('change', function() {
            if (this.files[0]) {
                _camImageFile = this.files[0];
                const nameEl = document.getElementById('mog-image-name');
                nameEl.textContent = this.files[0].name;
                nameEl.style.color = '#86efac';
            }
        });

        // Options
        document.getElementById('mog-camloop-toggle').addEventListener('change', function() {
            _camLoop = this.checked;
            if (_camVideoEl) _camVideoEl.loop = _camLoop;
        });
        document.getElementById('mog-camspeed').addEventListener('input', function() {
            _camSpeed = parseFloat(this.value);
            document.getElementById('mog-camspeed-val').textContent = _camSpeed.toFixed(2) + 'x';
            if (_camVideoEl) _camVideoEl.playbackRate = _camSpeed;
        });
        document.getElementById('mog-cammirror-toggle').addEventListener('change', function() {
            _camMirror = this.checked;
        });

        function setCamStatus(text, color) {
            const el = document.getElementById('mog-camstatus-text');
            if (el) { el.textContent = text; el.style.color = color || 'rgba(255,255,255,0.3)'; }
        }

        function buildFakeStream() {
            _camCanvasEl = document.createElement('canvas');
            _camCanvasEl.width = 640; _camCanvasEl.height = 480;
            const ctx = _camCanvasEl.getContext('2d');

            if (_camSrcType === 'video' && _camVideoFile) {
                _camVideoEl = document.createElement('video');
                _camVideoEl.src = URL.createObjectURL(_camVideoFile);
                _camVideoEl.loop = _camLoop;
                _camVideoEl.muted = true;
                _camVideoEl.playbackRate = _camSpeed;
                _camVideoEl.play().catch(() => {});

                function drawFrame() {
                    if (!_camSpoofActive) return;
                    ctx.save();
                    if (_camMirror) { ctx.translate(640, 0); ctx.scale(-1, 1); }
                    ctx.drawImage(_camVideoEl, 0, 0, 640, 480);
                    ctx.restore();
                    requestAnimationFrame(drawFrame);
                }
                _camVideoEl.addEventListener('canplay', () => { drawFrame(); }, { once: true });

            } else if (_camSrcType === 'image' && _camImageFile) {
                const img = new Image();
                img.src = URL.createObjectURL(_camImageFile);
                img.onload = () => {
                    function drawStatic() {
                        if (!_camSpoofActive) return;
                        ctx.save();
                        if (_camMirror) { ctx.translate(640, 0); ctx.scale(-1, 1); }
                        ctx.drawImage(img, 0, 0, 640, 480);
                        ctx.restore();
                        requestAnimationFrame(drawStatic);
                    }
                    drawStatic();
                };
            } else {
                setCamStatus('No file selected', '#fca5a5');
                return null;
            }

            return _camCanvasEl.captureStream(30);
        }

        function startCamSpoof() {
            const fakeStream = buildFakeStream();
            if (!fakeStream) return;
            _camStream = fakeStream;

            // ── Level 1: patch getUserMedia so the game gets our fake stream
            // from the start — affects scanner-video and LiveKit track
            if (!_origGetUserMedia) {
                _origGetUserMedia = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);
            }
            navigator.mediaDevices.getUserMedia = async function(constraints) {
                if (constraints && (constraints.video || constraints.video === true)) {
                    setCamStatus('Active (getUserMedia)', '#86efac');
                    if (constraints.audio) {
                        try {
                            const realAudio = await _origGetUserMedia({ audio: constraints.audio });
                            return new MediaStream([
                                ..._camStream.getVideoTracks(),
                                ...realAudio.getAudioTracks()
                            ]);
                        } catch(e) {
                            return _camStream;
                        }
                    }
                    return _camStream;
                }
                return _origGetUserMedia(constraints);
            };

            // ── Level 2: if the game already has scanner-video running,
            // swap its srcObject directly right now
            const scannerVid = document.querySelector('video.scanner-video');
            if (scannerVid && scannerVid.srcObject) {
                console.log('🎥 Direct scanner-video swap');
                scannerVid.srcObject = _camStream;
                setCamStatus('Active (direct swap)', '#86efac');
            }

            // ── Level 3: intercept every future srcObject assignment on
            // scanner-video so if it restarts it still gets our stream
            const _srcObjDesc = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'srcObject');
            _camSrcObjPatch = function(stream) {
                if (this.classList?.contains('scanner-video') && stream && _camSpoofActive) {
                    console.log('🎥 scanner-video srcObject intercepted — replacing with fake stream');
                    setCamStatus('Active (intercepted)', '#86efac');
                    _srcObjDesc.set.call(this, _camStream);
                    return;
                }
                _srcObjDesc.set.call(this, stream);
            };
            Object.defineProperty(HTMLMediaElement.prototype, 'srcObject', {
                get() { return _srcObjDesc.get.call(this); },
                set: _camSrcObjPatch,
                configurable: true
            });

            // ── Level 4: patch RTCPeerConnection.addTrack so LiveKit sends
            // our fake video track instead of the real camera track
            if (!_origAddTrack) {
                _origAddTrack = RTCPeerConnection.prototype.addTrack;
                RTCPeerConnection.prototype.addTrack = function(track, ...streams) {
                    if (track.kind === 'video' && _camSpoofActive && _camStream) {
                        const fakeTrack = _camStream.getVideoTracks()[0];
                        if (fakeTrack) {
                            console.log('🎥 RTCPeerConnection.addTrack — swapping real video for fake');
                            setCamStatus('Active (LiveKit patched)', '#86efac');
                            return _origAddTrack.call(this, fakeTrack, ...streams);
                        }
                    }
                    return _origAddTrack.call(this, track, ...streams);
                };
            }

            // ── Level 5: for already-established LiveKit connections,
            // find any active RTCSenders and replace their track
            try {
                // LiveKit creates RTCPeerConnections — iterate all of them
                // by watching the prototype we already patched; but for any
                // existing senders we need to call replaceTrack directly
                const fakeTrack = _camStream.getVideoTracks()[0];
                if (fakeTrack && window._mogPCs) {
                    for (const pc of window._mogPCs) {
                        pc.getSenders().forEach(sender => {
                            if (sender.track?.kind === 'video') {
                                sender.replaceTrack(fakeTrack).then(() => {
                                    console.log('🎥 replaceTrack success on existing sender');
                                    setCamStatus('Active (replaceTrack)', '#86efac');
                                }).catch(e => console.warn('replaceTrack failed:', e));
                            }
                        });
                    }
                }
            } catch(e) {}
        }

        function stopCamSpoof() {
            // Restore getUserMedia first, save ref before nulling
            const savedGetUserMedia = _origGetUserMedia;
            if (_origGetUserMedia) {
                navigator.mediaDevices.getUserMedia = _origGetUserMedia;
                _origGetUserMedia = null;
            }
            // Restore srcObject interception
            if (_camSrcObjPatch) {
                const _srcObjDesc = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'srcObject');
                Object.defineProperty(HTMLMediaElement.prototype, 'srcObject', {
                    get() { return _srcObjDesc.get.call(this); },
                    set(v) { _srcObjDesc.set.call(this, v); },
                    configurable: true
                });
                _camSrcObjPatch = null;
            }
            // Restore addTrack
            if (_origAddTrack) {
                RTCPeerConnection.prototype.addTrack = _origAddTrack;
                _origAddTrack = null;
            }
            if (_camVideoEl) { _camVideoEl.pause(); _camVideoEl = null; }
            if (_camStream) { _camStream.getTracks().forEach(t => t.stop()); _camStream = null; }
            _camSpoofActive = false;

            // Give real camera back to scanner-video and all senders
            const base = savedGetUserMedia || navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);
            base({ video: true }).then(realStream => {
                const realTrack = realStream.getVideoTracks()[0];
                // Restore scanner-video
                const scannerVid = document.querySelector('video.scanner-video');
                if (scannerVid) scannerVid.srcObject = realStream;
                // Restore peer connection senders
                if (realTrack && window._mogPCs) {
                    for (const pc of window._mogPCs) {
                        pc.getSenders().forEach(sender => {
                            if (sender.track?.kind === 'video') {
                                sender.replaceTrack(realTrack).catch(() => {});
                            }
                        });
                    }
                }
            }).catch(() => {});

            setCamStatus('Inactive', 'rgba(255,255,255,0.3)');
        }

        // ── PARTICLE ENGINE ───────────────────────────────────────────────────
        const _particleCfg = {
            active: false,
            count: 80,
            size: 5,
            speed: 1.0,
            drift: 0.5,
            opacity: 70,
            color: '#ffffff',
            rainbow: false,
            shape: 'circle',
            glow: true,
            wobble: true
        };
        let _particleCanvas = null;
        let _particleCtx = null;
        let _particleRAF = null;
        let _particles = [];

        function _makeParticle() {
            return {
                x: Math.random() * window.innerWidth,
                y: -20 - Math.random() * window.innerHeight,
                r: (_particleCfg.size * 0.5) + Math.random() * _particleCfg.size * 0.8,
                vy: (1.0 + Math.random() * 1.5) * _particleCfg.speed,
                vx: (Math.random() - 0.5) * _particleCfg.drift,
                wobblePhase: Math.random() * Math.PI * 2,
                wobbleSpeed: 0.01 + Math.random() * 0.03,
                wobbleAmp: 0.5 + Math.random() * 2.0,
                hue: Math.random() * 360,
                alpha: 0.3 + Math.random() * 0.7
            };
        }

        function _drawShape(ctx, p, color) {
            const s = p.r;
            ctx.fillStyle = color;
            ctx.strokeStyle = color;
            if (_particleCfg.glow) {
                ctx.shadowColor = color;
                ctx.shadowBlur = s * 2.5;
            } else {
                ctx.shadowBlur = 0;
            }
            ctx.beginPath();
            switch (_particleCfg.shape) {
                case 'circle':
                    ctx.arc(p.x, p.y, s, 0, Math.PI * 2);
                    ctx.fill();
                    break;
                case 'square':
                    ctx.fillRect(p.x - s, p.y - s, s * 2, s * 2);
                    break;
                case 'star': {
                    const spikes = 5, outer = s, inner = s * 0.45;
                    let rot = (Math.PI / 2) * 3;
                    const step = Math.PI / spikes;
                    ctx.moveTo(p.x, p.y - outer);
                    for (let i = 0; i < spikes; i++) {
                        ctx.lineTo(p.x + Math.cos(rot) * outer, p.y + Math.sin(rot) * outer); rot += step;
                        ctx.lineTo(p.x + Math.cos(rot) * inner, p.y + Math.sin(rot) * inner); rot += step;
                    }
                    ctx.lineTo(p.x, p.y - outer);
                    ctx.fill();
                    break;
                }
                case 'heart': {
                    const hs = s * 0.9;
                    ctx.moveTo(p.x, p.y + hs * 0.6);
                    ctx.bezierCurveTo(p.x - hs * 1.2, p.y - hs * 0.4, p.x - hs * 2.2, p.y + hs * 0.6, p.x, p.y + hs * 1.8);
                    ctx.bezierCurveTo(p.x + hs * 2.2, p.y + hs * 0.6, p.x + hs * 1.2, p.y - hs * 0.4, p.x, p.y + hs * 0.6);
                    ctx.fill();
                    break;
                }
            }
        }

        function _particleLoop() {
            if (!_particleCfg.active) return;
            const W = window.innerWidth, H = window.innerHeight;
            if (_particleCanvas.width !== W) _particleCanvas.width = W;
            if (_particleCanvas.height !== H) _particleCanvas.height = H;
            _particleCtx.clearRect(0, 0, W, H);

            // ensure count matches
            while (_particles.length < _particleCfg.count) _particles.push(_makeParticle());
            while (_particles.length > _particleCfg.count) _particles.pop();

            for (const p of _particles) {
                p.wobblePhase += p.wobbleSpeed;
                if (_particleCfg.wobble) p.x += Math.sin(p.wobblePhase) * p.wobbleAmp;
                p.x += p.vx;
                p.y += p.vy;
                if (p.y > H + 30) {
                    p.y = -20; p.x = Math.random() * W;
                    p.vx = (Math.random() - 0.5) * _particleCfg.drift;
                    p.hue = Math.random() * 360;
                }
                const baseAlpha = (_particleCfg.opacity / 100) * p.alpha;
                let color;
                if (_particleCfg.rainbow) {
                    color = `hsla(${p.hue},100%,70%,${baseAlpha})`;
                    p.hue = (p.hue + 0.3) % 360;
                } else {
                    const hex = _particleCfg.color;
                    const r = parseInt(hex.slice(1,3),16);
                    const g = parseInt(hex.slice(3,5),16);
                    const b = parseInt(hex.slice(5,7),16);
                    color = `rgba(${r},${g},${b},${baseAlpha})`;
                }
                _particleCtx.globalAlpha = 1;
                _drawShape(_particleCtx, p, color);
            }
            _particleRAF = requestAnimationFrame(_particleLoop);
        }

        function startParticles() {
            if (_particleCanvas) { stopParticles(); }
            _particleCanvas = document.createElement('canvas');
            _particleCanvas.style.cssText = 'position:fixed;top:0;left:0;width:100vw;height:100vh;pointer-events:none;z-index:999990;';
            document.body.appendChild(_particleCanvas);
            _particleCtx = _particleCanvas.getContext('2d');
            _particles = Array.from({ length: _particleCfg.count }, _makeParticle);
            // spread vertically so they don't all arrive at once
            _particles.forEach((p, i) => { p.y = Math.random() * window.innerHeight; });
            _particleCfg.active = true;
            _particleLoop();
        }

        function stopParticles() {
            _particleCfg.active = false;
            if (_particleRAF) { cancelAnimationFrame(_particleRAF); _particleRAF = null; }
            if (_particleCanvas) { _particleCanvas.remove(); _particleCanvas = null; _particleCtx = null; }
            _particles = [];
        }

        // Wire up particle controls
        document.getElementById('mog-particles-toggle').addEventListener('change', function() {
            if (this.checked) startParticles(); else stopParticles();
        });
        document.getElementById('mog-particles-count').addEventListener('input', function() {
            _particleCfg.count = parseInt(this.value);
            document.getElementById('mog-particles-count-val').textContent = this.value;
        });
        document.getElementById('mog-particles-size').addEventListener('input', function() {
            _particleCfg.size = parseInt(this.value);
            document.getElementById('mog-particles-size-val').textContent = this.value + 'px';
        });
        document.getElementById('mog-particles-speed').addEventListener('input', function() {
            _particleCfg.speed = parseFloat(this.value);
            document.getElementById('mog-particles-speed-val').textContent = parseFloat(this.value).toFixed(1) + 'x';
            // Update existing particles' velocity to reflect new speed immediately
            _particles.forEach(p => {
                p.vy = (1.0 + Math.random() * 1.5) * _particleCfg.speed;
            });
        });
        document.getElementById('mog-particles-drift').addEventListener('input', function() {
            _particleCfg.drift = parseFloat(this.value);
            document.getElementById('mog-particles-drift-val').textContent = parseFloat(this.value).toFixed(1);
        });
        document.getElementById('mog-particles-opacity').addEventListener('input', function() {
            _particleCfg.opacity = parseInt(this.value);
            document.getElementById('mog-particles-opacity-val').textContent = this.value + '%';
        });
        document.getElementById('mog-particles-color').addEventListener('input', function() {
            _particleCfg.color = this.value;
        });
        document.getElementById('mog-particles-rainbow').addEventListener('change', function() {
            _particleCfg.rainbow = this.checked;
        });
        document.getElementById('mog-particles-glow').addEventListener('change', function() {
            _particleCfg.glow = this.checked;
        });
        document.getElementById('mog-particles-wobble').addEventListener('change', function() {
            _particleCfg.wobble = this.checked;
        });
        document.querySelectorAll('.mog-shape-btn').forEach(b => {
            b.addEventListener('click', function() {
                _particleCfg.shape = this.dataset.shape;
                document.querySelectorAll('.mog-shape-btn').forEach(x => {
                    const on = x.dataset.shape === _particleCfg.shape;
                    x.style.background = on ? 'rgba(var(--mog-accent-rgb),0.15)' : 'rgba(255,255,255,0.04)';
                    x.style.color = on ? 'var(--mog-accent)' : 'rgba(255,255,255,0.4)';
                    x.style.borderColor = on ? 'rgba(var(--mog-accent-rgb),0.4)' : 'rgba(255,255,255,0.1)';
                });
            });
        });

        // ── OVERLAY IMAGES (ban + loading) ────────────────────────────────────
        const OVERLAY_URLS = {
            ban:     'https://raw.githubusercontent.com/sevkabevka/sevkabevka.github.io/main/ChatGPT%20Image%2023%20%D0%BC%D0%B0%D1%8F%202026%20%D0%B3.,%2019_13_02.png',
            loading: 'https://raw.githubusercontent.com/sevkabevka/sevkabevka.github.io/main/ChatGPT%20Image%2023%20%D0%BC%D0%B0%D1%8F%202026%20%D0%B3.,%2017_59_13_Nero_AI_Image_Upscaler_Photo_Face.png'
        };

        let _overlayActive = null; // 'ban' | 'loading' | null
        let _overlayImg = { ban: null, loading: null };
        let _overlayCanvas = null;
        let _overlayStream = null;
        let _overlayRAF = null;

        // Preload both images immediately
        ['ban', 'loading'].forEach(key => {
            const img = new Image();
            img.crossOrigin = 'anonymous';
            img.src = OVERLAY_URLS[key];
            img.onload = () => { _overlayImg[key] = img; console.log(`🖼 Overlay [${key}] loaded`); };
            img.onerror = () => console.warn(`⚠️ Overlay [${key}] failed to load`);
        });

        function setOverlayStatus(text, color) {
            const el = document.getElementById('mog-overlay-status-text');
            if (el) { el.textContent = text; el.style.color = color || 'rgba(255,255,255,0.3)'; }
        }

        function buildOverlayStream(key) {
            const img = _overlayImg[key];
            if (!img) {
                setOverlayStatus(`${key} image not loaded yet`, '#fca5a5');
                return null;
            }
            _overlayCanvas = document.createElement('canvas');
            _overlayCanvas.width = 640;
            _overlayCanvas.height = 480;
            const ctx = _overlayCanvas.getContext('2d');

            function drawOverlay() {
                if (!_overlayActive) return;
                ctx.save();
                ctx.translate(640, 0);
                ctx.scale(-1, 1);
                ctx.drawImage(img, 0, 0, 640, 480);
                ctx.restore();
                _overlayRAF = requestAnimationFrame(drawOverlay);
            }
            drawOverlay();
            return _overlayCanvas.captureStream(30);
        }

        function _pushTrackToAll(stream) {
            const track = stream ? stream.getVideoTracks()[0] : null;
            if (!track) return;
            // scanner-video
            const scannerVid = document.querySelector('video.scanner-video');
            if (scannerVid) scannerVid.srcObject = stream;
            // all active peer connection senders
            if (window._mogPCs) {
                for (const pc of window._mogPCs) {
                    try {
                        pc.getSenders().forEach(sender => {
                            if (sender.track?.kind === 'video') {
                                sender.replaceTrack(track).catch(() => {});
                            }
                        });
                    } catch(e) {}
                }
            }
        }

        function startOverlay(key) {
            // fully tear down any existing overlay first, never skip restoreCam
            if (_overlayRAF) { cancelAnimationFrame(_overlayRAF); _overlayRAF = null; }
            if (_overlayStream) { _overlayStream.getTracks().forEach(t => t.stop()); _overlayStream = null; }
            _overlayCanvas = null;
            _overlayActive = null;

            const img = _overlayImg[key];
            if (!img) {
                setOverlayStatus(`${key} image not loaded yet — try again`, '#fca5a5');
                return;
            }

            _overlayActive = key;
            _overlayCanvas = document.createElement('canvas');
            _overlayCanvas.width = 640; _overlayCanvas.height = 480;
            const ctx = _overlayCanvas.getContext('2d');

            function drawOverlay() {
                if (!_overlayActive) return;
                ctx.save();
                ctx.translate(640, 0);
                ctx.scale(-1, 1);
                ctx.drawImage(img, 0, 0, 640, 480);
                ctx.restore();
                _overlayRAF = requestAnimationFrame(drawOverlay);
            }
            drawOverlay();

            _overlayStream = _overlayCanvas.captureStream(30);
            _pushTrackToAll(_overlayStream);
            setOverlayStatus(`${key.toUpperCase()} active`, key === 'ban' ? '#fca5a5' : '#93c5fd');
        }

        function stopOverlay() {
            if (_overlayRAF) { cancelAnimationFrame(_overlayRAF); _overlayRAF = null; }
            if (_overlayStream) { _overlayStream.getTracks().forEach(t => t.stop()); _overlayStream = null; }
            _overlayActive = null;
            _overlayCanvas = null;

            // Always restore — cam spoof stream if active, otherwise real camera
            if (_camSpoofActive && _camStream) {
                _pushTrackToAll(_camStream);
            } else {
                // restore real camera to senders
                const base = _origGetUserMedia || navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);
                base({ video: true }).then(realStream => {
                    _pushTrackToAll(realStream);
                }).catch(() => {});
            }
            setOverlayStatus('None active', 'rgba(255,255,255,0.3)');
        }

        document.getElementById('mog-ban-overlay-toggle').addEventListener('change', function() {
            document.getElementById('mog-loading-overlay-toggle').checked = false;
            if (this.checked) {
                startOverlay('ban');
            } else {
                stopOverlay();
            }
        });

        document.getElementById('mog-loading-overlay-toggle').addEventListener('change', function() {
            document.getElementById('mog-ban-overlay-toggle').checked = false;
            if (this.checked) {
                startOverlay('loading');
            } else {
                stopOverlay();
            }
        });

        document.getElementById('mog-camspoof-toggle').addEventListener('change', function() {
            _camSpoofActive = this.checked;
            if (_camSpoofActive) {
                startCamSpoof();
            } else {
                stopCamSpoof();
            }
        });
    }

    // Expose Zustand patch status to menu
    const _origPatchStore = patchStore;
    // Mark zustand as patched in UI once it succeeds
    const _zustandInterval = setInterval(() => {
        const badge = document.getElementById('mog-zustand-badge');
        if (!badge) return;
        try {
            const wpChunk = window.webpackChunk_N_E || window.webpackChunknextjs_app || window.webpackChunk;
            if (!wpChunk) return;
            const req = wpChunk.push([[Symbol()], {}, e => e]);
            const mod = req(16225);
            const store = mod && Object.values(mod).find(v => v && typeof v.getState === 'function' && 'myScore' in (v.getState() || {}));
            if (store && store.getState().setMyScore?.__patched) {
                badge.textContent = 'PATCHED';
                badge.style.color = '#86efac';
                clearInterval(_zustandInterval);
            }
        } catch(e) {}
    }, 500);

    // Hook frame log to debug tab
    const _realLog = log;
    function log(...args) {
        if (CONFIG.debug) console.log('[Omoggle]', ...args);
        const msg = args.join(' ');
        if (msg.includes('📤') && msg.includes('frame=') && window._mogUpdateDebug) {
            window._mogUpdateDebug('frame', msg);
        }
        if (msg.includes('FINALIZE') && msg.includes('modified') && window._mogUpdateDebug) {
            window._mogUpdateDebug('finalize', msg.slice(0, 300));
        }
    }

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

})();