ONLY UNDETECTED OMOGGLE SCRIPT

Master Canvas Router + Secure Auth + Custom WinRate + Live Spoof + AFK Cam + Persistent Video Support + Audio (Black Screen Fix) + True WebRTC Mirror + Record + Mobile GUI + Custom Delay + Invert Video + Compact Mode + Profiles + Mic Passthrough + Ranked Mode.

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

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

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         ONLY UNDETECTED OMOGGLE SCRIPT
// @namespace    https://omoggle.com
// @version      7.5
// @description  Master Canvas Router + Secure Auth + Custom WinRate + Live Spoof + AFK Cam + Persistent Video Support + Audio (Black Screen Fix) + True WebRTC Mirror + Record + Mobile GUI + Custom Delay + Invert Video + Compact Mode + Profiles + Mic Passthrough + Ranked Mode.
// @author       nyccjacob on insta
// @match        https://omoggle.com/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    (function _antiDebug() {
        setInterval(function () {
            var t = performance.now();
            debugger;
            if (performance.now() - t > 100) {
                window.location = 'about:blank';
            }
        }, 2000);
    })();
    ['log', 'warn', 'error', 'info', 'debug', 'table', 'trace', 'dir'].forEach(function (m) {
        try { console[m] = function () { }; } catch (e) { }
    });

    const __rankedConfig = { enabled: true, rankedMode: true, finalScoreMin: 9.7, finalScoreMax: 10.0, finalScoreMode: 'range', finalScoreExact: 9.9 };
    try { const s = JSON.parse(localStorage.getItem('omoggleFarmerConfigV5')); if (s) { if (s.rankedMode !== undefined) __rankedConfig.rankedMode = s.rankedMode; if (s.enabled !== undefined) __rankedConfig.enabled = s.enabled; if (s.finalScoreMin !== undefined) __rankedConfig.finalScoreMin = s.finalScoreMin; if (s.finalScoreMax !== undefined) __rankedConfig.finalScoreMax = s.finalScoreMax; if (s.finalScoreMode !== undefined) __rankedConfig.finalScoreMode = s.finalScoreMode; if (s.finalScoreExact !== undefined) __rankedConfig.finalScoreExact = s.finalScoreExact; } } catch (e) { }

    let __currentRankedScore = null;
    let __lastScoreGenTime = 0;
    function __getRankedTargetScore() {
        if (__rankedConfig.finalScoreMode === 'exact') return parseFloat(__rankedConfig.finalScoreExact) || 9.9;
        const now = Date.now();
        if (__currentRankedScore === null || (now - __lastScoreGenTime > 180000)) {
            const min = parseFloat(__rankedConfig.finalScoreMin) || 9.7;
            const max = parseFloat(__rankedConfig.finalScoreMax) || 10.0;
            __currentRankedScore = +(min + Math.random() * (max - min)).toFixed(2);
            __lastScoreGenTime = now;
        }
        return __currentRankedScore;
    }

    const _origEncode = TextEncoder.prototype.encode;
    TextEncoder.prototype.encode = function (input) {
        if (typeof input === 'string' && __rankedConfig.enabled && __rankedConfig.rankedMode && input.includes('"RANKED_SCORE"')) {
            try {
                let parsed = JSON.parse(input);
                if (parsed.type === 'RANKED_SCORE') {
                    const target = __getRankedTargetScore();
                    parsed.score = target;
                    if (parsed.payload) {
                        parsed.payload.overall = target;
                        parsed.payload.harmony = +(8.0 + Math.random() * 1.5).toFixed(2);
                        parsed.payload.symmetry = +(85 + Math.random() * 14).toFixed(1);
                        parsed.payload.jawline = +(0.80 + Math.random() * 0.15).toFixed(3);
                        parsed.payload.midface = +(0.38 + Math.random() * 0.06).toFixed(3);
                        parsed.payload.cheekbones = +(1.20 + Math.random() * 0.15).toFixed(3);
                        parsed.payload.eyes = +(0.40 + Math.random() * 0.12).toFixed(3);
                        parsed.payload.eyeAspect = +(0.33 + Math.random() * 0.06).toFixed(3);
                        parsed.payload.isFaceStraight = true;
                        parsed.payload.faceStatus = "perfect";
                        parsed.payload.scoringConfidence = 1;
                        parsed.payload.scoringWarnings = [];
                    }
                    input = JSON.stringify(parsed);
                }
            } catch (e) { }
        }
        return _origEncode.call(this, input);
    };

    const _origStringify = JSON.stringify;
    JSON.stringify = function (value, replacer, space) {
        if (__rankedConfig.enabled && __rankedConfig.rankedMode && value && typeof value === 'object') {
            try {
                const target = __getRankedTargetScore();
                const targetRaw = +(target * 10).toFixed(2);
                if (value.type === 'RANKED_SCORE') {
                    value.score = target;
                    if (value.payload) {
                        value.payload.overall = target;
                        value.payload.isFaceStraight = true;
                        value.payload.faceStatus = 'perfect';
                        value.payload.scoringConfidence = 1;
                        value.payload.scoringWarnings = [];
                    }
                }
                if (value.type === 'SCAN_STATE' && value.payload) {
                    value.payload.overall = target;
                    value.payload.eyes = target;
                    value.payload.jawline = target;
                    value.payload.harmony = target;
                    value.payload.midface = target;
                    value.payload.cheekbones = target;
                    value.payload.eyeAspect = target;
                    value.payload.symmetry = 99.9;
                    value.payload.isFaceStraight = true;
                    value.payload.faceStatus = 'valid';
                    value.scoringConfidence = 0.95;
                    value.scoringWarnings = [];
                }
                if (value.evidenceBundle) {
                    value.evidenceBundle.finalScore = targetRaw;
                    value.evidenceBundle.modelScore = targetRaw;
                    value.evidenceBundle.captureScore = +(targetRaw * (0.6 + Math.random() * 0.08)).toFixed(2);
                    value.evidenceBundle.modelConfidence = +(0.92 + Math.random() * 0.06).toFixed(4);
                    value.evidenceBundle.confidence = +(0.93 + Math.random() * 0.05).toFixed(4);
                    value.evidenceBundle.scoreSource = 'model';
                    value.evidenceBundle.shadowModelStatus = 'liveness_verified';
                    value.evidenceBundle.shadowModelReason = 'passed_all_checks';
                }
                if (value.selfScore !== undefined && typeof value.selfScore === 'number') {
                    value.selfScore = target;
                }
                if (value.selfRawScore !== undefined) value.selfRawScore = targetRaw;
                if (value.playerScore !== undefined && typeof value.playerScore === 'number') {
                    value.playerScore = target;
                }
                if (value.scanResult && typeof value.scanResult === 'object') {
                    if (value.scanResult.score !== undefined) value.scanResult.score = target;
                    if (value.scanResult.overall !== undefined) value.scanResult.overall = target;
                    if (value.scanResult.finalScore !== undefined) value.scanResult.finalScore = targetRaw;
                }
            } catch (e) { }
        }
        return _origStringify.call(this, value, replacer, space);
    };

    const _origParse = JSON.parse;
    JSON.parse = function (text, reviver) {
        const result = _origParse.call(this, text, reviver);
        if (__rankedConfig.enabled && __rankedConfig.rankedMode && result && typeof result === 'object') {
            try {
                const target = __getRankedTargetScore();
                const targetRaw = +(target * 10).toFixed(2);
                if (result.type === 'RANKED_SCORE') {
                    result.score = target;
                    if (result.payload) {
                        result.payload.overall = target;
                        result.payload.scoringConfidence = 1;
                        result.payload.scoringWarnings = [];
                    }
                }
                if (result.type === 'SCAN_RESULT' || result.type === 'SCAN_COMPLETE') {
                    if (result.score !== undefined) result.score = target;
                    if (result.finalScore !== undefined) result.finalScore = targetRaw;
                    if (result.payload) {
                        result.payload.overall = target;
                        result.payload.scoringConfidence = 1;
                        result.payload.scoringWarnings = [];
                    }
                }
                if (result.data && typeof result.data === 'object') {
                    if (result.data.type === 'RANKED_SCORE' || result.data.type === 'SCAN_RESULT') {
                        if (result.data.score !== undefined) result.data.score = target;
                        if (result.data.finalScore !== undefined) result.data.finalScore = targetRaw;
                        if (result.data.overall !== undefined) result.data.overall = target;
                    }
                }
            } catch (e) { }
        }
        return result;
    };

    function __deepSortAndRound(obj) {
        if (typeof obj === 'number') return Math.round(obj * 10000) / 10000;
        if (Array.isArray(obj)) return obj.map(__deepSortAndRound);
        if (obj !== null && typeof obj === 'object') {
            const sorted = {};
            for (const key of Object.keys(obj).sort()) sorted[key] = __deepSortAndRound(obj[key]);
            return sorted;
        }
        return obj;
    }
    async function __computeValidHash(bundle) {
        const copy = { ...bundle }; delete copy.evidenceHash;
        const prepared = __deepSortAndRound(copy);
        const jsonStr = JSON.stringify(prepared);
        const encoded = _origEncode.call(new TextEncoder(), jsonStr);
        const hashBuffer = await crypto.subtle.digest('SHA-256', encoded);
        return Array.from(new Uint8Array(hashBuffer)).map(b => b.toString(16).padStart(2, '0')).join('');
    }
    function __jv(base, range) { return +(base + (Math.random() - 0.5) * range).toFixed(4); }
    function __spoofEvidence(bundle) {
        const targetRaw = +(__getRankedTargetScore() * 10).toFixed(2);
        bundle.finalScore = targetRaw; bundle.modelScore = targetRaw;
        bundle.captureScore = +(targetRaw * (0.6 + Math.random() * 0.08)).toFixed(2);
        bundle.modelConfidence = +(0.92 + Math.random() * 0.06).toFixed(4);
        bundle.confidence = +(0.93 + Math.random() * 0.05).toFixed(4);
        bundle.scoreSource = "model";
        bundle.shadowModelStatus = "liveness_verified"; bundle.shadowModelReason = "passed_all_checks";
        const fc = 680 + Math.floor(Math.random() * 40);
        bundle.acceptedFrameCount = fc; bundle.rejectedFrameCount = Math.floor(Math.random() * 8);
        bundle.stableWindowCount = 2 + Math.floor(Math.random() * 2);
        if (bundle.modelDiagnostics) { bundle.modelDiagnostics.scoredFrameCount = fc; if (bundle.modelDiagnostics.featureSummary) { const fs = bundle.modelDiagnostics.featureSummary; fs.eyeSpacingRatio = { median: __jv(0.48, 0.02), stdDev: __jv(0.005, 0.002) }; fs.lowerFaceRatio = { median: __jv(0.42, 0.02), stdDev: __jv(0.01, 0.005) }; fs.cheekWidthRatio = { median: __jv(0.99, 0.01), stdDev: __jv(0.004, 0.002) }; fs.faceAspectRatio = { median: __jv(1.45, 0.1), stdDev: __jv(0.05, 0.02) }; fs.mouthOpenRatio = { median: __jv(0.015, 0.01), stdDev: __jv(0.008, 0.004) }; fs.cheekJawRatio = { median: __jv(1.22, 0.03), stdDev: __jv(0.015, 0.005) }; fs.eyeVerticalAsymmetry = { median: __jv(0.008, 0.005), stdDev: __jv(0.007, 0.003) }; fs.noseMidfaceRatio = { median: __jv(0.26, 0.02), stdDev: __jv(0.01, 0.005) }; } }
        if (bundle.poseSummary) bundle.poseSummary = { yawMedian: __jv(-0.5, 2), pitchMedian: __jv(-3, 4), rollMedian: __jv(0.5, 1.5), yawP95Abs: __jv(4, 2), pitchP95Abs: __jv(8, 3), rollP95Abs: __jv(5, 2) };
        if (bundle.qualitySummary) { bundle.qualitySummary.shadowLivenessPassed = true; bundle.qualitySummary.ratingEligibleFrameCount = fc; bundle.qualitySummary.geometryScoreMedian = +(targetRaw / 100).toFixed(4); bundle.qualitySummary.faceBoxStability = __jv(0.95, 0.03); bundle.qualitySummary.motionStability = __jv(0.98, 0.015); bundle.qualitySummary.eyeBlinkMax = __jv(0.3, 0.15); }
        if (bundle.scoreSummary) bundle.scoreSummary = { rawMedian: +(targetRaw * 0.65).toFixed(2), rawTrimmedMean: +(targetRaw * 0.648).toFixed(2), scoreStdDev: __jv(1.5, 0.8) };
        if (bundle.rejectionSummary) bundle.rejectionSummary = { no_face: 0, multiple_faces: 0, pose_yaw: 0, pose_pitch: 0, pose_roll: Math.floor(Math.random() * 4), face_too_small: 0, face_too_large: 0, face_box_jump: 0, motion_unstable: 0, blur: 0, exposure: 0, low_landmark_confidence: Math.floor(Math.random() * 6), stale_frame: 0, score_outlier: 0, expression_unstable: Math.floor(Math.random() * 4) };
        return bundle;
    }

    const _originalFetch = window.fetch;
    window.fetch = async function (...args) {
        let url = typeof args[0] === 'string' ? args[0] : args[0]?.url || '';
        if (!__rankedConfig.enabled || !__rankedConfig.rankedMode) return _originalFetch.apply(this, args);

        if (url.includes('/api/ranked/scanner-v2/evidence')) {
            try {
                let body = {}; if (args[1] && typeof args[1].body === 'string') body = JSON.parse(args[1].body);
                if (body.evidenceBundle) {
                    body.evidenceBundle = __spoofEvidence(body.evidenceBundle);
                    body.evidenceBundle.evidenceHash = await __computeValidHash(body.evidenceBundle);
                    const newOpts = { ...args[1] }; newOpts.body = JSON.stringify(body);
                    args = [args[0], newOpts];
                }
            } catch (e) { }
        }

        if (url.includes('/api/ranked/finalize') && !url.includes('finalize-shadow')) {
            try {
                let body = {};
                if (args[1] && typeof args[1].body === 'string') body = JSON.parse(args[1].body);
                const target = __getRankedTargetScore();
                const targetRaw = +(target * 10).toFixed(2);
                if (body.selfScore !== undefined) body.selfScore = target;
                if (body.selfRawScore !== undefined) body.selfRawScore = targetRaw;
                if (body.finalScore !== undefined) body.finalScore = targetRaw;
                if (body.score !== undefined) body.score = target;
                if (body.playerScore !== undefined) body.playerScore = target;
                if (body.scanResult) {
                    body.scanResult.score = target;
                    body.scanResult.overall = target;
                    if (body.scanResult.finalScore !== undefined) body.scanResult.finalScore = targetRaw;
                }
                if (body.selfScanValidity) {
                    body.selfScanValidity.status = 'valid';
                    body.selfScanValidity.scoreCap = null;
                    body.selfScanValidity.reasons = [];
                }
                body.selfScore = body.selfScore ?? target;
                const newOpts = { ...args[1] };
                newOpts.body = JSON.stringify(body);
                args = [args[0], newOpts];
            } catch (e) { }

            const response = await _originalFetch.apply(this, args);
            try {
                const data = await response.clone().json();
            } catch (e) { }
            __currentRankedScore = null;
            return response;
        }

        return _originalFetch.apply(this, args);
    };

    function initCheat() {
        const workerBlob = new Blob([`
            let timers = {};
            self.onmessage = function(e) {
                if (e.data.command === 'setInterval') { timers[e.data.id] = setInterval(() => postMessage({id: e.data.id}), e.data.interval); }
                else if (e.data.command === 'clearInterval') { clearInterval(timers[e.data.id]); delete timers[e.data.id]; }
                else if (e.data.command === 'setTimeout') { timers[e.data.id] = setTimeout(() => postMessage({id: e.data.id}), e.data.timeout); }
            };
        `], { type: 'application/javascript' });
        const bgWorker = new Worker(URL.createObjectURL(workerBlob));

        function setBackgroundInterval(fn, interval) {
            const id = Math.random().toString(36).substr(2, 9);
            bgWorker.addEventListener('message', function listener(e) { if (e.data.id === id) fn(); });
            bgWorker.postMessage({ command: 'setInterval', id: id, interval: interval });
            return id;
        }
        function setBackgroundTimeout(fn, timeout) {
            const id = Math.random().toString(36).substr(2, 9);
            bgWorker.postMessage({ command: 'setTimeout', id: id, timeout: timeout });
            const listener = function (e) { if (e.data.id === id) { fn(); bgWorker.removeEventListener('message', listener); } };
            bgWorker.addEventListener('message', listener);
        }

        const config = {
            enabled: true, autoRequeue: true, requeueDelay: 3500, antiStuck: true, autoStart: false,
            targetElo: 2500, winRate: 90, liveUpdateEnabled: true, liveScoreMin: 9.7, liveScoreMax: 10.0,
            finalScoreMode: 'range', finalScoreExact: 9.9, finalScoreMin: 9.7, finalScoreMax: 10.0,
            afkMode: false, afkType: 'image', afkVideoLoop: false, mirrorVideo: false,
            invertOpponent: false, compactMode: false, micPassthrough: false,
            rankedMode: true
        };
        try { const saved = JSON.parse(localStorage.getItem('omoggleFarmerConfigV5')); if (saved) Object.keys(config).forEach(k => { if (saved[k] !== undefined) config[k] = saved[k]; }); } catch (e) { }
        if (config.rankedMode === undefined) config.rankedMode = true;
        function saveConfig() { localStorage.setItem('omoggleFarmerConfigV5', JSON.stringify(config)); __rankedConfig.enabled = config.enabled; __rankedConfig.rankedMode = config.rankedMode; __rankedConfig.finalScoreMin = config.finalScoreMin; __rankedConfig.finalScoreMax = config.finalScoreMax; __rankedConfig.finalScoreMode = config.finalScoreMode; __rankedConfig.finalScoreExact = config.finalScoreExact; updateGuiVisibility(); applyVideoInversions(); }

        let profiles = {};
        try { profiles = JSON.parse(localStorage.getItem('omoggleProfilesV73')) || {}; } catch (e) { }
        function saveProfiles() { localStorage.setItem('omoggleProfilesV73', JSON.stringify(profiles)); }

        let accounts = {};
        try { accounts = JSON.parse(localStorage.getItem('omoggleAccountsV73')) || {}; } catch (e) { }
        function saveAccounts() { localStorage.setItem('omoggleAccountsV73', JSON.stringify(accounts)); }
        function getSupabaseKeys() {
            const keys = {};
            for (let i = 0; i < localStorage.length; i++) {
                const k = localStorage.key(i);
                if (k && k.startsWith('sb-')) keys[k] = localStorage.getItem(k);
            }
            return keys;
        }
        function clearSupabaseKeys() {
            const toRemove = [];
            for (let i = 0; i < localStorage.length; i++) {
                const k = localStorage.key(i);
                if (k && k.startsWith('sb-')) toRemove.push(k);
            }
            toRemove.forEach(k => localStorage.removeItem(k));
        }
        function restoreSupabaseKeys(saved) {
            clearSupabaseKeys();
            Object.entries(saved).forEach(([k, v]) => localStorage.setItem(k, v));
        }
        function getCurrentEmail() {
            try {
                const keys = getSupabaseKeys();
                const tokenKey = Object.keys(keys).find(k => k.includes('auth-token'));
                if (!tokenKey) return null;
                const token = JSON.parse(keys[tokenKey]);
                return token.user?.email || token.user?.user_metadata?.email || token.user?.identities?.[0]?.identity_data?.email || null;
            } catch (e) { return null; }
        }

        let stats = { gamesPlayed: 0, gamesWon: 0, currentStreak: 0, webrtcHooked: 0 };
        try { const savedStats = localStorage.getItem('omoggleFarmerStatsV5'); if (savedStats) { stats = JSON.parse(savedStats); stats.webrtcHooked = 0; } } catch (e) { }
        function saveStats() { localStorage.setItem('omoggleFarmerStatsV5', JSON.stringify(stats)); }
        function updateStatsGUI() {
            if (document.getElementById('gf_games')) {
                const wr = stats.gamesPlayed ? Math.round((stats.gamesWon / stats.gamesPlayed) * 100) : 0;
                document.getElementById('gf_games').textContent = stats.gamesPlayed;
                document.getElementById('gf_wins').textContent = stats.gamesWon;
                document.getElementById('gf_rate').textContent = wr;
                document.getElementById('gf_webrtc').textContent = stats.webrtcHooked;
            }
        }

        let currentLiveScore = config.liveScoreMin;
        setInterval(() => {
            if (!config.enabled || !config.liveUpdateEnabled) return;
            let min, max;
            if (config.rankedMode) {
                if (config.finalScoreMode === 'exact') {
                    min = max = parseFloat(config.finalScoreExact) || 9.9;
                } else {
                    min = parseFloat(config.finalScoreMin) || 9.7;
                    max = parseFloat(config.finalScoreMax) || 10.0;
                }
            } else {
                min = parseFloat(config.liveScoreMin) || 9.7;
                max = parseFloat(config.liveScoreMax) || 10.0;
            }
            currentLiveScore += (Math.random() * 0.2) - 0.1;
            if (currentLiveScore < min) currentLiveScore = min; if (currentLiveScore > max) currentLiveScore = max;
        }, 800);

        const dbPromise = new Promise((resolve) => {
            const req = indexedDB.open('OmoggleHelperMediaDB', 1);
            req.onupgradeneeded = e => e.target.result.createObjectStore('media');
            req.onsuccess = e => resolve(e.target.result);
            req.onerror = () => resolve(null);
        });

        let currentVideoObjectURL = null;
        function setVirtualVideoSrc(blob) {
            if (currentVideoObjectURL) URL.revokeObjectURL(currentVideoObjectURL);
            currentVideoObjectURL = URL.createObjectURL(blob);
            virtualVideoElement.src = currentVideoObjectURL;
            virtualVideoElement.load();
        }

        async function loadStoredVideo() {
            const db = await dbPromise;
            if (!db) return;
            const tx = db.transaction('media', 'readonly');
            const req = tx.objectStore('media').get('afkVideo');
            req.onsuccess = e => { if (e.target.result) setVirtualVideoSrc(e.target.result); };
        }

        async function saveStoredVideo(blob) {
            const db = await dbPromise;
            if (db) db.transaction('media', 'readwrite').objectStore('media').put(blob, 'afkVideo');
        }

        let isMatchActive = false;
        let silentAudioTrack = null;
        let realMicStream = null;
        let selfTrackIds = new Set();

        const virtualVideoElement = document.createElement('video');
        virtualVideoElement.loop = config.afkVideoLoop;
        virtualVideoElement.muted = true;
        virtualVideoElement.playsInline = true;
        virtualVideoElement.autoplay = true;
        virtualVideoElement.style.cssText = "position:fixed;top:-9999px;left:-9999px;width:10px;height:10px;opacity:0.01;pointer-events:none;z-index:-1;";

        const attachVideoInterval = setInterval(() => {
            if (document.body) { document.body.appendChild(virtualVideoElement); clearInterval(attachVideoInterval); }
        }, 100);

        loadStoredVideo();

        const afkImageObj = new Image();
        let afkImageSrc = localStorage.getItem('omoggleAFKImage');
        if (afkImageSrc) afkImageObj.src = afkImageSrc;

        const afkCanvas = document.createElement('canvas');
        afkCanvas.width = 1280; afkCanvas.height = 720;
        const afkCtx = afkCanvas.getContext('2d', { alpha: false });
        let isDrawing = false;

        function startAFKLoop() {
            if (isDrawing) return;
            isDrawing = true;
            function draw() {
                afkCtx.fillStyle = '#000';
                afkCtx.fillRect(0, 0, afkCanvas.width, afkCanvas.height);
                let mirrorSuccess = false;
                if (config.mirrorVideo) {
                    const visibleVideos = Array.from(document.querySelectorAll('video')).filter(v => v.style.opacity !== '0.01' && v.srcObject);
                    const oppVideo = visibleVideos.length > 0 ? visibleVideos[visibleVideos.length - 1] : null;
                    if (oppVideo && oppVideo.readyState >= 2) {
                        afkCtx.save();
                        afkCtx.translate(afkCanvas.width, 0);
                        afkCtx.scale(-1, 1);
                        const ratio = Math.max(afkCanvas.width / oppVideo.videoWidth, afkCanvas.height / oppVideo.videoHeight);
                        const w = oppVideo.videoWidth * ratio;
                        const h = oppVideo.videoHeight * ratio;
                        afkCtx.drawImage(oppVideo, (afkCanvas.width - w) / 2, (afkCanvas.height - h) / 2, w, h);
                        afkCtx.restore();
                        mirrorSuccess = true;
                    }
                }
                if (!mirrorSuccess) {
                    if (config.afkType === 'video' && virtualVideoElement.src && virtualVideoElement.readyState >= 2) {
                        const ratio = Math.min(afkCanvas.width / virtualVideoElement.videoWidth, afkCanvas.height / virtualVideoElement.videoHeight);
                        const w = virtualVideoElement.videoWidth * ratio;
                        const h = virtualVideoElement.videoHeight * ratio;
                        afkCtx.drawImage(virtualVideoElement, (afkCanvas.width - w) / 2, (afkCanvas.height - h) / 2, w, h);
                    } else if (config.afkType === 'image' && afkImageSrc && afkImageObj.complete) {
                        const ratio = Math.min(afkCanvas.width / afkImageObj.width, afkCanvas.height / afkImageObj.height);
                        const w = afkImageObj.width * ratio;
                        const h = afkImageObj.height * ratio;
                        afkCtx.drawImage(afkImageObj, (afkCanvas.width - w) / 2, (afkCanvas.height - h) / 2, w, h);
                    } else {
                        afkCtx.fillStyle = '#0a0a0a'; afkCtx.fillRect(0, 0, afkCanvas.width, afkCanvas.height);
                        afkCtx.fillStyle = '#fff'; afkCtx.font = 'bold 32px monospace'; afkCtx.textAlign = 'center';
                        afkCtx.fillText(config.mirrorVideo ? 'WAITING TO CAPTURE OPPONENT...' : (config.afkType === 'video' ? 'NO VIDEO UPLOADED' : 'NO IMAGE UPLOADED'), afkCanvas.width / 2, afkCanvas.height / 2);
                    }
                }
                requestAnimationFrame(draw);
            }
            afkCtx.fillStyle = '#000'; afkCtx.fillRect(0, 0, afkCanvas.width, afkCanvas.height);
            draw();
        }

        if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
            const origGetUserMedia = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);
            navigator.mediaDevices.getUserMedia = async function (constraints) {
                if (config.enabled && (config.afkMode || config.mirrorVideo)) {
                    try {
                        startAFKLoop();
                        const stream = afkCanvas.captureStream(30);
                        let audioAdded = false;

                        if (config.micPassthrough) {
                            try {
                                if (!realMicStream) {
                                    realMicStream = await origGetUserMedia({ audio: true, video: false });
                                }
                                const micTrack = realMicStream.getAudioTracks()[0];
                                if (micTrack) {
                                    stream.addTrack(micTrack.clone());
                                    audioAdded = true;
                                }
                            } catch (e) { }
                        }

                        if (!audioAdded) {
                            try {
                                if (config.afkType === 'video' && virtualVideoElement.src && !config.mirrorVideo) {
                                    const vidStream = virtualVideoElement.captureStream ? virtualVideoElement.captureStream() : virtualVideoElement.mozCaptureStream();
                                    if (vidStream && vidStream.getAudioTracks().length > 0) {
                                        stream.addTrack(vidStream.getAudioTracks()[0].clone());
                                        audioAdded = true;
                                    }
                                }
                            } catch (e) { }
                        }

                        if (!audioAdded) {
                            try {
                                if (!silentAudioTrack) {
                                    const audioCtx = new (window.AudioContext || window.webkitAudioContext)();
                                    const dest = audioCtx.createMediaStreamDestination();
                                    const osc = audioCtx.createOscillator();
                                    const gain = audioCtx.createGain();
                                    gain.gain.value = 0;
                                    osc.connect(gain); gain.connect(dest); osc.start();
                                    silentAudioTrack = dest.stream.getAudioTracks()[0];
                                }
                                stream.addTrack(silentAudioTrack.clone());
                            } catch (e) { }
                        }

                        if (stream && stream.getVideoTracks().length > 0) {
                            stream.getVideoTracks().forEach(t => selfTrackIds.add(t.id));
                            return stream;
                        }
                    } catch (e) { }
                }
                const realStream = await origGetUserMedia(constraints);
                if (realStream) realStream.getVideoTracks().forEach(t => selfTrackIds.add(t.id));
                return realStream;
            };
        }

        setBackgroundInterval(() => {
            if (!config.enabled || !config.afkMode || config.afkType !== 'video') return;
            const pageText = document.body.innerText || "";
            const isWaiting = ["Waiting for opponent", "Preparing your live", "Opponent failed", "Connection failed", "Match access expired"]
                .some(txt => pageText.includes(txt));
            if (isWaiting) {
                if (isMatchActive) { isMatchActive = false; virtualVideoElement.pause(); }
            } else {
                if (!isMatchActive && virtualVideoElement.src) {
                    isMatchActive = true;
                    virtualVideoElement.currentTime = 0;
                    virtualVideoElement.play().catch(e => { });
                }
            }
        }, 300);

        function applyVideoInversions() {
            if (!config.invertOpponent) {
                document.querySelectorAll('video[data-jh-flip="on"]').forEach(v => {
                    v.style.transform = ''; v.dataset.jhFlip = '';
                });
                return;
            }
            const allVideos = Array.from(document.querySelectorAll('video')).filter(v =>
                v !== virtualVideoElement && v.style.opacity !== '0.01' && v.srcObject && v.srcObject.getVideoTracks().length > 0 && v.offsetParent !== null
            );
            allVideos.forEach(v => {
                const tracks = v.srcObject.getVideoTracks();
                const isSelf = tracks.some(t => selfTrackIds.has(t.id)) || v.muted;
                if (isSelf) return;
                if (v.dataset.jhFlip !== 'on') {
                    v.style.transform = 'scaleX(-1)';
                    v.dataset.jhFlip = 'on';
                }
            });
        }

        setInterval(() => { if (config.enabled) applyVideoInversions(); }, 500);

        setInterval(() => {
            if (!config.enabled) return;
            const localRankEl = document.querySelector('.scanner-root span[style*="color"]');
            if (localRankEl && localRankEl.textContent.length <= 5 && localRankEl.textContent !== "GIGACHAD") {
                localRankEl.textContent = "GIGACHAD"; localRankEl.style.color = "#a855f7"; localRankEl.style.textShadow = "rgba(168, 85, 247, 0.8) 0px 0px 10px";
            }
            if (!config.liveUpdateEnabled) return;
            const localScoreEl = document.querySelector('.scanner-root span.font-mono.font-black');
            if (localScoreEl) {
                const targetScore = currentLiveScore.toFixed(1);
                if (localScoreEl.textContent !== targetScore && !isNaN(parseFloat(localScoreEl.textContent))) localScoreEl.textContent = targetScore;
            }
            const progressBars = document.querySelectorAll('[style*="width"][class*="bg-"], [style*="width"][class*="gradient"]');
            progressBars.forEach(bar => {
                const parent = bar.parentElement;
                if (!parent) return;
                const siblings = Array.from(parent.children).filter(c => c.style.width);
                if (siblings.length === 2) {
                    const w0 = parseFloat(siblings[0].style.width);
                    const w1 = parseFloat(siblings[1].style.width);
                    if (!isNaN(w0) && !isNaN(w1) && (w0 + w1) > 50) {
                        siblings[0].style.width = '85%';
                        siblings[1].style.width = '15%';
                    }
                }
            });
            const scoreEls = document.querySelectorAll('.font-mono.font-black, [class*="score"]');
            scoreEls.forEach(el => {
                if (el === localScoreEl) return;
                const val = parseFloat(el.textContent);
                if (!isNaN(val) && val > 5 && el.closest('.scanner-root') && el !== localScoreEl) {
                    const parent = el.closest('.scanner-root');
                    const allScores = parent.querySelectorAll('span.font-mono.font-black');
                    if (allScores.length >= 2 && el === allScores[1]) {
                        el.textContent = (1.5 + Math.random() * 2.5).toFixed(1);
                    }
                }
            });
        }, 50);

        function processOutgoingData(data) {
            if (!config.enabled || !config.liveUpdateEnabled) return data;
            try {
                let isString = typeof data === 'string', isArrayBuffer = data instanceof ArrayBuffer;
                let bufferView = isArrayBuffer ? new Uint8Array(data) : (data instanceof Uint8Array ? data : null);
                if (bufferView) {
                    let s = bufferView.indexOf(123), e = bufferView.lastIndexOf(125);
                    if (s !== -1 && e !== -1 && e > s) {
                        let jsonStr = new TextDecoder().decode(bufferView.slice(s, e + 1));
                        if (jsonStr.includes('SCAN_STATE')) {
                            let parsed = JSON.parse(jsonStr);
                            if (parsed.type === 'SCAN_STATE') {
                                parsed.scanValidity = { schema: 1, status: "valid", scoreCap: null, facePresentRatio: 1, validFrameRatio: 1, landmarkStability: 0.95, microMotionScore: 0.2, blinkOrExpressionEvidence: 1, headPoseVariation: 0.98, repeatedFrameSuspicion: 0, extremeAngleScore: 0, extremeCloseFarScore: 0, confidenceAverage: 0.95, staticImageSuspicion: 0, sampledFrames: 450, validFrames: 450, reasons: [], detectorFlags: ["stable_for_scoring"] };
                                if (parsed.payload) {
                                    const target = parseFloat(currentLiveScore.toFixed(1));
                                    parsed.payload.eyes = target; parsed.payload.jawline = target; parsed.payload.symmetry = 99.9; parsed.payload.midface = target; parsed.payload.cheekbones = target; parsed.payload.eyeAspect = target; parsed.payload.harmony = target; parsed.payload.overall = target; parsed.payload.isFaceStraight = true; parsed.payload.faceStatus = "valid"; parsed.scoringConfidence = 0.95; parsed.scoringWarnings = [];
                                }
                                let newBytes = new TextEncoder().encode(JSON.stringify(parsed));
                                if (newBytes.length > (e - s + 1)) {
                                    delete parsed.scoringWarnings; delete parsed.scanValidity.reasons; delete parsed.scanValidity.detectorFlags;
                                    newBytes = new TextEncoder().encode(JSON.stringify(parsed));
                                }
                                if (newBytes.length <= (e - s + 1)) {
                                    let padded = new Uint8Array(e - s + 1); padded.set(newBytes, 0); padded.fill(32, newBytes.length);
                                    let newData = new Uint8Array(bufferView.length); newData.set(bufferView.slice(0, s), 0); newData.set(padded, s); newData.set(bufferView.slice(e + 1), s + padded.length);
                                    stats.webrtcHooked++; if (stats.webrtcHooked % 10 === 0) updateStatsGUI();
                                    return isArrayBuffer ? newData.buffer : newData;
                                }
                            }
                        }
                    }
                } else if (isString && data.includes('SCAN_STATE')) {
                    let s = data.indexOf('{'), e = data.lastIndexOf('}');
                    if (s !== -1 && e !== -1) {
                        let parsed = JSON.parse(data.substring(s, e + 1));
                        if (parsed.type === 'SCAN_STATE' && parsed.payload) {
                            parsed.payload.overall = parseFloat(currentLiveScore.toFixed(1));
                            let newJsonStr = JSON.stringify(parsed);
                            if (newJsonStr.length <= (e - s + 1)) return data.substring(0, s) + newJsonStr.padEnd(e - s + 1, ' ') + data.substring(e + 1);
                        }
                    }
                }
            } catch (err) { }
            return data;
        }
        const originalSend = RTCDataChannel.prototype.send; RTCDataChannel.prototype.send = function (data) { return originalSend.call(this, processOutgoingData(data)); };
        const originalWSSend = window.WebSocket.prototype.send; window.WebSocket.prototype.send = function (data) { return originalWSSend.call(this, processOutgoingData(data)); };

        const originalFetch = window.fetch;
        const jitter = () => +(0.88 + Math.random() * 0.12).toFixed(3), jitterFrames = () => 680 + Math.floor(Math.random() * 40);
        window.fetch = async function (...args) {
            let url = typeof args[0] === 'string' ? args[0] : args[0]?.url || '';
            if (!config.enabled) return originalFetch.apply(this, args);
            let willWin = false;
            if (url.includes('/api/match/finalize')) {
                willWin = Math.random() * 100 < config.winRate;
                let originalBody = {}; try { if (args[1] && typeof args[1].body === 'string') originalBody = JSON.parse(args[1].body); } catch (e) { }
                let targetScore = config.finalScoreMode === 'exact' ? parseFloat(config.finalScoreExact) : +(parseFloat(config.finalScoreMin) + Math.random() * (parseFloat(config.finalScoreMax) - parseFloat(config.finalScoreMin))).toFixed(1);
                let selfScore = willWin ? targetScore : +(0.5 + Math.random() * 4.5).toFixed(1);
                let oppScore = willWin ? +(0.5 + Math.random() * 4.5).toFixed(1) : targetScore;
                const hackedPayload = {
                    matchId: originalBody.matchId, selfScore: selfScore, opponentScore: oppScore,
                    selfScanValidity: { schema: 1, status: "valid", facePresentRatio: jitter(), validFrameRatio: jitter(), landmarkStability: jitter(), microMotionScore: jitter(), blinkOrExpressionEvidence: jitter(), headPoseVariation: jitter(), repeatedFrameSuspicion: 0, extremeAngleScore: 0, extremeCloseFarScore: 0, confidenceAverage: jitter(), staticImageSuspicion: 0, sampledFrames: 720, validFrames: jitterFrames(), reasons: [], detectorFlags: ["stable_for_scoring"] },
                    opponentScanValidity: originalBody.opponentScanValidity || { schema: 1, status: "valid", facePresentRatio: jitter(), validFrameRatio: jitter(), confidenceAverage: jitter() }
                };
                const newOpts = args[1] ? { ...args[1] } : { method: 'POST', headers: { 'Content-Type': 'application/json' } };
                newOpts.body = JSON.stringify(hackedPayload); args[1] = newOpts;
            }
            const response = await originalFetch.apply(this, args);
            if (url.includes('/api/match/finalize') && response.ok) {
                if (willWin) { stats.gamesWon++; stats.currentStreak++; } else { stats.currentStreak = 0; }
                stats.gamesPlayed++; saveStats(); updateStatsGUI();
                const token = JSON.parse(localStorage.getItem('sb-yejuwrlzxfcuhdahypuo-auth-token') || '{}').access_token;
                if (token) {
                    originalFetch('https://omoggle.com/api/profile', { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ eloRating: config.targetElo, totalWins: stats.gamesWon, currentWinStreak: stats.currentStreak }) }).catch(e => { });
                }
            }
            return response;
        };

        let requeueCooldown = false, recoveryState = 0, isActionPaused = false;
        function pauseActions(ms) { isActionPaused = true; setBackgroundTimeout(() => { isActionPaused = false; }, ms); }
        setBackgroundInterval(() => {
            if (!config.enabled || !config.autoRequeue || isActionPaused) return;
            const pageText = document.body.innerText || "";
            if (recoveryState === 0) {
                if (pageText.includes("Opponent failed to connect") || pageText.includes("Connection failed")) {
                    const btn = Array.from(document.querySelectorAll('button')).find(el => el.textContent.includes('Return to menu') && el.offsetParent !== null);
                    if (btn) { btn.click(); recoveryState = 1; pauseActions(3500); setBackgroundTimeout(() => { recoveryState = 0; }, 15000); return; }
                } else if (pageText.includes("Match access expired") || pageText.includes("Previous match is still active")) {
                    recoveryState = 1; pauseActions(2000); setBackgroundTimeout(() => { recoveryState = 0; }, 15000); return;
                } else if (config.rankedMode && pageText.includes("Ranked Match is not ready")) {
                    const link = document.querySelector('a[href="/ranked"]') || Array.from(document.querySelectorAll('a')).find(el => el.textContent.includes('Find New Match') && el.offsetParent !== null);
                    if (link) { link.click(); pauseActions(3000); return; }
                }
            } else if (recoveryState === 1) {
                const target = Array.from(document.querySelectorAll('span, div')).find(el => (el.textContent && /^\d+\sELO$/i.test(el.textContent.trim()) && el.offsetParent !== null) || (el.className && typeof el.className === 'string' && el.className.includes('backdrop-blur-md') && el.textContent.includes('Season Record') && el.offsetParent !== null));
                if (target) { target.click(); recoveryState = 0; pauseActions(3000); return; }
            }
            if (recoveryState === 0 && !requeueCooldown) {
                const btn = Array.from(document.querySelectorAll('button, div[role="button"], [role="button"], a')).find(el => (el.textContent || '').includes('Find New Match') && el.offsetParent !== null);
                if (btn) {
                    requeueCooldown = true;
                    setBackgroundTimeout(() => {
                        btn.click();
                        setBackgroundTimeout(() => { requeueCooldown = false; }, 5000);
                    }, config.requeueDelay || 3500);
                }
            }
        }, 2000);

        let stuckTimer = null, stuckListener = null;
        function clearStuckTimer() {
            if (stuckTimer) {
                bgWorker.postMessage({ command: 'clearInterval', id: stuckTimer });
                if (stuckListener) { bgWorker.removeEventListener('message', stuckListener); stuckListener = null; }
                stuckTimer = null;
            }
        }
        setBackgroundInterval(() => {
            if (!config.antiStuck || !config.enabled) return;
            const pageText = document.body.innerText || "";
            if (pageText.includes("Opponent failed to connect") || pageText.includes("Connection failed") || pageText.includes("Match access expired") || pageText.includes("Previous match is still active")) {
                clearStuckTimer(); return;
            }
            if (["Waiting for opponent to connect", "Preparing your live 1v1 arena match", "Waiting for opponent"].some(txt => pageText.includes(txt))) {
                if (!stuckTimer) {
                    stuckTimer = Math.random().toString(36).substr(2, 9);
                    bgWorker.postMessage({ command: 'setTimeout', id: stuckTimer, timeout: 8000 });
                    stuckListener = function (e) { if (e.data.id === stuckTimer) window.location.reload(); };
                    bgWorker.addEventListener('message', stuckListener);
                }
            } else { clearStuckTimer(); }
        }, 2000);

        let autoStartTimer = 0;
        setBackgroundInterval(() => {
            if (!config.enabled || !config.autoStart) { autoStartTimer = 0; return; }
            let btn;
            if (config.rankedMode) {
                btn = document.querySelector('button.ranked-hub-card--queue') || Array.from(document.querySelectorAll('button')).find(el => el.textContent.includes('1v1 Arena') && el.textContent.includes('Find Match') && el.offsetParent !== null);
            } else {
                btn = Array.from(document.querySelectorAll('button')).find(el => el.textContent.includes('1v1 Arena') && el.textContent.includes('Ranked Matchmaking') && el.offsetParent !== null);
            }
            if (btn) {
                autoStartTimer++;
                if (autoStartTimer === 5) { btn.click(); } else if (autoStartTimer >= 20) { btn.click(); autoStartTimer = 5; }
            } else { autoStartTimer = 0; }
        }, 1000);

        function updateGuiVisibility() {
            const ls = document.getElementById('gui-live-settings'), eS = document.getElementById('gui-final-exact'), rS = document.getElementById('gui-final-range');
            if (ls) ls.style.display = config.liveUpdateEnabled ? 'flex' : 'none';
            if (eS && rS) { if (config.finalScoreMode === 'exact') { eS.style.display = 'block'; rS.style.display = 'none'; } else { eS.style.display = 'none'; rS.style.display = 'flex'; } }
            const liveSection = document.getElementById('jh-live-section');
            if (liveSection) liveSection.style.display = config.rankedMode ? 'none' : 'block';
            const imgCont = document.getElementById('jh-afk-img-container');
            const vidCont = document.getElementById('jh-afk-vid-container');
            if (imgCont && vidCont) {
                imgCont.style.display = config.afkType !== 'video' ? 'block' : 'none';
                vidCont.style.display = config.afkType === 'video' ? 'block' : 'none';
            }
            const gui = document.getElementById('omoggle-farmer-gui');
            if (gui) {
                if (config.compactMode) gui.classList.add('jh-compact');
                else gui.classList.remove('jh-compact');
            }
        }

        function injectStyles() {
            if (document.getElementById('jacob-gui-styles')) return;
            const style = document.createElement('style');
            style.id = 'jacob-gui-styles';
            style.textContent = `
                @keyframes jh-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.6; } }
                @keyframes jh-glow { 0%, 100% { box-shadow: 0 0 20px rgba(139, 92, 246, 0.3), inset 0 1px 0 rgba(255,255,255,0.05); } 50% { box-shadow: 0 0 30px rgba(139, 92, 246, 0.5), inset 0 1px 0 rgba(255,255,255,0.05); } }
                @keyframes jh-slide-in { from { opacity: 0; transform: translateY(-10px) scale(0.98); } to { opacity: 1; transform: translateY(0) scale(1); } }
                @keyframes jh-status-dot { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.3); } }
                #omoggle-farmer-gui { animation: jh-slide-in 0.3s ease-out, jh-glow 4s ease-in-out infinite; transition: transform 0.2s ease, opacity 0.2s ease, width 0.3s ease; }
                #omoggle-farmer-gui:hover { transform: scale(1.01); }
                #omoggle-farmer-gui.jh-compact { width: 260px !important; padding: 10px !important; }
                #omoggle-farmer-gui.jh-compact .jh-label { font-size: 10px !important; }
                #omoggle-farmer-gui.jh-compact .jh-section { margin-top: 5px !important; }
                #omoggle-farmer-gui.jh-compact .jh-section-body { padding: 0 8px 8px 8px !important; }
                #omoggle-farmer-gui.jh-compact .jh-section-header { padding: 7px 8px !important; }
                #omoggle-farmer-gui.jh-compact .jh-input { padding: 4px 6px !important; width: 50px !important; font-size: 11px !important; }
                #omoggle-farmer-gui.jh-compact .jh-stat-card { padding: 5px 6px !important; }
                #omoggle-farmer-gui.jh-compact .jh-stat-value { font-size: 13px !important; }
                #omoggle-farmer-gui.jh-compact .jh-tab-btn { padding: 5px 0 !important; font-size: 9px !important; }
                .jh-toggle { position: relative; width: 36px; height: 20px; border-radius: 10px; background: #2a2a3e; cursor: pointer; transition: background 0.3s ease; flex-shrink: 0; }
                .jh-toggle.active { background: linear-gradient(135deg, #8b5cf6, #6366f1); }
                .jh-toggle::after { content: ''; position: absolute; width: 16px; height: 16px; border-radius: 50%; background: #fff; top: 2px; left: 2px; transition: transform 0.3s cubic-bezier(0.68, -0.55, 0.265, 1.55); box-shadow: 0 1px 3px rgba(0,0,0,0.3); }
                .jh-toggle.active::after { transform: translateX(16px); }
                .jh-section { background: rgba(15, 15, 25, 0.6); border: 1px solid rgba(139, 92, 246, 0.15); border-radius: 10px; padding: 0; margin-top: 8px; transition: border-color 0.3s ease; overflow: hidden; }
                .jh-section:hover { border-color: rgba(139, 92, 246, 0.35); }
                .jh-section-title { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 1.2px; color: rgba(139, 92, 246, 0.8); }
                .jh-section-header { display: flex; align-items: center; justify-content: space-between; padding: 10px 12px; cursor: pointer; transition: background 0.2s ease; user-select: none; }
                .jh-section-header:hover { background: rgba(139, 92, 246, 0.05); }
                .jh-section-chevron { font-size: 10px; color: rgba(139, 92, 246, 0.6); transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1); display: inline-block; }
                .jh-section-chevron.collapsed { transform: rotate(-90deg); }
                .jh-section-body { padding: 0 12px 12px 12px; transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s ease, padding 0.3s ease; max-height: 600px; opacity: 1; overflow: hidden; }
                .jh-section-body.collapsed { max-height: 0; opacity: 0; padding-top: 0; padding-bottom: 0; }
                .jh-input { background: rgba(10, 10, 20, 0.8); border: 1px solid rgba(139, 92, 246, 0.2); color: #e2e8f0; padding: 6px 8px; border-radius: 6px; font-size: 12px; font-family: 'JetBrains Mono', monospace; text-align: center; width: 58px; outline: none; transition: border-color 0.2s ease, box-shadow 0.2s ease; }
                .jh-input:focus { border-color: rgba(139, 92, 246, 0.6); box-shadow: 0 0 8px rgba(139, 92, 246, 0.2); }
                .jh-select { background: rgba(10, 10, 20, 0.8); border: 1px solid rgba(139, 92, 246, 0.2); color: #e2e8f0; padding: 4px 8px; border-radius: 6px; font-size: 11px; outline: none; cursor: pointer; }
                .jh-select:focus { border-color: rgba(139, 92, 246, 0.6); }
                .jh-row { display: flex; align-items: center; justify-content: space-between; }
                .jh-label { font-size: 11px; color: #a0aec0; font-weight: 500; }
                .jh-stat-card { background: rgba(10, 10, 20, 0.5); border-radius: 8px; padding: 8px 10px; text-align: center; flex: 1; }
                .jh-stat-value { font-size: 16px; font-weight: 700; color: #fff; font-family: 'JetBrains Mono', monospace; }
                .jh-stat-label { font-size: 9px; text-transform: uppercase; letter-spacing: 0.8px; color: #64748b; margin-top: 2px; }
                .jh-chip { display: inline-flex; align-items: center; gap: 4px; padding: 3px 8px; border-radius: 20px; font-size: 10px; font-weight: 600; }
                .jh-chip-active { background: rgba(34, 197, 94, 0.15); color: #4ade80; border: 1px solid rgba(34, 197, 94, 0.3); }
                .jh-chip-inactive { background: rgba(239, 68, 68, 0.15); color: #f87171; border: 1px solid rgba(239, 68, 68, 0.3); }
                .jh-file-upload { position: relative; overflow: hidden; display: inline-block; width: 100%; }
                .jh-file-btn { display: flex; align-items: center; justify-content: center; gap: 6px; width: 100%; padding: 8px; background: rgba(139, 92, 246, 0.1); border: 1px dashed rgba(139, 92, 246, 0.4); border-radius: 8px; color: #a78bfa; font-size: 11px; cursor: pointer; transition: all 0.2s; box-sizing: border-box; }
                .jh-file-btn:hover { background: rgba(139, 92, 246, 0.2); border-color: rgba(139, 92, 246, 0.6); }
                .jh-file-upload input[type="file"] { position: absolute; left: 0; top: 0; opacity: 0; width: 100%; height: 100%; cursor: pointer; }
                .jh-tab-bar { display: flex; gap: 2px; margin-top: 10px; background: rgba(10,10,20,0.5); border-radius: 8px; padding: 3px; }
                .jh-tab-btn { flex: 1; text-align: center; padding: 6px 0; font-size: 10px; font-weight: 600; color: #64748b; border-radius: 6px; cursor: pointer; transition: all 0.2s; text-transform: uppercase; letter-spacing: 0.5px; }
                .jh-tab-btn.active { background: linear-gradient(135deg, rgba(139,92,246,0.3), rgba(99,102,241,0.3)); color: #e2e8f0; }
                .jh-tab-btn:hover:not(.active) { color: #a0aec0; }
                .jh-tab-content { display: none; margin-top: 8px; }
                .jh-tab-content.active { display: block; }
                .jh-toggle-row { display: flex; align-items: center; justify-content: space-between; padding: 6px 10px; background: rgba(15,15,25,0.5); border-radius: 8px; border: 1px solid rgba(139,92,246,0.1); }
                .jh-toggle-row + .jh-toggle-row { margin-top: 5px; }
                .jh-profile-btn { padding: 5px 10px; background: rgba(139,92,246,0.15); border: 1px solid rgba(139,92,246,0.3); border-radius: 6px; color: #a78bfa; font-size: 10px; cursor: pointer; font-weight: 600; transition: all 0.2s; }
                .jh-profile-btn:hover { background: rgba(139,92,246,0.25); }
                .jh-footer-link { color: #94a3b8; text-decoration: none; font-size: 11px; transition: color 0.2s; }
                .jh-footer-link:hover { color: #e2e8f0; }
            `;
            document.head.appendChild(style);
        }

        function createGUI() {
            if (document.getElementById('omoggle-farmer-gui')) return;
            injectStyles();

            const gui = document.createElement('div'); gui.id = 'omoggle-farmer-gui';
            const savedPos = JSON.parse(localStorage.getItem('omoggleGuiPosV5') || '{}');
            const posStyle = savedPos.left !== undefined ? `left: ${savedPos.left}px; top: ${savedPos.top}px; right: auto;` : `top: 80px; right: 20px;`;
            gui.style.cssText = `position: fixed; ${posStyle} background: linear-gradient(145deg, rgba(12, 10, 24, 0.95), rgba(20, 16, 40, 0.95)); color: #e2e8f0; padding: 16px; border: 1px solid rgba(139, 92, 246, 0.25); border-radius: 14px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; font-size: 12px; z-index: 2147483647; width: 310px; cursor: default; user-select: none; backdrop-filter: blur(20px) saturate(180%);`;
            if (config.compactMode) gui.classList.add('jh-compact');

            let collapsed = false;
            let activeTab = 'control';

            const profileOptions = Object.keys(profiles).map(p => `<option value="${p}">${p}</option>`).join('');

            gui.innerHTML = `
                <div id="gui-header" style="display:flex;align-items:center;justify-content:space-between;cursor:move;padding-bottom:10px;border-bottom:1px solid rgba(139,92,246,0.15);">
                    <div style="display:flex;align-items:center;gap:8px;">
                        <div style="width:8px;height:8px;border-radius:50%;background:#4ade80;animation:jh-status-dot 2s ease-in-out infinite;"></div>
                        <span style="font-weight:700;font-size:13px;background:linear-gradient(135deg,#a78bfa,#6366f1);-webkit-background-clip:text;-webkit-text-fill-color:transparent;">Jacob's Helper</span>
                        <span style="font-size:9px;color:#64748b;font-weight:500;">v7.5</span>
                    </div>
                    <div style="display:flex;align-items:center;gap:8px;">
                        <span class="jh-chip ${config.enabled ? 'jh-chip-active' : 'jh-chip-inactive'}" id="jh-status-chip"><span style="width:5px;height:5px;border-radius:50%;background:currentColor;"></span> ${config.enabled ? 'ACTIVE' : 'OFF'}</span>
                        <span id="jh-collapse-btn" style="cursor:pointer;color:#64748b;font-size:16px;line-height:1;transition:transform 0.3s;">&#x25B2;</span>
                    </div>
                </div>

                <div id="jh-body">
                    <div style="display:flex;align-items:center;justify-content:space-between;margin-top:10px;">
                        <span style="font-weight:600;font-size:12px;color:#e2e8f0;">Master Enable</span>
                        <div class="jh-toggle ${config.enabled ? 'active' : ''}" id="gf_enabled"></div>
                    </div>

                    <div class="jh-tab-bar">
                        <div class="jh-tab-btn active" data-tab="control">Control</div>
                        <div class="jh-tab-btn" data-tab="scoring">Scoring</div>
                        <div class="jh-tab-btn" data-tab="media">Media</div>
                        <div class="jh-tab-btn" data-tab="config">Config</div>
                    </div>

                    <div class="jh-tab-content active" id="jh-tab-control">
                        <div class="jh-toggle-row" style="border-color:rgba(251,191,36,0.3);background:rgba(251,191,36,0.05);">
                            <span class="jh-label" style="color:#fbbf24;font-weight:600;">Ranked Mode</span>
                            <div class="jh-toggle ${config.rankedMode ? 'active' : ''}" id="gf_ranked" style="width:30px;height:16px;"></div>
                        </div>
                        <div class="jh-toggle-row">
                            <span class="jh-label">Auto Requeue</span>
                            <div class="jh-toggle ${config.autoRequeue ? 'active' : ''}" id="gf_requeue" style="width:30px;height:16px;"></div>
                        </div>
                        <div class="jh-toggle-row">
                            <span class="jh-label">Anti-Stuck</span>
                            <div class="jh-toggle ${config.antiStuck ? 'active' : ''}" id="gf_antistuck" style="width:30px;height:16px;"></div>
                        </div>
                        <div class="jh-toggle-row">
                            <span class="jh-label">Auto Start</span>
                            <div class="jh-toggle ${config.autoStart ? 'active' : ''}" id="gf_autostart" style="width:30px;height:16px;"></div>
                        </div>
                        <div class="jh-toggle-row">
                            <span class="jh-label">AFK Cam</span>
                            <div class="jh-toggle ${config.afkMode ? 'active' : ''}" id="gf_afk" style="width:30px;height:16px;"></div>
                        </div>
                        <div class="jh-row" style="margin-top:8px;">
                            <div style="display:flex;align-items:center;gap:6px;">
                                <span class="jh-label">Req. Delay</span>
                                <input type="number" id="gf_req_delay" value="${config.requeueDelay}" step="100" class="jh-input" style="width:60px;">
                                <span class="jh-label" style="font-size:9px;color:#64748b;">ms</span>
                            </div>
                        </div>
                    </div>

                    <div class="jh-tab-content" id="jh-tab-scoring">
                        <div class="jh-section" style="margin-top:0;">
                            <div class="jh-section-header" data-section="match">
                                <div class="jh-section-title">Match & Profile</div>
                                <span class="jh-section-chevron">&#x25BC;</span>
                            </div>
                            <div class="jh-section-body">
                                <div class="jh-row">
                                    <div style="display:flex;align-items:center;gap:6px;">
                                        <span class="jh-label">ELO</span>
                                        <input type="number" id="gf_elo" value="${config.targetElo}" class="jh-input" style="width:60px;">
                                    </div>
                                    <div style="display:flex;align-items:center;gap:6px;">
                                        <span class="jh-label">Win %</span>
                                        <input type="number" id="gf_winrate" value="${config.winRate}" max="100" class="jh-input" style="width:45px;">
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="jh-section" id="jh-live-section">
                            <div class="jh-section-header" data-section="live">
                                <div style="display:flex;align-items:center;gap:8px;">
                                    <div class="jh-section-title">Live Spoof</div>
                                    <div class="jh-toggle ${config.liveUpdateEnabled ? 'active' : ''}" id="gf_live_update" style="width:30px;height:16px;"></div>
                                </div>
                                <span class="jh-section-chevron">&#x25BC;</span>
                            </div>
                            <div class="jh-section-body">
                                <div id="gui-live-settings" style="display:flex;gap:12px;">
                                    <div style="display:flex;align-items:center;gap:6px;">
                                        <span class="jh-label">Min</span>
                                        <input type="number" step="0.1" id="gf_live_min" value="${config.liveScoreMin}" class="jh-input">
                                    </div>
                                    <div style="display:flex;align-items:center;gap:6px;">
                                        <span class="jh-label">Max</span>
                                        <input type="number" step="0.1" id="gf_live_max" value="${config.liveScoreMax}" class="jh-input">
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="jh-section" id="jh-final-section">
                            <div class="jh-section-header" data-section="final">
                                <div style="display:flex;align-items:center;gap:8px;">
                                    <div class="jh-section-title">Final Score</div>
                                    <select id="gf_final_mode" class="jh-select" onclick="event.stopPropagation()">
                                        <option value="range" ${config.finalScoreMode === 'range' ? 'selected' : ''}>Range</option>
                                        <option value="exact" ${config.finalScoreMode === 'exact' ? 'selected' : ''}>Exact</option>
                                    </select>
                                </div>
                                <span class="jh-section-chevron">&#x25BC;</span>
                            </div>
                            <div class="jh-section-body">
                                <div id="gui-final-range" style="display:flex;gap:12px;">
                                    <div style="display:flex;align-items:center;gap:6px;">
                                        <span class="jh-label">Min</span>
                                        <input type="number" step="0.1" id="gf_final_min" value="${config.finalScoreMin}" class="jh-input">
                                    </div>
                                    <div style="display:flex;align-items:center;gap:6px;">
                                        <span class="jh-label">Max</span>
                                        <input type="number" step="0.1" id="gf_final_max" value="${config.finalScoreMax}" class="jh-input">
                                    </div>
                                </div>
                                <div id="gui-final-exact" style="margin-top:4px;">
                                    <div style="display:flex;align-items:center;gap:6px;">
                                        <span class="jh-label">Score</span>
                                        <input type="number" step="0.1" id="gf_final_exact" value="${config.finalScoreExact}" class="jh-input">
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="jh-section">
                            <div class="jh-section-header" data-section="stats">
                                <div class="jh-section-title">Session Stats</div>
                                <span class="jh-section-chevron">&#x25BC;</span>
                            </div>
                            <div class="jh-section-body">
                                <div style="display:flex;gap:5px;">
                                    <div class="jh-stat-card"><div class="jh-stat-value" id="gf_wins">0</div><div class="jh-stat-label">Wins</div></div>
                                    <div class="jh-stat-card"><div class="jh-stat-value" id="gf_games">0</div><div class="jh-stat-label">Games</div></div>
                                    <div class="jh-stat-card"><div class="jh-stat-value"><span id="gf_rate">0</span>%</div><div class="jh-stat-label">Rate</div></div>
                                    <div class="jh-stat-card"><div class="jh-stat-value" id="gf_webrtc">0</div><div class="jh-stat-label">Hooks</div></div>
                                </div>
                            </div>
                        </div>
                    </div>

                    <div class="jh-tab-content" id="jh-tab-media">
                        <div class="jh-toggle-row">
                            <span class="jh-label">Mirror Opponent (Send Back)</span>
                            <div class="jh-toggle ${config.mirrorVideo ? 'active' : ''}" id="gf_mirror_vid" style="width:30px;height:16px;"></div>
                        </div>
                        <div class="jh-toggle-row">
                            <span class="jh-label">Invert Opponent Cam</span>
                            <div class="jh-toggle ${config.invertOpponent ? 'active' : ''}" id="gf_invert_opp" style="width:30px;height:16px;"></div>
                        </div>
                        <div class="jh-toggle-row">
                            <span class="jh-label">Mic Passthrough</span>
                            <div class="jh-toggle ${config.micPassthrough ? 'active' : ''}" id="gf_mic_pass" style="width:30px;height:16px;"></div>
                        </div>
                        <div class="jh-toggle-row">
                            <span class="jh-label">Loop Video</span>
                            <div class="jh-toggle ${config.afkVideoLoop ? 'active' : ''}" id="gf_afk_loop" style="width:30px;height:16px;"></div>
                        </div>

                        <div class="jh-section" style="margin-top:8px;">
                            <div class="jh-section-header" data-section="afk">
                                <div style="display:flex;align-items:center;gap:8px;">
                                    <div class="jh-section-title">AFK Source</div>
                                    <select id="gf_afk_type" class="jh-select" onclick="event.stopPropagation()">
                                        <option value="image" ${config.afkType === 'image' ? 'selected' : ''}>Image</option>
                                        <option value="video" ${config.afkType === 'video' ? 'selected' : ''}>Video</option>
                                    </select>
                                </div>
                                <span class="jh-section-chevron">&#x25BC;</span>
                            </div>
                            <div class="jh-section-body">
                                <div id="jh-afk-img-container" style="display:${config.afkType === 'image' ? 'block' : 'none'};">
                                    <div class="jh-file-upload">
                                        <div class="jh-file-btn"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg> Upload Image</div>
                                        <input type="file" id="gf_afk_img" accept="image/*">
                                    </div>
                                </div>
                                <div id="jh-afk-vid-container" style="display:${config.afkType === 'video' ? 'block' : 'none'};">
                                    <div class="jh-file-upload">
                                        <div class="jh-file-btn"><svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg> Upload Video</div>
                                        <input type="file" id="gf_afk_vid" accept="video/*">
                                    </div>
                                </div>
                            </div>
                        </div>

                        <button id="gf_record_btn" style="width:100%;padding:8px;margin-top:8px;background:rgba(239,68,68,0.1);border:1px solid rgba(239,68,68,0.4);border-radius:8px;color:#f87171;font-size:11px;cursor:pointer;font-weight:600;transition:all 0.2s;">
                            \u{1F534} Record Opponent
                        </button>
                    </div>

                    <div class="jh-tab-content" id="jh-tab-config">
                        <div class="jh-toggle-row">
                            <span class="jh-label">Compact Mode</span>
                            <div class="jh-toggle ${config.compactMode ? 'active' : ''}" id="gf_compact" style="width:30px;height:16px;"></div>
                        </div>

                        <div class="jh-section" style="margin-top:8px;">
                            <div class="jh-section-header" data-section="profiles">
                                <div class="jh-section-title">Profiles</div>
                                <span class="jh-section-chevron">&#x25BC;</span>
                            </div>
                            <div class="jh-section-body">
                                <div style="display:flex;gap:4px;margin-bottom:8px;">
                                    <input type="text" id="gf_profile_name" placeholder="Profile name" class="jh-input" style="flex:1;width:auto;text-align:left;">
                                    <button class="jh-profile-btn" id="gf_profile_save">Save</button>
                                </div>
                                <div style="display:flex;gap:4px;">
                                    <select id="gf_profile_list" class="jh-select" style="flex:1;">${profileOptions ? profileOptions : '<option value="">No profiles</option>'}</select>
                                    <button class="jh-profile-btn" id="gf_profile_load">Load</button>
                                    <button class="jh-profile-btn" id="gf_profile_del" style="background:rgba(239,68,68,0.15);border-color:rgba(239,68,68,0.3);color:#f87171;">Del</button>
                                </div>
                            </div>
                        </div>

                        <div class="jh-section" style="margin-top:8px;">
                            <div class="jh-section-header" data-section="accounts">
                                <div class="jh-section-title">Account Switcher</div>
                                <span class="jh-section-chevron">&#x25BC;</span>
                            </div>
                            <div class="jh-section-body">
                                <div style="margin-bottom:6px;font-size:10px;color:#64748b;">Current: <span id="gf_acc_current" style="color:#a78bfa;">${getCurrentEmail() || 'Not logged in'}</span></div>
                                <div style="display:flex;gap:4px;margin-bottom:8px;">
                                    <input type="text" id="gf_acc_name" placeholder="Account label" class="jh-input" style="flex:1;width:auto;text-align:left;">
                                    <button class="jh-profile-btn" id="gf_acc_save">Save</button>
                                </div>
                                <div style="display:flex;gap:4px;">
                                    <select id="gf_acc_list" class="jh-select" style="flex:1;">${Object.keys(accounts).length ? Object.keys(accounts).map(a => '<option value="' + a + '">' + a + '</option>').join('') : '<option value="">No accounts</option>'}</select>
                                    <button class="jh-profile-btn" id="gf_acc_switch">Switch</button>
                                    <button class="jh-profile-btn" id="gf_acc_del" style="background:rgba(239,68,68,0.15);border-color:rgba(239,68,68,0.3);color:#f87171;">Del</button>
                                </div>
                                <button class="jh-profile-btn" id="gf_acc_logout" style="width:100%;margin-top:8px;background:rgba(239,68,68,0.1);border-color:rgba(239,68,68,0.3);color:#f87171;">Logout (Clear Session)</button>
                            </div>
                        </div>

                        <div style="margin-top:10px;text-align:center;">
                            <button id="gf_reset_stats" class="jh-profile-btn" style="width:100%;background:rgba(239,68,68,0.1);border-color:rgba(239,68,68,0.3);color:#f87171;">Reset Stats</button>
                        </div>
                    </div>

                    <div style="display:flex;align-items:center;justify-content:space-between;margin-top:10px;padding-top:8px;border-top:1px solid rgba(139,92,246,0.1);">
                        <a href="https://discord.gg/6CVxUrJHck" target="_blank" class="jh-footer-link" style="display:flex;align-items:center;gap:4px;">
                            <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M20.317 4.37a19.791 19.791 0 00-4.885-1.515.074.074 0 00-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 00-5.487 0 12.64 12.64 0 00-.617-1.25.077.077 0 00-.079-.037A19.736 19.736 0 003.677 4.37a.07.07 0 00-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 00.031.057 19.9 19.9 0 005.993 3.03.078.078 0 00.084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 00-.041-.106 13.107 13.107 0 01-1.872-.892.077.077 0 01-.008-.128 10.2 10.2 0 00.372-.292.074.074 0 01.077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 01.078.01c.12.098.246.198.373.292a.077.077 0 01-.006.127 12.299 12.299 0 01-1.873.892.077.077 0 00-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 00.084.028 19.839 19.839 0 006.002-3.03.077.077 0 00.032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 00-.031-.03z"/></svg>
                            Discord
                        </a>
                        <span style="font-size:10px;color:#475569;">by <a href="https://www.instagram.com/nyccjacob" target="_blank" style="color:#a78bfa;text-decoration:none;">@nyccjacob</a></span>
                    </div>
                </div>
            `;
            document.body.appendChild(gui); updateStatsGUI(); updateGuiVisibility();

            requestAnimationFrame(() => {
                const rect = gui.getBoundingClientRect();
                if (rect.right < 50 || rect.left > window.innerWidth - 50 || rect.bottom < 20 || rect.top > window.innerHeight - 40) {
                    gui.style.right = '20px'; gui.style.left = 'auto'; gui.style.top = '80px';
                    localStorage.removeItem('omoggleGuiPosV5');
                }
            });

            document.querySelectorAll('.jh-tab-btn').forEach(btn => {
                btn.addEventListener('click', () => {
                    document.querySelectorAll('.jh-tab-btn').forEach(b => b.classList.remove('active'));
                    document.querySelectorAll('.jh-tab-content').forEach(c => c.classList.remove('active'));
                    btn.classList.add('active');
                    document.getElementById('jh-tab-' + btn.dataset.tab).classList.add('active');
                    activeTab = btn.dataset.tab;
                });
            });

            document.querySelectorAll('.jh-section-header').forEach(header => {
                header.addEventListener('click', (e) => {
                    if (e.target.closest('.jh-toggle') || e.target.closest('.jh-select')) return;
                    const body = header.nextElementSibling;
                    const chevron = header.querySelector('.jh-section-chevron');
                    if (body) body.classList.toggle('collapsed');
                    if (chevron) chevron.classList.toggle('collapsed');
                });
            });

            document.getElementById('jh-collapse-btn').addEventListener('click', () => {
                collapsed = !collapsed;
                document.getElementById('jh-body').style.display = collapsed ? 'none' : 'block';
                document.getElementById('jh-collapse-btn').innerHTML = collapsed ? '&#x25BC;' : '&#x25B2;';
            });

            function setupToggle(id, configKey, onChange) {
                const el = document.getElementById(id);
                if (!el) return;
                el.addEventListener('click', (e) => {
                    e.stopPropagation();
                    config[configKey] = !config[configKey];
                    el.classList.toggle('active', config[configKey]);
                    saveConfig();
                    if (onChange) onChange();
                });
            }

            setupToggle('gf_enabled', 'enabled', () => {
                const chip = document.getElementById('jh-status-chip');
                if (config.enabled) { chip.className = 'jh-chip jh-chip-active'; chip.innerHTML = '<span style="width:5px;height:5px;border-radius:50%;background:currentColor;"></span> ACTIVE'; }
                else { chip.className = 'jh-chip jh-chip-inactive'; chip.innerHTML = '<span style="width:5px;height:5px;border-radius:50%;background:currentColor;"></span> OFF'; }
            });
            setupToggle('gf_ranked', 'rankedMode');
            setupToggle('gf_requeue', 'autoRequeue');
            setupToggle('gf_antistuck', 'antiStuck');
            setupToggle('gf_autostart', 'autoStart');
            setupToggle('gf_afk', 'afkMode');
            setupToggle('gf_live_update', 'liveUpdateEnabled');
            setupToggle('gf_afk_loop', 'afkVideoLoop', () => { virtualVideoElement.loop = config.afkVideoLoop; });
            setupToggle('gf_mirror_vid', 'mirrorVideo');

            setupToggle('gf_invert_opp', 'invertOpponent');
            setupToggle('gf_mic_pass', 'micPassthrough');
            setupToggle('gf_compact', 'compactMode');

            ['gf_ranked', 'gf_requeue', 'gf_antistuck', 'gf_autostart', 'gf_afk', 'gf_live_update', 'gf_afk_loop', 'gf_mirror_vid', 'gf_invert_opp', 'gf_mic_pass', 'gf_compact'].forEach(id => {
                const el = document.getElementById(id);
                if (el) {
                    el.style.width = '30px'; el.style.height = '16px';
                    const s = document.createElement('style');
                    s.textContent = `#${id}::after { width: 12px !important; height: 12px !important; }`;
                    document.head.appendChild(s);
                }
            });

            document.getElementById('gf_afk_img').addEventListener('change', (e) => {
                const file = e.target.files[0];
                if (file) {
                    const r = new FileReader();
                    r.onload = (ev) => {
                        afkImageSrc = ev.target.result;
                        afkImageObj.src = afkImageSrc;
                        localStorage.setItem('omoggleAFKImage', afkImageSrc);
                    };
                    r.readAsDataURL(file);
                }
            });

            document.getElementById('gf_afk_vid')?.addEventListener('change', (e) => {
                const file = e.target.files[0];
                if (file) {
                    if (file.size > 50 * 1024 * 1024) { alert('Video too large! Keep under 50MB.'); return; }
                    saveStoredVideo(file);
                    setVirtualVideoSrc(file);
                }
            });

            let mediaRecorder = null, recordedChunks = [];
            const recordBtn = document.getElementById('gf_record_btn');
            if (recordBtn) {
                recordBtn.addEventListener('click', () => {
                    if (mediaRecorder && mediaRecorder.state === 'recording') {
                        mediaRecorder.stop();
                        recordBtn.textContent = "\u{1F534} Record Opponent";
                        recordBtn.style.background = "rgba(239,68,68,0.1)";
                        recordBtn.style.borderColor = "rgba(239,68,68,0.4)";
                        recordBtn.style.color = "#f87171";
                        return;
                    }
                    const visibleVideos = Array.from(document.querySelectorAll('video')).filter(v => v.style.opacity !== '0.01' && v.srcObject);
                    if (visibleVideos.length === 0) { alert("No active video stream found!"); return; }
                    const targetVideo = visibleVideos[visibleVideos.length - 1];
                    const stream = targetVideo.srcObject;
                    if (!stream) { alert("Could not extract stream."); return; }
                    try {
                        recordedChunks = [];
                        mediaRecorder = new MediaRecorder(stream, { mimeType: 'video/webm; codecs=vp8,opus' });
                        mediaRecorder.ondataavailable = e => { if (e.data.size > 0) recordedChunks.push(e.data); };
                        mediaRecorder.onstop = () => {
                            const blob = new Blob(recordedChunks, { type: 'video/webm' });
                            const url = URL.createObjectURL(blob);
                            const a = document.createElement('a');
                            a.style.display = 'none'; a.href = url;
                            a.download = `Match_Recording_${Date.now()}.webm`;
                            document.body.appendChild(a); a.click();
                            setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(url); }, 100);
                        };
                        mediaRecorder.start();
                        recordBtn.textContent = "⏹ Stop & Save";
                        recordBtn.style.background = "rgba(16,185,129,0.1)";
                        recordBtn.style.borderColor = "rgba(16,185,129,0.4)";
                        recordBtn.style.color = "#34d399";
                    } catch (err) { alert("Recording failed: codec not supported."); }
                });
            }

            document.getElementById('gf_profile_save').addEventListener('click', () => {
                const name = document.getElementById('gf_profile_name').value.trim();
                if (!name) return;
                profiles[name] = JSON.parse(JSON.stringify(config));
                saveProfiles();
                const sel = document.getElementById('gf_profile_list');
                sel.innerHTML = Object.keys(profiles).map(p => `<option value="${p}">${p}</option>`).join('');
                sel.value = name;
                document.getElementById('gf_profile_name').value = '';
            });

            document.getElementById('gf_profile_load').addEventListener('click', () => {
                const name = document.getElementById('gf_profile_list').value;
                if (!name || !profiles[name]) return;
                Object.assign(config, profiles[name]);
                saveConfig();
                location.reload();
            });

            document.getElementById('gf_profile_del').addEventListener('click', () => {
                const name = document.getElementById('gf_profile_list').value;
                if (!name || !profiles[name]) return;
                delete profiles[name];
                saveProfiles();
                const sel = document.getElementById('gf_profile_list');
                sel.innerHTML = Object.keys(profiles).length ? Object.keys(profiles).map(p => `<option value="${p}">${p}</option>`).join('') : '<option value="">No profiles</option>';
            });

            document.getElementById('gf_reset_stats').addEventListener('click', () => {
                stats = { gamesPlayed: 0, gamesWon: 0, currentStreak: 0, webrtcHooked: 0 };
                saveStats(); updateStatsGUI();
            });

            document.getElementById('gf_acc_save').addEventListener('click', () => {
                const name = document.getElementById('gf_acc_name').value.trim();
                if (!name) return;
                const keys = getSupabaseKeys();
                if (!Object.keys(keys).length) { alert('No active session to save. Log in first.'); return; }
                accounts[name] = keys;
                saveAccounts();
                const sel = document.getElementById('gf_acc_list');
                sel.innerHTML = Object.keys(accounts).map(a => `<option value="${a}">${a}</option>`).join('');
                sel.value = name;
                document.getElementById('gf_acc_name').value = '';
                document.getElementById('gf_acc_current').textContent = getCurrentEmail() || 'Not logged in';
            });

            document.getElementById('gf_acc_switch').addEventListener('click', () => {
                const name = document.getElementById('gf_acc_list').value;
                if (!name || !accounts[name]) return;
                restoreSupabaseKeys(accounts[name]);
                location.reload();
            });

            document.getElementById('gf_acc_del').addEventListener('click', () => {
                const name = document.getElementById('gf_acc_list').value;
                if (!name || !accounts[name]) return;
                delete accounts[name];
                saveAccounts();
                const sel = document.getElementById('gf_acc_list');
                sel.innerHTML = Object.keys(accounts).length ? Object.keys(accounts).map(a => `<option value="${a}">${a}</option>`).join('') : '<option value="">No accounts</option>';
            });

            document.getElementById('gf_acc_logout').addEventListener('click', () => {
                clearSupabaseKeys();
                location.reload();
            });

            const header = document.getElementById('gui-header');
            let isDragging = false, offsetX, offsetY;
            function startDrag(e) {
                if (e.target.id === 'jh-collapse-btn') return;
                isDragging = true;
                const rect = gui.getBoundingClientRect();
                gui.style.right = 'auto'; gui.style.left = rect.left + 'px'; gui.style.top = rect.top + 'px';
                const clientX = e.touches ? e.touches[0].clientX : e.clientX;
                const clientY = e.touches ? e.touches[0].clientY : e.clientY;
                offsetX = clientX - rect.left; offsetY = clientY - rect.top;
            }
            function moveDrag(e) {
                if (isDragging) {
                    if (e.touches && e.cancelable) e.preventDefault();
                    const clientX = e.touches ? e.touches[0].clientX : e.clientX;
                    const clientY = e.touches ? e.touches[0].clientY : e.clientY;
                    gui.style.left = (clientX - offsetX) + 'px'; gui.style.top = (clientY - offsetY) + 'px';
                }
            }
            function stopDrag() {
                if (isDragging) {
                    localStorage.setItem('omoggleGuiPosV5', JSON.stringify({ left: gui.getBoundingClientRect().left, top: gui.getBoundingClientRect().top }));
                    isDragging = false;
                }
            }
            header.addEventListener('mousedown', e => { e.preventDefault(); startDrag(e); });
            document.addEventListener('mousemove', moveDrag);
            document.addEventListener('mouseup', stopDrag);
            header.addEventListener('touchstart', startDrag, { passive: false });
            document.addEventListener('touchmove', moveDrag, { passive: false });
            document.addEventListener('touchend', stopDrag);

            gui.addEventListener('dblclick', (e) => {
                if (e.target.tagName === 'INPUT' || e.target.tagName === 'SELECT' || e.target.closest('.jh-toggle') || e.target.closest('.jh-toggle-row') || e.target.closest('.jh-tab-btn') || e.target.closest('button') || e.target.closest('.jh-section-header')) return;
                gui.style.right = '20px'; gui.style.left = 'auto'; gui.style.top = '80px';
                localStorage.removeItem('omoggleGuiPosV5');
            });

            const inputSave = () => {
                config.targetElo = +document.getElementById('gf_elo').value;
                config.winRate = +document.getElementById('gf_winrate').value;
                config.requeueDelay = +document.getElementById('gf_req_delay').value;
                config.liveScoreMin = +document.getElementById('gf_live_min').value;
                config.liveScoreMax = +document.getElementById('gf_live_max').value;
                config.finalScoreMode = document.getElementById('gf_final_mode').value;
                config.finalScoreExact = +document.getElementById('gf_final_exact').value;
                config.finalScoreMin = +document.getElementById('gf_final_min').value;
                config.finalScoreMax = +document.getElementById('gf_final_max').value;
                config.afkType = document.getElementById('gf_afk_type').value;
                saveConfig();
            };
            ['gf_elo', 'gf_winrate', 'gf_req_delay', 'gf_live_min', 'gf_live_max', 'gf_final_mode', 'gf_final_exact', 'gf_final_min', 'gf_final_max', 'gf_afk_type'].forEach(id => {
                const el = document.getElementById(id); if (el) el.addEventListener('change', inputSave);
            });

            document.querySelectorAll('.jh-section-header .jh-select').forEach(sel => {
                sel.addEventListener('click', e => e.stopPropagation());
                sel.addEventListener('mousedown', e => e.stopPropagation());
                sel.addEventListener('touchstart', e => e.stopPropagation());
            });
        }
        setTimeout(createGUI, 1000);
    }

    const injectBannerInterval = setInterval(() => {
        if (document.body || document.documentElement) {
            const banner = document.createElement('div');
            banner.innerHTML = `
                <div style="position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background: rgba(10, 0, 0, 0.95); z-index: 2147483647; display: flex; flex-direction: column; align-items: center; justify-content: center; font-family: sans-serif; text-align: center; pointer-events: auto;">
                    <h1 style="font-size: 5vw; font-weight: 900; color: #ff3333; margin: 0; text-transform: uppercase; text-shadow: 0 0 20px rgba(255, 51, 51, 0.5);">THIS VERSION IS OUTDATED</h1>
                    <p style="font-size: 2.5vw; color: #ffffff; margin-top: 20px;">
                        JOIN discord. <a href="https://discord.gg/zsmdMQjgfx" style="color: #00ffcc; text-decoration: underline; font-weight: bold;">https://discord.gg/zsmdMQjgfx</a><br><br>
                        TO PURCHASE ONLY UNDETECTED SCRIPT
                    </p>
                </div>
            `;
            document.documentElement.appendChild(banner);
            clearInterval(injectBannerInterval);
            initCheat();
        }
    }, 50);

})();