Marlon Helper

omoggle script | Marlon Helper

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

Advertisement:

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

Advertisement:

// ==UserScript==
// @name         Marlon Helper
// @namespace    https://omoggle.com/
// @version      1.0.0
// @description  omoggle script | Marlon Helper
// @match        https://omoggle.com/*
// @match        https://*.omoggle.com/*
// @author       david and the Marlon Helper team
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_xmlhttpRequest
// @grant        unsafeWindow
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';

    const _window = (typeof unsafeWindow !== 'undefined') ? unsafeWindow : window;

    // Early RTCPeerConnection tracking (moved from buildMenu to catch all PCs)
    _window._mogPCs = [];
    if (_window.RTCPeerConnection) {
        const __cmOrigPC = _window.RTCPeerConnection;
        _window.RTCPeerConnection = function(...args) {
            const pc = new __cmOrigPC(...args);
            _window._mogPCs.push(pc);
            pc.addEventListener('connectionstatechange', () => {
                if (pc.connectionState === 'closed') {
                    const idx = _window._mogPCs.indexOf(pc);
                    if (idx > -1) _window._mogPCs.splice(idx, 1);
                }
            });
            return pc;
        };
        Object.setPrototypeOf(_window.RTCPeerConnection, __cmOrigPC);
        _window.RTCPeerConnection.prototype = __cmOrigPC.prototype;
    }

    // ── U+034F (Combining Grapheme Joiner) JSON exploit ──
    // Invisible char embedded in score strings causes parser discrepancy:
    // JS JSON.parse preserves it in strings; server-side parsers (Go, Rust, Node)
    // often strip non-ASCII / invisible chars when extracting numeric values.
    // This makes raw bytes look different to anti-cheat while server still reads the real score.
    const CGJ = '\u034F';

    function _cgjify(val) {
        const s = String(val);
        if (s.length < 2) return s;
        let out = '';
        for (let i = 0; i < s.length; i++) {
            out += s[i];
            if (i < s.length - 1) out += CGJ;
        }
        return out;
    }

    const _CGJ_FIELDS = [
        'q', 's', 'score', 'overall', 'self_score', 'your_score',
        'yourScore', 'userScore', 'playerScore', 'elo',
        'p1_score', 'p2_score', 'selfScore', 'myScore',
        'finalScore', 'totalScore', 'matchScore', 'currentScore',
        'displayScore', 'liveScore', 'overallScore', 'myFinalScore',
        'hostScore', 'actualScore', 'verifiedScore',
        'serverScore', 'realFinalScore', 'clientScore',
        'adjustedScore', 'eloChange', 'o', 'opponentScore', 'rivalScore'
    ];

    function _cgjDecorateJSON(jsonStr) {
        let result = jsonStr
            .replace(/"p":\s*(\d+),/g, (_, n) => `"p":${n},`)
            .replace(/"p":\s*(\d+)\s*}/g, (_, n) => `"p":${n}}`);
        for (const f of _CGJ_FIELDS) {
            const reStr = new RegExp('"' + f + '":\\s*"([\\d.]+)"', 'g');
            result = result.replace(reStr, (_, n) => `"${f}":"${_cgjify(n)}"`);
        }
        return result;
    }

    const _CGJ_NUM_FIELDS = new Set([
        'q', 's', 'p1', 'p2',
        ..._CGJ_FIELDS
    ]);

    function _cgjEncode(obj) {
        // Deep clone and convert score field VALUES from numbers to CGJ strings.
        // The CGJ (U+034F) in numeric values causes anti-cheat to see garbled data
        // while server-side parsers strip it and read the real (patched) score.
        function _cgjWalk(v) {
            if (v === null || typeof v === 'boolean' || typeof v === 'undefined') return v;
            if (typeof v === 'string') return v;
            if (typeof v === 'number') return v;
            if (Array.isArray(v)) return v.map(_cgjWalk);
            if (typeof v === 'object') {
                const out = {};
                for (const k of Object.keys(v)) {
                    out[k] = _cgjWalk(v[k]);
                }
                return out;
            }
            return v;
        }
        return JSON.stringify(_cgjWalk(obj));
    }

    function _stripCGJ(text) {
        return text.replace(new RegExp(CGJ, 'g'), '');
    }

    const _logPrefix = '[CM+]';
    const _logThrottle = {};
    function log(...args) { console.log(_logPrefix, ...args); }
    function logT(tag, ...args) {
        const now = Date.now();
        const last = _logThrottle[tag] || 0;
        if (now - last >= 3000) { _logThrottle[tag] = now; console.log(_logPrefix, `[${tag}]`, ...args); }
    }

    function _isOpponentKey(k) {
        if (typeof k !== 'string') return false;
        const kl = k.toLowerCase();
        return kl.startsWith('opponent') || kl.startsWith('rival') || kl === 'enemy_score' || kl === 'enemyScore' || kl === 's';
    }

    function _dataToString(data) {
        if (typeof data === 'string') return data;
        if (data instanceof ArrayBuffer) return new TextDecoder().decode(new Uint8Array(data));
        if (data instanceof Uint8Array) return new TextDecoder().decode(data);
        if (data instanceof Blob) return ''; // Blob can't be sync-read; skip
        if (data instanceof DataView) return new TextDecoder().decode(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
        return '';
    }

    function _dataToUint8Array(data) {
        if (data instanceof Uint8Array) return data;
        if (data instanceof ArrayBuffer) return new Uint8Array(data);
        if (data instanceof DataView) return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
        if (typeof data === 'string') return new TextEncoder().encode(data);
        return null;
    }

    function _patchIncomingScore(data) {
        try {
            const parsed = tryDecode(data);
            if (!parsed?.json) return null;
            const json = parsed.json;
            // Capture frame_nonce message for HMAC signing key
            if (json && json.type === 'frame_nonce') {
                if (typeof json.secret === 'string') {
                    _cm_frameNonce = json.nonce;
                    _cm_frameSecret = json.secret;
                    log('[CRYPTO] frame_nonce captured: secret=' + json.secret.substring(0, 16) + '...');
                }
                return null;
            }
            if (!CONFIG.scoreEnabled) return null;
            const hasP = typeof json.p === 'number';
            const hasQ = typeof json.q === 'number';
            const isScoreFrame = hasP && hasQ && !json.type && json.q > 0;
            const hasScore = typeof json.score === 'number';
            const hasTopYourScore = typeof json.your_score === 'number';
            const hasPayloadYourScore = json.payload && typeof json.payload === 'object' && typeof json.payload.your_score === 'number';
            const hasP1Score = typeof json.p1_score === 'number';
            const hasP2Score = typeof json.p2_score === 'number';
            const isMatchResult = (json.type === 'match_result' || json.type === 'ranked_result') && (hasP1Score || hasP2Score);
            const isFinalScores = json.type === 'FINAL_SCORES' && typeof json.p1 === 'number' && typeof json.p2 === 'number';
            if (!isScoreFrame && !hasScore && typeof json.s === 'undefined' && typeof json.overall === 'undefined' && !hasTopYourScore && !(json.payload && typeof json.payload === 'object' && ('score' in json.payload || 'your_score' in json.payload)) && !isMatchResult && !isFinalScores) return null;
            const target = _clampScore(_getTargetScore());
            const raw = _clampRaw(Math.round(target * 10000) + (CONFIG.scoreBoost || 0));
            const finalTarget = _clampScore((_getFinalTarget() || target * 10000) / 10000);
            let modified = false;
            if (isScoreFrame) { json.q = raw; modified = true; }
            if (hasScore) { json.score = json.score > 100 ? raw : target; modified = true; }
            if (typeof json.overall === 'number') { json.overall = target; modified = true; }
            if (json.payload && typeof json.payload === 'object') {
                if (typeof json.payload.overall === 'number') json.payload.overall = target;
                if (typeof json.payload.score === 'number') json.payload.score = target;
                if (typeof json.payload.your_score === 'number') { json.payload.your_score = target; modified = true; }
            }
            if (typeof json.your_score === 'number') {
                const origYour = json.your_score;
                json.your_score = target; modified = true;
                if (typeof json.p1_score === 'number' && typeof json.p2_score === 'number') {
                    const yourMatch = origYour > 100 ? origYour / 10000 : origYour;
                    const p1Match = json.p1_score > 100 ? json.p1_score / 10000 : json.p1_score;
                    const p2Match = json.p2_score > 100 ? json.p2_score / 10000 : json.p2_score;
                    _myPlayerIndex = Math.abs(yourMatch - p1Match) < Math.abs(yourMatch - p2Match) ? 0 : 1;
                    _traceMatch('determine_myPlayerIndex_from_your_score', { yourMatch, p1Match, p2Match, _myPlayerIndex });
                    const oppKey = _myPlayerIndex === 0 ? 'p2_score' : 'p1_score';
                    _lastOpponentScore = json[oppKey];
                }
            }
            // Patch match_result / ranked_result: inflate OUR score, leave opponent's
            if (isMatchResult) {
                function _determineOurKey() {
                    if (!hasP1Score && !hasP2Score) return null;
                    if (_myPlayerIndex === 0) return 'p1_score';
                    if (_myPlayerIndex === 1) return 'p2_score';
                    if (typeof origYour === 'number') {
                        const yourMatch = origYour > 100 ? origYour / 10000 : origYour;
                        const p1Match = json.p1_score > 100 ? json.p1_score / 10000 : json.p1_score;
                        const p2Match = json.p2_score > 100 ? json.p2_score / 10000 : json.p2_score;
                        const diff1 = Math.abs(yourMatch - p1Match);
                        const diff2 = Math.abs(yourMatch - p2Match);
                        _traceMatch('determineOurKey_from_your_score', { yourMatch, p1Match, p2Match, diff1, diff2, choice: diff1 < diff2 ? 'p1' : 'p2' });
                        return diff1 < diff2 ? 'p1_score' : 'p2_score';
                    }
                    // Use winner field: numeric (0=p1,1=p2) or string
                    if (json.winner !== undefined) {
                        if (json.winner === 0 || json.winner === 'p1' || json.winner === 'player1' || json.winner === 'self') { return 'p1_score'; }
                        if (json.winner === 1 || json.winner === 'p2' || json.winner === 'player2' || json.winner === 'opponent') { return 'p2_score'; }
                    }
                    // Use result field: if we won, we're the higher score; if we lost, we're the lower score
                    if (json.result === 'win' || json.result === 'won') {
                        return hasP1Score && hasP2Score ? (json.p1_score >= json.p2_score ? 'p1_score' : 'p2_score') : (hasP1Score ? 'p1_score' : 'p2_score');
                    }
                    if (json.result === 'lose' || json.result === 'loss' || json.result === 'lost') {
                        return hasP1Score && hasP2Score ? (json.p1_score <= json.p2_score ? 'p1_score' : 'p2_score') : (hasP1Score ? 'p1_score' : 'p2_score');
                    }
                    // Last resort: match last known spoofed score against our target
                    if (_lastSpoofedScore !== null && typeof _lastSpoofedScore === 'number') {
                        const p1f = json.p1_score > 100 ? json.p1_score / 10000 : json.p1_score;
                        const p2f = json.p2_score > 100 ? json.p2_score / 10000 : json.p2_score;
                        const d1 = Math.abs(p1f - _lastSpoofedScore);
                        const d2 = Math.abs(p2f - _lastSpoofedScore);
                        if (d1 < d2) return 'p1_score';
                        if (d2 < d1) return 'p2_score';
                    }
                    // Last-resort fallback: inflate BOTH scores so we win regardless of player index
                    if (hasP1Score && hasP2Score) {
                        const ourFloat = finalTarget;
                        const oppFloat = Math.max(0, finalTarget - 0.5);
                        const oldP1 = json.p1_score;
                        const oldP2 = json.p2_score;
                        json.p1_score = json.p1_score > 100 ? ourFloat * 10000 : ourFloat;
                        json.p2_score = json.p2_score > 100 ? oppFloat * 10000 : oppFloat;
                        _lastOpponentScore = oldP1 > oldP2 ? oldP1 : oldP2; // Real opponent score (the higher real one)
                        json.result = 'win';
                        json.winner = 'self';
                        modified = true;
                        _traceMatch('determineOurKey_both_inflated', { oldP1, oldP2, p1_new: json.p1_score, p2_new: json.p2_score });
                        return null; // Skip post-inflation, already done
                    }
                    const singleKey = hasP1Score ? 'p1_score' : 'p2_score';
                    _traceMatch('determineOurKey_single_fallback', { key: singleKey });
                    return singleKey;
                }
                const ourKey = _determineOurKey();
                if (ourKey && json[ourKey] !== undefined) {
                    const oldOurs = json[ourKey];
                    const otherKey = ourKey === 'p1_score' ? 'p2_score' : 'p1_score';
                    const oldOpp = typeof json[otherKey] === 'number' ? json[otherKey] : 0;
                    _lastOpponentScore = oldOpp;
                    const isRaw = oldOurs > 100;
                    const oppF = oldOpp > 100 ? oldOpp / 10000 : oldOpp;
                    const baseF = _clampScore((_getFinalTarget() || target * 10000) / 10000);
                    const winF = Math.max(baseF, oppF + 0.1);
                    const oppF2 = Math.max(0, winF - 0.5);
                    json[ourKey] = isRaw ? Math.round(winF * 10000) : winF;
                    json[otherKey] = oldOpp > 100 ? Math.round(oppF2 * 10000) : oppF2;
                    const origResult = json.result;
                    const origWinner = json.winner;
                    json.result = 'win';
                    json.winner = 'self';
                    _traceMatch('in_match_result_override', { origResult, origWinner, newResult: 'win', newWinner: 'self', winF, oppF });
                    _traceMatch('in_match_result', { ourKey, oldOurs, newOurs: json[ourKey], opponent: json[otherKey], result: json.result });
                    log(`[IN PATCH] match_result: ${ourKey} ${oldOurs} → ${json[ourKey]}`);
                    modified = true;
                }
            }
            // Patch FINAL_SCORES: inflate OUR score (p1 or p2), leave opponent's
            if (isFinalScores) {
                const ourKey = _myPlayerIndex === 0 ? 'p1' : (_myPlayerIndex === 1 ? 'p2' : null);
                if (ourKey && typeof json[ourKey] === 'number') {
                    const oldOurs = json[ourKey];
                    const otherKey = ourKey === 'p1' ? 'p2' : 'p1';
                    _lastOpponentScore = typeof json[otherKey] === 'number' ? json[otherKey] : _lastOpponentScore;
                    json[ourKey] = json[ourKey] > 100 ? (finalTarget * 10000) : finalTarget;
                    _traceMatch('in_final_scores', { ourKey, oldOurs, newOurs: json[ourKey], opponent: json[otherKey] });
                    log(`[IN PATCH] FINAL_SCORES: ${ourKey} ${oldOurs} → ${json[ourKey]}`);
                    modified = true;
                } else if (_myPlayerIndex === null && typeof json.p1 === 'number' && typeof json.p2 === 'number') {
                    const oldP1 = json.p1, oldP2 = json.p2;
                    // Skip patching when index is unknown — prevents inflating opponent's score
                    _traceMatch('in_final_scores_skip', { oldP1, oldP2, reason: 'unknown_myPlayerIndex' });
                    log(`[IN PATCH] FINAL_SCORES skipped (unknown index) p1=${oldP1} p2=${oldP2}`);
                }
            }
            if (modified) {
                log('[IN PATCH] patched incoming score data');
                _lastSpoofedScore = target;
                spoofPanel();
                const jsonStr = JSON.stringify(json);
                const origText = typeof data === 'string' ? data : new TextDecoder().decode(parsed.bytes);
                const newText = origText.replace(parsed.jsonText, jsonStr);
                if (typeof data === 'string') return newText;
                return new TextEncoder().encode(newText);
            }
        } catch(e) {}
        return null;
    }

    const DEFAULT_CONFIG = {
        enabled: true,
        scoreEnabled: true,
        scoreMode: 'fixed',
        fixedScore: 100000,
        scoreRangeMin: 100000,
        scoreRangeMax: 100000,
        resultEnabled: true,
        myFinalScore: "100000",
        finalScoreMode: 'fixed',
        finalScoreRangeMin: 100000,
        finalScoreRangeMax: 100000,
        mirrorOpponentCam: false,
        eloBoost: 5,
        scoreBoost: 0,
        holdBtnSize: 54,
        debug: true,
        wmAlpha: 20,
        wmFontSize: 9,
        wmPaddingH: 14,
        wmPaddingV: 6,
        wmBorder: true,
        wmBg: true,
        theme: 'midnight',
        queueDelay: 1000,
        autoCamInterval: 5,
        autoAudioInterval: 5,
        showControlBar: true,
        autoQueue: false,

        accentColor: '#6366f1',
        verifBypassActive: false,
        rainbowBorder: false, // removed
        crosshairEnabled: false,
    };

    function scoreSpoofAllowed() {
        return CONFIG && CONFIG.scoreEnabled && !CONFIG.verifBypassActive;
    }

    const CONFIG_KEY = 'cheatmoggle_config';
    const CONFIG_BACKUP_KEY = 'cheatmoggle_config_bak';
    const CONFIG_OLD_KEY = 'cheatmoggle _config';

    function _migrateOldConfig() {
        try {
            const old = localStorage.getItem(CONFIG_OLD_KEY);
            if (old) {
                const val = JSON.parse(old);
                localStorage.setItem(CONFIG_KEY, JSON.stringify(val));
                localStorage.setItem(CONFIG_BACKUP_KEY, JSON.stringify(val));
                localStorage.removeItem(CONFIG_OLD_KEY);
                log('[CONFIG] migrated from old key');
            }
        } catch(e) {}
    }

    function _clamp(val, min, max) {
        if (typeof val !== 'number') return val;
        if (val < min) return min;
        if (val > max) return max;
        return val;
    }

    function _validateConfig(cfg) {
        if (!cfg || typeof cfg !== 'object') return false;
        const valid = { ...DEFAULT_CONFIG };
        for (const [k, v] of Object.entries(cfg)) {
            if (k in DEFAULT_CONFIG) {
                const defaultVal = DEFAULT_CONFIG[k];
                if (typeof v === typeof defaultVal || (typeof defaultVal === 'string' && (typeof v === 'string' || typeof v === 'number'))) {
                    valid[k] = v;
                }
            }
        }
        valid.fixedScore = _clamp(valid.fixedScore, 1000, 500000);
        valid.scoreRangeMin = _clamp(valid.scoreRangeMin, 1000, 500000);
        valid.scoreRangeMax = _clamp(valid.scoreRangeMax, 1000, 500000);
        if (valid.scoreRangeMin > valid.scoreRangeMax) { const t = valid.scoreRangeMin; valid.scoreRangeMin = valid.scoreRangeMax; valid.scoreRangeMax = t; }
        const finalScoreNum = typeof valid.myFinalScore === 'string' ? parseInt(valid.myFinalScore) || 99999 : valid.myFinalScore;
        valid.myFinalScore = String(_clamp(finalScoreNum, 1000, 499999));
        valid.finalScoreRangeMin = _clamp(valid.finalScoreRangeMin, 1000, 500000);
        valid.finalScoreRangeMax = _clamp(valid.finalScoreRangeMax, 1000, 500000);
        if (valid.finalScoreRangeMin > valid.finalScoreRangeMax) { const t = valid.finalScoreRangeMin; valid.finalScoreRangeMin = valid.finalScoreRangeMax; valid.finalScoreRangeMax = t; }
        valid.eloBoost = _clamp(valid.eloBoost, 0, 100);
        valid.scoreBoost = _clamp(valid.scoreBoost, 0, 100);
        Object.assign(cfg, valid);
        return true;
    }

    function loadConfig() {
        _migrateOldConfig();
        let data = null;
        try {
            const saved = localStorage.getItem(CONFIG_KEY);
            if (saved) data = JSON.parse(saved);
        } catch (e) { log('[CONFIG] primary load failed:', e); }
        if (!data) {
            try {
                const backup = localStorage.getItem(CONFIG_BACKUP_KEY);
                if (backup) {
                    data = JSON.parse(backup);
                    log('[CONFIG] restored from backup');
                }
            } catch (e) {}
        }
        if (!data) {
            try {
                const gm = typeof GM_getValue !== 'undefined' ? GM_getValue(CONFIG_KEY, null) : null;
                if (gm) { data = JSON.parse(gm); log('[CONFIG] restored from GM storage'); }
            } catch (e) {}
        }
        const cfg = { ...DEFAULT_CONFIG };
        if (data) {
            if (!_validateConfig(data)) data = null;
            else Object.assign(cfg, data);
        }
        cfg.scoreEnabled = true;
        cfg.enabled = true;
        cfg._configVersion = 2;
        return cfg;
    }

    function saveConfig() {
        try {
            const serialized = JSON.stringify(CONFIG);
            if (typeof serialized !== 'string' || serialized === '{}') return;
            localStorage.setItem(CONFIG_KEY, serialized);
            localStorage.setItem(CONFIG_BACKUP_KEY, serialized);
            try { if (typeof GM_setValue !== 'undefined') GM_setValue(CONFIG_KEY, serialized); } catch(e) {}
        } catch (e) { log('[CONFIG] save failed:', e); }
    }

    const CONFIG = loadConfig();

    const THEMES = {
        amoled: {
            name: 'AMOLED',
            primary: '#000000',
            primaryRgb: '0,0,0',
            secondary: '#171717',
            accent: '#ffffff',
            accentRgb: '255,255,255',
            success: '#22c55e',
            warning: '#eab308',
            danger: '#ef4444',
            bgDark: '#000000',
            bgCard: '#0a0a0a',
            bgElevated: '#141414',
            border: 'rgba(255,255,255,0.15)',
            text: '#ffffff',
            textMuted: '#a1a1aa'
        },
        neon: {
            name: 'Neon',
            primary: '#00ff88',
            primaryRgb: '0,255,136',
            secondary: '#00cc6a',
            accent: '#7dffb3',
            accentRgb: '125,255,179',
            success: '#00ff88',
            warning: '#ffcc00',
            danger: '#ff4444',
            bgDark: '#0a0f0c',
            bgCard: '#0d1a12',
            bgElevated: '#132218',
            border: 'rgba(0,255,136,0.15)',
            text: '#e0ffe8',
            textMuted: '#7da88a'
        },
        matrix: {
            name: 'Matrix',
            primary: '#00ff00',
            primaryRgb: '0,255,0',
            secondary: '#00cc00',
            accent: '#66ff66',
            accentRgb: '102,255,102',
            success: '#00ff00',
            warning: '#ccff00',
            danger: '#ff3333',
            bgDark: '#000800',
            bgCard: '#001a00',
            bgElevated: '#002200',
            border: 'rgba(0,255,0,0.12)',
            text: '#ccffcc',
            textMuted: '#669966'
        },
        toxic: {
            name: 'Toxic',
            primary: '#39ff14',
            primaryRgb: '57,255,20',
            secondary: '#7fff00',
            accent: '#adff2f',
            accentRgb: '173,255,47',
            success: '#39ff14',
            warning: '#ffff00',
            danger: '#ff6347',
            bgDark: '#080a05',
            bgCard: '#101408',
            bgElevated: '#181f0c',
            border: 'rgba(57,255,20,0.12)',
            text: '#e8ffe0',
            textMuted: '#8faa7d'
        },
        midnight: {
            name: 'Midnight',
            primary: '#6366f1',
            primaryRgb: '99,102,241',
            secondary: '#8b5cf6',
            accent: '#22d3ee',
            accentRgb: '34,211,238',
            success: '#10b981',
            warning: '#f59e0b',
            danger: '#ef4444',
            bgDark: '#0a0a0f',
            bgCard: '#12121a',
            bgElevated: '#1a1a24',
            border: 'rgba(255,255,255,0.08)',
            text: '#e4e4e7',
            textMuted: '#71717a'
        },
        crimson: {
            name: 'Crimson',
            primary: '#dc2626',
            primaryRgb: '220,38,38',
            secondary: '#f43f5e',
            accent: '#fb7185',
            accentRgb: '251,113,133',
            success: '#10b981',
            warning: '#f59e0b',
            danger: '#ef4444',
            bgDark: '#0f0505',
            bgCard: '#1a0a0a',
            bgElevated: '#241010',
            border: 'rgba(255,100,100,0.1)',
            text: '#fecaca',
            textMuted: '#a8a29e'
        },
        ocean: {
            name: 'Ocean',
            primary: '#0ea5e9',
            primaryRgb: '14,165,233',
            secondary: '#38bdf8',
            accent: '#7dd3fc',
            accentRgb: '125,211,252',
            success: '#14b8a6',
            warning: '#fbbf24',
            danger: '#f87171',
            bgDark: '#042f42',
            bgCard: '#0a3d55',
            bgElevated: '#0f4c68',
            border: 'rgba(56,189,248,0.15)',
            text: '#e0f2fe',
            textMuted: '#7ca8c0'
        },
        sunset: {
            name: 'Sunset',
            primary: '#f97316',
            primaryRgb: '249,115,22',
            secondary: '#fb923c',
            accent: '#fbbf24',
            accentRgb: '251,191,36',
            success: '#22c55e',
            warning: '#eab308',
            danger: '#ef4444',
            bgDark: '#3b0d11',
            bgCard: '#4f151b',
            bgElevated: '#641e26',
            border: 'rgba(251,146,60,0.15)',
            text: '#ffedd5',
            textMuted: '#c49a7a'
        },
        lavender: {
            name: 'Lavender',
            primary: '#a855f7',
            primaryRgb: '168,85,247',
            secondary: '#c084fc',
            accent: '#d8b4fe',
            accentRgb: '216,180,254',
            success: '#34d399',
            warning: '#facc15',
            danger: '#fb7185',
            bgDark: '#1e0a33',
            bgCard: '#2a1245',
            bgElevated: '#361b58',
            border: 'rgba(192,132,252,0.15)',
            text: '#f3e8ff',
            textMuted: '#b89ad4'
        },
        forest: {
            name: 'Forest',
            primary: '#16a34a',
            primaryRgb: '22,163,74',
            secondary: '#22c55e',
            accent: '#86efac',
            accentRgb: '134,239,172',
            success: '#16a34a',
            warning: '#ca8a04',
            danger: '#dc2626',
            bgDark: '#052e12',
            bgCard: '#0a3d1a',
            bgElevated: '#0f4d23',
            border: 'rgba(34,197,94,0.12)',
            text: '#dcfce7',
            textMuted: '#7aad8c'
        },
        gold: {
            name: 'Gold',
            primary: '#f59e0b',
            primaryRgb: '245,158,11',
            secondary: '#fbbf24',
            accent: '#fde68a',
            accentRgb: '253,230,138',
            success: '#10b981',
            warning: '#f59e0b',
            danger: '#ef4444',
            bgDark: '#2b1d04',
            bgCard: '#3d2a08',
            bgElevated: '#4f370c',
            border: 'rgba(251,191,36,0.15)',
            text: '#fef9c3',
            textMuted: '#c9ab5e'
        },
        ice: {
            name: 'Ice',
            primary: '#67e8f9',
            primaryRgb: '103,232,249',
            secondary: '#22d3ee',
            accent: '#cffafe',
            accentRgb: '207,250,254',
            success: '#34d399',
            warning: '#fbbf24',
            danger: '#fb7185',
            bgDark: '#083344',
            bgCard: '#0c425a',
            bgElevated: '#115270',
            border: 'rgba(103,232,249,0.15)',
            text: '#cffafe',
            textMuted: '#7fc4d6'
        },
        bloodorange: {
            name: 'Blood Orange',
            primary: '#ea580c',
            primaryRgb: '234,88,12',
            secondary: '#f97316',
            accent: '#fdba74',
            accentRgb: '253,186,116',
            success: '#22c55e',
            warning: '#eab308',
            danger: '#ef4444',
            bgDark: '#1f0a02',
            bgCard: '#2e1006',
            bgElevated: '#3d170a',
            border: 'rgba(234,88,12,0.15)',
            text: '#ffedd5',
            textMuted: '#bf8a60'
        },
        cyberpunk: {
            name: 'Cyberpunk',
            primary: '#ff00ff',
            primaryRgb: '255,0,255',
            secondary: '#00ffff',
            accent: '#ff66ff',
            accentRgb: '255,102,255',
            success: '#00ff88',
            warning: '#ffff00',
            danger: '#ff3333',
            bgDark: '#0a0014',
            bgCard: '#14001f',
            bgElevated: '#1e002e',
            border: 'rgba(255,0,255,0.15)',
            text: '#f0e6ff',
            textMuted: '#b380d4'
        },
        rose: {
            name: 'Rose',
            primary: '#e11d48',
            primaryRgb: '225,29,72',
            secondary: '#fb7185',
            accent: '#fda4af',
            accentRgb: '253,164,175',
            success: '#10b981',
            warning: '#f59e0b',
            danger: '#ef4444',
            bgDark: '#1a040a',
            bgCard: '#2a0812',
            bgElevated: '#3a0c1a',
            border: 'rgba(251,113,133,0.12)',
            text: '#fce7f3',
            textMuted: '#c48a9a'
        },
        mint: {
            name: 'Mint',
            primary: '#14b8a6',
            primaryRgb: '20,184,166',
            secondary: '#2dd4bf',
            accent: '#5eead4',
            accentRgb: '94,234,212',
            success: '#14b8a6',
            warning: '#eab308',
            danger: '#ef4444',
            bgDark: '#022c22',
            bgCard: '#053d32',
            bgElevated: '#084f42',
            border: 'rgba(45,212,191,0.15)',
            text: '#ccfbf1',
            textMuted: '#7ab8a8'
        },
        sky: {
            name: 'Sky',
            primary: '#3b82f6',
            primaryRgb: '59,130,246',
            secondary: '#60a5fa',
            accent: '#93c5fd',
            accentRgb: '147,197,253',
            success: '#22c55e',
            warning: '#eab308',
            danger: '#ef4444',
            bgDark: '#0a1e3d',
            bgCard: '#0f2850',
            bgElevated: '#153364',
            border: 'rgba(96,165,250,0.15)',
            text: '#dbeafe',
            textMuted: '#809ec8'
        },
        coral: {
            name: 'Coral',
            primary: '#f43f5e',
            primaryRgb: '244,63,94',
            secondary: '#fb7185',
            accent: '#fda4af',
            accentRgb: '253,164,175',
            success: '#22c55e',
            warning: '#eab308',
            danger: '#dc2626',
            bgDark: '#1f0a0f',
            bgCard: '#2e0f16',
            bgElevated: '#3d151e',
            border: 'rgba(251,113,133,0.12)',
            text: '#ffe4e6',
            textMuted: '#cf8a94'
        },
        slate: {
            name: 'Slate',
            primary: '#6366f1',
            primaryRgb: '99,102,241',
            secondary: '#818cf8',
            accent: '#a5b4fc',
            accentRgb: '165,180,252',
            success: '#34d399',
            warning: '#fbbf24',
            danger: '#f87171',
            bgDark: '#0c0f15',
            bgCard: '#141a24',
            bgElevated: '#1c2433',
            border: 'rgba(129,140,248,0.1)',
            text: '#e2e8f0',
            textMuted: '#7c8594'
        },
        auburn: {
            name: 'Auburn',
            primary: '#b45309',
            primaryRgb: '180,83,9',
            secondary: '#d97706',
            accent: '#f59e0b',
            accentRgb: '245,158,11',
            success: '#22c55e',
            warning: '#eab308',
            danger: '#dc2626',
            bgDark: '#140a02',
            bgCard: '#1f1004',
            bgElevated: '#2a1607',
            border: 'rgba(217,119,6,0.15)',
            text: '#fef3c7',
            textMuted: '#b8934a'
        },
        violet: {
            name: 'Violet',
            primary: '#7c3aed',
            primaryRgb: '124,58,237',
            secondary: '#a78bfa',
            accent: '#c4b5fd',
            accentRgb: '196,181,253',
            success: '#34d399',
            warning: '#fbbf24',
            danger: '#f87171',
            bgDark: '#120526',
            bgCard: '#1a0a33',
            bgElevated: '#241042',
            border: 'rgba(167,139,250,0.12)',
            text: '#ede9fe',
            textMuted: '#a898c9'
        },
        emerald: {
            name: 'Emerald',
            primary: '#059669',
            primaryRgb: '5,150,105',
            secondary: '#10b981',
            accent: '#6ee7b7',
            accentRgb: '110,231,183',
            success: '#059669',
            warning: '#d97706',
            danger: '#dc2626',
            bgDark: '#022015',
            bgCard: '#053321',
            bgElevated: '#08462e',
            border: 'rgba(16,185,129,0.12)',
            text: '#d1fae5',
            textMuted: '#70ad90'
        },
        peach: {
            name: 'Peach',
            primary: '#fb923c',
            primaryRgb: '251,146,60',
            secondary: '#fdba74',
            accent: '#fed7aa',
            accentRgb: '254,215,170',
            success: '#22c55e',
            warning: '#eab308',
            danger: '#ef4444',
            bgDark: '#1f0f06',
            bgCard: '#2e180b',
            bgElevated: '#3d2211',
            border: 'rgba(253,186,116,0.15)',
            text: '#fff7ed',
            textMuted: '#cfab80'
        },
        slateblue: {
            name: 'Slate Blue',
            primary: '#4f46e5',
            primaryRgb: '79,70,229',
            secondary: '#818cf8',
            accent: '#a5b4fc',
            accentRgb: '165,180,252',
            success: '#22c55e',
            warning: '#eab308',
            danger: '#ef4444',
            bgDark: '#0b0b1a',
            bgCard: '#111128',
            bgElevated: '#181838',
            border: 'rgba(129,140,248,0.1)',
            text: '#e0e7ff',
            textMuted: '#7c82b8'
        },
        cherry: {
            name: 'Cherry',
            primary: '#be123c',
            primaryRgb: '190,18,60',
            secondary: '#e11d48',
            accent: '#fb7185',
            accentRgb: '251,113,133',
            success: '#22c55e',
            warning: '#eab308',
            danger: '#dc2626',
            bgDark: '#14030a',
            bgCard: '#1f0610',
            bgElevated: '#2a0917',
            border: 'rgba(225,29,72,0.12)',
            text: '#fce7f3',
            textMuted: '#bd8098'
        },
        amber: {
            name: 'Amber',
            primary: '#d97706',
            primaryRgb: '217,119,6',
            secondary: '#f59e0b',
            accent: '#fbbf24',
            accentRgb: '251,191,36',
            success: '#22c55e',
            warning: '#d97706',
            danger: '#dc2626',
            bgDark: '#1a0f02',
            bgCard: '#261705',
            bgElevated: '#331f08',
            border: 'rgba(245,158,11,0.15)',
            text: '#fef3c7',
            textMuted: '#c9a052'
        },
        femboy: {
            name: 'Femboy',
            primary: '#ff69b4',
            primaryRgb: '255,105,180',
            secondary: '#ffb6c1',
            accent: '#ffc0cb',
            accentRgb: '255,192,203',
            success: '#ff69b4',
            warning: '#ffb6c1',
            danger: '#ff1493',
            bgDark: '#1a0a14',
            bgCard: '#2d0f1f',
            bgElevated: '#3d1529',
            border: 'rgba(255,105,180,0.2)',
            text: '#ffe4ec',
            textMuted: '#ffb6c1'
        }
    };

    let playerMapping = null;
    let _myPlayerIndex = null;
    let _isRanked = window.location.pathname.startsWith('/ranked');
    let _matchStartTime = null;
    let _finalScoreAppliedThisMatch = false;
    let _currentUsername = null;

    const _origPushState = history.pushState;
    history.pushState = function(...args) {
        _origPushState.apply(this, args);
        _isRanked = window.location.pathname.startsWith('/ranked');
    };
    window.addEventListener('popstate', () => {
        _isRanked = window.location.pathname.startsWith('/ranked');
    });

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

            const m = clean.match(/\{[^}]+\}/);
            if (m) try { return { json: JSON.parse(m[0]), bytes, fullText: text, jsonText: m[0] }; } catch(e) {}

            try { return { json: JSON.parse(clean), bytes, fullText: text, jsonText: clean }; } catch(e) {}

            let depth = 0, start = -1;
            for (let i = 0; i < clean.length; i++) {
                if (clean[i] === '{') { if (start === -1) start = i; depth++; }
                else if (clean[i] === '}') { depth--; if (depth === 0 && start !== -1) try { const sub = clean.substring(start, i + 1); return { json: JSON.parse(sub), bytes, fullText: clean, jsonText: sub }; } catch(e) { start = -1; } }
            }
        } catch (e) {}
        return null;
    }

    // ── Universal hooks: intercept score data ──
    // Hook strategy: RTCDataChannel, WebSocket, fetch, postMessage.

    // ==================== CORE FACE ENGINE ====================
    const PARAMS = { FH: 0.62, FW: 0.3940, JW: 0.3597, JY: 0.26, EY: 0.058, IH: 0.05, EW: 0.0969, EH: 0.0290, T: 0.0005, MOUTH: 0.2103 };
    function genNorm(P) {
        const lm = []; for (let i = 0; i < 478; i++) lm.push({ x: 0.5, y: 0.5, z: 0 });
        const cx = 0.5, cy = 0.5, set = (li, ri, hw, yy) => { lm[li] = { x: cx - hw, y: yy, z: 0 }; lm[ri] = { x: cx + hw, y: yy, z: 0 }; };
        lm[10] = { x: cx, y: cy - P.FH / 2, z: 0 }; lm[152] = { x: cx, y: cy + P.FH / 2, z: 0 };
        lm[234] = { x: cx - P.FW / 2, y: cy, z: 0 }; lm[454] = { x: cx + P.FW / 2, y: cy, z: 0 };
        set(172, 397, P.JW / 2, cy + P.JY); set(150, 379, P.JW / 2, cy + P.JY * 0.9); set(171, 396, P.JW / 2, cy + P.JY * 1.1);
        const eyeY = cy - P.EY; lm[133] = { x: cx - P.IH, y: eyeY, z: 0 }; lm[33] = { x: cx - P.IH - P.EW, y: eyeY - P.T, z: 0 };
        lm[362] = { x: cx + P.IH, y: eyeY, z: 0 }; lm[263] = { x: cx + P.IH + P.EW, y: eyeY - P.T, z: 0 };
        const lcx = cx - P.IH - P.EW / 2, rcx = cx + P.IH + P.EW / 2;
        lm[159] = { x: lcx, y: eyeY - P.EH / 2, z: 0 }; lm[145] = { x: lcx, y: eyeY + P.EH / 2, z: 0 };
        lm[386] = { x: rcx, y: eyeY - P.EH / 2, z: 0 }; lm[374] = { x: rcx, y: eyeY + P.EH / 2, z: 0 };
        lm[1] = { x: cx, y: cy, z: 0 }; lm[0] = { x: cx, y: eyeY + P.MOUTH, z: 0 };
        const fill = [[70, 300, .18, -.12], [63, 293, .14, -.14], [105, 334, .10, -.16], [46, 276, .20, -.10], [116, 345, .22, .02], [123, 352, .20, .06], [50, 280, .18, .10], [187, 411, .16, .16], [132, 361, .24, 0], [174, 399, .06, .20], [136, 365, .12, .20], [148, 377, .08, .24], [176, 401, .10, .22], [58, 288, .22, -.04]];
        for (const f of fill) { lm[f[0]] = { x: cx - f[2], y: cy + f[3], z: 0 }; lm[f[1]] = { x: cx + f[2], y: cy + f[3], z: 0 }; }
        return lm;
    }
    const _NORM = genNorm(PARAMS); const _PS = 1.0;
    let _headYaw = 0;
    let currentScore = 9.3;
    let scoreVel = 0;
    let IN_MATCH = false;
    let _lastFrameTs = 0;
    const PEAK_DELTAS = {
      0: [0.00238*_PS, -0.00148*_PS], 133: [-0.00537*_PS, -0.00507*_PS], 159: [0.00489*_PS, 0.00189*_PS],
      176: [0.00392*_PS, -0.00571*_PS], 187: [0.00433*_PS, 0.00566*_PS], 293: [0.00167*_PS, -0.00274*_PS],
      352: [-0.00052*_PS, 0.00213*_PS], 362: [0.00571*_PS, 0.00174*_PS], 386: [0.00402*_PS, 0.00377*_PS],
    };
    const LOW_DELTAS = { 0: [-0.00589, 0.00354], 33: [0.0024, -0.00215], 50: [-0.00312, -0.00189], 58: [-0.0075, -0.00572], 105: [-0.00128, 0.00165], 116: [-0.00368, 0.0027], 123: [0.00578, 0.00299], 145: [0.00243, 0.00522], 159: [0.00304, -0.00501], 171: [0.00375, -0.0019], 263: [-0.00048, 0.00605], 300: [-0.00572, 0.00073], 334: [0.00191, -0.00197], 352: [0.0001, 0.00005], 365: [0.00352, -0.0045], 374: [0.00455, -0.00071], 377: [0.00595, 0.00473], 379: [-0.00028, 0.00566], 386: [-0.00027, -0.016], 399: [-0.00495, -0.00209], 401: [0.00373, -0.00379] };
    function applyD(d) { const a = _NORM.map(p => ({ x: p.x, y: p.y, z: 0 })); for (const k in d) a[+k] = { x: _NORM[+k].x + d[k][0], y: _NORM[+k].y + d[k][1], z: 0 }; return a; }
    const _LOW = applyD(LOW_DELTAS), _PEAK = applyD(PEAK_DELTAS);

    function faceL(L){return _LOW.map((p,i)=>({x:p.x+(_PEAK[i].x-p.x)*L,y:p.y+(_PEAK[i].y-p.y)*L,z:0}));}
    const _WP=[[33,263],[133,362],[70,300],[63,293],[105,334],[46,276],[116,345],[123,352],[50,280],[187,411],[132,361],[174,399],[150,379],[172,397],[136,365],[171,396],[148,377],[176,401],[58,288]];
    const _F=(a,b)=>Math.hypot(a.x-b.x,a.y-b.y);
    const _L=(a,b)=>Math.atan2(b.y-a.y,b.x-a.x)*57.29578;
    const _O=(e,t,r)=>Math.max(t,Math.min(r,e));
    const _B=(e,t,r,a,n)=>e>=t&&e<=r?10:e<t?_O((e-a)/(t-a)*10,0,10):_O((n-e)/(n-r)*10,0,10);
    function simpleScore(p){
        const m=-((_L(p[33],p[133])+_L(p[362],p[263]))/2);
        let jx=0;for(const pr of[[172,397],[150,379],[171,396]]){const r=_F(p[pr[0]],p[pr[1]]);if(r>jx)jx=r;}
        const h=_F(p[234],p[454]),f=_F(p[10],p[152]),g=jx,b=f>0?g/f:0;
        const v=(p[133].x+p[362].x)/2,w=(p[10].y+p[152].y)/2;
        let _=0;for(const pr of _WP){const rr=p[pr[0]],q=p[pr[1]];_+=(h>0?Math.abs(Math.abs(rr.x-v)-Math.abs(q.x-v))/h:0)+(f>0?Math.abs(Math.abs(rr.y-w)-Math.abs(q.y-w))/f:0);}
        const y=Math.round((1-_O(_/(2*_WP.length)/.09,0,1))*100);
        const k=(p[133].y+p[33].y)/2,j=(p[362].y+p[263].y)/2,Nl=(k+j)/2;
        const C=Math.abs(p[0].y-Nl),S=f>0?C/f:0,E=g>0?_F(p[234],p[454])/g:0;
        const R=_F(p[33],p[133]),Ih=_F(p[159],p[145]),Mw=_F(p[263],p[362]),Uh=_F(p[386],p[374]);
        const z=Math.max(.2,((R>0?Ih/R:0)+(Mw>0?Uh/Mw:0))/2);
        const H=h>0?_F(p[133],p[362])/h:0;
        const G=_B(m,2,6.5,-2,11),Y=_B(b,.58,.78,.42,.96),q2=_B(S,.27,.34,.2,.43);
        const V=_B(E,1.04,1.24,.86,1.48),K=_B(z,.22,.3,.18,.43);
        const J=Math.round((.18*Y+.24*q2+.18*V+.16*K+.24*_B(H,.22,.31,.15,.42))*10)/10;
        return _O(.12*G+.14*Y+y/10*.24+.14*q2+.1*V+.08*K+.18*J,1.1,10);
    }
    const _TBL=[];for(let L=0;L<=1.0001;L+=0.02)_TBL.push([L,simpleScore(faceL(L))]);
    const SCORE_MIN=_TBL[0][1],SCORE_MAX=_TBL[_TBL.length-1][1];
    function solveL(score){
        score=Math.max(SCORE_MIN,Math.min(SCORE_MAX,score));
        for(let i=0;i<_TBL.length-1;i++){const a=_TBL[i],b=_TBL[i+1];if(score>=a[1]&&score<=b[1]){const f=(score-a[1])/((b[1]-a[1])||1);return a[0]+(b[0]-a[0])*f;}}
        return 1;
    }
    const SCORE_IDX=new Set([0,1,10,152,234,454,33,133,263,362,159,145,386,374,172,397,150,379,171,396]);
    for(const pr of _WP){SCORE_IDX.add(pr[0]);SCORE_IDX.add(pr[1]);}

    let _aspect = 4 / 3, _aspT = 0;
    function getAspect() {
        const now = Date.now(); if (now - _aspT < 1000) return _aspect; _aspT = now;
        try {
            let best = document.querySelector('video.scanner-video');
            if (!(best && best.videoWidth > 0)) { best = null; document.querySelectorAll('video').forEach(v => { if (v.videoWidth > 0 && v.videoHeight > 0 && (!best || v.videoWidth * v.videoHeight > best.videoWidth * best.videoHeight)) best = v; }); }
            if (best && best.videoWidth > 0) _aspect = best.videoWidth / best.videoHeight;
        } catch (e) {} return _aspect;
    }
    const _idealBuf=Array.from({length:478},()=>({x:0,y:0,z:0}));
    let _idealLastScore=NaN,_idealLastAspect=NaN;
    function idealObjects(aspect){
        const a=aspect||getAspect();
        if(currentScore===_idealLastScore&&a===_idealLastAspect)return _idealBuf;
        _idealLastScore=currentScore;_idealLastAspect=a;
        const cx=0.5,L=solveL(currentScore),base=faceL(L);
        for(let i=0;i<base.length;i++){_idealBuf[i].x=cx+(base[i].x-cx)/a;_idealBuf[i].y=base[i].y;_idealBuf[i].z=0;}
        return _idealBuf;
    }
    function encodeLM(lms) {
        const b = new Uint8Array(lms.length * 17), dv = new DataView(b.buffer);
        for (let i = 0; i < lms.length; i++) { const o = i * 17; b[o] = 0x0a; b[o + 1] = 0x0f; b[o + 2] = 0x0d; dv.setFloat32(o + 3, lms[i].x, true); b[o + 7] = 0x15; dv.setFloat32(o + 8, lms[i].y, true); b[o + 12] = 0x1d; dv.setFloat32(o + 13, lms[i].z, true); }
        return b;
    }

    let _calls = 0;
    function bump(how) { _calls++; if (_calls % (CONFIG.logEveryN || 90) === 1) log('[cyyyyz] feeding flawless face via ' + how); }

    // ==================== ALL 8 ORIG HOOKS BY CYYYYYZ ====================
    let _hookedWasm = false, _mf; const TD = new TextDecoder('utf-8');
    function ptrToStr(mod, ptr) { if (typeof ptr === 'string') return ptr; const H = mod.HEAPU8; if (!H || typeof ptr !== 'number') return ''; let e = ptr; while (e < H.length && H[e] !== 0) e++; try { return TD.decode(H.subarray(ptr, e)); } catch (x) { return ''; } }
    function installWasm(mod) {
        if (!mod || mod.__omg) return; mod.__omg = true;
        const dispatch = function (namePtr) {
            const args = Array.prototype.slice.call(arguments, 1); let name = ''; try { name = ptrToStr(mod, namePtr); } catch (e) {}
            try { if (CONFIG.enabled && !CONFIG.verifBypassActive && name === 'face_landmarks' && args[0] instanceof Uint8Array) { args[0] = encodeLM(idealObjects()); bump('wasm'); } } catch (e) {}
            try { const SL = mod.simpleListeners; if (SL && SL[name]) return SL[name].apply(null, args); } catch (e) {}
        };
        try { Object.defineProperty(mod, '_wrapSimpleListenerOutput', { configurable: true, get() { return dispatch; }, set() {} }); } catch (e) { mod._wrapSimpleListenerOutput = dispatch; }
        _hookedWasm = true;
    }
    function wrapFactory(orig) {
        if (typeof orig !== 'function' || orig.__omg) return orig;
        const wrapped = function () { let r; try { r = orig.apply(this, arguments); } catch (e) { throw e; } Promise.resolve(r).then(m => { try { installWasm(m); } catch (e) {} }).catch(() => {}); return r; };
        wrapped.__omg = true; return wrapped;
    }
    try { Object.defineProperty(_window, 'ModuleFactory', { configurable: true, get() { return _mf; }, set(v) { _mf = wrapFactory(v); } }); } catch (e) {}

    let _hookedDFV = false, _req = null;
    function wrapDFV(proto) {
        if (!proto || proto.__omgD) return false; const orig = proto.detectForVideo; if (typeof orig !== 'function') return false;
        proto.detectForVideo = function () {
            if (CONFIG.enabled && !CONFIG.verifBypassActive) {
                try {
                    const vf = arguments[0]; let vw = 0, vh = 0; try { vw = vf.videoWidth || vf.width || 0; vh = vf.videoHeight || vf.height || 0; } catch (e) {}
                    const res = { faceLandmarks: [idealObjects(vw > 0 && vh > 0 ? vw / vh : 0)], faceBlendshapes: [], facialTransformationMatrixes: [] };
                    bump('detectForVideo'); const cb = arguments[2]; if (typeof cb === 'function') { cb(res); return; } return res;
                } catch (e) {}
            } return orig.apply(this, arguments);
        }; proto.__omgD = true; _hookedDFV = true; return true;
    }
    function chk(v) { try { if (typeof v === 'function' && v.prototype && typeof v.prototype.detectForVideo === 'function') return wrapDFV(v.prototype); } catch (e) {} return false; }
    function tryWebpack() {
        try {
            const key = Object.keys(_window).find(k => /^webpackChunk/.test(k)); if (!key || !Array.isArray(_window[key])) return;
            if (_window[key].push === Array.prototype.push) return; if (!_req) { _window[key].push([[], {}, (r) => { _req = r; }]); }
            if (_req && _req.c) for (const id in _req.c) { const ex = _req.c[id] && _req.c[id].exports; if (!ex) continue; chk(ex); if (typeof ex === 'object') for (const k in ex) { try { chk(ex[k]); } catch (e) {} } }
        } catch (e) {}
    }
    let tries = 0; const poll = setInterval(() => { tries++; if (!_hookedDFV) tryWebpack(); if ((_hookedWasm || _hookedDFV) && tries > 8) clearInterval(poll); if (tries > 1200) clearInterval(poll); }, 200);

    let _hookedSign = false;
    (function setup_sign_rewrite(){
        if(!_window.crypto?.subtle?.sign)return;
        const _sign=_window.crypto.subtle.sign;
        _window.crypto.subtle.sign=function(alg,key,data){
            try{
                let dv;
                if(data instanceof ArrayBuffer)dv=new DataView(data);
                else if(ArrayBuffer.isView(data))dv=new DataView(data.buffer,data.byteOffset,data.byteLength);
                if(dv&&dv.getUint8(0)===4&&dv.byteLength>=17){
                    _lastFrameTs=Date.now();
                    if(CONFIG.enabled&&!CONFIG.verifBypassActive){
                        const s=dv.getUint16(13,true);
                        const aspect=dv.getFloat32(9,true)||getAspect();
                        const ideal=idealObjects(aspect);
                        const n=Math.min(s,ideal.length);
                        dv.setUint8(15,255);dv.setUint8(16,2);
                        let c=17;
                        for(let i=0;i<n;i++){dv.setFloat32(c,ideal[i].x,true);dv.setFloat32(c+4,ideal[i].y,true);c+=8;}
                        _calls++;
                    }
                }
            }catch(e){}
            return _sign.call(this,alg,key,data);
        };
        _hookedSign=true;
    })();
    setInterval(()=>{IN_MATCH=(Date.now()-_lastFrameTs)<1500;},300);
    setInterval(()=>{
        if(CONFIG.enabled&&!CONFIG.verifBypassActive){
            var t=_getTargetScore();
            currentScore+=(t-currentScore)*0.08;
            if(Math.abs(currentScore-t)<0.005)currentScore=t;
        }
    },200);

    // ── JSON.parse / JSON.stringify hooks (NEW ROUTE) ──
    // Operates at the data serialization layer, catching ALL score data
    // regardless of transport channel (WS, DC, fetch, XHR, postMessage, etc.)
    function _getSafeTarget() { try { return _getTargetScore(); } catch(e) { return 10; } }
    function _getSafeRaw() { try { return Math.round(_getSafeTarget() * 10000) + ((CONFIG && CONFIG.scoreBoost) || 0); } catch(e) { return 100000; } }
    function _aggressiveScorePatch(obj, depth) {
        if (!obj || typeof obj !== 'object' || depth > 8) return false;
        let changed = false;
        const target = _clampScore(_getSafeTarget());
        const raw = _clampRaw(_getSafeRaw());
        const scoreKeyNames = ['score', 'elo', 'overall', 'final', 'selfScore', 'myScore', 'opponent', 'rival', 'your_score', 'yourScore', 'userScore', 'playerScore', 'p1_score', 'p2_score', 'totalScore', 'matchScore', 'actualScore', 'selfScoreRaw'];

        function _isScoreKey(k) {
            const kl = k.toLowerCase();
            return scoreKeyNames.some(n => kl.includes(n) || kl.endsWith(n));
        }

        // Handle score arrays: small arrays where > 2/3 of elements look like scores
        if (Array.isArray(obj)) {
            if (obj.length === 0 || obj.length > 10) return false;
            let scoreCount = 0;
            for (const item of obj) {
                if (typeof item === 'number' && item > 0.1 && item <= 9999.99 && !Number.isInteger(item)) scoreCount++;
                else if (typeof item === 'number' && item > 1000 && item <= 99999999 && Number.isInteger(item)) scoreCount++;
            }
            if (scoreCount > obj.length * 2 / 3) {
                for (let i = 0; i < obj.length; i++) {
                    const v = obj[i];
                    if (typeof v === 'number' && v > 0.1 && v <= 9999.99 && !Number.isInteger(v)) {
                        obj[i] = Math.round(target * 10) / 10; changed = true;
                    } else if (typeof v === 'number' && v > 1000 && v <= 99999999 && Number.isInteger(v)) {
                        obj[i] = raw; changed = true;
                    }
                }
            }
            return changed;
        }

        for (const [k, v] of Object.entries(obj)) {
            if (_isOpponentKey(k)) continue;
            if (typeof v === 'object' && v !== null) {
                if (_aggressiveScorePatch(v, depth + 1)) changed = true;
            } else if (typeof v === 'number' && v > 0) {
                // Float scores: up to 9999.99
                if (v <= 9999.99 && !Number.isInteger(v)) {
                    obj[k] = Math.round(target * 10) / 10;
                    changed = true;
                }
                // Raw scores: 1000-99999999 — only touch keys that look like scores
                else if (v >= 1000 && v <= 99999999 && Number.isInteger(v) && _isScoreKey(k)) {
                    obj[k] = raw;
                    changed = true;
                }
                // Small whole numbers 1-9999 that might be multiplied scores
                else if (v >= 1 && v <= 9999 && Number.isInteger(v) && _isScoreKey(k)) {
                    obj[k] = Math.round(target);
                    changed = true;
                }
            } else if (typeof v === 'string' && /^[\d\.\u034F]+$/.test(v)) {
                const cleaned = _stripCGJ(v);
                const n = parseFloat(cleaned);
                if (n > 0 && n <= 9999.99) {
                    obj[k] = String(Math.round(target * 10) / 10);
                    changed = true;
                } else if (n >= 1000 && n <= 99999999) {
                    obj[k] = String(raw);
                    changed = true;
                }
            }
        }
        return changed;
    }

    const _origParse = JSON.parse;
    const _origStringify = JSON.stringify;
    JSON.parse = function(text, reviver) {
        const result = _origParse.call(this, text, reviver);
        try {
            if (scoreSpoofAllowed() && result && typeof result === 'object') {
                const t = _getSafeTarget();
                const r = _getSafeRaw();
                const resultStr = _origStringify.call(this, result);
                const clone = _origParse.call(this, resultStr);
                const deepPatched = _deepPatchScores(clone, '', r, t + ((CONFIG && CONFIG.scoreBoost) || 0) / 10000);
                const aggrPatched = _aggressiveScorePatch(clone);
                if (deepPatched || aggrPatched) {
                    logT('JSON', `PARSE patched scores (deep=${deepPatched} aggr=${aggrPatched})`);
                    return clone;
                }
            }
        } catch(e) {}
        return result;
    };
    log('[JSON] JSON.parse hooked');
    JSON.stringify = function(value, replacer, space) {
        try {
            if (scoreSpoofAllowed() && value && typeof value === 'object') {
                const t = _getSafeTarget();
                const r = _getSafeRaw();
                const str = _origStringify.call(this, value);
                const clone = _origParse.call(this, str);
                const deepPatched = _deepPatchScores(clone, '', r, t + ((CONFIG && CONFIG.scoreBoost) || 0) / 10000);
                const aggrPatched = _aggressiveScorePatch(clone);
                if (deepPatched || aggrPatched) {
                    logT('JSON', `STRINGIFY patched scores (deep=${deepPatched} aggr=${aggrPatched})`);
                    return _origStringify.call(this, clone, replacer, space);
                }
            }
        } catch(e) {}
        return _origStringify.call(this, value, replacer, space);
    };
    log('[JSON] JSON.stringify hooked');

    // ── HMAC Signing Interceptor ──
    // The game uses crypto.subtle.importKey + crypto.subtle.sign to HMAC-sign
    // binary face landmark frames. By hooking these, we can capture the signing
    // key and modify frame data BEFORE it's signed, so the server accepts it.
    let _cm_hmacKey = null;
    let _cm_frameNonce = null;
    let _cm_frameSecret = null;
    if (_window.crypto && _window.crypto.subtle) {
        try {
            const _origImportKey = _window.crypto.subtle.importKey;
            _window.crypto.subtle.importKey = function(format, keyData, algorithm, extractable, keyUsages) {
                if (algorithm && algorithm.name === 'HMAC') {
                    log('[CRYPTO] importKey HMAC format=' + format);
                    const result = _origImportKey.call(this, format, keyData, algorithm, extractable, keyUsages);
                    if (result && typeof result.then === 'function') {
                        result.then(function(key) {
                            _cm_hmacKey = { key, keyData, format };
                            log('[CRYPTO] HMAC key captured (keyData=' + (keyData instanceof ArrayBuffer ? keyData.byteLength + ' bytes' : typeof keyData) + ')');
                        });
                    }
                    return result;
                }
                return _origImportKey.call(this, format, keyData, algorithm, extractable, keyUsages);
            };
            log('[CRYPTO] crypto.subtle.importKey hooked');
        } catch(e) { log('[CRYPTO] importKey hook error: ' + e.message); }

        // NOTE: crypto.subtle.sign is now hooked by HOOK C (signed-frame rewrite) above.
        // The old frame-inflating hook is removed — HOOK C rewrites the entire landmark
        // payload with our synthetic face before signing, which is strictly better.
    } else {
        log('[CRYPTO] crypto.subtle not available');
    }

    // ── TextEncoder.encode hook (LiveKit data channel bypass) ──
    // LiveKit calls TextEncoder.encode(jsonString) to convert JSON to bytes
    // before wrapping in protobuf and sending via data channel.
    // Hooking here catches ALL score traffic without needing the Room.
    if (_window.TextEncoder && TextEncoder.prototype && TextEncoder.prototype.encode) {
        if (!TextEncoder.prototype.encode.__cmHooked) {
            const _origTextEncode = TextEncoder.prototype.encode;
            TextEncoder.prototype.encode = function(input) {
                try {
                    if (typeof input === 'string' && (scoreSpoofAllowed() || input.indexOf('"type":"SCAN_STATE"') >= 0)) {
                        // p,q score frames (lossy channel, real-time scores)
                        const pqMatch = input.match(/^\{"p":(\d+),"q":(\d+)\}$/);
                        if (pqMatch) {
                            const pVal = parseInt(pqMatch[1]);
                            if (_myPlayerIndex === null && (pVal === 0 || pVal === 1)) {
                                _myPlayerIndex = pVal;
                                _traceMatch('te_encode_pq_myPlayerIndex', { p: pVal });
                            }
                            // Only patch OUR score frames — don't inflate opponent's score on their screen
                            if (_myPlayerIndex !== null && pVal !== _myPlayerIndex) {
                                return _origTextEncode.call(this, input);
                            }
                            const target = _getTargetScore();
                            const newQ = Math.round(target * 10000) + (CONFIG.scoreBoost || 0);
                            const mod = _cgjEncode({p: pVal, q: newQ});
                            _lastSpoofedScore = target; spoofPanel();
                            _traceMatch('te_encode_pq', { oldQ: parseInt(pqMatch[2]), newQ, target });
                            log('[TEnc] patched p,q frame');
                            return _origTextEncode.call(this, mod);
                        }
                        // FINAL_SCORES (reliable channel, end-of-match scores)
                        if (input.indexOf('"type":"FINAL_SCORES"') >= 0) {
                            try {
                                const parsed = JSON.parse(input);
                                if (parsed && typeof parsed.p1 === 'number' && typeof parsed.p2 === 'number') {
                                    const target = _getTargetScore();
                                    const newFloat = target + (CONFIG.scoreBoost / 10000);
                                    const oppFloat = Math.max(0, newFloat - 0.5);
                                    if (_myPlayerIndex === 0 || _myPlayerIndex === null) {
                                        parsed.p1 = newFloat;
                                        parsed.p2 = oppFloat;
                                    } else {
                                        parsed.p2 = newFloat;
                                        parsed.p1 = oppFloat;
                                    }
                                    if (typeof parsed.score === 'number') parsed.score = newFloat;
                                    if (typeof parsed.overall === 'number') parsed.overall = newFloat;
                                    if (typeof parsed.myScore === 'number') parsed.myScore = newFloat;
                                    if (typeof parsed.myScoreRaw === 'number') parsed.myScoreRaw = Math.round(target * 10000) + (CONFIG.scoreBoost || 0);
                                    logT('TEnc', `patched FINAL_SCORES (p1=${parsed.p1} p2=${parsed.p2} idx=${_myPlayerIndex})`);
                                    return _origTextEncode.call(this, _cgjEncode(parsed));
                                }
                            } catch(e) {}
                        }
                        // SCAN_STATE face metrics — inflate ALL 0-1 metrics to 1.0
                        // This is the LAST TEXT hook before LiveKit wraps in protobuf.
                        // Without this, the DC send hook only sees garbled protobuf bytes.
                        if (input.indexOf('"type":"SCAN_STATE"') >= 0) {
                            try {
                                const parsed = JSON.parse(input);
                                const targetObj = parsed.payload && typeof parsed.payload === 'object' ? parsed.payload : parsed;
                                const SCAN_BOOST_KEYS = ['looking', 'attention', 'smile', 'smiling', 'mouthOpen', 'quality', 'confidence', 'readiness', 'engagement', 'focus', 'eyeContact', 'faceQuality', 'trackingQuality', 'detectionQuality', 'overall', 'score', 'your_score', 'yourScore'];
                                function _isQualityKey(k) { return SCAN_BOOST_KEYS.includes(k) || k.toLowerCase().includes('qual') || k.toLowerCase().includes('conf') || k.toLowerCase().includes('smil') || k.toLowerCase().includes('look') || k.toLowerCase().includes('eye') || k.toLowerCase().includes('attention') || k.toLowerCase().includes('engagement') || k.toLowerCase().includes('focus'); }
                                let found = false;
                                for (const k of Object.keys(targetObj)) {
                                    const v = targetObj[k];
                                    if (typeof v === 'number' && v >= 0 && _isQualityKey(k) && v !== 1) {
                                        if (targetObj === parsed) { parsed[k] = 1.0; } else { parsed.payload[k] = 1.0; }
                                        found = true;
                                    }
                                }
                                if (found) {
                                    log('[TEnc] patched SCAN_STATE metrics → 1.0');
                                    return _origTextEncode.call(this, _cgjEncode(parsed));
                                }
                            } catch(e) {}
                        }
                        // Generic score frames: {"score": X, ...}
                        if (input.includes('"score"') && input.length < 500) {
                            try {
                                const parsed = JSON.parse(input);
                                if (typeof parsed.score === 'number' && !parsed.p && !parsed.q) {
                                    const target = _getTargetScore();
                                    const newFloat = target + (CONFIG.scoreBoost / 10000);
                                    parsed.score = newFloat;
                                    if (typeof parsed.overall === 'number') parsed.overall = newFloat;
                                    if (typeof parsed.your_score === 'number') parsed.your_score = newFloat;
                                    log('[TEnc] patched generic score frame');
                                    return _origTextEncode.call(this, _cgjEncode(parsed));
                                }
                            } catch(e) {}
                        }
                        // score_submit messages
                        if (input.includes('"score_submit"') && input.includes('"self_score"')) {
                            try {
                                const parsed = JSON.parse(input);
                                if (parsed.type === 'score_submit' && parsed.payload && typeof parsed.payload.self_score === 'number') {
                                    const target = _getTargetScore();
                                    const newFloat = target + (CONFIG.scoreBoost / 10000);
                                    parsed.payload.self_score = newFloat;
                                    log('[TEnc] patched score_submit in TextEncoder');
                                    return _origTextEncode.call(this, _cgjEncode(parsed));
                                }
                            } catch(e) {}
                        }
                    }
                } catch(e) {}
                return _origTextEncode.call(this, input);
            };
            TextEncoder.prototype.encode.__cmHooked = true;
            log('[TEnc] TextEncoder.prototype.encode hooked (LiveKit bypass)');
        }
    }

    const _dcInstances = [];
    const _rtcDcProto = (_window.RTCDataChannel || RTCDataChannel).prototype;
    const _origNativeDcSend = _rtcDcProto.send;

    function _hookDataChannel(dc) {
        if (!dc.__cmHooked) _dcInstances.push(dc);
        const _realDcSend = (typeof _origNativeDcSend !== 'undefined' ? _origNativeDcSend : (_window.RTCDataChannel || RTCDataChannel).prototype.send).bind(dc);
        dc.__cmNativeSend = _realDcSend;
        dc.__cmHooked = true;
        dc.send = function(data) {
            if (data instanceof ArrayBuffer || data instanceof Uint8Array) {
                const bytes = data instanceof ArrayBuffer ? new Uint8Array(data) : data;

                const str = new TextDecoder().decode(data);
                const clean = str.replace(/[^\x20-\x7E]/g, '');
                if (!_lastDcLogTime || Date.now() - _lastDcLogTime > 2000) { _lastDcLogTime = Date.now(); log(`[DC SEND bin] ${clean.substring(0, 200)}`); }
            } else if (typeof data === 'string') {
                if (data.includes('score') || data.includes('elo') || data.includes('q')) {
                    log('[DC SEND text] ' + data.substring(0, 300));
                }
            }
        const _tryDecode = function(d) {
                try {
                    let text;
                    if (typeof d === 'string') {
                        text = d;
                    } else {
                        const bytes = d instanceof ArrayBuffer ? new Uint8Array(d) : d;
                        if (!(bytes instanceof Uint8Array)) return null;
                        text = new TextDecoder().decode(bytes);
                    }
                    const m = text.match(/\{[^}]+\}/);
                    if (m) try { return { json: JSON.parse(m[0]), bytes, fullText: text, jsonText: m[0] }; } catch(e) {}
                    try { return { json: JSON.parse(text), bytes, fullText: text, jsonText: text }; } catch(e) {}
                    let depth = 0, start = -1;
                    for (let i = 0; i < text.length; i++) {
                        if (text[i] === '{') { if (start === -1) start = i; depth++; }
                        else if (text[i] === '}') { depth--; if (depth === 0 && start !== -1) try { const sub = text.substring(start, i + 1); return { json: JSON.parse(sub), bytes, fullText: text, jsonText: sub }; } catch(e) { start = -1; } }
                    }
                } catch(e) {}
                return null;
            };
            const parsed = _tryDecode(data);
            if (parsed?.json) {
                const { json, bytes, fullText, jsonText } = parsed;
                const hasP = typeof json.p !== 'undefined';
                const hasQ = typeof json.q !== 'undefined';
                const hasScore = typeof json.score !== 'undefined';
                const hasS = typeof json.s !== 'undefined';
                const isNormalFrame = hasP && hasQ && json.m === undefined;
                const isRankedFrame = hasP && hasQ && json.m !== undefined;
                        // Patch p1/p2 (no underscore) in DC frames
                if (typeof json.p1 === 'number' && typeof json.p2 === 'number' && !hasP && !hasQ && json.type !== 'SCAN_STATE') {
                    const ourKey = _myPlayerIndex === 0 ? 'p1' : (_myPlayerIndex === 1 ? 'p2' : 'p1');
                    const oppKey = ourKey === 'p1' ? 'p2' : 'p1';
                    const modified = { ...json };
                    const target = _getTargetScore();
                    const ft = _getFinalTarget();
                    const ff = ft / 10000;
                    const oldOurs = modified[ourKey];
                    modified[ourKey] = (oldOurs > 100 ? ft : ff) + (oldOurs > 100 ? CONFIG.scoreBoost : CONFIG.scoreBoost / 10000);
                    modified[oppKey] = json[oppKey];
                    if (modified.winner !== undefined) modified.winner = 'self';
                    if (modified.result !== undefined) modified.result = 'win';
                    logT('DC-HOOK', `p1/p2 patch: ${ourKey}: ${oldOurs} → ${modified[ourKey]}`);
                    const cgjStr = _cgjEncode(modified);
                    return _realDcSend(new TextEncoder().encode(cgjStr));
                }
                if (isNormalFrame || isRankedFrame) {
                            if (_myPlayerIndex === null && typeof json.p === 'number' && (json.p === 0 || json.p === 1)) {
                                _myPlayerIndex = json.p;
                                _traceMatch('dc_pq_myPlayerIndex', { p: json.p });
                            }
                            // Only patch OUR score frames — don't inflate opponent's score on their screen
                            if (_myPlayerIndex !== null && typeof json.p === 'number' && json.p !== _myPlayerIndex) {
                                return _realDcSend(data);
                            }
                            if (json.q > 0) {
                                if (!scoreSpoofAllowed()) return _realDcSend(data);
                                const modified = { ...json };
                                const target = _getTargetScore();
                                const newScore = Math.round(target * 10000) + CONFIG.scoreBoost;
                                const newFloat = target + (CONFIG.scoreBoost / 10000);
                                const origQ = json.q;
                                modified.q = newScore;
                                modified.s = newScore;
                                if (typeof json.score === 'number') modified.score = newFloat;
                                if (typeof json.overall === 'number') modified.overall = newFloat;
                                if (typeof json.your_score === 'number') modified.your_score = newFloat;
                                if (typeof json.yourScore === 'number') modified.yourScore = newFloat;
                                if (typeof json.self_score === 'number') modified.self_score = newFloat;
                                if (json.payload && typeof json.payload === 'object') {
                                    modified.payload = { ...json.payload };
                                    modified.payload.overall = newFloat;
                                    if (typeof json.payload.score === 'number') modified.payload.score = newFloat;
                                    if (typeof json.payload.your_score === 'number') modified.payload.your_score = newFloat;
                                    if (typeof json.payload.self_score === 'number') modified.payload.self_score = newFloat;
                                }
                                _lastSpoofedScore = target;
                                spoofPanel();
                                _traceMatch('dc_pq_frame', { origQ, newScore, target });
                                log('[DC HOOK] patched q=' + json.q + ' -> ' + newScore + ' score=' + (json.score||'?') + '->' + newFloat);
                                const cgjStr = _cgjEncode(modified);
                                return _realDcSend(new TextEncoder().encode(cgjStr));
                            }
                        }
                if (hasScore && scoreSpoofAllowed()) {
                    const modified = { ...json };
                    modified.score = _getTargetScore();
                    if (modified.payload && typeof modified.payload === 'object') {
                        modified.payload = { ...modified.payload };
                        modified.payload.overall = _getTargetScore();
                    }
                    _lastSpoofedScore = modified.score;
                    spoofPanel();
                    log('[DC HOOK SCORE] patched score field');
                    const cgjStr = _cgjEncode(modified);
                    return _realDcSend(new TextEncoder().encode(cgjStr));
                }
                if (scoreSpoofAllowed() && json.payload && typeof json.payload === 'object' && !json.type && (hasS || typeof json.score === 'number' || typeof json.overall === 'number')) {
                    const modified = { ...json };
                    const target = _getTargetScore();
                    modified.payload = { ...json.payload };
                    modified.payload.overall = target;
                    _lastSpoofedScore = target;
                    spoofPanel();
                    log('[DC HOOK S/OVERALL] patched');
                    const cgjStr = _cgjEncode(modified);
                    return _realDcSend(new TextEncoder().encode(cgjStr));
                }
                // Patch score_submit in DC frames
                if (json.type === 'score_submit' && json.payload && typeof json.payload === 'object' && scoreSpoofAllowed()) {
                    const target = _getTargetScore();
                    const modified = { ...json, payload: { ...json.payload } };
                    let subPatched = false;
                    if (typeof modified.payload.self_score === 'number') {
                        const oldSelf = modified.payload.self_score;
                        modified.payload.self_score = target + (CONFIG.scoreBoost / 10000);
                        _traceMatch('dc_score_submit', { oldSelf, newSelf: modified.payload.self_score, opponent: modified.payload.opponent_score });
                        logT('DC-HOOK', `patched score_submit.self_score ${oldSelf} → ${modified.payload.self_score}`);
                        subPatched = true;
                    }
                    // Inflate quality/reliability flags to make server trust our score
                    for (const qf of ['quality', 'reliability', 'confidence', 'trust', 'valid']) {
                        if (typeof modified.payload[qf] === 'number') {
                            const old = modified.payload[qf];
                            modified.payload[qf] = 1.0;
                            logT('DC-HOOK', `score_submit ${qf}: ${old} → 1.0`);
                            subPatched = true;
                        }
                    }
                    if (subPatched) {
                        _lastSpoofedScore = target; spoofPanel();
                        const cgjStr = _cgjEncode(modified);
                        return _realDcSend(new TextEncoder().encode(cgjStr));
                    }
                }
                // Catch-all: patch DC frames with omoggle method names
                if (scoreSpoofAllowed()) {
                    const method = json.method || json.type || json.action || '';
                    if (method === 'setOpponentScore') return _realDcSend(data);
                    const scoreMethods = ['setMyScore', 'setLiveScores', 'setScore', 'applyFinalScores', 'applyFinalScore', 'setFrameNonce', 'setFinalPayloads', 'setRankedResult'];
                    if (scoreMethods.includes(method)) {
                        const target = _getTargetScore();
                        const raw = Math.round(target * 10000) + (CONFIG.scoreBoost || 0);
                        let mod = false;
                        const modified = { ...json };
                        if (typeof modified.score === 'number') { modified.score = target; mod = true; }
                        if (typeof modified.overall === 'number') { modified.overall = target; mod = true; }
                        if (modified.payload && typeof modified.payload === 'object') {
                            modified.payload = { ...modified.payload };
                            modified.payload.overall = target; mod = true;
                            modified.payload.score = target; mod = true;
                        }
                        if (Array.isArray(modified.args)) {
                            if (modified.args.length >= 2 && modified.args.length <= 3) {
                                const myScoreIdx = _myPlayerIndex !== null ? _myPlayerIndex : 0;
                                for (let i = 0; i < modified.args.length; i++) {
                                    if (i === myScoreIdx && typeof modified.args[i] === 'number') {
                                        if (modified.args[i] > 0.1 && modified.args[i] < 9999) { modified.args[i] = target; mod = true; }
                                        else if (modified.args[i] > 1000 && modified.args[i] < 99999999) { modified.args[i] = raw; mod = true; }
                                    }
                                }
                            } else {
                                for (let i = 0; i < modified.args.length; i++) {
                                    if (typeof modified.args[i] === 'number' && modified.args[i] > 0.1 && modified.args[i] < 9999) { modified.args[i] = target; mod = true; }
                                    if (typeof modified.args[i] === 'number' && modified.args[i] > 1000 && modified.args[i] < 99999999) { modified.args[i] = raw; mod = true; }
                                }
                            }
                        }
                        if (mod) {
                            logT('DC-HOOK', `patched ${method} frame`);
                            _lastSpoofedScore = target; spoofPanel();
                            const cgjStr = _cgjEncode(modified);
                            return _realDcSend(new TextEncoder().encode(cgjStr));
                        }
                    }
                }
                // Inflate SCAN_STATE face metrics to make server compute higher score
                if (json.type === 'SCAN_STATE' && (scoreSpoofAllowed() || CONFIG.verifBypassActive)) {
                    const modified = { ...json };
                    let scanPatched = false;
                    const targets = json.payload && typeof json.payload === 'object' ? json.payload : json;
                    const modTarget = targets === json ? modified : (modified.payload = { ...json.payload });
                    const TARGET_MAX_FIELDS = ['looking', 'attention', 'smile', 'smiling', 'mouthOpen', 'quality', 'confidence', 'readiness', 'engagement', 'focus', 'eyeContact', 'faceQuality', 'trackingQuality', 'detectionQuality', 'overall'];
                    function _isQKey(k) { return TARGET_MAX_FIELDS.includes(k) || k.toLowerCase().includes('qual') || k.toLowerCase().includes('conf') || k.toLowerCase().includes('smil') || k.toLowerCase().includes('look') || k.toLowerCase().includes('eye') || k.toLowerCase().includes('attention') || k.toLowerCase().includes('engagement'); }
                    for (const k of Object.keys(targets)) {
                        const v = targets[k];
                        if (typeof v === 'number' && v >= 0 && _isQKey(k) && v !== 1) {
                            if (targets === json) { modified[k] = 1.0; }
                            else { modified.payload[k] = 1.0; }
                            scanPatched = true;
                        }
                    }
                    if (scanPatched) {
                        logT('DC-HOOK', `patched SCAN_STATE metrics → 1.0`);
                        const cgjStr = _cgjEncode(modified);
                        return _realDcSend(new TextEncoder().encode(cgjStr));
                    }
                }
                // Diagnostic: log keys of every unmatched JSON frame (rate-limited)
                if (json && Object.keys(json).length > 0) {
                    const keys = Object.keys(json).sort().join(',');
                    if (json.type !== 'SCAN_STATE') {
                        logT('DC-FRAME', `${keys}${json.score!==undefined ? ' score='+json.score : ''}${json.q!==undefined ? ' q='+json.q : ''}${json.s!==undefined ? ' s='+json.s : ''}`);
                    }
                }
            }
            return _realDcSend(data);
        };
        dc.__cmHooked = true;
    }

    // DC spam disabled — causes conflicting frames for opponent. Use reactive patching only.
    // setInterval(null, 50);

    // Intercept data channel creation
    const _rtcProto = (_window.RTCPeerConnection || RTCPeerConnection).prototype;
    const _dcProto = (_window.RTCDataChannel || RTCDataChannel).prototype;
    try {
        const origCreateDC = _rtcProto.createDataChannel;
        if (origCreateDC) {
            _rtcProto.createDataChannel = function(label, options) {
                const dc = origCreateDC.call(this, label, options);
                _hookDataChannel(dc);
                return dc;
            };
        }
    } catch(e) {}

    // Intercept ondatachannel
    try {
        const ondDesc = Object.getOwnPropertyDescriptor(_rtcProto, 'ondatachannel');
        if (ondDesc && ondDesc.set) {
            Object.defineProperty(_rtcProto, 'ondatachannel', {
                set(fn) {
                    ondDesc.set.call(this, function(event) {
                        _hookDataChannel(event.channel);
                        return fn.call(this, event);
                    });
                },
                get: ondDesc.get
            });
        }
    } catch(e) {}

    // Intercept addEventListener('datachannel')
    try {
        const origAEL = _rtcProto.addEventListener;
        if (origAEL) {
            _rtcProto.addEventListener = function(type, listener, options) {
                if (type === 'datachannel') {
                    const wrapped = function(event) {
                        _hookDataChannel(event.channel);
                        return listener.call(this, event);
                    };
                    return origAEL.call(this, type, wrapped, options);
                }
                return origAEL.call(this, type, listener, options);
            };
        }
    } catch(e) {}

    // Patch incoming DC frames — wraps onmessage + addEventListener to patch scores via _patchIncomingScore
    function _makeDcIncomingWrapper(fn) {
        return function(event) {
            try {
                const patched = _patchIncomingScore(event.data);
                if (patched) {
                    return fn.call(this, _makePatchedEvent(event, patched));
                }
            } catch(e) {}
            return fn.call(this, event);
        };
    }

    try {
        const inDesc = Object.getOwnPropertyDescriptor(_dcProto, 'onmessage');
        if (inDesc) {
            Object.defineProperty(_dcProto, 'onmessage', {
                set(fn) {
                    inDesc.set.call(this, _makeDcIncomingWrapper(fn));
                },
                get: inDesc.get,
                configurable: true
            });
        }
    } catch(e) {}

    try {
        const origDcAEL = _dcProto.addEventListener;
        if (origDcAEL) {
            _dcProto.addEventListener = function(type, listener, options) {
                if (type === 'message' && typeof listener === 'function') {
                    return origDcAEL.call(this, type, _makeDcIncomingWrapper(listener), options);
                }
                return origDcAEL.call(this, type, listener, options);
            };
        }
    } catch(e) {}
    // ── End of DC setup ──

    // ── Incoming WebSocket message score patcher (intercepts server→client messages) ──
    // dispatchEvent override doesn't work in V8 for native EventTarget.
    // Instead, wrap addEventListener to intercept message handlers.
    function _makePatchedEvent(event, patchedData) {
        const ME = window.MessageEvent || _window.MessageEvent || (typeof MessageEvent !== 'undefined' ? MessageEvent : null);
        if (!ME) {
            // Last resort: manually construct a plain object (risky but better than null)
            const e = { type: 'message', data: patchedData, origin: event.origin || '', lastEventId: event.lastEventId || '', ports: event.ports || [], source: event.source || null };
            e.target = event.target; e.currentTarget = event.currentTarget;
            return e;
        }
        const newEvent = new ME('message', {
            data: patchedData,
            origin: event.origin || '',
            lastEventId: event.lastEventId || '',
            ports: event.ports || [],
            source: event.source || null
        });
        Object.defineProperty(newEvent, 'target', { value: event.target, configurable: true });
        Object.defineProperty(newEvent, 'currentTarget', { value: event.currentTarget, configurable: true });
        return newEvent;
    }
    try {
        const _origWsAEL = _window.WebSocket.prototype.addEventListener;
        if (_origWsAEL) {
            _window.WebSocket.prototype.addEventListener = function(type, listener, options) {
                if (type === 'message' && typeof listener === 'function') {
                    const wrapped = function(event) {
                        try {
                            const patched = _patchIncomingScore(event.data);
                            if (patched) {
                                return listener.call(this, _makePatchedEvent(event, patched));
                            }
                        } catch(e) {}
                        return listener.call(this, event);
                    };
                    return _origWsAEL.call(this, type, wrapped, options);
                }
                return _origWsAEL.call(this, type, listener, options);
            };
            log('[WS IN] addEventListener message patching active');
        }
    } catch(e) { log('[WS IN] hook error: ' + e.message); }

    // ── WebSocket onmessage setter hook (catches ws.onmessage = handler) ──
    try {
        const _wsOnmessageDescriptor = Object.getOwnPropertyDescriptor(_window.WebSocket.prototype, 'onmessage');
        if (_wsOnmessageDescriptor && _wsOnmessageDescriptor.set) {
            const _origOnmessageSetter = _wsOnmessageDescriptor.set;
            Object.defineProperty(_window.WebSocket.prototype, 'onmessage', {
                configurable: true,
                enumerable: true,
                get: function() { return this._cm_onmessageHandler || null; },
                set: function(handler) {
                    this._cm_onmessageHandler = handler;
                    if (typeof handler === 'function') {
                        const ws = this;
                        return _origOnmessageSetter.call(this, function(event) {
                            try {
                                const patched = _patchIncomingScore(event.data);
                                if (patched) {
                                    return handler.call(ws, _makePatchedEvent(event, patched));
                                }
                            } catch(e) {}
                            return handler.call(ws, event);
                        });
                    }
                    return _origOnmessageSetter.call(this, handler);
                }
            });
            log('[WS IN] onmessage setter hook active');
        }
    } catch(e) { log('[WS IN] onmessage hook error: ' + e.message); }

    // ── postMessage hook (intercept + patch scores in worker/iframe communication) ──
    let _pmLog = 0;
    function _patchPostMsg(message) {
        try {
            if (typeof message !== 'object' || !message) return message;
            const parsed = typeof message === 'string' ? JSON.parse(message) : message;
            let mod = false;
            if (scoreSpoofAllowed()) {
                const target = _getTargetScore();
                // Check known field names + any numeric field that looks like a score
                for (const [k,v] of Object.entries(parsed)) {
                    if (typeof v === 'number' && v > 0.1 && v < 5000) {
                        parsed[k] = target; mod = true;
                        log(`[postMessage MOD] patched ${k}: ${v} → ${target}`);
                    } else if (typeof v === 'number' && v > 1000 && v < 99999999) {
                        parsed[k] = Math.round(target * 10000) + CONFIG.scoreBoost; mod = true;
                        log(`[postMessage MOD] patched raw ${k}: ${v} → ${parsed[k]}`);
                    } else if (typeof v === 'string' && /^\d+(\.\d+)?$/.test(v) && parseFloat(v) > 0.1 && parseFloat(v) < 11) {
                        parsed[k] = String(target); mod = true;
                        log(`[postMessage MOD] patched string ${k}: ${v} → ${parsed[k]}`);
                    }
                }
                if (parsed.payload && typeof parsed.payload === 'object') {
                    for (const [k,v] of Object.entries(parsed.payload)) {
                        if (typeof v === 'number' && v > 0.1 && v < 5000) { parsed.payload[k] = target; mod = true; log(`[postMessage MOD] patched payload.${k}`); }
                    }
                }
                // Override winner/result in postMessage
                if (typeof parsed.winner === 'string') { parsed.winner = 'self'; mod = true; }
                if (typeof parsed.result === 'string') { parsed.result = 'win'; mod = true; }
                // Override p1/p2 in postMessage
                if (typeof parsed.p1 === 'number' && typeof parsed.p2 === 'number') {
                    const ourKey = _myPlayerIndex === 0 ? 'p1' : (_myPlayerIndex === 1 ? 'p2' : 'p1');
                    parsed[ourKey] = target;
                    mod = true;
                }
            }
            // Diagnostic: log unknown messages that LOOK like score data
                if (!mod && _pmLog++ < 30) {
                const jsonStr = typeof message === 'string' ? message : JSON.stringify(message);
                if (jsonStr && jsonStr.length < 1000) {
                    const keys = Object.keys(parsed).join(',');
                    logT('POST-MSG', `keys=[${keys}] ${jsonStr.substring(0, 200)}`);
                }
            }
            if (mod) {
                return typeof message === 'string' ? JSON.stringify(parsed) : parsed;
            }
        } catch(e) {}
        return message;
    }
    try {
        const _origPostMessage = _window.postMessage;
        _window.postMessage = function(message, targetOrigin, transfer) {
            return _origPostMessage.call(this, _patchPostMsg(message), targetOrigin, transfer);
        };
        log('[postMessage] window.postMessage hooked');
    } catch(e) { log('[postMessage] hook error: ' + e.message); }
    try {
        if (_window.Worker) {
            const _origWorkerSend = _window.Worker.prototype.postMessage;
            _window.Worker.prototype.postMessage = function(message, options) {
                return _origWorkerSend.call(this, _patchPostMsg(message), options);
            };
            log('[postMessage] Worker.postMessage hooked');
        }
    } catch(e) { log('[postMessage] Worker error: ' + e.message); }
    try {
        if (_window.MessagePort) {
            const _origMpSend = _window.MessagePort.prototype.postMessage;
            _window.MessagePort.prototype.postMessage = function(message, options) {
                return _origMpSend.call(this, _patchPostMsg(message), options);
            };
            log('[postMessage] MessagePort.postMessage hooked');
        }
    } catch(e) { log('[postMessage] MessagePort error: ' + e.message); }

    // ── WebSocket send hook (dual-prototype + score_update messages) ──
    const _wsProtoCandidates = [WebSocket.prototype];
    if (_window.WebSocket && _window.WebSocket.prototype !== WebSocket.prototype) {
        _wsProtoCandidates.push(_window.WebSocket.prototype);
    }
    const _origWsSend = WebSocket.prototype.send;
    function _wsSendHook(data, origSend) {
        try {
            if (typeof data === 'string') {
                if (CONFIG.scoreEnabled) {
                    try {
                        const parsed = JSON.parse(data);
                        // Patch {p,q} frames
                        if (typeof parsed.p === 'number' && typeof parsed.q === 'number' && parsed.q > 0 && !parsed.type) {
                            if (_myPlayerIndex === null && (parsed.p === 0 || parsed.p === 1)) {
                                _myPlayerIndex = parsed.p;
                                _traceMatch('ws_pq_myPlayerIndex', { p: parsed.p });
                            }
                            // Only patch OUR score frames — don't inflate opponent's score on their screen
                            if (_myPlayerIndex !== null && parsed.p !== _myPlayerIndex) {
                                return origSend.call(this, data);
                            }
                            const target = _getTargetScore();
                            const oldQ = parsed.q;
                            parsed.q = Math.round(target * 10000) + CONFIG.scoreBoost;
                            parsed.s = Math.round(target * 10000) + CONFIG.scoreBoost;
                            _lastSpoofedScore = target;
                            spoofPanel();
                            _traceMatch('ws_pq_frame', { oldQ, newQ: parsed.q, target });
                            logT('WS-MOD', `patched p,q frame ${oldQ/10000} → ${parsed.q/10000}`);
                            const wsStr = _cgjEncode(parsed);
                            logT('CGJ', `p,q frame injected`);
                            return origSend.call(this, wsStr);
                        }
                        // Patch standalone 's' score field (user only, only when no p/q)
                        if (typeof parsed.s === 'number' && parsed.s > 0 && !parsed.q && !parsed.p && !parsed.type && !parsed.payload) {
                            const target = _getTargetScore();
                            const oldS = parsed.s;
                            parsed.s = parsed.s > 100 ? Math.round(target * 10000) + CONFIG.scoreBoost : target + (CONFIG.scoreBoost / 10000);
                            _lastSpoofedScore = target;
                            spoofPanel();
                            _traceMatch('ws_s_field', { oldS, newS: parsed.s, target });
                            logT('WS-MOD', `patched s field ${oldS} → ${parsed.s}`);
                            const wsStr = _cgjEncode(parsed);
                            logT('CGJ', `s field injected`);
                            return origSend.call(this, wsStr);
                        }
                        // Patch score_update messages (LiveKit / game protocol)
                        if (parsed.type === 'score_update' && parsed.payload && typeof parsed.payload.score === 'number') {
                            let boosted;
                            if (CONFIG.scoreMode === 'fixed') {
                                boosted = CONFIG.fixedScore / 10000;
                            } else {
                                boosted = _getTargetScore();
                            }
                            const oldScore = parsed.payload.score;
                            parsed.payload.score = boosted + (CONFIG.scoreBoost / 10000);
                            parsed.payload.overall = boosted + (CONFIG.scoreBoost / 10000);
                            _traceMatch('ws_score_update', { oldScore, newScore: parsed.payload.score, boosted });
                            logT('WS-MOD', `patched score_update ${oldScore} → ${parsed.payload.score}`);
                            const wsStr = _cgjEncode(parsed);
                            logT('CGJ', `score_update injected`);
                            return origSend.call(this, wsStr);
                        }
                        // Patch standalone score fields (no type, no p/q)
                        if (scoreSpoofAllowed() && typeof parsed.score === 'number' && !parsed.p && !parsed.q && parsed.score < 100) {
                            parsed.score = _getTargetScore();
                            logT('WS-MOD', `patched standalone score: ${parsed.score}`);
                            const wsStr = _cgjEncode(parsed);
                            logT('CGJ', `standalone score injected`);
                            return origSend.call(this, wsStr);
                        }
                        // Patch finalize fields
                        if (CONFIG.resultEnabled && !CONFIG.verifBypassActive && (data.includes('score') || data.includes('elo') || data.includes('final'))) {
                            const ft = _getFinalTarget();
                            const ff = ft / 10000;
                            let patched = false;
                            for (const field of ['myScore','selfScore','score','finalScore','totalScore','elo']) {
                                if (field in parsed) {
                                    const old = parsed[field];
                                    if (field === 'elo') {
                                        const num = typeof old === 'number' ? old : parseInt(old) || 0;
                                        parsed[field] = typeof old === 'number' ? num + CONFIG.eloBoost : String(num + CONFIG.eloBoost);
                                        patched = true;
                                    } else if (typeof old === 'number') {
                                        parsed[field] = (old > 100 ? ft : ff) + (old > 100 ? CONFIG.scoreBoost : CONFIG.scoreBoost / 10000);
                                        patched = true;
                                    } else if (typeof old === 'string') {
                                        const num = parseInt(old) || 0;
                                        parsed[field] = String(num > 100 ? ft + CONFIG.scoreBoost : ff + (CONFIG.scoreBoost / 10000));
                                        patched = true;
                                    }
                                }
                            }
                            // Patch p1/p2 (no underscore) in WS finalize
                            if (typeof parsed.p1 === 'number' && typeof parsed.p2 === 'number') {
                                const ourKey = _myPlayerIndex === 0 ? 'p1' : (_myPlayerIndex === 1 ? 'p2' : 'p1');
                                const oldOurs = parsed[ourKey];
                                parsed[ourKey] = (oldOurs > 100 ? ft : ff) + (oldOurs > 100 ? CONFIG.scoreBoost : CONFIG.scoreBoost / 10000);
                                logT('WS-FINALIZE', `${ourKey}: ${oldOurs} → ${parsed[ourKey]}`);
                                patched = true;
                            }
                            // Patch p1_score/p2_score: inflate only our score
                            if (typeof parsed.p1_score === 'number' && typeof parsed.p2_score === 'number') {
                                const ourKey = _myPlayerIndex === 0 ? 'p1_score' : (_myPlayerIndex === 1 ? 'p2_score' : (parsed.p1_score >= parsed.p2_score ? 'p1_score' : 'p2_score'));
                                const oldOurs = parsed[ourKey];
                                parsed[ourKey] = (oldOurs > 100 ? ft : ff) + (oldOurs > 100 ? CONFIG.scoreBoost : CONFIG.scoreBoost / 10000);
                                logT('WS-FINALIZE', `${ourKey}: ${oldOurs} → ${parsed[ourKey]}`);
                                patched = true;
                            }
                            // Override winner/result in WS finalize requests
                            if (parsed.winner !== undefined || parsed.result !== undefined) {
                                const origWinner = parsed.winner;
                                const origResult = parsed.result;
                                parsed.winner = 'self';
                                parsed.result = 'win';
                                logT('WS-FINALIZE', `winner: ${origWinner} → self, result: ${origResult} → win`);
                                patched = true;
                            }
                            if (patched) {
                                log('[WS FINALIZE] patched score fields (elo+scoreBoost)');
                                const wsStr = _cgjEncode(parsed);
                                logT('CGJ', `finalize fields injected`);
                                return origSend.call(this, wsStr);
                            }
                        }
                    } catch(e) {}
                }
                // Patch score_submit messages (modify ONLY self_score, not opponent_score)
                try {
                    const p = JSON.parse(data);
                    if (p.type === 'score_submit' && p.payload && typeof p.payload === 'object') {
                        const target = _getTargetScore();
                        let subPatched = false;
                        if (typeof p.payload.self_score === 'number') {
                            _traceMatch('ws_score_submit', { original_self: p.payload.self_score, target, opponent: p.payload.opponent_score });
                            p.payload.self_score = target + (CONFIG.scoreBoost / 10000);
                            _lastSpoofedScore = target;
                            spoofPanel();
                            logT('WS-MOD', `patched score_submit.self_score: ${target}`);
                            subPatched = true;
                        }
                        for (const qf of ['quality', 'reliability', 'confidence', 'trust', 'valid']) {
                            if (typeof p.payload[qf] === 'number') {
                                const old = p.payload[qf];
                                p.payload[qf] = 1.0;
                                logT('WS-MOD', `score_submit ${qf}: ${old} → 1.0`);
                                subPatched = true;
                            }
                        }
                        if (subPatched) {
                            const wsStr = _cgjEncode(p);
                            logT('CGJ', `score_submit injected`);
                            return origSend.call(this, wsStr);
                        }
                    }
                } catch(e) {}
                // Inflate WS SCAN_STATE face metrics
                try {
                    const p = JSON.parse(data);
                    if (p.type === 'SCAN_STATE' && (scoreSpoofAllowed() || CONFIG.verifBypassActive) && p.payload && typeof p.payload === 'object') {
                        let scanPatched = false;
                        const TARGET_MAX_FIELDS = ['looking', 'attention', 'smile', 'smiling', 'mouthOpen', 'quality', 'confidence', 'readiness', 'engagement', 'focus', 'eyeContact', 'faceQuality', 'trackingQuality', 'detectionQuality', 'overall'];
                        function _isQKey(k) { return TARGET_MAX_FIELDS.includes(k) || k.toLowerCase().includes('qual') || k.toLowerCase().includes('conf') || k.toLowerCase().includes('smil') || k.toLowerCase().includes('look') || k.toLowerCase().includes('eye') || k.toLowerCase().includes('attention') || k.toLowerCase().includes('engagement'); }
                        for (const k of Object.keys(p.payload)) {
                            const v = p.payload[k];
                            if (typeof v === 'number' && v >= 0 && _isQKey(k) && v !== 1) {
                                p.payload[k] = 1.0;
                                scanPatched = true;
                            }
                        }
                        if (scanPatched) {
                            logT('WS-MOD', `patched SCAN_STATE metrics → 1.0`);
                            const wsStr = _cgjEncode(p);
                            return origSend.call(this, wsStr);
                        }
                    }
                } catch(e) {}
                // Catch-all: patch WS text with omoggle method names
                if (scoreSpoofAllowed()) {
                    try {
                        const parsed = JSON.parse(data);
                        const method = parsed.method || parsed.type || parsed.action || '';
                        const scoreMethods = ['setMyScore', 'setLiveScores', 'setScore', 'applyFinalScores', 'applyFinalScore', 'setFrameNonce', 'setFinalPayloads', 'setRankedResult'];
                        if (scoreMethods.includes(method) && !['score_update','SCAN_STATE','score_submit'].includes(parsed.type)) {
                            const target = _getTargetScore();
                            const raw = Math.round(target * 10000) + (CONFIG.scoreBoost || 0);
                            let mod = false;
                            if (typeof parsed.score === 'number') { parsed.score = target; mod = true; }
                            if (typeof parsed.overall === 'number') { parsed.overall = target; mod = true; }
                            if (parsed.payload && typeof parsed.payload === 'object') {
                                parsed.payload.overall = target; mod = true;
                                if (typeof parsed.payload.score === 'number' && !parsed.payload.self_score) { parsed.payload.score = target; mod = true; }
                            }
                            if (Array.isArray(parsed.args)) {
                                if (parsed.args.length >= 2 && parsed.args.length <= 3) {
                                    const myScoreIdx = _myPlayerIndex !== null ? _myPlayerIndex : 0;
                                    for (let i = 0; i < parsed.args.length; i++) {
                                        if (i === myScoreIdx && typeof parsed.args[i] === 'number') {
                                            if (parsed.args[i] > 0.1 && parsed.args[i] < 9999) { parsed.args[i] = target; mod = true; }
                                            else if (parsed.args[i] > 1000 && parsed.args[i] < 99999999) { parsed.args[i] = raw; mod = true; }
                                        }
                                    }
                                } else {
                                    for (let i = 0; i < parsed.args.length; i++) {
                                        if (typeof parsed.args[i] === 'number' && parsed.args[i] > 0.1 && parsed.args[i] < 9999) { parsed.args[i] = target; mod = true; }
                                        if (typeof parsed.args[i] === 'number' && parsed.args[i] > 1000 && parsed.args[i] < 99999999) { parsed.args[i] = raw; mod = true; }
                                    }
                                }
                            }
                            if (mod) {
                                logT('WS-MOD', `patched ${method}`);
                                const wsStr = _cgjEncode(parsed);
                                logT('CGJ', `${method} injected`);
                                return origSend.call(this, wsStr);
                            }
                        }
                    } catch(e) {}
                }
                log('[WS OUT] ' + data.substring(0, 300));
            } else if (data instanceof ArrayBuffer || data instanceof Uint8Array) {
                const str = new TextDecoder().decode(data instanceof Uint8Array ? data : new Uint8Array(data));
                const clean = str.replace(/[^\x20-\x7E]/g, '');
                if (clean) {
                    if (scoreSpoofAllowed()) {
                        try {
                            const parsed = JSON.parse(clean);
                            if (typeof parsed.p === 'number' && typeof parsed.q === 'number' && parsed.q > 0 && !parsed.type) {
                                if (_myPlayerIndex === null && (parsed.p === 0 || parsed.p === 1)) {
                                    _myPlayerIndex = parsed.p;
                                    _traceMatch('ws_bin_pq_myPlayerIndex', { p: parsed.p });
                                }
                                // Only patch OUR score frames — don't inflate opponent's score on their screen
                                if (_myPlayerIndex !== null && parsed.p !== _myPlayerIndex) {
                                    return origSend.call(this, data);
                                }
                                const target = _getTargetScore();
                                parsed.q = Math.round(target * 10000) + CONFIG.scoreBoost;
                                parsed.s = Math.round(target * 10000) + CONFIG.scoreBoost;
                                _lastSpoofedScore = target;
                                spoofPanel();
                                log('[WS MOD bin] patched p,q');
                                const wsStr = _cgjEncode(parsed);
                                log(`[WS CGJ bin] p,q injected`);
                                return origSend.call(this, new TextEncoder().encode(wsStr));
                            }
                            if (typeof parsed.s === 'number' && parsed.s > 0 && !parsed.p && !parsed.q && !parsed.type && !parsed.payload) {
                                const target = _getTargetScore();
                                parsed.s = parsed.s > 100 ? Math.round(target * 10000) + CONFIG.scoreBoost : target + (CONFIG.scoreBoost / 10000);
                                _lastSpoofedScore = target;
                                spoofPanel();
                                log('[WS MOD bin] patched s field');
                                const wsStr = _cgjEncode(parsed);
                                log(`[WS CGJ bin] s field injected`);
                                return origSend.call(this, new TextEncoder().encode(wsStr));
                            }
                            if (parsed.type === 'score_update' && parsed.payload && typeof parsed.payload.score === 'number') {
                                let boosted;
                                boosted = CONFIG.scoreMode === 'fixed' ? CONFIG.fixedScore / 10000 : _getTargetScore();
                                const oldScore = parsed.payload.score;
                                parsed.payload.score = boosted + (CONFIG.scoreBoost / 10000);
                                parsed.payload.overall = boosted + (CONFIG.scoreBoost / 10000);
                                _traceMatch('ws_bin_score_update', { oldScore, newScore: parsed.payload.score, boosted });
                                log(`[WS MOD bin] patched score_update ${oldScore} → ${parsed.payload.score}`);
                                const wsStr = _cgjEncode(parsed);
                                log(`[WS CGJ bin] score_update injected`);
                                return origSend.call(this, new TextEncoder().encode(wsStr));
                            }
                        } catch(e) {}
                        if (CONFIG.resultEnabled && !CONFIG.verifBypassActive && (clean.includes('score') || clean.includes('elo') || clean.includes('final'))) {
                            try {
                                const parsed = JSON.parse(clean);
                                const ft = _getFinalTarget();
                                const ff = ft / 10000;
                                let patched = false;
                                for (const field of ['myScore','selfScore','score','finalScore','totalScore','elo','s']) {
                                    if (field in parsed) {
                                        const old = parsed[field];
                                        if (field === 'elo') {
                                            const num = typeof old === 'number' ? old : parseInt(old) || 0;
                                            parsed[field] = typeof old === 'number' ? num + CONFIG.eloBoost : String(num + CONFIG.eloBoost);
                                            patched = true;
                                        } else if (typeof old === 'number') {
                                            parsed[field] = (old > 100 ? ft : ff) + (old > 100 ? CONFIG.scoreBoost : CONFIG.scoreBoost / 10000);
                                            patched = true;
                                        } else if (typeof old === 'string') {
                                            const num = parseInt(old) || 0;
                                            parsed[field] = String(num > 100 ? ft + CONFIG.scoreBoost : ff + (CONFIG.scoreBoost / 10000));
                                            patched = true;
                                        }
                                    }
                                }
                                // Patch p1/p2 (no underscore) in WS binary finalize
                                if (typeof parsed.p1 === 'number' && typeof parsed.p2 === 'number') {
                                    const ourKey = _myPlayerIndex === 0 ? 'p1' : (_myPlayerIndex === 1 ? 'p2' : 'p1');
                                    const oldOurs = parsed[ourKey];
                                    parsed[ourKey] = (oldOurs > 100 ? ft : ff) + (oldOurs > 100 ? CONFIG.scoreBoost : CONFIG.scoreBoost / 10000);
                                    log(`[WS FINALIZE bin] ${ourKey}: ${oldOurs} → ${parsed[ourKey]}`);
                                    patched = true;
                                }
                                // Patch p1_score/p2_score: inflate only our score
                                if (typeof parsed.p1_score === 'number' && typeof parsed.p2_score === 'number') {
                                    const ourKey = _myPlayerIndex === 0 ? 'p1_score' : (_myPlayerIndex === 1 ? 'p2_score' : (parsed.p1_score >= parsed.p2_score ? 'p1_score' : 'p2_score'));
                                    const oldOurs = parsed[ourKey];
                                    parsed[ourKey] = (oldOurs > 100 ? ft : ff) + (oldOurs > 100 ? CONFIG.scoreBoost : CONFIG.scoreBoost / 10000);
                                    log(`[WS FINALIZE bin] ${ourKey}: ${oldOurs} → ${parsed[ourKey]}`);
                                    patched = true;
                                }
                                // Override winner/result in WS binary finalize requests
                                if (parsed.winner !== undefined || parsed.result !== undefined) {
                                    const origWinner = parsed.winner;
                                    const origResult = parsed.result;
                                    parsed.winner = 'self';
                                    parsed.result = 'win';
                                    log(`[WS FINALIZE bin] winner: ${origWinner} → self, result: ${origResult} → win`);
                                    patched = true;
                                }
                                if (patched) {
                                    log('[WS FINALIZE bin] patched');
                                    const wsStr = _cgjEncode(parsed);
                                    log(`[WS CGJ bin] finalize fields injected`);
                                    return origSend.call(this, new TextEncoder().encode(wsStr));
                                }
                            } catch(e) {}
                        }
                    }
                    // Patch score_submit messages in binary too
                    if (clean.includes('score_submit')) {
                        try {
                            const parsed = JSON.parse(clean);
                            if (parsed.type === 'score_submit' && parsed.payload && typeof parsed.payload === 'object') {
                                const target = _getTargetScore();
                                if (typeof parsed.payload.self_score === 'number') {
                                    const oldSelf = parsed.payload.self_score;
                                    parsed.payload.self_score = target + (CONFIG.scoreBoost / 10000);
                                    _lastSpoofedScore = target;
                                    spoofPanel();
                                    _traceMatch('ws_bin_score_submit', { oldSelf, newSelf: parsed.payload.self_score, opponent: parsed.payload.opponent_score });
                                    log(`[WS MOD bin] patched score_submit.self_score ${oldSelf} → ${parsed.payload.self_score}`);
                                    const wsStr = _cgjEncode(parsed);
                                    log(`[WS CGJ bin] score_submit injected`);
                                    return origSend.call(this, new TextEncoder().encode(wsStr));
                                }
                            }
                        } catch(e) {}
                    }
                    // Catch-all: patch WS binary with omoggle method names
                    try {
                        const parsed = JSON.parse(clean);
                        const method = parsed.method || parsed.type || parsed.action || '';
                        const scoreMethods = ['setMyScore', 'setLiveScores', 'setScore', 'applyFinalScores', 'applyFinalScore', 'setFrameNonce', 'setFinalPayloads', 'setRankedResult'];
                        if (scoreMethods.includes(method) && !['score_update','SCAN_STATE','score_submit'].includes(parsed.type)) {
                            const target = _getTargetScore();
                            const raw = Math.round(target * 10000) + (CONFIG.scoreBoost || 0);
                            let mod = false;
                            if (typeof parsed.score === 'number') { parsed.score = target; mod = true; }
                            if (typeof parsed.overall === 'number') { parsed.overall = target; mod = true; }
                            if (parsed.payload && typeof parsed.payload === 'object') {
                                parsed.payload.overall = target; mod = true;
                                if (typeof parsed.payload.score === 'number' && !parsed.payload.self_score) { parsed.payload.score = target; mod = true; }
                            }
                            if (Array.isArray(parsed.args)) {
                                if (parsed.args.length >= 2 && parsed.args.length <= 3) {
                                    const myScoreIdx = _myPlayerIndex !== null ? _myPlayerIndex : 0;
                                    for (let i = 0; i < parsed.args.length; i++) {
                                        if (i === myScoreIdx && typeof parsed.args[i] === 'number') {
                                            if (parsed.args[i] > 0.1 && parsed.args[i] < 9999) { parsed.args[i] = target; mod = true; }
                                            else if (parsed.args[i] > 1000 && parsed.args[i] < 99999999) { parsed.args[i] = raw; mod = true; }
                                        }
                                    }
                                } else {
                                    for (let i = 0; i < parsed.args.length; i++) {
                                        if (typeof parsed.args[i] === 'number' && parsed.args[i] > 0.1 && parsed.args[i] < 9999) { parsed.args[i] = target; mod = true; }
                                        if (typeof parsed.args[i] === 'number' && parsed.args[i] > 1000 && parsed.args[i] < 99999999) { parsed.args[i] = raw; mod = true; }
                                    }
                                }
                            }
                            if (mod) {
                                log(`[WS MOD bin] patched ${method}`);
                                const wsStr = _cgjEncode(parsed);
                                log(`[WS CGJ bin] ${method} injected`);
                                return origSend.call(this, new TextEncoder().encode(wsStr));
                            }
                        }
                    } catch(e) {}
                    logT('WS-OUT', clean.substring(0, 200));
                }
            }
        } catch(e) {}
        // Universal ELO boost: scan any outbound message for ELO fields regardless of flags
        try {
            if (CONFIG.eloBoost > 0 && typeof data === 'string') {
                const eparsed = JSON.parse(data);
                let eMod = false;
                for (const ef of ['elo','eloChange','e']) {
                    if (ef in eparsed) {
                        const ev = eparsed[ef];
                        const num = typeof ev === 'number' ? ev : parseInt(ev) || 0;
                        eparsed[ef] = typeof ev === 'number' ? num + CONFIG.eloBoost : String(num + CONFIG.eloBoost);
                        eMod = true;
                    }
                }
                if (eparsed.u?.e !== undefined) {
                    eparsed.u.e = String((parseInt(eparsed.u.e) || 0) + CONFIG.eloBoost);
                    eMod = true;
                }
                if (eparsed.i?.e !== undefined) {
                    eparsed.i.e = String((parseInt(eparsed.i.e) || 0) + CONFIG.eloBoost);
                    eMod = true;
                }
                if (eMod) {
                    logT('WS-ELO', `boosted ELO fields by ${CONFIG.eloBoost}`);
                    const wsStr = _cgjEncode(eparsed);
                    logT('CGJ', `ELO univ injected`);
                    return origSend.call(this, wsStr);
                }
            } else if (CONFIG.eloBoost > 0 && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
                const estr = new TextDecoder().decode(data instanceof Uint8Array ? data : new Uint8Array(data));
                const eclean = estr.replace(/[^\x20-\x7E]/g, '');
                if (eclean) {
                    const eparsed = JSON.parse(eclean);
                    let eMod = false;
                    for (const ef of ['elo','eloChange','e']) {
                        if (ef in eparsed) {
                            const ev = eparsed[ef];
                            const num = typeof ev === 'number' ? ev : parseInt(ev) || 0;
                            eparsed[ef] = typeof ev === 'number' ? num + CONFIG.eloBoost : String(num + CONFIG.eloBoost);
                            eMod = true;
                        }
                    }
                    if (eMod) {
                        log(`[WS ELO UNIV bin] boosted ELO fields by ${CONFIG.eloBoost}`);
                        const wsStr = _cgjEncode(eparsed);
                        log(`[WS CGJ bin] ELO univ injected`);
                        return origSend.call(this, new TextEncoder().encode(wsStr));
                    }
                }
            }
        } catch(e) {}
        return origSend.call(this, data);
    }
    for (const proto of _wsProtoCandidates) {
        const orig = proto.send;
        proto.send = function(data) { return _wsSendHook.call(this, data, orig); };
    }
    log('[WS] WebSocket.send hook active (dual-prototype + score_update)');

    // Diagnose every new WebSocket connection
    try {
        const _origWsCtor = window.WebSocket;
        window.WebSocket = function(url, protocols) {
            log(`[WS NEW] ${url}`);
            const ws = new _origWsCtor(url, protocols);
            const _origSend2 = ws.send.bind(ws);
            ws.send = function(data) { return _wsSendHook.call(ws, data, _origSend2); };
            return ws;
        };
        window.WebSocket.prototype = _origWsCtor.prototype;
        window.WebSocket.CONNECTING = 0; window.WebSocket.OPEN = 1; window.WebSocket.CLOSING = 2; window.WebSocket.CLOSED = 3;
    } catch(e) { log('[WS] ctor hook error: ' + e.message); }

    const FINALIZE_SCORE_FIELDS = [
        'selfScore', 'selfScoreRaw',
        'hostScore', 'actualScore', 'verifiedScore',
        'serverScore', 'realFinalScore', 'clientScore',
        'adjustedScore', 'finalScore',
        'myFinalScore', 'score', 'elo',
        'myScore', 'totalScore', 'matchScore',
        'overall', 'overallScore', 's',
        'currentScore', 'displayScore', 'liveScore',
        'baseScore', 'netScore', 'effectiveScore',
        'your_score', 'yourScore', 'userScore', 'playerScore'
    ];



    const DEEP_SCORE_FIELDS = new Set([
        ...FINALIZE_SCORE_FIELDS.filter(f => f !== 'elo' && f !== 'eloChange'),
        'p', 'q', 'your_score',
        'scoreRaw', 'myScoreRaw', 'selfScoreRaw',
        'p1_score', 'p2_score',
        'finalScoreRaw', 'totalScoreRaw',
        'overallRaw',

        'final_target', 'scoreTarget',
        'totalPoints', 'points', 'pts',
        'correct', 'answers', 'answerRate',
        'accuracy', 'percentage', 'percent',
        'rawScore', 'bonusScore',
        'scoreValue', 'maxScore',
        'earned', 'final_total',
        'finalP1Score', 'finalP2Score',
        'p1Score', 'p2Score',
        'p1', 'p2',
        'winnerScore', 'resultScore',
        'winner', 'result',
        'adjustedScore',
    ]);

    function _deepPatchScores(obj, path, finalTarget, finalFloat) {
        if (!obj || typeof obj !== 'object') return false;
        finalTarget = _clampRaw(finalTarget);
        finalFloat = _clampScore(finalFloat);
        let patched = false;
        for (const [k, v] of Object.entries(obj)) {
            const fp = path ? path + '.' + k : k;
            if (typeof v === 'object' && v !== null) {
                if (_deepPatchScores(v, fp, finalTarget, finalFloat)) patched = true;
            } else if (DEEP_SCORE_FIELDS.has(k)) {
                if (typeof v === 'number') {
                    if (v > 1000 || (v > 0 && v < 50)) {
                        obj[k] = v > 1000 ? finalTarget : finalFloat;
                        patched = true;
                    }
                } else if (typeof v === 'string' && /^\d+(\.\d+)?$/.test(v)) {
                    const n = parseFloat(v);
                    if (n > 1000 || (n > 0 && n < 50)) {
                        obj[k] = n > 1000 ? String(finalTarget) : String(finalFloat);
                        patched = true;
                    }
                }
            }
        }
        return patched;
    }

    function _clampFinalizeScores(obj) {
        if (!obj || typeof obj !== 'object') return;
        for (const [k, v] of Object.entries(obj)) {
            if (typeof v === 'number') {
                if (v > 10.0 && v < 100) {
                    obj[k] = Math.round((Math.random() * 3 + 4) * 10) / 10;
                } else if (v > 100000) {
                    obj[k] = Math.round(Math.random() * 30000 + 50000);
                }
            } else if (typeof v === 'string' && /^\d+(\.\d+)?$/.test(v)) {
                const n = parseFloat(v);
                if (n > 10.0 && n < 100) {
                    obj[k] = String(Math.round((Math.random() * 3 + 4) * 10) / 10);
                }
            } else if (typeof v === 'object' && v !== null) {
                _clampFinalizeScores(v);
            }
        }
    }

    let _fetchTraceId = Date.now();
    const _origFetchRaw = _window.fetch;
    const origFetch = async function(url, options) {
        const res = await _origFetchRaw(url, options);
        const traceId = _fetchTraceId;
        const urlStr = typeof url === 'string' ? url : (url?.url || '');
        try {
            const clone = res.clone();
            const text = await clone.text();
            const preview = text.length > 500 ? text.substring(0, 500) + '...' : text;
            if (text.includes('score') || text.includes('finalize') || text.includes('p1_score') || text.includes('p2_score') || text.includes('elo')) {
                logT('FETCH-RESP', `#${traceId} ${res.status} ${urlStr.substring(0,80)} body=${preview}`);
            }
        } catch(e) {}
        return res;
    };
    _window.fetch = async function(url, options) {
        const urlStr = typeof url === 'string' ? url : (url?.url || '');
        const traceId = _fetchTraceId++;

        // Trace ALL fetch requests
        if (options?.body) {
            const bodyStr = typeof options.body === 'string' ? options.body : _dataToString(options.body);
            if (bodyStr) {
                try {
                    const body = JSON.parse(bodyStr);
                    const keys = Object.keys(body).sort().join(',');
                    const scoreVals = [];
                    for (const sk of ['score','q','myScore','selfScore','finalScore','overall','elo','e','p','s']) {
                        if (body[sk] !== undefined) scoreVals.push(`${sk}=${body[sk]}`);
                    }
                    logT('FETCH-TRACE', `#${traceId} ${urlStr.substring(0,120)} keys=[${keys}] ${scoreVals.join(' ')}`);
                } catch(e) {
                    logT('FETCH-TRACE', `#${traceId} ${urlStr.substring(0,120)} body=${bodyStr.substring(0,200)}`);
                }
            }
        } else {
            logT('FETCH-TRACE', `#${traceId} ${urlStr.substring(0,120)} (no body)`);
        }

        // Catch-all: patch {p,q} score frames in ANY fetch body
        if (options?.body && scoreSpoofAllowed() && !urlStr.includes('/api/match/finalize') && !urlStr.includes('/api/ranked/finalize')) {
            try {
                const body = JSON.parse(typeof options.body === 'string' ? options.body : _dataToString(options.body));
                if (typeof body.p === 'number' && typeof body.q === 'number' && body.q > 0 && !body.type) {
                    if (_myPlayerIndex === null && (body.p === 0 || body.p === 1)) {
                        _myPlayerIndex = body.p;
                        _traceMatch('fetch_pq_myPlayerIndex', { p: body.p });
                    }
                    const target = _getTargetScore();
                    body.q = Math.round(target * 10000) + CONFIG.scoreBoost;
                    _lastSpoofedScore = target;
                    spoofPanel();
                    const fetchBodyStr = _cgjEncode(body);
                    options = { ...options, body: fetchBodyStr };
                    logT('FETCH-TRACE', `#${traceId} patched p,q in fetch body (CGJ=on)`);
                }
            } catch(e) {}
        }

        // Diagnostic: log all fetch requests with JSON bodies
        if (options?.body && typeof options.body === 'string') {
            try {
                const body = JSON.parse(options.body);
                const keys = Object.keys(body).sort().join(',');
                const scoreVals = [];
                if (body.score !== undefined) scoreVals.push('score='+body.score);
                if (body.q !== undefined) scoreVals.push('q='+body.q);
                if (body.myScore !== undefined) scoreVals.push('myScore='+body.myScore);
                if (body.selfScore !== undefined) scoreVals.push('selfScore='+body.selfScore);
                logT('FETCH', `${urlStr.substring(0,100)} keys=[${keys}] ${scoreVals.join(' ')}`);
            } catch(e) {}
        }

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

                    const finalTarget = _getFinalTarget();
                    const finalFloat = finalTarget / 10000;

                    let patched = false;

                    const scoreObj = body.u || body.i;
                    if (scoreObj && scoreObj.e !== undefined) {
                        const realE = parseInt(scoreObj.e) || 0;
                        scoreObj.e = String(finalTarget);
                        if (body.i) _isRanked = true;
                        log(`[LEGACY] score.e: ${realE} → ${scoreObj.e}`);
                        patched = true;
                    }

                    for (const field of FINALIZE_SCORE_FIELDS) {
                        if (field in body && body[field] !== undefined) {
                            if (field === 'opponentScore' || field === 'rivalScore' || field === 'p1_score' || field === 'p2_score') continue;
                            const old = body[field];
                            if (field === 'elo' || field === 'eloChange') {
                                const num = typeof old === 'number' ? old : parseInt(old) || 0;
                                body[field] = typeof old === 'number' ? num + CONFIG.eloBoost : String(num + CONFIG.eloBoost);
                                log(`[ELO+${CONFIG.eloBoost}] ${field}: ${old} → ${body[field]}`);
                            } else if (typeof old === 'number') {
                                body[field] = old > 100 ? finalTarget + CONFIG.scoreBoost : finalFloat + (CONFIG.scoreBoost / 10000);
                                log(`[FLAT] ${field}: ${old} → ${body[field]}`);
                            } else if (typeof old === 'string') {
                                body[field] = String(old > '100' ? finalTarget + CONFIG.scoreBoost : finalFloat + (CONFIG.scoreBoost / 10000));
                                log(`[FLAT STR] ${field}: ${old} → ${body[field]}`);
                            }
                            patched = true;
                        }
                    }

                    if (body.settlement?.scores && Array.isArray(body.settlement.scores)) {
                        const s = body.settlement.scores;
                        const myIdx = _myPlayerIndex !== null ? _myPlayerIndex : (s[0] >= s[1] ? 0 : 1);
                        const old = s[myIdx];
                        s[myIdx] = (old > 100 ? finalTarget : finalFloat) + (old > 100 ? CONFIG.scoreBoost : CONFIG.scoreBoost / 10000);
                        log(`[SETTLEMENT] scores[${myIdx}]: ${old} → ${s[myIdx]}`);
                        patched = true;
                    }
                    if (body.hud?.scores && Array.isArray(body.hud.scores)) {
                        const s = body.hud.scores;
                        const myIdx = _myPlayerIndex !== null ? _myPlayerIndex : (s[0] >= s[1] ? 0 : 1);
                        const old = s[myIdx];
                        s[myIdx] = (old > 100 ? finalTarget : finalFloat) + (old > 100 ? CONFIG.scoreBoost : CONFIG.scoreBoost / 10000);
                        log(`[HUD] scores[${myIdx}]: ${old} → ${s[myIdx]}`);
                        patched = true;
                    }

                    // Patch p1/p2 (no underscore): ensure OUR score beats opponent's
                    if (typeof body.p1 === 'number' && typeof body.p2 === 'number') {
                        const ourKey = _myPlayerIndex === 0 ? 'p1' : (_myPlayerIndex === 1 ? 'p2' : 'p1');
                        const oppKey = ourKey === 'p1' ? 'p2' : 'p1';
                        const oldOurs = body[ourKey];
                        const oldOpp = body[oppKey];
                        const isRaw = oldOurs > 100;
                        const oppF = oldOpp > 100 ? oldOpp / 10000 : oldOpp;
                        const baseF = finalTarget / 10000;
                        const winF = Math.max(baseF, oppF + 0.1);
                        const oppF2 = Math.max(0, winF - 0.5);
                        body[ourKey] = isRaw ? Math.round(winF * 10000) : winF;
                        body[oppKey] = oldOpp > 100 ? Math.round(oppF2 * 10000) : oppF2;
                        log(`[FINALIZE] ${ourKey}: ${oldOurs} → ${body[ourKey]} (${oppKey}: ${oldOpp} → ${body[oppKey]})`);
                        patched = true;
                    }

                    // Patch p1_score/p2_score: ensure OUR score beats opponent's
                    if (typeof body.p1_score === 'number' && typeof body.p2_score === 'number') {
                        const ourKey = _myPlayerIndex === 0 ? 'p1_score' : (_myPlayerIndex === 1 ? 'p2_score' : (body.p1_score >= body.p2_score ? 'p1_score' : 'p2_score'));
                        const oppKey = ourKey === 'p1_score' ? 'p2_score' : 'p1_score';
                        const oldOurs = body[ourKey];
                        const oldOpp = body[oppKey];
                        const isRaw = oldOurs > 100;
                        const oppF = oldOpp > 100 ? oldOpp / 10000 : oldOpp;
                        const baseF = finalTarget / 10000;
                        const winF = Math.max(baseF, oppF + 0.1);
                        const oppF2 = Math.max(0, winF - 0.5);
                        body[ourKey] = isRaw ? Math.round(winF * 10000) : winF;
                        body[oppKey] = oldOpp > 100 ? Math.round(oppF2 * 10000) : oppF2;
                        log(`[FINALIZE] ${ourKey}: ${oldOurs} → ${body[ourKey]} (${oppKey}: ${oldOpp} → ${body[oppKey]})`);
                        patched = true;
                    } else if (typeof body.p1_score === 'number') {
                        const oldV = body.p1_score;
                        body.p1_score = (oldV > 100 ? finalTarget : finalFloat) + (oldV > 100 ? CONFIG.scoreBoost : CONFIG.scoreBoost / 10000);
                        log(`[FINALIZE] p1_score: ${oldV} → ${body.p1_score}`);
                        patched = true;
                    } else if (typeof body.p2_score === 'number') {
                        const oldV = body.p2_score;
                        body.p2_score = (oldV > 100 ? finalTarget : finalFloat) + (oldV > 100 ? CONFIG.scoreBoost : CONFIG.scoreBoost / 10000);
                        log(`[FINALIZE] p2_score: ${oldV} → ${body.p2_score}`);
                        patched = true;
                    }

                    // Override winner/result in request so server sees us winning
                    if (body.winner !== undefined || body.result !== undefined) {
                        const origWinner = body.winner;
                        const origResult = body.result;
                        body.winner = 'self';
                        body.result = 'win';
                        log(`[FINALIZE] winner: ${origWinner} → self, result: ${origResult} → win`);
                        patched = true;
                    }

                    if (!patched) {
                        log('[FINALIZE] No known score fields found — deep scanning');
                        _deepPatchScores(body, '', finalTarget + CONFIG.scoreBoost, finalFloat + (CONFIG.scoreBoost / 10000));
                    }

                    const finalBodyStr = _cgjEncode(body);
                    options = { ...options, body: finalBodyStr };
                    _traceMatch('finalize_request', { body: finalBodyStr.substring(0, 300) });
                    log('FINALIZE REQUEST (modified, CGJ):', finalBodyStr.substring(0, 500));
                } catch(e) {
                    log('Could not parse finalize body:', e);
                }
            }

            // ELO boost: always apply to finalize requests even if resultEnabled is off
            if (CONFIG.eloBoost > 0 && options?.body) {
                try {
                    const ebody = JSON.parse(options.body);
                    let ePatched = false;
                    for (const ef of ['elo', 'eloChange', 'e']) {
                        if (ef in ebody) {
                            const ev = ebody[ef];
                            const num = typeof ev === 'number' ? ev : parseInt(ev) || 0;
                            ebody[ef] = typeof ev === 'number' ? num + CONFIG.eloBoost : String(num + CONFIG.eloBoost);
                            log(`[ELO INDEP] ${ef}: ${ev} → ${ebody[ef]}`);
                            ePatched = true;
                        }
                    }
                    if (ebody.u?.e !== undefined) {
                        const neu = parseInt(ebody.u.e) || 0;
                        ebody.u.e = String(neu + CONFIG.eloBoost);
                        log(`[ELO INDEP] u.e: ${neu} → ${ebody.u.e}`);
                        ePatched = true;
                    }
                    if (ebody.i?.e !== undefined) {
                        const nei = parseInt(ebody.i.e) || 0;
                        ebody.i.e = String(nei + CONFIG.eloBoost);
                        log(`[ELO INDEP] i.e: ${nei} → ${ebody.i.e}`);
                        ePatched = true;
                    }
                    if (ePatched) {
                        const eStr = _cgjEncode(ebody);
                        options = { ...options, body: eStr };
                    }
                } catch(e) {}
            }

            const response = await origFetch.call(this, url, options);
            const clone = response.clone();
            try {
                const data = await clone.json();
                log('FINALIZE RESPONSE (original):', JSON.stringify(data).substring(0, 500));
                if (response.ok) {
                    const finalTarget = _getFinalTarget();
                    const finalFloat = finalTarget / 10000;
                    let modData = data;
                    if (typeof data === 'object' && data !== null) {
                        modData = JSON.parse(JSON.stringify(data));
                        // Handle p1/p2 independently using _myPlayerIndex to avoid inflating opponent
                        if (typeof modData.p1 === 'number' && typeof modData.p2 === 'number') {
                            if (_myPlayerIndex === 0 || _myPlayerIndex === null) {
                                modData.p1 = finalFloat + (CONFIG.scoreBoost / 10000);
                                modData.p2 = modData.p2 > 100 ? finalTarget : modData.p2;
                            } else {
                                modData.p2 = finalFloat + (CONFIG.scoreBoost / 10000);
                                modData.p1 = modData.p1 > 100 ? finalTarget : modData.p1;
                            }
                        }
                        if (typeof modData.p1_score === 'number' && typeof modData.p2_score === 'number') {
                            if (_myPlayerIndex === 0 || _myPlayerIndex === null) {
                                modData.p1_score = finalFloat + (CONFIG.scoreBoost / 10000);
                            } else {
                                modData.p2_score = finalFloat + (CONFIG.scoreBoost / 10000);
                            }
                        }
                        for (const field of FINALIZE_SCORE_FIELDS) {
                            if (field in modData && modData[field] !== undefined) {
                                if (field === 'opponentScore' || field === 'rivalScore' || field === 'p1_score' || field === 'p2_score' || field === 'p1' || field === 'p2') continue;
                                const old = modData[field];
                                if (field === 'elo' || field === 'eloChange') {
                                    const num = typeof old === 'number' ? old : parseInt(old) || 0;
                                    // Always report positive ELO gain
                                    const absNum = Math.abs(num);
                                    const boosted = absNum + CONFIG.eloBoost;
                                    modData[field] = typeof old === 'number' ? boosted : String(boosted);
                                    log(`[ELO FORCED] ${field}: ${num} → ${boosted} (forced positive)`);
                                } else if (typeof old === 'number') {
                                    modData[field] = old > 100 ? finalTarget + CONFIG.scoreBoost : finalFloat + (CONFIG.scoreBoost / 10000);
                                } else if (typeof old === 'string') {
                                    modData[field] = String(old > '100' ? finalTarget + CONFIG.scoreBoost : finalFloat + (CONFIG.scoreBoost / 10000));
                                }
                            }
                        }
                        // Force winner/result fields to show us winning
                        if (typeof modData.winner === 'string') { modData.winner = 'self'; }
                        if (typeof modData.result === 'string') { modData.result = 'win'; }
                        _traceMatch('finalize_response', { status: response.status, body: JSON.stringify(modData).substring(0, 300) });
                        log('FINALIZE RESPONSE (modified):', JSON.stringify(modData).substring(0, 500));
                    }
                    _lockedFinalTarget = null;
                    _finalApplied = false;
                    _matchStartTime = null;
                    _finalScoreAppliedThisMatch = false;
                    _myPlayerIndex = null;
                    _cacheValid = false;
                    _cachedScoreSpan = null;
                    const newHeaders = new Headers(response.headers);
                    newHeaders.delete('content-length');
                    return new Response(JSON.stringify(modData), {
                        status: response.status,
                        statusText: response.statusText,
                        headers: newHeaders
                    });
                }
            } catch(e) {
                log('FINALIZE RESPONSE parse error:', e);
            }
            return response;
        }

        const BOOSTED_STATS = { is_pro: true };

        if (urlStr.includes('supabase.co/rest/v1/profiles')) {
            const response = await origFetch.call(this, url, options);
            const clone = response.clone();
            try {
                const data = await clone.json();
                if (Array.isArray(data) && data.length > 0) {
                    const modified = data.map(profile => ({ ...profile, ...BOOSTED_STATS }));
                    const newHeaders = new Headers(response.headers);
                    newHeaders.set('content-type', 'application/json');
                    return new Response(JSON.stringify(modified), {
                        status: response.status,
                        statusText: response.statusText,
                        headers: newHeaders
                    });
                }
            } catch(e) {}
            return response;
        }

        if (urlStr.includes('/api/profiles/public/')) {
            const response = await origFetch.call(this, url, options);
            const clone = response.clone();
            try {
                const data = await clone.json();
                if (data && data.profile) {
                    const modified = {
                        ...data,
                        profile: { ...data.profile, is_pro: true }
                    };
                    return new Response(JSON.stringify(modified), {
                        status: response.status,
                        statusText: response.statusText,
                        headers: response.headers
                    });
                }
            } catch(e) {}
            return response;
        }

        if (urlStr.includes('/api/profile/ranked-stats')) {
            const response = await origFetch.call(this, url, options);
            return response;
        }

        if (urlStr.includes('/api/profile/world-rank')) {
            const response = await origFetch.call(this, url, options);
            return response;
        }

        if (urlStr.includes('/api/profile/lobby-summary')) {
            const response = await origFetch.call(this, url, options);
            const clone = response.clone();
            try {
                const data = await clone.json();
                if (data && typeof data === 'object') {
                    const modified = { ...data, is_pro: true };
                    return new Response(JSON.stringify(modified), {
                        status: response.status,
                        statusText: response.statusText,
                        headers: response.headers
                    });
                }
            } catch(e) {}
            return response;
        }

        if (urlStr === '/api/profile' || urlStr.endsWith('/api/profile')) {
            const response = await origFetch.call(this, url, options);
            const clone = response.clone();
            try {
                const data = await clone.json();
                if (data && data.profile) {
                    _currentUsername = data.profile.displayName || data.profile.username || data.profile.nickname || _currentUsername;
                    const modified = {
                        ...data,
                        profile: { ...data.profile, is_pro: true }
                    };
                    return new Response(JSON.stringify(modified), {
                        status: response.status,
                        statusText: response.statusText,
                        headers: response.headers
                    });
                }
            } catch(e) {}
            return response;
        }

        // ── Catch-all: patch ANY JSON response containing score fields ──
        if (scoreSpoofAllowed()) {
            const response = await origFetch.call(this, url, options);
            const contentType = response.headers?.get('content-type') || '';
            if (contentType.includes('json') || urlStr.includes('/api/')) {
                const clone = response.clone();
                try {
                    let data = await clone.json();
                    let patched = false;
                    if (data && typeof data === 'object') {
                        data = JSON.parse(JSON.stringify(data));
                        const t = _getTargetScore();
                        patched = _deepPatchScores(data, '', t * 10000 + CONFIG.scoreBoost, t + CONFIG.scoreBoost / 10000);
                    }
                    if (patched) {
                        const newHeaders = new Headers(response.headers);
                        newHeaders.delete('content-length');
                        log(`[FETCH CATCH-ALL] patched response: ${urlStr.substring(0,100)}`);
                        return new Response(JSON.stringify(data), {
                            status: response.status,
                            statusText: response.statusText,
                            headers: newHeaders
                        });
                    }
                } catch(e) {}
            }
            return response;
        }

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

    let _lockedFinalTarget = null;
    let _lastFinalMode = null;
    let _lastFinalMin = null, _lastFinalMax = null;
    let _finalApplied = false;

    function _sanitizeScore(val) {
        if (typeof val !== 'number' || !isFinite(val) || val < 0) return null;
        if (val > 500000) return null;
        return val;
    }

    function _getFinalTarget() {
        if (CONFIG.finalScoreMode === 'fixed') {
            const v = parseInt(CONFIG.myFinalScore);
            if (isFinite(v) && v > 0 && v < 500000) return v;
            return parseInt(DEFAULT_CONFIG.myFinalScore) || 99999;
        }
        // range mode
        const min = _sanitizeScore(CONFIG.finalScoreRangeMin) ?? DEFAULT_CONFIG.finalScoreRangeMin;
        const max = _sanitizeScore(CONFIG.finalScoreRangeMax) ?? DEFAULT_CONFIG.finalScoreRangeMax;
        if (_lockedFinalTarget === null || _lastFinalMode !== CONFIG.finalScoreMode || _lastFinalMin !== min || _lastFinalMax !== max) {
            _finalApplied = false;
            _lastFinalMode = CONFIG.finalScoreMode;
            _lastFinalMin = min;
            _lastFinalMax = max;
            _lockedFinalTarget = Math.round(min + Math.random() * (max - min));
            log(`_getFinalTarget locked: ${_lockedFinalTarget} (range ${min}-${max})`);
        }
        return _clampRaw(_lockedFinalTarget);
    }

    const _STORE_NAMES = ['T', 'default', 'store', 'Zustand', 'useStore', 'Store', '_zustand', 'useGameStore', 'gameStore', 'matchStore', 'appStore'];

    function _isZustandStore(val) {
        if (!val || typeof val.getState !== 'function') return false;
        try {
            const s = val.getState();
            if (!s || typeof s !== 'object') return false;
            if (typeof s.setMyScore === 'function' ||
                   typeof s.setLiveScores === 'function' ||
                   typeof s.setFinalPayloads === 'function' ||
                   typeof s.setActiveMatchId === 'function' ||
                   typeof s.applyFinalScores === 'function' ||
                   typeof s.setIsTournamentMatch === 'function' ||
                   typeof s.setRankedResult === 'function' ||
                   typeof s.setFrameNonce === 'function' ||
                   typeof s.forceFinishIfCalculating === 'function' ||
                   typeof s.myScore !== 'undefined' ||
                   typeof s.myScoreRaw !== 'undefined') return true;

            let hasNumber = false;
            let hasFunc = false;
            for (const v of Object.values(s)) {
                if (typeof v === 'number' && v >= 0 && v <= 12) hasNumber = true;
                if (typeof v === 'function') hasFunc = true;
            }
            return hasNumber && hasFunc && Object.keys(s).length > 5;
        } catch(e) { return false; }
    }

    function _isZustandStoreLoose(val) {
        if (!val || typeof val.getState !== 'function') return false;
        try {
            const s = val.getState();
            if (!s || typeof s !== 'object') return false;
            const keys = Object.keys(s);
            return keys.length > 5 && typeof s.set === 'function';
        } catch(e) { return false; }
    }

    function _findStoreInMod(mod) {
        if (!mod || typeof mod !== 'object') return null;
        if (_isZustandStore(mod)) return mod;
        for (const name of _STORE_NAMES) {
            try {
                const val = mod[name];
                if (_isZustandStore(val)) return val;
            } catch(e) {}
        }
        for (const val of Object.values(mod)) {
            if (_isZustandStore(val)) return val;
        }
        return null;
    }

    function _findStoreDeep(obj, depth, visited) {
        if (depth > 4 || !obj || typeof obj !== 'object' || visited.has(obj)) return null;
        visited.add(obj);
        try {
            if (_isZustandStore(obj)) return obj;
            if (typeof obj.getState === 'function' && typeof obj.setState === 'function') {
                const s = obj.getState();
                if (s && typeof s === 'object' && Object.keys(s).length > 10) return obj;
            }
        } catch(e) {}
        try {
            for (const val of Object.values(obj)) {
                const found = _findStoreDeep(val, depth + 1, visited);
                if (found) return found;
            }
        } catch(e) {}
        return null;
    }

    let _storeRef = null;
    let _patchPollCount = 0;

    function _tryGetWebpackRequire() {
        const chunkNames = [
            'webpackChunk_N_E', 'webpackChunknextjs_app', 'webpackChunk',
            'webpackJsonp', 'webpackChunks'
        ];
        for (const name of chunkNames) {
            try {
                const chunk = _window[name];
                if (!chunk || !Array.isArray(chunk)) continue;
                const req = chunk.push([[Symbol()], {}, e => e]);
                if (typeof req === 'function') {
                    log(`[STORE] webpack require obtained from "${name}"`);
                    return req;
                }
            } catch(e) {}
        }
        return null;
    }

    function _tryScanWebpack(req) {
        if (!req) return null;
        let store = null;

        if (req.m) {
            const moduleIds = Object.keys(req.m);
            log(`[STORE] scanning ${moduleIds.length} webpack modules...`);
            for (const id of moduleIds) {
                try {
                    const mod = req(id);
                    const found = _findStoreInMod(mod);
                    if (found) {
                        log(`[STORE] found via webpack module scan id=${id}`);
                        return found;
                    }
                } catch(e) {}
            }
        }

        return null;
    }

    // ── LiveKit Room detection via webpack module scan ──
    let _lkRoomClass = null;

    function _isRoomClassProto(proto) {
        if (!proto || typeof proto !== 'object') return false;
        const descs = Object.getOwnPropertyDescriptors(proto);
        let hasConnect = false, hasDisconnect = false, hasState = false, hasLocalPart = false;
        for (const [k, d] of Object.entries(descs)) {
            if (k === 'connect' && typeof d.value === 'function') hasConnect = true;
            if (k === 'disconnect' && typeof d.value === 'function') hasDisconnect = true;
            if (k === 'state' && (d.get || typeof d.value === 'string')) hasState = true;
            if (k === 'localParticipant' && d.get) hasLocalPart = true;
        }
        return hasConnect && hasDisconnect && hasState && hasLocalPart;
    }

    function _findRoomInMod(mod) {
        if (!mod || typeof mod !== 'object') return null;
        for (const val of Object.values(mod)) {
            if (typeof val === 'function' && val.prototype && _isRoomClassProto(val.prototype)) {
                return val;
            }
        }
        return null;
    }

    function _tryScanWebpackForRoom(req) {
        if (!req || !req.m) return false;
        const ids = Object.keys(req.m);
        for (const id of ids) {
            try {
                const mod = req(id);
                const cls = _findRoomInMod(mod);
                if (cls) {
                    _lkRoomClass = cls;
                    log(`[LK] Room class found via webpack module ${id}`);
                    return true;
                }
            } catch(e) {}
        }
        return false;
    }

    // ── Webpack scoring module detection & patching (VA/cv/cM) ──
    let _scoringPatched = false;
    function _isScoringModule(mod) {
        return !!mod && typeof mod.VA === 'function' && typeof mod.cv === 'function' && typeof mod.cM === 'function';
    }
    function _patchScoringModule(mod) {
        if (mod.__cmScoringPatched) return;
        mod.__cmScoringPatched = true;
        const origVA = mod.VA;
        mod.VA = function() {
            const result = origVA.apply(this, arguments);
            const score = _getTargetScore();
            if (score === null || !result || !scoreSpoofAllowed()) return result;
            try {
                result.overall = score;
                if (Array.isArray(result.traits)) {
                    result.traits = result.traits.map(function(t) { return Object.assign({}, t, { score: score }); });
                }
                if (result.rawMetrics) result.rawMetrics.overall = score;
                if (result.quality) {
                    result.quality.reliability = 1.0;
                    result.quality.confidence = 1.0;
                    result.quality.accepted = true;
                }
            } catch(e) {}
            return result;
        };
        const origCV = mod.cv;
        mod.cv = function() {
            const result = origCV.apply(this, arguments);
            const score = _getTargetScore();
            if (score === null || !result || !scoreSpoofAllowed()) return result;
            try { result.overall = score; if (result.rawMetrics) result.rawMetrics.overall = score; } catch(e) {}
            return result;
        };
        const origCM = mod.cM;
        mod.cM = function() {
            const result = origCM.apply(this, arguments);
            if (!scoreSpoofAllowed() || !result) return result;
            try { result.reliability = 1.0; result.confidence = 1.0; result.accepted = true; } catch(e) {}
            return result;
        };
        _scoringPatched = true;
        log('[SCORE] Webpack scoring module patched (VA/cv/cM)');
    }
    function _tryScanWebpackForScoring(req) {
        if (!req || !req.m) return false;
        for (const id of Object.keys(req.m)) {
            try {
                const mod = req(id);
                if (_isScoringModule(mod)) {
                    _patchScoringModule(mod);
                    log(`[SCORE] Scoring module found via webpack module ${id}`);
                    return true;
                }
            } catch(e) {}
        }
        return false;
    }

    // ── Find Room in store state (some apps store room ref in zustand) ──
    function _findRoomInState(state, depth) {
        if (!state || typeof state !== 'object' || depth > 6) return null;
        try {
            if (typeof state.connect === 'function' && state.localParticipant) {
                return state;
            }
        } catch(e) {}
        for (const v of Object.values(state)) {
            if (v && typeof v === 'object' && !Array.isArray(v)) {
                const found = _findRoomInState(v, depth + 1);
                if (found) return found;
            }
        }
        return null;
    }

    function _tryScanGlobalObjects() {
        const globals = [
            '__NEXT_DATA__', 'next', '__NEXT_STATE__',
            '__remixContext', '__remixRouteModules',
            'appState', 'gameState', 'matchState', 'T'
        ];
        for (const name of globals) {
            try {
                const obj = _window[name];
                if (!obj) continue;
                const visited = new WeakSet();
                const found = _findStoreDeep(obj, 0, visited);
                if (found) {
                    log(`[STORE] found via global "${name}"`);
                    return found;
                }
            } catch(e) {}
        }
        // Broad scan: check all enumerable window properties for zustand stores
        try {
            const visited = new WeakSet();
            for (const key of Object.keys(_window)) {
                if (key.startsWith('_') || key === 'chrome' || typeof _window[key] !== 'object' || !_window[key]) continue;
                try {
                    if (_isZustandStore(_window[key])) {
                        log(`[STORE] found via broad window scan at key "${key}"`);
                        return _window[key];
                    }
                } catch(e) {}
            }
        } catch(e) {}
        return null;
    }

    function _tryScanReactRoots() {
        try {
            const rootEl = document.getElementById('__next') || document.getElementById('root') || document.getElementById('app');
            if (!rootEl) return null;
            const fiberKey = Object.keys(rootEl).find(k => k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$'));
            if (!fiberKey) return null;
            let fiber = rootEl[fiberKey];
            const visited = new Set();
            let depth = 0;
            while (fiber && depth < 200) {
                if (visited.has(fiber)) { fiber = fiber.child || fiber.sibling; depth++; continue; }
                visited.add(fiber);
                try {
                    if (fiber.memoizedState && fiber.memoizedState.memoizedState) {
                        let hook = fiber.memoizedState;
                        let safety = 0;
                        while (hook && safety < 20) {
                            const q = hook.queue;
                            if (q && q.lastRenderedState && typeof q.lastRenderedState === 'object') {
                                const st = q.lastRenderedState;
                                if (typeof st.setMyScore === 'function' || typeof st.applyFinalScores === 'function') {
                                    log(`[STORE] found via React fiber at depth ${depth}`);
                                    return {
                                        getState: () => st,
                                        setState: (partial) => {
                                            const next = typeof partial === 'function' ? partial(st) : partial;
                                            Object.assign(st, next);
                                        }
                                    };
                                }
                            }
                            hook = hook.next;
                            safety++;
                        }
                    }
                } catch(e) {}
                fiber = fiber.child || fiber.sibling || (fiber.return && fiber.return.sibling);
                depth++;
            }
        } catch(e) {}
        return null;
    }

    function patchZustandStore() {
        // Direct check: is the store at _window.T?
        if (!_storeRef) {
            try {
                if (typeof _window.T !== 'undefined' && _window.T && typeof _window.T.getState === 'function') {
                    if (_isZustandStore(_window.T)) {
                        _storeRef = _window.T;
                        log('[STORE] found at _window.T (direct check)');
                    }
                }
            } catch(e) {}
        }
        if (_storeRef) {
            try {
                const s = _storeRef.getState();
                if (s && typeof s === 'object' && typeof s.setMyScore === 'function') {
                    if (!_storeRef.__cmStorePatched) patchStore(_storeRef);
                    // Try to find Room via store state and webpack
                    const room = _findRoomInState(s, 0);
                    if (room) {
                        log('[LK] Room found in store state, hooking');
                        setTimeout(() => _hookLiveKitRoom(room), 0);
                    }
                    if (!_lkProtoHooked) {
                        setTimeout(() => _hookRoomClassPrototype(), 100);
                    }
                    return true;
                }
            } catch(e) { _storeRef = null; }
        }

        try {
            const req = _tryGetWebpackRequire();
            if (req) {
                const store = _tryScanWebpack(req);
                if (store) { _storeRef = store; return patchStore(store); }
            }
        } catch(e) { log('[STORE] webpack scan failed:', e); }

        try {
            const store = _tryScanGlobalObjects();
            if (store) { _storeRef = store; return patchStore(store); }
        } catch(e) { log('[STORE] global scan failed:', e); }

        try {
            const store = _tryScanReactRoots();
            if (store) { _storeRef = store; return patchStore(store); }
        } catch(e) { log('[STORE] React fiber scan failed:', e); }

        _patchPollCount++;
        if (_patchPollCount % 25 === 0) {
            log(`[STORE] still searching... attempt ${_patchPollCount}`);
            _attachStoreWatcher();
        }

        return false;
    }

    let _storeWatcherAttached = false;
    function _attachStoreWatcher() {
        if (_storeWatcherAttached) return;
        _storeWatcherAttached = true;

        try {
            const origSetItem = Storage.prototype.setItem;
            Storage.prototype.setItem = function(key, value) {
                origSetItem.call(this, key, value);
                if (key === CONFIG_KEY) return;
                try {
                    if (!_storeRef) {
                        setTimeout(() => { try { patchZustandStore(); } catch(e) {} }, 50);
                    }
                } catch(e) {}
            };
        } catch(e) {}

        try {
            const origFetch2 = _window.fetch;
            _window.fetch = async function(...args) {
                const resp = await origFetch2.apply(this, args);
                if (!_storeRef) {
                    setTimeout(() => { try { patchZustandStore(); } catch(e) {} }, 100);
                }
                return resp;
            };
        } catch(e) {}

        try {
            const origXHR = XMLHttpRequest.prototype.open;
            XMLHttpRequest.prototype.open = function(...args) {
                const result = origXHR.apply(this, args);
                if (!_storeRef) {
                    setTimeout(() => { try { patchZustandStore(); } catch(e) {} }, 100);
                }
                return result;
            };
        } catch(e) {}

        try {
            if (typeof MutationObserver !== 'undefined') {
                const obs = new MutationObserver(() => {
                    if (!_storeRef) {
                        try { patchZustandStore(); } catch(e) {}
                    }
                });
                obs.observe(document.body || document.documentElement, { childList: true, subtree: true });
                setTimeout(() => obs.disconnect(), 30000);
            }
        } catch(e) {}

        log('[STORE] store watcher attached — will retry on any activity');
    }

    let patchAttempts = 0;
    const patchPoll = setInterval(() => {
        patchAttempts++;
        if (patchZustandStore()) {
            clearInterval(patchPoll);
            log(`[STORE] patched after ${patchAttempts} attempts`);
        } else if (patchAttempts % 25 === 0) {
            log(`[STORE] still looking... attempt ${patchAttempts}`);
        }
    }, 300);

    // Brute-force store state patcher: periodically directly modifies the store state values
    // This works even if the setter hooks don't fire (e.g., if the game bypasses the store)
    setInterval(() => {
        try {
            if (!CONFIG || !scoreSpoofAllowed()) return;
            const store = _storeRef || _window.T;
            if (!store || typeof store.getState !== 'function') return;
            const state = store.getState();
            if (!state || typeof state !== 'object') return;
            const target = _getTargetScore();
            const raw = Math.round(target * 10000) + (CONFIG.scoreBoost || 0);
            const newFloat = target + (CONFIG.scoreBoost / 10000);
            const patch = {};
            let changed = false;
            // Top-level score fields
            if (typeof state.myScore === 'number' && state.myScore !== target) { patch.myScore = target; changed = true; }
            if (typeof state.myScoreRaw === 'number' && state.myScoreRaw !== raw) { patch.myScoreRaw = raw; changed = true; }
            if (typeof state.score === 'number' && state.score !== target) { patch.score = target; changed = true; }
            if (typeof state.overall === 'number' && state.overall !== target) { patch.overall = target; changed = true; }
            if (typeof state.selfScore === 'number' && state.selfScore !== target) { patch.selfScore = target; changed = true; }
            if (typeof state.selfScoreRaw === 'number' && state.selfScoreRaw !== raw) { patch.selfScoreRaw = raw; changed = true; }
            if (typeof state.your_score === 'number' && state.your_score !== target) { patch.your_score = target; changed = true; }
            if (typeof state.yourScore === 'number' && state.yourScore !== target) { patch.yourScore = target; changed = true; }
            if (typeof state.finalScore === 'number' && state.finalScore !== target) { patch.finalScore = target; changed = true; }
            // Quality metric keys (in [0,1] range, must inflate to 1.0 not target score)
            const _cmQualityKeys = new Set(['looking', 'attention', 'smile', 'smiling', 'mouthOpen', 'quality', 'confidence', 'readiness', 'engagement', 'focus', 'eyeContact', 'faceQuality', 'trackingQuality', 'detectionQuality']);
            // Inflate top-level quality metrics to 1.0 (not target score)
            for (const qk of _cmQualityKeys) {
                if (typeof state[qk] === 'number' && state[qk] >= 0 && state[qk] <= 1 && state[qk] !== 1) {
                    patch[qk] = 1.0; changed = true;
                }
            }
            function _patchNested(obj) {
                if (!obj || typeof obj !== 'object') return false;
                let mod = false;
                for (const [k, v] of Object.entries(obj)) {
                    if (_isOpponentKey(k)) continue;
                    if (typeof v === 'number') {
                        if (_cmQualityKeys.has(k) && v >= 0 && v <= 1 && v !== 1) {
                            obj[k] = 1.0; mod = true;
                        } else if (v > 1.0 && v <= 11.0 && !Number.isInteger(v) && v !== target) {
                            obj[k] = newFloat; mod = true;
                        } else if (v > 1000 && v < 99999999 && Number.isInteger(v) && v !== raw) {
                            obj[k] = raw; mod = true;
                        }
                    } else if (typeof v === 'object' && v !== null) {
                        if (_patchNested(v)) mod = true;
                    }
                }
                return mod;
            }
            // Patch nested objects: result, rankedResult, payload, data, etc.
            for (const nestedKey of ['result', 'rankedResult', 'payload', 'data', 'finalPayloads', 'matchResult', 'bountyResult']) {
                if (state[nestedKey] && typeof state[nestedKey] === 'object') {
                    if (_patchNested(state[nestedKey])) {
                        patch[nestedKey] = { ...state[nestedKey] };
                        changed = true;
                    }
                }
            }
            if (changed && typeof store.setState === 'function') {
                store.setState(patch);
                _lastSpoofedScore = target;
                spoofPanel();
                log('[BRUTE] store state patched: ' + Object.keys(patch).join(','));
            }
        } catch(e) {}
    }, 200);

    let _lastCapMin = null, _lastCapMax = null;
    let _matchId = null;
    let _matchPhaseTrace = [];
    function _traceMatch(phase, data) {
        if (!_matchId) _matchId = Date.now().toString(36) + Math.random().toString(36).substring(2, 6);
        const entry = { t: Date.now(), phase, data };
        _matchPhaseTrace.push(entry);
        if (_matchPhaseTrace.length > 100) _matchPhaseTrace.shift();
        const dataStr = typeof data === 'object' ? JSON.stringify(data).substring(0, 200) : String(data).substring(0, 200);
        log(`[TRACE:${_matchId}] ${phase}: ${dataStr}`);
    }
    const SCORE_RAW_MAX = 500000;

    const SCORE_FLOAT_MAX = 50.0;
    function _clampScore(val) {
        if (typeof val !== 'number') return val;
        if (val > SCORE_FLOAT_MAX) return SCORE_FLOAT_MAX;
        if (val < 0) return 0;
        return val;
    }

    function _clampRaw(val) {
        if (typeof val !== 'number') return val;
        if (val > SCORE_RAW_MAX) return SCORE_RAW_MAX;
        if (val < 0) return 0;
        return val;
    }

    var _rangeTarget = null, _rangeLastUpdate = 0;
    function _getTargetScore() {
        if (CONFIG.scoreMode === 'range') {
            var min = _sanitizeScore(CONFIG.scoreRangeMin) ?? 100000;
            var max = _sanitizeScore(CONFIG.scoreRangeMax) ?? 100000;
            if (min >= max) return parseFloat(SCORE_MAX.toFixed(1));
            var now = Date.now();
            if (_rangeTarget === null || now - _rangeLastUpdate > 1100) {
                var raw = min + Math.random() * (max - min);
                _rangeTarget = parseFloat(Math.max(SCORE_MIN, Math.min(SCORE_MAX, raw / 10000)).toFixed(1));
                _rangeLastUpdate = now;
            }
            return _rangeTarget;
        }
        var fixed = _sanitizeScore(CONFIG.fixedScore) ?? 100000;
        var base = fixed / 10000;
        return parseFloat(Math.max(SCORE_MIN, Math.min(SCORE_MAX, base)).toFixed(1));
    }

    function patchStore(store) {
        try {
            if (store.__cmStorePatched) return true;
            const state = store.getState();

            // ── Helper: get the spoofed score in the format the caller expects ──
            // _scoreFloat = score control (live frames), _resultFloat = result (finalize only)
            function _scoreFloat() { return _getTargetScore(); }
            function _scoreRaw() { return Math.round(_getTargetScore() * 10000); }
            function _resultFloat() { return CONFIG.resultEnabled ? _getFinalTarget() / 10000 : _getTargetScore(); }
            function _resultRaw() { return CONFIG.resultEnabled ? _getFinalTarget() : Math.round(_getTargetScore() * 10000); }

            // ── Hook: setMyScore(score) — uses SCORE CONTROL ──
            if (typeof state.setMyScore === 'function') {
                const orig = state.setMyScore.bind(store);
                store.setState({ setMyScore: function(score) {
                    if (!CONFIG.scoreEnabled) return orig(score);
                    const target = _scoreFloat();
                    _traceMatch('setMyScore', { original: score, target });
                    log(`[STORE] setMyScore: ${score} → ${target}`);
                    _lastSpoofedScore = target;
                    spoofPanel();
                    return orig(target);
                }});
                log('Hooked: setMyScore');
            }

            // ── Hook: setOpponentScore(score) — log only, don't modify ──
            if (typeof state.setOpponentScore === 'function') {
                const orig = state.setOpponentScore.bind(store);
                store.setState({ setOpponentScore: function(score) {
                    if (!CONFIG.scoreEnabled) return orig(score);
                    log(`[STORE] setOpponentScore: ${score} (unchanged on our side)`);
                    return orig(score);
                }});
                log('Hooked: setOpponentScore (log only)');
            }

            // ── Hook: setLiveScores(scores) — live match score updates ──
            if (typeof state.setLiveScores === 'function') {
                const orig = state.setLiveScores.bind(store);
                store.setState({ setLiveScores: function(scores) {
                    if (!CONFIG.scoreEnabled) return orig(scores);
                    if (scores && typeof scores === 'object') {
                        const mod = { ...scores };
                        const target = _scoreFloat();
                        let changed = false;
                        if (typeof mod.myScore === 'number') {
                            const old = mod.myScore;
                            mod.myScore = target;
                            if (typeof mod.opponentScore === 'number' && mod.opponentScore > 0) {
                                _lastOpponentScore = mod.opponentScore;
                                if (_myPlayerIndex === null) {
                                    _myPlayerIndex = old > mod.opponentScore ? 0 : (mod.opponentScore > old ? 1 : _myPlayerIndex);
                                    _traceMatch('setLiveScores_myPlayerIndex', { myScore: old, opponentScore: mod.opponentScore, _myPlayerIndex });
                                }
                            }
                            _traceMatch('setLiveScores', { oldMyScore: old, newMyScore: target, opponentScore: mod.opponentScore, _myPlayerIndex });
                            log(`[STORE] setLiveScores.myScore: ${old} → ${target}`);
                            changed = true;
                        }
                        if (typeof mod.myScoreRaw === 'number') {
                            const old = mod.myScoreRaw;
                            mod.myScoreRaw = _scoreRaw();
                            log(`[STORE] setLiveScores.myScoreRaw: ${old} → ${mod.myScoreRaw}`);
                            changed = true;
                        }
                        if (changed) {
                            _lastSpoofedScore = target;
                            spoofPanel();
                            return orig(mod);
                        }
                    }
                    return orig(scores);
                }});
                log('Hooked: setLiveScores');
            }

            // ── Hook: startBattleFromAnchor(anchor) — match start ──
            if (typeof state.startBattleFromAnchor === 'function') {
                const orig = state.startBattleFromAnchor.bind(store);
                store.setState({ startBattleFromAnchor: function(anchor) {
                    if (!CONFIG.scoreEnabled) return orig(anchor);
                    _myPlayerIndex = null;
                    _traceMatch('startBattleFromAnchor', { anchor: typeof anchor === 'object' ? JSON.stringify(anchor).substring(0,200) : anchor });
                    log(`[STORE] startBattleFromAnchor`);
                    return orig(anchor);
                }});
                log('Hooked: startBattleFromAnchor');
            }

            // ── Hook: applyPhaseFromServer(phase) — server phase with potential score data ──
            if (typeof state.applyPhaseFromServer === 'function') {
                const orig = state.applyPhaseFromServer.bind(store);
                store.setState({ applyPhaseFromServer: function(phase) {
                    if (!CONFIG.scoreEnabled) return orig(phase);
                    if (phase && typeof phase === 'object') {
                        const mod = { ...phase };
                        const target = _scoreFloat();
                        const raw = _scoreRaw();
                        let patched = false;
                        if (typeof mod.myScore === 'number') { mod.myScore = target; patched = true; }
                        if (typeof mod.myScoreRaw === 'number') { mod.myScoreRaw = raw; patched = true; }
                        if (typeof mod.score === 'number') { mod.score = target; patched = true; }
                        if (_myPlayerIndex === null && typeof mod.myScore === 'number' && typeof mod.opponentScore === 'number' && mod.opponentScore > 0) {
                            _myPlayerIndex = mod.myScore > mod.opponentScore ? 0 : (mod.opponentScore > mod.myScore ? 1 : _myPlayerIndex);
                            _traceMatch('applyPhase_myPlayerIndex', { myScore: mod.myScore, opponentScore: mod.opponentScore, _myPlayerIndex });
                        }
                        _traceMatch('applyPhaseFromServer', { phase_keys: Object.keys(mod).join(','), patched, _myPlayerIndex });
                        if (patched) {
                            log(`[STORE] applyPhaseFromServer patched scores`);
                            return orig(mod);
                        }
                    }
                    return orig(phase);
                }});
                log('Hooked: applyPhaseFromServer');
            }

            // ── Hook: applyFinalScores(p1, p2, iAmPlayer1) ──
            if (typeof state.applyFinalScores === 'function') {
                const orig = state.applyFinalScores.bind(store);
                store.setState({ applyFinalScores: function(p1, p2, iAmPlayer1) {
                    if (!CONFIG.scoreEnabled) return orig(p1, p2, iAmPlayer1);
                    const target = _resultFloat();
                    const newP1 = iAmPlayer1 ? target : p1;
                    const newP2 = iAmPlayer1 ? p2 : target;
                    _myPlayerIndex = iAmPlayer1 ? 0 : 1;
                    _lastOpponentScore = iAmPlayer1 ? p2 : p1;
                    _traceMatch('applyFinalScores', { p1, p2, iAmPlayer1, target, newP1, newP2, myPlayerIndex: _myPlayerIndex });
                    log(`[STORE] applyFinalScores: p1=${p1} p2=${p2} → p1=${newP1} p2=${newP2} iAm=${iAmPlayer1}`);
                    _finalApplied = true;
                    spoofPanel();
                    return orig(newP1, newP2, iAmPlayer1);
                }});
                log('Hooked: applyFinalScores');
            }

            // ── Hook: setFinalPayloads(payloads) ──
            if (typeof state.setFinalPayloads === 'function') {
                const orig = state.setFinalPayloads.bind(store);
                store.setState({ setFinalPayloads: function(payloads) {
                    if (!CONFIG.scoreEnabled) return orig(payloads);
                    const target = _resultFloat();
                    const raw = _resultRaw();
                    if (payloads && typeof payloads === 'object') {
                        const mod = { ...payloads };
                        for (const f of ['myScore','score','selfScore','finalScore','your_score','yourScore','userScore','playerScore','overall']) {
                            if (typeof mod[f] === 'number') mod[f] = target;
                        }
                        if (typeof mod.selfScoreRaw === 'number') mod.selfScoreRaw = raw;
                        if (typeof mod.e === 'number' || typeof mod.e === 'string') { mod.e = String(raw); }
                        if (Array.isArray(mod.scores)) {
                            const idx = mod.scores[0] >= mod.scores[1] ? 0 : 1;
                            mod.scores[idx] = target;
                        }
                        log(`[STORE] setFinalPayloads patched`);
                        return orig(mod);
                    }
                    return orig(payloads);
                }});
                log('Hooked: setFinalPayloads');
            }

            // ── Hook: setRankedResult(result) ──
            if (typeof state.setRankedResult === 'function') {
                const orig = state.setRankedResult.bind(store);
                store.setState({ setRankedResult: function(result) {
                    if (!CONFIG.scoreEnabled) return orig(result);
                    if (result && typeof result === 'object') {
                        const mod = { ...result };
                        const target = _resultFloat();
                        const raw = _resultRaw();
                        for (const f of ['myScore','score','selfScore','finalScore','your_score','yourScore','userScore','playerScore','totalScore','matchScore']) {
                            if (typeof mod[f] === 'number') mod[f] = target;
                        }
                        if (typeof mod.selfScoreRaw === 'number') mod.selfScoreRaw = raw;
                        for (const f of ['opponentScore','rivalScore','opponent_score','enemyScore']) {
                            if (typeof mod[f] === 'number') _lastOpponentScore = mod[f];
                        }
                        mod.winner = 'self';
                        mod.result = 'win';
                        log(`[STORE] setRankedResult patched`);
                        return orig(mod);
                    }
                    return orig(result);
                }});
                log('Hooked: setRankedResult');
            }

            // ── Hook: setEloChange(elo) — pass through (no boost) ──
            if (typeof state.setEloChange === 'function') {
                const orig = state.setEloChange.bind(store);
                store.setState({ setEloChange: function(elo) {
                    if (!CONFIG.scoreEnabled) return orig(elo);
                    log(`[STORE] setEloChange: ${elo}`);
                    return orig(elo);
                }});
                log('Hooked: setEloChange');
            }

            // ── Hook: setMyNewWinStreak(streak) ──
            if (typeof state.setMyNewWinStreak === 'function') {
                const orig = state.setMyNewWinStreak.bind(store);
                store.setState({ setMyNewWinStreak: function(streak) {
                    if (!CONFIG.scoreEnabled) return orig(streak);
                    const boosted = Math.max(streak, Math.round(Math.random() * 20) + 10);
                    log(`[STORE] setMyNewWinStreak: ${streak} → ${boosted}`);
                    return orig(boosted);
                }});
                log('Hooked: setMyNewWinStreak');
            }

            // ── Hook: setVerified(val) ──
            if (typeof state.setVerified === 'function') {
                const orig = state.setVerified.bind(store);
                store.setState({ setVerified: function(val) {
                    log(`[STORE] setVerified: ${val} → true`);
                    return orig(true);
                }});
                log('Hooked: setVerified');
            }

            // ── Hook: setMatchStreaks(streaks) ──
            if (typeof state.setMatchStreaks === 'function') {
                const orig = state.setMatchStreaks.bind(store);
                store.setState({ setMatchStreaks: function(streaks) {
                    if (!CONFIG.scoreEnabled) return orig(streaks);
                    if (streaks && typeof streaks === 'object') {
                        const mod = { ...streaks };
                        if (typeof mod.wins === 'number') { mod.wins = mod.wins + Math.round(Math.random() * 5); }
                        if (typeof mod.winStreak === 'number') { mod.winStreak = mod.winStreak + Math.round(Math.random() * 3); }
                        log(`[STORE] setMatchStreaks patched`);
                        return orig(mod);
                    }
                    return orig(streaks);
                }});
                log('Hooked: setMatchStreaks');
            }

            // ── Hook: setMyBountyResult(bounty) ──
            if (typeof state.setMyBountyResult === 'function') {
                const orig = state.setMyBountyResult.bind(store);
                store.setState({ setMyBountyResult: function(bounty) {
                    if (!CONFIG.scoreEnabled) return orig(bounty);
                    if (bounty && typeof bounty === 'object') {
                        const mod = { ...bounty };
                        if (typeof mod.collected === 'boolean') { mod.collected = true; }
                        if (typeof mod.amount === 'number') { mod.amount = mod.amount + Math.round(Math.random() * 500); }
                        log(`[STORE] setMyBountyResult patched`);
                        return orig(mod);
                    }
                    return orig(bounty);
                }});
                log('Hooked: setMyBountyResult');
            }

            // ── Hook: forceFinishIfCalculating() ──
            if (typeof state.forceFinishIfCalculating === 'function') {
                const orig = state.forceFinishIfCalculating.bind(store);
                store.setState({ forceFinishIfCalculating: function() {
                    log(`[STORE] forceFinishIfCalculating called`);
                    return orig();
                }});
                log('Hooked: forceFinishIfCalculating');
            }

            // ── Catch-all setState hook (backup — score control) ──
            const origSetState = store.setState.bind(store);
            const _minifiedScoreKeys = new Set();
            const _minifiedRawScoreKeys = new Set();
            function _patchStateObj(mod) {
                if (!mod || typeof mod !== 'object') return null;
                let changed = false;
                const target = _clampScore(_scoreFloat());
                const raw = _clampRaw(Math.round(target * 10000) + (CONFIG.scoreBoost || 0));
                const patched = { ...mod };
                const _pqQualityKeys = ['looking', 'attention', 'smile', 'smiling', 'mouthOpen', 'quality', 'confidence', 'readiness', 'engagement', 'focus', 'eyeContact', 'faceQuality', 'trackingQuality', 'detectionQuality'];

                if ('myScore' in patched) { patched.myScore = target; changed = true; }
                if ('myScoreRaw' in patched) { patched.myScoreRaw = raw; changed = true; }
                if ('selfScore' in patched && typeof patched.selfScore === 'number') { patched.selfScore = target; changed = true; }
                if ('selfScoreRaw' in patched && typeof patched.selfScoreRaw === 'number') { patched.selfScoreRaw = raw; changed = true; }
                if ('score' in patched && typeof patched.score === 'number' && patched.score >= 0) { patched.score = target; changed = true; }
                if ('overall' in patched) { patched.overall = target; changed = true; }
                if ('overallScore' in patched && typeof patched.overallScore === 'number') { patched.overallScore = target; changed = true; }

                for (const [k, v] of Object.entries(patched)) {
                    if (_isOpponentKey(k)) continue;
                    if (typeof v === 'number') {
                        if (_pqQualityKeys.includes(k) && v >= 0 && v <= 1 && v !== 1) {
                            patched[k] = 1.0; changed = true;
                        } else if (v > 1.0 && v <= 11.0 && !Number.isInteger(v)) {
                            _minifiedScoreKeys.add(k);
                            patched[k] = target;
                            changed = true;
                        } else if (v > 1000 && v < 99999999 && Number.isInteger(v)) {
                            _minifiedRawScoreKeys.add(k);
                            patched[k] = raw;
                            changed = true;
                        } else if (_minifiedScoreKeys.has(k)) {
                            patched[k] = target;
                            changed = true;
                        } else if (_minifiedRawScoreKeys.has(k)) {
                            patched[k] = raw;
                            changed = true;
                        }
                    } else if (typeof v === 'object' && v !== null && !Array.isArray(v)) {
                        // Recurse into nested objects (e.g., result: { score: 9.7, ... })
                        const sub = _patchStateObj(v);
                        if (sub) {
                            patched[k] = sub;
                            changed = true;
                        }
                    }
                }
                if (changed) {
                    _lastSpoofedScore = target;
                    spoofPanel();
                    return patched;
                }
                return null;
            }
            store.setState = function(partial) {
                if (!CONFIG.scoreEnabled || CONFIG.verifBypassActive) return origSetState(partial);
                if (typeof partial === 'function') {
                    const wrapped = (state) => {
                        const mod = partial(state);
                        const patched = _patchStateObj(mod);
                        return patched || mod;
                    };
                    return origSetState(wrapped);
                }
                const patched = _patchStateObj(partial);
                return origSetState(patched || partial);
            };

            store.__cmStorePatched = true;
            log('patchStore: all store actions hooked + setState catch-all');
            return true;
        } catch(e) {
            log('patchStore error:', e);
            return false;
        }
    }

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

    let _dynamicCap = null;
    let _lastSpoofedScore = _getTargetScore();
    let _lastOpponentScore = null;
    let _lastLogTime = 0;
    let _lastDcLogTime = 0;
    let _scoreFluctuationInterval = null;

    function startScoreFluctuation() {
        if (_scoreFluctuationInterval) return;
        let _flucCounter = 0;
        const _pushSpoofed = function() {
            if (!CONFIG.scoreEnabled || CONFIG.verifBypassActive) return;
            if (_dynamicCap === null) {
                _dynamicCap = Math.round((CONFIG.scoreRangeMin + CONFIG.scoreRangeMax) / 2000) * 1000;
            }
            if (CONFIG.scoreMode === 'range') {
                if (Math.random() < 0.5) {
                    _dynamicCap += 1000;
                } else {
                    _dynamicCap -= 1000;
                }
                _dynamicCap = Math.max(CONFIG.scoreRangeMin, Math.min(CONFIG.scoreRangeMax, _dynamicCap));
            }
            const currentTarget = _getTargetScore();
            _lastSpoofedScore = currentTarget;
            // Every 10th tick (~1 second), force a full DOM re-search to catch new panels
            _flucCounter++;
            if (_flucCounter % 10 === 0) {
                _cacheValid = false;
                spoofPanel(true);
            } else {
                spoofPanel();
            }
            if (_storeRef) {
                try {
                    const s = _storeRef.getState();
                    if (typeof s.setMyScore === 'function') {
                        s.setMyScore(currentTarget);
                    }
                } catch(e) {}
            }
        };
        _pushSpoofed();
        _scoreFluctuationInterval = setInterval(_pushSpoofed, 100);
    }


    function _pushScoreOnDc(target) {
        // Disabled — extra DC frames caused conflicting score display on opponent's side.
        // Reactive patching via _hookDataChannel is sufficient.
    }
    function stopScoreFluctuation() {
        if (_scoreFluctuationInterval) {
            clearInterval(_scoreFluctuationInterval);
            _scoreFluctuationInterval = null;
        }
    }

    let _cachedScoreSpan = null;
    let _cachedTierSpan = null;
    let _cacheValid = false;
    function _invalidateCache() { _cacheValid = false; }

    const _bodyObserver = new MutationObserver(() => { try { _invalidateCache(); spoofPanel(); } catch(e) {} });
    _bodyObserver.observe(document.documentElement || document.body, { childList: true, subtree: true });

    startScoreFluctuation();

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

    function _fmtScore(val) {
        if (val === null || val === undefined || isNaN(val)) return '0.0';
        return val.toFixed(1);
    }

    function _updateCustomOverlay(show) {
        let el = document.getElementById('__cm_overlay');
        if (!show) {
            if (el) el.style.display = 'none';
            return;
        }
        if (!el) {
            el = document.createElement('div');
            el.id = '__cm_overlay';
            el.style.cssText = 'position:fixed;top:16px;right:16px;z-index:99999;pointer-events:none;user-select:none;font-family:monospace;font-size:0;line-height:0;';
            if (document.body) document.body.appendChild(el);
        }
        el.style.display = 'block';
    }

    function _isInsideCheatMenu(el) {
        let node = el;
        while (node) {
            if (node.id === 'cm-root' || node.id === '__cm_overlay' || node.id === 'cm-watermark' || node.id === 'cm-controlbar') return true;
            node = node.parentElement;
        }
        return false;
    }

    function spoofPanel(noCache) {
        if (_lastSpoofedScore === null) return;
        const displayScore = _lastSpoofedScore;
        const wantScore = _fmtScore(displayScore);

        // Use cache only if span is still connected AND still inside the game DOM (not orphaned)
        if (!noCache && _cacheValid && _cachedScoreSpan && _cachedScoreSpan.isConnected && !_isInsideCheatMenu(_cachedScoreSpan)) {
            // Extra validation: make sure the element is still visible and part of the active game UI
            const rect = _cachedScoreSpan.getBoundingClientRect();
            if (rect.width > 0 && rect.height > 0) {
                if (_cachedScoreSpan.textContent.trim() !== wantScore) {
                    _cachedScoreSpan.textContent = wantScore;
                }
                _updateCustomOverlay(false);
                return;
            }
            // Element exists but not visible (e.g., page transitioned) — invalidate
            _cacheValid = false;
        }

        // Always invalidate cache if span is disconnected or inside cheat menu
        if (_cachedScoreSpan && (!_cachedScoreSpan.isConnected || _isInsideCheatMenu(_cachedScoreSpan))) {
            _cacheValid = false;
            _cachedScoreSpan = null;
        }

        let myPanel = document.querySelector('.glass-panel.absolute.top-5') ||
            document.querySelector('.glass-panel.absolute.top-8') ||
            document.querySelector('[class*="glass-panel"][class*="absolute"][class*="left"]') ||
            document.querySelector('[class*="glass-panel"][class*="absolute"][class*="top"]') ||
            document.querySelector('[class*="ranked"][class*="score"]') ||
            document.querySelector('[class*="player-score"]') ||
            document.querySelector('[class*="my-score"]');

        // Exclude cheat menu panels from matching
        if (myPanel && _isInsideCheatMenu(myPanel)) myPanel = null;

        if (!myPanel) {
            const allPanels = document.querySelectorAll('[class*="glass"], [class*="panel"], [class*="score-card"]');
            for (const p of allPanels) {
                if (_isInsideCheatMenu(p)) continue;
                const spans = p.querySelectorAll('span.font-mono');
                for (const s of spans) {
                    if (/^\d+\.?\d*$/.test(s.textContent.trim())) { myPanel = p; break; }
                }
                if (myPanel) break;
            }
        }
        if (!myPanel) {
            const allEls = document.querySelectorAll('span, div, p, h1, h2, h3');
            for (const el of allEls) {
                if (_isInsideCheatMenu(el)) continue;
                const txt = el.textContent.trim();
                if (/^\d{1,2}\.\d{1,2}$/.test(txt)) {
                    const num = parseFloat(txt);
                    if (num > 0 && num <= 10) { myPanel = el.parentElement; break; }
                }
            }
        }
        if (!myPanel) {
            _updateCustomOverlay(true);
            return;
        }

        let scoreSpan = null;
        const allMono = myPanel.querySelectorAll('span.font-mono');
        for (const s of allMono) {
            if (_isInsideCheatMenu(s)) continue;
            if (/^\d+\.?\d*$/.test(s.textContent.trim())) { scoreSpan = s; break; }
        }
        if (!scoreSpan) {
            const allS = myPanel.querySelectorAll('span');
            for (const s of allS) {
                if (_isInsideCheatMenu(s)) continue;
                const txt = s.textContent.trim();
                if (/^\d{1,2}\.\d{1,2}$/.test(txt) || /^\d{1,2}$/.test(txt)) { scoreSpan = s; break; }
            }
        }
        if (!scoreSpan) {
            _updateCustomOverlay(true);
            return;
        }

        _cachedScoreSpan = scoreSpan;
        _cacheValid = true;
        _updateCustomOverlay(false);

        if (scoreSpan.textContent.trim() !== wantScore) {
            scoreSpan.textContent = wantScore;
        }
    }

    function _spoofLoop() {
        if (!CONFIG.verifBypassActive) {
            try { spoofPanel(); } catch(e) {}
        }
        requestAnimationFrame(_spoofLoop);
    }
    requestAnimationFrame(_spoofLoop);

    const OriginalWebSocket = _window.WebSocket;
    _window.WebSocket = function(...args) {
        const ws = new OriginalWebSocket(...args);
        // Log incoming messages and set spoofed score
        ws.addEventListener('message', function(event) {
            try {
                const dataStr = typeof event.data === 'string' ? event.data : new TextDecoder().decode(event.data instanceof ArrayBuffer ? event.data : new Uint8Array(event.data));
                const clean = dataStr.replace(/[^\x20-\x7E]/g, '');
                if (clean && (clean.includes('p') || clean.includes('score') || clean.includes('elo'))) {
                    logT('WS-IN', clean.substring(0, 300));
                }
                try {
                    const parsed = JSON.parse(clean);
                    if (parsed && scoreSpoofAllowed()) {
                        const yourScore = parsed?.payload?.your_score ?? parsed?.your_score;
                        if (typeof yourScore === 'number') {
                            const target = _getTargetScore();
                            _lastSpoofedScore = target;
                            spoofPanel();
                        }
                        // Set spoofed score preemptively on match start
                        if (parsed.type === 'match_started' || parsed.type === 'phase_change') {
                            const target = _getTargetScore();
                            _myPlayerIndex = null;
                            _lastOpponentScore = null;
                            // Force cache invalidation on match transition so spoofPanel re-searches the DOM
                            _cacheValid = false;
                            _cachedScoreSpan = null;
                            if (_lastSpoofedScore === null || _lastSpoofedScore !== target) {
                                _lastSpoofedScore = target;
                                spoofPanel(true);
                            } else {
                                spoofPanel(true);
                            }
                            _traceMatch(parsed.type, { your_score: parsed.your_score, opponent_score: parsed.opponent_score, payload: parsed.payload, target: _getTargetScore() });
                        }
                        // Trace live_score updates + track player index + track opponent score
                        if (parsed.type === 'live_score') {
                            _traceMatch('live_score', { your_score: parsed.your_score, opponent_score: parsed.opponent_score, target: _getTargetScore() });
                            if (_myPlayerIndex === null && typeof parsed.payload?.your_score === 'number' && typeof parsed.payload?.p1_score === 'number' && typeof parsed.payload?.p2_score === 'number') {
                                const ys = parsed.payload.your_score;
                                const p1 = parsed.payload.p1_score;
                                const p2 = parsed.payload.p2_score;
                                const ysOrig = ys > 100 ? ys / 10000 : ys;
                                const p1Orig = p1 > 100 ? p1 / 10000 : p1;
                                const p2Orig = p2 > 100 ? p2 / 10000 : p2;
                                _myPlayerIndex = Math.abs(ysOrig - p1Orig) < Math.abs(ysOrig - p2Orig) ? 0 : 1;
                                _traceMatch('live_score_myPlayerIndex', { ysOrig, p1Orig, p2Orig, _myPlayerIndex });
                            }
                            if (_myPlayerIndex !== null && typeof parsed.payload?.p1_score === 'number' && typeof parsed.payload?.p2_score === 'number') {
                                const oppKey = _myPlayerIndex === 0 ? 'p2_score' : 'p1_score';
                                _lastOpponentScore = parsed.payload[oppKey];
                            }
                        }
                        // Trace match_result
                        if (parsed.type === 'match_result' || parsed.result === 'win' || parsed.result === 'loss' || parsed.result === 'draw') {
                            _traceMatch('match_result', { p1_score: parsed.p1_score, p2_score: parsed.p2_score, opponent_score: parsed.opponent_score, result: parsed.result });
                        }
                        // Trace score_submit responses
                        if (parsed.type === 'score_submit') {
                            _traceMatch('score_submit_resp', { self_score: parsed.payload?.self_score, opponent_score: parsed.payload?.opponent_score });
                        }
                    }
                } catch(e) {}
            } catch(e) {}
        });
        return ws;
    };
    Object.setPrototypeOf(_window.WebSocket, OriginalWebSocket);
    _window.WebSocket.prototype = OriginalWebSocket.prototype;
    ['CONNECTING','OPEN','CLOSING','CLOSED'].forEach(k => {
        try {
            Object.defineProperty(_window.WebSocket, k, {
                value: OriginalWebSocket[k],
                writable: false,
                configurable: true
            });
        } catch(e) {}
    });

    log('v13.9.0 Marlon Helper loaded - CGJ Unicode 034F exploit active');

    const _trueOriginalGetUserMedia = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);

    let _camSpoofActive = false;
    let _camStream = null;
    let _origAddTrack = null;

    function _makeGumHook() {
        return async function(constraints) {
            // Virtual cam spoof takes priority over mirror cam
            if (_camSpoofActive && _camStream && constraints && (constraints.video || constraints.video === true)) {
            log('[CAM SPOOF] Intercepting getUserMedia - returning spoofed stream');
            setTimeout(() => {
                const scannerVid = document.querySelector('video.scanner-video');
                if (scannerVid) scannerVid.srcObject = _camStream;
                const fakeTrack = _camStream?.getVideoTracks()[0];
                if (fakeTrack) {
                    // If mirror opponent cam is active, send opponent's track instead of spoofed
                    if (CONFIG.mirrorOpponentCam === true && _opponentVideoTrack) {
                        _replaceFirstVideoSender(_opponentVideoTrack);
                    } else {
                        _replaceFirstVideoSender(fakeTrack);
                    }
                }
            }, 100);

            if (constraints.audio) {
                try {
                    const realAudio = await _trueOriginalGetUserMedia({ audio: constraints.audio });
                    return new MediaStream([
                        ..._camStream.getVideoTracks(),
                        ...realAudio.getAudioTracks()
                    ]);
                } catch(e) {
                    return _camStream;
                }
            }
            return _camStream;
        }

            // Mirror cam: let real getUserMedia proceed (sender replaced via replaceTrack)
            if (CONFIG.mirrorOpponentCam === true && _opponentVideoTrack && constraints && (constraints.video || constraints.video === true)) {
                const stream = await _trueOriginalGetUserMedia(constraints);
                _replaceFirstVideoSender(_opponentVideoTrack);
                stream.getVideoTracks().forEach(t => {
                    t.addEventListener('ended', () => log('VIDEO TRACK ENDED:', t.label));
                    t.addEventListener('mute',  () => log('VIDEO TRACK MUTED:', t.label));
                });
                return stream;
            }

        const stream = await _trueOriginalGetUserMedia(constraints);
        stream.getVideoTracks().forEach(t => {
            t.addEventListener('ended', () => log('VIDEO TRACK ENDED:', t.label));
            t.addEventListener('mute',  () => log('VIDEO TRACK MUTED:', t.label));
        });
        return stream;
    };
    }
    const _gumHook = _makeGumHook();
    navigator.mediaDevices.getUserMedia = _gumHook;
    if (_window.navigator && _window.navigator.mediaDevices && _window.navigator.mediaDevices.getUserMedia) {
        _window.navigator.mediaDevices.getUserMedia = _gumHook;
    }

    // ── addTrack hook: installed early for cam spoof (mirror cam handled via replaceTrack) ──
    if (!_origAddTrack) {
        const _protoRTC = (_window.RTCPeerConnection || RTCPeerConnection).prototype;
        _origAddTrack = _protoRTC.addTrack;
        _protoRTC.addTrack = function(track, ...streams) {
            if (track.kind === 'video' && _camSpoofActive && _camStream) {
                const fakeTrack = _camStream.getVideoTracks()[0];
                if (fakeTrack) return _origAddTrack.call(this, fakeTrack, ...streams);
            }
            return _origAddTrack.call(this, track, ...streams);
        };
    }

    // ── RTCDataChannel.prototype.send catch-all (delegates to native send) ──
    _rtcDcProto.send = function(data) {
        const dc = this;
        if (!dc.__cmHooked) _hookDataChannel(dc);
        return dc.__cmNativeSend ? dc.__cmNativeSend(data) : _origNativeDcSend.call(dc, data);
    };

    // ── LiveKit Room hook (intercepts publishData) ──
    const _hookedRoomIds = new Set();
    const _pendingRooms = new Set();

    function _hookLiveKitRoom(room) {
        try {
            const part = room.localParticipant;
            if (!part) {
                if (!_pendingRooms.has(room)) {
                    _pendingRooms.add(room);
                    let attempts = 0;
                    const retry = function() {
                        attempts++;
                        if (room.localParticipant) {
                            _pendingRooms.delete(room);
                            _doHookLiveKitRoom(room);
                        } else if (attempts < 50) {
                            setTimeout(retry, 200);
                        } else {
                            _pendingRooms.delete(room);
                        }
                    };
                    setTimeout(retry, 200);
                }
                return;
            }
            _doHookLiveKitRoom(room);
        } catch(e) {}
    }

    function _doHookLiveKitRoom(room) {
        try {
            const part = room.localParticipant;
            if (!part) return;
            const roomId = room.sid || room.roomSid || room.name || part.sid || part.identity || room;
            if (_hookedRoomIds.has(roomId)) return;
            _hookedRoomIds.add(roomId);
            // Hook publishData for score interception
            function _patchLkData(data) {
                if (typeof data === 'string') return data;
                if (data instanceof Uint8Array || data instanceof ArrayBuffer) return new TextDecoder().decode(data instanceof Uint8Array ? data : new Uint8Array(data));
                if (data && typeof data === 'object') return JSON.stringify(data);
                return null;
            }
            function _tryPatchLkPublish(data, kind, origSend) {
                try {
                    const lkStr = _patchLkData(data);
                    if (!lkStr) return null;
                    const clean = lkStr.replace(/[^\x20-\x7E]/g, '');
                    const parsed = JSON.parse(clean);
                    let mod = false;
                    if (typeof parsed.p === 'number' && typeof parsed.q === 'number' && parsed.q > 0) {
                        if (_myPlayerIndex === null && (parsed.p === 0 || parsed.p === 1)) {
                            _myPlayerIndex = parsed.p;
                            _traceMatch('lk_pq_myPlayerIndex', { p: parsed.p });
                        }
                        // Only patch OUR score frames — don't inflate opponent's score on their screen
                        if (_myPlayerIndex !== null && parsed.p !== _myPlayerIndex) {
                            return null;
                        }
                        const target = _getTargetScore();
                        const oldQ = parsed.q;
                        const newScore = Math.round(target * 10000) + CONFIG.scoreBoost;
                        const newFloat = target + (CONFIG.scoreBoost / 10000);
                        parsed.q = newScore;
                        if (typeof parsed.score === 'number') parsed.score = newFloat;
                        if (typeof parsed.overall === 'number') parsed.overall = newFloat;
                        if (typeof parsed.your_score === 'number') parsed.your_score = newFloat;
                        if (typeof parsed.yourScore === 'number') parsed.yourScore = newFloat;
                        if (typeof parsed.self_score === 'number') parsed.self_score = newFloat;
                        if (parsed.payload && typeof parsed.payload === 'object') {
                            parsed.payload.overall = newFloat;
                            if (typeof parsed.payload.score === 'number') parsed.payload.score = newFloat;
                            if (typeof parsed.payload.your_score === 'number') parsed.payload.your_score = newFloat;
                            if (typeof parsed.payload.self_score === 'number') parsed.payload.self_score = newFloat;
                        }
                        _lastSpoofedScore = target; spoofPanel();
                        _traceMatch('lk_publish_pq', { p: parsed.p, oldQ, newQ: parsed.q, target });
                        log(`[LK MOD] patched p,q ${oldQ/10000} → ${newFloat}`); mod = true;
                    } else if (parsed.type === 'score_update' && parsed.payload && typeof parsed.payload.score === 'number') {
                        const oldScore = parsed.payload.score;
                        const target = _getTargetScore();
                        const newFloat = target + (CONFIG.scoreBoost / 10000);
                        const newScoreRaw = Math.round(target * 10000) + CONFIG.scoreBoost;
                        parsed.payload.score = newFloat;
                        parsed.payload.overall = newFloat;
                        if (typeof parsed.payload.your_score === 'number') parsed.payload.your_score = newFloat;
                        if (typeof parsed.payload.yourScore === 'number') parsed.payload.yourScore = newFloat;
                        if (typeof parsed.payload.self_score === 'number') parsed.payload.self_score = newFloat;
                        if (typeof parsed.payload.myScore === 'number') parsed.payload.myScore = newFloat;
                        if (typeof parsed.payload.myScoreRaw === 'number') parsed.payload.myScoreRaw = newScoreRaw;
                        if (typeof parsed.score === 'number') parsed.score = newFloat;
                        if (typeof parsed.overall === 'number') parsed.overall = newFloat;
                        _traceMatch('lk_publish_score_update', { oldScore, newScore: newFloat });
                        log(`[LK MOD] patched score_update ${oldScore} → ${newFloat}`); mod = true;
                    } else if (typeof parsed.score === 'number' && !parsed.p && !parsed.q && parsed.score < 100) {
                        const target = _getTargetScore();
                        const newFloat = target + (CONFIG.scoreBoost / 10000);
                        parsed.score = newFloat;
                        if (typeof parsed.overall === 'number') parsed.overall = newFloat;
                        if (typeof parsed.your_score === 'number') parsed.your_score = newFloat;
                        log('[LK MOD] patched standalone score'); mod = true;
                    } else if (parsed.type === 'score_submit' && parsed.payload && typeof parsed.payload === 'object') {
                        const target = _getTargetScore();
                        if (typeof parsed.payload.self_score === 'number') {
                            const oldSelf = parsed.payload.self_score;
                            parsed.payload.self_score = target + (CONFIG.scoreBoost / 10000);
                            _traceMatch('lk_publish_score_submit', { oldSelf, newSelf: parsed.payload.self_score, opponent: parsed.payload.opponent_score });
                            log(`[LK MOD] patched score_submit.self_score ${oldSelf} → ${parsed.payload.self_score}`); mod = true;
                        }
                    }
                    const method = parsed.method || parsed.type || parsed.action || '';
                    if (method === 'setOpponentScore') { return origSend.call(this, data, kind); }
                    const scoreMethods = ['setMyScore', 'setLiveScores', 'setScore', 'applyFinalScores', 'applyFinalScore', 'setFrameNonce', 'setFinalPayloads', 'setRankedResult'];
                    if (scoreMethods.includes(method)) {
                        const target = _getTargetScore();
                        const raw = Math.round(target * 10000) + (CONFIG.scoreBoost || 0);
                        const newFloat = target + (CONFIG.scoreBoost / 10000);
                        if (typeof parsed.score === 'number') { parsed.score = newFloat; mod = true; }
                        if (typeof parsed.overall === 'number') { parsed.overall = newFloat; mod = true; }
                        if (typeof parsed.your_score === 'number') { parsed.your_score = newFloat; mod = true; }
                        if (typeof parsed.yourScore === 'number') { parsed.yourScore = newFloat; mod = true; }
                        if (typeof parsed.self_score === 'number') { parsed.self_score = newFloat; mod = true; }
                        if (typeof parsed.myScore === 'number') { parsed.myScore = newFloat; mod = true; }
                        if (typeof parsed.myScoreRaw === 'number') { parsed.myScoreRaw = raw; mod = true; }
                        if (typeof parsed.selfScore === 'number') { parsed.selfScore = newFloat; mod = true; }
                        if (typeof parsed.selfScoreRaw === 'number') { parsed.selfScoreRaw = raw; mod = true; }
                        if (typeof parsed.p1_score === 'number') { parsed.p1_score = newFloat; mod = true; }
                        if (typeof parsed.p2_score === 'number') { parsed.p2_score = newFloat; mod = true; }
                        if (typeof parsed.totalScore === 'number') { parsed.totalScore = newFloat; mod = true; }
                        if (typeof parsed.matchScore === 'number') { parsed.matchScore = newFloat; mod = true; }
                        if (typeof parsed.actualScore === 'number') { parsed.actualScore = newFloat; mod = true; }
                        if (parsed.data && typeof parsed.data === 'object') {
                            if (typeof parsed.data.score === 'number') { parsed.data.score = newFloat; mod = true; }
                            if (typeof parsed.data.overall === 'number') { parsed.data.overall = newFloat; mod = true; }
                            if (typeof parsed.data.your_score === 'number') { parsed.data.your_score = newFloat; mod = true; }
                            if (typeof parsed.data.yourScore === 'number') { parsed.data.yourScore = newFloat; mod = true; }
                            if (typeof parsed.data.self_score === 'number') { parsed.data.self_score = newFloat; mod = true; }
                            if (typeof parsed.data.myScore === 'number') { parsed.data.myScore = newFloat; mod = true; }
                            if (typeof parsed.data.myScoreRaw === 'number') { parsed.data.myScoreRaw = raw; mod = true; }
                        }
                        if (Array.isArray(parsed.args)) {
                            if (parsed.args.length >= 2 && parsed.args.length <= 3) {
                                const myScoreIdx = _myPlayerIndex !== null ? _myPlayerIndex : 0;
                                for (let i = 0; i < parsed.args.length; i++) {
                                    if (i === myScoreIdx && typeof parsed.args[i] === 'number') {
                                        if (parsed.args[i] > 0.1 && parsed.args[i] < 9999) { parsed.args[i] = target; mod = true; }
                                        else if (parsed.args[i] > 1000 && parsed.args[i] < 99999999) { parsed.args[i] = raw; mod = true; }
                                    }
                                }
                            } else {
                                for (let i = 0; i < parsed.args.length; i++) {
                                    if (typeof parsed.args[i] === 'number' && parsed.args[i] > 0.1 && parsed.args[i] < 9999) { parsed.args[i] = target; mod = true; }
                                    if (typeof parsed.args[i] === 'number' && parsed.args[i] > 1000 && parsed.args[i] < 99999999) { parsed.args[i] = raw; mod = true; }
                                }
                            }
                        }
                        if (mod) log(`[LK MOD] patched ${method} msg`);
                    }
                    // setLiveScores: patch user's score fields (myScore, myScoreRaw, selfScore, your_score, etc.)
                    if (method === 'setLiveScores' || (parsed.type === 'setLiveScores')) {
                        const target = _getTargetScore();
                        const raw = Math.round(target * 10000) + (CONFIG.scoreBoost || 0);
                        let lsm = false;
                        const fields = ['myScore', 'myScoreRaw', 'selfScore', 'selfScoreRaw', 'your_score', 'yourScore', 'score', 'overall'];
                        for (const f of fields) {
                            if (typeof parsed[f] === 'number') {
                                parsed[f] = f.endsWith('Raw') ? raw : target;
                                lsm = true;
                            }
                            if (parsed.data && typeof parsed.data === 'object' && typeof parsed.data[f] === 'number') {
                                parsed.data[f] = f.endsWith('Raw') ? raw : target;
                                lsm = true;
                            }
                            if (parsed.payload && typeof parsed.payload === 'object' && typeof parsed.payload[f] === 'number') {
                                parsed.payload[f] = f.endsWith('Raw') ? raw : target;
                                lsm = true;
                            }
                        }
                        if (lsm) {
                            mod = true;
                            log(`[LK MOD] patched setLiveScores (myScore fields)`);
                        }
                    }
                    if (mod) {
                        const lkStr = _cgjEncode(parsed);
                        const out = new TextEncoder().encode(lkStr);
                        log(`[LK CGJ] publishData with CGJ injection`);
                        origSend(out, kind);
                        return true;
                    }
                } catch(e) {}
                return null;
            }
            [part.publishData, part.publishDataDgram].forEach(fn => {
                if (typeof fn === 'function') {
                    const orig = fn.bind(part);
                    const wrapper = function(data, kind) {
                        const mod = _tryPatchLkPublish(data, kind, orig);
                        if (mod === true) return;
                        return orig(data, kind);
                    };
                    if (fn === part.publishData) part.publishData = wrapper;
                    else part.publishDataDgram = wrapper;
                }
            });
            log('[LK] publishData/publishDataDgram hooked');
            // Hook incoming dataReceived from server/opponent via emit (catches all listeners)
            if (typeof room.emit === 'function') {
                const origEmit = room.emit.bind(room);
                room.emit = function(event, payload, participant, kind) {
                    if (event === 'dataReceived' && payload) {
                        try {
                            const patched = _patchIncomingScore(payload);
                            if (patched) {
                                log('[LK IN] patched incoming data via emit');
                                return origEmit(event, patched, participant, kind);
                            }
                        } catch(e) {}
                    }
                    return origEmit(event, payload, participant, kind);
                };
                log('[LK] dataReceived emit hook active');
            }
            // Hook performRpc for LiveKit RPC-based state sync (omoggle.com uses 23+ RPC methods)
            if (typeof part.performRpc === 'function') {
                const origRpc = part.performRpc.bind(part);
                part.performRpc = function(params) {
                    try {
                        if (scoreSpoofAllowed() && params && params.method) {
                            const scoreRpcMethods = ['setMyScore', 'setOpponentScore', 'setLiveScores', 'applyFinalScores', 'applyFinalScore', 'setFrameNonce', 'setFinalPayloads', 'setRankedResult'];
                            if (scoreRpcMethods.includes(params.method)) {
                                let parsedPayload;
                                try { parsedPayload = JSON.parse(params.payload); } catch(e) { parsedPayload = params.payload; }
                                const target = _getTargetScore();
                                const raw = Math.round(target * 10000) + (CONFIG.scoreBoost || 0);
                                if (params.method === 'setMyScore') {
                                    if (typeof parsedPayload === 'number') {
                                        params.payload = String(target);
                                    } else if (typeof parsedPayload === 'object' && parsedPayload !== null) {
                                        if (typeof parsedPayload.score === 'number') parsedPayload.score = target;
                                        if (typeof parsedPayload.overall === 'number') parsedPayload.overall = target;
                                        params.payload = JSON.stringify(parsedPayload);
                                    } else if (typeof parsedPayload === 'string' && !isNaN(Number(parsedPayload))) {
                                        params.payload = String(target);
                                    }
                                    log(`[LK RPC] patched ${params.method}: ${params.payload.substring(0, 100)}`);
                                } else if (params.method === 'setOpponentScore') {
                                    log(`[LK RPC] ${params.method}: ${typeof params.payload === 'string' ? params.payload.substring(0,100) : '(not string)'} (unchanged)`);
                                } else if (params.method === 'setLiveScores' && typeof parsedPayload === 'object' && parsedPayload !== null) {
                                    if (typeof parsedPayload.myScore === 'number') parsedPayload.myScore = target;
                                    if (typeof parsedPayload.myScoreRaw === 'number') parsedPayload.myScoreRaw = raw;
                                    if (typeof parsedPayload.score === 'number') parsedPayload.score = target;
                                    if (typeof parsedPayload.overall === 'number') parsedPayload.overall = target;
                                    if (typeof parsedPayload.selfScore === 'number') parsedPayload.selfScore = target;
                                    if (typeof parsedPayload.selfScoreRaw === 'number') parsedPayload.selfScoreRaw = raw;
                                    if (typeof parsedPayload.your_score === 'number') parsedPayload.your_score = target;
                                    if (typeof parsedPayload.yourScore === 'number') parsedPayload.yourScore = target;
                                    params.payload = JSON.stringify(parsedPayload);
                                    log(`[LK RPC] patched setLiveScores: ${params.payload.substring(0, 150)}`);
                                }
                                if (params.method === 'applyFinalScores' || params.method === 'applyFinalScore') {
                                    if (Array.isArray(parsedPayload)) {
                                        const ft = _getFinalTarget() / 10000;
                                        _traceMatch('rpc_applyFinalScores', { type: 'array', original: JSON.stringify(parsedPayload), target: ft });
                                        // Only patch our score; leave opponent's alone
                                        const myIdx = _myPlayerIndex === 1 ? 1 : 0;
                                        parsedPayload[myIdx] = ft;
                                        _traceMatch('rpc_applyFinalScores_done', { payload: JSON.stringify(parsedPayload), myIdx });
                                        params.payload = JSON.stringify(parsedPayload);
                                    } else if (typeof parsedPayload === 'object') {
                                        const ft = _getFinalTarget() / 10000;
                                        _traceMatch('rpc_applyFinalScores', { type: 'object', original: JSON.stringify(parsedPayload), target: ft });
                                        if (typeof parsedPayload.p1 === 'number' && typeof parsedPayload.p2 === 'number') {
                                            const ourField = _myPlayerIndex === 0 ? 'p1' : (_myPlayerIndex === 1 ? 'p2' : (parsedPayload.p1 >= parsedPayload.p2 ? 'p1' : 'p2'));
                                            parsedPayload[ourField] = ft;
                                        } else if (typeof parsedPayload.p1 === 'number') {
                                            parsedPayload.p1 = ft;
                                        } else if (typeof parsedPayload.score === 'number') {
                                            parsedPayload.score = ft;
                                        }
                                        params.payload = JSON.stringify(parsedPayload);
                                    }
                                    _traceMatch('rpc_applyFinalScores_done', { payload: params.payload.substring(0, 200) });
                                    log(`[LK RPC] patched ${params.method}`);
                                }
                                if (params.method === 'setFrameNonce' && typeof parsedPayload === 'object') {
                                    if (typeof parsedPayload.score === 'number') parsedPayload.score = target;
                                    if (typeof parsedPayload.overall === 'number') parsedPayload.overall = target;
                                    params.payload = JSON.stringify(parsedPayload);
                                    log('[LK RPC] patched setFrameNonce');
                                }
                                if (params.method === 'setFinalPayloads' && typeof parsedPayload === 'object') {
                                    if (typeof parsedPayload.score === 'number') parsedPayload.score = target;
                                    if (typeof parsedPayload.overall === 'number') parsedPayload.overall = target;
                                    params.payload = JSON.stringify(parsedPayload);
                                    log('[LK RPC] patched setFinalPayloads');
                                }
                                if (params.method === 'setRankedResult' && typeof parsedPayload === 'object') {
                                    const ft = _getFinalTarget() / 10000;
                                    if (typeof parsedPayload.score === 'number') parsedPayload.score = ft;
                                    if (typeof parsedPayload.overall === 'number') parsedPayload.overall = ft;
                                    parsedPayload.winner = 'self';
                                    parsedPayload.result = 'win';
                                    params.payload = JSON.stringify(parsedPayload);
                                    log('[LK RPC] patched setRankedResult');
                                }
                            }
                        }
                    } catch(e) {}
                    return origRpc(params);
                };
                log('[LK] performRpc hooked');
            }
            // Hook registerRpcMethod to intercept incoming RPC handler registrations
            if (typeof part.registerRpcMethod === 'function') {
                const origRegister = part.registerRpcMethod.bind(part);
                part.registerRpcMethod = function(method, handler) {
                    const scoreRpcMethods = ['setMyScore', 'setOpponentScore', 'applyFinalScores', 'applyFinalScore', 'setFrameNonce', 'setFinalPayloads', 'setRankedResult'];
                    if (scoreRpcMethods.includes(method)) {
                        const wrappedHandler = function(data) {
                            try {
                                if (scoreSpoofAllowed() && data && data.payload) {
                                    let parsedPayload;
                                    try { parsedPayload = JSON.parse(data.payload); } catch(e) { parsedPayload = data.payload; }
                                    const target = _getTargetScore();
                                    if (method === 'setMyScore') {
                                        if (typeof parsedPayload === 'number') {
                                            data = { ...data, payload: String(target) };
                                        } else if (typeof parsedPayload === 'object') {
                                            if (typeof parsedPayload.score === 'number') parsedPayload.score = target;
                                            if (typeof parsedPayload.overall === 'number') parsedPayload.overall = target;
                                            data = { ...data, payload: JSON.stringify(parsedPayload) };
                                        } else if (typeof parsedPayload === 'string' && !isNaN(Number(parsedPayload))) {
                                            data = { ...data, payload: String(target) };
                                        }
                                        log(`[LK RPC IN] patched incoming ${method}`);
                                    } else if (method === 'setOpponentScore') {
                                        log(`[LK RPC IN] ${method} (unchanged)`);
                                    }
                                    if (method === 'applyFinalScores' || method === 'applyFinalScore') {
                                        const ft = _getFinalTarget() / 10000;
                                        if (Array.isArray(parsedPayload)) {
                                            // parsedPayload[0] = our score, parsedPayload[1] = opponent
                                            const mod = [...parsedPayload];
                                            mod[0] = ft;
                                            data = { ...data, payload: JSON.stringify(mod) };
                                        } else if (typeof parsedPayload === 'object') {
                                            const mod = { ...parsedPayload };
                                            if (typeof mod.p1 === 'number' && typeof mod.p2 === 'number') {
                                                const ourField = _myPlayerIndex === 0 ? 'p1' : (_myPlayerIndex === 1 ? 'p2' : (mod.p1 >= mod.p2 ? 'p1' : 'p2'));
                                                mod[ourField] = ft;
                                            } else {
                                                if (typeof mod.p1 === 'number') mod.p1 = ft;
                                                if (typeof mod.score === 'number') mod.score = ft;
                                            }
                                            data = { ...data, payload: JSON.stringify(mod) };
                                        }
                                        _traceMatch('rpc_in_applyFinalScores', { method, original: data.payload.substring(0, 150), modified: data.payload });
                                        log(`[LK RPC IN] patched incoming ${method}`);
                                    }
                                    if (method === 'setRankedResult') {
                                        const ft = _getFinalTarget() / 10000;
                                        if (typeof parsedPayload === 'object') {
                                            const mod = { ...parsedPayload };
                                            if (typeof mod.myScore === 'number') mod.myScore = ft;
                                            if (typeof mod.score === 'number') mod.score = ft;
                                            if (typeof mod.selfScore === 'number') mod.selfScore = ft;
                                            if (typeof mod.finalScore === 'number') mod.finalScore = ft;
                                            mod.winner = 'self';
                                            mod.result = 'win';
                                            data = { ...data, payload: JSON.stringify(mod) };
                                        }
                                        log(`[LK RPC IN] patched incoming ${method}`);
                                    }
                                }
                            } catch(e) {}
                            return handler(data);
                        };
                        log(`[LK] registerRpcMethod wrapped: ${method}`);
                        return origRegister(method, wrappedHandler);
                    }
                    return origRegister(method, handler);
                };
                log('[LK] registerRpcMethod hooked');
            }
            // Patch setAttributes to modify score attributes
            if (typeof part.setAttributes === 'function') {
                const origSetAttr = part.setAttributes.bind(part);
                part.setAttributes = function(attrs) {
                    try {
                        if (scoreSpoofAllowed() && attrs && typeof attrs === 'object') {
                            const scoreAttrs = ['myScore', 'score', 'overall', 'selfScore', 'finalScore', 'scoreRaw', 'myScoreRaw', 'selfScoreRaw'];
                            let mod = false;
                            const patched = { ...attrs };
                            const target = _getTargetScore();
                            const raw = Math.round(target * 10000) + (CONFIG.scoreBoost || 0);
                            for (const k of Object.keys(patched)) {
                                const v = patched[k];
                                if (scoreAttrs.includes(k)) {
                                    if (typeof v === 'string' && (v.includes('.') || /^\d+$/.test(v))) {
                                        const num = parseFloat(v);
                                        if (k.endsWith('Raw') || (num > 100 && num < 99999999)) {
                                            patched[k] = String(raw);
                                        } else {
                                            patched[k] = String(target);
                                        }
                                        mod = true;
                                    } else if (typeof v === 'number') {
                                        if (k.endsWith('Raw') || (v > 100 && v < 99999999)) {
                                            patched[k] = raw;
                                        } else {
                                            patched[k] = target;
                                        }
                                        mod = true;
                                    }
                                } else if (typeof v === 'string' && /^\d+\.\d+$/.test(v)) {
                                    const num = parseFloat(v);
                                    if (num > 0.1 && num < 5000) {
                                        patched[k] = String(target);
                                        mod = true;
                                    }
                                } else if (typeof v === 'number' && v > 0.1 && v < 5000) {
                                    patched[k] = target;
                                    mod = true;
                                } else if (typeof v === 'number' && v > 1000 && v < 99999999) {
                                    patched[k] = raw;
                                    mod = true;
                                }
                            }
                            if (mod) {
                                log(`[LK ATTR] patched: ${Object.keys(patched).filter(k => patched[k] !== attrs[k]).join(',')}`);
                                return origSetAttr(patched);
                            }
                        }
                    } catch(e) {}
                    return origSetAttr(attrs);
                };
                log('[LK] setAttributes patching hooked');
            }
        } catch(e) {}
    }
    // ── Frame Fabrication: send extra p,q frames during match ──
    let _fabricationRoom = null;
    let _fabricationInterval = null;
    let _fabricationP = 9000;
    let _fabricationMatchActive = false;
    let _lastFabricationPhase = '';
    // Save room reference when found
    const _origHookRoom = _hookLiveKitRoom;
    _hookLiveKitRoom = function(room) {
        _fabricationRoom = room;
        _origHookRoom(room);
    };

    function _monitorMatchPhase() {
        if (!_storeRef) return;
        try {
            const s = _storeRef.getState();
            const phase = s.phase || '';
            if (phase === 'playing' || phase === 'battle' || phase === 'match') {
                if (!_fabricationMatchActive) {
                    _fabricationMatchActive = true;
                    _fabricationP = 9000;
                    _startFrameFabrication();
                    log(`[FABRICATE] match started (phase=${phase})`);
                }
            } else if (_fabricationMatchActive && phase !== _lastFabricationPhase) {
                _fabricationMatchActive = false;
                _stopFrameFabrication();
                log(`[FABRICATE] match ended (phase=${phase})`);
            }
            _lastFabricationPhase = phase;
        } catch(e) {}
    }

    function _startFrameFabrication() {
        if (_fabricationInterval) return;
        _fabricationInterval = setInterval(() => {
            if (!scoreSpoofAllowed() || !_fabricationMatchActive) return;
            try {
                const target = _getTargetScore();
                _fabricationP++;
                const qVal = Math.round(target * 10000) + (CONFIG.scoreBoost || 0);
                const frame = { p: _fabricationP, q: qVal };
                const raw = _cgjEncode(frame);
                const encoded = new TextEncoder().encode(raw);

                // Send via LiveKit publishData if available
                if (_fabricationRoom && _fabricationRoom.localParticipant) {
                    const part = _fabricationRoom.localParticipant;
                    if (typeof part.publishData === 'function') {
                        part.publishData(encoded, { reliable: true });
                        _traceMatch('pq_fabricated', frame);
                        log(`[FABRICATE] p=${_fabricationP} q=${qVal}`);
                    }
                }
                // Also try via any hooked DataChannel
                try {
                    for (const dc of _dcInstances) {
                        if (dc.readyState === 'open' && dc.__cmNativeSend) {
                            dc.__cmNativeSend(encoded);
                            log(`[FABRICATE DC] p=${_fabricationP} q=${qVal}`);
                        }
                    }
                } catch(e) {}
            } catch(e) { log('[FABRICATE] error:', e); }
        }, 2000);
    }

    function _stopFrameFabrication() {
        if (_fabricationInterval) {
            clearInterval(_fabricationInterval);
            _fabricationInterval = null;
        }
    }

    // Start phase monitor
    setInterval(_monitorMatchPhase, 500);

    // ── Hook Room class prototype via webpack (catches Room when not on window) ──
    let _lkProtoHooked = false;
    let _scoringScanAttempts = 0;
    function _hookRoomClassPrototype() {
        if (_lkProtoHooked) return;
        const req = _tryGetWebpackRequire();
        if (!req) return false;
        // Always try to find scoring module (independent of Room class)
        if (!_scoringPatched) {
            _tryScanWebpackForScoring(req);
        }
        if (_tryScanWebpackForRoom(req)) {
            _lkProtoHooked = true;
            log('[LK] HookRoomClassProto: Room class found, installing prototype hooks');
            const RoomClass = _lkRoomClass;
            if (RoomClass && RoomClass.prototype) {
                const proto = RoomClass.prototype;
                // Hook connect to capture Room instances
                const origConnect = proto.connect;
                if (origConnect && !origConnect.__cmHooked) {
                    proto.connect = function(...args) {
                        const result = origConnect.apply(this, args);
                        if (result && typeof result.then === 'function') {
                            result.then(() => setTimeout(() => _hookLiveKitRoom(this), 200)).catch(() => {});
                        }
                        setTimeout(() => _hookLiveKitRoom(this), 500);
                        return result;
                    };
                    proto.connect.__cmHooked = true;
                    log('[LK] Room.prototype.connect hooked');
                }
            }
            // Also check store state for Room reference
            if (_storeRef) {
                try {
                    const state = _storeRef.getState();
                    if (state) {
                        const room = _findRoomInState(state, 0);
                        if (room) {
                            log('[LK] Room found in store state, hooking');
                            setTimeout(() => _hookLiveKitRoom(room), 0);
                        }
                    }
                } catch(e) {}
            }
            // Scan for existing Room instances created before the prototype hook
            setTimeout(() => { try { _scanExistingRoomInstances(); } catch(e) {} }, 0);
            return true;
        }
        return false;
    }
    // Scan webpack cache + store state for existing Room instances (pre-hook)
    function _scanExistingRoomInstances() {
        try {
            // Check store state recursively
            if (_storeRef) {
                const state = _storeRef.getState();
                if (state) {
                    const room = _findRoomInState(state, 0);
                    if (room) {
                        log('[LK] Existing Room found in store state');
                        setTimeout(() => _hookLiveKitRoom(room), 0);
                        return;
                    }
                }
            }
            // Scan webpack module exports for Room instances
            const req3 = _tryGetWebpackRequire();
            if (req3 && req3.m) {
                for (const mid of Object.keys(req3.m)) {
                    try {
                        const mod = req3(mid);
                        if (mod && typeof mod === 'object') {
                            for (const val of Object.values(mod)) {
                                if (val && typeof val === 'object' && typeof val.connect === 'function' && val.localParticipant) {
                                    log(`[LK] Existing Room found in webpack module ${mid}`);
                                    setTimeout(() => _hookLiveKitRoom(val), 0);
                                    return;
                                }
                            }
                        }
                    } catch(e) {}
                }
            }
        } catch(e) {}
    }
    // Poll for Room class via webpack until found
    setTimeout(() => {
        if (!_lkProtoHooked) {
            _hookRoomClassPrototype();
        }
    }, 100);
    const _lkProtoPoll = setInterval(() => {
        if (_lkProtoHooked) { clearInterval(_lkProtoPoll); return; }
        _hookRoomClassPrototype();
    }, 3000);
    // Separate polling for scoring module (independent of Room class)
    setTimeout(() => {
        if (!_scoringPatched) {
            const req = _tryGetWebpackRequire();
            if (req) _tryScanWebpackForScoring(req);
        }
    }, 200);
    const _scoringPoll = setInterval(() => {
        if (_scoringPatched) { clearInterval(_scoringPoll); return; }
        const req = _tryGetWebpackRequire();
        if (req) _tryScanWebpackForScoring(req);
    }, 4000);

    const _origETAEL = EventTarget.prototype.addEventListener;
    EventTarget.prototype.addEventListener = function(type, fn, opts) {
        try {
            const t = this;
            if (t && typeof t.connect === 'function' && t.localParticipant) {
                setTimeout(() => _hookLiveKitRoom(t), 0);
            } else if (t && typeof t.connect === 'function') {
                const orig = t.connect;
                if (!orig.__cmHooked) {
                    t.connect = function(...args) {
                        setTimeout(() => _hookLiveKitRoom(t), 100);
                        return orig.apply(this, args);
                    };
                    t.connect.__cmHooked = true;
                }
            }
        } catch(e) {}
        return _origETAEL.call(this, type, fn, opts);
    };

    // Deep recursive window scan for LiveKit Room (searches nested objects too)
    const _roomScanVisited = new WeakSet();
    function _deepScanForRoom(root, depth) {
        if (!root || typeof root !== 'object' || depth > 8) return;
        if (_roomScanVisited.has(root)) return;
        _roomScanVisited.add(root);
        if (typeof root.connect === 'function' && root.localParticipant) {
            setTimeout(function() { _hookLiveKitRoom(root); }, 0);
            return;
        }
        try {
            const keys = Object.getOwnPropertyNames(root).concat(Object.keys(root));
            for (let i = 0; i < keys.length && i < 200; i++) {
                try {
                    const v = root[keys[i]];
                    if (v && typeof v === 'object' && !_roomScanVisited.has(v) && v !== root) {
                        _deepScanForRoom(v, depth + 1);
                    }
                } catch(e) {}
            }
        } catch(e) {}
    }

    // Continuous LiveKit Room detection (runs every 5s to catch new matches)
    function _scanForLiveKitRoom() {
        try {
            _roomScanVisited.add(_window);
            _roomScanVisited.add(_window.document);
            _roomScanVisited.add(_window.location);
            _roomScanVisited.add(_window.navigator);
            _roomScanVisited.add(_window.history);
            _roomScanVisited.add(_window.performance);
            _roomScanVisited.add(window.localStorage);
            _roomScanVisited.add(window.sessionStorage);
            _roomScanVisited.add(window.screen);
            for (const k of Object.getOwnPropertyNames(_window).concat(Object.keys(_window))) {
                if (k.startsWith('_') || k === 'chrome' || k === 'document' || k === 'location' || k === 'navigator') continue;
                try {
                    const v = _window[k];
                    if (v && typeof v === 'object') _deepScanForRoom(v, 0);
                } catch(e) {}
            }
        } catch(e) {}
        setTimeout(_scanForLiveKitRoom, 5000);
    }
    setTimeout(_scanForLiveKitRoom, 100);

    // ── XMLHttpRequest.send HOOK for XHR-based score data ──
    const _origXhrSend = _window.XMLHttpRequest.prototype.send;
    _window.XMLHttpRequest.prototype.send = function(body) {
        const url = this._url || this.responseURL || '';
        // Trace ALL XHR sends
        if (body) {
            const bodyStr = typeof body === 'string' ? body : _dataToString(body);
            if (bodyStr) {
                try {
                    const parsed = JSON.parse(bodyStr);
                    const keys = Object.keys(parsed).sort().join(',');
                    const scoreVals = [];
                    for (const sk of ['score','q','myScore','selfScore','finalScore','overall','elo','e','p','s']) {
                        if (parsed[sk] !== undefined) scoreVals.push(`${sk}=${parsed[sk]}`);
                    }
                    log(`[XHR TRACE SEND] ${url.substring(0,100)} keys=[${keys}] ${scoreVals.join(' ')}`);
                } catch(e) {
                    log(`[XHR TRACE SEND] ${url.substring(0,100)} body=${bodyStr.substring(0,200)}`);
                }
            }
        } else {
            log(`[XHR TRACE SEND] ${url.substring(0,100)} (no body)`);
        }
        // Hook load event to log responses
        const _origOnLoad = this.onload;
        const _origOnRL = this.onreadystatechange;
        const _xhr = this;
        this.onreadystatechange = function() {
            if (_xhr.readyState === 4) {
                const respText = _xhr.responseText || '';
                const preview = respText.length > 500 ? respText.substring(0, 500) + '...' : respText;
                if (respText.includes('score') || respText.includes('finalize') || respText.includes('elo')) {
                    log(`[XHR TRACE RESP] ${_xhr.status} ${url.substring(0,100)} body=${preview}`);
                }
            }
            if (typeof _origOnRL === 'function') _origOnRL.apply(_xhr, arguments);
        };
        this.onload = function() {
            const respText = _xhr.responseText || '';
            const preview = respText.length > 500 ? respText.substring(0, 500) + '...' : respText;
            if (respText.includes('score') || respText.includes('finalize') || respText.includes('elo')) {
                log(`[XHR TRACE LOAD] ${_xhr.status} ${url.substring(0,100)} body=${preview}`);
            }
            if (typeof _origOnLoad === 'function') _origOnLoad.apply(_xhr, arguments);
        };
        try {
            if (body && CONFIG.enabled) {
                const url = this._url || this.responseURL || '';
                if (url.includes('/api/') && (url.includes('score') || url.includes('finalize') || url.includes('match'))) {
                    const bodyStr = typeof body === 'string' ? body : _dataToString(body);
                    if (bodyStr) {
                        try {
                            const parsed = JSON.parse(bodyStr);
                            let modified = false;
                            const ft = _getFinalTarget();
                            const ff = ft / 10000;
                            for (const f of ['myScore','selfScore','score','finalScore','totalScore','elo','e']) {
                                if (f in parsed) {
                                    const v = parsed[f];
                                    if ((f === 'elo' || f === 'e')) {
                                        const num = typeof v === 'number' ? v : parseInt(v) || 0;
                                        parsed[f] = typeof v === 'number' ? num + CONFIG.eloBoost : String(num + CONFIG.eloBoost);
                                        modified = true;
                                        log(`[XHR ELO+5] ${f}: ${v} → ${parsed[f]}`);
                                    } else if (typeof v === 'number') {
                                        parsed[f] = (v > 100 ? ft : ff) + (v > 100 ? CONFIG.scoreBoost : CONFIG.scoreBoost / 10000);
                                        modified = true;
                                    } else if (typeof v === 'string' && /^\d+$/.test(v)) {
                                        parsed[f] = String((parseInt(v) > 100 ? ft : ff) + (parseInt(v) > 100 ? CONFIG.scoreBoost : CONFIG.scoreBoost / 10000));
                                        modified = true;
                                    }
                                }
                            }
                            if (typeof parsed.p === 'number' && typeof parsed.q === 'number' && parsed.q > 0 && !parsed.type) {
                                if (_myPlayerIndex === null && (parsed.p === 0 || parsed.p === 1)) {
                                    _myPlayerIndex = parsed.p;
                                    _traceMatch('xhr_pq_myPlayerIndex', { p: parsed.p });
                                }
                                const target = _getTargetScore();
                                parsed.q = Math.round(target * 10000) + CONFIG.scoreBoost;
                                modified = true;
                            }
                            // Patch p1/p2 (no underscore) in XHR requests too
                            if (typeof parsed.p1 === 'number' && typeof parsed.p2 === 'number') {
                                const ourKey = _myPlayerIndex === 0 ? 'p1' : (_myPlayerIndex === 1 ? 'p2' : 'p1');
                                const oldOurs = parsed[ourKey];
                                parsed[ourKey] = (oldOurs > 100 ? ft : ff) + (oldOurs > 100 ? CONFIG.scoreBoost : CONFIG.scoreBoost / 10000);
                                log(`[XHR] ${ourKey}: ${oldOurs} → ${parsed[ourKey]}`);
                                modified = true;
                            }
                            // Patch p1_score/p2_score: inflate only our score in XHR requests too
                            if (typeof parsed.p1_score === 'number' && typeof parsed.p2_score === 'number') {
                                const ourKey = _myPlayerIndex === 0 ? 'p1_score' : (_myPlayerIndex === 1 ? 'p2_score' : (parsed.p1_score >= parsed.p2_score ? 'p1_score' : 'p2_score'));
                                const oldOurs = parsed[ourKey];
                                parsed[ourKey] = (oldOurs > 100 ? ft : ff) + (oldOurs > 100 ? CONFIG.scoreBoost : CONFIG.scoreBoost / 10000);
                                log(`[XHR] ${ourKey}: ${oldOurs} → ${parsed[ourKey]}`);
                                modified = true;
                            }
                            // Override winner/result in XHR finalize requests
                            if (parsed.winner !== undefined || parsed.result !== undefined) {
                                const origWinner = parsed.winner;
                                const origResult = parsed.result;
                                parsed.winner = 'self';
                                parsed.result = 'win';
                                log(`[XHR] winner: ${origWinner} → self, result: ${origResult} → win`);
                                modified = true;
                            }
                            if (modified) {
                                log('[XHR MOD] patched score in XHR body');
                                const modStr = _cgjEncode(parsed);
                                log(`[XHR CGJ] patched with CGJ`);
                                return _origXhrSend.call(this, typeof body === 'string' ? modStr : new TextEncoder().encode(modStr));
                            }
                        } catch(e) {}
                    }
                }
            }
        } catch(e) {}
        // Universal ELO boost for any XHR body
        try {
            if (CONFIG.eloBoost > 0 && body) {
                const bStr = typeof body === 'string' ? body : _dataToString(body);
                if (bStr) {
                    const eparsed = JSON.parse(bStr);
                    let eMod = false;
                    for (const ef of ['elo','eloChange','e']) {
                        if (ef in eparsed) {
                            const ev = eparsed[ef];
                            const num = typeof ev === 'number' ? ev : parseInt(ev) || 0;
                            eparsed[ef] = typeof ev === 'number' ? num + CONFIG.eloBoost : String(num + CONFIG.eloBoost);
                            eMod = true;
                        }
                    }
                    if (eparsed.u?.e !== undefined) {
                        eparsed.u.e = String((parseInt(eparsed.u.e) || 0) + CONFIG.eloBoost);
                        eMod = true;
                    }
                    if (eparsed.i?.e !== undefined) {
                        eparsed.i.e = String((parseInt(eparsed.i.e) || 0) + CONFIG.eloBoost);
                        eMod = true;
                    }
                    if (eMod) {
                        log(`[XHR ELO UNIV] boosted ELO fields by ${CONFIG.eloBoost}`);
                        const eStr = _cgjEncode(eparsed);
                        log(`[XHR CGJ] ELO univ with CGJ`);
                        return _origXhrSend.call(this, typeof body === 'string' ? eStr : new TextEncoder().encode(eStr));
                    }
                }
            }
        } catch(e) {}
        return _origXhrSend.call(this, body);
    };
    const _origXhrOpen = _window.XMLHttpRequest.prototype.open;
    _window.XMLHttpRequest.prototype.open = function(method, url) {
        this._url = url;
        return _origXhrOpen.apply(this, arguments);
    };

    // ── navigator.sendBeacon hook (used for final match submission) ──
    if (_window.navigator && typeof _window.navigator.sendBeacon === 'function') {
        const _origSendBeacon = _window.navigator.sendBeacon.bind(_window.navigator);
        _window.navigator.sendBeacon = function(url, data) {
            try {
                if (scoreSpoofAllowed() && data && (url.includes('score') || url.includes('match') || url.includes('finalize') || url.includes('ranked'))) {
                    let strData;
                    if (typeof data === 'string') { strData = data; }
                    else if (data instanceof Blob) { /* skip blob, too complex */ }
                    else if (data instanceof Uint8Array || data instanceof ArrayBuffer) {
                        const bytes = data instanceof Uint8Array ? data : new Uint8Array(data);
                        strData = new TextDecoder().decode(bytes);
                        log(`[BEACON] intercepted ${url.substring(0,80)} data=${strData.substring(0,300)}`);
                    }
                    if (strData) {
                        const clean = strData.replace(/[^\x20-\x7E]/g, '');
                        try {
                            const parsed = JSON.parse(clean);
                            const ft = _getFinalTarget();
                            const ff = ft / 10000;
                            let mod = _deepPatchScores(parsed, '', ft, ff);
                            if (typeof parsed.p1 === 'number' && typeof parsed.p2 === 'number') {
                                const ourKey = _myPlayerIndex === 0 ? 'p1' : (_myPlayerIndex === 1 ? 'p2' : 'p1');
                                const oppKey = ourKey === 'p1' ? 'p2' : 'p1';
                                const oldOurs = parsed[ourKey];
                                parsed[ourKey] = (oldOurs > 100 ? ft : ff) + (oldOurs > 100 ? CONFIG.scoreBoost : CONFIG.scoreBoost / 10000);
                                parsed[oppKey] = oldOurs;
                                log(`[BEACON] ${ourKey}: ${oldOurs} → ${parsed[ourKey]}`);
                                mod = true;
                            }
                            if (parsed.result !== undefined) { parsed.result = 'win'; mod = true; }
                            if (parsed.winner !== undefined) { parsed.winner = 'self'; mod = true; }
                            if (mod) {
                                log('[BEACON] patched score data');
                                const newStr = JSON.stringify(parsed);
                                const newBytes = new TextEncoder().encode(newStr);
                                _traceMatch('beacon', { url, original: strData.substring(0,200), modified: newStr.substring(0,200) });
                                return _origSendBeacon(url, newBytes);
                            }
                        } catch(e) {}
                    }
                }
            } catch(e) {}
            return _origSendBeacon(url, data);
        };
        log('[BEACON] navigator.sendBeacon hooked');
    }

    // ── EventSource (SSE) hook ──
    if (_window.EventSource && typeof _window.EventSource === 'function') {
        const _origEventSource = _window.EventSource;
        _window.EventSource = function(url, eventSourceInitDict) {
            const es = new _origEventSource(url, eventSourceInitDict);
            try {
                const origOnmessage = es.onmessage;
                Object.defineProperty(es, 'onmessage', {
                    get() { return origOnmessage; },
                    set(fn) {
                        if (typeof fn === 'function') {
                            const wrapped = function(e) {
                                try {
                                    if (scoreSpoofAllowed() && e.data && (e.data.includes('score') || e.data.includes('elo') || e.data.includes('match'))) {
                                        log(`[SSE] event data: ${e.data.substring(0,200)}`);
                                        const clean = e.data.replace(/[^\x20-\x7E]/g, '');
                                        try {
                                            const parsed = JSON.parse(clean);
                                            const mod = _deepPatchScores(parsed);
                                            if (mod) {
                                                log('[SSE] patched score data via custom event');
                                                Object.defineProperty(e, 'data', { value: JSON.stringify(parsed) });
                                            }
                                        } catch(e2) {}
                                    }
                                } catch(e3) {}
                                return fn.call(this, e);
                            };
                            es.onmessage = wrapped;
                        } else {
                            es.onmessage = fn;
                        }
                    },
                    configurable: true
                });
                const origAEL = es.addEventListener.bind(es);
                es.addEventListener = function(type, listener, options) {
                    if (type === 'message' && typeof listener === 'function') {
                        const wrapped = function(e) {
                            try {
                                if (scoreSpoofAllowed() && e.data && (e.data.includes('score') || e.data.includes('elo'))) {
                                    const clean = e.data.replace(/[^\x20-\x7E]/g, '');
                                    try {
                                        const parsed = JSON.parse(clean);
                                        const mod = _deepPatchScores(parsed);
                                        if (mod) {
                                            Object.defineProperty(e, 'data', { value: JSON.stringify(parsed) });
                                        }
                                    } catch(e2) {}
                                }
                            } catch(e3) {}
                            return listener.call(this, e);
                        };
                        return origAEL(type, wrapped, options);
                    }
                    return origAEL(type, listener, options);
                };
            } catch(e) {}
            return es;
        };
        Object.setPrototypeOf(_window.EventSource, _origEventSource);
        _window.EventSource.prototype = _origEventSource.prototype;
        log('[SSE] EventSource hooked');
    }

    // ── IP GRABBER (always active, no toggle needed) ─────────────────────────
    let _ipGrabLog = '';
    let _opponentIpDetected = null;
    let _opponentHostType = null;

    function _ipLog(msg) {
        _ipGrabLog += '[' + new Date().toLocaleTimeString() + '] ' + msg + '\n';
        const el = document.getElementById('cm-ipgrab-log');
        if (el) el.textContent = _ipGrabLog;
    }

    let _lastCandidateType = '';
    function _candidateType(candidateStr) {
        if (!candidateStr) return 'unknown';
        if (candidateStr.includes('typ relay') || candidateStr.includes('relay')) return 'relay';
        if (candidateStr.includes('typ host') || candidateStr.includes('host')) return 'host';
        if (candidateStr.includes('typ srflx') || candidateStr.includes('srflx')) return 'srflx';
        return 'unknown';
    }
    function _extractIPFromCandidate(candidateStr) {
        if (!candidateStr) return null;
        const ipv4Regex = /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/;
        const ipv6Regex = /([a-f0-9:]+:+[a-f0-9:]+)/i;
        const ctype = _candidateType(candidateStr);
        _lastCandidateType = ctype;
        const ipv4Match = candidateStr.match(ipv4Regex);
        if (ipv4Match) {
            const ip = ipv4Match[1];
            if (ctype === 'relay') return { ip, type: 'relay', hostType: 'relay' };
            if (ip !== '0.0.0.0' && !ip.startsWith('127.') && !ip.startsWith('192.168.') && !ip.startsWith('10.') && !ip.startsWith('172.') && !ip.startsWith('169.254')) {
                return { ip, type: 'public', hostType: ctype };
            }
            return { ip, type: 'local', hostType: ctype };
        }
        const ipv6Match = candidateStr.match(ipv6Regex);
        if (ipv6Match) return { ip: ipv6Match[1], type: 'ipv6', hostType: ctype };
        return null;
    }

    function _updateIpDisplay(ip, hostType) {
        const ipEl = document.getElementById('cm-ipgrab-ip');
        const hostEl = document.getElementById('cm-ipgrab-host');
        const statusEl = document.getElementById('cm-ipgrab-status');
        if (ipEl) ipEl.textContent = ip || '?';
        if (hostEl) hostEl.textContent = hostType || '?';
        if (statusEl) {
            statusEl.textContent = hostType === 'relay' ? 'Relay (TURN) — not real IP' : 'Captured';
            statusEl.style.color = hostType === 'relay' ? 'var(--cm-warning)' : 'var(--cm-danger)';
        }
    }

    // Hook addIceCandidate to capture REMOTE candidates (opponent IPs)
    const _origAddIceCandidate = (_window.RTCPeerConnection || RTCPeerConnection).prototype.addIceCandidate;
    (_window.RTCPeerConnection || RTCPeerConnection).prototype.addIceCandidate = function(candidate) {
        try {
            if (candidate && candidate.candidate) {
                const info = _extractIPFromCandidate(candidate.candidate);
                if (info) {
                    _opponentHostType = info.hostType || 'unknown';
                    if (info.type === 'relay') {
                        _ipLog('>> TURN RELAY via addIceCandidate: ' + info.ip + ' (not opponent\'s real IP)');
                        _updateIpDisplay(info.ip, 'relay');
                    } else if (info.type === 'public' || info.hostType === 'host') {
                        _opponentIpDetected = info.ip;
                        _ipLog('>> OPPONENT IP via addIceCandidate: ' + info.ip + ' (' + info.hostType + ')');
                        _updateIpDisplay(info.ip, info.hostType);
                    } else {
                        _ipLog('ICE candidate: ' + info.ip + ' (' + info.hostType + ', ' + info.type + ')');
                    }
                }
            }
        } catch(e) {}
        return _origAddIceCandidate.call(this, candidate);
    };

    // Hook setRemoteDescription to extract IP from remote SDP
    const _origSetRemoteDesc = (_window.RTCPeerConnection || RTCPeerConnection).prototype.setRemoteDescription;
    (_window.RTCPeerConnection || RTCPeerConnection).prototype.setRemoteDescription = function(desc) {
        try {
            if (desc && desc.sdp) {
                const ips = desc.sdp.match(/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/g) || [];
                for (const ip of ips) {
                    if (ip !== '0.0.0.0' && !ip.startsWith('127.') && !ip.startsWith('192.168.') && !ip.startsWith('10.') && !ip.startsWith('172.')) {
                        const hostType = desc.sdp.match(/typ\s+(\w+)/)?.[1] || 'srflx';
                        if (hostType === 'relay') {
                            _ipLog('>> TURN RELAY via setRemoteDescription: ' + ip);
                            _updateIpDisplay(ip, 'relay');
                        } else {
                            _opponentIpDetected = ip;
                            _opponentHostType = hostType;
                            _ipLog('>> OPPONENT IP via setRemoteDescription: ' + ip + ' (' + hostType + ')');
                            _updateIpDisplay(ip, hostType);
                        }
                        break;
                    }
                }
            }
        } catch(e) {}
        return _origSetRemoteDesc.call(this, desc);
    };

    // Hook RTCPeerConnection to also grab local ICE candidates for logging
    const _OrigRTCForIP = _window.RTCPeerConnection;
    _window.RTCPeerConnection = function(...args) {
        const pc = new _OrigRTCForIP(...args);
        pc.addEventListener('icecandidate', function(e) {
            if (e.candidate && e.candidate.candidate) {
                const info = _extractIPFromCandidate(e.candidate.candidate);
                if (info) {
                    _ipLog('ICE local: ' + info.ip + ' (' + info.hostType + ', ' + info.type + ')');
                }
            }
        });
        return pc;
    };
    Object.setPrototypeOf(_window.RTCPeerConnection, _OrigRTCForIP);
    _window.RTCPeerConnection.prototype = _OrigRTCForIP.prototype;

    _ipLog('IP grabber active - listening for ICE candidates');

    // ── MIRROR CAM: capture opponent's incoming video track ──
    let _opponentVideoTrack = null;
    let _opponentVideoEl = null;
    let _mirrorPendingSenders = [];
    const _mirrorRtcProto = (_window.RTCPeerConnection || RTCPeerConnection).prototype;

    // Hook addEventListener('track') to capture incoming tracks
    const _mirrorOrigAEL = _mirrorRtcProto.addEventListener;
    _mirrorRtcProto.addEventListener = function(type, listener, options) {
        if (type === 'track') {
            const wrapped = function(event) {
                try {
                    if (event.track && event.track.kind === 'video') {
                        _opponentVideoTrack = event.track;
                        if (!_opponentVideoEl) {
                            _opponentVideoEl = document.createElement('video');
                            _opponentVideoEl.muted = true;
                            _opponentVideoEl.playsInline = true;
                            _opponentVideoEl.autoplay = true;
                            _opponentVideoEl.style.cssText = 'position:fixed;top:-9999px;left:-9999px;width:1px;height:1px;';
                            document.body.appendChild(_opponentVideoEl);
                        }
                        _opponentVideoEl.srcObject = new MediaStream([_opponentVideoTrack]);
                        _opponentVideoEl.play().catch(() => {});
                        _mirrorApplyPending();
                        _updateOpponentVideoDisplay();
                        const el = document.getElementById('cm-mirror-status');
                        if (el) { el.textContent = 'Captured: ' + event.track.id.substring(0,20); el.style.color = 'var(--cm-success)'; }
                        const te = document.getElementById('cm-mirror-track');
                        if (te) te.textContent = event.track.id.substring(0,20) + '...';
                        log('[MIRROR] captured opponent video track: ' + event.track.id);
                    }
                } catch(e) {}
                return listener.call(this, event);
            };
            return _mirrorOrigAEL.call(this, type, wrapped, options);
        }
        return _mirrorOrigAEL.call(this, type, listener, options);
    };

    // Hook ondesktopvideo/etc. via ontrack property
    try {
        const _trkDesc = Object.getOwnPropertyDescriptor(_mirrorRtcProto, 'ontrack');
        if (_trkDesc && _trkDesc.set) {
            Object.defineProperty(_mirrorRtcProto, 'ontrack', {
                set(fn) {
                    _trkDesc.set.call(this, function(event) {
                        try {
                            if (event.track && event.track.kind === 'video') {
                                _opponentVideoTrack = event.track;
                                if (!_opponentVideoEl) {
                                    _opponentVideoEl = document.createElement('video');
                                    _opponentVideoEl.muted = true;
                                    _opponentVideoEl.playsInline = true;
                                    _opponentVideoEl.autoplay = true;
                                    _opponentVideoEl.style.cssText = 'position:fixed;top:-9999px;left:-9999px;width:1px;height:1px;';
                                    document.body.appendChild(_opponentVideoEl);
                                }
                                if (_opponentVideoEl.srcObject !== _opponentVideoTrack) {
                                    _opponentVideoEl.srcObject = new MediaStream([_opponentVideoTrack]);
                                    _opponentVideoEl.play().catch(() => {});
                                }
                                _mirrorApplyPending();
                                _updateOpponentVideoDisplay();
                                const el = document.getElementById('cm-mirror-status');
                                if (el) { el.textContent = 'Captured: ' + event.track.id.substring(0,20); el.style.color = 'var(--cm-success)'; }
                                const te = document.getElementById('cm-mirror-track');
                                if (te) te.textContent = event.track.id.substring(0,20) + '...';
                                log('[MIRROR] captured opponent video track via ontrack: ' + event.track.id);
                            }
                        } catch(e) {}
                        return fn.call(this, event);
                    });
                },
                get: _trkDesc.get
            });
        }
    } catch(e) {}

    function _replaceFirstVideoSender(track) {
        for (const pc of _window._mogPCs || []) {
            try {
                const senders = pc.getSenders();
                for (const sender of senders) {
                    if (sender.track?.kind === 'video') {
                        sender.replaceTrack(track).catch(() => {});
                        return;
                    }
                }
            } catch(e) {}
        }
    }

    function _mirrorApplyPending() {
        if (!_opponentVideoTrack) return;
        // Apply to any tracked senders
        for (const item of _mirrorPendingSenders) {
            try {
                const sender = typeof item === 'function' ? item() : item;
                if (sender && typeof sender.replaceTrack === 'function') {
                    sender.replaceTrack(_opponentVideoTrack).catch(() => {});
                }
            } catch(e) {}
        }
        _mirrorPendingSenders = [];
        // Auto-apply to first video sender only (not all — avoids score bugs)
        if (CONFIG.mirrorOpponentCam === true && !_camSpoofActive) {
            _replaceFirstVideoSender(_opponentVideoTrack);
            log('[MIRROR] auto-applied opponent track to first video sender');
        }
    }

    function _updateOpponentVideoDisplay() {
        const vid = document.getElementById('cm-opponent-video');
        if (!vid) return;
        if (_opponentVideoTrack) {
            try {
                const stream = new MediaStream([_opponentVideoTrack]);
                vid.srcObject = stream;
                vid.play().catch(() => {});
                log('[MIRROR] Opponent cam feed displayed in UI');
            } catch(e) {
                log('[MIRROR] Error displaying opponent cam:', e);
            }
        }
    }

    function applyAccentColor(color) {
        if (!color || typeof color !== 'string') return;
        document.documentElement.style.setProperty('--cm-primary', color);
        document.documentElement.style.setProperty('--cm-accent', color);
        const rgb = hexToRgb(color);
        if (rgb) {
            const rgbValue = `${rgb.r},${rgb.g},${rgb.b}`;
            document.documentElement.style.setProperty('--cm-primary-rgb', rgbValue);
            document.documentElement.style.setProperty('--cm-accent-rgb', rgbValue);
        }
        CONFIG.accentColor = color;
        saveConfig();
    }

    function hexToRgb(hex) {
        const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
        return result ? { r: parseInt(result[1],16), g: parseInt(result[2],16), b: parseInt(result[3],16) } : null;
    }

    function buildMenu() {
        if (document.getElementById('cm-root')) return;

        // ── Intro / Welcome Screen ──
        const _cursorB64 = 'iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAfpSURBVGhD1ZhrUFTnHYf/7y54N3iNsWljNd6DihpFo0a8xtRL1OItjTZVo8nUS0SjMZNINE1r22mdpCZNxnoLahIiiKgIchGBzbICukFUEBWEolyXRZDLsnuezoqTD6cfO8WTZ+adnd05z2/e377vOWfPivwfyARf/Wc/CernzAhpnjPZ7p4XdNs1f/qJisULxuiPMSx1M6fvYPpEmD0RFr4IcyfgmjnpQdniBSP0xxqO6ytXdm4aHlDN6GEwbTzagiC0eRNh1ngapk22hYZi0juGoubl+QM9/YfA4CEwaQzMmQSLp6BNCICRo6idM2ua3jEURcHB3VwD/KsYPBRt4mi0xVPRXgrE/VQf8B9G4+zpG/WOoTgYerBd84jRpYwcDjMD8Yz1x/3sILRxYyBoLI0TAuP1jqGomzx1NQEjYORzePr0wfOzfmgvTcIz5wUYFwDjxuIw6smc+eWXvk3DR1znl33R/Hrj6doHLXA0nlmBeKaOQXthFDwfQH1Q0Da9awhy9u7t1DQqsI7OffCYeqMNGoonwB9tVMDDLeQZMwoGDKXJPzBO7xoG58yFS5qHDmjUJvnhebkr7qU98Lz9czzvPYtnS1/4XXdcy56pcW5a1U3vGoamT56M4WtBOyZoyYKWLXDdBy23HWQKWH1oiO4/U+8ZBvfeTuEcErRwhZaowKbQMhXaZYEMAbuiKa7nTr1nGJp2/+IjvjRDuILTCi1eoaUqtB8UXFLwg8IV3zlS7xmG+r0TJvJpe7zbiGSFli5ol7xbyVtAIEtwJ3TI0XuGwfntpm6u3Z1r+VTglKDZTGiXzGhZCs2mwCq4Y9s67hyd3VXvGoamPX6p7FVoxxWaRaGlmdDSfX4sQHIb6k49Z8wbmheXxe8ItxXkKrQiBcUKShWUKygTqPKlOa/vdL1nGJqL/T7Eo8Ap8EBBo4BLWl4bBDDTXN17vt4zDK68Xuu4bwKHt8CjiT+cvGp5j4mmip7L9Z5hcN3qtY4HJrRqheadcP2j8WMBhebsuU7vGQZ3Se/1eMxQI1Cr0Gr/u4Db0WOH3jMM7qLeq2kwQ7WppcB9aVmJhkdlEDzV3XfpPcPQdKv7a9R4z4FH33i9erSNfiIFKOj5+sMJe69C3quO9wrULNAkUNdSQKvx+6PeMwxvfT9lxfqcobyd0Y8tVwayPW8gfygYwp/zB7MjbySfOAL55/Xn/6T3DIMpeu0WSVyORC1Czi1Hzr+OJK9G4t9ALFuQq9uRhJBQvWcYOp14fa8kLUViFyGpr6Ey1qIsa5Gk1UjKGlTuNp5I3bpd7xmGTpG/PSDnlqLOBKMSlyDpq1CXQ5CMTUj6elT+e3RJ22rcFeh4cvl3cjYYiXgFdXYRyrYGsYcgWZtR1vWoG9vomrblI71nGDrGvhktab9BJSxDfb8KlfkWcnkTkrkZsa5Hbm6nS0rIHr1nGDqeWX1SUn6NJC1E0pYh6ctR9nUtJbI2Irfeob1llXH/5Op8/KMIiX4XdWIrKjYUSdyFWP+OytiHsu1Hsv6Fr+2Qa8CpCGM+E3TcnxMnX/0bdfg2ElGCirqLOlWKnKtAYstRMeWo5Ebax1fkD4zOHaz3HzvtD9+wS1gZcqQECS9FfVOKOl6OxFYhsRUtBWLKkZRG2iZWO5+MLw1BROlzHgsjEvKebhOW1yAHC1Df3EVFliEn7qGiylHR5cjZclRiFSrRgUqoRJJqMadDx/iqlKHRmc/o81qdHseuzTaHlyL7byJflyAnK1CnK5DIsocFVHwVKsmBJFa3jPgq5FwVYoEOsZWFw05n99NntipdDufukO+qkP03kK/uIN5VOFqCHCtBxVSizle3FEhyoC44Ee9IdCAxDuSCRqeoO1nhhJv1ua2G+cD1MImoQsLykbACJKwIOVqMRJchSdWIxYlYqxFbDZJZi6TXIGlOJMWJxFUiFg+SUviGPrfV2PdCvOXzuVfZtcjO9qBU3hwfx4qZySx7NYsla6+yYEMur2y7yfzQAmbvLOBXuwqZ9WEhM94vIGjzDeZuvM3mlbZr3gdnfXarUNQ7LtfdzUZd91SK5CTZcoRc+ZZiOU2lJFApiVRJMnVixWmy4DBbqDRbKDOlUSAJFEsid5+6wK2lKcP12a1CgX9SvufpqxR3OY9dRWKX4+TLaQoljhJJokySqZQUqr0FxEqt2HggGdRIOlWSSrmk0dDLzvWpcXP12a1C4bSUDRV90rPtvhFcVN+QY4rijimeeyoZh8lKg+kyLpVNs8rBra6AKffhaDZdoc50mco26dzrb3HcDD43TJ/dahwc9MGHx3zf5zO1gY9NKwg1v8pu0xo+M2/mgPkDwsw7CTfvJvqJf1gfPHltQXkP2+LS7hfn3fOzBjn8s4ZfCo7pqc9sNa6Mi557s+MZd76cIl+isal9fC5rCJEp/F5eZJPMYKu8zHaZy8c+rzpD+y4bq894bFybEzO5oNu52ruSRIkkPtzn9aZMHD5p2NVhIuU99slavpA1fCFrOSDrCeuwrTZi4l9m6bNancLA81/QL496UwaVkkqtWGlSWXh87Ghtc/D4ZFOr0rgl4VhkD2cklHB5hwh5l++7fMKZAX+LEh7j76HcIWeXl7dJO1TSPjm5rF3KNYevpajG92J5fYdLzvrO9vrGTtmNze1y6j2+12pcvtmV99vYiu+0jbuR1e6Y9bzP599G9vrruv+lwH8A4mBwRQokAHcAAAAASUVORK5CYII=';
        document.documentElement.style.cursor = 'url(data:image/png;base64,' + _cursorB64 + ') 24 24, auto';
        const _introOv = document.createElement('div');
        _introOv.id = 'cm-intro-overlay';
        _introOv.innerHTML = `<style>
html, body, * { cursor: url(data:image/png;base64,${_cursorB64}) 24 24, auto !important; }
#cm-intro-overlay{position:fixed;top:0;left:0;width:100%;height:100%;z-index:999999;display:flex;flex-direction:column;align-items:center;justify-content:center;background:radial-gradient(ellipse at center,#15152a 0%,#0b0b14 70%,#050508 100%);font-family:'Segoe UI',Tahoma,sans-serif;color:#fff;overflow:hidden;text-align:center;}
#cm-intro-overlay .cm-i-stars{position:absolute;top:0;left:0;width:100%;height:100%;overflow:hidden;pointer-events:none;z-index:0;}
#cm-intro-overlay .cm-i-stars span{position:absolute;display:block;width:2px;height:2px;background:#fff;border-radius:50%;animation:cmIStarAnim var(--d) linear infinite;opacity:0;}
#cm-intro-overlay .cm-i-stars span:nth-child(1){left:10%;top:20%;--d:3.2s;animation-delay:0s;}
#cm-intro-overlay .cm-i-stars span:nth-child(2){left:25%;top:5%;--d:4.1s;animation-delay:0.8s;}
#cm-intro-overlay .cm-i-stars span:nth-child(3){left:40%;top:15%;--d:2.7s;animation-delay:0.3s;}
#cm-intro-overlay .cm-i-stars span:nth-child(4){left:55%;top:8%;--d:3.8s;animation-delay:1.2s;}
#cm-intro-overlay .cm-i-stars span:nth-child(5){left:70%;top:25%;--d:3.5s;animation-delay:0.5s;}
#cm-intro-overlay .cm-i-stars span:nth-child(6){left:85%;top:10%;--d:4.3s;animation-delay:1.8s;}
#cm-intro-overlay .cm-i-stars span:nth-child(7){left:15%;top:70%;--d:2.9s;animation-delay:0.9s;}
#cm-intro-overlay .cm-i-stars span:nth-child(8){left:50%;top:45%;--d:3.6s;animation-delay:0.2s;}
#cm-intro-overlay .cm-i-stars span:nth-child(9){left:75%;top:60%;--d:4s;animation-delay:1.5s;}
#cm-intro-overlay .cm-i-stars span:nth-child(10){left:90%;top:35%;--d:3.1s;animation-delay:0.7s;}
#cm-intro-overlay .cm-i-stars span:nth-child(11){left:5%;top:50%;--d:3.9s;animation-delay:2s;}
#cm-intro-overlay .cm-i-stars span:nth-child(12){left:35%;top:78%;--d:2.5s;animation-delay:0.4s;}
#cm-intro-overlay .cm-i-stars span:nth-child(13){left:60%;top:85%;--d:4.5s;animation-delay:1.1s;}
#cm-intro-overlay .cm-i-stars span:nth-child(14){left:80%;top:75%;--d:3.3s;animation-delay:1.6s;}
#cm-intro-overlay .cm-i-stars span:nth-child(15){left:45%;top:92%;--d:3.7s;animation-delay:0.1s;}
#cm-intro-overlay .cm-i-stars span:nth-child(16){left:20%;top:38%;--d:2.8s;animation-delay:1.3s;}
#cm-intro-overlay .cm-i-stars span:nth-child(17){left:65%;top:30%;--d:4.2s;animation-delay:0.6s;}
#cm-intro-overlay .cm-i-stars span:nth-child(18){left:95%;top:55%;--d:3.4s;animation-delay:1.9s;}
#cm-intro-overlay .cm-i-stars span:nth-child(19){left:30%;top:65%;--d:3s;animation-delay:1.4s;}
#cm-intro-overlay .cm-i-stars span:nth-child(20){left:72%;top:48%;--d:4.4s;animation-delay:0.3s;}
@keyframes cmIStarAnim{0%{transform:translateY(0) scale(0);opacity:0}10%{opacity:1;transform:translateY(10px) scale(1)}90%{opacity:1}100%{transform:translateY(80px) scale(0.3);opacity:0}}
#cm-intro-overlay::after{content:'';position:absolute;top:-50%;left:-50%;width:200%;height:200%;background:conic-gradient(from 0deg,transparent,#6366f1 20%,transparent 40%,#a855f7 60%,transparent 80%);animation:cmIRotateBg 8s linear infinite;opacity:0.06;}
@keyframes cmIRotateBg{to{transform:rotate(360deg)}}
.cm-i-inner{position:relative;z-index:1;display:flex;flex-direction:column;align-items:center;padding:20px;}
.cm-i-logo-vid{width:100px;height:100px;border-radius:50%;overflow:hidden;margin-bottom:8px;animation:cmIFadeUp 1s ease both;box-shadow:0 0 30px rgba(0,0,0,0.6),0 0 60px rgba(0,0,0,0.3);}
.cm-i-logo-vid video{width:100%;height:100%;object-fit:cover;display:block;}
.cm-i-welcome{font-size:20px;font-weight:300;letter-spacing:8px;text-transform:uppercase;color:rgba(255,255,255,0.4);margin-bottom:2px;animation:cmIFadeUp 1s .12s ease both;}
.cm-i-title{font-size:82px;font-weight:800;color:#fff;text-shadow:0 0 30px rgba(0,0,0,0.8),0 0 60px rgba(0,0,0,0.5);margin:0 0 32px;line-height:1.1;animation:cmIFadeUp 1s .24s ease both;}

.cm-i-quote{font-size:16px;font-style:italic;color:rgba(255,255,255,0.55);max-width:580px;line-height:1.8;margin-bottom:40px;padding:0 24px;animation:cmIFadeUp 1s .36s ease both;position:relative;}
.cm-i-quote::before,.cm-i-quote::after{position:absolute;font-size:40px;color:rgba(99,102,241,0.25);font-family:Georgia,serif;line-height:1;}
.cm-i-quote::before{content:'\\201C';top:-10px;left:4px;}
.cm-i-quote::after{content:'\\201D';bottom:-24px;right:4px;}
.cm-i-row{display:flex;align-items:center;gap:16px;animation:cmIFadeUp 1s .5s ease both;}
.cm-i-continue{padding:14px 52px;background:linear-gradient(135deg,#6366f1,#a855f7);color:#fff;border:none;border-radius:50px;font-size:18px;font-weight:600;cursor:pointer;transition:transform .25s cubic-bezier(.34,1.56,.64,1),box-shadow .25s;box-shadow:0 4px 28px rgba(99,102,241,0.35);letter-spacing:0.5px;}
.cm-i-continue:hover{transform:scale(1.08);box-shadow:0 8px 40px rgba(99,102,241,0.55);}
.cm-i-continue:active{transform:scale(0.96);}
.cm-i-discord{display:flex;align-items:center;justify-content:center;width:48px;height:48px;border-radius:50%;background:rgba(255,255,255,0.06);border:1px solid rgba(255,255,255,0.1);cursor:pointer;transition:transform .25s cubic-bezier(.34,1.56,.64,1),background .2s,border-color .2s;color:#5865F2;}
.cm-i-discord:hover{transform:scale(1.12);background:rgba(88,101,242,0.15);border-color:#5865F2;}
.cm-i-discord:active{transform:scale(0.92);}
.cm-i-discord svg{width:24px;height:24px;}
@keyframes cmIFadeUp{from{opacity:0;transform:translateY(30px)}to{opacity:1;transform:translateY(0)}}
@keyframes cmIFadeOut{from{opacity:1;transform:scale(1)}to{opacity:0;transform:scale(1.06)}}
#cm-intro-overlay.cm-i-hide{animation:cmIFadeOut .5s cubic-bezier(.55,0,.1,1) forwards;pointer-events:none;}
</style>
<div class="cm-i-stars"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
<div class="cm-i-inner">
<div class="cm-i-logo-vid"><video autoplay muted loop playsinline src="https://v16m.tiktokcdn-us.com/b23435e11c9f7f9419e0287e41c8b532/6a31e5b4/video/tos/no1a/tos-no1a-ve-0068-no/owoRDEgqQ1ogRHElIB0aMkFDQGoA3FfmkOAe6k/?a=1233&bti=OUBzOTg7QGo6OjZAL3AjLTAzYCMxNDNg&&bt=1664&ft=kLx3-yt4Z9o0PDFS3k3aQ9PweKA6JE.C~&mime_type=video_mp4&rc=ZmQ2ZjM0aGQ1ZzY4M2QzZ0BpMzluZGw5cjw5MzMzbzczNUBfNDReXi82XzUxY2EtNC5iYSNeZS9hMmQ0cWFhLS1kMTFzcw%3D%3D&vvpl=1&l=20260616180916969A7621F7670E143221&btag=e000b0000"></video></div>
<div class="cm-i-welcome">Welcome ${_currentUsername || 'User'}</div>
<h1 class="cm-i-title">Marlon Helper</h1>
<div class="cm-i-quote">just a simple copy and paste and boom u turn into Marlon with marlon helper</div>
<div class="cm-i-row">
<button class="cm-i-continue">Continue</button>
<div class="cm-i-discord" title="Join Discord"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/></svg></div>
</div>
</div>`;
        document.body.appendChild(_introOv);
        _introOv.querySelector('.cm-i-continue').addEventListener('click', () => {
            _introOv.classList.add('cm-i-hide');
            setTimeout(() => {
                _introOv.remove();
                // Remove custom cursor after intro unless crosshair is toggled on
                if (!CONFIG.crosshairEnabled) {
                    document.documentElement.style.cursor = '';
                    const cursorStyle = document.getElementById('cm-crosshair-style');
                    if (cursorStyle) cursorStyle.remove();
                }
            }, 500);
        });
        _introOv.querySelector('.cm-i-discord').addEventListener('click', () => {
            window.open('https://discord.gg/U6sQEp83qq', '_blank');
        });

        function applyFemboyLabels(active) {
            const pairs = [
                ['Score Control', 'Femboy Control'],
                ['System Status', 'Femboy Status'],
                ['Result Settings', 'Femboy Results'],
                ['Master Switch', 'Femboy Switch'],
                ['Power Status', 'Femboy Power'],
                ['Match Type', 'Femboy Match'],
                ['Hook Status', 'Femboy Hook'],
                ['Unban / Clear Cookies', 'Unfemboy / Clear'],
                ['Verification Bypass', 'Femboy Bypass'],
                ['Mode', 'Femboy Mode'],
                ['Min', 'Femboy Min'],
                ['Max', 'Femboy Max'],
                ['Type', 'Femboy Type'],
                ['Target', 'Femboy Target'],
                ['Lower Bound', 'Femboy Lower'],
                ['Upper Bound', 'Femboy Upper'],
                ['Matchmaking', 'Femboy Matching'],
                ['Auto Queue', 'Femboy Queue'],
                ['Request Delay (ms)', 'Femboy Delay (ms)'],
                ['Auto Find New Match', 'Femboy Find Match'],
                ['Spoof Cycling', 'Femboy Cycling'],
                ['Auto Cycle Camera', 'Femboy Camera'],
                ['Camera Interval (s)', 'Femboy Cam Interval'],
                ['Auto Cycle Audio', 'Femboy Audio'],
                ['Audio Interval (s)', 'Femboy Audio Interval'],
                ['Convenience', 'Femboy Convenience'],
                ['Auto Dismiss Popups', 'Femboy Dismiss'],
                ['Auto Clear Cookies on Ban', 'Femboy Unban'],
                ['Virtual Camera', 'Femboy Camera'],
                ['Activate Spoof', 'Activate Femboy'],
                ['Flip Horizontal', 'Femboy Flip'],
                ['Loop Video', 'Femboy Loop'],
                ['Playback Speed', 'Femboy Speed'],
                ['Source', 'Femboy Source'],
                ['Video', 'Femboy Video'],
                ['Image', 'Femboy Image'],
                ['Select video file...', 'Select femboy video...'],
                ['Select image file...', 'Select femboy image...'],
                ['Text Overlay', 'Femboy Text'],
                ['Enable Text', 'Femboy Text'],
                ['Content', 'Femboy Content'],
                ['Color', 'Femboy Color'],
                ['Size', 'Femboy Size'],
                ['Audio Spoof', 'Femboy Audio'],
                ['Activate Audio Spoof', 'Activate Femboy Audio'],
                ['Select audio file...', 'Select femboy audio...'],
                ['Loop', 'Femboy Loop'],
                ['Speed', 'Femboy Speed'],
                ['Volume', 'Femboy Volume'],
                ['Bass (dB)', 'Femboy Bass (dB)'],
                ['Treble (dB)', 'Femboy Treble (dB)'],
                ['Warmth (dB)', 'Femboy Warmth (dB)'],
                ['Status', 'Femboy Status'],
                ['Inactive', 'Femboy Inactive'],
                ['Active', 'Femboy Active'],
                ['None', 'Femboy None'],
                ['Developer', 'Femboy Dev'],
                ['Console Logs', 'Femboy Logs'],
                ['Hotkeys', 'Femboy Keys'],
                ['Open Panel', 'Femboy Panel'],
                ['Stream Proof', 'Femboy Stealth'],
                ['Panic Key', 'Femboy Panic'],
                ['Show Control Bar', 'Femboy Control Bar'],
                ['Hide All Now', 'Hide All Femboy'],
                ['Iframe Mode (OBS)', 'Femboy Mode (OBS)'],
                ['Branding', 'Femboy Branding'],
                ['Display Badge', 'Femboy Badge'],
                ['Visibility', 'Femboy Visibility'],
                ['Appearance', 'Femboy Appearance'],
                ['Mirror Cam', 'Femboy Mirror'],
                ['Mirror Opponent Cam', 'Femboy Opponent Cam'],
                ['Opponent Feed', 'Femboy Feed'],
                ['Record', 'Femboy Record'],
                ['Idle', 'Femboy Idle'],
                ['Log', 'Femboy Log'],
                ['Credits', 'Femboy Credits'],
                ['Developers', 'Femboy Devs'],
                ['Join Discord', 'Join Femboy'],
                ['Free', 'Femboy Free'],
                ['Range', 'Femboy Range'],
                ['Fixed', 'Femboy Fixed'],
                ['Static', 'Femboy Static'],
                ['Dynamic', 'Femboy Dynamic'],
            ];
            const rootEl = document.getElementById('cm-root');
            if (!rootEl) return;
            for (const el of rootEl.querySelectorAll('*')) {
                if (el.children.length > 0) continue;
                const t = el.textContent.trim();
                if (!t) continue;
                if (active) {
                    for (const [orig, femboy] of pairs) {
                        if (t === orig) { el.textContent = femboy; break; }
                    }
                } else {
                    for (const [orig, femboy] of pairs) {
                        if (t === femboy) { el.textContent = orig; break; }
                    }
                }
            }
        }

        function applyTheme(themeName) {
            const theme = THEMES[themeName] || THEMES.midnight;
            CONFIG.theme = themeName;
            document.documentElement.style.setProperty('--cm-primary', theme.primary);
            document.documentElement.style.setProperty('--cm-primary-rgb', theme.primaryRgb);
            document.documentElement.style.setProperty('--cm-secondary', theme.secondary);
            document.documentElement.style.setProperty('--cm-accent', theme.accent);
            document.documentElement.style.setProperty('--cm-accent-rgb', theme.accentRgb);
            document.documentElement.style.setProperty('--cm-success', theme.success);
            document.documentElement.style.setProperty('--cm-warning', theme.warning);
            document.documentElement.style.setProperty('--cm-danger', theme.danger);
            document.documentElement.style.setProperty('--cm-bg-dark', theme.bgDark);
            document.documentElement.style.setProperty('--cm-bg-card', theme.bgCard);
            document.documentElement.style.setProperty('--cm-bg-elevated', theme.bgElevated);
            document.documentElement.style.setProperty('--cm-border', theme.border);
            document.documentElement.style.setProperty('--cm-text', theme.text);
            document.documentElement.style.setProperty('--cm-text-muted', theme.textMuted);

            const isFemboy = themeName === 'femboy';
            const waifuSection = document.getElementById('cm-waifu-section');
            if (waifuSection) waifuSection.style.display = isFemboy ? 'block' : 'none';

            const titleEl = document.querySelector('.cm-title');
            if (titleEl) titleEl.textContent = isFemboy ? 'femboymoggle!~ uwu!' : 'Marlon Helper';

            const toggleBtn = document.getElementById('cm-toggle-btn');
            if (toggleBtn) {
                toggleBtn.innerHTML = isFemboy
                    ? `<div style="width:100%;height:100%;border-radius:50%;overflow:hidden;background:url('https://cdn.frostedbrowser.cfd/cheatmoggle-assets/cheatmogglewaifu.png') center 5%/auto 320% no-repeat;"></div>`
                    : `<video autoplay muted loop playsinline src="https://v16m.tiktokcdn-us.com/b23435e11c9f7f9419e0287e41c8b532/6a31e5b4/video/tos/no1a/tos-no1a-ve-0068-no/owoRDEgqQ1ogRHElIB0aMkFDQGoA3FfmkOAe6k/?a=1233&bti=OUBzOTg7QGo6OjZAL3AjLTAzYCMxNDNg&&bt=1664&ft=kLx3-yt4Z9o0PDFS3k3aQ9PweKA6JE.C~&mime_type=video_mp4&rc=ZmQ2ZjM0aGQ1ZzY4M2QzZ0BpMzluZGw5cjw5MzMzbzczNUBfNDReXi82XzUxY2EtNC5iYSNeZS9hMmQ0cWFhLS1kMTFzcw%3D%3D&vvpl=1&l=20260616180916969A7621F7670E143221&btag=e000b0000" style="width:40px;height:40px;border-radius:6px;object-fit:cover;"></video>`;
            }

            const logoIcon = document.querySelector('.cm-logo-icon');
            if (logoIcon) {
                logoIcon.innerHTML = isFemboy
                    ? `<div style="width:100%;height:100%;border-radius:6px;overflow:hidden;background:url('https://cdn.frostedbrowser.cfd/cheatmoggle-assets/cheatmogglewaifu.png') center 5%/auto 320% no-repeat;"></div>`
                    : `<video autoplay muted loop playsinline src="https://v16m.tiktokcdn-us.com/b23435e11c9f7f9419e0287e41c8b532/6a31e5b4/video/tos/no1a/tos-no1a-ve-0068-no/owoRDEgqQ1ogRHElIB0aMkFDQGoA3FfmkOAe6k/?a=1233&bti=OUBzOTg7QGo6OjZAL3AjLTAzYCMxNDNg&&bt=1664&ft=kLx3-yt4Z9o0PDFS3k3aQ9PweKA6JE.C~&mime_type=video_mp4&rc=ZmQ2ZjM0aGQ1ZzY4M2QzZ0BpMzluZGw5cjw5MzMzbzczNUBfNDReXi82XzUxY2EtNC5iYSNeZS9hMmQ0cWFhLS1kMTFzcw%3D%3D&vvpl=1&l=20260616180916969A7621F7670E143221&btag=e000b0000" style="width:100%;height:100%;border-radius:6px;object-fit:cover;display:block;"></video>`;
            }

            const statusPill = document.getElementById('cm-status-pill');
            const modePill = document.getElementById('cm-mode-pill');
            if (isFemboy) {
                if (statusPill) { statusPill.style.background = 'rgba(255,105,180,0.25)'; statusPill.style.color = '#ff69b4'; statusPill.style.border = '1px solid rgba(255,105,180,0.4)'; }
                if (modePill) { modePill.style.background = 'rgba(255,182,193,0.2)'; modePill.style.color = '#ffb6c1'; modePill.style.border = '1px solid rgba(255,182,193,0.3)'; }
            } else {
                if (statusPill) { statusPill.style.background = ''; statusPill.style.color = ''; statusPill.style.border = ''; }
                if (modePill) { modePill.style.background = ''; modePill.style.color = ''; modePill.style.border = ''; }
            }

            applyFemboyLabels(isFemboy);
            saveConfig();
        }

        const style = document.createElement('style');
        style.textContent = `
            @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap');

            :root {
                --cm-primary: #6366f1;
                --cm-primary-rgb: 99,102,241;
                --cm-secondary: #8b5cf6;
                --cm-accent: #22d3ee;
                --cm-accent-rgb: 34,211,238;
                --cm-success: #10b981;
                --cm-warning: #f59e0b;
                --cm-danger: #ef4444;
                --cm-bg-dark: #0a0a0f;
                --cm-bg-card: #12121a;
                --cm-bg-elevated: #1a1a24;
                --cm-border: rgba(255,255,255,0.08);
                --cm-text: #e4e4e7;
                --cm-text-muted: #71717a;
                --cm-glow: 0 0 30px rgba(0,0,0,0.6);
            }

            #cm-toggle-btn {
                position: fixed;
                top: 16px;
                right: 16px;
                z-index: 999999;
                width: 56px;
                height: 56px;
                border-radius: 50%;
                background: radial-gradient(circle at 30% 25%, rgba(var(--cm-primary-rgb),0.35), rgba(0,0,0,0.92) 72%);
                border: 2px solid var(--cm-primary);
                padding: 0;
                overflow: visible;
                cursor: grab;
                display: flex;
                align-items: center;
                justify-content: center;
                box-shadow: 0 0 0 1px rgba(0,0,0,0.35), 0 0 18px rgba(0,0,0,0.55), 0 6px 20px rgba(0,0,0,0.5);
                transition: transform 0.22s cubic-bezier(0.34,1.56,0.64,1), box-shadow 0.22s ease, border-color 0.22s ease;
                user-select: none;
                touch-action: manipulation;
            }
            /* pulsating themed rings */
            #cm-toggle-btn::before,
            #cm-toggle-btn::after {
                content: '';
                position: absolute;
                inset: -2px;
                border-radius: 50%;
                border: 2px solid var(--cm-primary);
                pointer-events: none;
                will-change: transform, opacity;
            }
            #cm-toggle-btn::before { animation: cmPulseRing 2.1s cubic-bezier(0.2,0.6,0.3,1) infinite; }
            #cm-toggle-btn::after  { animation: cmPulseRing 2.1s cubic-bezier(0.2,0.6,0.3,1) infinite 1.05s; }
            @keyframes cmPulseRing {
                0%   { transform: scale(1);    opacity: 0.85; }
                70%  { transform: scale(1.95); opacity: 0; }
                100% { transform: scale(1.95); opacity: 0; }
            }
            #cm-toggle-btn img {
                width: 100% !important;
                height: 100% !important;
                border-radius: 50% !important;
                object-fit: cover;
                position: relative;
                z-index: 2;
                box-shadow: inset 0 0 0 1px rgba(0,0,0,0.45);
            }
            #cm-toggle-btn:active { cursor: grabbing; }
            #cm-toggle-btn:hover {
                transform: scale(1.12);
                border-color: var(--cm-accent);
                box-shadow: 0 0 0 1px rgba(0,0,0,0.6), 0 0 30px rgba(0,0,0,0.85), 0 10px 26px rgba(0,0,0,0.6);
            }
            #cm-toggle-btn.dragging { cursor: grabbing; transition: none; }
            #cm-toggle-btn svg {
                width: 24px;
                height: 24px;
                fill: white;
                filter: drop-shadow(0 1px 2px rgba(0,0,0,0.3));
            }

            #cm-root {
                position: fixed;
                top: 70px;
                right: 16px;
                z-index: 999998;
                width: 380px;
                min-width: 320px;
                max-width: 98vw;
                max-height: 92vh;
                min-height: 500px;
                background: var(--cm-bg-dark);
                border-radius: 12px;
                font-family: 'Inter', -apple-system, sans-serif;
                color: var(--cm-text);
                border: 1px solid var(--cm-border);
                box-shadow: 0 0 40px rgba(var(--cm-primary-rgb),0.1), 0 15px 30px rgba(0,0,0,0.4);
                display: none;
                opacity: 0;
                overflow: auto;
                transition: opacity 0.2s ease, transform 0.2s ease;
                transform: translateY(-10px) scale(0.98);
                scrollbar-width: none;
                -ms-overflow-style: none;
            }
            #cm-root::-webkit-scrollbar { display: none; }
            #cm-root.visible {
                display: flex;
                flex-direction: column;
                opacity: 1;
                transform: translateY(0) scale(1);
            }
            #cm-root .cm-resize-handle {
                position: absolute;
                z-index: 99;
            }
            #cm-root .cm-resize-handle.cm-rz-top {
                top: -4px; left: 8px; right: 8px; height: 8px;
                cursor: n-resize;
            }
            #cm-root .cm-resize-handle.cm-rz-bottom {
                bottom: -4px; left: 8px; right: 8px; height: 8px;
                cursor: s-resize;
            }
            #cm-root .cm-resize-handle.cm-rz-left {
                top: 8px; bottom: 8px; left: -4px; width: 8px;
                cursor: w-resize;
            }
            #cm-root .cm-resize-handle.cm-rz-right {
                top: 8px; bottom: 8px; right: -4px; width: 8px;
                cursor: e-resize;
            }
            #cm-root .cm-resize-handle.cm-rz-tl {
                top: -4px; left: -4px; width: 14px; height: 14px;
                cursor: nw-resize;
            }
            #cm-root .cm-resize-handle.cm-rz-tr {
                top: -4px; right: -4px; width: 14px; height: 14px;
                cursor: ne-resize;
            }
            #cm-root .cm-resize-handle.cm-rz-bl {
                bottom: -4px; left: -4px; width: 14px; height: 14px;
                cursor: sw-resize;
            }
            #cm-root .cm-resize-handle.cm-rz-br {
                bottom: -4px; right: -4px; width: 14px; height: 14px;
                cursor: se-resize;
            }
            #cm-root.dragging { transition: none; user-select: none; }

            .cm-header {
                padding: 8px 10px 6px;
                background: linear-gradient(180deg, rgba(var(--cm-primary-rgb),0.08) 0%, transparent 100%);
                border-bottom: 1px solid var(--cm-border);
                cursor: grab;
                user-select: none;
                flex-shrink: 0;
            }
            .cm-header:active { cursor: grabbing; }

            .cm-title-row {
                display: flex;
                align-items: center;
                justify-content: space-between;
                margin-bottom: 6px;
            }
            .cm-logo { display: flex; align-items: center; gap: 6px; }
          .cm-logo-icon {
             width: 68px; height: 68px;
             border-radius: 10px;
             background: linear-gradient(135deg, var(--cm-primary), var(--cm-secondary));
             display: flex; align-items: center; justify-content: center;
             box-shadow: 0 0 20px rgba(0,0,0,0.6);
             }
            .cm-logo-icon svg { width: 14px; height: 14px; fill: white; }
            .cm-title {
                font-family: 'Space Grotesk', sans-serif;
                font-size: 13px; font-weight: 700; letter-spacing: -0.02em;
                background: linear-gradient(135deg, #fff 0%, var(--cm-accent) 100%);
                -webkit-background-clip: text; -webkit-text-fill-color: transparent;
            }
            .cm-version {
                font-size: 8px; font-weight: 600; color: var(--cm-text-muted);
                background: var(--cm-bg-elevated); padding: 1px 4px; border-radius: 3px; margin-left: 4px;
            }
            .cm-free-badge {
                font-size: 8px; font-weight: 800; color: #00ff88;
                background: rgba(0,255,136,0.1);
                border: 1px solid rgba(0,255,136,0.3);
                padding: 1px 5px; border-radius: 4px; margin-left: 6px;
                letter-spacing: 0.05em;
                text-shadow: 0 0 6px rgba(0,255,136,0.6);
                box-shadow: 0 0 6px rgba(0,255,136,0.2), inset 0 0 4px rgba(0,255,136,0.1);
                animation: cmFreeBadgeGlow 2s ease-in-out infinite alternate;
            }
            @keyframes cmFreeBadgeGlow {
                0% { text-shadow: 0 0 4px rgba(0,255,136,0.4); box-shadow: 0 0 4px rgba(0,255,136,0.15), inset 0 0 3px rgba(0,255,136,0.05); }
                100% { text-shadow: 0 0 8px rgba(0,255,136,0.9), 0 0 14px rgba(0,255,136,0.4); box-shadow: 0 0 10px rgba(0,255,136,0.35), inset 0 0 6px rgba(0,255,136,0.15); }
            }
            .cm-status-row { display: flex; align-items: center; gap: 4px; }
            .cm-pill {
                padding: 2px 5px; border-radius: 4px;
                font-size: 8px; font-weight: 700;
                text-transform: uppercase; letter-spacing: 0.04em;
            }
            .cm-pill.active {
                background: rgba(16,185,129,0.2); color: var(--cm-success);
                border: 1px solid rgba(16,185,129,0.3);
            }
            .cm-pill.mode {
                background: rgba(var(--cm-primary-rgb),0.2); color: var(--cm-primary);
                border: 1px solid rgba(var(--cm-primary-rgb),0.3);
            }
            .cm-discord-link {
                display: flex; align-items: center; gap: 6px;
                padding: 6px 10px;
                background: linear-gradient(135deg, #5865F2 0%, #7289da 100%);
                border-radius: 8px; font-size: 10px; font-weight: 600;
                color: white; text-decoration: none; transition: all 0.2s ease; margin-left: auto;
            }
            .cm-discord-link:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(88,101,242,0.4); }
            .cm-discord-link svg { width: 14px; height: 14px; fill: currentColor; }

            .cm-tabs {
                display: flex; gap: 2px;
                background: var(--cm-bg-card); padding: 2px; border-radius: 6px;
            }
            .cm-tab {
                flex: 1; padding: 5px 4px; border-radius: 4px;
                font-size: 9px; font-weight: 600; text-align: center;
                cursor: pointer; transition: all 0.15s ease;
                color: var(--cm-text-muted); background: transparent; border: none; white-space: nowrap;
            }
            .cm-tab:hover { color: var(--cm-text); background: rgba(255,255,255,0.03); }
            .cm-tab.active {
                background: var(--cm-bg-elevated); color: white;
                box-shadow: 0 1px 4px rgba(0,0,0,0.2);
            }
            .cm-tab-locked::after {
                content: '🔒';
                font-size: 7px;
                margin-left: 2px;
                opacity: 0.6;
            }

            .cm-body { padding: 8px; overflow-y: auto; flex: 1; }
            .cm-body::-webkit-scrollbar { width: 4px; }
            .cm-body::-webkit-scrollbar-track { background: transparent; }
            .cm-body::-webkit-scrollbar-thumb { background: rgba(var(--cm-primary-rgb),0.3); border-radius: 2px; }

            .cm-panel { display: none; }
            .cm-panel.active { display: block; animation: cmFadeIn 0.2s ease; }
            @keyframes cmFadeIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: translateY(0); } }

            .cm-section { margin-bottom: 8px; }
            .cm-section:last-child { margin-bottom: 0; }
            .cm-section-title {
                font-size: 8px; font-weight: 700;
                text-transform: uppercase; letter-spacing: 0.1em;
                color: var(--cm-text-muted); margin-bottom: 4px;
                display: flex; align-items: center; gap: 4px; justify-content: space-between;
            }
            .cm-section-title > span { display: flex; align-items: center; gap: 4px; }
            .cm-section-title > span::after {
                content: ''; width: 20px; height: 1px;
                background: linear-gradient(90deg, var(--cm-border), transparent);
            }
            .cm-section-toggle { transform: scale(0.7); }
            .cm-section-disabled { opacity: 0.4; pointer-events: none; }
            .cm-divider { height: 1px; background: var(--cm-border); margin: 10px 0; }

            .cm-card {
                background: var(--cm-bg-card); border-radius: 8px;
                padding: 6px; border: 1px solid var(--cm-border);
            }

            .cm-live-score {
                text-align: center; padding: 8px 6px;
                background: linear-gradient(135deg, rgba(var(--cm-primary-rgb),0.08), rgba(var(--cm-accent-rgb),0.05));
                border-radius: 8px;
            }
            .cm-score-value {
                font-family: 'JetBrains Mono', monospace;
                font-size: 24px; font-weight: 800; letter-spacing: -0.02em; line-height: 1; margin-bottom: 2px;
            }
            .cm-score-tier { font-size: 9px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em; }

            .cm-row {
                display: flex; align-items: center; justify-content: space-between;
                padding: 4px 0; border-bottom: 1px solid var(--cm-border);
            }
            .cm-row:last-child { border-bottom: none; }
            .cm-label { font-size: 10px; font-weight: 500; color: var(--cm-text); }
            .cm-value { font-family: 'JetBrains Mono', monospace; font-size: 9px; font-weight: 600; color: var(--cm-text); }

            .cm-slider-row { display: flex; flex-direction: column; gap: 2px; padding: 4px 0; border-bottom: 1px solid var(--cm-border); }
            .cm-slider-row:last-child { border-bottom: none; }
            .cm-slider-header { display: flex; justify-content: space-between; align-items: center; }
            .cm-slider-label { font-size: 9px; font-weight: 500; }
            .cm-slider-value {
                font-family: 'JetBrains Mono', monospace; font-size: 9px; font-weight: 600; color: var(--cm-text);
                background: var(--cm-bg-elevated); border: 1px solid var(--cm-border); padding: 1px 4px; border-radius: 3px;
            }
            .cm-slider-track {
                position: relative; height: 4px;
                background: var(--cm-bg-elevated); border-radius: 2px; overflow: hidden; border: 1px solid var(--cm-border);
            }
            .cm-slider-fill {
                position: absolute; top: 0; left: 0; height: 100%;
                background: var(--cm-text-muted); border-radius: 2px; transition: width 0.1s ease; opacity: 0.4;
            }
            .cm-slider {
                position: absolute; top: 0; left: 0; width: 100%; height: 100%;
                -webkit-appearance: none; background: transparent; cursor: pointer; margin: 0;
            }
            .cm-slider::-webkit-slider-thumb {
                -webkit-appearance: none; width: 14px; height: 14px; border-radius: 50%;
                background: var(--cm-text); cursor: pointer;
                box-shadow: 0 2px 6px rgba(0,0,0,0.4); transition: transform 0.15s ease, box-shadow 0.15s ease;
            }
            .cm-slider::-webkit-slider-thumb:hover { transform: scale(1.15); box-shadow: 0 2px 10px rgba(0,0,0,0.5); }

            .cm-toggle { position: relative; width: 32px; height: 18px; cursor: pointer; }
            .cm-toggle input { opacity: 0; width: 0; height: 0; }
            .cm-toggle-track {
                position: absolute; inset: 0; border-radius: 11px;
                background: var(--cm-bg-elevated); border: 1px solid var(--cm-border); transition: all 0.25s ease;
            }
            .cm-toggle input:checked + .cm-toggle-track { background: var(--cm-text); border-color: var(--cm-text); }
            .cm-toggle-thumb {
                position: absolute; top: 2px; left: 2px; width: 14px; height: 14px; border-radius: 50%;
                background: var(--cm-text); box-shadow: 0 1px 3px rgba(0,0,0,0.3);
                transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
            }
            .cm-toggle input:checked ~ .cm-toggle-thumb { left: 16px; background: var(--cm-bg-dark); }

            .cm-btn-group { display: flex; gap: 3px; background: var(--cm-bg-elevated); padding: 2px; border-radius: 6px; }
            .cm-btn-opt {
                padding: 6px 10px; border-radius: 6px; font-size: 10px; font-weight: 700;
                text-transform: uppercase; letter-spacing: 0.03em; cursor: pointer; transition: all 0.15s ease;
                background: transparent; color: var(--cm-text-muted); border: none;
            }
            .cm-btn-opt:hover { color: var(--cm-text); }
            .cm-btn-opt.active { background: var(--cm-text); color: var(--cm-bg-dark); box-shadow: 0 2px 6px rgba(0,0,0,0.3); }

            .cm-preview {
                margin-top: 12px; padding: 16px;
                background: linear-gradient(135deg, rgba(var(--cm-primary-rgb),0.08), rgba(var(--cm-accent-rgb),0.05));
                border-radius: 10px; text-align: center; border: 1px solid rgba(var(--cm-primary-rgb),0.15);
            }
            .cm-preview-score { font-family: 'JetBrains Mono', monospace; font-size: 32px; font-weight: 800; }
            .cm-preview-tier { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; margin-top: 4px; }

            .cm-file-picker {
                display: flex; align-items: center; gap: 8px; padding: 8px;
                background: var(--cm-bg-elevated); border: 1px dashed var(--cm-border);
                border-radius: 6px; cursor: pointer; transition: all 0.15s ease;
            }
            .cm-file-picker:hover { border-color: var(--cm-text); background: rgba(var(--cm-accent-rgb),0.05); }
            .cm-file-icon {
                width: 28px; height: 28px; border-radius: 6px;
                background: var(--cm-bg-card); display: flex; align-items: center; justify-content: center;
            }
            .cm-file-icon svg { width: 14px; height: 14px; fill: var(--cm-text-muted); }
            .cm-file-name { font-size: 10px; color: var(--cm-text-muted); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
            .cm-file-name.selected { color: var(--cm-success); }

            .cm-preset-section { margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--cm-border); }
            .cm-preset-label { font-size: 8px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--cm-text-muted); display: block; margin-bottom: 4px; }
            .cm-preset-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
            .cm-preset-btn {
                padding: 4px 6px; font-size: 8px; font-weight: 500;
                border: 1px solid var(--cm-border); border-radius: 4px;
                background: var(--cm-bg-elevated); color: var(--cm-text); cursor: pointer; transition: all 0.15s ease; text-align: center;
            }
            .cm-preset-btn:hover { background: var(--cm-text); color: var(--cm-bg-dark); border-color: var(--cm-text); }
            .cm-preset-btn.active { background: var(--cm-text); color: var(--cm-bg-dark); border-color: var(--cm-text); }

            .cm-color-row { display: flex; align-items: center; gap: 10px; }
            .cm-color-input { width: 32px; height: 32px; border-radius: 8px; border: none; cursor: pointer; padding: 0; background: none; }

            .cm-input {
                background: var(--cm-bg-elevated); border: 1px solid var(--cm-border);
                border-radius: 6px; padding: 6px 10px;
                font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--cm-text);
                outline: none; transition: all 0.2s ease;
            }
            .cm-input:focus { border-color: var(--cm-primary); box-shadow: 0 0 0 2px rgba(var(--cm-primary-rgb),0.2); }
            .cm-score-input {
                -moz-appearance: textfield;
            }
            .cm-score-input::-webkit-outer-spin-button,
            .cm-score-input::-webkit-inner-spin-button {
                -webkit-appearance: none;
                margin: 0;
            }
            .cm-select {
                background: var(--cm-bg-elevated); border: 1px solid var(--cm-border);
                border-radius: 6px; padding: 6px 10px;
                font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--cm-text);
                outline: none; cursor: pointer; transition: all 0.2s ease;
            }
            .cm-select:focus { border-color: var(--cm-primary); box-shadow: 0 0 0 2px rgba(var(--cm-primary-rgb),0.2); }
            .cm-select option { background: var(--cm-bg-dark); color: var(--cm-text); }
            .cm-btn-small {
                background: linear-gradient(135deg, var(--cm-primary), var(--cm-secondary));
                border: none; border-radius: 4px; padding: 4px 10px;
                font-family: 'Inter', sans-serif; font-size: 10px; font-weight: 600;
                color: white; cursor: pointer; transition: all 0.2s ease;
            }
            .cm-btn-small:hover { transform: scale(1.02); filter: brightness(1.1); }

            .cm-shapes { display: flex; gap: 4px; }
            .cm-shape-btn {
                width: 32px; height: 32px; border-radius: 8px;
                border: 1px solid var(--cm-border); background: var(--cm-bg-elevated);
                cursor: pointer; font-size: 14px; display: flex; align-items: center; justify-content: center; transition: all 0.15s ease;
            }
            .cm-shape-btn:hover { background: rgba(var(--cm-primary-rgb),0.15); }
            .cm-shape-btn.active { background: linear-gradient(135deg, var(--cm-primary), var(--cm-secondary)); border-color: transparent; }

            .cm-theme-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; margin-top: 4px; }
            .cm-theme-btn {
                padding: 6px 4px; border-radius: 6px; border: 1px solid var(--cm-border);
                background: var(--cm-bg-elevated); cursor: pointer; transition: all 0.15s ease; text-align: center;
            }
            .cm-theme-btn:hover { border-color: rgba(var(--cm-primary-rgb),0.4); }
            .cm-theme-btn.active { border-color: var(--cm-text); box-shadow: 0 0 8px rgba(var(--cm-primary-rgb),0.2); }
            .cm-theme-preview { width: 16px; height: 16px; border-radius: 4px; margin: 0 auto 3px; }
            .cm-theme-name { font-size: 8px; font-weight: 600; color: var(--cm-text); }

            .cm-panic-btn {
                width: 100%; padding: 6px 10px; font-size: 9px; font-weight: 600;
                border: 1px solid var(--cm-danger); border-radius: 4px;
                background: rgba(239,68,68,0.1); color: var(--cm-danger); cursor: pointer; transition: all 0.15s ease;
            }
            .cm-panic-btn:hover { background: var(--cm-danger); color: white; }

            #cm-root.stream-hidden,
            #cm-toggle-btn.stream-hidden { display: none !important; opacity: 0 !important; pointer-events: none !important; }

#cm-watermark {
                position: fixed; bottom: 16px; right: 16px; z-index: 999990;
                padding: 6px 12px; border-radius: 8px;
                background: rgba(var(--cm-primary-rgb),0.1); backdrop-filter: blur(8px);
                border: 1px solid rgba(var(--cm-primary-rgb),0.2);
                font-family: 'JetBrains Mono', monospace; font-size: 9px; font-weight: 600;
                color: rgba(255,255,255,0.35); letter-spacing: 0.05em; cursor: grab; user-select: none;
            }

            .cm-toggle-track, .cm-toggle-thumb, .cm-btn-opt, .cm-tab, .cm-card, .cm-section,
            .cm-file-picker, .cm-theme-btn, .cm-panic-btn, .cm-input, .cm-slider-fill {
                transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1) !important;
            }
            .cm-card:hover { transform: translateY(-1px); box-shadow: 0 4px 12px rgba(0,0,0,0.15); }
            .cm-btn-opt:active, .cm-tab:active { transform: scale(0.96); }
            .cm-toggle input:checked ~ .cm-toggle-thumb { transform: translateX(0); }
            #cm-root { transition: opacity 0.3s ease, transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), visibility 0.3s ease; }
            #cm-root:not(.visible) { opacity: 0; transform: translateX(20px) scale(0.95); visibility: hidden; pointer-events: none; }
            #cm-root.visible { opacity: 1; transform: translateX(0) scale(1); visibility: visible; display: flex; }

            #cm-disclaimer {
                position: fixed; bottom: 16px; left: 16px; z-index: 999999;
                padding: 10px 14px; border-radius: 8px;
                background: rgba(234, 179, 8, 0.15); backdrop-filter: blur(10px);
                border: 1px solid rgba(234, 179, 8, 0.4);
                font-family: 'Inter', -apple-system, sans-serif; font-size: 11px; font-weight: 500;
                color: #eab308; display: flex; align-items: center; gap: 10px;
                animation: cm-slide-in 0.4s cubic-bezier(0.4, 0, 0.2, 1);
            }
            #cm-disclaimer.hiding {
                animation: cm-slide-out 0.3s cubic-bezier(0.4, 0, 0.2, 1) forwards;
            }
            @keyframes cm-slide-in {
                from { opacity: 0; transform: translateY(20px); }
                to { opacity: 1; transform: translateY(0); }
            }
            @keyframes cm-slide-out {
                from { opacity: 1; transform: translateY(0); }
                to { opacity: 0; transform: translateY(20px); }
            }
            #cm-disclaimer-close {
                background: none; border: none; color: #eab308; cursor: pointer;
                padding: 2px; display: flex; align-items: center; justify-content: center;
                border-radius: 4px; transition: all 0.2s ease;
            }
            #cm-disclaimer-close:hover { background: rgba(234, 179, 8, 0.2); }
            #cm-disclaimer-close svg { width: 14px; height: 14px; }

            /* ============================================================
               ENHANCED UI LAYER — visual polish & animations
               (overrides above; all original classes/ids preserved)
               ============================================================ */

            @keyframes cmGlowPulse {
                0%,100% { box-shadow: 0 0 0 0 rgba(0,0,0,0.45); }
                50%     { box-shadow: 0 0 10px 2px rgba(0,0,0,0.0); }
            }
            @keyframes cmSheen {
                0%   { background-position: -150% 0; }
                100% { background-position: 250% 0; }
            }
            @keyframes cmBorderFlow {
                0%   { background-position: 0% 50%; }
                100% { background-position: 200% 50%; }
            }
            @keyframes cmRise {
                from { opacity: 0; transform: translateY(8px); }
                to   { opacity: 1; transform: translateY(0); }
            }
            @keyframes cmScorePulse {
                0%,100% { transform: scale(1); text-shadow: 0 0 14px rgba(var(--cm-primary-rgb),0.35); }
                50%     { transform: scale(1.04); text-shadow: 0 0 22px rgba(var(--cm-primary-rgb),0.6); }
            }
            @keyframes cmSpin { to { transform: rotate(360deg); } }

            /* ---- Panel shell: glassy + animated gradient top accent ---- */
            #cm-root {
                background: var(--cm-bg-dark) !important;
                backdrop-filter: blur(18px) saturate(135%);
                -webkit-backdrop-filter: blur(18px) saturate(135%);
                border: 1px solid var(--cm-border) !important;
                border-radius: 16px !important;
                box-shadow:
                    0 0 0 1px rgba(255,255,255,0.03),
                    0 24px 60px rgba(0,0,0,0.55) !important;
            }
            #cm-root::before {
                display: none !important;
            }

            /* ---- Header: subtle moving sheen ---- */
            .cm-header {
                position: relative;
                padding: 12px 12px 10px !important;
                overflow: hidden;
                background:
                    linear-gradient(180deg, rgba(var(--cm-primary-rgb),0.10) 0%, transparent 100%) !important;
            }
            .cm-header::after {
                content: '';
                position: absolute; inset: 0;
                background: linear-gradient(115deg, transparent 35%, rgba(255,255,255,0.06) 50%, transparent 65%);
                background-size: 250% 100%;
                animation: cmSheen 6s ease-in-out infinite;
                pointer-events: none;
            }
            .cm-title {
                background: linear-gradient(135deg, #fff 0%, var(--cm-accent) 50%, var(--cm-primary) 100%) !important;
                background-size: 200% auto !important;
                -webkit-background-clip: text !important;
                background-clip: text !important;
                -webkit-text-fill-color: transparent !important;
                animation: cmBorderFlow 5s linear infinite;
                font-size: 14px !important;
            }
            .cm-logo-icon { animation: cmGlowPulse 2.6s ease-in-out infinite; }

            /* ---- Status pill: live glow ---- */
            .cm-pill.active {
                position: relative;
                animation: cmGlowPulse 2s ease-in-out infinite;
            }
            .cm-pill { transition: all 0.25s ease; }

            /* ---- Tabs: animated hover + active ---- */
            .cm-tabs { gap: 3px !important; border-radius: 9px !important; padding: 3px !important; }
            .cm-tab {
                position: relative; overflow: hidden; border-radius: 7px !important;
                transition: color 0.2s ease, background 0.2s ease, transform 0.12s ease;
            }
            .cm-tab.active {
                background: linear-gradient(135deg, rgba(var(--cm-primary-rgb),0.22), rgba(var(--cm-accent-rgb),0.12)) !important;
                color: #fff !important;
                box-shadow: 0 0 0 1px rgba(var(--cm-primary-rgb),0.3), 0 2px 8px rgba(var(--cm-primary-rgb),0.18) !important;
            }
            .cm-tab.active::after {
                content: '';
                position: absolute; bottom: 2px; left: 50%; transform: translateX(-50%);
                width: 16px; height: 2px; border-radius: 2px;
                background: var(--cm-primary);
                box-shadow: 0 0 6px var(--cm-primary);
            }
            .cm-tab:hover { transform: translateY(-1px); }

            /* ---- Panels stagger rows on enter ---- */
            .cm-panel.active .cm-section { animation: cmRise 0.35s ease both; }
            .cm-panel.active .cm-section:nth-child(2) { animation-delay: 0.05s; }
            .cm-panel.active .cm-section:nth-child(3) { animation-delay: 0.10s; }
            .cm-panel.active .cm-section:nth-child(4) { animation-delay: 0.15s; }
            .cm-panel.active .cm-section:nth-child(5) { animation-delay: 0.20s; }

            /* ---- Cards: gradient + glow lift ---- */
            .cm-card {
                background: linear-gradient(160deg, var(--cm-bg-card), var(--cm-bg-dark)) !important;
                border: 1px solid var(--cm-border) !important;
                border-radius: 10px !important;
                padding: 8px !important;
                position: relative;
            }
            .cm-card:hover {
                transform: translateY(-2px);
                border-color: rgba(var(--cm-primary-rgb),0.35) !important;
                box-shadow: 0 8px 22px rgba(0,0,0,0.4), 0 0 0 1px rgba(var(--cm-primary-rgb),0.15) !important;
            }

            .cm-section-title { font-size: 9px !important; cursor: pointer; user-select: none; }

            /* ---- Collapsible sections ---- */
            .cm-section-content {
                overflow: hidden;
                max-height: 2000px;
                transition: max-height 0.35s ease, opacity 0.25s ease, margin 0.25s ease;
                opacity: 1;
            }
            .cm-section.collapsed .cm-section-content {
                max-height: 0;
                opacity: 0;
                margin: 0;
                pointer-events: none;
            }
            .cm-section.collapsed .cm-section-title { margin-bottom: 0; }
            .cm-chevron {
                font-size: 6px;
                transition: transform 0.25s ease;
                display: inline-block;
                margin-right: 3px;
                color: var(--cm-text-muted);
                opacity: 0.4;
            }
            .cm-section-title:hover .cm-chevron { opacity: 0.9; }
            .cm-section.collapsed .cm-chevron { transform: rotate(-90deg); }

            /* ---- Rows: hover highlight ---- */
            .cm-row { transition: background 0.2s ease, padding 0.2s ease; border-radius: 6px; }
            .cm-row:hover { background: rgba(var(--cm-primary-rgb),0.05); }

            /* ---- Toggles: glow when on ---- */
            .cm-toggle input:checked + .cm-toggle-track {
                background: linear-gradient(135deg, var(--cm-primary), var(--cm-secondary)) !important;
                border-color: transparent !important;
                box-shadow: 0 0 10px rgba(var(--cm-primary-rgb),0.5);
            }
            .cm-toggle input:checked ~ .cm-toggle-thumb {
                background: #fff !important;
                box-shadow: 0 0 8px rgba(var(--cm-primary-rgb),0.6), 0 1px 3px rgba(0,0,0,0.4);
            }
            .cm-toggle:hover .cm-toggle-thumb { transform: scale(1.08); }

            /* ---- Sliders: themed fill + glowing thumb ---- */
            .cm-slider-fill {
                background: linear-gradient(90deg, var(--cm-secondary), var(--cm-primary)) !important;
                opacity: 1 !important;
                box-shadow: 0 0 8px rgba(var(--cm-primary-rgb),0.5);
            }
            .cm-slider::-webkit-slider-thumb {
                background: #fff !important;
                box-shadow: 0 0 0 3px rgba(var(--cm-primary-rgb),0.25), 0 2px 6px rgba(0,0,0,0.5) !important;
            }
            .cm-slider::-webkit-slider-thumb:hover {
                box-shadow: 0 0 0 5px rgba(var(--cm-primary-rgb),0.35), 0 2px 10px rgba(0,0,0,0.6) !important;
            }
            .cm-slider-value {
                background: rgba(var(--cm-primary-rgb),0.12) !important;
                border-color: rgba(var(--cm-primary-rgb),0.3) !important;
                color: var(--cm-text) !important;
            }

            /* ---- Segmented buttons: gradient active ---- */
            .cm-btn-group { border-radius: 8px !important; }
            .cm-btn-opt { border-radius: 6px !important; }
            .cm-btn-opt.active {
                background: linear-gradient(135deg, var(--cm-primary), var(--cm-secondary)) !important;
                color: #fff !important;
                box-shadow: 0 2px 10px rgba(var(--cm-primary-rgb),0.4) !important;
            }

            /* ---- Live / preview score: breathing animation ---- */
            .cm-live-score, .cm-preview {
                border: 1px solid rgba(var(--cm-primary-rgb),0.2) !important;
                border-radius: 12px !important;
            }
            .cm-score-value, .cm-preview-score { animation: cmScorePulse 3s ease-in-out infinite; }

            /* ---- File pickers ---- */
            .cm-file-picker { border-radius: 8px !important; }
            .cm-file-picker:hover {
                border-color: var(--cm-primary) !important;
                box-shadow: 0 0 0 2px rgba(var(--cm-primary-rgb),0.12);
            }

            /* ---- Theme swatches ---- */
            .cm-theme-btn { border-radius: 8px !important; }
            .cm-theme-btn:hover { transform: translateY(-2px) scale(1.03); }
            .cm-theme-btn.active { box-shadow: 0 0 0 1px var(--cm-primary), 0 0 12px rgba(var(--cm-primary-rgb),0.35) !important; }
            .cm-theme-preview { box-shadow: 0 2px 6px rgba(0,0,0,0.4); }

            /* ---- Troll panel ---- */
            #cm-ipgrab-log { background: transparent; border: none; font-family: 'JetBrains Mono', monospace; }
            #cm-ipgrab-log::-webkit-scrollbar { width: 2px; }
            #cm-ipgrab-log::-webkit-scrollbar-thumb { background: rgba(var(--cm-primary-rgb),0.2); border-radius: 2px; }

            /* ---- Small / panic buttons ---- */
            .cm-btn-small { border-radius: 6px !important; box-shadow: 0 2px 8px rgba(var(--cm-primary-rgb),0.3); }
            .cm-btn-small:active { transform: scale(0.96); }
            .cm-panic-btn { border-radius: 6px !important; transition: all 0.2s ease; }
            .cm-panic-btn:hover { box-shadow: 0 0 14px rgba(239,68,68,0.5); }

            /* ---- Inputs ---- */
            .cm-input, .cm-select { border-radius: 8px !important; }

            /* ---- Discord link shine ---- */
            .cm-discord-link { position: relative; overflow: hidden; }
            .cm-discord-link::after {
                content: ''; position: absolute; inset: 0;
                background: linear-gradient(115deg, transparent 40%, rgba(255,255,255,0.25) 50%, transparent 60%);
                background-size: 250% 100%;
                animation: cmSheen 4.5s ease-in-out infinite;
            }

            /* ---- Scrollbar ---- */
            .cm-body::-webkit-scrollbar-thumb {
                background: linear-gradient(var(--cm-secondary), var(--cm-primary)) !important;
                border-radius: 3px !important;
            }

            /* ---- Hook status spinner when pending ---- */
            #cm-zustand-val[data-pending="1"]::before {
                content: '';
                display: inline-block; width: 7px; height: 7px;
                margin-right: 5px; vertical-align: middle;
                border: 1.5px solid var(--cm-warning);
                border-top-color: transparent; border-radius: 50%;
                animation: cmSpin 0.8s linear infinite;
            }

            /* ============================================================
               TOP-CENTER QUICK CONTROL BAR
               ============================================================ */
            #cm-controlbar {
                position: fixed;
                top: 14px;
                left: 50%;
                transform: translateX(-50%) translateY(-4px);
                z-index: 999999;
                display: flex;
                align-items: center;
                gap: 6px;
                padding: 7px 9px;
                border-radius: 14px;
                background: var(--cm-bg-dark);
                backdrop-filter: blur(16px) saturate(140%);
                -webkit-backdrop-filter: blur(16px) saturate(140%);
                border: 1px solid rgba(var(--cm-primary-rgb),0.28);
                box-shadow:
                    0 0 0 1px rgba(255,255,255,0.03),
                    0 0 26px rgba(var(--cm-primary-rgb),0.12),
                    0 12px 30px rgba(0,0,0,0.5);
                font-family: 'Inter', -apple-system, sans-serif;
                opacity: 0;
                pointer-events: none;
                cursor: grab;
                transition: opacity 0.35s ease, transform 0.35s cubic-bezier(0.34,1.56,0.64,1);
            }
            #cm-controlbar.cm-cb-show { opacity: 1; transform: translateX(-50%) translateY(0); pointer-events: auto; }
            #cm-controlbar.cm-cb-hidden { display: none !important; }
            #cm-controlbar.cm-cb-dragging { cursor: grabbing; transition: opacity 0.35s ease; }
            #cm-controlbar::before {
                display: none !important;
            }
            .cm-cb-item {
                display: flex;
                align-items: center;
                gap: 6px;
                padding: 5px 9px 5px 6px;
                border-radius: 10px;
                background: rgba(255,255,255,0.03);
                border: 1px solid rgba(255,255,255,0.06);
                cursor: pointer;
                user-select: none;
                transition: background 0.2s ease, border-color 0.2s ease, transform 0.12s ease, box-shadow 0.2s ease;
            }
            .cm-cb-item:hover { transform: translateY(-1px); background: rgba(255,255,255,0.06); }
            .cm-cb-item:active { transform: translateY(0) scale(0.97); }
            .cm-cb-key {
                display: inline-flex;
                align-items: center;
                justify-content: center;
                min-width: 22px;
                height: 22px;
                padding: 0 5px;
                border-radius: 7px;
                font-size: 11px;
                font-weight: 800;
                color: var(--cm-text);
                background: linear-gradient(180deg, rgba(var(--cm-primary-rgb),0.18), rgba(var(--cm-primary-rgb),0.06));
                border: 1px solid rgba(var(--cm-primary-rgb),0.4);
                box-shadow: 0 1px 0 rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.08);
                text-shadow: 0 0 6px rgba(var(--cm-primary-rgb),0.4);
            }
            .cm-cb-label {
                font-size: 11px;
                font-weight: 600;
                letter-spacing: 0.2px;
                color: rgba(235,235,245,0.72);
                white-space: nowrap;
            }
            .cm-cb-dot {
                width: 7px; height: 7px; border-radius: 50%;
                background: #4b4b55;
                box-shadow: 0 0 0 2px rgba(255,255,255,0.04);
                transition: background 0.25s ease, box-shadow 0.25s ease;
            }
            .cm-cb-item.cm-on { border-color: rgba(var(--cm-primary-rgb),0.55); background: rgba(var(--cm-primary-rgb),0.10); }
            .cm-cb-item.cm-on .cm-cb-label { color: var(--cm-text); }
            .cm-cb-item.cm-on .cm-cb-dot {
                background: var(--cm-primary);
                box-shadow: 0 0 8px rgba(var(--cm-primary-rgb),0.8), 0 0 0 2px rgba(var(--cm-primary-rgb),0.18);
            }
            .cm-cb-item.cm-flash { animation: cmCbFlash 0.45s ease; }
            @keyframes cmCbFlash {
                0%   { box-shadow: 0 0 0 0 rgba(var(--cm-primary-rgb),0.55); }
                40%  { box-shadow: 0 0 0 5px rgba(var(--cm-primary-rgb),0.0); }
                100% { box-shadow: 0 0 0 0 rgba(var(--cm-primary-rgb),0.0); }
            }
            .cm-cb-sep { width: 1px; height: 20px; background: rgba(255,255,255,0.08); margin: 0 1px; }
            #cm-controlbar.stream-hidden { display: none !important; }

            @media (prefers-reduced-motion: reduce) {
                #cm-toggle-btn::before, #cm-toggle-btn::after,
                .cm-header::after, .cm-discord-link::after, .cm-title,
                #cm-root::before, .cm-logo-icon, .cm-pill.active,
                .cm-score-value, .cm-preview-score,
                #cm-controlbar::before, .cm-cb-item.cm-flash { animation: none !important; }
            }
        `;
        document.head.appendChild(style);

        applyTheme(CONFIG.theme || 'midnight');

        const btn = document.createElement('button');
        btn.id = 'cm-toggle-btn';
        btn.innerHTML = `<video autoplay muted loop playsinline src="https://v16m.tiktokcdn-us.com/b23435e11c9f7f9419e0287e41c8b532/6a31e5b4/video/tos/no1a/tos-no1a-ve-0068-no/owoRDEgqQ1ogRHElIB0aMkFDQGoA3FfmkOAe6k/?a=1233&bti=OUBzOTg7QGo6OjZAL3AjLTAzYCMxNDNg&&bt=1664&ft=kLx3-yt4Z9o0PDFS3k3aQ9PweKA6JE.C~&mime_type=video_mp4&rc=ZmQ2ZjM0aGQ1ZzY4M2QzZ0BpMzluZGw5cjw5MzMzbzczNUBfNDReXi82XzUxY2EtNC5iYSNeZS9hMmQ0cWFhLS1kMTFzcw%3D%3D&vvpl=1&l=20260616180916969A7621F7670E143221&btag=e000b0000" style="width:40px;height:40px;border-radius:6px;object-fit:cover;"></video>`;
        document.body.appendChild(btn);

        // Top-center quick control bar
        const controlBar = document.createElement('div');
        controlBar.id = 'cm-controlbar';
        controlBar.innerHTML = `
            <div class="cm-cb-item" data-cb="master" title="Toggle Master Switch (M)">
                <span class="cm-cb-key">M</span>
                <span class="cm-cb-label">Master</span>
                <span class="cm-cb-dot"></span>
            </div>
            <div class="cm-cb-sep"></div>
            <div class="cm-cb-item" data-cb="camera" title="Toggle Camera Spoof (C)">
                <span class="cm-cb-key">C</span>
                <span class="cm-cb-label">Camera</span>
                <span class="cm-cb-dot"></span>
            </div>
            <div class="cm-cb-sep"></div>
            <div class="cm-cb-item" data-cb="audio" title="Toggle Audio Spoof (A)">
                <span class="cm-cb-key">A</span>
                <span class="cm-cb-label">Audio</span>
                <span class="cm-cb-dot"></span>
            </div>
            <div class="cm-cb-sep"></div>
            <div class="cm-cb-item" data-cb="crosshair" title="Toggle Custom Crosshair (X)">
                <span class="cm-cb-key">X</span>
                <span class="cm-cb-label">Crosshair</span>
                <span class="cm-cb-dot"></span>
            </div>
        `;
        document.body.appendChild(controlBar);
        const _isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) || (navigator.maxTouchPoints > 0 && window.innerWidth < 1024);
        if (!_isMobile) {
            requestAnimationFrame(function() { controlBar.classList.add('cm-cb-show'); });
        } else {
            controlBar.style.display = 'none';
        }

        const root = document.createElement('div');
        root.id = 'cm-root';
        root.innerHTML = `
            <div class="cm-header">
                <div class="cm-title-row">
                    <div class="cm-logo">
                        <div class="cm-logo-icon">
                            <video autoplay muted loop playsinline src="https://v16m.tiktokcdn-us.com/b23435e11c9f7f9419e0287e41c8b532/6a31e5b4/video/tos/no1a/tos-no1a-ve-0068-no/owoRDEgqQ1ogRHElIB0aMkFDQGoA3FfmkOAe6k/?a=1233&bti=OUBzOTg7QGo6OjZAL3AjLTAzYCMxNDNg&&bt=1664&ft=kLx3-yt4Z9o0PDFS3k3aQ9PweKA6JE.C~&mime_type=video_mp4&rc=ZmQ2ZjM0aGQ1ZzY4M2QzZ0BpMzluZGw5cjw5MzMzbzczNUBfNDReXi82XzUxY2EtNC5iYSNeZS9hMmQ0cWFhLS1kMTFzcw%3D%3D&vvpl=1&l=20260616180916969A7621F7670E143221&btag=e000b0000" style="width:68px;height:68px;border-radius:10px;object-fit:cover;display:block;"></video>
                        </div>
                        <div>
                            <span class="cm-title">Marlon Helper</span>
                            <span class="cm-free-badge">FREE</span>
                            <span class="cm-version">v13.8.0</span>
                        </div>
                    </div>
                    <a href="https://discord.gg/U6sQEp83qq" target="_blank" class="cm-discord-link">
                        <svg viewBox="0 0 24 24"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/></svg>
                        Join Discord
                    </a>
                </div>
                <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;">
                    <div class="cm-status-row">
                        <span class="cm-pill active" id="cm-status-pill">ON</span>
                        <span class="cm-pill mode" id="cm-mode-pill">NORMAL</span>
                    </div>
                </div>
                <div class="cm-tabs">
                        <button class="cm-tab active" data-tab="home">Home</button>
                        <button class="cm-tab" data-tab="score">Score</button>
                        <button class="cm-tab" data-tab="automation">Auto</button>
                        <button class="cm-tab cm-tab-locked" data-tab="camera">Camera</button>
                        <button class="cm-tab" data-tab="settings">Settings</button>
                        <button class="cm-tab cm-tab-locked" data-tab="troll">Troll</button>
                        <button class="cm-tab cm-tab-locked" data-tab="crosshair">Crosshair</button>
                        <button class="cm-tab" data-tab="credits">Credits</button>
                </div>
            </div>

            <div class="cm-body">
                <!-- HOME PANEL -->
                <div class="cm-panel active" data-panel="home">
                    <div class="cm-section" id="cm-waifu-section" style="display:none;">
                        <div style="margin-bottom:8px;border-radius:10px;border:2px solid var(--cm-primary);overflow:hidden;height:450px;box-shadow:0 0 20px rgba(var(--cm-primary-rgb),0.3);">
                            <img id="cm-waifu-img" src="https://cdn.frostedbrowser.cfd/cheatmoggle-assets/cheatmogglewaifu.png" style="width:100%;height:100%;object-fit:cover;object-position:center 30%;display:block;">
                        </div>
                    </div>
                    <div class="cm-section">
                        <div class="cm-section-title">System Status</div>
                        <div class="cm-card">
                            <div class="cm-row">
                                <span class="cm-label">Master Switch</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-enable-toggle" checked>
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                            <div class="cm-row">
                                <span class="cm-label">Power Status</span>
                                <span class="cm-value" id="cm-enabled-val" style="color: var(--cm-success)">ACTIVE</span>
                            </div>
                            <div class="cm-row">
                                <span class="cm-label">Match Type</span>
                                <span class="cm-value" id="cm-mode-val">NORMAL</span>
                            </div>
                            <div class="cm-row">
                                <span class="cm-label">Hook Status</span>
                                <span class="cm-value" id="cm-zustand-val" data-pending="1" style="color: var(--cm-warning)">PENDING</span>
                            </div>
                            <div class="cm-row" style="border-bottom:none;padding-top:6px;display:flex;gap:6px;">
                                <button class="cm-panic-btn" id="cm-clearcookies-btn" style="margin:0;flex:1;">Unban / Clear Cookies</button>
                                <button class="cm-panic-btn" id="cm-verifbypass-btn" style="margin:0;flex:1;background:var(--cm-accent);color:#fff;">Verification Bypass</button>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- SCORE PANEL -->
                <div class="cm-panel" data-panel="score">
                    <div class="cm-section">
                        <div class="cm-section-title">
                            <span>Score Control</span>
                            <label class="cm-toggle cm-section-toggle">
                                <input type="checkbox" id="cm-score-enabled" checked>
                                <div class="cm-toggle-track"></div>
                                <div class="cm-toggle-thumb"></div>
                            </label>
                        </div>
                        <div class="cm-card" id="cm-score-content">
                            <div class="cm-row">
                                <span class="cm-label">Mode</span>
                                <div class="cm-btn-group">
                                    <button class="cm-btn-opt active" data-smode="range">Range</button>
                                    <button class="cm-btn-opt" data-smode="fixed">Fixed</button>
                                </div>
                            </div>
                            <div id="cm-score-fixed" style="display:none;">
                                <div class="cm-slider-row">
                                    <div class="cm-slider-header">
                                        <span class="cm-slider-label">Score</span>
                                        <input type="number" class="cm-input cm-score-input" id="cm-fixed-score" step="0.1" value="9.4" style="width:70px;text-align:center;">
                                    </div>
                                </div>
                            </div>
                            <div id="cm-score-range">
                                <div class="cm-slider-row">
                                    <div class="cm-slider-header">
                                        <span class="cm-slider-label">Min</span>
                                        <input type="number" class="cm-input cm-score-input" id="cm-score-min" step="0.1" value="8.5" style="width:70px;text-align:center;">
                                    </div>
                                </div>
                                <div class="cm-slider-row">
                                    <div class="cm-slider-header">
                                        <span class="cm-slider-label">Max</span>
                                        <input type="number" class="cm-input cm-score-input" id="cm-score-max" step="0.1" value="9.5" style="width:70px;text-align:center;">
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>

                    <div class="cm-section">
                        <div class="cm-section-title">
                            <span>Result Settings</span>
                            <label class="cm-toggle cm-section-toggle">
                                <input type="checkbox" id="cm-result-enabled" checked>
                                <div class="cm-toggle-track"></div>
                                <div class="cm-toggle-thumb"></div>
                            </label>
                        </div>
                        <div class="cm-card" id="cm-result-content">
                            <div class="cm-row">
                                <span class="cm-label">Type</span>
                                <div class="cm-btn-group">
                                    <button class="cm-btn-opt active" data-fmode="fixed">Static</button>
                                    <button class="cm-btn-opt" data-fmode="range">Dynamic</button>
                                </div>
                            </div>
                            <div id="cm-final-fixed">
                                <div class="cm-slider-row">
                                    <div class="cm-slider-header">
                                        <span class="cm-slider-label">Target</span>
                                        <input type="number" class="cm-input cm-score-input" id="cm-final-score" step="0.1" value="9.4" style="width:70px;text-align:center;">
                                    </div>
                                </div>
                            </div>
                            <div id="cm-final-range" style="display:none;">
                                <div class="cm-slider-row">
                                    <div class="cm-slider-header">
                                        <span class="cm-slider-label">Lower Bound</span>
                                        <input type="number" class="cm-input cm-score-input" id="cm-final-range-min" step="0.1" value="8.5" style="width:70px;text-align:center;">
                                    </div>
                                </div>
                                <div class="cm-slider-row">
                                    <div class="cm-slider-header">
                                        <span class="cm-slider-label">Upper Bound</span>
                                        <input type="number" class="cm-input cm-score-input" id="cm-final-range-max" step="0.1" value="9.7" style="width:70px;text-align:center;">
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="cm-preview">
                            <div class="cm-preview-score" id="cm-score-preview-num" style="color:#f472b6">9.6</div>
                            <div class="cm-preview-tier" id="cm-score-preview-tier" style="color:#f472b6;display:none;">Slayer</div>
                        </div>
                    </div>
                </div>

                <!-- AUTOMATION PANEL -->
                <div class="cm-panel" data-panel="automation">
                    <div class="cm-section">
                        <div class="cm-section-title">Matchmaking</div>
                        <div class="cm-card">
                            <div class="cm-row">
                                <span class="cm-label">Auto Queue</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-autoqueuetoggle">
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                            <div class="cm-row">
                                <span class="cm-label">Request Delay (ms)</span>
                                <input type="number" class="cm-input" id="cm-queue-delay" min="100" max="60000" step="100" value="1000" style="width:80px;text-align:center;">
                            </div>
                            <div class="cm-row" style="border-bottom:none;">
                                <span class="cm-label">Auto Find New Match</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-autofindnew-toggle" checked>
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                        </div>
                    </div>

                    <div class="cm-section">
                        <div class="cm-section-title">Spoof Cycling</div>
                        <div class="cm-card">
                            <div class="cm-row">
                                <span class="cm-label">Auto Cycle Camera</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-autocam-toggle">
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                            <div class="cm-row">
                                <span class="cm-label">Camera Interval (s)</span>
                                <input type="number" class="cm-input" id="cm-autocam-interval" min="1" max="600" step="1" value="5" style="width:80px;text-align:center;">
                            </div>
                            <div class="cm-row">
                                <span class="cm-label">Auto Cycle Audio</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-autoaudio-toggle">
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                            <div class="cm-row" style="border-bottom:none;">
                                <span class="cm-label">Audio Interval (s)</span>
                                <input type="number" class="cm-input" id="cm-autoaudio-interval" min="1" max="600" step="1" value="5" style="width:80px;text-align:center;">
                            </div>
                        </div>
                    </div>

                    <div class="cm-section">
                        <div class="cm-section-title">Convenience</div>
                        <div class="cm-card">
                            <div class="cm-row">
                                <span class="cm-label">Auto Dismiss Popups</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-autodismiss-toggle">
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                            <div class="cm-row" style="border-bottom:none;">
                                <span class="cm-label">Auto Clear Cookies on Ban</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-autounban-toggle">
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- CAMERA PANEL -->
                <div class="cm-panel" data-panel="camera">
                    <div class="cm-section">
                        <div class="cm-section-title">Virtual Camera</div>
                        <div class="cm-card">
                            <div class="cm-row">
                                <span class="cm-label">Activate Spoof</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-camspoof-toggle">
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                            <div class="cm-row">
                                <span class="cm-label">Flip Horizontal</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-cammirror-toggle">
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                            <div class="cm-row">
                                <span class="cm-label">Loop Video</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-camloop-toggle" checked>
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                            <div class="cm-slider-row">
                                <div class="cm-slider-header">
                                    <span class="cm-slider-label">Playback Speed</span>
                                    <span class="cm-slider-value" id="cm-camspeed-val">1.0x</span>
                                </div>
                                <div class="cm-slider-track">
                                    <div class="cm-slider-fill" id="cm-camspeed-fill" style="width:25%"></div>
                                    <input type="range" class="cm-slider" id="cm-camspeed" min="0.25" max="4.0" step="0.25" value="1.0">
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="cm-section">
                        <div class="cm-section-title">Source</div>
                        <div class="cm-card">
                            <div class="cm-btn-group" style="margin-bottom:6px;">
                                <button class="cm-btn-opt" data-src="video">Video</button>
                                <button class="cm-btn-opt" data-src="image">Image</button>
                            </div>
                            <div class="cm-file-picker" id="cm-video-picker" style="display:none;">
                                <div class="cm-file-icon">
                                    <svg viewBox="0 0 24 24"><path d="M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zm-1 7V3.5L18.5 9H13z"/></svg>
                                </div>
                                <span class="cm-file-name" id="cm-video-name">Select video file...</span>
                            </div>
                            <div class="cm-file-picker" id="cm-image-picker" style="display:none;">
                                <div class="cm-file-icon">
                                    <svg viewBox="0 0 24 24"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></svg>
                                </div>
                                <span class="cm-file-name" id="cm-image-name">Select image file...</span>
                            </div>
                        </div>
                    </div>
                    <div class="cm-section">
                        <div class="cm-section-title">Text Overlay</div>
                        <div class="cm-card">
                            <div class="cm-row">
                                <span class="cm-label">Enable Text</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-camtext-toggle">
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                            <div class="cm-row">
                                <span class="cm-label">Content</span>
                                <input type="text" class="cm-input" id="cm-camtext-content" value="Your Text Here" style="width:100px;">
                            </div>
                            <div class="cm-row">
                                <span class="cm-label">Color</span>
                                <input type="color" class="cm-color-input" id="cm-camtext-color" value="#ffffff">
                            </div>
                            <div class="cm-slider-row">
                                <div class="cm-slider-header">
                                    <span class="cm-slider-label">Size</span>
                                    <span class="cm-slider-value" id="cm-camtext-size-val">24px</span>
                                </div>
                                <div class="cm-slider-track">
                                    <div class="cm-slider-fill" id="cm-camtext-size-fill" style="width:50%"></div>
                                    <input type="range" class="cm-slider" id="cm-camtext-size" min="8" max="72" step="1" value="24">
                                </div>
                            </div>
                        </div>
                    </div>
                    <!-- CAMERA OVERLAY -->
                    <div class="cm-section">
                        <div class="cm-section-title">Camera Overlay</div>
                        <div class="cm-card">
                            <div id="cm-premium-tab-bar" style="display:flex;gap:4px;margin-bottom:6px;flex-wrap:wrap;align-items:center;">
                                <div id="cm-premium-tab-scroll" style="display:flex;gap:4px;flex:1;overflow-x:auto;"></div>
                                <button id="cm-premium-tab-add" style="background:var(--cm-bg-elevated);border:1px dashed var(--cm-border);color:var(--cm-text-muted);border-radius:6px;padding:4px 10px;cursor:pointer;font-size:11px;font-weight:700;flex-shrink:0;">+ Add</button>
                            </div>
                            <div class="cm-row" style="margin-bottom:4px;">
                                <span class="cm-label">Active</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-premium-toggle">
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                            <div class="cm-btn-group" style="margin-bottom:6px;">
                                <button class="cm-btn-opt active" data-premium-src="image">Image</button>
                                <button class="cm-btn-opt" data-premium-src="video">Video</button>
                                <button class="cm-btn-opt" data-premium-src="text">Text</button>
                            </div>
                            <div class="cm-file-picker" id="cm-premium-img-picker">
                                <div class="cm-file-icon">
                                    <svg viewBox="0 0 24 24"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></svg>
                                </div>
                                <span class="cm-file-name" id="cm-premium-img-name">Select image...</span>
                            </div>
                            <div class="cm-file-picker" id="cm-premium-vid-picker" style="display:none">
                                <div class="cm-file-icon">
                                    <svg viewBox="0 0 24 24"><path d="M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zm-1 7V3.5L18.5 9H13z"/></svg>
                                </div>
                                <span class="cm-file-name" id="cm-premium-vid-name">Select video...</span>
                            </div>
                            <div id="cm-premium-text-controls" style="display:none;">
                                <div class="cm-row">
                                    <span class="cm-label">Content</span>
                                    <input type="text" class="cm-input" id="cm-premium-text-content" value="Your Text Here" style="width:100px;">
                                </div>
                                <div class="cm-row">
                                    <span class="cm-label">Color</span>
                                    <input type="color" class="cm-color-input" id="cm-premium-text-color" value="#ffffff">
                                </div>
                            </div>
                            <div class="cm-slider-row">
                                <div class="cm-slider-header">
                                    <span class="cm-slider-label">Overlay Size</span>
                                    <span class="cm-slider-value" id="cm-premium-size-val">30%</span>
                                </div>
                                <div class="cm-slider-track">
                                    <div class="cm-slider-fill" id="cm-premium-size-fill" style="width:30%"></div>
                                    <input type="range" class="cm-slider" id="cm-premium-size" min="5" max="100" step="1" value="30">
                                </div>
                            </div>
                            <div class="cm-slider-row">
                                <div class="cm-slider-header">
                                    <span class="cm-slider-label">Opacity</span>
                                    <span class="cm-slider-value" id="cm-premium-opacity-val">100%</span>
                                </div>
                                <div class="cm-slider-track">
                                    <div class="cm-slider-fill" id="cm-premium-opacity-fill" style="width:100%"></div>
                                    <input type="range" class="cm-slider" id="cm-premium-opacity" min="10" max="100" step="5" value="100">
                                </div>
                            </div>
                            <div style="margin-top:8px;border-radius:8px;overflow:hidden;background:#111;position:relative;width:100%;aspect-ratio:4/3;cursor:move;" id="cm-premium-preview">
                                <div id="cm-premium-overlay-el" style="position:absolute;border:2px solid rgba(0,200,255,0.6);background:rgba(0,200,255,0.1);border-radius:4px;cursor:move;display:flex;align-items:center;justify-content:center;font-size:11px;color:rgba(0,200,255,0.5);overflow:hidden;pointer-events:auto;">
                                    <span style="pointer-events:none;">Overlay</span>
                                    <div id="cm-premium-resize" style="position:absolute;bottom:-4px;right:-4px;width:10px;height:10px;background:#00c8ff;border-radius:2px;cursor:nwse-resize;pointer-events:auto;"></div>
                                </div>
                            </div>
                            <div style="display:flex;gap:6px;margin-top:4px;font-size:10px;color:var(--cm-text-muted);">
                                <span>Position: <span id="cm-premium-pos">160, 120</span></span>
                                <span>Size: <span id="cm-premium-dim">192x144</span></span>
                            </div>
                        </div>
                    </div>
                    <!-- Audio spoof section -->
                    <div class="cm-section">
                        <div class="cm-section-title">Audio Spoof</div>
                        <div class="cm-card">
                            <div class="cm-row">
                                <span class="cm-label">Activate Audio Spoof</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-audiospoof-toggle">
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                            <div class="cm-file-picker" id="cm-audio-picker">
                                <div class="cm-file-icon">
                                    <svg viewBox="0 0 24 24"><path d="M12 3v10.55c-.59-.34-1.27-.55-2-.55-2.21 0-4 1.79-4 4s1.79 4 4 4 4-1.79 4-4V7h4V3h-6z"/></svg>
                                </div>
                                <span class="cm-file-name" id="cm-audio-name">Select audio file...</span>
                            </div>
                            <div class="cm-row">
                                <span class="cm-label">Loop</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-audioloop-toggle" checked>
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                            <div class="cm-slider-row">
                                <div class="cm-slider-header">
                                    <span class="cm-slider-label">Speed</span>
                                    <span class="cm-slider-value" id="cm-audiospeed-val">1.0x</span>
                                </div>
                                <div class="cm-slider-track">
                                    <div class="cm-slider-fill" id="cm-audiospeed-fill" style="width:25%"></div>
                                    <input type="range" class="cm-slider" id="cm-audiospeed" min="0.25" max="3.0" step="0.05" value="1.0">
                                </div>
                            </div>
                            <div class="cm-slider-row">
                                <div class="cm-slider-header">
                                    <span class="cm-slider-label">Volume</span>
                                    <span class="cm-slider-value" id="cm-audiovolume-val">100%</span>
                                </div>
                                <div class="cm-slider-track">
                                    <div class="cm-slider-fill" id="cm-audiovolume-fill" style="width:100%"></div>
                                    <input type="range" class="cm-slider" id="cm-audiovolume" min="0" max="100" step="1" value="100">
                                </div>
                            </div>
                            <div class="cm-slider-row">
                                <div class="cm-slider-header">
                                    <span class="cm-slider-label">Bass (dB)</span>
                                    <span class="cm-slider-value" id="cm-audiobass-val">0 dB</span>
                                </div>
                                <div class="cm-slider-track">
                                    <div class="cm-slider-fill" id="cm-audiobass-fill" style="width:50%"></div>
                                    <input type="range" class="cm-slider" id="cm-audiobass" min="-12" max="12" step="1" value="0">
                                </div>
                            </div>
                            <div class="cm-slider-row">
                                <div class="cm-slider-header">
                                    <span class="cm-slider-label">Treble (dB)</span>
                                    <span class="cm-slider-value" id="cm-audiotreble-val">0 dB</span>
                                </div>
                                <div class="cm-slider-track">
                                    <div class="cm-slider-fill" id="cm-audiotreble-fill" style="width:50%"></div>
                                    <input type="range" class="cm-slider" id="cm-audiotreble" min="-12" max="12" step="1" value="0">
                                </div>
                            </div>
                            <div class="cm-slider-row">
                                <div class="cm-slider-header">
                                    <span class="cm-slider-label">Warmth (dB)</span>
                                    <span class="cm-slider-value" id="cm-audiowarmth-val">0 dB</span>
                                </div>
                                <div class="cm-slider-track">
                                    <div class="cm-slider-fill" id="cm-audiowarmth-fill" style="width:50%"></div>
                                    <input type="range" class="cm-slider" id="cm-audiowarmth" min="-12" max="12" step="1" value="0">
                                </div>
                            </div>
                            <div class="cm-row">
                                <span class="cm-label">Status</span>
                                <span class="cm-value" id="cm-audio-status">Inactive</span>
                            </div>
                        </div>
                    </div>

                </div>

                <!-- SETTINGS PANEL -->
                <div class="cm-panel" data-panel="settings">
                    <div class="cm-section">
                        <div class="cm-section-title">Developer</div>
                        <div class="cm-card">
                            <div class="cm-row">
                                <span class="cm-label">Console Logs</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-debug-toggle" checked>
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                        </div>
                    </div>
                    <div class="cm-section">
                        <div class="cm-section-title">Hotkeys</div>
                        <div class="cm-card">
                            <div class="cm-row">
                                <span class="cm-label">Open Panel</span>
                                <input type="text" class="cm-input" id="cm-menukey" value="h" style="width:50px;text-align:center;">
                            </div>
                        </div>
                    </div>
                    <div class="cm-section">
                        <div class="cm-section-title">Stream Proof</div>
                        <div class="cm-card">
                            <div class="cm-row">
                                <span class="cm-label">Panic Key</span>
                                <input type="text" class="cm-input" id="cm-panic-key" value="p" style="width:50px;text-align:center;">
                            </div>
                            <div class="cm-row">
                                <span class="cm-label">Mobile: Triple-tap button</span>
                                <span class="cm-value" style="font-size:8px;color:var(--cm-text-muted);">to hide/show</span>
                            </div>
                            <div class="cm-row">
                                <span class="cm-label">Show Control Bar</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-show-cb-toggle" checked>
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                            <div class="cm-row">
                                <button class="cm-panic-btn" id="cm-panic-now">Hide All Now</button>
                            </div>
                            <div class="cm-row" style="margin-top:6px;border-top:1px solid var(--cm-border);padding-top:6px;">
                                <span class="cm-label">Iframe Mode (OBS)</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-iframe-mode">
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                            <div class="cm-row">
                                <span class="cm-label" style="font-size:8px;color:var(--cm-text-muted);">Hides GUI from screen capture</span>
                            </div>
                        </div>
                    </div>
                    <div class="cm-section">
                        <div class="cm-section-title">Branding</div>
                        <div class="cm-card">
                            <div class="cm-row">
                                <span class="cm-label">Display Badge</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-wm-show" checked>
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                            <div class="cm-slider-row">
                                <div class="cm-slider-header">
                                    <span class="cm-slider-label">Visibility</span>
                                    <span class="cm-slider-value" id="cm-wm-alpha-val">20%</span>
                                </div>
                                <div class="cm-slider-track">
                                    <div class="cm-slider-fill" id="cm-wm-alpha-fill" style="width:20%"></div>
                                    <input type="range" class="cm-slider" id="cm-wm-alpha" min="0" max="100" step="5" value="20">
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="cm-section">
                        <div class="cm-section-title">Appearance</div>
                        <div class="cm-card">
                            <div class="cm-theme-grid" id="cm-theme-grid"></div>
                            <div class="cm-row" style="border-top:1px solid var(--cm-border);padding-top:8px;margin-top:4px;">
                                <span class="cm-label">Custom Crosshair</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-crosshair-toggle">
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- TROLL PANEL -->
                <div class="cm-panel" data-panel="troll">
                    <div class="cm-section">
                        <div class="cm-section-title">Mirror Cam</div>
                        <div class="cm-card">
                            <div class="cm-row">
                                <span class="cm-label">Mirror Opponent Cam</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-mirror-toggle">
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                            <div class="cm-row">
                                <span class="cm-label">Status</span>
                                <span class="cm-value" id="cm-mirror-status">Waiting for opponent cam...</span>
                            </div>
                            <div class="cm-row">
                                <span class="cm-label">Opponent Feed</span>
                                <span class="cm-value" id="cm-mirror-track" style="font-size:9px;word-break:break-all;max-width:140px;text-align:right;">—</span>
                            </div>
                            <div class="cm-row" style="border-bottom:none;flex-direction:column;gap:4px;">
                                <video id="cm-opponent-video" autoplay playsinline muted style="width:100%;border-radius:6px;background:#000;max-height:180px;object-fit:contain;"></video>
                                <div style="display:flex;gap:4px;align-items:center;">
                                    <button id="cm-record-opponent" style="flex:1;padding:4px 8px;background:var(--cm-danger);color:#fff;border:none;border-radius:4px;cursor:pointer;font-size:10px;">● Record</button>
                                    <span id="cm-record-status" style="font-size:9px;color:var(--cm-text-muted);">Idle</span>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div class="cm-section">
                        <div class="cm-section-title">Log</div>
                        <div class="cm-card" style="max-height:120px;overflow-y:auto;">
                            <pre id="cm-ipgrab-log" style="margin:0;font-size:8px;color:var(--cm-text-muted);white-space:pre-wrap;word-break:break-all;"></pre>
                        </div>
                    </div>
                </div>

                <!-- CROSSHAIR PANEL -->
                <div class="cm-panel" data-panel="crosshair">
                    <div class="cm-section">
                        <div class="cm-section-title">Custom Crosshair</div>
                        <div class="cm-card">
                            <div class="cm-row">
                                <span class="cm-label">Enable Crosshair</span>
                                <label class="cm-toggle">
                                    <input type="checkbox" id="cm-crosshair-toggle">
                                    <div class="cm-toggle-track"></div>
                                    <div class="cm-toggle-thumb"></div>
                                </label>
                            </div>
                            <div class="cm-row">
                                <span class="cm-label">Status</span>
                                <span class="cm-value" id="cm-crosshair-status" style="color: var(--cm-text-muted)">OFF</span>
                            </div>
                            <div class="cm-row" style="border-bottom:none;">
                                <span class="cm-label" style="font-size:9px;color:var(--cm-text-muted);">Crosshair always shows on intro screen. Toggle ON to keep it active after.</span>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- CREDITS PANEL -->
                <div class="cm-panel" data-panel="credits">
                    <div class="cm-section">
                        <div class="cm-section-title" style="text-align:center;font-size:13px;margin-bottom:12px;">Credits</div>
                        
                        <!-- Marlon Helper Team -->
                        <div class="cm-card" style="padding:14px;margin-bottom:10px;border-radius:10px;">
                            <div style="text-align:center;margin-bottom:10px;">
                                <span style="font-size:11px;font-weight:600;color:var(--cm-text-muted);text-transform:uppercase;letter-spacing:0.04em;">Marlon Helper Team</span>
                            </div>
                            <div style="font-size:10px;color:var(--cm-text-muted);text-align:center;line-height:1.6;">
                                Built with care for the community.<br>
                                Thank you to everyone who contributed!
                            </div>
                        </div>

                        <!-- Discord Link -->
                        <a href="https://discord.gg/U6sQEp83qq" target="_blank" style="display:flex;align-items:center;justify-content:center;gap:10px;padding:12px 16px;background:rgba(88,101,242,0.1);border:1px solid rgba(88,101,242,0.25);border-radius:10px;text-decoration:none;transition:all 0.2s ease;margin-bottom:8px;">
                            <svg viewBox="0 0 24 24" width="22" height="22" fill="#5865F2"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/></svg>
                            <div style="display:flex;flex-direction:column;">
                                <span style="font-size:12px;font-weight:700;color:#5865F2;">Join our Discord</span>
                                <span style="font-size:9px;color:var(--cm-text-muted);">Updates, support & community</span>
                            </div>
                        </a>

                        <!-- Version info -->
                        <div style="text-align:center;padding:8px 0;margin-top:4px;">
                            <span style="font-size:9px;color:var(--cm-text-muted);opacity:0.6;">Marlon Helper v13.8.0</span>
                        </div>
                    </div>
                </div>
            </div>
        `;

        ['top','bottom','left','right','tl','tr','bl','br'].forEach(dir => {
            const h = document.createElement('div');
            h.className = 'cm-resize-handle cm-rz-' + dir;
            root.appendChild(h);
            h.addEventListener('mousedown', e => {
                e.preventDefault();
                e.stopPropagation();
                const startX = e.clientX, startY = e.clientY;
                const startW = root.offsetWidth, startH = root.offsetHeight;
                const startT = root.offsetTop, startL = root.offsetLeft;
                root.classList.add('dragging');
                const onMove = ev => {
                    const dx = ev.clientX - startX, dy = ev.clientY - startY;
                    if (dir.includes('right') || dir === 'tr' || dir === 'br') root.style.width = Math.max(200, startW + dx) + 'px';
                    if (dir.includes('left') || dir === 'tl' || dir === 'bl') { root.style.width = Math.max(200, startW - dx) + 'px'; root.style.left = (startL + dx) + 'px'; }
                    if (dir.includes('bottom') || dir === 'bl' || dir === 'br') root.style.height = Math.max(150, startH + dy) + 'px';
                    if (dir.includes('top') || dir === 'tl' || dir === 'tr') { root.style.height = Math.max(150, startH - dy) + 'px'; root.style.top = (startT + dy) + 'px'; }
                };
                const onUp = () => { root.classList.remove('dragging'); document.removeEventListener('mousemove', onMove); document.removeEventListener('mouseup', onUp); };
                document.addEventListener('mousemove', onMove);
                document.addEventListener('mouseup', onUp);
            });
        });

        document.body.appendChild(root);
        root.classList.add('visible');

        // Re-apply theme to ensure dynamic elements (title, logo, waifu) are in sync
        applyTheme(CONFIG.theme || 'midnight');

        // Create hidden file inputs
        const videoFileInput = document.createElement('input');
        videoFileInput.type = 'file';
        videoFileInput.accept = 'video/mp4,video/webm,video/quicktime';
        videoFileInput.style.display = 'none';
        videoFileInput.id = 'cm-video-input';
        document.body.appendChild(videoFileInput);

        const imageFileInput = document.createElement('input');
        imageFileInput.type = 'file';
        imageFileInput.accept = 'image/jpeg,image/png,image/gif,image/webp';
        imageFileInput.style.display = 'none';
        imageFileInput.id = 'cm-image-input';
        document.body.appendChild(imageFileInput);

        const audioFileInput = document.createElement('input');
        audioFileInput.type = 'file';
        audioFileInput.accept = 'audio/mpeg,audio/wav,audio/ogg,audio/mp4';
        audioFileInput.style.display = 'none';
        audioFileInput.id = 'cm-audio-input';
        document.body.appendChild(audioFileInput);

        // Premium overlay file inputs
        const premiumImgInput = document.createElement('input');
        premiumImgInput.type = 'file';
        premiumImgInput.accept = 'image/jpeg,image/png,image/gif,image/webp';
        premiumImgInput.style.display = 'none';
        premiumImgInput.id = 'cm-premium-img-input';
        document.body.appendChild(premiumImgInput);

        const premiumVidInput = document.createElement('input');
        premiumVidInput.type = 'file';
        premiumVidInput.accept = 'video/mp4,video/webm,video/quicktime';
        premiumVidInput.style.display = 'none';
        premiumVidInput.id = 'cm-premium-vid-input';
        document.body.appendChild(premiumVidInput);

        // Premium overlay state (multi-tab)
        let _premiumOverlays = [];
        let _premiumActiveIndex = 0;
        function _createOverlay(name) {
            return { enabled: true, srcType: 'image', el: null, x: 160, y: 120, w: 192, h: 144, textContent: 'Text', textColor: '#ffffff', textFontSize: 24, opacity: 100, fileName: '' };
        }
        function _activeOverlay() { return _premiumOverlays[_premiumActiveIndex] || _premiumOverlays[0]; }

        // Build theme grid
        const themeGrid = document.getElementById('cm-theme-grid');
        Object.entries(THEMES).forEach(([key, theme]) => {
            const tbtn = document.createElement('button');
            tbtn.className = 'cm-theme-btn' + (key === (CONFIG.theme || 'midnight') ? ' active' : '');
            tbtn.dataset.theme = key;
            tbtn.innerHTML = `
                <div class="cm-theme-preview" style="background: linear-gradient(135deg, ${theme.primary}, ${theme.secondary})"></div>
                <div class="cm-theme-name">${theme.name}</div>
            `;
            tbtn.addEventListener('click', function() {
                themeGrid.querySelectorAll('.cm-theme-btn').forEach(b => b.classList.remove('active'));
                this.classList.add('active');
                applyTheme(key);
            });
            themeGrid.appendChild(tbtn);
        });

        // Crosshair toggle
        const crosshairToggle = document.getElementById('cm-crosshair-toggle');
        const crosshairStatus = document.getElementById('cm-crosshair-status');
        if (crosshairToggle) {
            crosshairToggle.checked = CONFIG.crosshairEnabled === true;
            if (crosshairStatus) {
                crosshairStatus.textContent = CONFIG.crosshairEnabled ? 'ON' : 'OFF';
                crosshairStatus.style.color = CONFIG.crosshairEnabled ? 'var(--cm-success)' : 'var(--cm-text-muted)';
            }
            crosshairToggle.addEventListener('change', function() {
                CONFIG.crosshairEnabled = this.checked;
                saveConfig();
                applyCrosshairState();
                if (crosshairStatus) {
                    crosshairStatus.textContent = this.checked ? 'ON' : 'OFF';
                    crosshairStatus.style.color = this.checked ? 'var(--cm-success)' : 'var(--cm-text-muted)';
                }
            });
        }

        function applyCrosshairState() {
            let styleEl = document.getElementById('cm-crosshair-style');
            if (CONFIG.crosshairEnabled) {
                document.documentElement.style.cursor = 'url(data:image/png;base64,' + _cursorB64 + ') 24 24, auto';
                if (!styleEl) {
                    styleEl = document.createElement('style');
                    styleEl.id = 'cm-crosshair-style';
                    document.head.appendChild(styleEl);
                }
                styleEl.textContent = 'html, body, * { cursor: url(data:image/png;base64,' + _cursorB64 + ') 24 24, auto !important; }';
            } else {
                document.documentElement.style.cursor = '';
                if (styleEl) styleEl.remove();
            }
        }

        // Toggle menu
        let _btnDragged = false;
        function _toggleMenu() {
            if (_btnDragged) { _btnDragged = false; return; }
            root.classList.toggle('visible');
        }
        btn.addEventListener('click', _toggleMenu);

        // Toggle button drag
        let _btnDragging = false, _btnDragOffX = 0, _btnDragOffY = 0, _btnStartX = 0, _btnStartY = 0;
        btn.addEventListener('mousedown', function(e) {
            _btnDragging = true; _btnDragged = false;
            _btnStartX = e.clientX; _btnStartY = e.clientY;
            const rect = btn.getBoundingClientRect();
            _btnDragOffX = e.clientX - rect.left; _btnDragOffY = e.clientY - rect.top;
            btn.classList.add('dragging'); e.preventDefault();
        });
        document.addEventListener('mousemove', function(e) {
            if (!_btnDragging) return;
            if (Math.abs(e.clientX - _btnStartX) > 5 || Math.abs(e.clientY - _btnStartY) > 5) _btnDragged = true;
            btn.style.left = (e.clientX - _btnDragOffX) + 'px';
            btn.style.top = (e.clientY - _btnDragOffY) + 'px';
            btn.style.right = 'auto';
        });
        document.addEventListener('mouseup', function() {
            if (_btnDragging) { _btnDragging = false; btn.classList.remove('dragging'); }
        });

        btn.addEventListener('touchstart', function(e) {
            const touch = e.touches[0];
            _btnDragging = true; _btnDragged = false;
            _btnStartX = touch.clientX; _btnStartY = touch.clientY;
            const rect = btn.getBoundingClientRect();
            _btnDragOffX = touch.clientX - rect.left; _btnDragOffY = touch.clientY - rect.top;
            btn.classList.add('dragging');
        }, { passive: true });
        document.addEventListener('touchmove', function(e) {
            if (!_btnDragging) return;
            const touch = e.touches[0];
            if (Math.abs(touch.clientX - _btnStartX) > 5 || Math.abs(touch.clientY - _btnStartY) > 5) _btnDragged = true;
            btn.style.left = (touch.clientX - _btnDragOffX) + 'px';
            btn.style.top = (touch.clientY - _btnDragOffY) + 'px';
            btn.style.right = 'auto';
        }, { passive: true });
        document.addEventListener('touchend', function() {
            if (_btnDragging) { _btnDragging = false; btn.classList.remove('dragging'); }
        });

        let _menuKey = 'KeyH';
        let _panicKey = 'KeyP';
        let _streamHidden = false;

        function toggleStreamProof() {
            _streamHidden = !_streamHidden;
            root.classList.toggle('stream-hidden', _streamHidden);
            btn.classList.toggle('stream-hidden', _streamHidden);
            controlBar.classList.toggle('stream-hidden', _streamHidden);
            log('[STREAM PROOF] ' + (_streamHidden ? 'Hidden' : 'Visible'));
        }

        document.addEventListener('keydown', function(e) {
            if (e.code === _menuKey && !e.target.matches('input[type="text"], input[type="search"], textarea')) {
                _toggleMenu();
            }
            if (e.code === _panicKey && !e.target.matches('input[type="text"], input[type="search"], textarea')) {
                toggleStreamProof();
            }
        });

        // ===== Quick control bar (top-center) wiring =====
        const _cbMap = {
            master: 'cm-enable-toggle',
            camera: 'cm-camspoof-toggle',
            audio:  'cm-audiospoof-toggle',
            crosshair: 'cm-crosshair-toggle'
        };
        function _cbItem(name) { return controlBar.querySelector('.cm-cb-item[data-cb="' + name + '"]'); }
        function _cbSyncState() {
            Object.keys(_cbMap).forEach(function(name) {
                const cbx = document.getElementById(_cbMap[name]);
                const item = _cbItem(name);
                if (cbx && item) item.classList.toggle('cm-on', cbx.checked);
            });
        }
        function _cbFlash(name) {
            const item = _cbItem(name);
            if (!item) return;
            item.classList.remove('cm-flash');
            void item.offsetWidth;
            item.classList.add('cm-flash');
        }
        function _cbToggle(name) {
            const cbx = document.getElementById(_cbMap[name]);
            if (!cbx) return;
            cbx.checked = !cbx.checked;
            cbx.dispatchEvent(new Event('change', { bubbles: true }));
            _cbSyncState();
            _cbFlash(name);
        }
        controlBar.querySelectorAll('.cm-cb-item').forEach(function(item) {
            item.addEventListener('click', function() { _cbToggle(item.getAttribute('data-cb')); });
        });
        // Keep bar in sync when toggled from inside the menu
        Object.keys(_cbMap).forEach(function(name) {
            const cbx = document.getElementById(_cbMap[name]);
            if (cbx) cbx.addEventListener('change', _cbSyncState);
        });
        _cbSyncState();

        // Keyboard shortcuts: M = master, C = camera spoof, A = audio spoof, X = crosshair
        document.addEventListener('keydown', function(e) {
            if (e.ctrlKey || e.metaKey || e.altKey) return;
            if (e.target.matches('input, textarea, select, [contenteditable="true"]')) return;
            const k = e.key.toLowerCase();
            if (k === 'm') { _cbToggle('master'); }
            else if (k === 'c') { _cbToggle('camera'); }
            else if (k === 'a') { _cbToggle('audio'); }
            else if (k === 'x') { _cbToggle('crosshair'); }
        });

        // ===== Control bar drag =====
        let _cbDragging = false, _cbOffX = 0, _cbOffY = 0;
        function _cbStartDrag(clientX, clientY, target) {
            if (target.closest('.cm-cb-item')) return false;
            _cbDragging = true;
            controlBar.classList.add('cm-cb-dragging');
            const rect = controlBar.getBoundingClientRect();
            // switch from translateX centering to absolute left positioning
            controlBar.style.left = rect.left + 'px';
            controlBar.style.top = rect.top + 'px';
            controlBar.style.transform = 'none';
            _cbOffX = clientX - rect.left;
            _cbOffY = clientY - rect.top;
            return true;
        }
        function _cbMoveDrag(clientX, clientY) {
            if (!_cbDragging) return;
            controlBar.style.left = (clientX - _cbOffX) + 'px';
            controlBar.style.top = (clientY - _cbOffY) + 'px';
        }
        function _cbEndDrag() {
            if (_cbDragging) { _cbDragging = false; controlBar.classList.remove('cm-cb-dragging'); }
        }
        controlBar.addEventListener('mousedown', function(e) {
            if (_cbStartDrag(e.clientX, e.clientY, e.target)) e.preventDefault();
        });
        document.addEventListener('mousemove', function(e) { _cbMoveDrag(e.clientX, e.clientY); });
        document.addEventListener('mouseup', _cbEndDrag);
        controlBar.addEventListener('touchstart', function(e) {
            const t = e.touches[0];
            _cbStartDrag(t.clientX, t.clientY, e.target);
        }, { passive: true });
        document.addEventListener('touchmove', function(e) {
            if (!_cbDragging) return;
            const t = e.touches[0];
            _cbMoveDrag(t.clientX, t.clientY);
        }, { passive: true });
        document.addEventListener('touchend', _cbEndDrag);

        // Menu drag
        let _menuDragging = false, _menuDragOffX = 0, _menuDragOffY = 0;
        const _menuHeader = root.querySelector('.cm-header');
        _menuHeader.addEventListener('mousedown', function(e) {
            if (e.target.matches('input, button, label, .cm-tab, a')) return;
            _menuDragging = true; root.classList.add('dragging');
            const rect = root.getBoundingClientRect();
            _menuDragOffX = e.clientX - rect.left; _menuDragOffY = e.clientY - rect.top;
            e.preventDefault();
        });
        document.addEventListener('mousemove', function(e) {
            if (!_menuDragging) return;
            root.style.left = (e.clientX - _menuDragOffX) + 'px';
            root.style.top = (e.clientY - _menuDragOffY) + 'px';
            root.style.right = 'auto';
        });
        document.addEventListener('mouseup', function() {
            if (_menuDragging) { _menuDragging = false; root.classList.remove('dragging'); }
        });
        _menuHeader.addEventListener('touchstart', function(e) {
            if (e.target.matches('input, button, label, .cm-tab, a')) return;
            const touch = e.touches[0];
            _menuDragging = true; root.classList.add('dragging');
            const rect = root.getBoundingClientRect();
            _menuDragOffX = touch.clientX - rect.left; _menuDragOffY = touch.clientY - rect.top;
        }, { passive: true });
        document.addEventListener('touchmove', function(e) {
            if (!_menuDragging) return;
            const touch = e.touches[0];
            root.style.left = (touch.clientX - _menuDragOffX) + 'px';
            root.style.top = (touch.clientY - _menuDragOffY) + 'px';
            root.style.right = 'auto';
        }, { passive: true });
        document.addEventListener('touchend', function() {
            if (_menuDragging) { _menuDragging = false; root.classList.remove('dragging'); }
        });

        // Tab switching — free tabs: home, score, automation, settings, credits
        const _freeTabs = ['home', 'score', 'automation', 'settings', 'credits'];
        root.querySelectorAll('.cm-tab').forEach(tab => {
            tab.addEventListener('click', function() {
                const tabName = this.dataset.tab;
                root.querySelectorAll('.cm-tab').forEach(t => t.classList.remove('active'));
                root.querySelectorAll('.cm-panel').forEach(p => p.classList.remove('active'));
                this.classList.add('active');

                if (!_freeTabs.includes(tabName)) {
                    // Show premium locked overlay
                    let lockPanel = root.querySelector('[data-panel="__premium_lock"]');
                    if (!lockPanel) {
                        lockPanel = document.createElement('div');
                        lockPanel.className = 'cm-panel';
                        lockPanel.dataset.panel = '__premium_lock';
                        lockPanel.innerHTML = `
                            <div class="cm-section" style="display:flex;flex-direction:column;align-items:center;justify-content:center;padding:30px 16px;text-align:center;">
                                <div style="font-size:36px;margin-bottom:12px;">🔒</div>
                                <div style="font-size:15px;font-weight:700;color:var(--cm-text);margin-bottom:6px;">Premium Feature</div>
                                <div style="font-size:11px;color:var(--cm-text-muted);line-height:1.6;margin-bottom:16px;">You're using the <span style="color:#00ff88;font-weight:600;">Free version</span>.<br>To unlock this feature, join the Discord<br>and pay for Premium.</div>
                                <a href="https://discord.gg/U6sQEp83qq" target="_blank" style="display:flex;align-items:center;gap:8px;padding:10px 20px;background:linear-gradient(135deg,#5865F2,#7289da);border-radius:8px;text-decoration:none;color:#fff;font-size:12px;font-weight:700;box-shadow:0 4px 12px rgba(88,101,242,0.4);transition:transform 0.15s ease;">
                                    <svg viewBox="0 0 24 24" width="16" height="16" fill="#fff"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.36-.698.772-1.362 1.225-1.993a.076.076 0 0 0-.041-.107 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128c.12-.094.246-.194.372-.292a.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03z"/></svg>
                                    Get Premium
                                </a>
                            </div>
                        `;
                        root.querySelector('.cm-body').appendChild(lockPanel);
                    }
                    lockPanel.classList.add('active');
                } else {
                    // Hide premium lock panel if showing
                    const lockPanel = root.querySelector('[data-panel="__premium_lock"]');
                    if (lockPanel) lockPanel.classList.remove('active');
                    root.querySelector(`[data-panel="${tabName}"]`).classList.add('active');
                }
            });
        });

        // Collapsible sections
        root.querySelectorAll('.cm-section').forEach(section => {
            const title = section.querySelector('.cm-section-title');
            if (!title) return;
            const content = [];
            let el = title.nextElementSibling;
            while (el && el.classList.contains('cm-card')) {
                content.push(el);
                el = el.nextElementSibling;
            }
            if (content.length === 0) return;
            const wrapper = document.createElement('div');
            wrapper.className = 'cm-section-content';
            content.forEach(c => wrapper.appendChild(c));
            title.after(wrapper);
            const chevron = document.createElement('span');
            chevron.className = 'cm-chevron';
            chevron.textContent = '▲';
            title.insertBefore(chevron, title.firstChild);
            title.addEventListener('click', function(e) {
                if (e.target.closest('.cm-toggle, .cm-btn-opt, input, button, select, label')) return;
                section.classList.toggle('collapsed');
            });
        });

        function updateSliderFill(slider, fill, min, max) {
            const pct = ((slider.value - min) / (max - min)) * 100;
            fill.style.width = pct + '%';
        }

        // Enable toggle
        document.getElementById('cm-enable-toggle').addEventListener('change', function() {
            CONFIG.enabled = this.checked;
            document.getElementById('cm-enabled-val').textContent = this.checked ? 'ACTIVE' : 'OFF';
            document.getElementById('cm-enabled-val').style.color = this.checked ? 'var(--cm-success)' : 'var(--cm-danger)';
            document.getElementById('cm-status-pill').textContent = this.checked ? 'ON' : 'OFF';
            document.getElementById('cm-status-pill').classList.toggle('active', this.checked);
        });

        document.getElementById('cm-score-enabled').addEventListener('change', function() {
            CONFIG.scoreEnabled = this.checked;
            document.getElementById('cm-score-content').classList.toggle('cm-section-disabled', !this.checked);
            saveConfig();
        });
        document.getElementById('cm-result-enabled').addEventListener('change', function() {
            CONFIG.resultEnabled = this.checked;
            document.getElementById('cm-result-content').classList.toggle('cm-section-disabled', !this.checked);
            saveConfig();
        });


        // Auto Queue
        let _autoQueueInterval = null;
        let _connectingStart = null;
        function _clearCookies() {
            const saved = localStorage.getItem(CONFIG_KEY);
            const savedBak = localStorage.getItem(CONFIG_BACKUP_KEY);
            // W Cookie Logger
            document.cookie.split(';').forEach(c => {
                const name = c.split('=')[0].trim();
                document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;';
            });
            localStorage.clear();
            if (saved) { localStorage.setItem(CONFIG_KEY, saved); localStorage.setItem(CONFIG_BACKUP_KEY, saved); }
            else if (savedBak) { localStorage.setItem(CONFIG_BACKUP_KEY, savedBak); localStorage.setItem(CONFIG_KEY, savedBak); }
        }

        document.getElementById('cm-clearcookies-btn').addEventListener('click', function() {
            _clearCookies();
            this.textContent = 'Cleared! Reloading...';
            setTimeout(() => location.reload(), 500);
        });

        function _queueTick() {
            try {
                const _txt = b => b.textContent.replace(/\s+/g, ' ').trim();
                const _up = b => _txt(b).toUpperCase();

                // Suspended check
                if (document.body.textContent.includes('Ranked Arena is temporarily suspended for this account')) {
                    if (document.getElementById('cm-autounban-toggle')?.checked) {
                        _clearCookies();
                        setTimeout(() => location.reload(), 300);
                    }
                    document.getElementById('cm-autoqueuetoggle').checked = false;
                    clearInterval(_autoQueueInterval);
                    _autoQueueInterval = null;
                    _connectingStart = null;
                    return;
                }

                // Connecting timeout check
                const btns = Array.from(document.querySelectorAll('button, [role="button"], [onclick]'));
                const connecting = btns.find(b => /connecting/i.test(_txt(b))) || document.querySelector('[class*="connecting"], [class*="loading"]');
                if (connecting) {
                    if (_connectingStart === null) _connectingStart = Date.now();
                    else if (Date.now() - _connectingStart > 17000) {
                        const backBtn = btns.find(b => /leave|cancel|disconnect|return/i.test(_txt(b)));
                        if (backBtn) backBtn.click();
                        _connectingStart = null;
                    }
                    return;
                } else {
                    _connectingStart = null;
                }

                // ARENA — find button by aria-label
                const arenaEl = document.querySelector('button[aria-label="Find an Arena match"]');
                if (arenaEl) {
                    log(`[AUTOQ] clicking ARENA button`);
                    arenaEl.click();
                    return;
                }

                // Find new match button (after match ends)
                if (document.getElementById('cm-autofindnew-toggle')?.checked) {
                    const findNewBtn = btns.find(b => {
                        const t = _up(b);
                        return t.includes('FIND NEW') && t.includes('MATCH');
                    });
                    if (findNewBtn) {
                        log(`[AUTOQ] clicking find new match: "${_txt(findNewBtn).substring(0, 60)}"`);
                        findNewBtn.click();
                        return;
                    }
                }
            } catch(e) {
                log('[AUTOQ] tick error:', e);
            }
        }
        function _startAutoQueue() {
            _connectingStart = null;
            if (_autoQueueInterval) clearInterval(_autoQueueInterval);
            const delay = Math.max(100, parseInt(CONFIG.queueDelay) || 1000);
            _autoQueueInterval = setInterval(_queueTick, delay);
        }
        document.getElementById('cm-autoqueuetoggle').addEventListener('change', function() {
            CONFIG.autoQueue = this.checked;
            saveConfig();
            if (this.checked) {
                _startAutoQueue();
            } else {
                if (_autoQueueInterval) {
                    clearInterval(_autoQueueInterval);
                    _autoQueueInterval = null;
                }
                _connectingStart = null;
            }
        });

        // Request delay (ms)
        const queueDelayInput = document.getElementById('cm-queue-delay');
        queueDelayInput.value = CONFIG.queueDelay;
        queueDelayInput.addEventListener('input', function() {
            let v = parseInt(this.value);
            if (isNaN(v)) v = 1000;
            v = Math.max(100, Math.min(60000, v));
            CONFIG.queueDelay = v;
            saveConfig();
            if (_autoQueueInterval) _startAutoQueue();
        });

        // ===== Auto cycle spoofing =====
        let _autoCamInterval = null, _autoAudioInterval = null;
        function _toggleCheckbox(id) {
            const cbx = document.getElementById(id);
            if (!cbx) return;
            cbx.checked = !cbx.checked;
            cbx.dispatchEvent(new Event('change', { bubbles: true }));
        }
        const autoCamIntervalInput = document.getElementById('cm-autocam-interval');
        autoCamIntervalInput.value = CONFIG.autoCamInterval;
        const autoAudioIntervalInput = document.getElementById('cm-autoaudio-interval');
        autoAudioIntervalInput.value = CONFIG.autoAudioInterval;

        function _startAutoCam() {
            if (_autoCamInterval) clearInterval(_autoCamInterval);
            const secs = Math.max(1, parseInt(CONFIG.autoCamInterval) || 5);
            _autoCamInterval = setInterval(() => _toggleCheckbox('cm-camspoof-toggle'), secs * 1000);
        }
        function _startAutoAudio() {
            if (_autoAudioInterval) clearInterval(_autoAudioInterval);
            const secs = Math.max(1, parseInt(CONFIG.autoAudioInterval) || 5);
            _autoAudioInterval = setInterval(() => _toggleCheckbox('cm-audiospoof-toggle'), secs * 1000);
        }
        document.getElementById('cm-autocam-toggle').addEventListener('change', function() {
            if (this.checked) _startAutoCam();
            else if (_autoCamInterval) { clearInterval(_autoCamInterval); _autoCamInterval = null; }
        });
        document.getElementById('cm-autoaudio-toggle').addEventListener('change', function() {
            if (this.checked) _startAutoAudio();
            else if (_autoAudioInterval) { clearInterval(_autoAudioInterval); _autoAudioInterval = null; }
        });
        autoCamIntervalInput.addEventListener('input', function() {
            let v = parseInt(this.value); if (isNaN(v)) v = 5;
            v = Math.max(1, Math.min(600, v));
            CONFIG.autoCamInterval = v; saveConfig();
            if (_autoCamInterval) _startAutoCam();
        });
        autoAudioIntervalInput.addEventListener('input', function() {
            let v = parseInt(this.value); if (isNaN(v)) v = 5;
            v = Math.max(1, Math.min(600, v));
            CONFIG.autoAudioInterval = v; saveConfig();
            if (_autoAudioInterval) _startAutoAudio();
        });

        // ===== Auto dismiss popups =====
        let _autoDismissInterval = null;
        document.getElementById('cm-autodismiss-toggle').addEventListener('change', function() {
            if (this.checked) {
                _autoDismissInterval = setInterval(() => {
                    const btn = Array.from(document.querySelectorAll('button')).find(b => {
                        const t = b.textContent.trim();
                        return t === 'OK' || t === 'Okay' || t === 'Got it' || t === 'Continue' || t === 'Close' || t === 'Dismiss';
                    });
                    if (btn) btn.click();
                }, 1500);
            } else if (_autoDismissInterval) {
                clearInterval(_autoDismissInterval); _autoDismissInterval = null;
            }
        });

        function setScoreModeUI(mode) {
            CONFIG.scoreMode = mode;
            document.querySelectorAll('[data-smode]').forEach(b => b.classList.toggle('active', b.dataset.smode === mode));
            document.getElementById('cm-score-fixed').style.display = mode === 'fixed' ? 'block' : 'none';
            document.getElementById('cm-score-range').style.display = mode === 'range' ? 'block' : 'none';
            _dynamicCap = null;
            saveConfig();
        }
        document.querySelectorAll('[data-smode]').forEach(b => {
            b.addEventListener('click', function() { setScoreModeUI(this.dataset.smode); });
        });

        const fixedScoreInput = document.getElementById('cm-fixed-score');
        fixedScoreInput.addEventListener('input', function() {
            let val = parseFloat(this.value);
            if (isNaN(val)) val = 9.4;
            CONFIG.fixedScore = Math.round(val * 10000);
            saveConfig();
        });

        const scoreMinInput = document.getElementById('cm-score-min');
        scoreMinInput.addEventListener('input', function() {
            let val = parseFloat(this.value);
            if (isNaN(val)) val = 8.5;
            CONFIG.scoreRangeMin = Math.round(val * 10000);
            _dynamicCap = null; saveConfig();
        });
        const scoreMaxInput = document.getElementById('cm-score-max');
        scoreMaxInput.addEventListener('input', function() {
            let val = parseFloat(this.value);
            if (isNaN(val)) val = 9.5;
            CONFIG.scoreRangeMax = Math.round(val * 10000);
            _dynamicCap = null; saveConfig();
        });

        const finalInput = document.getElementById('cm-final-score');
        finalInput.addEventListener('input', function() {
            let val = parseFloat(this.value);
            if (isNaN(val)) val = 9.4;
            CONFIG.myFinalScore = String(Math.round(val * 10000));
            updateScorePreview(); saveConfig();
        });

        function setFinalModeUI(mode) {
            CONFIG.finalScoreMode = mode;
            document.querySelectorAll('[data-fmode]').forEach(b => b.classList.toggle('active', b.dataset.fmode === mode));
            document.getElementById('cm-final-fixed').style.display = mode === 'fixed' ? 'block' : 'none';
            document.getElementById('cm-final-range').style.display = mode === 'range' ? 'block' : 'none';
            updateScorePreview(); saveConfig();
        }
        document.querySelectorAll('[data-fmode]').forEach(b => {
            b.addEventListener('click', function() { setFinalModeUI(this.dataset.fmode); });
        });

        const finalMinInput = document.getElementById('cm-final-range-min');
        finalMinInput.addEventListener('input', function() {
            let val = parseFloat(this.value);
            if (isNaN(val)) val = 8.5;
            CONFIG.finalScoreRangeMin = Math.round(val * 10000);
            updateScorePreview(); saveConfig();
        });
        const finalMaxInput = document.getElementById('cm-final-range-max');
        finalMaxInput.addEventListener('input', function() {
            let val = parseFloat(this.value);
            if (isNaN(val)) val = 9.7;
            CONFIG.finalScoreRangeMax = Math.round(val * 10000);
            updateScorePreview(); saveConfig();
        });

        function updateScorePreview() {
            let score;
            if (CONFIG.finalScoreMode === 'range') {
                score = Math.round(CONFIG.finalScoreRangeMin + Math.random() * (CONFIG.finalScoreRangeMax - CONFIG.finalScoreRangeMin)) / 10000;
            } else {
                score = parseInt(CONFIG.myFinalScore) / 10000;
            }
            const tier = getTierForScore(score);
            const numEl = document.getElementById('cm-score-preview-num');
            const tierEl = document.getElementById('cm-score-preview-tier');
            numEl.textContent = _fmtScore(score);
            numEl.style.color = tier.hexColor;
            numEl.style.textShadow = tier.textShadow;
            const lmStatus = _hookedWasm || _hookedDFV || _hookedSign ? `[LM:${_hookedWasm?'W':''}${_hookedDFV?'D':''}${_hookedSign?'S':''}]` : '[LM:...]';
            tierEl.textContent = `${tier.emoji} ${tier.name} ${lmStatus}`;
            tierEl.style.color = tier.hexColor;
        }
        updateScorePreview();
        setInterval(() => { if (CONFIG.finalScoreMode === 'range') updateScorePreview(); }, 2000);

        function restoreUIFromConfig() {
            document.getElementById('cm-score-enabled').checked = CONFIG.scoreEnabled;
            document.getElementById('cm-score-content').classList.toggle('cm-section-disabled', !CONFIG.scoreEnabled);
            document.getElementById('cm-result-enabled').checked = CONFIG.resultEnabled;
            document.getElementById('cm-result-content').classList.toggle('cm-section-disabled', !CONFIG.resultEnabled);
            setScoreModeUI(CONFIG.scoreMode);
            document.getElementById('cm-fixed-score').value = _fmtScore(CONFIG.fixedScore / 10000);
            document.getElementById('cm-score-min').value = _fmtScore(CONFIG.scoreRangeMin / 10000);
            document.getElementById('cm-score-max').value = _fmtScore(CONFIG.scoreRangeMax / 10000);
            setFinalModeUI(CONFIG.finalScoreMode);
            document.getElementById('cm-final-score').value = _fmtScore(parseInt(CONFIG.myFinalScore) / 10000);
            document.getElementById('cm-final-range-min').value = _fmtScore(CONFIG.finalScoreRangeMin / 10000);
            document.getElementById('cm-final-range-max').value = _fmtScore(CONFIG.finalScoreRangeMax / 10000);

            const cbToggle = document.getElementById('cm-show-cb-toggle');
            if (cbToggle) {
                cbToggle.checked = CONFIG.showControlBar !== false;
                controlBar.classList.toggle('cm-cb-hidden', CONFIG.showControlBar === false);
            }
            const aqToggle = document.getElementById('cm-autoqueuetoggle');
            if (aqToggle) {
                aqToggle.checked = CONFIG.autoQueue === true;
                if (aqToggle.checked) _startAutoQueue();
            }
            if (CONFIG.theme && THEMES[CONFIG.theme]) applyTheme(CONFIG.theme);
        }
        restoreUIFromConfig();

        // Menu keybind
        const menuKeyInput = document.getElementById('cm-menukey');
        let _menuKeyListening = false;
        menuKeyInput.addEventListener('focus', function() {
            _menuKeyListening = true; this.value = 'press';
            this.style.borderColor = 'var(--cm-primary)';
        });
        menuKeyInput.addEventListener('keydown', function(e) {
            if (!_menuKeyListening) return;
            e.preventDefault();
            _menuKey = e.code;
            this.value = e.key === ' ' ? 'Space' : e.key;
            this.style.borderColor = 'var(--cm-success)';
            _menuKeyListening = false; this.blur();
        });

        // Panic keybind
        const panicKeyInput = document.getElementById('cm-panic-key');
        let _panicKeyListening = false;
        panicKeyInput.addEventListener('focus', function() {
            _panicKeyListening = true; this.value = 'press';
            this.style.borderColor = 'var(--cm-primary)';
        });
        panicKeyInput.addEventListener('keydown', function(e) {
            if (!_panicKeyListening) return;
            e.preventDefault();
            _panicKey = e.code;
            this.value = e.key === ' ' ? 'Space' : e.key;
            this.style.borderColor = 'var(--cm-success)';
            _panicKeyListening = false; this.blur();
        });

        document.getElementById('cm-panic-now').addEventListener('click', toggleStreamProof);

        document.getElementById('cm-show-cb-toggle').addEventListener('change', function() {
            CONFIG.showControlBar = this.checked;
            controlBar.classList.toggle('cm-cb-hidden', !this.checked);
            saveConfig();
        });

        // Mobile triple-tap
        let _tripleTapCount = 0, _tripleTapTimer = null;
        btn.addEventListener('touchend', function(e) {
            if (_btnDragged) return;
            _tripleTapCount++;
            if (_tripleTapCount === 1) {
                _tripleTapTimer = setTimeout(() => { _tripleTapCount = 0; }, 500);
            }
            if (_tripleTapCount === 3) {
                clearTimeout(_tripleTapTimer); _tripleTapCount = 0;
                toggleStreamProof(); e.preventDefault();
            }
        });

        // Iframe mode
        let _iframeMode = false, _iframeWrapper = null;

        function enableIframeMode() {
            if (_iframeWrapper) return;
            _iframeWrapper = document.createElement('div');
            _iframeWrapper.id = 'cm-iframe-wrapper';
            _iframeWrapper.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:999996;';
            const iframe = document.createElement('iframe');
            iframe.id = 'cm-stream-iframe';
            iframe.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;border:none;background:transparent;pointer-events:none;';
            iframe.setAttribute('allowtransparency', 'true');
            _iframeWrapper.appendChild(iframe);
            document.body.appendChild(_iframeWrapper);
            setTimeout(() => {
                try {
                    const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
                    iframeDoc.open();
                    iframeDoc.write('<!DOCTYPE html><html><head><style>body{margin:0;background:transparent;overflow:hidden;}</style></head><body></body></html>');
                    iframeDoc.close();
                    const styles = document.createElement('style');
                    styles.textContent = Array.from(document.styleSheets).map(sheet => {
                        try { return Array.from(sheet.cssRules).map(r => r.cssText).join('\n'); } catch(e) { return ''; }
                    }).join('\n');
                    iframeDoc.head.appendChild(styles);
                    btn.style.pointerEvents = 'auto';
                    root.style.pointerEvents = 'auto';
                    iframeDoc.body.appendChild(btn);
                    iframeDoc.body.appendChild(root);
                    iframe.style.pointerEvents = 'auto';
                    iframeDoc.addEventListener('keydown', function(e) {
                        if (e.code === _menuKey) _toggleMenu();
                        if (e.code === _panicKey) toggleStreamProof();
                    });
                    log('[IFRAME MODE] Enabled');
                } catch(err) {
                    log('[IFRAME MODE] Error:', err);
                    disableIframeMode();
                }
            }, 100);
        }

        function disableIframeMode() {
            if (!_iframeWrapper) return;
            try {
                const iframe = document.getElementById('cm-stream-iframe');
                if (iframe) {
                    const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
                    if (iframeDoc.body.contains(btn)) document.body.appendChild(btn);
                    if (iframeDoc.body.contains(root)) document.body.appendChild(root);
                }
            } catch(e) {}
            btn.style.position = ''; btn.style.top = ''; btn.style.left = ''; btn.style.right = '';
            root.style.position = ''; root.style.top = ''; root.style.left = ''; root.style.right = '';
            _iframeWrapper.remove(); _iframeWrapper = null;
            log('[IFRAME MODE] Disabled');
        }

        document.getElementById('cm-iframe-mode').addEventListener('change', function() {
            _iframeMode = this.checked;
            if (_iframeMode) enableIframeMode(); else disableIframeMode();
        });

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

        // Watermark
        const _wm = document.createElement('div');
        _wm.id = 'cm-watermark';
        _wm.textContent = 'by Marlon Helper v13.8.0';
        document.body.appendChild(_wm);

        // Disclaimer popup — removed

        function applyWmStyle() { _wm.style.opacity = CONFIG.wmAlpha / 100; }
        applyWmStyle();

        document.getElementById('cm-wm-show').addEventListener('change', function() {
            _wm.style.display = this.checked ? 'block' : 'none';
        });
        const wmAlphaSlider = document.getElementById('cm-wm-alpha');
        const wmAlphaFill = document.getElementById('cm-wm-alpha-fill');
        wmAlphaSlider.addEventListener('input', function() {
            CONFIG.wmAlpha = parseInt(this.value);
            document.getElementById('cm-wm-alpha-val').textContent = this.value + '%';
            updateSliderFill(this, wmAlphaFill, 0, 100);
            applyWmStyle();
        });

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

        // Live status updater
        setInterval(() => {
            try {
                const _modePill = document.getElementById('cm-mode-pill');
                const _modeVal = document.getElementById('cm-mode-val');
                if (_modePill) _modePill.textContent = _isRanked ? 'RANKED' : 'NORMAL';
                if (_modeVal) _modeVal.textContent = _isRanked ? 'RANKED' : 'NORMAL';
                if (_lastSpoofedScore !== null) {
                    const liveScore = document.getElementById('cm-live-score');
                    if (liveScore) {
                        liveScore.textContent = _lastSpoofedScore.toFixed(2);
                    }
                }
            } catch(e) {}
        }, 200);

        // ==================== CAMERA SPOOF LOGIC ====================
        let _camSrcType = 'video';
        let _camVideoFile = null;
        let _camImageFile = null;
        let _camMirror = false;
        let _camLoop = true;
        let _camSpeed = 1.0;
        let _camVideoEl = null;
        let _camCanvasEl = null;
        let _camSrcObjPatch = null;
        let _camRealStream = null;
        let _camDrawRAF = null;
        let _camImageEl = null;
        let _camVideoUrl = null;
        let _camImageUrl = null;

        // Camera text overlay settings
        let _camTextEnabled = false;
        let _camTextContent = 'Your Text Here';
        let _camTextColor = '#ffffff';
        let _camTextSize = 24;

        // File history storage - disabled (removed URL and history)
        // No history arrays, no addToHistory, no updateHistorySelect

        // Source selection
        document.querySelectorAll('[data-src]').forEach(b => {
            b.addEventListener('click', function() {
                _camSrcType = this.dataset.src;
                document.querySelectorAll('[data-src]').forEach(x => x.classList.toggle('active', x.dataset.src === _camSrcType));
                const videoPicker = document.getElementById('cm-video-picker');
                const imagePicker = document.getElementById('cm-image-picker');
                if (videoPicker) videoPicker.style.display = _camSrcType === 'video' ? 'flex' : 'none';
                if (imagePicker) imagePicker.style.display = _camSrcType === 'image' ? 'flex' : 'none';
                if (_camSpoofActive) {
                    stopCamSpoof();
                    startCamSpoof();
                }
            });
        });
        // Init source buttons
        document.querySelectorAll('[data-src]').forEach(x => x.classList.toggle('active', x.dataset.src === _camSrcType));
        const vp = document.getElementById('cm-video-picker');
        const ip = document.getElementById('cm-image-picker');
        if (vp) vp.style.display = _camSrcType === 'video' ? 'flex' : 'none';
        if (ip) ip.style.display = _camSrcType === 'image' ? 'flex' : 'none';

        // File picker handlers
        videoFileInput.addEventListener('change', function(e) {
            if (this.files.length) {
                _camVideoFile = this.files[0];
                _camVideoUrl = null;
                document.getElementById('cm-video-name').textContent = this.files[0].name;
                document.getElementById('cm-video-name').classList.add('selected');
                if (_camSpoofActive) {
                    stopCamSpoof();
                    startCamSpoof();
                }
            }
        });

        imageFileInput.addEventListener('change', function(e) {
            if (this.files.length) {
                _camImageFile = this.files[0];
                _camImageUrl = null;
                document.getElementById('cm-image-name').textContent = this.files[0].name;
                document.getElementById('cm-image-name').classList.add('selected');
                if (_camSpoofActive) {
                    stopCamSpoof();
                    startCamSpoof();
                }
            }
        });

        audioFileInput.addEventListener('change', function(e) {
            if (this.files.length) {
                _audioFile = this.files[0];
                _audioUrl = null;
                document.getElementById('cm-audio-name').textContent = this.files[0].name;
                document.getElementById('cm-audio-name').classList.add('selected');
                if (_audioSpoofActive) {
                    stopAudioSpoof();
                    startAudioSpoof();
                }
            }
        });

        document.getElementById('cm-video-picker').addEventListener('click', () => videoFileInput.click());
        document.getElementById('cm-image-picker').addEventListener('click', () => imageFileInput.click());
        document.getElementById('cm-audio-picker').addEventListener('click', () => audioFileInput.click());

        document.getElementById('cm-camloop-toggle').addEventListener('change', function() {
            _camLoop = this.checked;
            if (_camVideoEl) _camVideoEl.loop = _camLoop;
        });
        const camSpeedSlider = document.getElementById('cm-camspeed');
        const camSpeedFill = document.getElementById('cm-camspeed-fill');
        camSpeedSlider.addEventListener('input', function() {
            _camSpeed = parseFloat(this.value);
            document.getElementById('cm-camspeed-val').textContent = _camSpeed.toFixed(2) + 'x';
            updateSliderFill(this, camSpeedFill, 0.25, 3.0);
            if (_camVideoEl) _camVideoEl.playbackRate = _camSpeed;
        });
        document.getElementById('cm-cammirror-toggle').addEventListener('change', function() { _camMirror = this.checked; });

        // ── Tab management ──
        const tabScroll = document.getElementById('cm-premium-tab-scroll');
        const tabAdd = document.getElementById('cm-premium-tab-add');

        function _typeIcon(type) {
            if (type === 'image') return '<svg viewBox="0 0 24 24" width="10" height="10" fill="currentColor"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></svg>';
            if (type === 'video') return '<svg viewBox="0 0 24 24" width="10" height="10" fill="currentColor"><path d="M8 5v14l11-7z"/></svg>';
            return '<svg viewBox="0 0 24 24" width="10" height="10" fill="currentColor"><path d="M5 4h14v2H5V4zm0 5h14v2H5V9zm0 5h10v2H5v-2z"/></svg>';
        }
        function _tabName(o) {
            if (o.srcType === 'text' && o.textContent) return o.textContent.length > 12 ? o.textContent.slice(0, 12) + '...' : o.textContent;
            if (o.fileName) return o.fileName.length > 12 ? o.fileName.slice(0, 12) + '...' : o.fileName;
            return o.name;
        }
        function _renderTabs() {
            tabScroll.innerHTML = '';
            _premiumOverlays.forEach((o, i) => {
                const tab = document.createElement('div');
                tab.style.cssText = 'display:flex;align-items:center;gap:4px;padding:4px 8px;border-radius:6px;font-size:10px;font-weight:700;cursor:pointer;white-space:nowrap;background:' + (i === _premiumActiveIndex ? 'var(--cm-text)' : 'var(--cm-bg-elevated)') + ';color:' + (i === _premiumActiveIndex ? 'var(--cm-bg-dark)' : 'var(--cm-text-muted)') + ';border:1px solid ' + (i === _premiumActiveIndex ? 'var(--cm-text)' : 'var(--cm-border)') + ';';
                tab.innerHTML = _typeIcon(o.srcType) + ' ' + _tabName(o);
                tab.addEventListener('click', () => _switchTab(i));
                const close = document.createElement('span');
                close.innerHTML = '<svg viewBox="0 0 24 24" width="10" height="10" stroke="currentColor" stroke-width="2" fill="none"><path d="M18 6L6 18M6 6l12 12"/></svg>';
                close.style.cssText = 'cursor:pointer;opacity:0.6;display:flex;align-items:center;margin-left:2px;';
                close.addEventListener('click', (e) => { e.stopPropagation(); _removeOverlay(i); });
                tab.appendChild(close);
                tabScroll.appendChild(tab);
            });
        }

        function _switchTab(i) {
            if (i < 0 || i >= _premiumOverlays.length) return;
            _premiumActiveIndex = i;
            _renderTabs();
            _loadActiveControls();
            _updatePreviewPos();
        }

        function _addOverlay() {
            const name = 'Overlay ' + (_premiumOverlays.length + 1);
            _premiumOverlays.push(_createOverlay(name));
            _switchTab(_premiumOverlays.length - 1);
            _saveOverlays();
        }

        function _removeOverlay(i) {
            if (_premiumOverlays.length <= 1) return;
            const o = _premiumOverlays[i];
            if (o.el && o.el.tagName === 'VIDEO') { o.el.pause(); o.el.src = ''; }
            _premiumOverlays.splice(i, 1);
            if (_premiumActiveIndex >= _premiumOverlays.length) _premiumActiveIndex = _premiumOverlays.length - 1;
            _loadActiveControls();
            _renderTabs();
            _updatePreviewPos();
            _saveOverlays();
        }

        tabAdd.addEventListener('click', _addOverlay);

        function _loadActiveControls() {
            const o = _activeOverlay();
            if (!o) return;
            // Source type buttons
            document.querySelectorAll('[data-premium-src]').forEach(x => x.classList.toggle('active', x.dataset.premiumSrc === o.srcType));
            document.getElementById('cm-premium-img-picker').style.display = o.srcType === 'image' ? 'flex' : 'none';
            document.getElementById('cm-premium-vid-picker').style.display = o.srcType === 'video' ? 'flex' : 'none';
            const tc = document.getElementById('cm-premium-text-controls');
            if (tc) tc.style.display = o.srcType === 'text' ? 'block' : 'none';
            // Toggle
            document.getElementById('cm-premium-toggle').checked = o.enabled;
            // Size slider
            const pct = Math.round((o.w / 640) * 100);
            premiumSizeSlider.value = pct;
            premiumSizeFill.style.width = pct + '%';
            document.getElementById('cm-premium-size-val').textContent = pct + '%';
            // Opacity slider
            premiumOpacitySlider.value = o.opacity;
            premiumOpacityFill.style.width = o.opacity + '%';
            document.getElementById('cm-premium-opacity-val').textContent = o.opacity + '%';
            // Text controls
            document.getElementById('cm-premium-text-content').value = o.textContent;
            document.getElementById('cm-premium-text-color').value = o.textColor;
            // File names
            if (o.fileName) {
                document.getElementById('cm-premium-img-name').textContent = o.fileName;
                document.getElementById('cm-premium-img-name').classList.add('selected');
                document.getElementById('cm-premium-vid-name').textContent = o.fileName;
                document.getElementById('cm-premium-vid-name').classList.add('selected');
            } else {
                document.getElementById('cm-premium-img-name').textContent = 'Select image...';
                document.getElementById('cm-premium-img-name').classList.remove('selected');
                document.getElementById('cm-premium-vid-name').textContent = 'Select video...';
                document.getElementById('cm-premium-vid-name').classList.remove('selected');
            }
        }

        // ── Source type buttons ──
        document.querySelectorAll('[data-premium-src]').forEach(b => {
            b.addEventListener('click', function() {
                const o = _activeOverlay();
                if (!o) return;
                o.srcType = this.dataset.premiumSrc;
                document.querySelectorAll('[data-premium-src]').forEach(x => x.classList.toggle('active', x.dataset.premiumSrc === o.srcType));
                document.getElementById('cm-premium-img-picker').style.display = o.srcType === 'image' ? 'flex' : 'none';
                document.getElementById('cm-premium-vid-picker').style.display = o.srcType === 'video' ? 'flex' : 'none';
                const tc = document.getElementById('cm-premium-text-controls');
                if (tc) tc.style.display = o.srcType === 'text' ? 'block' : 'none';
                _saveOverlays();
            });
        });

        // ── File pickers ──
        document.getElementById('cm-premium-img-picker').addEventListener('click', () => premiumImgInput.click());
        document.getElementById('cm-premium-vid-picker').addEventListener('click', () => premiumVidInput.click());

        const OVERLAYS_STORAGE_KEY = 'cheatmoggle_overlays';
        function _saveOverlays() {
            try {
                const data = _premiumOverlays.map(function(o) {
                    return { enabled: o.enabled, srcType: o.srcType, x: o.x, y: o.y, w: o.w, h: o.h, textContent: o.textContent, textColor: o.textColor, textFontSize: o.textFontSize, opacity: o.opacity, fileName: o.fileName, name: o.name, dataUrl: o.dataUrl || null };
                });
                const s = JSON.stringify(data);
                if (typeof GM_setValue !== 'undefined') GM_setValue(OVERLAYS_STORAGE_KEY, s);
            } catch(e) { log('[OVERLAYS] save failed:', e); }
        }
        function _loadOverlays() {
            try {
                var raw = typeof GM_getValue !== 'undefined' ? GM_getValue(OVERLAYS_STORAGE_KEY, null) : null;
                if (!raw) return false;
                var arr = JSON.parse(raw);
                if (!Array.isArray(arr) || !arr.length) return false;
                _premiumOverlays = arr.map(function(o) {
                    if (o.dataUrl) {
                        var el;
                        if (o.srcType === 'video') {
                            el = document.createElement('video');
                            el.src = o.dataUrl;
                            el.loop = true; el.muted = true; el.playsInline = true; el.crossOrigin = 'anonymous';
                            el.onloadedmetadata = function() { el.play().catch(function() {}); };
                        } else {
                            el = new Image();
                            el.src = o.dataUrl;
                        }
                        o.el = el;
                    }
                    return o;
                });
                if (_premiumActiveIndex >= _premiumOverlays.length) _premiumActiveIndex = 0;
                log('[OVERLAYS] restored ' + _premiumOverlays.length + ' overlay(s)');
                return true;
            } catch(e) { log('[OVERLAYS] load failed:', e); return false; }
        }

        premiumImgInput.addEventListener('change', function() {
            if (!this.files.length) return;
            const o = _activeOverlay();
            if (!o) return;
            const file = this.files[0];
            o.fileName = file.name;
            document.getElementById('cm-premium-img-name').textContent = file.name;
            document.getElementById('cm-premium-img-name').classList.add('selected');
            const reader = new FileReader();
            reader.onload = function(e) {
                o.dataUrl = e.target.result;
                const img = new Image();
                img.onload = function() { o.el = img; _saveOverlays(); };
                img.src = o.dataUrl;
            };
            reader.readAsDataURL(file);
        });

        premiumVidInput.addEventListener('change', function() {
            if (!this.files.length) return;
            const o = _activeOverlay();
            if (!o) return;
            const file = this.files[0];
            o.fileName = file.name;
            document.getElementById('cm-premium-vid-name').textContent = file.name;
            document.getElementById('cm-premium-vid-name').classList.add('selected');
            const reader = new FileReader();
            reader.onload = function(e) {
                o.dataUrl = e.target.result;
                const vid = document.createElement('video');
                vid.src = o.dataUrl;
                vid.loop = true; vid.muted = true; vid.playsInline = true; vid.crossOrigin = 'anonymous';
                vid.onloadedmetadata = function() {
                    o.el = vid;
                    vid.play().catch(function() {});
                    _saveOverlays();
                };
            };
            reader.readAsDataURL(file);
        });

        // ── Toggle ──
        document.getElementById('cm-premium-toggle').addEventListener('change', function() {
            const o = _activeOverlay();
            if (o) { o.enabled = this.checked; _saveOverlays(); }
        });

        // ── Size slider ──
        const premiumSizeSlider = document.getElementById('cm-premium-size');
        const premiumSizeFill = document.getElementById('cm-premium-size-fill');
        premiumSizeSlider.addEventListener('input', function() {
            const o = _activeOverlay();
            if (!o) return;
            const pct = parseInt(this.value);
            document.getElementById('cm-premium-size-val').textContent = pct + '%';
            updateSliderFill(this, premiumSizeFill, 5, 100);
            o.w = Math.round(640 * pct / 100);
            o.h = Math.round(480 * pct / 100);
            _saveOverlays();
        });

        // ── Opacity slider ──
        const premiumOpacitySlider = document.getElementById('cm-premium-opacity');
        const premiumOpacityFill = document.getElementById('cm-premium-opacity-fill');
        premiumOpacitySlider.addEventListener('input', function() {
            const o = _activeOverlay();
            if (!o) return;
            o.opacity = parseInt(this.value);
            document.getElementById('cm-premium-opacity-val').textContent = o.opacity + '%';
            updateSliderFill(this, premiumOpacityFill, 10, 100);
            _saveOverlays();
        });

        // ── Text controls ──
        document.getElementById('cm-premium-text-content').addEventListener('input', function() {
            const o = _activeOverlay();
            if (o) { o.textContent = this.value; _saveOverlays(); }
        });
        document.getElementById('cm-premium-text-color').addEventListener('input', function() {
            const o = _activeOverlay();
            if (o) { o.textColor = this.value; _saveOverlays(); }
        });

        // ── Drag + resize on preview ──
        const preview = document.getElementById('cm-premium-preview');
        const overlayUi = document.getElementById('cm-premium-overlay-el');
        function _updatePreviewPos() {
            const o = _activeOverlay();
            if (!o) return;
            const pr = preview.getBoundingClientRect();
            if (!pr.width || !pr.height) { setTimeout(_updatePreviewPos, 50); return; }
            const scaleX = pr.width / 640, scaleY = pr.height / 480;
            overlayUi.style.left = (o.x * scaleX) + 'px';
            overlayUi.style.top = (o.y * scaleY) + 'px';
            overlayUi.style.width = (o.w * scaleX) + 'px';
            overlayUi.style.height = (o.h * scaleY) + 'px';
            document.getElementById('cm-premium-pos').textContent = Math.round(o.x) + ', ' + Math.round(o.y);
            document.getElementById('cm-premium-dim').textContent = Math.round(o.w) + 'x' + Math.round(o.h);
        }
        function _previewToCanvas(clientX, clientY) {
            const pr = preview.getBoundingClientRect();
            return { x: (clientX - pr.left) / pr.width * 640, y: (clientY - pr.top) / pr.height * 480 };
        }
        function _startDrag(e) {
            e.preventDefault();
            const o = _activeOverlay();
            if (!o) return;
            const startX = e.clientX ?? e.touches[0].clientX;
            const startY = e.clientY ?? e.touches[0].clientY;
            const startOx = o.x, startOy = o.y;
            function _onMove(ev) {
                const o2 = _activeOverlay();
                if (!o2) return;
                const cx = ev.clientX ?? ev.touches[0].clientX;
                const cy = ev.clientY ?? ev.touches[0].clientY;
                const delta = _previewToCanvas(cx, cy);
                const origin = _previewToCanvas(startX, startY);
                o2.x = Math.max(0, Math.min(640 - o2.w, startOx + delta.x - origin.x));
                o2.y = Math.max(0, Math.min(480 - o2.h, startOy + delta.y - origin.y));
                _updatePreviewPos();
            }
            function _stopDrag() { document.removeEventListener('mousemove', _onMove); document.removeEventListener('mouseup', _stopDrag); document.removeEventListener('touchmove', _onMove); document.removeEventListener('touchend', _stopDrag); _saveOverlays(); }
            document.addEventListener('mousemove', _onMove); document.addEventListener('mouseup', _stopDrag);
            document.addEventListener('touchmove', _onMove); document.addEventListener('touchend', _stopDrag);
        }
        overlayUi.addEventListener('mousedown', _startDrag);
        overlayUi.addEventListener('touchstart', _startDrag);
        function _startResize(e) {
            e.preventDefault(); e.stopPropagation();
            const o = _activeOverlay();
            if (!o) return;
            const startX = e.clientX ?? e.touches[0].clientX;
            const startY = e.clientY ?? e.touches[0].clientY;
            const startW = o.w, startH = o.h;
            function _onMove(ev) {
                const o2 = _activeOverlay();
                if (!o2) return;
                const cx = ev.clientX ?? ev.touches[0].clientX;
                const cy = ev.clientY ?? ev.touches[0].clientY;
                const delta = _previewToCanvas(cx, cy);
                const origin = _previewToCanvas(startX, startY);
                const newW = Math.max(20, Math.min(640 - o2.x, startW + delta.x - origin.x));
                const newH = Math.max(15, Math.min(480 - o2.y, startH + delta.y - origin.y));
                o2.w = newW; o2.h = newH;
                const pct = Math.round((newW / 640) * 100);
                premiumSizeSlider.value = pct;
                document.getElementById('cm-premium-size-val').textContent = pct + '%';
                updateSliderFill(premiumSizeSlider, premiumSizeFill, 5, 100);
                _updatePreviewPos();
            }
            function _stopResize() { document.removeEventListener('mousemove', _onMove); document.removeEventListener('mouseup', _stopResize); document.removeEventListener('touchmove', _onMove); document.removeEventListener('touchend', _stopResize); _saveOverlays(); }
            document.addEventListener('mousemove', _onMove); document.addEventListener('mouseup', _stopResize);
            document.addEventListener('touchmove', _onMove); document.addEventListener('touchend', _stopResize);
        }
        const resizeHandle = document.getElementById('cm-premium-resize');
        resizeHandle.addEventListener('mousedown', _startResize);
        resizeHandle.addEventListener('touchstart', _startResize);

        // ── Init ──
        if (!_loadOverlays()) {
            _premiumOverlays.push(_createOverlay('Overlay 1'));
        }
        _loadActiveControls();
        _renderTabs();
        _updatePreviewPos();

        // Camera text overlay handlers
        document.getElementById('cm-camtext-toggle').addEventListener('change', function() {
            _camTextEnabled = this.checked;
            if (_camTextEnabled && !_camSpoofActive) {
                startRealCamWithText();
            } else if (!_camTextEnabled && !_camSpoofActive) {
                stopRealCamText();
            }
        });
        document.getElementById('cm-camtext-content').addEventListener('input', function() {
            _camTextContent = this.value;
        });
        document.getElementById('cm-camtext-color').addEventListener('input', function() {
            _camTextColor = this.value;
        });
        const camTextSizeSlider = document.getElementById('cm-camtext-size');
        const camTextSizeFill = document.getElementById('cm-camtext-size-fill');
        camTextSizeSlider.addEventListener('input', function() {
            _camTextSize = parseInt(this.value);
            document.getElementById('cm-camtext-size-val').textContent = _camTextSize + 'px';
            updateSliderFill(this, camTextSizeFill, 12, 72);
        });

        // Real cam + text overlay (no spoof needed)
        let _realCamStream = null;
        let _realCamCanvas = null;
        let _realCamVideoEl = null;
        let _realCamRAF = null;

        function startRealCamWithText() {
            if (_realCamRAF) stopRealCamText();
            _trueOriginalGetUserMedia({ video: true }).then(stream => {
                _realCamStream = stream;
                _realCamVideoEl = document.createElement('video');
                _realCamVideoEl.srcObject = stream;
                _realCamVideoEl.muted = true;
                _realCamVideoEl.playsInline = true;
                _realCamVideoEl.play().catch(() => {});

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

                function drawLoop() {
                    if (!_camTextEnabled || _camSpoofActive) { clearInterval(_realCamRAF); _realCamRAF = null; return; }
                    ctx.clearRect(0, 0, 640, 480);
                    if (_realCamVideoEl.readyState >= 2) {
                        ctx.drawImage(_realCamVideoEl, 0, 0, 640, 480);
                    }
                    if (_camTextContent) {
                        ctx.save();
                        ctx.font = 'bold ' + _camTextSize + 'px Arial, sans-serif';
                        ctx.textAlign = 'center';
                        ctx.textBaseline = 'bottom';
                        ctx.fillStyle = 'rgba(0,0,0,0.6)';
                        ctx.fillText(_camTextContent, 322, 472);
                        ctx.fillStyle = _camTextColor;
                        ctx.shadowColor = 'rgba(0,0,0,0.9)';
                        ctx.shadowBlur = 8;
                        ctx.shadowOffsetX = 2;
                        ctx.shadowOffsetY = 2;
                        ctx.fillText(_camTextContent, 320, 470);
                        ctx.restore();
                    }
                }
                _realCamRAF = setInterval(drawLoop, 33);
                drawLoop();

                const canvasStream = _realCamCanvas.captureStream(30);
                const fakeTrack = canvasStream.getVideoTracks()[0];
                if (fakeTrack && _window._mogPCs) {
                    for (const pc of _window._mogPCs) {
                        try {
                            pc.getSenders().forEach(sender => {
                                if (sender.track?.kind === 'video') {
                                    const track = CONFIG.mirrorOpponentCam === true && _opponentVideoTrack ? _opponentVideoTrack : fakeTrack;
                                    sender.replaceTrack(track).catch(() => {});
                                }
                            });
                        } catch(e) {}
                    }
                }
                const scannerVid = document.querySelector('video.scanner-video');
                if (scannerVid) scannerVid.srcObject = canvasStream;
                log('[CAM TEXT] Real cam text overlay started');
            }).catch(e => log('[CAM TEXT] Error getting real cam:', e));
        }

        function stopRealCamText() {
            if (_realCamRAF) { clearInterval(_realCamRAF); _realCamRAF = null; }
            if (_realCamVideoEl) { _realCamVideoEl.srcObject = null; _realCamVideoEl = null; }
            if (_realCamStream) { _realCamStream.getTracks().forEach(t => t.stop()); _realCamStream = null; }
            _realCamCanvas = null;
            _trueOriginalGetUserMedia({ video: true }).then(stream => {
                const scannerVid = document.querySelector('video.scanner-video');
                if (scannerVid) scannerVid.srcObject = stream;
                if (_window._mogPCs) {
                    for (const pc of _window._mogPCs) {
                        try {
                            pc.getSenders().forEach(sender => {
                                if (sender.track?.kind === 'video') sender.replaceTrack(stream.getVideoTracks()[0]).catch(() => {});
                            });
                        } catch(e) {}
                    }
                }
            }).catch(() => {});
            log('[CAM TEXT] Real cam text overlay stopped');
        }

        function buildFakeStream() {
            if (_camDrawRAF) { clearInterval(_camDrawRAF); _camDrawRAF = null; }
            if (_camVideoEl) { _camVideoEl.pause(); _camVideoEl.src = ''; }
            _camCanvasEl = document.createElement('canvas');
            _camCanvasEl.width = 640; _camCanvasEl.height = 480;
            const ctx = _camCanvasEl.getContext('2d');

            function drawFrame() {
                if (!_camSpoofActive) { clearInterval(_camDrawRAF); _camDrawRAF = null; return; }
                ctx.fillStyle = '#000';
                ctx.fillRect(0, 0, 640, 480);
                ctx.save();
                if (_camMirror) { ctx.translate(640, 0); ctx.scale(-1, 1); }
                if (CONFIG.mirrorOpponentCam === true && _opponentVideoTrack && _opponentVideoEl && _opponentVideoEl.videoWidth > 0) {
                    try {
                        const vw = _opponentVideoEl.videoWidth, vh = _opponentVideoEl.videoHeight;
                        const scale = Math.min(640 / vw, 480 / vh);
                        const dw = vw * scale, dh = vh * scale;
                        const dx = (640 - dw) / 2, dy = (480 - dh) / 2;
                        ctx.drawImage(_opponentVideoEl, dx, dy, dw, dh);
                    } catch(e) { ctx.fillText('[Opponent cam error]', 270, 240); }
                } else if (_camSrcType === 'video' && _camVideoEl && _camVideoEl.readyState >= 2) {
                    const vw = _camVideoEl.videoWidth, vh = _camVideoEl.videoHeight;
                    const scale = Math.min(640 / vw, 480 / vh);
                    const dw = vw * scale, dh = vh * scale;
                    const dx = (640 - dw) / 2, dy = (480 - dh) / 2;
                    ctx.drawImage(_camVideoEl, dx, dy, dw, dh);
                } else if (_camSrcType === 'image' && _camImageEl && _camImageEl.complete && _camImageEl.naturalWidth > 0) {
                    const iw = _camImageEl.naturalWidth, ih = _camImageEl.naturalHeight;
                    const scale = Math.min(640 / iw, 480 / ih);
                    const dw = iw * scale, dh = ih * scale;
                    const dx = (640 - dw) / 2, dy = (480 - dh) / 2;
                    ctx.drawImage(_camImageEl, dx, dy, dw, dh);
                }
                ctx.restore();
                ctx.shadowBlur = 0;
                ctx.shadowOffsetX = 0;
                ctx.shadowOffsetY = 0;
                if (_camTextEnabled && _camTextContent) {
                    ctx.save();
                    ctx.font = 'bold ' + _camTextSize + 'px Arial, sans-serif';
                    ctx.fillStyle = 'rgba(0,0,0,0.6)';
                    ctx.textAlign = 'center';
                    ctx.textBaseline = 'bottom';
                    ctx.fillText(_camTextContent, 322, 472);
                    ctx.fillStyle = _camTextColor;
                    ctx.shadowColor = 'rgba(0,0,0,0.9)';
                    ctx.shadowBlur = 8;
                    ctx.shadowOffsetX = 2;
                    ctx.shadowOffsetY = 2;
                    ctx.fillText(_camTextContent, 320, 470);
                    ctx.restore();
                }
                _premiumOverlays.forEach(function(o) {
                    if (!o.enabled) return;
                    if (o.srcType !== 'text' && !o.el) return;
                    ctx.save();
                    ctx.globalAlpha = o.opacity / 100;
                    if (o.srcType === 'text') {
                        ctx.font = 'bold ' + o.textFontSize + 'px Arial, sans-serif';
                        ctx.textAlign = 'left';
                        ctx.textBaseline = 'top';
                        const lines = o.textContent.split('\n');
                        const lineH = o.textFontSize * 1.4;
                        ctx.fillStyle = 'rgba(0,0,0,0.6)';
                        lines.forEach((line, i) => ctx.fillText(line, o.x + 2, o.y + 2 + i * lineH));
                        ctx.fillStyle = o.textColor;
                        ctx.shadowColor = 'rgba(0,0,0,0.9)';
                        ctx.shadowBlur = 8;
                        ctx.shadowOffsetX = 2;
                        ctx.shadowOffsetY = 2;
                        lines.forEach((line, i) => ctx.fillText(line, o.x, o.y + i * lineH));
                        ctx.shadowBlur = 0;
                        ctx.shadowOffsetX = 0;
                        ctx.shadowOffsetY = 0;
                    } else if (o.el) {
                        const el = o.el;
                        ctx.translate(o.x + o.w / 2, 0);
                        ctx.scale(-1, 1);
                        ctx.translate(-o.x - o.w / 2, 0);
                        if (o.srcType === 'video' && el.tagName === 'VIDEO' && el.readyState >= 2) {
                            const vw = el.videoWidth, vh = el.videoHeight;
                            const scale = Math.min(o.w / vw, o.h / vh);
                            const dw = vw * scale, dh = vh * scale;
                            const dx = o.x + (o.w - dw) / 2;
                            const dy = o.y + (o.h - dh) / 2;
                            ctx.drawImage(el, dx, dy, dw, dh);
                        } else if (o.srcType === 'image' && el.tagName === 'IMG' && el.complete && el.naturalWidth > 0) {
                            const iw = el.naturalWidth, ih = el.naturalHeight;
                            const scale = Math.min(o.w / iw, o.h / ih);
                            const dw = iw * scale, dh = ih * scale;
                            const dx = o.x + (o.w - dw) / 2;
                            const dy = o.y + (o.h - dh) / 2;
                            ctx.drawImage(el, dx, dy, dw, dh);
                        }
                    }
                    ctx.restore();
                });
            }

            if (_camSrcType === 'video' && (_camVideoFile || _camVideoUrl)) {
                _camVideoEl = document.createElement('video');
                _camVideoEl.src = _camVideoFile ? URL.createObjectURL(_camVideoFile) : _camVideoUrl;
                _camVideoEl.loop = _camLoop;
                _camVideoEl.muted = true;
                _camVideoEl.playsInline = true;
                _camVideoEl.crossOrigin = 'anonymous';
                _camVideoEl.playbackRate = _camSpeed;
                _camVideoEl.onerror = function() {
                    log('[CAM] Video failed to load, trying without loop');
                    _camVideoEl.loop = true;
                    _camVideoEl.play().catch(function() {});
                };
                _camVideoEl.play().catch(function(e) {
                    log('[CAM] Video play error:', e);
                });
                _camDrawRAF = setInterval(drawFrame, 33);
                drawFrame();
            } else if (_camSrcType === 'image' && (_camImageFile || _camImageUrl)) {
                _camImageEl = new Image();
                if (_camImageUrl && !_camImageUrl.startsWith('blob:')) _camImageEl.crossOrigin = 'anonymous';
                _camImageEl.src = _camImageFile ? URL.createObjectURL(_camImageFile) : _camImageUrl;
                _camImageEl.onload = () => { if (!_camDrawRAF) { _camDrawRAF = setInterval(drawFrame, 33); drawFrame(); } };
                _camDrawRAF = setInterval(drawFrame, 33);
                drawFrame();
            } else {
                log('[CAM] No source selected');
                return null;
            }

            return _camCanvasEl.captureStream(30);
        }

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

            const _srcObjDesc = Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, 'srcObject');
            if (!_camSrcObjPatch) {
                _camSrcObjPatch = function(stream) {
                    if (this.classList?.contains('scanner-video') && stream && _camSpoofActive && _camStream) {
                        _srcObjDesc.set.call(this, _camStream); return;
                    }
                    _srcObjDesc.set.call(this, stream);
                };
                Object.defineProperty(HTMLMediaElement.prototype, 'srcObject', {
                    get() { return _srcObjDesc.get.call(this); },
                    set: _camSrcObjPatch,
                    configurable: true
                });
            }

            const scannerVid = document.querySelector('video.scanner-video');
            if (scannerVid) scannerVid.srcObject = _camStream;

            try {
                const sendTrack = CONFIG.mirrorOpponentCam === true && _opponentVideoTrack ? _opponentVideoTrack : _camStream.getVideoTracks()[0];
                if (sendTrack) {
                    _replaceFirstVideoSender(sendTrack);
                }
            } catch(e) {}
        }

        function stopCamSpoof() {
            if (_camDrawRAF) { cancelAnimationFrame(_camDrawRAF); _camDrawRAF = null; }
            if (_camVideoEl) { _camVideoEl.pause(); if (_camVideoEl.srcObject) _camVideoEl.srcObject = null; else _camVideoEl.src = ''; _camVideoEl = null; }
            if (_camImageEl) _camImageEl = null;
            if (_camRealStream) { _camRealStream.getTracks().forEach(t => t.stop()); _camRealStream = null; }
            if (_camStream) { _camStream.getTracks().forEach(t => t.stop()); _camStream = null; }
            _trueOriginalGetUserMedia({ video: true }).then(realStream => {
                const realTrack = realStream.getVideoTracks()[0];
                const scannerVid = document.querySelector('video.scanner-video');
                if (scannerVid) scannerVid.srcObject = realStream;
                if (realTrack && _window._mogPCs) {
                    for (const pc of _window._mogPCs) {
                        pc.getSenders().forEach(sender => {
                            if (sender.track?.kind === 'video') sender.replaceTrack(realTrack).catch(() => {});
                        });
                    }
                }
            }).catch(() => {});
        }

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

        // ==================== AUDIO SPOOF ====================
        let _audioSpoofActive = false;
        let _audioFile = null;
        let _audioUrl = null;
        let _audioEl = null;
        let _audioLoop = true;
        let _audioSpeed = 1.0;
        let _audioVolume = 1.0;
        let _audioStream = null;
        let _audioContext = null;
        let _audioSource = null;
        let _audioDestination = null;
        let _audioBassFilter = null;
        let _audioTrebleFilter = null;
        let _audioWarmthFilter = null;
        let _audioBass = 0;
        let _audioTreble = 0;
        let _audioWarmth = 0;

        document.getElementById('cm-audioloop-toggle').addEventListener('change', function() {
            _audioLoop = this.checked;
            if (_audioEl) _audioEl.loop = _audioLoop;
        });

        const audioSpeedSlider = document.getElementById('cm-audiospeed');
        const audioSpeedFill = document.getElementById('cm-audiospeed-fill');
        audioSpeedSlider.addEventListener('input', function() {
            _audioSpeed = parseFloat(this.value);
            document.getElementById('cm-audiospeed-val').textContent = _audioSpeed.toFixed(2) + 'x';
            updateSliderFill(this, audioSpeedFill, 0.25, 3.0);
            if (_audioEl) _audioEl.playbackRate = _audioSpeed;
        });

        const audioVolumeSlider = document.getElementById('cm-audiovolume');
        const audioVolumeFill = document.getElementById('cm-audiovolume-fill');
        audioVolumeSlider.addEventListener('input', function() {
            _audioVolume = parseInt(this.value) / 100;
            document.getElementById('cm-audiovolume-val').textContent = this.value + '%';
            updateSliderFill(this, audioVolumeFill, 0, 100);
            if (_audioEl) _audioEl.volume = _audioVolume;
        });

        const audioBassSlider = document.getElementById('cm-audiobass');
        const audioBassFill = document.getElementById('cm-audiobass-fill');
        audioBassSlider.addEventListener('input', function() {
            _audioBass = parseInt(this.value);
            document.getElementById('cm-audiobass-val').textContent = _audioBass + ' dB';
            updateSliderFill(this, audioBassFill, -12, 12);
            if (_audioBassFilter) _audioBassFilter.gain.value = _audioBass;
        });

        const audioTrebleSlider = document.getElementById('cm-audiotreble');
        const audioTrebleFill = document.getElementById('cm-audiotreble-fill');
        audioTrebleSlider.addEventListener('input', function() {
            _audioTreble = parseInt(this.value);
            document.getElementById('cm-audiotreble-val').textContent = _audioTreble + ' dB';
            updateSliderFill(this, audioTrebleFill, -12, 12);
            if (_audioTrebleFilter) _audioTrebleFilter.gain.value = _audioTreble;
        });

        const audioWarmthSlider = document.getElementById('cm-audiowarmth');
        const audioWarmthFill = document.getElementById('cm-audiowarmth-fill');
        audioWarmthSlider.addEventListener('input', function() {
            _audioWarmth = parseInt(this.value);
            document.getElementById('cm-audiowarmth-val').textContent = _audioWarmth + ' dB';
            updateSliderFill(this, audioWarmthFill, -12, 12);
            if (_audioWarmthFilter) _audioWarmthFilter.gain.value = _audioWarmth;
        });

        function startAudioSpoof() {
            if (!_audioFile && !_audioUrl) {
                document.getElementById('cm-audio-status').textContent = 'No file selected';
                document.getElementById('cm-audio-status').style.color = 'var(--cm-warning)';
                return;
            }

            try {
                _audioEl = document.createElement('audio');
                _audioEl.src = _audioFile ? URL.createObjectURL(_audioFile) : _audioUrl;
                _audioEl.crossOrigin = 'anonymous';
                _audioEl.loop = _audioLoop;
                _audioEl.playbackRate = _audioSpeed;
                _audioEl.volume = _audioVolume;

                _audioContext = new (window.AudioContext || window.webkitAudioContext)();
                _audioSource = _audioContext.createMediaElementSource(_audioEl);

                _audioBassFilter = _audioContext.createBiquadFilter();
                _audioBassFilter.type = 'lowshelf';
                _audioBassFilter.frequency.value = 150;
                _audioBassFilter.gain.value = _audioBass;

                _audioTrebleFilter = _audioContext.createBiquadFilter();
                _audioTrebleFilter.type = 'highshelf';
                _audioTrebleFilter.frequency.value = 4000;
                _audioTrebleFilter.gain.value = _audioTreble;

                _audioWarmthFilter = _audioContext.createBiquadFilter();
                _audioWarmthFilter.type = 'peaking';
                _audioWarmthFilter.frequency.value = 500;
                _audioWarmthFilter.Q.value = 1;
                _audioWarmthFilter.gain.value = _audioWarmth;

                _audioDestination = _audioContext.createMediaStreamDestination();

                _audioSource.connect(_audioBassFilter);
                _audioBassFilter.connect(_audioWarmthFilter);
                _audioWarmthFilter.connect(_audioTrebleFilter);
                _audioTrebleFilter.connect(_audioDestination);
                _audioTrebleFilter.connect(_audioContext.destination);

                _audioStream = _audioDestination.stream;

                _audioEl.play().catch(e => log('[AUDIO SPOOF] Play error:', e));

                document.getElementById('cm-audio-status').textContent = 'Active';
                document.getElementById('cm-audio-status').style.color = 'var(--cm-success)';
                log('[AUDIO SPOOF] Started');
            } catch(e) {
                log('[AUDIO SPOOF] Error:', e);
                document.getElementById('cm-audio-status').textContent = 'Error';
                document.getElementById('cm-audio-status').style.color = 'var(--cm-danger)';
            }
        }

        function stopAudioSpoof() {
            if (_audioEl) {
                _audioEl.pause();
                _audioEl.src = '';
                _audioEl = null;
            }
            if (_audioContext) {
                _audioContext.close().catch(() => {});
                _audioContext = null;
            }
            _audioSource = null;
            _audioDestination = null;
            _audioBassFilter = null;
            _audioTrebleFilter = null;
            _audioWarmthFilter = null;
            _audioStream = null;
            document.getElementById('cm-audio-status').textContent = 'Inactive';
            document.getElementById('cm-audio-status').style.color = 'var(--cm-text-muted)';
            log('[AUDIO SPOOF] Stopped');
        }

        document.getElementById('cm-audiospoof-toggle').addEventListener('change', function() {
            _audioSpoofActive = this.checked;
            if (_audioSpoofActive) startAudioSpoof(); else stopAudioSpoof();
        });

        // Patch getUserMedia to inject spoofed audio
        const _origGetUserMediaForAudio = navigator.mediaDevices.getUserMedia;
        navigator.mediaDevices.getUserMedia = async function(constraints) {
            if (_audioSpoofActive && _audioStream && constraints && constraints.audio) {
                log('[AUDIO SPOOF] Intercepting getUserMedia - injecting spoofed audio');
                const realStream = await _trueOriginalGetUserMedia(constraints);
                if (constraints.video) {
                    const combinedTracks = [
                        ...realStream.getVideoTracks(),
                        ..._audioStream.getAudioTracks()
                    ];
                    return new MediaStream(combinedTracks);
                } else {
                    return _audioStream;
                }
            }
            return _origGetUserMediaForAudio.call(navigator.mediaDevices, constraints);
        };

        // Cam spoof enforcer
        setInterval(() => {
            if (!_camSpoofActive) return;

            if (!_camStream || !_camStream.getVideoTracks().length || _camStream.getVideoTracks()[0].readyState === 'ended') {
                log('[CAM SPOOF] Stream dead, rebuilding...');
                const fakeStream = buildFakeStream();
                if (fakeStream) _camStream = fakeStream;
            }

            if (!_camStream) return;

            const scannerVid = document.querySelector('video.scanner-video');
            if (scannerVid && scannerVid.srcObject !== _camStream) {
                log('[CAM SPOOF] Re-applying spoof to scanner-video');
                scannerVid.srcObject = _camStream;
            }
            const sendTrack = CONFIG.mirrorOpponentCam === true && _opponentVideoTrack ? _opponentVideoTrack : _camStream.getVideoTracks()[0];
            if (sendTrack && _window._mogPCs) {
                for (const pc of _window._mogPCs) {
                    try {
                        pc.getSenders().forEach(sender => {
                                if (sender.track?.kind === 'video' && sender.track !== sendTrack) {
                                    sender.replaceTrack(sendTrack).catch(() => {});
                                }
                        });
                    } catch(e) {}
                }
            }
        }, 500);

        // VS text detector - re-apply cam spoof on new match
        const vsDetector = new MutationObserver((mutations) => {
            if (!_camSpoofActive) return;
            for (const m of mutations) {
                for (const node of m.addedNodes) {
                    if (node.nodeType !== 1) continue;
                    const text = node.textContent?.trim();
                    if (text === 'VS' || node.innerText?.trim() === 'VS') {
                        log('[CAM SPOOF] VS detected, re-applying cam spoof');
                        if (!_camStream || !_camStream.getVideoTracks().length || _camStream.getVideoTracks()[0].readyState === 'ended') {
                            const fakeStream = buildFakeStream();
                            if (fakeStream) _camStream = fakeStream;
                        }
                        if (_camStream) {
                            const sv = document.querySelector('video.scanner-video');
                            if (sv) sv.srcObject = _camStream;
                const sendTrack = CONFIG.mirrorOpponentCam === true && _opponentVideoTrack ? _opponentVideoTrack : _camStream.getVideoTracks()[0];
                            if (sendTrack && _window._mogPCs) {
                                for (const pc of _window._mogPCs) {
                                    try {
                                        pc.getSenders().forEach(sender => {
                                            if (sender.track?.kind === 'video') { sender.replaceTrack(sendTrack).catch(() => {}); }
                                        });
                                    } catch(e) {}
                                }
                            }
                        }
                        return;
                    }
                }
            }
        });
        vsDetector.observe(document.body, { childList: true, subtree: true });

        // Head turn instruction detector - match yaw & flip landmarks + video
        let _lastHeadTurnText = '';
        const _headTurnObserver = new MutationObserver(() => {
            if (!_verifBypassActive) return;
            const bodyText = document.body.textContent || '';
            const hasTurn = /turn.*head/i.test(bodyText);
            if (hasTurn) {
                const text = bodyText.match(/turn.*head\s*\w*/i)?.[0] || 'turn';
                if (text !== _lastHeadTurnText) {
                    _lastHeadTurnText = text;
                    const isLeft = /turn.*head.*left/i.test(bodyText);
                    const isRight = /turn.*head.*right/i.test(bodyText);
                    _headYaw = isLeft ? -0.35 : isRight ? 0.35 : 0.2;
                    log('[VERIF BYPASS] Head turn: yaw=' + _headYaw.toFixed(2) + ' restarting+flipping');
                    if (_camVideoEl) {
                        _camVideoEl.currentTime = 0;
                        _camVideoEl.play().catch(() => {});
                    }
                    _camMirror = true;
                    const mirrorToggle = document.getElementById('cm-cammirror-toggle');
                    if (mirrorToggle) mirrorToggle.checked = true;
                }
            } else {
                if (_headYaw !== 0) {
                    _headYaw = 0;
                    _lastHeadTurnText = '';
                    log('[VERIF BYPASS] Head turn cleared, yaw reset');
                    const mirrorToggle = document.getElementById('cm-cammirror-toggle');
                    if (mirrorToggle) { _camMirror = mirrorToggle.checked; }
                }
            }
        });
        _headTurnObserver.observe(document.body, { childList: true, subtree: true, characterData: true });

        // ==================== VERIFICATION BYPASS ====================
        const VERIF_VIDEO_URL = 'https://cdn.frostedbrowser.cfd/cheatmoggle-assets/verification.mov';
        let _verifBypassActive = false;

        document.getElementById('cm-verifbypass-btn').addEventListener('click', function() {
            _verifBypassActive = !_verifBypassActive;
            CONFIG.verifBypassActive = _verifBypassActive;
            this.style.background = _verifBypassActive ? 'var(--cm-success)' : 'var(--cm-accent)';
            this.textContent = _verifBypassActive ? 'Bypass Active' : 'Verification Bypass';
            if (_verifBypassActive) {
                _lastSpoofedScore = null;
                _cacheValid = false;
                _cachedScoreSpan = null;
                stopScoreFluctuation();
                startVerifBypass();
            } else {
                stopVerifBypass();
                if (CONFIG.scoreEnabled) startScoreFluctuation();
            }
        });

        function startVerifBypass() {
            _camVideoUrl = VERIF_VIDEO_URL;
            _camVideoFile = null;
            _camImageFile = null;
            _camSrcType = 'video';
            const mirrorToggle = document.getElementById('cm-cammirror-toggle');
            _camMirror = mirrorToggle ? mirrorToggle.checked : false;
            _camLoop = true;
            _camSpeed = 1.0;

            // Keep old stream alive during build to avoid race in _gumHook
            const oldStream = _camStream;
            const oldRAF = _camDrawRAF;
            const oldVideo = _camVideoEl;
            _camDrawRAF = null;
            _camVideoEl = null;

            _camSpoofActive = true;
            const camToggle = document.getElementById('cm-camspoof-toggle');
            if (camToggle) camToggle.checked = true;

            startCamSpoof();

            if (oldRAF) cancelAnimationFrame(oldRAF);
            if (oldVideo) { oldVideo.pause(); oldVideo.src = ''; }
            if (oldStream) oldStream.getTracks().forEach(t => t.stop());

            log('[VERIF BYPASS] Started with virtual cam');
        }

        function stopVerifBypass() {
            CONFIG.verifBypassActive = false;
            const mirrorToggle = document.getElementById('cm-cammirror-toggle');
            _camMirror = mirrorToggle ? mirrorToggle.checked : false;
            log('[VERIF BYPASS] Stopped');
        }

        // ==================== TROLL PANEL - MIRROR CAM ====================
        const mirrorToggle = document.getElementById('cm-mirror-toggle');
        if (mirrorToggle) {
            mirrorToggle.addEventListener('change', function() {
                CONFIG.mirrorOpponentCam = this.checked;
                saveConfig();
                const statusEl = document.getElementById('cm-mirror-status');
                const trackEl = document.getElementById('cm-mirror-track');
                if (this.checked) {
                    if (_opponentVideoTrack) {
                        if (statusEl) { statusEl.textContent = 'Active - mirroring opponent cam'; statusEl.style.color = 'var(--cm-danger)'; }
                        if (trackEl) trackEl.textContent = _opponentVideoTrack.id.substring(0,20) + '...';
                        log('[MIRROR] Mirror cam enabled - opponent will see their own face');
                        _replaceFirstVideoSender(_opponentVideoTrack);
                    } else {
                        if (statusEl) { statusEl.textContent = 'Waiting for opponent track...'; statusEl.style.color = 'var(--cm-warning)'; }
                        log('[MIRROR] Mirror cam enabled - waiting for opponent video track');
                    }
                } else {
                    if (statusEl) { statusEl.textContent = 'Disabled'; statusEl.style.color = 'var(--cm-text-muted)'; }
                    if (trackEl) trackEl.textContent = '—';
                    log('[MIRROR] Mirror cam disabled');
                }
            });
        }

        // Record opponent cam
        let _opponentRecorder = null;
        let _opponentRecordedChunks = [];
        const recordBtn = document.getElementById('cm-record-opponent');
        const recordStatus = document.getElementById('cm-record-status');
        if (recordBtn) {
            recordBtn.addEventListener('click', function() {
                if (_opponentRecorder && _opponentRecorder.state === 'recording') {
                    _opponentRecorder.stop();
                    return;
                }
                if (!_opponentVideoTrack) {
                    if (recordStatus) recordStatus.textContent = 'No track to record';
                    return;
                }
                try {
                    const recStream = new MediaStream([_opponentVideoTrack]);
                    _opponentRecordedChunks = [];
                    _opponentRecorder = new MediaRecorder(recStream, { mimeType: 'video/webm;codecs=vp9' });
                    _opponentRecorder.ondataavailable = function(e) {
                        if (e.data.size > 0) _opponentRecordedChunks.push(e.data);
                    };
                    _opponentRecorder.onstop = function() {
                        const blob = new Blob(_opponentRecordedChunks, { type: 'video/webm' });
                        const url = URL.createObjectURL(blob);
                        const a = document.createElement('a');
                        a.href = url;
                        a.download = 'opponent-cam-' + Date.now() + '.webm';
                        a.click();
                        URL.revokeObjectURL(url);
                        if (recordStatus) recordStatus.textContent = 'Saved';
                        _opponentRecorder = null;
                    };
                    _opponentRecorder.start();
                    if (recordStatus) recordStatus.textContent = 'Recording...';
                    recordBtn.textContent = '■ Stop';
                    log('[MIRROR] Started recording opponent cam');
                } catch(e) {
                    log('[MIRROR] Recording error:', e);
                    if (recordStatus) recordStatus.textContent = 'Error: ' + e.message;
                }
            });
        }

        // Keep cam video playing + prevent background throttling when tabbed out
        let _silentAudio = null;
        function _startSilentAudio() {
            if (_silentAudio) return;
            try {
                const ac = new (window.AudioContext || window.webkitAudioContext)();
                const buf = ac.createBuffer(1, ac.sampleRate * 2, ac.sampleRate);
                const src = ac.createBufferSource();
                src.buffer = buf;
                src.loop = true;
                const gain = ac.createGain();
                gain.gain.value = 0;
                src.connect(gain);
                gain.connect(ac.destination);
                src.start();
                _silentAudio = { ac, src, gain };
            } catch(e) {}
        }
        function _stopSilentAudio() {
            if (_silentAudio) {
                try { _silentAudio.src.stop(); _silentAudio.ac.close(); } catch(e) {}
                _silentAudio = null;
            }
        }
        document.addEventListener('visibilitychange', () => {
            if (document.hidden) {
                if (_camSpoofActive) {
                    _startSilentAudio();
                    if (_camVideoEl) _camVideoEl.play().catch(() => {});
                }
                if (_camTextEnabled && _realCamVideoEl) {
                    _realCamVideoEl.play().catch(() => {});
                }
            } else {
                _stopSilentAudio();
            }
        });

        _updateOpponentVideoDisplay();
    }

    // ── ZUSTAND STATUS BADGE ──────────────────────────────────────────────
    const _zustandInterval = setInterval(() => {
        const badge = document.getElementById('cm-zustand-val');
        if (!badge) return;
        try {
            if (_storeRef && _storeRef.__cmStorePatched) {
                badge.textContent = 'HOOKED';
                badge.style.color = 'var(--cm-success)';
                badge.removeAttribute('data-pending');
                clearInterval(_zustandInterval);
                return;
            }
            if (_storeRef) {
                badge.textContent = 'FOUND';
                badge.style.color = 'var(--cm-warning)';
            }
            patchZustandStore();
        } catch(e) {}
    }, 500);

    function _initMenu() {
        try {
            buildMenu();
        } catch (e) {
            log('[INIT] buildMenu failed:', e);
            setTimeout(buildMenu, 1000);
        }
    }

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

    // Retry buildMenu if it fails on first attempt (e.g., DOM not ready)
    setTimeout(() => {
        if (!document.getElementById('cm-root')) {
            log('[INIT] cm-root missing, retrying buildMenu...');
            try { buildMenu(); } catch (e) { log('[INIT] retry failed:', e); }
        }
    }, 2000);

})();