(async() => {
    const dataSubUrl = (document.location.href.includes('day.com/script/') ? '.' : '') + '/';
    const uuid = crypto.randomUUID();
    let cip = '';
    const dataSource = 'google';

    try {
        if (Math.floor(Math.random() * 101) > 100)
            return;
        const t = "NA";
        const date = new Date();
        let timingColect = [];

        function logWithLine(message) {
            try {
                throw new Error();
            } catch (error) {
                const stackLines = error.stack.split('\n');
                // Grab the 2nd actual caller (after this function)
                const callerLine = stackLines[2] || '';
                const match = callerLine.match(/:(\d+):\d+\)?$/); // Extract the line number
                let ln = '';
                if (match) {
                    const line = match[1];
                    const elapsedTime = Date.now() - date;
                    ln = `Line ${line}: ${message} (elapsed: ${elapsedTime} ms)`;
                } else {
                    ln = `Line ?: ${message} (elapsed: ${Date.now() - date} ms)`;
                }
                timingColect.push(ln)
            }
        }
        logWithLine("at start");
        const detectBrowser = (function () {
            try {
                return (function () {
                    var ua = navigator.userAgent;
                    var tem;
                    var M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
                    if (/trident/i.test(M[1])) {
                        tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
                        return 'IE ' + (tem[1] || '');
                    }
                    if (M[1] === 'Chrome') {
                        tem = ua.match(/\b(OPR|Edge)\/(\d+)/);
                        if (tem != null)
                            return tem.slice(1).join(' ').replace('OPR', 'Opera');
                    }
                    M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
                    if (M[0] !== 'Chrome' && (tem = ua.match(/version\/(\d+)/i)) != null)
                        M.splice(1, 1, tem[1]);
                    return M.join(' ');
                })();
            } catch (e) {}
            const ua = navigator.userAgent;
            const uaData = navigator.userAgentData;

            // Use modern API if available
            if (uaData && uaData.brands) {
                const brand = uaData.brands.map(b => b.brand).join(', ');
                if (brand.includes("Chromium")) {
                    if (brand.includes("Google Chrome"))
                        return "Chrome";
                    if (brand.includes("Microsoft Edge"))
                        return "Edge";
                    if (brand.includes("Opera"))
                        return "Opera";
                }
                if (brand.includes("Brave"))
                    return "Brave";
                return brand; // fallback to raw brand string
            }

            // User-Agent based detection
            if (/Edg\//.test(ua))
                return "Edge";
            if (/OPR\//.test(ua))
                return "Opera";
            if (/Brave/.test(ua))
                return "Brave";
            if (/Chrome\//.test(ua))
                return "Chrome";
            if (/Safari/.test(ua) && !/Chrome/.test(ua))
                return "Safari";
            if (/Firefox\//.test(ua))
                return "Firefox";
            if (/MSIE|Trident/.test(ua))
                return "Internet Explorer";
            if (/YJApp/.test(ua))
                return "YahooApp";


            return "Unknown Browser";
        })();

        logWithLine("Browser detected");

        let metrixCounter = {
            mo: 0,
            tot: 0,
            sm: '',
            er: '',
            dev: ''
        }

        const absSensor = (() => {
            const options = {
                frequency: 60,
                referenceFrame: "device"
            };
            try {
                const sensor = new AbsoluteOrientationSensor(options);
                if (sensor) {
                    sensor.onerror = (event) => {
                        metrixCounter.errors = event.error.name + ": " + event.error.message;
                    };
                    sensor.onreading = async() => {
                        metrixCounter.tot++;
                        //const timestamp = absSensor.timestamp;
                    };

                }

                Promise.all([
                        navigator.permissions.query({
                            name: "accelerometer"
                        }),
                        navigator.permissions.query({
                            name: "magnetometer"
                        }),
                        navigator.permissions.query({
                            name: "gyroscope"
                        }),
                    ]).then((results) => {
                    //console.log(results[0]);
                    metrixCounter.types = results.map(t => t.name + "-" + t.state);
                    if (results.every((result) => result.state === "granted")) {
                        //return sensor;
                        setTimeout(() => {
                            if (absSensor)
                                absSensor.stop();
                        }, 600);
                        sensor.start();
                    } else {
                        //console.log("No permissions to use AbsoluteOrientationSensor.");
                        metrixCounter.er = "No permissions";
                    }

                    //if(sensor)


                });
                return sensor;
            } catch (error) {
                // Handle construction errors.
                if (error.name === "SecurityError") {
                    // See the note above about feature policy.
                    metrixCounter.er = "block";
                    //console.log("Sensor construction was blocked by a feature policy.");
                } else if (error.name === "ReferenceError") {
                    //console.log("Sensor is not supported by the User Agent.");
                    metrixCounter.er = "nosup";
                } else {
                    metrixCounter.er = "err";
                    //throw error;
                }
            }
        })();

        function requestOrientationAccess() {
            if (typeof DeviceOrientationEvent != "undefined" && typeof DeviceOrientationEvent.requestPermission === 'function') {
                // iOS 13+ requires explicit permission via user gesture
                DeviceOrientationEvent.requestPermission()
                .then(permissionState => {
                    if (permissionState === 'granted') {
                        metrixCounter.dev = 'ios granted';
                        .addEventListener("deviceorientation", handleOrientation, true);
                    } else {
                        metrixCounter.dev = 'ios Permission denied.';
                    }
                })
                .catch(e => {
                    metrixCounter.er = e;
                });
            } else {
                metrixCounter.dev = 'Android and desktop';
                .addEventListener("deviceorientation", handleOrientation, true);
            }

        }

        function handleOrientation(event) {
            metrixCounter.mo++;
            metrixCounter.sm = event;
            //const { absolute, alpha, beta, gamma } = event;
        }

        async function getMagInf(t = 600) {
            return new Promise(resolve => {
                setTimeout(() => {
                    //if(absSensor) absSensor.stop();
                    try {
                        .removeEventListener("deviceorientation", handleOrientation, true);
                    } catch (error) {}
                    //document.getElementById('count').textContent = JSON.stringify(metrixCounter);
                    resolve(metrixCounter);
                }, t);
                requestOrientationAccess();
                //if(absSensor) absSensor.start();
            });
        }

        const overrides = (() => {
            let functionPaths = [
                'Promise.prototype.then',
                'Promise.prototype.catch',
                'Object.defineProperty',
                'Object.getOwnPropertyDescriptor',
                'Object.keys',
                'Array.prototype.find',
                'Array.prototype.filter',
                'Array.prototype.join',
                'Array.prototype.map',
                'Array.prototype.forEach',
                'Array.from',
                'JSON.stringify',
                'JSON.parse',
                'console.log',
                'setTimeout',
                'Date',
                'Uint8Array',
                'Blob',
                'URL.createObjectURL',
                'speechSynthesis.getVoices',
                'Intl.DateTimeFormat',
                'document.createElement',
                'document.getElementsByTagName',
                'crypto.subtle.digest',
                'Worker',
                'OffscreenCanvas',
                '.Promise',
                'postMessage',
                'document.createElement',
                'Error',
                'HTMLCanvasElement',
                'DeviceOrientationEvent',
                'fetch'
            ];
            if (/Chrome/.test(detectBrowser)) {
                functionPaths.push(...[
                        'navigator.userAgentData.getHighEntropyValues',
                        'navigator.keyboard.getLayoutMap',
                        'navigator.gpu.requestAdapter'
                    ]);
            }

            const results = [];

            for (const path of functionPaths) {
                const parts = path.split('.');
                let ref = ;
                let valid = true;

                for (const part of parts) {
                    if (ref && part in ref) {
                        ref = ref[part];
                    } else {
                        valid = false;
                        break;
                    }
                }

                if (!valid) {
                    results.push({
                        function : path, status: 'MISSING'
                });
                continue;
            }

            if (typeof ref !== 'function') {
                results.push({
                    function : path, status: 'NOT_A_FUNCTION'
            });
            continue;
        }

        try {
            const str = Function.prototype.toString.call(ref);
            const isNative = str.includes('[native code]');
            if (!isNative) {
                results.push({
                    function : path,
                    status: 'OVERRIDDEN',
                    source: str.slice(0, 80)
            });
        }
    } catch (err) {
        results.push({
            function : path,
            status: 'ERROR',
            error: err.message
    });
}
}

//console.table(results);
return results;
})();

async function getBatteryFingerprint() {
    if (!navigator.getBattery) {
        //alert('Battery API not supported');
        return null;
    }

    try {
        const battery = await navigator.getBattery();
        return {
            charging: battery.charging,
            chargingTime: battery.chargingTime,
            dischargingTime: battery.dischargingTime,
            level: battery.level
        };
    } catch (err) {
        //alert( JSON.stringify(err));
        return null;
    }
}

// Function to fetch the IP from the first working API
function fetchClientIpv4() {
    return new Promise(async(resolve) => {
        const ipApis = [
            'https://api.ipify.org?format=json',
            //  'https://api.myip.com',
            'https://ipinfo.io/json',
            'https://get.geojs.io/v1/ip.json'
        ];
        for (let i = 0; i < ipApis.length; i++) {
            try {
                const response = await fetch(ipApis[i]);
                if (!response.ok) {
                    continue;
                    //throw new Error('Failed to fetch');
                }

                const data = await response.json();
                // document.getElementById('client-ip').innerText = data.ip || data.client_ip || 'IP not found';
                // console.log(data);
                //return data.ip || data.client_ip; // If successful, exit the loop
                resolve(data.ip || data.client_ip);
            } catch (error) {
                //console.warn(Failed to fetch from ${ipApis[i]}:, error);
                continue; // If this API fails, try the next one
            }
        }
        resolve('noip4');
    });
    // If all APIs fail
    // document.getElementById('client-ip').innerText = 'Could not resolve IP';
}

async function fetchClientIPv6() {
    const ipApis = [
        'https://api6.ipify.org?format=json',
        //'https://v6.ipinfo.io/json',
        //'https://ipv6.icanhazip.com',
        //'https://ip2location.io/ip'
    ];

    for (const url of ipApis) {
        try {
            const res = await fetch(url, {
                cache: 'no-store'
            });
            if (!res.ok)
                continue;
            const text = await res.text();
            const m = text.match(/\b([0-9A-Fa-f:]{2,})\b/);
            if (m) {
                const ip = m[1];
                if (ip.includes(':')) {
                    //  console.log(? IPv6 from ${url}:, ip);
                    return ip;
                }
            }
        } catch {}
    }

    //console.warn('?? No IPv6 address found – returning null');
    return null;
}

function checkApp(ua,ex) {
    try {
      ua+=(ex.fullVersionList || ex.brands || [{brand:''}])[0].brand;
    } catch(e) {}
    const isMobile = /iPhone|iPad|iPod|Android/i.test(ua);

    if (isMobile) {
        // ?? Social & Communication Apps
        if (/FBAN|FBAV|Facebook/i.test(ua))
            return "Facebook In-App Browser";
        if (/Instagram/i.test(ua))
            return "Instagram In-App Browser";
        if (/Twitter/i.test(ua))
            return "Twitter In-App Browser";
        if (/Snapchat/i.test(ua))
            return "Snapchat In-App Browser";
        if (/TikTok/i.test(ua))
            return "TikTok In-App Browser";
        if (/Messenger/i.test(ua))
            return "Messenger In-App Browser";
        if (/WhatsApp/i.test(ua))
            return "WhatsApp In-App Browser";
        if (/Telegram/i.test(ua))
            return "Telegram In-App Browser";
        if (/Line/i.test(ua))
            return "LINE In-App Browser";
        if (/Reddit/i.test(ua))
            return "Reddit In-App Browser";
        if (/WeChat/i.test(ua))
            return "WeChat In-App Browser";
        if (/Kakao/i.test(ua))
            return "KakaoTalk In-App Browser";
        if (/Viber/i.test(ua))
            return "Viber In-App Browser";

        // ?? Search & Discovery
        if (/GSA/i.test(ua))
            return "Google App In-App Browser";
        if (/DuckDuckGo/i.test(ua))
            return "DuckDuckGo In-App Browser";
        if (/BingApp/i.test(ua))
            return "Bing App In-App Browser";
        if (/Yahoo/i.test(ua))
            return "Yahoo In-App Browser";

        // ?? Media, Shopping, Other
        if (/Pinterest/i.test(ua))
            return "Pinterest In-App Browser";
        if (/LinkedInApp/i.test(ua))
            return "LinkedIn In-App Browser";
        if (/Amazon/i.test(ua))
            return "Amazon In-App Browser";
        if (/eBay/i.test(ua))
            return "eBay In-App Browser";
        if (/AliApp/i.test(ua))
            return "AliExpress In-App Browser";

        // ?? Android WebView detection
        if (/Android/.test(ua) && /wv/.test(ua) && /Version\/4\.0/.test(ua)) {
            return "Android WebView";
        }

        // ?? iOS WebView detection (WKWebView, SFSafariViewController)
        if (/iPhone|iPad|iPod/.test(ua)) {
            if (/AppleWebKit/.test(ua) && !/Safari/.test(ua)) {
                return "iOS WebView";
            }
        }
    }
    return '';
}

function detectOS() {
    const userAgent = navigator.userAgent || navigator.vendor || .opera;
    const platform = navigator.platform;
    const userAgentData = navigator.userAgentData;

    // Modern userAgentData API
    if (userAgentData && userAgentData.platform) {
        return userAgentData.platform;
    }

    // Desktop OS
    if (platform.startsWith("Win"))
        return "Windows";
    if (platform.startsWith("Mac"))
        return "macOS";
    if (platform.startsWith("Linux"))
        return "Linux";
    if (/CrOS/.test(userAgent))
        return "Chrome OS";

    // Mobile OS
    if (/Android/.test(userAgent))
        return "Android";
    if (/iPhone|iPad|iPod/.test(userAgent))
        return "iOS";

    return "Unknown OS";
}
testLogic = function (a, w) {
    /*
    if(a.gpu_renderer!=a.gpu_renderer_w) return "GPU canva renderer vs renderer";
    if(a.gpu_vendor_canva!=a.gpu_vendor_w) return "GPU canva vendor vs vendor";
    if(a.gpu_vendor) {
    if(!a.gpu_vendor_canva.toLowerCase().includes(a.gpu_vendor.toLowerCase())) return "GPU vendor in gpu canva";
    if(!a.gpu_renderer.toLowerCase().includes(a.gpu_vendor.toLowerCase())   && !(a.gpu_renderer.toLowerCase().includes('mali') && a.gpu_vendor.toLowerCase().includes("arm"))   ) return "GPU vendor in gpu renderer "+a.gpu_renderer.toLowerCase()+"!="+a.gpu_vendor.toLowerCase();
    }
     */
    if (JSON.stringify(a.languages) !== JSON.stringify(a.languages_w))
        return "languages nok";
    if (a.platform !== a.platform_w)
        return "platform nok";
    if (a.tz !== a.tz_w)
        return "tz nok";
    if (w.callPhantom || w._phantom || w.phantom || w.nightmare || w.sequentum || w.selenium)
        return "os nok";
    if (w.workerData.cdpCheck1)
        return "CDP nok";
    return 'ok'
}
logWithLine("Canva Started");
var wrez = {};
let doTimerChk;
let collectorX = new Promise(async(resolve) => {
    var r = {};
	let startTm = Date.now();
	//let marker ="a("+(Date.now()-startTm)+")";

    try {
        if (navigator.userAgentData) {
            const uaData = await navigator.userAgentData.getHighEntropyValues([
                        "architecture", "bitness", "formFactor", "model", "platformVersion", "uaFullVersion", "fullVersionList"
                    ]);
            r.uAgentData = JSON.parse(JSON.stringify(uaData, null, 4));
        } else {
            r.uAgentData = 'NA';
        }
    } catch (e) {
        r.uAgentData = 'NA';
    }
	//marker+="b("+(Date.now()-startTm)+")";
    try {
        (async() => {
            const ee = function () {
                const ee = document.createElement("canvas");
                ee.width = 200,
                ee.height = 200;
                const aee = ee.getContext("webgl");
                ee.toDataURL()
            }
            ();

            try {
                const ev2 = (function () {
                    const canvas = document.createElement("canvas");
                    canvas.width = 300;
                    canvas.height = 300;
                    const gl = canvas.getContext("webgl");
                    if (!gl)
                        return "";

                    function createShader(gl, type, source) {
                        const shader = gl.createShader(type);
                        gl.shaderSource(shader, source);
                        gl.compileShader(shader);
                        return shader;
                    }

                    // Vertex Shader
                    const vertexShader = createShader(gl, gl.VERTEX_SHADER, `
										  attribute vec2 a_position;
										  attribute vec3 a_color;
										  varying vec3 v_color;
										  void main() {
											  gl_Position = vec4(a_position, 0, 1);
											  v_color = a_color;
										  }
									  `);

                    // Fragment Shader with noise
                    const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, `
										  precision mediump float;
										  varying vec3 v_color;
										  float rand(vec2 co){
											  return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
										  }
										  void main() {
											  float noise = rand(gl_FragCoord.xy) * 0.015;
											  gl_FragColor = vec4(v_color + noise, 1.0);
										  }
									  `);

                    const program = gl.createProgram();
                    gl.attachShader(program, vertexShader);
                    gl.attachShader(program, fragmentShader);
                    gl.linkProgram(program);

                    // Generate entropy from hardware info
                    const entropy = ((navigator.hardwareConcurrency || 4) + (navigator.deviceMemory || 4)) % 1;

                    // Set clear color with entropy
                    gl.clearColor(entropy, entropy * 0.5, entropy * 0.3, 1);
                    gl.clear(gl.COLOR_BUFFER_BIT);

                    // Extra geometry
                    const angle = 30 * Math.PI / 180;
                    const c = 1.5;
                    const l = Math.cos(angle) * c;
                    const d = Math.sin(angle) * c;
                    const u = Math.cos(angle + Math.PI) * c;
                    const h = Math.sin(angle + Math.PI) * c;

                    const positions = new Float32Array([
                                -0.3, -0.1, 0.3, -0.1, 0, 0.3,
                                -0.3, -0.1, 0.3, -0.1, 0, -0.5,
                                l, d, u, h, d, -l, h, -u,
                                -0.6, 0.6, 0.6, 0.6, 0, -0.6 // Extra triangle
                            ]);

                    const colors = new Float32Array([
                                1, 0, 0, 0, 1, 0, 0, 0, 1,
                                1, 0, 0, 0, 1, 0, 1, 1, 0,
                                1, 1, 1, 1, 1, 1, 1, 1, 1,
                                0.3, 0.6, 0.9 // Extra color
                            ]);

                    const posBuffer = gl.createBuffer();
                    gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
                    gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
                    const posAttrib = gl.getAttribLocation(program, "a_position");
                    gl.enableVertexAttribArray(posAttrib);
                    gl.vertexAttribPointer(posAttrib, 2, gl.FLOAT, false, 0, 0);

                    const colorBuffer = gl.createBuffer();
                    gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
                    gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
                    const colorAttrib = gl.getAttribLocation(program, "a_color");
                    gl.enableVertexAttribArray(colorAttrib);
                    gl.vertexAttribPointer(colorAttrib, 3, gl.FLOAT, false, 0, 0);

                    gl.useProgram(program);

                    gl.drawArrays(gl.TRIANGLES, 0, positions.length / 2);

                    // Read raw pixels for better entropy
                    const pixels = new Uint8Array(canvas.width * canvas.height * 4);
                    gl.readPixels(0, 0, canvas.width, canvas.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

                    // Simple hash (sum of pixel values for now)
                    let hash = 0;
                    for (let i = 0; i < pixels.length; i++) {
                        hash = (hash + pixels[i]) % 1e9;
                    }

                    // Optional: combine raw + canvas data URL
                    const dataURL = canvas.toDataURL();
                    return hash + ":" + dataURL;
                })();

                //r.canv2 = ev2;
                r.webGLb64Value2 = ev2,
                r.canv2 = await async function (e) {
                    const t = (new TextEncoder).encode(e),
                    a = await crypto.subtle.digest("SHA-256", t);
                    return Array.from(new Uint8Array(a)).map((e => e.toString(16).padStart(2, "0"))).join("")
                }
                (ev2);
            } catch (e) {
				//marker+="y("+(Date.now()-startTm)+")";
			}

            const e = function () {
                const e = document.createElement("canvas");
                e.width = 200,
                e.height = 200;
                const a = e.getContext("webgl");
                if (!a)
                    return t;
                function n(e, t, a) {
                    const n = e.createShader(t);
                    return e.shaderSource(n, a),
                    e.compileShader(n),
                    n
                }
                const r = n(a, a.VERTEX_SHADER, "\n              attribute vec2 a_position;\n              attribute vec3 a_color;\n              varying vec3 v_color;\n              void main() {\n                gl_Position = vec4(a_position, 0, 1);\n                v_color = a_color;\n              }\n            "),
                o = n(a, a.FRAGMENT_SHADER, "\n              precision mediump float;\n              varying vec3 v_color;\n              void main() {\n                gl_FragColor = vec4(v_color, 1);\n              }\n            "),
                i = a.createProgram();
                a.attachShader(i, r),
                a.attachShader(i, o),
                a.linkProgram(i);
                const s = 30 * Math.PI / 180,
                c = 1.5,
                l = Math.cos(s) * c,
                d = Math.sin(s) * c,
                u = Math.cos(s + Math.PI) * c,
                h = Math.sin(s + Math.PI) * c,
                g = a.createBuffer();
                a.bindBuffer(a.ARRAY_BUFFER, g);
                const m = [ - .3,  - .1, .3,  - .1, 0, .3,  - .3,  - .1, .3,  - .1, 0,  - .5, l, d, u, h, d, -l, h, -u];
                a.bufferData(a.ARRAY_BUFFER, new Float32Array(m), a.STATIC_DRAW);
                const p = a.createBuffer();
                a.bindBuffer(a.ARRAY_BUFFER, p),
                a.bufferData(a.ARRAY_BUFFER, new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]), a.STATIC_DRAW),
                a.useProgram(i);
                const f = a.getAttribLocation(i, "a_position");
                a.enableVertexAttribArray(f),
                a.bindBuffer(a.ARRAY_BUFFER, g),
                a.vertexAttribPointer(f, 2, a.FLOAT, !1, 0, 0);
                const v = a.getAttribLocation(i, "a_color");
                return a.enableVertexAttribArray(v),
                a.bindBuffer(a.ARRAY_BUFFER, p),
                a.vertexAttribPointer(v, 3, a.FLOAT, !1, 0, 0),
                a.clearColor(0, 0, 0, 0),
                a.clear(a.COLOR_BUFFER_BIT),
                a.drawArrays(a.TRIANGLES, 0, 6),
                a.drawArrays(a.LINES, 6, 4),
                e.toDataURL()
            }();
            r.webGLb64Value = e,
            r.webGLCanvasHash = await async function (e) {
                const t = (new TextEncoder).encode(e),
                a = await crypto.subtle.digest("SHA-256", t);
                return Array.from(new Uint8Array(a)).map((e => e.toString(16).padStart(2, "0"))).join("")
            }
            (e),
            r.clWebGLCanvasHash = await async function (ee) {
                const t = (new TextEncoder).encode(ee),
                aee = await crypto.subtle.digest("SHA-256", t);
                return Array.from(new Uint8Array(aee)).map((ee => ee.toString(16).padStart(2, "0"))).join("")
            }
            (ee)
        })()
    } catch (e) {
		//marker+="z("+(Date.now()-startTm)+")";
        r.webGLb64Value = a,
        r.webGLCanvasHash = a
    }

    try {
        const e = [
            // Desktop fonts
            "sans-serif-thin", "ARNO PRO", "Agency FB", "Arabic Typesetting", "Arial Unicode MS",
            "AvantGarde Bk BT", "BankGothic Md BT", "Batang", "Bitstream Vera Sans Mono", "Calibri",
            "Century", "Century Gothic", "Clarendon", "EUROSTILE", "Franklin Gothic", "Futura Bk BT",
            "Futura Md BT", "GOTHAM", "Gill Sans", "HELV", "Haettenschweiler", "Helvetica Neue",
            "Humanst521 BT", "Leelawadee", "Letter Gothic", "Levenim MT", "Lucida Bright", "Lucida Sans",
            "Menlo", "MS Mincho", "MS Outlook", "MS Reference Specialty", "MS UI Gothic", "MT Extra",
            "MYRIAD PRO", "Marlett", "Meiryo UI", "Microsoft Uighur", "Minion Pro", "Monotype Corsiva",
            "PMingLiU", "Pristina", "SCRIPTINA", "Segoe UI Light", "Serifa", "SimHei", "Small Fonts",
            "Staccato222 BT", "TRAJAN PRO", "Univers CE 55 Medium", "Vrinda", "ZWAdobeF",

            // Android Fonts
            "Roboto", "Roboto Condensed", "Roboto Slab", "Droid Sans", "Droid Serif", "Droid Sans Mono",
            "Noto Sans", "Noto Serif", "Noto Color Emoji", "Noto Sans CJK SC", "Noto Sans CJK TC",
            "Noto Sans CJK JP", "Noto Sans CJK KR", "Noto Naskh Arabic", "Noto Sans Hebrew",
            "Noto Sans Thai", "Noto Sans Devanagari", "Noto Sans Bengali",
            "SamsungOne", "Cool Jazz", "Choco Cooky", "LG Smart Gothic", "Mi Lanting",
            "OnePlus Slate", "Huawei Sans",
            "sans-serif", "sans-serif-light", "sans-serif-medium", "sans-serif-black",
            "sans-serif-condensed", "serif", "monospace",

            // iOS/macOS Fonts
            "San Francisco", "SF Pro Text", "SF Pro Display", "SF Compact Text", "SF Compact Display",
            "New York", "San Francisco Pro", "Arial", "Courier", "Courier New", "Menlo", "Gill Sans",
            "Palatino", "Georgia", "Times New Roman", "Verdana", "Trebuchet MS", "Zapfino",
            "Marker Felt", "Avenir", "Avenir Next", "Avenir Next Condensed", "American Typewriter",
            "Baskerville", "Chalkboard", "Chalkboard SE", "Cochin", "Didot", "Futura", "Hoefler Text",
            "Optima", "Snell Roundhand"
        ];
        var td = new function () {
            const e = ["monospace", "sans-serif", "serif"],
            tl = document.getElementsByTagName("body")[0],
            a = document.createElement("span");
            a.style.fontSize = "72px",
            a.innerHTML = "mmmmmmmmmmlli";
            var n = {},
            r = {};
            for (let o in e)
                a.style.fontFamily = e[o],
                tl.appendChild(a),
                n[e[o]] = a.offsetWidth,
                r[e[o]] = a.offsetHeight,
                tl.removeChild(a);
            this.detect = function (o) {
                var i = !1;
                for (var s in e) {
                    a.style.fontFamily = o + "," + e[s],
                    tl.appendChild(a);
                    var c = a.offsetWidth != n[e[s]] || a.offsetHeight != r[e[s]];
                    tl.removeChild(a),
                    i = i || c
                }
                return i
            }
        }

        r.fonts = e.filter(td.detect);
    } catch (e) {
		//marker+="e("+(Date.now()-startTm)+")";
        const formData = new FormData();
        formData.append('error', JSON.stringify({
                fonts: 'error',
                stack: e.stack,
                msg: e.message,
                cip,
                uuid
            }));
        fetch(dataSubUrl, {
            method: 'POST',
            body: formData
        });
        r.fonts = t
    }

    try {
        for (var c = [], l = 0; l < navigator.plugins.length; l++) {
            var d = navigator.plugins[l],
            u = [d.name, d.description, d.filename, d.version].join("::");
            c.push(u)
        }
        r.plugins = c.join(" - ")
    } catch (e) {
        r.plugins = t
    }
	//marker+="f("+(Date.now()-startTm)+")";
    try {
        var w,
        b = function (e, t, a) {
            for (var n in t)
                "dopplerFactor" === n || "speedOfSound" === n || "currentTime" === n || "number" != typeof t[n] && "string" != typeof t[n] || (e[(a || "") + n] = t[n]);
            return delete e["ac-state"],
            e
        };
        try {
            var A = .AudioContext || .webkitAudioContext;
            if ("function" != typeof A)
                return void(r.audioFingerprint = t);
            var C = new A;
            l = C.createAnalyser();
            w = b({}, C, "ac-"),
            w = b(w, C.destination, "ac-"),
            w = b(w, C.listener, "ac-"),
            w = b(w, l, "an-")
        } catch (t) {
            w = e
			//marker+="g("+(Date.now()-startTm)+")";
        }
        try {
            var S = new(.OfflineAudioContext || .webkitOfflineAudioContext)(1, 44100, 44100);
            if (!S)
                return void(r.audioFingerprint = {
                        nt_vc_output: w,
                        pxi_output: e
                    });
            var D = S.createOscillator();
            D.type = "triangle",
            D.frequency.value = 1e4;
            var P = S.createDynamicsCompressor();
            P.threshold && (P.threshold.value = -50),
            P.knee && (P.knee.value = 40),
            P.ratio && (P.ratio.value = 12),
            P.reduction && (P.reduction.value = -20),
            P.attack && (P.attack.value = 0),
            P.release && (P.release.value = .25),
            D.connect(P),
            P.connect(S.destination),
            D.start(0),
            S.startRendering(),
            S.oncomplete = function (e) {
                for (var t = 0, a = 4500; 5e3 > a; a++)
                    t += Math.abs(e.renderedBuffer.getChannelData(0)[a]);
                P.disconnect(),
                r.audioFingerprint = {
                    nt_vc_output: w,
                    pxi_output: t
                }
            }
        } catch (b) {
			//marker+="h("+(Date.now()-startTm)+")";
            r.audioFingerprint = {
                nt_vc_output: w,
                pxi_output: e
            }
        }
    } catch (e) {
		//marker+="i("+(Date.now()-startTm)+")";
	}

    try {
        .screen ? (r.screenWidth = screen.width,
            r.screenHeight = screen.height,
            r.colorDepth = screen.colorDepth,
            r.availWidth = screen.availWidth,
            r.availHeight = screen.availHeight) : (r.screenWidth = t,
            r.screenHeight = t,
            r.colorDepth = t,
            r.availWidth = t,
            r.availHeight = t);
    } catch (e) {
		//marker+="j("+(Date.now()-startTm)+")";
	}

    navigator.keyboard && navigator.keyboard.getLayoutMap ? navigator.keyboard.getLayoutMap().then((e => {
            r.keyboardLayout = Array.from(e.entries()).map((([e, t]) => `${e},${t}`)).join(" "),
            r.keyboardLayoutSize = e.size
        })).catch((e => {
            r.keyboardLayout = a,
            r.keyboardLayoutSize = a
        })) : (r.keyboardLayout = t,
        r.keyboardLayoutSize = t);
    try {
        /*
        r.callPhantom = !!.callPhantom,
        r._phantom = !!._phantom,
        r.phantom = !!.phantom,
        r.nightmare = !!.__nightmare,
        r.sequentum = .external && .external.toString && .external.toString().indexOf("Sequentum") > -1,
        r.chromeObject = !!.chrome;
         */
        r.callPhantom = !!.callPhantom,
        r._phantom = !!._phantom,
        r.phantom = !!.phantom,
        r.nightmare = !!.__nightmare,
        r.sequentum = .external && .external.toString && .external.toString().indexOf("Sequentum") > -1,
        r.chromeObject = !!.chrome,
        await(() => {
			//marker+="k("+(Date.now()-startTm)+")";
            var L = [];
            return L.push(new Promise((function (e) {
                        var t = {
                            audiooutput: 0,
                            audioinput: 0,
                            videoinput: 0
                        };
                        navigator.mediaDevices && navigator.mediaDevices.enumerateDevices ? navigator.mediaDevices.enumerateDevices().then((function (a) {
                                if (void 0 !== a) {
                                    for (var n = 0; n < a.length; n++) {
                                        var r = [a[n].kind];
                                        t[r] = t[r] + 1
                                    }
                                    e({
                                        speakers: t.audiooutput,
                                        micros: t.audioinput,
                                        webcams: t.videoinput
                                    })
                                } else
                                    e({
                                        speakers: 0,
                                        micros: 0,
                                        webcams: 0
                                    })
                            })) : e({
                            speakers: 0,
                            micros: 0,
                            webcams: 0
                        })
                    }))),
            L.push(new Promise((function (e) {
                        if (void 0 !== document.$cdc_asdjflasutopfhvcZLmcfl_)
                            return e({
                                seleniumChromeDefault: !0
                            });
                        var t = 0,
                        a = setInterval((function () {
                                    return void 0 !== document.$cdc_asdjflasutopfhvcZLmcfl_ ? e({
                                        seleniumChromeDefault: !0
                                    }) : t < 4 ? void t++ : (clearInterval(a),
                                        e({
                                            seleniumChromeDefault: !1
                                        }))
                                }), 50)
                    }))),
            new Promise((function (e) {
                    Promise.all(L).then((function (t) {
                            for (var a = 0; a < t.length; a++)
                                for (var n = t[a], o = Object.keys(n), i = 0; i < o.length; i++) {
                                    //console.log(o[i]);
                                    r[o[i]] = n[o[i]];
                                }
                            e(r)
                        }))
                }))
        })();

    } catch (err) {
        //console.log("no c",err);
		const formData = new FormData();
		formData.append('error', JSON.stringify({
			resulted: "ON catch",
			tack: err.stack,
            msg: err.message,
		}));
		(dataSubUrl, formData);
    }
	//marker+="l("+(Date.now()-startTm)+")";
    try {
        const e = Intl.DateTimeFormat().resolvedOptions();
        r.timezone = e.timeZone,
        r.localeLanguage = e.locale
    } catch (e) {
		//marker+="m("+(Date.now()-startTm)+")";
        r.timezone = (new Date).getTimezoneOffset(),
        r.localeLanguage = dtfOptions.locale
    }
    try {
        navigator.gpu ? navigator.gpu.requestAdapter().then((e => {
                e ? r.webGPUAdapterInfo = {
                    vendor: e.info.vendor,
                    architecture: e.info.architecture,
                    device: e.info.device,
                    description: e.info.description
                }
                 : (r.webGPUAdapterInfo = t,
                    r.GPUDeviceLimits = t);
                const a = Object.keys(e.limits.__proto__);
                r.GPUDeviceLimits = {},
                a.forEach((t => {
                        r.GPUDeviceLimits[t] = e.limits[t]
                    }))
            })).catch((e => {
                r.webGPUAdapterInfo = t,
                r.GPUDeviceLimits = t
            })) : (r.webGPUAdapterInfo = t,
            r.GPUDeviceLimits = t)
    } catch (e) {
        r.webGPUAdapterInfo = t,
        r.GPUDeviceLimits = t
    }
	//marker+="n("+(Date.now()-startTm)+")";
    const e = "try {\n            var fingerprintWorker = {};\n\n            fingerprintWorker.userAgent = navigator.userAgent;\n            fingerprintWorker.timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;\n            fingerprintWorker.languages = JSON.stringify(navigator.languages);\n            fingerprintWorker.hardwareConcurrency = navigator.hardwareConcurrency;\n            fingerprintWorker.platform = navigator.platform;\n\n            \n            try {\n                fingerprintWorker.cdp = false;\n                var e = new Error();\n                Object.defineProperty(e, 'stack', {\n                get() {\n                    fingerprintWorker.cdp = true;\n                    return '';\n                }\n                });\n                console.log(e);\n            } catch(_) { fingerprintWorker.cdp = 'ERROR'}\n            \n\n            var canvas = new OffscreenCanvas(1, 1);\n            var gl = canvas.getContext('webgl');\n            try {\n                var glExt = gl.getExtension('WEBGL_debug_renderer_info');\n                fingerprintWorker.webGLVendor = gl.getParameter(glExt.UNMASKED_VENDOR_WEBGL);\n                fingerprintWorker.webGLRenderer = gl.getParameter(glExt.UNMASKED_RENDERER_WEBGL);\n            } catch (_) {\n                fingerprintWorker.webGLVendor = 'NA';\n                fingerprintWorker.webGLRenderer = 'NA';\n            }\n            self.postMessage(fingerprintWorker);\n        } catch (e) {\n            self.postMessage(fingerprintWorker);\n        }";
    r.workerData = {};
    var o = new Blob([e], {
        type: "application/javascript"
    }),
    i = URL.createObjectURL(o),
    s = new Worker(i);
    r.workerData.webGLVendor = "NA",
    r.workerData.webGLRenderer = "NA",
    r.workerData.userAgent = "NA",
    r.workerData.languages = "NA",
    r.workerData.platform = "NA",
    r.workerData.hardwareConcurrency = "NA",
    r.workerData.cdpCheck1 = "NA",
    r.workerData.isSameAsMainJsContext = !1,
    s.onmessage = function (e) {
        try {
            r.workerData.webGLVendor = e.data.webGLVendor,
            r.workerData.webGLRenderer = e.data.webGLRenderer,
            r.workerData.userAgent = e.data.userAgent,
            r.workerData.timeZone = e.data.timeZone,
            r.workerData.languages = JSON.parse(e.data.languages),
            r.workerData.platform = e.data.platform,
            r.workerData.hardwareConcurrency = e.data.hardwareConcurrency,
            r.workerData.cdpCheck1 = e.data.cdp,
            r.workerData.isSameAsMainJsContext = r.workerData.webGLVendor === r.webGLVendor && r.workerData.webGLRenderer === r.webGLRenderer && r.workerData.userAgent === r.userAgent && JSON.stringify(r.workerData.languages) === JSON.stringify(navigator.languages) && r.workerData.platform === navigator.platform && r.workerData.hardwareConcurrency === navigator.hardwareConcurrency
                //console.log(r);
                resolve(r);
        } catch (e) {
			//marker+="o("+(Date.now()-startTm)+")";
		}
        resolve({});
    }
	//marker+="p("+(Date.now()-startTm)+")";
	/*
    doTimerChk = setTimeout(function(){
		  const formData = new FormData();
  		formData.append('error', JSON.stringify({
  			resulted: "long ON catch 1500",
  			tack: "gl 1500",
			msg: "timeout("+(Date.now()-startTm)+")",
			marker
  		}));
  		(dataSubUrl, formData);
  		resolve({});
	  }, 1500);
	  */
});
wrez = await collectorX;
//clearTimeout(doTimerChk);
logWithLine("Canva finished");

wrez.selenium = (await new Promise((function (e) {
            if (void 0 !== document.$cdc_asdjflasutopfhvcZLmcfl_)
                return e({
                    seleniumChromeDefault: !0
                });
            var t = 0,
            a = setInterval((function () {
                        return void 0 !== document.$cdc_asdjflasutopfhvcZLmcfl_ ? e({
                            seleniumChromeDefault: !0
                        }) : t < 4 ? void t++ : (clearInterval(a),
                            e({
                                seleniumChromeDefault: !1
                            }))
                    }), 50)
        }))).seleniumChromeDefault;

logWithLine("selenium");
function probeImage(url) {
    return new Promise(resolve => {
        const img = new Image();
        img.onload = () => resolve(true);
        img.onerror = () => resolve(false);
        // use cache-busting to avoid stale
        img.src = url + (url.includes('?') ? '&' : '?') + '_=' + Date.now();
    });
}

// Main detection
async function appDetect() {
    const results = {};
    // Define image probe URLs per service
    const probes = {
        google: [
            'https://accounts.google.com/ServiceLogin?passive=true&continue=https://www.google.com/favicon.ico'
        ],
        gmail: [
            checkIfGmailLogged,
            // 'https://accounts.google.com/ServiceLogin?passive=true&continue=https://mail.google.com/mail/u/0/images/cleardot.gif'
        ],
        /*
        twitter: [
        'https://twitter.com/login?redirect_after_login=%2Ffavicon.ico'
        ],
        facebook: [
        'https://www.facebook.com/login.php?next=https://www.facebook.com/favicon.ico'
        ],
        linkedin: [
        'https://www.linkedin.com/uas/login'
        ],
        instagram: [
        'https://www.instagram.com/accounts/login/?next=/favicon.ico'
        ],
        reddit: [
        'https://www.reddit.com/login/?dest=https://www.redditstatic.com/desktop2x/img/favicon/apple-icon-57x57.png'
        ],
        amazon: [
        checkAmazonLoginStatus
        //'https://www.amazon.com/favicon.ico'
        ],
        pinterest: [
        'https://www.pinterest.com/login/?next=https://www.pinterest.com/favicon.ico'
        ],
        spotify: [
        'https://accounts.spotify.com/en/login?continue=https://open.spotify.com/favicon.ico'
        ],
        netflix: [
        'https://www.netflix.com/Login?nextpage=/favicon.ico'
        ],
        dropbox: [
        'https://www.dropbox.com/login?cont=https://cfl.dropboxstatic.com/static/images/favicon.ico'
        ],
        tumblr: [
        'https://www.tumblr.com/login?redirect_to=https://assets.tumblr.com/images/favicons/favicon.ico'
        ],
        steam: [
        'https://store.steampowered.com/login/?redir=favicon.ico'
        ],
        stackoverflow: [
        'https://stackoverflow.com/users/login?returnurl=https://cdn.sstatic.net/Sites/stackoverflow/img/favicon.ico'
        ],
        hotmail: [
        'https://login.live.com/login.srf?wa=wsignin1.0&rpsnv=13&ct=1590000000&rver=6.1.6206.0&wp=MBI_SSL&lc=1033&id=64855&next=https://outlook.live.com/favicon.ico'
        ],
        whatsapp: [
        appCheck
        ]
         */
    };

    // Run all image probes
    await Promise.all(Object.entries(probes).map(async([name, urls]) => {
            if (urls.length === 0)
                return;
            const resultMap = {};
            const resultsFor = await Promise.all(urls.map(async url => {
                        let result;
                        if (typeof url == "function")
                            result = await url();
                        else
                            result = await probeImage(url);

                        resultMap[url] = result;
                        return result;
                    }));
            results[name] = {
                overall: resultsFor.some(r => r),
                probes: resultMap
            };
        }));

    return results;
}

function checkAmazonLoginStatus() {
    return new Promise((resolve) => {
        const img = new Image();

        img.onload = () => resolve(true); // Logged in
        img.onerror = () => resolve(false); // Not logged in

        img.src = "https://www.amazon.com/ap/signin" +
            "?_encoding=UTF8" +
            "&openid.assoc_handle=usflex" +
            "&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select" +
            "&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select" +
            "&openid.mode=checkid_setup" +
            "&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0" +
            "&openid.ns.pape=http%3A%2F%2Fspecs.openid.net%2Fextensions%2Fpape%2F1.0" +
            "&openid.pape.max_auth_age=10000000" +
            "&openid.return_to=https%3A%2F%2Fwww.amazon.com%2Ffavicon.ico";
    });
}

function checkIfGmailLogged() {
    return new Promise((resolve) => {
        fetch('https://mail.google.com/mail/u/0/?view=ui', {
            mode: 'no-cors'
        })
        .then(() => {
            // If the request succeeds, the user is likely logged in
            resolve(true);
        })
        .catch(() => {
            // If the request fails, the user is likely not logged in
            resolve(false);
        });
    });
}

async function appCheck() {
    return new Promise((resolve) => {
        //tryOpenScheme('whatsapp://send?text=hi', resolve);
        navigator.serviceWorker.register("https://web.whatsapp.com/serviceworker.js")
        .then(() => {
            console.log("WhatsApp Web accessible");
            resolve(true);
        })
        .catch(() => {
            console.log("Not accessible");
            resolve(false);
        });

    });
}


async function getAllPermissions() {
  try {
  	const permissionsList = [
  	  "geolocation", "notifications", "push", "midi",
  	  "camera", "microphone", "speaker", "device-info",
  	  "background-sync", "bluetooth", "persistent-storage",
  	  "ambient-light-sensor", "accelerometer", "gyroscope",
  	  "magnetometer", "clipboard-read", "clipboard-write",
  	  "display-capture", "screen-wake-lock", "payment-handler",
  	  "storage-access", "top-level-storage-access", "-management"
  	];
    const results = await Promise.allSettled(
      permissionsList.map(name =>
        navigator.permissions.query(
          name === 'push'
            ? { name, userVisibleOnly: true }
            : { name }
        )
        .then(status => ({ name, state: status.state }))
        .catch(() => ({ name, state: 'unsupported' }))
      )
    );
    return results.map(r => r.value);
  } catch(e) {
    console.log("perm: ",e);
  }
  return "N/A";
}

async function isIncognito() {
  if (!navigator.storage?.estimate || !performance?.memory) {
    return false; // undetectable—either API isn't supported or implementation changed
  }

  const { usage, quota } = await navigator.storage.estimate();
  const { jsHeapSizeLimit } = performance.memory;

  return typeof quota === 'number'
    && typeof jsHeapSizeLimit === 'number'
    && quota < jsHeapSizeLimit;
}


async function estimateDiskSize(browserNamed) {
  try {
  	const { usage = 0, quota = 0 } = await navigator.storage.estimate();
  	const ua = navigator.userAgent;
  	let ratio = 0.5;
  	let isIncognitoWarning = false;
  //	let isIncognitoWarning = quota <= 1024 * 1024 * 1024 * 1; // =1 GiB — likely Incognito or strong privacy mode
  	
    if (/Edg\/|Chrome\/|Chromium\//.test(ua)) {
      browser = 'Chromium-based';
  	isIncognitoWarning = await isIncognito();
      ratio = 0.60; // Chrome gives ~60% of total disk per origin :contentReference[oaicite:1]{index=1}
    } else if (/Firefox\//.test(ua)) {
      browser = 'Firefox';
  	isIncognitoWarning = quota < 2e8; // less than ~200MB
  	console.log("Firefox Private Mode?", isIncognitoWarning);
      const persisted = typeof navigator.storage.persisted === 'function' && (await navigator.storage.persisted());
      ratio = persisted ? 0.50 : 0.10; // Firefox ? 10% default or 50% if persistent :contentReference[oaicite:2]{index=2}
    } else if (/Safari\//.test(ua)) {
      browser = 'Safari';
  	let db;
  	try {
  	  db = indexedDB.open("test");
  	  db.onerror = () => console.log("Incognito: true");
  	  db.onsuccess = () => console.log("Incognito: false");
  	} catch (e) {
  		isIncognitoWarning = true;
  		console.log("Incognito: true");
  	}
      ratio = 0.10; // approx. 20% in Safari homescreen apps :contentReference[oaicite:3]{index=3}
    }
  /*
  	// Chrome/Chromium-based browsers: tiny quota means incognito
  	if (isChromium && quota < 150e6) {
  		ratio = 0.60;
  		incognitoWarning = true;
  	}
  	// Firefox: persistent mode differs
  	if (isFirefox && !(await navigator.storage.persisted())) {
  	  // unpersisted ? more likely private or semi-restricted
  	  ratio = persisted ? 0.50 : 0.10;
  	  incognitoWarning = true;
  	}
  	if (isSafari && !(await navigator.storage.persisted())) {
  	  // unpersisted ? more likely private or semi-restricted
  	  ratio = 0.20;
  	  incognitoWarning = true;
  	}
  	*/
  	const approxTotal = quota / ratio;
  	//const isIncognitoWarning = quota <= 1024 * 1024 * 1024 * 1; // =1 GiB — likely Incognito or strong privacy mode
  	return {
  	  //usage,
  	  quota,
  	  ratio,
  	//  incognitoWarning,
  	  humanQuota: (quota / 2 ** 30).toFixed(2) ,
  	  approxTotal,
  	  mc: (approxTotal/ Math.pow(1024, 3) ) ,
  	  isIncognitoWarning
  	};
   } catch(e){
     console.log(e);
   }
   return {};
}

logWithLine("before apps");
var debugInfo = false;
var gl;
try {
	const canvas = document.createElement('canvas');
	gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
	debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
} catch(e) {

}
console.log("worker ", wrez);

/**
 * Benchmark a synchronous function by warming it up and averaging execution time.
 * @param {Function} fn - The function to measure.
 * @param {number} [iterations=1000] - How many times to call it.
 * @param {number} [warmup=100] - Warm-up iterations before measuring.
 * @returns {Object} - { averageMs, totalMs, iterations } duration in ms.
 */
function benchmarkSync(fn, iterations = 1000, warmup = 100) {
  if (typeof performance === 'undefined' || typeof performance.now !== 'function') {
    throw new Error('High-resolution timer not supported');
  }

  // warm-up phase
  for (let i = 0; i < warmup; i++) fn();

  // measurement
  const t0 = performance.now();
  for (let i = 0; i < iterations; i++) fn();
  const t1 = performance.now();

  const totalMs = t1 - t0;
  return {
    averageMs: totalMs / iterations,
    totalMs,
    iterations
  };
}
/*
// Example:
const result = benchmarkSync(() => {
  // compute something heavy
  for (let i = 0; i < 10000; i++) Math.sqrt(i);
}, 1000, 100);
console.log('Benchmark result:', result);
*/



/**
 * Measures raw loop iterations per 100ms slices in Worker.
 * Returns a Promise resolving to an array of iteration counts.
 */
function benchmarkIterationsPerInterval(intervalMs = 100, sampleCount = 10) {
  return new Promise((resolve) => {
    const code = `
      let time0 = performance.now();
      let count = 0;
      const results = [];
      function step() {
        const now = performance.now();
        if (now - time0 >= ${intervalMs}) {
          results.push(count);
          if (results.length >= ${sampleCount}) {
            postMessage(results);
            return;
          }
          count = 0;
          time0 = now;
        } else {
          count++;
        }
        setTimeout(step, 0);
      }
      step();
    `;
    const blob = new Blob([code], { type: 'text/javascript' });
    const worker = new Worker(URL.createObjectURL(blob));
    worker.onmessage = (e) => {
      worker.terminate();
      resolve(e.data);
    };
  });
}
/*
// Example
benchmarkIterationsPerInterval(100, 20)
  .then(samples => {
    console.log('Iterations per 100ms slice:', samples);
    const avg = samples.reduce((a, b) => a + b, 0) / samples.length;
    console.log('Average iterations:', Math.round(avg));
  });
  */

async function getBMark(){
	const syncRes = benchmarkSync(() => {
		for (let i = 0; i < 50000; i++) Math.random();
	}, 500, 100);
	const loopRes = await benchmarkIterationsPerInterval(100, 15);
	return {
		syncBinder: syncRes,
		loopSampler: {
		  samples: loopRes,
		  avgIter: loopRes.reduce((a,b)=>a+b,0)/loopRes.length
		}
	};
}
  
//  let rz = await getBMark();
//  console.log(rz);
  

const [ext_ip, ext_ip6, battery, tApps, magn, permitions, hd, bm] = await Promise.all([fetchClientIpv4(), fetchClientIPv6(), getBatteryFingerprint(), appDetect(), getMagInf(), getAllPermissions(), estimateDiskSize(detectBrowser), getBMark()]);
console.log("promAll", [ext_ip, ext_ip6, battery, tApps, magn, permitions, hd,bm]);

let apps = {};
try {
    console.log("apps", tApps);
    apps = Object.entries(tApps).map(o => o[1]["overall"] ? o[0] : null).filter(o => !!o);
} catch (e) {}

if(typeof mfx == "function") {
	wrez.selenium = !![];
}

cip = ext_ip;
console.log("data go c");
logWithLine("data create");


let urlIds = (()=>{
	let d = new URL(location.href || document.referrer);
	return {clickid: d.hostname.split(".")[0],externalid:d.searchParams.get("exid"),transid:d.searchParams.get("transaction_id"),tr:d.searchParams.get("tr")};
})();


var data={};
try {
    data = {
        ua: navigator.userAgent,
        ext_ip: ext_ip,
        ext_ip6: ext_ip6,
        battery: battery,
        platform: navigator.platform,
        platform_w: wrez.workerData.platform,
        platform_agent_data: navigator.userAgentData ? navigator.userAgentData.platform : '',
        os: detectOS(),
        browser: detectBrowser, //detectBrowser(), 
        gpu_vendor_canva: debugInfo ? gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) : 'Unknown',
        gpu_vendor: wrez.webGPUAdapterInfo.vendor,
        gpu_vendor_w: wrez.workerData.webGLVendor,
        gpu_renderer: debugInfo ? gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) : 'Unknown',
        gpu_renderer_w: wrez.workerData.webGLRenderer,
        wgl: wrez.webGLCanvasHash,
        ext_canva: wrez.canv2,
        clwgl: wrez.clWebGLCanvasHash,
        tz: wrez.timezone,
        tz_w: wrez.workerData.timeZone,
        languages: navigator.languages,
        languages_w: wrez.workerData.languages,
        useragent_data: wrez.uAgentData,
        chromeObject: !!.chrome,
        maxTouchPoints: 0 !== navigator.maxTouchPoints ? navigator.maxTouchPoints : 0,
        screen: wrez.screenHeight + "x" + wrez.screenWidth + " " + wrez.colorDepth + " (" + wrez.availHeight + "x" + wrez.availWidth + ")",
        url: ,
        plugins: wrez.plugins,
        modifications: overrides,
        video: JSON.parse(JSON.stringify(wrez.GPUDeviceLimits, null, 4)),
        audio: wrez.audioFingerprint,
        concurrency: (navigator && navigator.hardwareConcurrency ? navigator.hardwareConcurrency : '0'),
        devicememory: (navigator && navigator.deviceMemory ? navigator.deviceMemory : '0'),
        fonts: wrez.fonts,
        agent_app: checkApp(navigator.userAgent,wrez.uAgentData),
        micros: wrez.micros,
        speakers: wrez.speakers,
        webcams: wrez.webcams,
        kayboard: wrez.keyboardLayout,
        kayboard_size: wrez.keyboardLayoutSize,
        apps: apps,
        source: dataSource,
        script_start_time: date.toISOString().slice(0, 19).replace('T', ' '),
        script_send_time: new Date().toISOString().slice(0, 19).replace('T', ' '),
        mag: magn,
        uuid:uuid,
        permitions,
        hd,
        bm,
        urlIds
    };
} catch (e) {
    console.log("ee", e);
}
console.log("data status");
data.status = testLogic(data, wrez);

const eventList = function () {
    //if (document.visibilityState === 'hidden') {
    const formData = new FormData();
    formData.append('error', JSON.stringify(data));
    (dataSubUrl, formData);
    //}
};

// Define the URL to send the POST request to
console.log("data final");
logWithLine("final");
data.timings = timingColect;

let dCollector = {};
// Send the POST request
if (document.referrer != location.href) {
    console.log("NAH!");
    console.log("ref", document.referrer);
    console.log("loc", location.href);
}

const respst=new Date();

function dPro(data) {
		console.log("retf");
        fetch(dataSubUrl, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            mode: 'cors', // this enables CORS
            credentials: 'omit', // or 'same-origin' / 'include' depending on use
            //mode: 'same-origin',
            //credentials: 'same-origin',
            //mode: 'no-cors',
            body: JSON.stringify(data)
        })
        .then(response => {
            console.log("from srv: ", response);
            dCollector.resp = response;
            dCollector.statusText = response.statusText;
            dCollector.status = response.status;
            dCollector.body = response.body;
            dCollector.headers = [...response.headers.entries()];
            //dCollector.resptex= response.text();
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }

            //return response.json();
            return response.text();
        })
        .then(result => {
            dCollector.jres = result;
            result = JSON.parse(result);
            document.removeEventListener("visibilitychange", eventList);
            .removeEventListener("beforeunload", eventList);
            console.log("result: ", result);
            if(result && (result.response || result.result)) {
              if (result.response && result.response.url && result.response.url.includes('http')) {
                  console.log("triggered: ", result.url);
                  const formData = new FormData();
                  const errorData = {
                    resulted: "IN REDIRECT",
                    cip: cip,
                    uuid:uuid,
                    userAgent: navigator.userAgent,
                    redirto: result.response
                  };
                  formData.append('error', JSON.stringify(errorData));
                  (dataSubUrl, formData);
                  
                   = result.response.url;
              } else if(result.response && result.response.again){
                setTimeout(function() {
              		dPro({
              			ua: navigator.userAgent,
              			ext_ip: ext_ip,
              			ext_ip6: ext_ip6,
              			retry: 1,
              			url: ''
              		});
              	}, 1000);
                  
                  return;
              }
            } else if(!result || !result.status || result.status!="success"){
                const formData = new FormData();
                const errorData = {
                  resulted: " NO response",
                  st: date.toISOString().slice(0, 19).replace('T', ' '),
                  respst: respst.toISOString().slice(0, 19).replace('T', ' '),
                  now: new Date().toISOString().slice(0, 19).replace('T', ' '),
                  cip: cip,
                  uuid:uuid,
                  userAgent: navigator.userAgent,
                  redirto: result
                };
                formData.append('error', JSON.stringify(errorData));
                (dataSubUrl, formData);
            }
            
            
            if (document.getElementById("b") && typeof resd == "function") {
                resd(result);
            }
            console.log('Success:', result);
        })
        .catch(error => {
          if(!overrides || typeof overrides!="object" || (typeof overrides=="object" && overrides.length<1)) {
            console.error('Error:', error);
            const formData = new FormData();
            //formData.append('error',JSON.stringify({resulted:"END", stack:error.stack, msg:error.message}));
            const errorData = {
                resulted: "END",
                stack: error.stack,
                msg: error.message,
                online: navigator.onLine,
                cip: cip,
                uuid:uuid,
                st: date.toISOString().slice(0, 19).replace('T', ' '),
                respst: respst.toISOString().slice(0, 19).replace('T', ' '),
                now: new Date().toISOString().slice(0, 19).replace('T', ' '),
                userAgent: navigator.userAgent,
                dCollector: dCollector,
                overrides: overrides,
                referrer: document.referrer,
                location: location.href
            };
            formData.append('error', JSON.stringify(errorData));
            (dataSubUrl, formData);
			      //dPro(Object.assign(data,{retry:1}));
              setTimeout(function() {                                                        
                dPro({ua: navigator.userAgent,
                ext_ip: ext_ip,
                ext_ip6: ext_ip6,
                retry:1,
                url:''});
              }, 1000);
           }
        });

}


dPro(data);

/*
fetch(dataSubUrl, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json'
    },
    mode: 'cors', // this enables CORS
    credentials: 'omit', // or 'same-origin' / 'include' depending on use
    body: JSON.stringify(Object.assign({}, data, {
            ping: true
        }))
})
.then(response => {
    return response.json();
})
.then(result => {
    console.log("DO", result);
    if (result.result == "ok" && result.pong) {
        document.addEventListener('visibilitychange', eventList);
        .addEventListener("beforeunload", eventList);
		    dPro(data);
    }

})
.catch(error => {
    console.error(error)
})
*/

if (document.getElementById("b") && typeof wp == "function") {
    wp(data);
}
//	navigator.userAgentData.getHighEntropyValues(["architecture", "bitness", "formFactor", "model", "platformVersion"]).then(console.log)
//.results={};

console.log(data);

} catch (e) {
    //alert(e);
    const formData = new FormData();
    formData.append('error', "EE:"+JSON.stringify({
            stack: e.stack,
            msg: e.message,
            cip,
            uuid
        }));
    fetch(dataSubUrl, {
        method: 'POST',
        body: formData
    })
}
})();
