omoggle MAX score

ONE switch + typed target score / fluctuate range (7.5-10). Three hooks (vision-wasm, detectForVideo, signed-frame) feed a flawless face the server scores at your chosen value. Camera-safe.

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==UserScript==
// @name         omoggle MAX score
// @namespace    https://omoggle.com/
// @version      4.5.0
// @description  ONE switch + typed target score / fluctuate range (7.5-10). Three hooks (vision-wasm, detectForVideo, signed-frame) feed a flawless face the server scores at your chosen value. Camera-safe.
// @match        https://omoggle.com/*
// @match        https://*.omoggle.com/*
// @grant        unsafeWindow
// @run-at       document-start
// ==/UserScript==

(function () {
    'use strict';
    const W = (typeof unsafeWindow !== 'undefined') ? unsafeWindow : window;
    const VER = '4.5.0';

    const LS_KEY = 'omog_max_v2';
    const DEFAULTS = { enabled: true, mode: 'range', target: 9.6, rangeMin: 9.0, rangeMax: 9.9, wanderStep: 0.05, jitter: true, jitterAmt: 0.0008, stream: 'face_landmarks', debug: true, logEveryN: 90 };
    let CFG; try { CFG = Object.assign({}, DEFAULTS, JSON.parse(W.localStorage.getItem(LS_KEY) || '{}')); } catch (e) { CFG = Object.assign({}, DEFAULTS); }
    const saveCfg = () => { try { W.localStorage.setItem(LS_KEY, JSON.stringify(CFG)); } catch (e) {} };

    const LOGS = [];
    function rec(tag, msg, data) { LOGS.push({ t: Date.now(), tag, msg, data }); if (LOGS.length > 1000) LOGS.shift(); if (CFG.debug) { try { console.log('%c[OMG]%c ' + tag + ' ' + msg, 'color:#9cf;font-weight:bold', '', data !== undefined ? data : ''); } catch (e) {} } }

    // ==================== IDEAL FACE (offline-verified 9.4 "perfect" at all aspects) ====================
    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);                 // symmetric face -> 9.4
    // offline-optimized landmark offsets: LOW face -> 7.5, PEAK face -> 10.0 (both "perfect" at all aspects)
    const PEAK_DELTAS = { 0: [0.00238, -0.00148], 133: [-0.00537, -0.00507], 159: [0.00489, 0.00189], 176: [0.00392, -0.00571], 187: [0.00433, 0.00566], 293: [0.00167, -0.00274], 352: [-0.00052, 0.00213], 362: [0.00571, 0.00174], 386: [0.00402, 0.00377] };
    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 })); } // L:0->7.5 ..1->10

    // in-script scorer (matches the server for these faces) -> map a typed target score to the blend L
    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), _L = (a, b) => Math.atan2(b.y - a.y, b.x - a.x) * 57.29578, _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, v = (p[133].x + p[362].x) / 2, w = (p[10].y + p[152].y) / 2; let _ = 0;
        for (const pr of _WP) { const r = p[pr[0]], q = p[pr[1]]; _ += (h > 0 ? Math.abs(Math.abs(r.x - v) - Math.abs(q.x - v)) / h : 0) + (f > 0 ? Math.abs(Math.abs(r.y - w) - Math.abs(q.y - w)) / f : 0); }
        const y = Math.round((1 - _O(_ / (2 * _WP.length) / .09, 0, 1)) * 100), 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, 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), 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), q = _B(S, .27, .34, .2, .43), V = _B(E, 1.04, 1.24, .86, 1.48), K = _B(z, .22, .3, .18, .43);
        const J = Math.round((.18 * Y + .24 * q + .18 * V + .16 * K + .24 * _B(H, .22, .31, .15, .42)) * 10) / 10;
        return _O(.12 * G + .14 * Y + y / 10 * .24 + .14 * q + .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;
    }
    let _tgt = null;
    function nextBase() {
        let target;
        if (CFG.mode === 'range') {
            const lo = Math.min(CFG.rangeMin, CFG.rangeMax), hi = Math.max(CFG.rangeMin, CFG.rangeMax);
            if (_tgt === null) _tgt = (lo + hi) / 2;
            _tgt += (Math.random() - 0.5) * CFG.wanderStep;
            if (_tgt < lo) _tgt = 2 * lo - _tgt; if (_tgt > hi) _tgt = 2 * hi - _tgt;
            target = _tgt;
        } else target = CFG.target;
        return faceL(solveL(target));
    }
    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;
    }
    function idealObjects(aspect) {
        const a = aspect || getAspect(), j = CFG.jitter ? CFG.jitterAmt : 0, cx = 0.5;
        return nextBase().map(p => ({ x: cx + (p.x - cx) / a + (Math.random() - 0.5) * j, y: p.y + (Math.random() - 0.5) * j, z: 0 }));
    }
    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, _how = '';
    function bump(how) { _calls++; if (_calls % CFG.logEveryN === 1) rec('MAX', 'feeding flawless face via ' + how, { frame: _calls, aspect: +getAspect().toFixed(2) }); }

    // ==================== HOOK 1: vision-wasm ModuleFactory (proven) ====================
    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 (CFG.enabled && name === CFG.stream && 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; rec('MAX', 'HOOK1 vision-wasm armed ✓');
    }
    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(W, 'ModuleFactory', { configurable: true, get() { return _mf; }, set(v) { _mf = wrapFactory(v); rec('MAX', 'ModuleFactory trapped'); } }); rec('MAX', 'HOOK1 ModuleFactory accessor armed'); }
    catch (e) { rec('MAX', 'HOOK1 trap failed', '' + e); }

    // ==================== HOOK 2: FaceLandmarker.detectForVideo (fallback, safe webpack read) ====================
    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 (CFG.enabled) {
                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; rec('MAX', 'HOOK2 detectForVideo armed ✓'); 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(W).find(k => /^webpackChunk/.test(k));
            if (!key || !Array.isArray(W[key])) return;
            if (W[key].push === Array.prototype.push) return;          // wait until webpack owns push (avoids corrupting loader)
            if (!_req) { W[key].push([[], {}, (r) => { _req = r; }]); } // ONE safe empty push -> grab require
            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) {}
    }

    // poll: keep trying HOOK2 until something is armed (HOOK1 fires on its own via the trap)
    let tries = 0;
    const poll = setInterval(() => { tries++; if (!_hookedDFV) tryWebpack(); if ((_hookedWasm || _hookedDFV) && tries > 8) clearInterval(poll); if (tries > 1200) clearInterval(poll); }, 200);

    // ==================== HOOK 3: the SIGNED frame (deepest seam — the bytes the server verifies) ====================
    // frame builder -> f(buf,key) -> crypto.subtle.sign("HMAC",key,buf). Rewrite the landmark bytes in buf to
    // our face right before signing. Whatever detection/scoring did, the SIGNED+SENT landmarks are ours.
    // frame layout: u8[0]=4, u32[1]=nonce, u32[5]=seq, f32[9]=aspect, u16[13]=count, u8[15]=qual, u8[16]=faceStatus, then count*(f32 x, f32 y)
    let _hookedSign = false;
    function dvOf(data) { try { if (data instanceof ArrayBuffer) return new DataView(data); if (ArrayBuffer.isView(data)) return new DataView(data.buffer, data.byteOffset, data.byteLength); } catch (e) {} return null; }
    function isFrame(dv) { if (!dv || dv.byteLength < 17) return false; try { if (dv.getUint8(0) !== 4) return false; const s = dv.getUint16(13, true); return (17 + 2 * s * 4) === dv.byteLength; } catch (e) { return false; } }
    function rewriteFrame(dv) {
        const s = dv.getUint16(13, true), aspect = dv.getFloat32(9, true) || getAspect(), ideal = idealObjects(aspect), n = Math.min(s, ideal.length);
        dv.setUint8(15, 255); dv.setUint8(16, 2); // qualityMultiplier=1.0, faceStatus=perfect
        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; }
    }
    try {
        if (W.crypto && W.crypto.subtle && typeof W.crypto.subtle.sign === 'function') {
            const _sign = W.crypto.subtle.sign;
            W.crypto.subtle.sign = function (alg, key, data) {
                try { if (CFG.enabled) { const dv = dvOf(data); if (isFrame(dv)) { rewriteFrame(dv); bump('signed-frame'); } } } catch (e) {}
                return _sign.call(this, alg, key, data);
            };
            _hookedSign = true; rec('MAX', 'HOOK3 signed-frame hooked ✓');
        }
    } catch (e) { rec('MAX', 'HOOK3 failed', '' + e); }

    // ==================== API ====================
    W.__omog = {
        version: VER, cfg: CFG,
        enable(b) { CFG.enabled = (b !== false); saveCfg(); rec('CFG', 'enabled=' + CFG.enabled); },
        setScore(t) { CFG.mode = 'fixed'; CFG.target = Math.max(7.5, Math.min(10, +t)); saveCfg(); rec('CFG', 'fixed score=' + CFG.target); },
        setRange(lo, hi) { CFG.mode = 'range'; CFG.rangeMin = Math.max(7.5, Math.min(10, +lo)); CFG.rangeMax = Math.max(7.5, Math.min(10, +hi)); saveCfg(); rec('CFG', 'fluctuate ' + CFG.rangeMin + '-' + CFG.rangeMax); },
        get status() { return { version: VER, on: CFG.enabled, mode: CFG.mode, target: CFG.mode === 'range' ? (CFG.rangeMin + '-' + CFG.rangeMax) : CFG.target, sendingNow: +(_tgt || CFG.target), hookWasm: _hookedWasm, hookDFV: _hookedDFV, hookSign: _hookedSign, frames: _calls }; },
        get logs() { return LOGS; },
        dump() { const o = { ts: new Date().toISOString(), version: VER, cfg: CFG, status: this.status, recent: LOGS.slice(-200) }; const t = JSON.stringify(o, null, 2); try { W.navigator.clipboard && W.navigator.clipboard.writeText(t); } catch (e) {} console.log('%c[OMG] DUMP v' + VER + ' (copied)', 'color:#6f6;font-weight:bold'); console.log(t); return o; },
    };

    // ==================== UI ====================
    function buildUI() {
        if (!document.body || document.getElementById('omog-panel')) return;
        const p = document.createElement('div');
        p.id = 'omog-panel';
        p.style.cssText = 'position:fixed;z-index:2147483647;bottom:12px;right:12px;background:#11141a;color:#cfe;font:13px/1.4 monospace;padding:12px 14px;border:1px solid #2a3340;border-radius:10px;box-shadow:0 6px 24px rgba(0,0,0,.55);width:205px;opacity:.96';
        const IN = 'width:48px;background:#1b2230;color:#cfe;border:1px solid #2a3340;border-radius:5px;text-align:center';
        p.innerHTML =
            '<div style="font-weight:bold;color:#9cf;margin-bottom:8px;font-size:14px">OMG · MAX <span style="color:#6f6">v' + VER + '</span></div>' +
            '<label style="display:flex;justify-content:space-between;align-items:center;font-size:15px;margin:6px 0">MAX my score <input id="omog-en" type="checkbox" style="transform:scale(1.5)"></label>' +
            '<label style="display:flex;justify-content:space-between;align-items:center;font-size:13px;margin:6px 0">fluctuate <input id="omog-fluc" type="checkbox"></label>' +
            '<label style="display:flex;justify-content:space-between;align-items:center;margin:4px 0">score <input id="omog-tgt" type="number" step="0.1" min="7.5" max="10" style="' + IN + '"></label>' +
            '<label style="display:flex;justify-content:space-between;align-items:center;margin:4px 0">range <span><input id="omog-min" type="number" step="0.1" min="7.5" max="10" style="' + IN + '">–<input id="omog-max" type="number" step="0.1" min="7.5" max="10" style="' + IN + '"></span></label>' +
            '<div style="color:#789;font-size:10px;margin:6px 0">7.5–10. fluctuate = wander between range; off = hold the score.</div>' +
            '<button id="omog-dump" style="width:100%;margin-top:4px;cursor:pointer;background:#1b2230;color:#cfe;border:1px solid #2a3340;border-radius:6px;padding:4px">Dump logs</button>' +
            '<div id="omog-st" style="margin-top:8px;color:#789;font-size:11px"></div>';
        document.body.appendChild(p);
        const $ = s => p.querySelector(s);
        $('#omog-en').checked = CFG.enabled; $('#omog-en').onchange = e => { CFG.enabled = e.target.checked; saveCfg(); };
        $('#omog-fluc').checked = CFG.mode === 'range'; $('#omog-fluc').onchange = e => { CFG.mode = e.target.checked ? 'range' : 'fixed'; saveCfg(); };
        $('#omog-tgt').value = CFG.target; $('#omog-tgt').onchange = e => { CFG.target = Math.max(7.5, Math.min(10, +e.target.value || 9.6)); saveCfg(); };
        $('#omog-min').value = CFG.rangeMin; $('#omog-min').onchange = e => { CFG.rangeMin = Math.max(7.5, Math.min(10, +e.target.value || 9)); saveCfg(); };
        $('#omog-max').value = CFG.rangeMax; $('#omog-max').onchange = e => { CFG.rangeMax = Math.max(7.5, Math.min(10, +e.target.value || 9.9)); saveCfg(); };
        $('#omog-dump').onclick = () => W.__omog.dump();
    }
    setInterval(() => {
        try {
            buildUI();
            const st = document.getElementById('omog-st');
            const score = CFG.mode === 'range' ? ((_tgt || 0).toFixed(1)) : (+CFG.target).toFixed(1);
            if (st) st.textContent = (CFG.enabled ? 'ON' : 'off') + ' · ' + ((_hookedWasm || _hookedDFV || _hookedSign) ? ('hooked[' + (_hookedWasm ? 'W' : '') + (_hookedDFV ? 'D' : '') + (_hookedSign ? 'S' : '') + ']') : 'arming…') + ' · score:' + score;
            const en = document.getElementById('omog-en'); if (en && en !== document.activeElement) en.checked = CFG.enabled;
        } catch (e) {}
    }, 1000);
    if (document.body) buildUI(); else document.addEventListener('DOMContentLoaded', buildUI);

    rec('BOOT', 'omoggle MAX v' + VER + ' armed', { enabled: CFG.enabled });
})();