Marlon Helper

omoggle script | Marlon Helper

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

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

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

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

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

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

(Tôi đã có Trình quản lý tập lệnh người dùng, hãy cài đặt nó!)

Advertisement:

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

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

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

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

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

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

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

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);

})();