(function() { "use strict"; const schema = 1; const payload_id = "20260824T195142Z-7e8dd04"; const DEFAULT_SIGNAL_TIMEOUT_MS = 50; const MISSING = Symbol("missing"); function runOneSignal(name, fn, timingSink, timingActive, perfNow) { return new Promise(resolve => { let settled = false; const startTime = timingActive ? perfNow() : 0; let syncMs = 0; const timer = setTimeout(() => { if (!settled) { settled = true; if (timingActive) { try { timingSink.push([ name, syncMs, perfNow() - startTime, "timeout" ]); } catch {} } resolve([ name, MISSING ]); } }, DEFAULT_SIGNAL_TIMEOUT_MS); try { const fnResult = fn(); if (timingActive) syncMs = perfNow() - startTime; Promise.resolve(fnResult).then(value => { if (!settled) { settled = true; clearTimeout(timer); if (timingActive) { try { timingSink.push([ name, syncMs, perfNow() - startTime, "ok" ]); } catch {} } resolve([ name, value ]); } }, () => { if (!settled) { settled = true; clearTimeout(timer); if (timingActive) { try { timingSink.push([ name, syncMs, perfNow() - startTime, "error" ]); } catch {} } resolve([ name, MISSING ]); } }); } catch { if (timingActive) syncMs = perfNow() - startTime; if (!settled) { settled = true; clearTimeout(timer); if (timingActive) { try { timingSink.push([ name, syncMs, syncMs, "error" ]); } catch {} } resolve([ name, MISSING ]); } } }); } function runSignals(entries) { const seen = Object.create(null); for (const [name] of entries) { if (Object.prototype.hasOwnProperty.call(seen, name)) { throw new Error(`runSignals: duplicate signal name "${name}"`); } seen[name] = true; } const timingSink = globalThis.__thumbmarkSignalTimings; const timingActive = Array.isArray(timingSink) && typeof performance === "object" && performance !== null && typeof performance.now === "function"; const perfNow = timingActive ? performance.now.bind(performance) : null; return Promise.all(entries.map(([name, fn]) => runOneSignal(name, fn, timingSink, timingActive, perfNow))).then(pairs => Object.fromEntries(pairs.filter(([, v]) => v !== MISSING))); } function isNativeCode(fn) { try { return typeof fn === "function" && Function.prototype.toString.call(fn).includes("[native code]"); } catch (err) { return true; } } function hasOwnMethodHit(instance, methodName) { try { return Object.prototype.hasOwnProperty.call(instance, methodName); } catch (err) { return false; } } function webdriverFlagPresent() { if (typeof navigator === "undefined" || !navigator) return false; return navigator.webdriver === true; } const AUTOMATION_GLOBAL_MARKER_NAMES = "_phantom callPhantom __nightmare __webdriver_evaluate __selenium_evaluate __webdriver_script_function __driver_evaluate __fxdriver_evaluate __driver_unwrapped __selenium_unwrapped __fxdriver_unwrapped domAutomation domAutomationController".split(" "); function automationGlobalHitCount() { return automationGlobalHits().length; } function automationGlobalHits() { let names; try { names = Object.getOwnPropertyNames(globalThis); } catch (err) { names = []; } const nameSet = new Set(names); const hits = []; for (const marker of AUTOMATION_GLOBAL_MARKER_NAMES) { if (nameSet.has(marker)) hits.push(marker); } for (const name of names) { if (name.startsWith("cdc_") || name.startsWith("$cdc_")) hits.push(name); } return hits; } function automationGlobalNames() { return automationGlobalHits().slice(); } function syntheticEventTrusted() { if (typeof Event !== "function") { throw new Error("Event constructor unavailable"); } return new Event("probe").isTrusted === true; } const ENGINE_API_MARKERS = [ { engine: "blink", test: () => typeof window === "object" && "chrome" in window && typeof window.chrome === "object" }, { engine: "gecko", test: () => typeof CSS === "object" && CSS && typeof CSS.supports === "function" && CSS.supports("-moz-appearance", "none") }, { engine: "webkit", test: () => typeof safari === "object" && safari !== null } ]; function claimedEngineFromUa(ua) { if (typeof ua !== "string" || ua.length === 0) return "unknown"; if (ua.includes("Firefox/")) return "gecko"; if (ua.includes("Chrome/") || ua.includes("Chromium/") || ua.includes("Edg/") || ua.includes("OPR/")) { return "blink"; } if (ua.includes("Safari/")) return "webkit"; return "unknown"; } function engineUaMismatch() { if (typeof window !== "object") { throw new Error("window unavailable"); } const ua = typeof navigator === "object" && navigator ? navigator.userAgent : undefined; const claimed = claimedEngineFromUa(ua); const votes = { blink: 0, gecko: 0, webkit: 0 }; for (const marker of ENGINE_API_MARKERS) { try { if (marker.test()) votes[marker.engine] += 1; } catch (err) {} } let apiEngine = "unknown"; let topVotes = 0; let tied = false; for (const engine of Object.keys(votes)) { if (votes[engine] > topVotes) { topVotes = votes[engine]; apiEngine = engine; tied = false; } else if (votes[engine] === topVotes && topVotes > 0) { tied = true; } } if (tied || topVotes === 0) apiEngine = "unknown"; if (claimed === "unknown" || apiEngine === "unknown") return false; return claimed !== apiEngine; } function claimedEngine() { const ua = typeof navigator === "object" && navigator ? navigator.userAgent : undefined; const engine = claimedEngineFromUa(ua); if (engine === "unknown") { throw new Error("engine could not be determined from UA"); } return engine; } function engineApiMarkersPresent() { if (typeof window !== "object") { throw new Error("window unavailable"); } const hits = []; for (const marker of ENGINE_API_MARKERS) { try { if (marker.test()) hits.push(marker.engine); } catch (err) {} } return hits; } function nativeCodeTamperCount() { return tamperedNativeHits().length; } function tamperedNativeHits() { const candidates = [ { label: "hasOwnProperty", fn: Object.prototype.hasOwnProperty }, { label: "arrayPush", fn: Array.prototype.push }, { label: "arraySlice", fn: Array.prototype.slice }, { label: "functionBind", fn: Function.prototype.bind }, { label: "jsonStringify", fn: JSON.stringify }, { label: "objectKeys", fn: Object.keys }, { label: "dateGetTime", fn: Date.prototype.getTime } ]; const hits = []; for (const {label, fn} of candidates) { try { if (!isNativeCode(fn)) hits.push(label); } catch (err) {} } return hits; } function tamperedNativeNames() { return tamperedNativeHits().slice(); } function overriddenPrototypeMethodCount() { return overriddenMethodHits().length; } function overriddenMethodHits() { const hits = []; if (hasOwnMethodHit([], "push")) hits.push("push"); if (hasOwnMethodHit({}, "hasOwnProperty")) hits.push("hasOwnProperty"); if (hasOwnMethodHit(function() {}, "bind")) hits.push("bind"); if (hasOwnMethodHit(new Date, "getTime")) hits.push("getTime"); if (typeof Document === "function" && typeof document === "object" && document && document instanceof Document) { if (hasOwnMethodHit(document, "createElement")) hits.push("createElement"); } return hits; } function overriddenMethodNames() { return overriddenMethodHits().slice(); } const NAVIGATOR_ACCESSOR_NAMES = "hardwareConcurrency userAgent platform language".split(" "); function navigatorAccessorOverriddenCount() { return navigatorOverriddenHits().length; } function navigatorOverriddenHits() { if (typeof navigator === "undefined" || !navigator) { throw new Error("navigator unavailable"); } const hits = []; for (const name of NAVIGATOR_ACCESSOR_NAMES) { try { if (Object.prototype.hasOwnProperty.call(navigator, name)) hits.push(name); } catch (err) {} } return hits; } function navigatorOverriddenNames() { return navigatorOverriddenHits().slice(); } function frozenNativeObjectCount() { return frozenNativeHits().length; } function frozenNativeCandidates() { const candidates = []; try { if (typeof navigator === "object" && navigator) candidates.push({ label: "navigator", obj: navigator }); } catch (err) {} try { if (typeof navigator === "object" && navigator && navigator.plugins) { candidates.push({ label: "navigatorPlugins", obj: navigator.plugins }); } } catch (err) {} try { if (typeof navigator === "object" && navigator && navigator.mimeTypes) { candidates.push({ label: "navigatorMimeTypes", obj: navigator.mimeTypes }); } } catch (err) {} try { if (typeof screen === "object" && screen) candidates.push({ label: "screen", obj: screen }); } catch (err) {} try { if (typeof Navigator === "function" && Navigator.prototype) { candidates.push({ label: "navigatorPrototype", obj: Navigator.prototype }); } } catch (err) {} return candidates; } function frozenNativeHits() { const hits = []; for (const {label, obj} of frozenNativeCandidates()) { try { if (Object.isFrozen(obj) || Object.isSealed(obj) || !Object.isExtensible(obj)) { hits.push(label); } } catch (err) {} } return hits; } function frozenNativeNames() { return frozenNativeHits().slice(); } function evalSourceLength() { if (typeof eval !== "function") { throw new Error("eval unavailable"); } return eval.toString().length; } const SOFTWARE_RENDERER_KEYWORDS = "swiftshader llvmpipe softpipe mesa virgl vmware virtualbox parallels basic microsoft".split(" "); let webglProbeCache = null; let webglProbeCacheDocument = Symbol("no-webgl-probe-yet"); function computeWebglProbe() { if (typeof document === "undefined" || !document) { return { documentAvailable: false }; } const canvas = document.createElement("canvas"); let gl = null; try { gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); } catch (err) { gl = null; } if (!gl) { return { documentAvailable: true, contextAvailable: false }; } try { let maxTextureSize; try { maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE); } catch (err) { maxTextureSize = undefined; } let extensionCount; try { const list = gl.getSupportedExtensions(); extensionCount = Array.isArray(list) ? list.length : undefined; } catch (err) { extensionCount = undefined; } let ext = null; try { ext = gl.getExtension("WEBGL_debug_renderer_info"); } catch (err) { ext = null; } if (!ext) { return { documentAvailable: true, contextAvailable: true, debugExtAvailable: false, maxTextureSize, extensionCount }; } let renderer; let vendor; let readError = false; try { renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL); vendor = gl.getParameter(ext.UNMASKED_VENDOR_WEBGL); } catch (err) { readError = true; } return { documentAvailable: true, contextAvailable: true, debugExtAvailable: true, readError, renderer, vendor, maxTextureSize, extensionCount }; } finally { try { const loseCtx = gl.getExtension("WEBGL_lose_context"); if (loseCtx) loseCtx.loseContext(); } catch (err) {} } } function getWebglProbe() { const currentDocument = typeof document === "undefined" ? undefined : document; if (webglProbeCacheDocument !== currentDocument) { webglProbeCache = computeWebglProbe(); webglProbeCacheDocument = currentDocument; } return webglProbeCache; } function gpuRendererClass() { const probe = getWebglProbe(); if (!probe.documentAvailable) { throw new Error("document unavailable"); } if (!probe.contextAvailable || !probe.debugExtAvailable) { return "unavailable"; } if (probe.readError) { return "unknown"; } if (typeof probe.renderer !== "string" || probe.renderer.length === 0) { return "unknown"; } const lowered = probe.renderer.toLowerCase(); for (const keyword of SOFTWARE_RENDERER_KEYWORDS) { if (lowered.includes(keyword)) { return "software"; } } return "hardware"; } function hardwareConcurrencyImplausible() { if (typeof navigator === "undefined" || !navigator || typeof navigator.hardwareConcurrency !== "number") { throw new Error("hardwareConcurrency unavailable"); } return navigator.hardwareConcurrency <= 1; } function screenGeometryImplausible() { if (typeof screen === "undefined" || !screen) { throw new Error("screen unavailable"); } const reservesNoChrome = screen.availWidth === screen.width && screen.availHeight === screen.height; const shallowColor = typeof screen.colorDepth === "number" && screen.colorDepth < 24; return reservesNoChrome || shallowColor; } function physicalCapabilityMissingCount() { return physicalCapabilityMissingHits().length; } function physicalCapabilityMissingHits() { if (typeof window !== "object") { throw new Error("window unavailable"); } const hits = []; try { if (typeof navigator !== "object" || !navigator || typeof navigator.maxTouchPoints !== "number") { hits.push("maxTouchPoints"); } } catch (err) {} try { if (typeof navigator !== "object" || !navigator || typeof navigator.mediaDevices !== "object" || !navigator.mediaDevices) { hits.push("mediaDevices"); } } catch (err) {} try { if (typeof navigator !== "object" || !navigator || !navigator.plugins || navigator.plugins.length === 0) { hits.push("plugins"); } } catch (err) {} try { if (typeof screen !== "object" || !screen || typeof screen.orientation === "undefined") { hits.push("screenOrientation"); } } catch (err) {} try { if (typeof matchMedia !== "function" || !matchMedia("(pointer: fine)").matches) { hits.push("pointerFine"); } } catch (err) {} return hits; } function physicalCapabilityMissingNames() { return physicalCapabilityMissingHits().slice(); } function sweepBait(tokens) { if (typeof document === "undefined" || !document || !document.body) { throw new Error("document unavailable"); } const container = document.createElement("div"); container.style.cssText = "position:absolute;top:-9999px;left:-9999px;width:1px;height:1px;overflow:visible;pointer-events:none;"; const nodes = []; for (const token of tokens) { const el = document.createElement("div"); el.className = token; el.style.cssText = "width:2px;height:2px;"; container.appendChild(el); nodes.push(el); } const collapsed = []; try { document.body.appendChild(container); for (const el of nodes) { const isCollapsed = el.offsetParent === null || el.offsetWidth === 0 && el.offsetHeight === 0; if (isCollapsed) collapsed.push(el.className); } } finally { if (container.parentNode) container.parentNode.removeChild(container); } return collapsed; } const baitSweepCache = new Map; function getBaitSweep(tokens) { const currentDocument = typeof document === "undefined" ? undefined : document; const cached = baitSweepCache.get(tokens); if (cached && cached.document === currentDocument) { return cached.result; } const result = sweepBait(tokens); baitSweepCache.set(tokens, { document: currentDocument, result }); return result; } const AD_BAIT_TOKENS = "ad-banner ad-container ad-slot banner-ad text-ad sponsored-ad google-ad ad-unit".split(" "); function adBaitBlockedCount() { return getBaitSweep(AD_BAIT_TOKENS).length; } function adBaitBlockedNames() { return getBaitSweep(AD_BAIT_TOKENS).slice(); } const TRACKER_BAIT_TOKENS = "tracking-pixel analytics-pixel beacon-pixel pixel-tracker user-tracker event-pixel telemetry-pixel stats-pixel".split(" "); function trackerBaitBlockedCount() { return getBaitSweep(TRACKER_BAIT_TOKENS).length; } function trackerBaitBlockedNames() { return getBaitSweep(TRACKER_BAIT_TOKENS).slice(); } let canvasReadbackProbeCache = null; let canvasReadbackProbeCacheDocument = Symbol("no-canvas-readback-probe-yet"); function computeCanvasReadbackProbe() { if (typeof document === "undefined" || !document) { return { documentAvailable: false }; } const canvas = document.createElement("canvas"); canvas.width = 16; canvas.height = 16; const ctx = canvas.getContext("2d"); if (!ctx) { return { documentAvailable: true, contextAvailable: false }; } ctx.fillStyle = "#ff0000"; ctx.fillRect(0, 0, 8, 8); ctx.fillStyle = "#00ff00"; ctx.fillRect(8, 0, 8, 8); ctx.fillStyle = "#0000ff"; ctx.beginPath(); ctx.arc(8, 12, 4, 0, Math.PI * 2); ctx.fill(); const first = ctx.getImageData(0, 0, 16, 16).data; const second = ctx.getImageData(0, 0, 16, 16).data; let diffBytes; if (first.length !== second.length) { diffBytes = Math.max(first.length, second.length); } else { diffBytes = 0; for (let i = 0; i < first.length; i += 1) { if (first[i] !== second[i]) diffBytes += 1; } } return { documentAvailable: true, contextAvailable: true, diffBytes }; } function getCanvasReadbackProbe() { const currentDocument = typeof document === "undefined" ? undefined : document; if (canvasReadbackProbeCacheDocument !== currentDocument) { canvasReadbackProbeCache = computeCanvasReadbackProbe(); canvasReadbackProbeCacheDocument = currentDocument; } return canvasReadbackProbeCache; } function canvasReadbackUnstable() { const probe = getCanvasReadbackProbe(); if (!probe.documentAvailable) { throw new Error("document unavailable"); } if (!probe.contextAvailable) { throw new Error("2d context unavailable"); } return probe.diffBytes > 0; } function gpuRenderer() { const probe = getWebglProbe(); if (!probe.documentAvailable) { throw new Error("document unavailable"); } if (!probe.contextAvailable || !probe.debugExtAvailable || probe.readError) { throw new Error("gpu renderer unavailable"); } if (typeof probe.renderer !== "string" || probe.renderer.length === 0) { throw new Error("gpu renderer unavailable"); } return probe.renderer; } function gpuVendor() { const probe = getWebglProbe(); if (!probe.documentAvailable) { throw new Error("document unavailable"); } if (!probe.contextAvailable || !probe.debugExtAvailable || probe.readError) { throw new Error("gpu vendor unavailable"); } if (typeof probe.vendor !== "string" || probe.vendor.length === 0) { throw new Error("gpu vendor unavailable"); } return probe.vendor; } function webglMaxTextureSize() { const probe = getWebglProbe(); if (!probe.documentAvailable) { throw new Error("document unavailable"); } if (!probe.contextAvailable || typeof probe.maxTextureSize !== "number") { throw new Error("MAX_TEXTURE_SIZE unavailable"); } return probe.maxTextureSize; } function webglExtensionCount() { const probe = getWebglProbe(); if (!probe.documentAvailable) { throw new Error("document unavailable"); } if (!probe.contextAvailable || typeof probe.extensionCount !== "number") { throw new Error("extension list unavailable"); } return probe.extensionCount; } function hardwareConcurrency() { if (typeof navigator === "undefined" || !navigator || typeof navigator.hardwareConcurrency !== "number") { throw new Error("hardwareConcurrency unavailable"); } return navigator.hardwareConcurrency; } function deviceMemory() { if (typeof navigator === "undefined" || !navigator || typeof navigator.deviceMemory !== "number") { throw new Error("deviceMemory unavailable"); } return navigator.deviceMemory; } function screenWidth() { if (typeof screen === "undefined" || !screen || typeof screen.width !== "number") { throw new Error("screen unavailable"); } return screen.width; } function screenHeight() { if (typeof screen === "undefined" || !screen || typeof screen.height !== "number") { throw new Error("screen unavailable"); } return screen.height; } function screenAvailWidth() { if (typeof screen === "undefined" || !screen || typeof screen.availWidth !== "number") { throw new Error("screen unavailable"); } return screen.availWidth; } function screenAvailHeight() { if (typeof screen === "undefined" || !screen || typeof screen.availHeight !== "number") { throw new Error("screen unavailable"); } return screen.availHeight; } function screenColorDepth() { if (typeof screen === "undefined" || !screen || typeof screen.colorDepth !== "number") { throw new Error("screen unavailable"); } return screen.colorDepth; } function devicePixelRatio() { if (typeof window === "undefined" || !window || typeof window.devicePixelRatio !== "number") { throw new Error("window unavailable"); } return window.devicePixelRatio; } function maxTouchPoints() { if (typeof navigator === "undefined" || !navigator || typeof navigator.maxTouchPoints !== "number") { throw new Error("maxTouchPoints unavailable"); } return navigator.maxTouchPoints; } function pluginCount() { if (typeof navigator === "undefined" || !navigator || !navigator.plugins || typeof navigator.plugins.length !== "number") { throw new Error("navigator.plugins unavailable"); } return navigator.plugins.length; } function navigatorUserAgent() { if (typeof navigator === "undefined" || !navigator || typeof navigator.userAgent !== "string") { throw new Error("navigator.userAgent unavailable"); } return navigator.userAgent; } function navigatorPlatform() { if (typeof navigator === "undefined" || !navigator || typeof navigator.platform !== "string") { throw new Error("navigator.platform unavailable"); } return navigator.platform; } function navigatorLanguages() { if (typeof navigator === "undefined" || !navigator || !Array.isArray(navigator.languages)) { throw new Error("navigator.languages unavailable"); } return navigator.languages.map(lang => String(lang)); } function canvasReadbackDiffBytes() { const probe = getCanvasReadbackProbe(); if (!probe.documentAvailable) { throw new Error("document unavailable"); } if (!probe.contextAvailable) { throw new Error("2d context unavailable"); } return probe.diffBytes; } const signals = [ [ "seedTrivial", () => true ], [ "webdriverFlagPresent", webdriverFlagPresent ], [ "automationGlobalHitCount", automationGlobalHitCount ], [ "syntheticEventTrusted", syntheticEventTrusted ], [ "nativeCodeTamperCount", nativeCodeTamperCount ], [ "overriddenPrototypeMethodCount", overriddenPrototypeMethodCount ], [ "navigatorAccessorOverriddenCount", navigatorAccessorOverriddenCount ], [ "gpuRendererClass", gpuRendererClass ], [ "hardwareConcurrencyImplausible", hardwareConcurrencyImplausible ], [ "screenGeometryImplausible", screenGeometryImplausible ], [ "adBaitBlockedCount", adBaitBlockedCount ], [ "trackerBaitBlockedCount", trackerBaitBlockedCount ], [ "canvasReadbackUnstable", canvasReadbackUnstable ], [ "engineUaMismatch", engineUaMismatch ], [ "frozenNativeObjectCount", frozenNativeObjectCount ], [ "evalSourceLength", evalSourceLength ], [ "physicalCapabilityMissingCount", physicalCapabilityMissingCount ], [ "gpuRenderer", gpuRenderer ], [ "gpuVendor", gpuVendor ], [ "webglMaxTextureSize", webglMaxTextureSize ], [ "webglExtensionCount", webglExtensionCount ], [ "hardwareConcurrency", hardwareConcurrency ], [ "deviceMemory", deviceMemory ], [ "screenWidth", screenWidth ], [ "screenHeight", screenHeight ], [ "screenAvailWidth", screenAvailWidth ], [ "screenAvailHeight", screenAvailHeight ], [ "screenColorDepth", screenColorDepth ], [ "devicePixelRatio", devicePixelRatio ], [ "maxTouchPoints", maxTouchPoints ], [ "pluginCount", pluginCount ], [ "automationGlobalNames", automationGlobalNames ], [ "tamperedNativeNames", tamperedNativeNames ], [ "overriddenMethodNames", overriddenMethodNames ], [ "navigatorOverriddenNames", navigatorOverriddenNames ], [ "frozenNativeNames", frozenNativeNames ], [ "adBaitBlockedNames", adBaitBlockedNames ], [ "trackerBaitBlockedNames", trackerBaitBlockedNames ], [ "physicalCapabilityMissingNames", physicalCapabilityMissingNames ], [ "engineApiMarkersPresent", engineApiMarkersPresent ], [ "claimedEngine", claimedEngine ], [ "navigatorUserAgent", navigatorUserAgent ], [ "navigatorPlatform", navigatorPlatform ], [ "navigatorLanguages", navigatorLanguages ], [ "canvasReadbackDiffBytes", canvasReadbackDiffBytes ] ]; return runSignals(signals).then(function(results) { return { schema, payload_id, signals: results }; }); })();