{"id":7083,"date":"2026-07-21T06:44:28","date_gmt":"2026-07-21T06:44:28","guid":{"rendered":"https:\/\/assistyu.com\/?page_id=7083"},"modified":"2026-10-11T00:49:31","modified_gmt":"2026-10-11T00:49:31","slug":"network-security-scan","status":"publish","type":"page","link":"https:\/\/assistyu.com\/fr\/cybersecurity-tools\/network-security-scan\/","title":{"rendered":"Network Security Scan"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-page\" data-elementor-id=\"7083\" class=\"elementor elementor-7083\">\n\t\t\t\t<div class=\"elementor-element elementor-element-c18dd00 e-con e-atomic-element e-flexbox-base e-default-div e-da084ef \" data-id=\"c18dd00\" data-element_type=\"e-flexbox\" data-e-type=\"e-flexbox\" data-interaction-id=\"c18dd00\">\n    \t\t<div class=\"elementor-element elementor-element-a8a40e2 elementor-widget elementor-widget-html\" data-id=\"a8a40e2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"html.default\">\n\t\t\t\t\t<!DOCTYPE html>\r\n<html lang=\"en\">\r\n\r\n<head>\r\n<meta charset=\"UTF-8\" \/>\r\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" \/>\r\n<title>AssistYU \u2014 Network Scan<\/title>\r\n<link rel=\"preconnect\" href=\"https:\/\/fonts.googleapis.com\" \/>\r\n<link rel=\"preconnect\" href=\"https:\/\/fonts.gstatic.com\" crossorigin \/>\r\n<link href=\"https:\/\/fonts.googleapis.com\/css2?family=Space+Grotesk:wght@400;500;600;700&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500;600;700&display=swap\" rel=\"stylesheet\" \/>\r\n<!-- Leaflet: precise interactive map + accuracy circle -->\r\n<link rel=\"stylesheet\" href=\"https:\/\/unpkg.com\/leaflet@1.9.4\/dist\/leaflet.css\" \/>\r\n<style>\r\n* { margin: 0; padding: 0; box-sizing: border-box; }\r\n:root {\r\n  --ayu-bg-deep: #060815;\r\n  --ayu-bg-navy: #090d24;\r\n  --ayu-bg-navy-2: #0b1130;\r\n  --ayu-text-primary: #ffffff;\r\n  --ayu-text-secondary: #d4daff;\r\n  --ayu-text-tertiary: #bcc4f0;\r\n  --glass-border: rgba(79, 110, 247, 0.15);\r\n  --border: rgba(79, 110, 247, 0.18);\r\n  --border-strong: rgba(79, 110, 247, 0.30);\r\n  --cyan: #4f6ef7;\r\n  --blue: #4f6ef7;\r\n  --violet: #8a6bff;\r\n  --danger: #ff3d68;\r\n  --safe: #22e6a8;\r\n  --amber: #ffb84d;\r\n  --font-display: 'Space Grotesk', sans-serif;\r\n  --font-body: 'Inter', sans-serif;\r\n  --font-mono: 'JetBrains Mono', monospace;\r\n  --surface: rgba(9, 13, 36, 0.55);\r\n  --surface-3: rgba(6, 8, 21, 0.40);\r\n  --hairline: rgba(79, 110, 247, 0.10);\r\n  --radius: 18px;\r\n  --shadow-md: 0 10px 30px rgba(0, 0, 0, 0.35);\r\n}\r\nhtml, body {\r\n  min-height: 100vh;\r\n  background: #060815;\r\n  color: var(--ayu-text-primary);\r\n  font-family: var(--font-body);\r\n  -webkit-font-smoothing: antialiased;\r\n  -moz-osx-font-smoothing: grayscale;\r\n  text-rendering: optimizeLegibility;\r\n  position: relative;\r\n  isolation: isolate;\r\n  overflow-x: hidden;\r\n}\r\n.page-bg { position: absolute; inset: 0; z-index: 0; pointer-events: none; background: linear-gradient(180deg, #060815 0%, #060815 20%, #090d24 50%, #060815 80%, #060815 100%); }\r\n.bg-layers { position: absolute; inset: 0; z-index: 0; pointer-events: none; mask-image: linear-gradient(to bottom, transparent 0%, black 20%, black 80%, transparent 100%); -webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 20%, black 80%, transparent 100%); }\r\n.ayu-bg-world { position: fixed; inset: 0; background-image: url('https:\/\/assistyu.com\/wp-content\/uploads\/2026\/07\/scan-network-scaled.jpeg?w=1600&q=80'); background-size: cover; background-position: center; background-attachment: fixed; opacity: 0.10; mask-image: radial-gradient(ellipse 80% 70% at 50% 40%, black 20%, transparent 75%); -webkit-mask-image: radial-gradient(ellipse 80% 70% at 50% 40%, black 20%, transparent 75%); }\r\n.ayu-bg-dots { position: absolute; inset: 0; background-image: radial-gradient(circle at 1px 1px, rgba(79, 110, 247, 0.08) 1px, transparent 1px); background-size: 48px 48px; mask-image: radial-gradient(ellipse 60% 50% at 50% 50%, black 20%, transparent 70%); -webkit-mask-image: radial-gradient(ellipse 60% 50% at 50% 50%, black 20%, transparent 70%); }\r\n.ayu-bg-glow { position: absolute; inset: 0; background: radial-gradient(ellipse 50% 40% at 15% 15%, rgba(79, 110, 247, 0.12), transparent 55%), radial-gradient(ellipse 35% 30% at 50% 50%, rgba(236, 72, 153, 0.04), transparent 60%), radial-gradient(ellipse 50% 40% at 70% 20%, rgba(34, 211, 238, 0.06), transparent 50%); }\r\n.ayu-bg-orb-1 { position: absolute; width: 400px; height: 400px; top: 10%; left: 5%; border-radius: 50%; background: radial-gradient(circle, rgba(79, 110, 247, 0.06) 0%, transparent 70%); animation: ayuOrbFloat1 20s ease-in-out infinite; }\r\n.ayu-bg-orb-2 { position: absolute; width: 300px; height: 300px; bottom: 15%; right: 10%; border-radius: 50%; background: radial-gradient(circle, rgba(139, 92, 246, 0.06) 0%, transparent 70%); animation: ayuOrbFloat2 25s ease-in-out infinite; }\r\n@keyframes ayuOrbFloat1 { 0%,100%{transform:translate(0,0) scale(1);} 33%{transform:translate(30px,-20px) scale(1.05);} 66%{transform:translate(-15px,15px) scale(0.95);} }\r\n@keyframes ayuOrbFloat2 { 0%,100%{transform:translate(0,0) scale(1);} 33%{transform:translate(-20px,25px) scale(1.08);} 66%{transform:translate(25px,-10px) scale(0.92);} }\r\n.ayu-content-overlay { position: relative; z-index: 1; }\r\na { color: inherit; text-decoration: none; }\r\nbutton { font-family: inherit; cursor: pointer; }\r\n::selection { background: var(--cyan); color: #04060d; }\r\nhtml { scroll-behavior: smooth; }\r\n@media(prefers-reduced-motion:reduce) { html { scroll-behavior: auto; } }\r\na:focus-visible, button:focus-visible, .swi input:focus-visible+.sws, .map-click:focus-visible, .card:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; border-radius: 8px; }\r\n\r\nmain { max-width: 85%; margin: 0 auto; padding: 130px 0 48px; position: relative; z-index: 1; }\r\n\r\n#start-view { display: flex; flex-direction: column; align-items: center; justify-content: center; min-height: calc(80vh - 130px); text-align: center; animation: fadeUp .6s cubic-bezier(.2,.8,.2,1); }\r\n@keyframes fadeUp { from{opacity:0;transform:translateY(18px);} to{opacity:1;transform:none;} }\r\n.start-shield { position: relative; width: 80px; height: 80px; margin-bottom: 28px; }\r\n.start-shield svg { width: 80px; height: 80px; color: var(--cyan); filter: drop-shadow(0 0 24px rgba(79,110,247,0.40)); }\r\n.start-shield::after { content: ''; position: absolute; inset: -12px; border-radius: 50%; background: radial-gradient(circle, rgba(79,110,247,0.10), transparent 70%); animation: pulse 2.5s ease-in-out infinite; }\r\n@keyframes pulse { 0%,100%{transform:scale(1);opacity:.6;} 50%{transform:scale(1.15);opacity:1;} }\r\n.start-title { font-family: var(--font-display); font-weight: 700; font-size: clamp(28px,5vw,48px); color: var(--ayu-text-primary); letter-spacing: -0.03em; line-height: 1.15; margin-bottom: 12px; }\r\n.start-title span { color: var(--cyan); }\r\n.start-sub { font-family: var(--font-body); font-size: clamp(14px,1.5vw,18px); color: var(--ayu-text-secondary); line-height: 1.6; max-width: 520px; margin-bottom: 36px; }\r\n.start-cta { display: inline-flex; align-items: center; gap: 12px; padding: 16px 36px; border-radius: 14px; cursor: pointer; font-family: var(--font-display); font-weight: 600; font-size: 16px; color: var(--ayu-text-primary); letter-spacing: 0.2px; background: linear-gradient(135deg, rgba(79,110,247,0.20), rgba(138,107,255,0.16)); border: 1px solid rgba(79,110,247,0.40); box-shadow: 0 4px 24px rgba(79,110,247,0.20), 0 0 60px rgba(79,110,247,0.06); transition: all .3s cubic-bezier(.2,.8,.2,1); position: relative; overflow: hidden; }\r\n.start-cta::before { content:''; position:absolute; inset:0; border-radius:14px; background: linear-gradient(135deg, rgba(255,255,255,0.05), transparent); pointer-events:none; }\r\n.start-cta svg { width:20px; height:20px; color: var(--cyan); transition: transform .3s; }\r\n.start-cta:hover { transform: translateY(-3px); box-shadow: 0 8px 36px rgba(79,110,247,0.30), 0 0 80px rgba(79,110,247,0.10); border-color: rgba(79,110,247,0.60); background: linear-gradient(135deg, rgba(79,110,247,0.28), rgba(138,107,255,0.22)); }\r\n.start-cta:hover svg { transform: translateX(3px); }\r\n.start-cta:active { transform: translateY(-1px); box-shadow: 0 4px 20px rgba(79,110,247,0.22); }\r\n.start-features { display: flex; gap: 24px; margin-top: 40px; flex-wrap: wrap; justify-content: center; }\r\n.start-feat { display: flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.5px; color: var(--ayu-text-tertiary); text-transform: uppercase; }\r\n.start-feat-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--cyan); box-shadow: 0 0 8px rgba(79,110,247,0.5); }\r\n\r\n.telemetry { display: flex; flex-wrap: wrap; gap: 16px; align-items: center; justify-content: space-between; margin: 24px 0 0; width: 100%; background: linear-gradient(135deg, rgba(9,13,36,.6) 0%, rgba(6,8,21,.7) 100%); border: 1px solid var(--border-strong); border-radius: var(--radius); padding: 18px 22px; box-shadow: var(--shadow-md); }\r\n.telemetry-left { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }\r\n.status-pill { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: 11px; letter-spacing: .5px; color: var(--ayu-text-primary); padding: 8px 14px; border-radius: 999px; background: rgba(6,8,21,.7); border: 1px solid var(--border); white-space: nowrap; transition: border-color .2s; }\r\n.status-pill:hover { border-color: rgba(34,211,238,.3); }\r\n.status-pill .dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }\r\n.status-pill .dot.online { background: var(--safe); box-shadow: 0 0 10px var(--safe); animation: lp 1.8s ease-in-out infinite; }\r\n.status-pill .lbl { color: var(--ayu-text-secondary); }\r\n.status-pill .val { color: #fff; font-weight: 600; }\r\n.net-activity { display: flex; align-items: center; gap: 9px; padding: 7px 14px; border-radius: 999px; background: rgba(6,8,21,.7); border: 1px solid var(--border); }\r\n.net-activity .net-lbl { font-family: var(--font-mono); font-size: 9px; letter-spacing: 1px; color: var(--ayu-text-secondary); text-transform: uppercase; }\r\n.net-activity svg { display: block; }\r\n.last-update { font-family: var(--font-mono); font-size: 11px; color: var(--ayu-text-secondary); white-space: nowrap; }\r\n.last-update b { color: #fff; }\r\n@keyframes lp { 0%,100%{opacity:1;} 50%{opacity:.4;} }\r\n\r\n.hero-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 16px; margin-top: 20px; width: 100%; }\r\n@media (max-width: 992px) { .hero-stats { grid-template-columns: repeat(2, 1fr); } }\r\n@media (max-width: 480px) { .hero-stats { grid-template-columns: 1fr; } }\r\n.stat-card { background: var(--surface); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px); border: 1px solid var(--border-strong); border-radius: var(--radius); padding: 20px 18px; position: relative; overflow: hidden; box-shadow: var(--shadow-md); transition: transform .35s cubic-bezier(.2,.8,.2,1), border-color .35s cubic-bezier(.2,.8,.2,1); text-align: left; }\r\n.stat-card::before { content:''; position:absolute; inset:0; background: radial-gradient(120% 140% at 15% 0%, rgba(79,110,247,.08), transparent 60%); pointer-events:none; }\r\n.stat-card:hover { transform: translateY(-4px); border-color: rgba(79,110,247,.45); }\r\n.stat-card .s-ico { width: 24px; height: 24px; color: #fff; opacity: .9; margin-bottom: 10px; flex-shrink: 0; }\r\n.stat-card .s-ico svg { width: 24px; height: 24px; display: block; }\r\n.stat-card .s-val { font-family: var(--font-display); font-weight: 700; font-size: clamp(20px, 2.4vw, 28px); letter-spacing: -.02em; line-height: 1; color: #fff; }\r\n.stat-card .s-val .unit { font-size: .5em; color: var(--ayu-text-secondary); margin-left: 2px; }\r\n.stat-card .s-label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 1px; text-transform: uppercase; color: var(--ayu-text-secondary); margin-top: 10px; }\r\n.stat-card .s-trend { position: absolute; top: 16px; right: 16px; font-family: var(--font-mono); font-size: 10px; color: var(--safe); }\r\n\r\n.panel { background: var(--surface); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); border: 1px solid var(--border-strong); border-radius: var(--radius); box-shadow: var(--shadow-md); position: relative; overflow: hidden; width: 100%; margin-top: 32px; }\r\n.panel::before { content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; background: radial-gradient(120% 150% at 20% 20%, rgba(79, 110, 247, 0.05), transparent 65%); }\r\n.panel > * { position: relative; z-index: 1; }\r\n.panel-pad { padding: clamp(18px, 2.2vw, 26px); }\r\n.desktop-only { display: block; }\r\n.mobile-only { display: none; }\r\n@media (max-width: 600px) { .desktop-only { display: none !important; } .mobile-only { display: block; } }\r\n\r\n#scan-stage { display: none; margin-top: 28px; text-align: center; }\r\n#scan-stage .eyebrow { text-align: center; font-size: 12px; letter-spacing: 1.5px; color: var(--ayu-text-tertiary); text-transform: uppercase; font-weight: 500; }\r\n#scan-stage .eyebrow span { color: var(--cyan); }\r\n#scan-stage .hl { display: block; font-family: var(--font-display); font-size: clamp(24px,4vw,42px); font-weight: 700; line-height: 1.15; margin-top: 8px; color: var(--ayu-text-primary); text-align: center; }\r\n#scan-stage .sw-t { transition: color .4s; }\r\n#scan-stage .sw-t.scanning { color: var(--cyan); text-shadow: 0 0 30px rgba(79,110,247,0.4); }\r\n#scan-stage .sw-t.exposed { color: var(--danger); text-shadow: 0 0 30px rgba(255,61,104,0.4); }\r\n#scan-stage .sw-t.protected { color: var(--safe); text-shadow: 0 0 30px rgba(34,230,168,0.4); }\r\n.scan-grid { margin-top: 12px; display: flex; flex-direction: column; align-items: center; gap: 12px; width: 100%; max-width: 700px; margin-left: auto; margin-right: auto; }\r\n.radar-sec { display: flex; flex-direction: column; align-items: center; margin-bottom: 8px; }\r\n.radar-box { position: relative; width: min(340px,55vw); aspect-ratio: 1; }\r\n#radarCanvas { width: 100%; height: 100%; display: block; }\r\n.rl { margin-top: 12px; font-family: var(--font-mono); font-size: 10px; letter-spacing: 2px; color: var(--ayu-text-tertiary); text-transform: uppercase; }\r\n.rl .live { color: var(--cyan); animation: lp 1.5s ease-in-out infinite; }\r\n.ensec { width: 100%; max-width: min(340px,55vw); margin: 0 auto; display: flex; flex-direction: column; align-items: center; gap: 10px; }\r\n.ensec .enb { width: 100%; height: 6px; border-radius: 99px; background: rgba(79,110,247,0.10); overflow: hidden; position: relative; }\r\n.ensec .enbf { height: 100%; width: 0%; border-radius: 99px; background: linear-gradient(90deg, var(--cyan), var(--blue), var(--violet)); transition: width .4s; box-shadow: 0 0 16px rgba(79,110,247,0.5); }\r\n.ensec .enp { font-family: var(--font-mono); font-size: 13px; font-weight: 600; color: var(--ayu-text-primary); letter-spacing: 1px; }\r\n.ensec .enp .pct { color: var(--cyan); }\r\n.ensec .en-status { font-family: var(--font-body); font-size: 13px; color: var(--ayu-text-secondary); letter-spacing: 0.3px; min-height: 1.6em; transition: color .3s; }\r\n.ensec .en-status.done { color: var(--safe); font-weight: 500; }\r\n.ensec .en-status .highlight { color: var(--cyan); font-weight: 600; }\r\n.ensec .en-status .done-highlight { color: var(--safe); font-weight: 600; }\r\n\r\n#verdict-view { display: none; padding-top: 20px; }\r\n.verdict-header { margin-top: 40px; text-align: center; display: flex; flex-direction: column; align-items: center; gap: 12px; animation: fadeUp .6s cubic-bezier(.2,.8,.2,1); }\r\n.verdict-header .vb { width: 48px; height: 48px; border-radius: 13px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; backdrop-filter: blur(8px); transition: all .4s; }\r\n.verdict-header .vb.dg { background: rgba(255,61,104,0.12); border: 1px solid rgba(255,61,104,0.35); color: var(--danger); box-shadow: 0 0 22px rgba(255,61,104,0.20), inset 0 1px 0 rgba(255,255,255,0.05); }\r\n.verdict-header .vb.sg { background: rgba(34,230,168,0.12); border: 1px solid rgba(34,230,168,0.35); color: var(--safe); box-shadow: 0 0 22px rgba(34,230,168,0.20), inset 0 1px 0 rgba(255,255,255,0.05); }\r\n.verdict-header .vb svg { width: 22px; height: 22px; }\r\n.verdict-header .vht-title { font-family: var(--font-display); font-weight: 700; font-size: clamp(28px,5vw,48px); color: var(--ayu-text-primary); letter-spacing: -0.03em; line-height: 1.15; }\r\n.verdict-header .vht-desc { font-family: var(--font-display); font-weight: 700; font-size: clamp(36px,7vw,72px); color: var(--ayu-text-primary); letter-spacing: -0.02em; line-height: 1.1; max-width: 900px; margin-top: 2px; white-space: nowrap; }\r\n.verdict-header.exposed .vht-desc { color: var(--danger); text-shadow: 0 0 40px rgba(255,61,104,0.2); }\r\n.verdict-header.protected .vht-desc { color: var(--safe); text-shadow: 0 0 40px rgba(34,230,168,0.2); }\r\n.verdict-header .vht-subdesc { font-family: var(--font-body); font-size: clamp(14px,1.3vw,17px); color: var(--ayu-text-secondary); line-height: 1.6; max-width: 700px; margin-top: -2px; white-space: nowrap; }\r\n.protect-toggle-row { display: inline-flex; align-items: center; gap: 14px; margin-top: 6px; padding: 10px 22px; border-radius: 999px; background: linear-gradient(135deg, rgba(9,13,36,0.85), rgba(6,8,21,0.75)); border: 1px solid var(--border-strong); backdrop-filter: blur(12px); box-shadow: 0 4px 20px rgba(0,0,0,0.3); }\r\n.protect-toggle-row .toggle-label { font-family: var(--font-mono); font-size: 12px; font-weight: 600; color: var(--ayu-text-secondary); letter-spacing: 0.5px; text-transform: uppercase; transition: color .3s; }\r\n.protect-toggle-row .toggle-label.active { color: var(--safe); }\r\n.protect-toggle-row .swi { position: relative; width: 44px; height: 22px; flex-shrink: 0; }\r\n.protect-toggle-row .swi input { opacity: 0; width: 0; height: 0; }\r\n.protect-toggle-row .sws { position: absolute; inset: 0; background: #1c2440; border-radius: 999px; transition: all .3s; border: 1px solid var(--border-strong); cursor: pointer; }\r\n.protect-toggle-row .sws::before { content:''; position:absolute; width:14px; height:14px; left:3px; top:3px; background:#8a97bd; border-radius:50%; transition: all .3s; }\r\n.protect-toggle-row .swi input:checked+.sws { background: linear-gradient(90deg, var(--cyan), var(--safe)); border-color: transparent; box-shadow: 0 0 18px rgba(34,230,168,0.35); }\r\n.protect-toggle-row .swi input:checked+.sws::before { transform: translateX(22px); background: #04101a; }\r\n\r\n.hero-blocks { display: flex; gap: 20px; margin-top: 32px; align-items: stretch; animation: fadeUp .6s cubic-bezier(.2,.8,.2,1); }\r\n.hero-block { flex: 1; min-width: 0; border-radius: 20px; padding: 28px 30px; backdrop-filter: blur(16px); border: 1px solid var(--border-strong); background: linear-gradient(135deg, rgba(9,13,36,0.85), rgba(6,8,21,0.75)); box-shadow: 0 8px 40px rgba(0,0,0,0.35); display: flex; flex-direction: column; position: relative; overflow: hidden; transition: border-color .4s, box-shadow .4s, background .4s; }\r\n.hero-block::before { content:''; position:absolute; inset:0; border-radius:18px; pointer-events:none; background: repeating-linear-gradient(0deg, transparent, transparent 3px, rgba(255,255,255,0.010) 3px, rgba(255,255,255,0.010) 4px); }\r\n.hero-block.exposed { border-color: rgba(255,61,104,0.28); box-shadow: 0 8px 40px rgba(0,0,0,0.35), 0 0 60px rgba(255,61,104,0.10), inset 0 1px 0 rgba(255,255,255,0.04); }\r\n.hero-block.exposed::after { content:''; position:absolute; inset:0; border-radius:18px; background: radial-gradient(38% 55% at 20% 30%, rgba(255,61,104,0.18), transparent 70%), radial-gradient(45% 60% at 80% 70%, rgba(255,184,77,0.10), transparent 70%), radial-gradient(30% 45% at 55% 90%, rgba(255,61,104,0.08), transparent 70%); animation: vhSmoke 15s ease-in-out infinite alternate; pointer-events:none; }\r\n.hero-block.protected { border-color: rgba(34,230,168,0.28); box-shadow: 0 8px 40px rgba(0,0,0,0.35), 0 0 60px rgba(34,230,168,0.10), inset 0 1px 0 rgba(255,255,255,0.04); }\r\n.hero-block.protected::after { content:''; position:absolute; inset:0; border-radius:18px; background: radial-gradient(38% 55% at 20% 30%, rgba(34,230,168,0.18), transparent 70%), radial-gradient(45% 60% at 80% 70%, rgba(79,110,247,0.12), transparent 70%), radial-gradient(30% 45% at 55% 90%, rgba(34,230,168,0.08), transparent 70%); animation: vhSmoke 15s ease-in-out infinite alternate; pointer-events:none; }\r\n@keyframes vhSmoke { 0%{transform:translate(-2%,-1%) scale(1);} 50%{transform:translate(2%,2%) scale(1.08);} 100%{transform:translate(-1%,3%) scale(1.02);} }\r\n@media(prefers-reduced-motion:reduce) { .hero-block::after { animation:none; } }\r\n.hero-block>* { position: relative; z-index: 2; }\r\n.hero-left { align-items: center; text-align: center; justify-content: center; gap: 10px; }\r\n.hero-left .threats-label { font-family: var(--font-mono); font-size: 12px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; }\r\n.hero-left .threats-label.danger { color: var(--danger); }\r\n.hero-left .threats-label.safe { color: var(--safe); }\r\n.hero-left .threats-count { font-family: var(--font-display); font-size: clamp(48px,7vw,76px); font-weight: 700; color: var(--ayu-text-primary); letter-spacing: -0.02em; line-height: 1; margin: 4px 0 2px; }\r\n.hero-left .threats-count .num { color: var(--danger); }\r\n.hero-left .threats-count .num.safe { color: var(--safe); }\r\n.hero-left .threats-detail { font-family: var(--font-body); font-size: clamp(14px,1.3vw,17px); color: var(--ayu-text-secondary); line-height: 1.5; }\r\n.hero-left .threats-detail .highlight { color: var(--ayu-text-primary); font-weight: 500; }\r\n.hero-left .threats-badges { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; margin-top: auto; padding-top: 18px; border-top: 1px solid rgba(79,110,247,0.08); width: 100%; }\r\n.hero-left .badge { display: inline-flex; align-items: center; gap: 6px; padding: 6px 16px; border-radius: 999px; font-family: var(--font-mono); font-size: 11px; font-weight: 700; letter-spacing: 0.5px; border: 1px solid transparent; }\r\n.hero-left .badge.crit { background: rgba(255,61,104,0.12); color: var(--danger); border-color: rgba(255,61,104,0.30); }\r\n.hero-left .badge.warn { background: rgba(255,184,77,0.12); color: var(--amber); border-color: rgba(255,184,77,0.30); }\r\n.hero-left .badge .dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; box-shadow: 0 0 6px currentColor; }\r\n.hero-right { align-items: center; justify-content: center; padding: 24px 28px; display: flex; flex-direction: column; }\r\n.hero-right .gauge-wrap { display: flex; flex-direction: row; align-items: center; justify-content: center; gap: 40px; width: 100%; flex: 1; }\r\n.hero-right .gauge-ring { position: relative; width: 180px; height: 180px; flex-shrink: 0; filter: drop-shadow(0 4px 24px rgba(0,0,0,0.5)); }\r\n.hero-right .gauge-ring svg { width: 180px; height: 180px; transform: rotate(-90deg); overflow: visible; }\r\n.hero-right .gauge-ring circle { fill: none; stroke-linecap: round; }\r\n.hero-right .gauge-ring .g-bg { stroke: rgba(79,110,247,0.08); stroke-width: 8; }\r\n.hero-right .gauge-ring .g-fill { stroke-width: 10; transition: stroke-dashoffset 1.4s cubic-bezier(.4,0,.2,1), stroke .5s; filter: drop-shadow(0 0 16px rgba(0,0,0,0.3)); }\r\n.hero-right .gauge-ring .g-inner { position: absolute; inset: 10px; border-radius: 50%; background: radial-gradient(circle at 35% 35%, rgba(255,255,255,0.06), transparent 60%), linear-gradient(135deg, rgba(9,13,36,0.95), rgba(6,8,21,0.90)); border: 1px solid rgba(79,110,247,0.08); box-shadow: inset 0 2px 10px rgba(0,0,0,0.4), inset 0 -1px 4px rgba(255,255,255,0.03); }\r\n.hero-right .gauge-ring .g-num { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; font-family: var(--font-display); }\r\n.hero-right .gauge-ring .g-num-val { font-size: 48px; font-weight: 700; color: var(--ayu-text-primary); line-height: 1; letter-spacing: -0.02em; text-shadow: 0 0 30px rgba(79,110,247,0.15); }\r\n.hero-right .gauge-ring .g-num-of { font-size: 13px; font-weight: 500; color: var(--ayu-text-tertiary); letter-spacing: 1px; margin-top: 0px; opacity: 0.7; }\r\n.hero-right .gauge-info { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; min-width: 0; flex: 1; padding: 4px 0; text-align: left; }\r\n.hero-right .gauge-grade { font-family: var(--font-display); font-size: clamp(28px,3vw,38px); font-weight: 700; letter-spacing: 0.3px; line-height: 1.2; }\r\n.hero-right .gauge-grade .sub { font-family: var(--font-body); font-size: clamp(16px,1.5vw,20px); font-weight: 400; color: var(--ayu-text-secondary); display: block; margin-top: 4px; }\r\n.hero-right .gauge-tags { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-start; margin-top: 4px; }\r\n.hero-right .gauge-tags .tag { font-family: var(--font-mono); font-size: 11px; font-weight: 500; padding: 6px 16px; border-radius: 999px; background: rgba(79,110,247,0.06); border: 1px solid rgba(79,110,247,0.12); color: var(--ayu-text-secondary); letter-spacing: 0.3px; transition: all .2s; }\r\n.hero-right .gauge-tags .tag.danger { background: rgba(255,61,104,0.12); border-color: rgba(255,61,104,0.25); color: var(--danger); }\r\n.hero-right .gauge-tags .tag.safe { background: rgba(34,230,168,0.12); border-color: rgba(34,230,168,0.25); color: var(--safe); }\r\n.hero-right .gauge-tags .tag.warn { background: rgba(255,184,77,0.12); border-color: rgba(255,184,77,0.25); color: var(--amber); }\r\n@media(max-width:768px) { .hero-blocks { flex-direction: column; } .hero-block { padding: 24px 22px; } .hero-left .threats-count { font-size: clamp(38px,10vw,56px); } .hero-right .gauge-wrap { flex-direction: column; text-align: center; gap: 24px; } .hero-right .gauge-info { align-items: center; text-align: center; } .hero-right .gauge-tags { justify-content: center; } .hero-right .gauge-ring { width: 140px; height: 140px; } .hero-right .gauge-ring svg { width: 140px; height: 140px; } .hero-right .gauge-ring .g-num-val { font-size: 36px; } .verdict-header { margin-top: 30px; } .verdict-header .vht-title { font-size: clamp(26px,4vw,38px); } .verdict-header .vht-desc { font-size: clamp(28px,5vw,44px); white-space: normal; } .verdict-header .vht-subdesc { white-space: normal; } }\r\n@media(max-width:480px) { .hero-block { padding: 20px 16px; } .hero-left .threats-count { font-size: 34px; } .hero-right .gauge-ring { width: 120px; height: 120px; } .hero-right .gauge-ring svg { width: 120px; height: 120px; } .hero-right .gauge-ring .g-num-val { font-size: 30px; } .hero-right .gauge-ring .g-num-of { font-size: 10px; } .verdict-header .vht-desc { font-size: clamp(24px,4vw,36px); white-space: normal; } .verdict-header .vht-subdesc { display: none; } }\r\n\r\n.rsec { margin-top: 20px; }\r\n.slab { margin-top: 32px; margin-bottom: 14px; font-family: var(--font-mono); font-size: 10px; letter-spacing: 2px; color: var(--ayu-text-secondary); text-transform: uppercase; font-weight: 600; display: flex; align-items: center; gap: 8px; }\r\n.slab::after { content:''; flex:1; height:1px; background: linear-gradient(90deg, rgba(79,110,247,0.20), transparent); }\r\n.g2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }\r\n.g3 { display: grid; grid-template-columns: repeat(3,1fr); gap: 14px; }\r\n#gth { grid-template-columns: 1fr 1fr !important; }\r\n@media(max-width:900px) { .g3 { grid-template-columns: repeat(2,1fr); } #gth { grid-template-columns: 1fr !important; } }\r\n@media(max-width:640px) { .g2 { grid-template-columns: 1fr; } .g3 { grid-template-columns: 1fr; } }\r\n@media(min-width:1440px) { .g2 { grid-template-columns: repeat(3,1fr); } }\r\n.card { position: relative; border-radius: 14px; padding: 20px 22px; display: flex; align-items: flex-start; gap: 16px; overflow: hidden; transition: transform .3s cubic-bezier(.2,.8,.2,1), box-shadow .3s, border-color .3s, background .3s; opacity: 0; transform: translateY(8px); animation: ci .45s ease forwards; background: linear-gradient(135deg, rgba(9,13,36,0.80), rgba(6,8,21,0.70)); border: 1px solid rgba(79,110,247,0.10); box-shadow: 0 2px 14px rgba(0,0,0,0.35), inset 0 1px 0 rgba(255,255,255,0.03); will-change: transform; backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); }\r\n.card::after { content:''; position:absolute; inset:0; border-radius:14px; pointer-events:none; background: repeating-linear-gradient(0deg, transparent, transparent 3px, rgba(255,255,255,0.008) 3px, rgba(255,255,255,0.008) 4px); opacity:1; transition: opacity .3s; }\r\n.card:hover { border-color: rgba(79,110,247,0.22); box-shadow: 0 6px 28px rgba(0,0,0,0.45), inset 0 1px 0 rgba(255,255,255,0.05); transform: translateY(-2px); }\r\n.card.c-cyan { border-color: rgba(79,110,247,0.14); background: linear-gradient(135deg, rgba(9,13,36,0.82), rgba(6,8,21,0.74)), radial-gradient(120% 120% at 0% 0%, rgba(79,110,247,0.04), transparent 60%); }\r\n.card.c-cyan:hover { border-color: rgba(79,110,247,0.28); box-shadow: 0 6px 28px rgba(0,0,0,0.45), 0 0 24px rgba(79,110,247,0.06); }\r\n.card.c-danger { border-color: rgba(255,61,104,0.28); background: linear-gradient(135deg, rgba(38,12,22,0.82), rgba(16,8,14,0.75)), radial-gradient(120% 120% at 0% 0%, rgba(255,61,104,0.16), transparent 60%); box-shadow: 0 2px 16px rgba(0,0,0,0.4), 0 0 26px rgba(255,61,104,0.10); }\r\n.card.c-danger:hover { border-color: rgba(255,61,104,0.45); box-shadow: 0 6px 28px rgba(0,0,0,0.5), 0 0 32px rgba(255,61,104,0.16); }\r\n.card.c-warn { border-color: rgba(255,184,77,0.28); background: linear-gradient(135deg, rgba(36,26,10,0.82), rgba(16,14,8,0.75)), radial-gradient(120% 120% at 0% 0%, rgba(255,184,77,0.14), transparent 60%); box-shadow: 0 2px 16px rgba(0,0,0,0.4), 0 0 24px rgba(255,184,77,0.08); }\r\n.card.c-warn:hover { border-color: rgba(255,184,77,0.40); box-shadow: 0 6px 28px rgba(0,0,0,0.5), 0 0 30px rgba(255,184,77,0.14); }\r\n.card.c-safe { border-color: rgba(34,230,168,0.22); background: linear-gradient(135deg, rgba(10,32,26,0.78), rgba(8,20,18,0.7)), radial-gradient(120% 120% at 0% 0%, rgba(34,230,168,0.10), transparent 60%); box-shadow: 0 2px 16px rgba(0,0,0,0.4), 0 0 22px rgba(34,230,168,0.06); }\r\n.card.c-safe:hover { border-color: rgba(34,230,168,0.35); box-shadow: 0 6px 28px rgba(0,0,0,0.5), 0 0 28px rgba(34,230,168,0.12); }\r\n.card.prot { border-color: rgba(34,230,168,0.28) !important; background: linear-gradient(135deg, rgba(10,32,26,0.82), rgba(8,20,18,0.75)), radial-gradient(120% 120% at 0% 0%, rgba(34,230,168,0.14), transparent 60%) !important; box-shadow: 0 2px 16px rgba(0,0,0,0.4), 0 0 26px rgba(34,230,168,0.10) !important; }\r\n.card.prot .ci { background: rgba(34,230,168,0.12) !important; border-color: rgba(34,230,168,0.35) !important; color: var(--safe) !important; }\r\n.card.prot .cv { color: var(--safe) !important; background: rgba(34,230,168,0.10) !important; border-color: rgba(34,230,168,0.22) !important; }\r\n.card.prot .cs { color: rgba(34,230,168,0.7) !important; }\r\n@keyframes ci { to { opacity:1; transform:none; } }\r\n.ci { width: 44px; height: 44px; border-radius: 11px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; background: rgba(79,110,247,0.06); border: 1px solid rgba(79,110,247,0.18); color: var(--cyan); transition: all .35s; position: relative; z-index: 1; box-shadow: inset 0 1px 0 rgba(255,255,255,0.04); }\r\n.card:hover .ci { transform: scale(1.06); }\r\n.card.c-danger .ci { background: rgba(255,61,104,0.10); border-color: rgba(255,61,104,0.28); color: var(--danger); box-shadow: inset 0 1px 0 rgba(255,255,255,0.04), 0 0 14px rgba(255,61,104,0.10); }\r\n.card.c-warn .ci { background: rgba(255,184,77,0.10); border-color: rgba(255,184,77,0.28); color: var(--amber); box-shadow: inset 0 1px 0 rgba(255,255,255,0.04), 0 0 14px rgba(255,184,77,0.08); }\r\n.card.c-safe .ci { background: rgba(34,230,168,0.10); border-color: rgba(34,230,168,0.28); color: var(--safe); box-shadow: inset 0 1px 0 rgba(255,255,255,0.04), 0 0 14px rgba(34,230,168,0.08); }\r\n.ci svg { width: 20px; height: 20px; }\r\n.cb { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: 6px; }\r\n.cl { font-size: 10px; letter-spacing: 1.5px; color: var(--ayu-text-secondary); text-transform: uppercase; font-weight: 600; }\r\n.cv { font-family: var(--font-mono); font-size: 14px; font-weight: 600; color: var(--ayu-text-primary); word-break: break-word; line-height: 1.4; padding: 6px 10px; border-radius: 6px; background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.06); transition: all .3s; display: inline-block; width: fit-content; max-width: 100%; }\r\n.cv.risk { color: var(--danger); background: rgba(255,61,104,0.08); border-color: rgba(255,61,104,0.22); }\r\n.cv.warn { color: var(--amber); background: rgba(255,184,77,0.08); border-color: rgba(255,184,77,0.22); }\r\n.cv.safe { color: var(--safe); background: rgba(34,230,168,0.08); border-color: rgba(34,230,168,0.22); }\r\n.cv.mask { color: var(--safe); font-style: italic; background: rgba(34,230,168,0.10); border-color: rgba(34,230,168,0.25); }\r\n.cs { font-size: 11px; color: var(--ayu-text-tertiary); line-height: 1.45; transition: color .3s; }\r\n.card:hover .cs { color: var(--ayu-text-secondary); }\r\n\r\n\/* =========================================================================\r\n   MAP CARD  (Leaflet-powered, precise)\r\n   ========================================================================= *\/\r\n.mapc { margin-top: 8px; border: 1px solid rgba(79,110,247,0.18); border-radius: 14px; overflow: hidden; background: rgba(9,13,36,0.85); backdrop-filter: blur(12px); box-shadow: 0 4px 20px rgba(0,0,0,0.35), 0 0 0 1px rgba(79,110,247,0.06); position: relative; display: flex; flex-direction: column; width: 100%; }\r\n.mapc::before { content:''; position:absolute; top:0; left:0; right:0; height:1px; background: linear-gradient(90deg, transparent, rgba(79,110,247,0.3), transparent); z-index:1; }\r\n.maph { display: flex; align-items: center; justify-content: space-between; padding: 14px 20px; font-family: var(--font-mono); font-size: 10px; letter-spacing: 1.5px; color: var(--ayu-text-primary); font-weight: 600; text-transform: uppercase; border-bottom: 1px solid rgba(79,110,247,0.12); background: rgba(9,13,36,0.6); flex-shrink: 0; gap: 10px; flex-wrap: wrap; }\r\n.maph-l { display: flex; align-items: center; gap: 10px; }\r\n.maph-l .map-label-icon { width: 18px; height: 18px; color: var(--cyan); opacity: 0.8; }\r\n.maph-l .map-label-text { font-size: 11px; letter-spacing: 1px; color: var(--ayu-text-secondary); }\r\n.maph-l .map-label-text .hl { color: var(--cyan); font-weight: 700; }\r\n.maph-r { display: flex; align-items: center; gap: 8px; }\r\n.precise-btn { display: inline-flex; align-items: center; gap: 7px; padding: 8px 14px; border-radius: 9px; border: 1px solid rgba(34,230,168,0.40); background: linear-gradient(135deg, rgba(34,230,168,0.14), rgba(79,110,247,0.12)); color: #fff; font-family: var(--font-mono); font-weight: 600; font-size: 10px; letter-spacing: 0.5px; text-transform: uppercase; cursor: pointer; transition: .25s; white-space: nowrap; }\r\n.precise-btn:hover { transform: translateY(-1px); box-shadow: 0 4px 16px rgba(34,230,168,0.22); border-color: rgba(34,230,168,0.6); }\r\n.precise-btn:disabled { opacity: .6; cursor: default; transform: none; box-shadow: none; }\r\n.precise-btn svg { width: 14px; height: 14px; color: var(--safe); flex-shrink: 0; }\r\n.maph-z { display: flex; gap: 4px; }\r\n.maph-z button { width: 30px; height: 30px; border-radius: 8px; border: 1px solid rgba(79,110,247,0.2); background: rgba(9,13,36,0.6); color: var(--ayu-text-primary); font-size: 18px; cursor: pointer; display: flex; align-items: center; justify-content: center; transition: all .2s; font-family: var(--font-mono); }\r\n.maph-z button:hover { border-color: rgba(79,110,247,0.5); background: rgba(79,110,247,0.1); color: var(--cyan); }\r\n.mapw { position: relative; height: 420px; width: 100%; overflow: hidden; }\r\n#mapLeaf { position: absolute; inset: 0; width: 100%; height: 100%; background: #0b1130; }\r\n.leaflet-container { background: #0b1130 !important; font-family: var(--font-mono); }\r\n\/* Essential Leaflet core CSS, inlined so the map works even if the CDN stylesheet is blocked *\/\r\n.leaflet-pane,.leaflet-tile,.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-tile-container,.leaflet-pane>svg,.leaflet-pane>canvas,.leaflet-zoom-box,.leaflet-image-layer,.leaflet-layer{position:absolute;left:0;top:0}\r\n.leaflet-container{overflow:hidden;-webkit-tap-highlight-color:transparent}\r\n.leaflet-tile,.leaflet-marker-icon,.leaflet-marker-shadow{-webkit-user-select:none;user-select:none;-webkit-user-drag:none}\r\n.leaflet-tile{filter:inherit;visibility:hidden}\r\n.leaflet-tile-loaded{visibility:inherit}\r\n.leaflet-container img.leaflet-tile,.leaflet-container .leaflet-marker-pane img,.leaflet-container .leaflet-tile-pane img{max-width:none!important;max-height:none!important;width:auto;padding:0}\r\n.leaflet-container .leaflet-overlay-pane svg{max-width:none!important;max-height:none!important}\r\n.leaflet-container.leaflet-touch-drag{touch-action:pinch-zoom}\r\n.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom{touch-action:none}\r\n.leaflet-pane{z-index:400}.leaflet-tile-pane{z-index:200}.leaflet-overlay-pane{z-index:400}.leaflet-shadow-pane{z-index:500}.leaflet-marker-pane{z-index:600}.leaflet-tooltip-pane{z-index:650}.leaflet-popup-pane{z-index:700}\r\n.leaflet-map-pane canvas{z-index:100}.leaflet-map-pane svg{z-index:200}\r\n.leaflet-control{position:relative;z-index:800;pointer-events:auto;float:left;clear:both}\r\n.leaflet-top,.leaflet-bottom{position:absolute;z-index:1000;pointer-events:none}\r\n.leaflet-top{top:0}.leaflet-bottom{bottom:0}.leaflet-left{left:0}.leaflet-right{right:0}\r\n.leaflet-right .leaflet-control{float:right;margin-right:10px}.leaflet-bottom .leaflet-control{margin-bottom:10px}.leaflet-left .leaflet-control{margin-left:10px}\r\n.leaflet-zoom-animated{transform-origin:0 0}\r\n.leaflet-zoom-anim .leaflet-zoom-animated{will-change:transform;transition:transform .25s cubic-bezier(0,0,.25,1)}\r\n.leaflet-zoom-anim .leaflet-tile,.leaflet-pan-anim .leaflet-tile{transition:none}\r\n.leaflet-zoom-anim .leaflet-zoom-hide{visibility:hidden}\r\n.leaflet-interactive{cursor:pointer}.leaflet-grab{cursor:grab}.leaflet-dragging .leaflet-grab{cursor:move}\r\n.leaflet-control-attribution{padding:0 5px}\r\n.ayu-osm-dark{filter:invert(1) hue-rotate(185deg) brightness(.82) contrast(.92) saturate(.6)}\r\n#mapLeaf{z-index:0}\r\n.leaflet-control-attribution { background: rgba(6,8,21,0.7) !important; color: var(--ayu-text-tertiary) !important; font-size: 9px !important; }\r\n.leaflet-control-attribution a { color: var(--cyan) !important; }\r\n.map-loc { position: absolute; bottom: 16px; left: 16px; z-index: 600; background: rgba(9,13,36,0.92); border: 1px solid rgba(79,110,247,0.2); border-radius: 12px; padding: 12px 18px; backdrop-filter: blur(12px); display: flex; align-items: center; gap: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.3); }\r\n.map-loc svg { width: 16px; height: 16px; color: var(--cyan); flex-shrink: 0; }\r\n.map-loc-t { font-family: var(--font-mono); font-size: 12px; color: var(--ayu-text-primary); font-weight: 600; }\r\n.map-loc-s { font-size: 10px; color: var(--ayu-text-secondary); margin-top: 2px; letter-spacing: 0.3px; }\r\n.map-acc { position: absolute; top: 16px; right: 16px; z-index: 600; font-family: var(--font-mono); font-size: 10px; letter-spacing: .5px; padding: 7px 13px; border-radius: 999px; border: 1px solid rgba(79,110,247,0.3); background: rgba(9,13,36,0.92); color: var(--ayu-text-secondary); backdrop-filter: blur(10px); }\r\n.map-acc b { color: var(--amber); }\r\n.map-acc.precise b { color: var(--safe); }\r\n.map-mask { position: absolute; inset: 0; z-index: 800; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px; opacity: 0; pointer-events: none; transition: all .5s; background: rgba(3,5,12,0.65); backdrop-filter: blur(6px); }\r\n.map-mask.show { opacity: 1; pointer-events: auto; }\r\n.map-mask svg { width: 36px; height: 36px; color: var(--safe); filter: drop-shadow(0 0 12px rgba(34,230,168,0.4)); animation: maskPulse 2s ease-in-out infinite; }\r\n.map-mask-t { font-family: var(--font-display); font-size: 16px; font-weight: 700; color: var(--safe); text-shadow: 0 0 20px rgba(34,230,168,0.4); letter-spacing: 0.5px; }\r\n.map-mask-s { font-family: var(--font-mono); font-size: 10px; color: rgba(34,230,168,0.7); letter-spacing: 1.5px; text-transform: uppercase; }\r\n@keyframes maskPulse { 0%,100%{transform:scale(1); filter: drop-shadow(0 0 12px rgba(34,230,168,0.4));} 50%{transform:scale(1.08); filter: drop-shadow(0 0 20px rgba(34,230,168,0.6));} }\r\n.map-section { margin-top: 32px; width: 100%; }\r\n\r\n.cta-block { margin-top: 40px; padding: 0; border-radius: 20px; border: none; background: transparent; position: relative; overflow: hidden; display: flex; flex-direction: column; align-items: stretch; gap: 0; width: 100%; }\r\n.cta-hero { position: relative; padding: 52px 56px; border-radius: 22px; background: radial-gradient(100% 160% at 50% -30%, rgba(79,110,247,0.14), transparent 60%), radial-gradient(70% 90% at 15% 110%, rgba(138,107,255,0.12), transparent 55%), radial-gradient(60% 90% at 95% 110%, rgba(34,230,168,0.06), transparent 55%), linear-gradient(180deg, rgba(9,13,36,0.94), rgba(6,8,21,0.90)); border: 1px solid rgba(79,110,247,0.16); backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px); box-shadow: 0 8px 44px rgba(0,0,0,0.4), inset 0 1px 0 rgba(255,255,255,0.04); isolation: isolate; display: flex; flex-direction: row; align-items: center; justify-content: space-between; gap: 40px; overflow: hidden; }\r\n.cta-hero::before { content:''; position:absolute; inset:-30%; z-index:0; pointer-events:none; background: radial-gradient(40% 50% at 30% 20%, rgba(79,110,247,0.14), transparent 70%), radial-gradient(40% 50% at 70% 80%, rgba(138,107,255,0.12), transparent 70%); filter: blur(50px); animation: ctaSmoke 10s ease-in-out infinite alternate; opacity: .8; }\r\n@keyframes ctaSmoke { 0%{transform:translate(-1%,1%) scale(1);} 100%{transform:translate(1%,-1%) scale(1.06);} }\r\n.cta-hero>* { position: relative; z-index: 1; }\r\n.cta-copy { display: flex; flex-direction: column; align-items: flex-start; text-align: left; gap: 16px; max-width: 560px; }\r\n.cta-badge { display: inline-flex; align-items: center; gap: 7px; font-family: var(--font-mono); font-size: 10px; letter-spacing: 2px; text-transform: uppercase; font-weight: 700; color: var(--cyan); padding: 6px 14px; border-radius: 999px; background: rgba(79,110,247,0.07); border: 1px solid rgba(79,110,247,0.2); }\r\n.cta-badge-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--cyan); box-shadow: 0 0 8px var(--cyan); animation: lp 1.5s ease-in-out infinite; }\r\n.cta-headline { font-family: var(--font-display); font-weight: 700; font-size: clamp(24px,3.2vw,34px); color: var(--ayu-text-primary); letter-spacing: -0.02em; line-height: 1.15; }\r\n.cta-headline em { font-style: normal; color: var(--cyan); }\r\n.cta-desc { font-family: var(--font-body); font-size: clamp(13px,1.2vw,15px); color: var(--ayu-text-secondary); line-height: 1.65; }\r\n.cta-trust { display: flex; align-items: center; gap: 16px; margin-top: 2px; flex-wrap: wrap; justify-content: flex-start; font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.5px; color: var(--ayu-text-tertiary); text-transform: uppercase; }\r\n.cta-trust-sep { width: 3px; height: 3px; border-radius: 50%; background: rgba(79,110,247,0.2); }\r\n.cta-actions-col { display: flex; flex-direction: column; align-items: center; gap: 14px; flex-shrink: 0; }\r\n.cta-btn { display: inline-flex; align-items: center; justify-content: center; gap: 10px; padding: 16px 34px; border-radius: 12px; border: 1px solid rgba(79,110,247,0.4); background: linear-gradient(135deg, rgba(79,110,247,0.16), rgba(138,107,255,0.12)); font-family: var(--font-display); font-weight: 600; font-size: 15px; color: var(--ayu-text-primary); letter-spacing: 0.2px; cursor: pointer; transition: all .3s cubic-bezier(.2,.8,.2,1); position: relative; overflow: hidden; text-decoration: none; white-space: nowrap; }\r\n.cta-btn::before { content:''; position:absolute; inset:0; border-radius:12px; background: linear-gradient(135deg, rgba(255,255,255,0.06), transparent); pointer-events:none; }\r\n.cta-btn svg { width: 18px; height: 18px; color: var(--cyan); transition: transform .3s; }\r\n.cta-btn:hover { transform: translateY(-2px); box-shadow: 0 8px 30px rgba(79,110,247,0.22); border-color: rgba(79,110,247,0.6); background: linear-gradient(135deg, rgba(79,110,247,0.24), rgba(138,107,255,0.18)); }\r\n.cta-btn:hover svg { transform: translateX(2px); }\r\n.cta-btn:active { transform: translateY(0); }\r\n.cta-link { font-family: var(--font-body); font-size: 13px; font-weight: 500; color: var(--ayu-text-secondary); cursor: pointer; transition: color .3s; text-decoration: none; display: inline-flex; align-items: center; gap: 6px; }\r\n.cta-link:hover { color: var(--ayu-text-primary); }\r\n.cta-link svg { width: 14px; height: 14px; transition: transform .25s; }\r\n.cta-link:hover svg { transform: translateX(2px); }\r\n@media(max-width:860px) { .cta-hero { flex-direction: column; text-align: center; padding: 40px 28px; gap: 28px; } .cta-copy { align-items: center; text-align: center; max-width: 100%; } .cta-trust { justify-content: center; } .cta-actions-col { width: 100%; } .cta-btn { width: 100%; } }\r\n@media(max-width:600px) { .mapw { height: 300px; } .cta-hero { padding: 32px 24px; } .maph { justify-content: center; } .maph-l .map-label-text { font-size: 9px; } .map-loc { bottom: 10px; left: 10px; padding: 10px 14px; } }\r\n\r\n.phone-pill { position: fixed; right: 24px; top: 50%; transform: translateY(-50%); z-index: 50; display: flex; align-items: center; gap: 0; flex-direction: row-reverse; padding: 0; border: 0; border-radius: 999px; background: transparent; box-shadow: none; cursor: pointer; transition: all .35s; }\r\n.phone-pill .pp-icon { width: 52px; height: 52px; border-radius: 50%; flex-shrink: 0; padding: 0; background: linear-gradient(135deg, var(--cyan), var(--blue)); display: flex; align-items: center; justify-content: center; box-shadow: 0 4px 20px rgba(79,110,247,0.35); border: 1px solid rgba(255,255,255,0.25); transition: all .3s; }\r\n.phone-pill:hover .pp-icon { transform: scale(1.08); box-shadow: 0 6px 26px rgba(79,110,247,0.5); }\r\n.phone-pill .pp-icon svg { width: 22px; height: 22px; color: #04070f; }\r\n.phone-pill .pp-text { font-family: var(--font-mono); font-weight: 600; font-size: 14px; color: var(--ayu-text-primary); white-space: nowrap; direction: ltr; text-align: right; max-width: 0; opacity: 0; overflow: hidden; padding: 12px 0; border-radius: 999px; background: linear-gradient(135deg, rgba(9,13,36,0.92), rgba(6,8,21,0.85)); border: 1px solid var(--border-strong); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); box-shadow: 0 4px 20px rgba(0,0,0,0.3), 0 0 20px rgba(79,110,247,0.1); transition: max-width .4s ease, opacity .3s ease, padding .4s ease, margin .4s ease; }\r\n.phone-pill.open .pp-text { max-width: 260px; opacity: 1; padding: 12px 18px; margin-right: 12px; }\r\n@media(max-width:480px) { .phone-pill { right: 14px; } .phone-pill .pp-icon { width: 46px; height: 46px; } }\r\n.pov { display: none; position: fixed; inset: 0; z-index: 100; background: rgba(3,5,12,0.88); backdrop-filter: blur(8px); flex-direction: column; align-items: center; justify-content: center; gap: 18px; }\r\n.pov.show { display: flex; }\r\n.povs { width: 76px; height: 76px; border-radius: 18px; background: linear-gradient(135deg, rgba(34,230,168,0.1), rgba(34,230,168,0.15)); border: 1px solid var(--safe); display: flex; align-items: center; justify-content: center; animation: psp 1.5s ease-in-out infinite; }\r\n@keyframes psp { 0%,100%{box-shadow:0 0 0 0 rgba(34,230,168,0.3);} 50%{box-shadow:0 0 0 18px rgba(34,230,168,0);} }\r\n.povs svg { width: 34px; height: 34px; color: var(--safe); }\r\n.povt { font-family: var(--font-display); font-size: 18px; font-weight: 700; color: var(--safe); }\r\n.povd { color: var(--ayu-text-secondary); font-size: 12px; text-align: center; max-width: 280px; line-height: 1.5; }\r\n@media(max-width:480px) { main { padding-top: 100px; padding-bottom: 36px; } .hl { font-size: 20px; } .map-loc { bottom: 8px; left: 8px; padding: 8px 10px; } }\r\n@media(prefers-reduced-motion:reduce) { .card { animation: none; opacity: 1; transform: none; } .cta-hero::before { animation: none; } .hero-block::after { animation: none; } }\r\n<\/style>\r\n<\/head>\r\n\r\n<body>\r\n<!-- \u2500\u2500 PAGE BACKGROUND \u2500\u2500 -->\r\n<div class=\"page-bg\"><\/div>\r\n<!-- \u2500\u2500 BACKGROUND LAYERS \u2500\u2500 -->\r\n<div class=\"bg-layers\">\r\n  <div class=\"ayu-bg-world\"><\/div>\r\n  <div class=\"ayu-bg-dots\"><\/div>\r\n  <div class=\"ayu-bg-glow\"><\/div>\r\n  <div class=\"ayu-bg-orb-1\"><\/div>\r\n  <div class=\"ayu-bg-orb-2\"><\/div>\r\n<\/div>\r\n\r\n<div class=\"ayu-content-overlay\">\r\n<main>\r\n<!-- START -->\r\n<div id=\"start-view\">\r\n  <div class=\"start-shield\">\r\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" aria-hidden=\"true\">\r\n      <path d=\"M12 2 3 6v6c0 5.2 3.8 9.8 9 11 5.2-1.2 9-5.8 9-11V6l-9-4Z\" \/>\r\n      <path d=\"M12 8v4M12 16h.01\" stroke-width=\"2\" stroke-linecap=\"round\" \/>\r\n    <\/svg>\r\n  <\/div>\r\n  <div class=\"start-title\">Network <span>Security Scan<\/span><\/div>\r\n  <div class=\"start-sub\">Real-time diagnostic of your IP exposure, browser fingerprint, open ports, blacklists, and threat intelligence \u2014 entirely client-side, zero data stored.<\/div>\r\n  <button class=\"start-cta\" id=\"startBtn\" aria-label=\"Start network security scan\">\r\n    Start Security Scan\r\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M5 12h14M12 5l7 7-7 7\"\/><\/svg>\r\n  <\/button>\r\n  <div class=\"start-features\">\r\n    <div class=\"start-feat\"><span class=\"start-feat-dot\"><\/span>IP &amp; location<\/div>\r\n    <div class=\"start-feat\"><span class=\"start-feat-dot\"><\/span>Threat intel<\/div>\r\n    <div class=\"start-feat\"><span class=\"start-feat-dot\"><\/span>Browser fingerprint<\/div>\r\n    <div class=\"start-feat\"><span class=\"start-feat-dot\"><\/span>Speed test<\/div>\r\n    <div class=\"start-feat\"><span class=\"start-feat-dot\"><\/span>Risk score<\/div>\r\n  <\/div>\r\n\r\n  <div class=\"telemetry\" role=\"status\" aria-live=\"polite\">\r\n    <div class=\"telemetry-left\">\r\n      <span class=\"status-pill\"><span class=\"dot online\"><\/span><span class=\"lbl\">Engine<\/span> <span class=\"val\">Active<\/span><\/span>\r\n      <span class=\"status-pill\"><span class=\"dot online\"><\/span><span class=\"lbl\">Heuristics<\/span> <span class=\"val\">Live<\/span><\/span>\r\n      <span class=\"status-pill\"><span class=\"dot online\"><\/span><span class=\"lbl\">IP Geolocation<\/span> <span class=\"val\">Ready<\/span><\/span>\r\n      <span class=\"status-pill\"><span class=\"dot online\"><\/span><span class=\"lbl\">Threat Intel<\/span> <span class=\"val\">Online<\/span><\/span>\r\n    <\/div>\r\n    <div style=\"display:flex; align-items:center; gap:12px;\">\r\n      <div class=\"net-activity\" title=\"Live network activity\">\r\n        <span class=\"net-lbl\">Bus<\/span>\r\n        <svg width=\"64\" height=\"22\" viewBox=\"0 0 64 22\" aria-hidden=\"true\">\r\n          <polyline points=\"2,18 6,12 10,18 14,8 18,14 22,4 26,12 30,8 34,16 38,6 42,14 46,10 50,18 54,8 58,14 62,8\" stroke=\"rgba(79,110,247,0.4)\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\/>\r\n        <\/svg>\r\n      <\/div>\r\n      <span class=\"last-update\">UPDATED <b id=\"lastUpdate\">--:--:--<\/b><\/span>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <div class=\"hero-stats\" aria-live=\"polite\">\r\n    <div class=\"stat-card\">\r\n      <div class=\"s-ico\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"9\"\/><path d=\"M2.5 12h19M12 2.5c2.5 2.7 3.8 6 3.8 9.5s-1.3 6.8-3.8 9.5c-2.5-2.7-3.8-6-3.8-9.5S9.5 5.2 12 2.5Z\"\/><\/svg><\/div>\r\n      <div class=\"s-trend\">\u25b2 live<\/div>\r\n      <div class=\"s-val\" id=\"statScans\">\u2014<\/div>\r\n      <div class=\"s-label\">Scans today<\/div>\r\n    <\/div>\r\n    <div class=\"stat-card\">\r\n      <div class=\"s-ico\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\"\/><\/svg><\/div>\r\n      <div class=\"s-trend\">\u25b2<\/div>\r\n      <div class=\"s-val\" id=\"statIssues\">\u2014<\/div>\r\n      <div class=\"s-label\">Issues found<\/div>\r\n    <\/div>\r\n    <div class=\"stat-card\">\r\n      <div class=\"s-ico\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><polyline points=\"23 4 23 10 17 10\"\/><polyline points=\"1 20 1 14 7 14\"\/><path d=\"M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15\"\/><\/svg><\/div>\r\n      <div class=\"s-trend\">\u25b2<\/div>\r\n      <div class=\"s-val\" id=\"statSpeed\">\u2014<\/div>\r\n      <div class=\"s-label\">Avg. speed (Mbps)<\/div>\r\n    <\/div>\r\n    <div class=\"stat-card\">\r\n      <div class=\"s-ico\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\"\/><polyline points=\"9 11 11 13 15 9\"\/><\/svg><\/div>\r\n      <div class=\"s-trend\">\u25b2<\/div>\r\n      <div class=\"s-val\" id=\"statRisk\">\u2014<\/div>\r\n      <div class=\"s-label\">Risk score (avg)<\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <div class=\"panel panel-pad\" style=\"border-color: rgba(79,110,247,.15); background: linear-gradient(150deg, rgba(9,13,36,.5) 0%, rgba(6,8,21,.6) 100%);\">\r\n    <h3 style=\"font-family: var(--font-display); font-size: 17px; font-weight: 700; color: #fff; margin-bottom: 12px; display: flex; align-items: center; gap: 10px;\">\r\n      <span style=\"color: var(--cyan); display: inline-flex; width:18px; height:18px; flex-shrink:0;\">\r\n        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\"\/><polyline points=\"9 11 11 13 15 9\"\/><\/svg>\r\n      <\/span>\r\n      Real-time Network Security Scan \u2014 In-Browser, Zero-Data-Transmission\r\n    <\/h3>\r\n    <div class=\"desktop-only\">\r\n      <p style=\"font-size: 13.5px; color: var(--ayu-text-secondary); line-height: 1.7; margin-bottom: 14px;\">\r\n        The <b>AssistYU Network Security Scan<\/b> is a powerful, client-side diagnostic tool that reveals exactly what your connection exposes to the internet. It performs a comprehensive audit of your <b>public IP<\/b>, <b>ISP<\/b>, <b>geolocation<\/b>, <b>WebRTC leaks<\/b>, <b>open ports<\/b>, <b>known CVEs<\/b>, <b>blacklist status<\/b>, and <b>device fingerprint<\/b> \u2014 all within your browser, without ever sending a single byte to our servers.\r\n      <\/p>\r\n      <p style=\"font-size: 13.5px; color: var(--ayu-text-secondary); line-height: 1.7; margin-bottom: 14px;\">\r\n        The scan leverages multiple public APIs (ipwho.is, ipapi.co, geojs.io, reallyfreegeoip.org, Shodan InternetDB) to fetch threat intelligence, then cross-references your browser's <b>canvas fingerprint<\/b>, <b>audio fingerprint<\/b>, <b>font list<\/b>, <b>WebGL GPU<\/b>, <b>hardware concurrency<\/b>, and <b>device memory<\/b> to build a complete risk profile. Every check is executed client-side; your IP and data are never stored or logged by AssistYU.\r\n      <\/p>\r\n      <p style=\"font-size: 13.5px; color: var(--ayu-text-secondary); line-height: 1.7;\">\r\n        The result is a detailed, evidence-based security verdict with a <b>risk score<\/b> (0\u2013100) and a <b>grade<\/b> (A\u2013F), along with actionable insights on <b>VPN\/proxy detection<\/b>, <b>blacklist status<\/b>, <b>open ports<\/b>, and <b>vulnerabilities<\/b>. Whether you're a privacy-conscious individual, a developer testing your infrastructure, or an IT administrator auditing your network, this scan gives you a complete picture of your digital exposure \u2014 without compromising your privacy.\r\n      <\/p>\r\n    <\/div>\r\n    <p class=\"mobile-only\" style=\"font-size: 13px; color: var(--ayu-text-secondary); line-height: 1.6;\">\r\n      A comprehensive client-side network scan that checks IP, location, WebRTC leaks, open ports, blacklists, CVEs, and device fingerprint \u2014 100% local, zero data stored.\r\n    <\/p>\r\n    <div style=\"display: flex; gap: 14px; flex-wrap: wrap; font-family: var(--font-mono); font-size: 11px; border-top: 1px solid rgba(255,255,255,.05); padding-top: 14px; margin-top: 14px;\">\r\n      <span style=\"color: var(--safe); display: flex; align-items: center; gap: 6px;\"><span style=\"width:6px;height:6px;border-radius:50%;background:var(--safe);box-shadow:0 0 6px var(--safe);\"><\/span> Client-side only<\/span>\r\n      <span style=\"color: var(--cyan); display: flex; align-items: center; gap: 6px;\"><span style=\"width:6px;height:6px;border-radius:50%;background:var(--cyan);box-shadow:0 0 6px var(--cyan);\"><\/span> Zero-data transmission<\/span>\r\n      <span style=\"color: var(--violet); display: flex; align-items: center; gap: 6px;\"><span style=\"width:6px;height:6px;border-radius:50%;background:var(--violet);box-shadow:0 0 6px var(--violet);\"><\/span> Threat intel APIs<\/span>\r\n      <span style=\"color: var(--blue); display: flex; align-items: center; gap: 6px;\"><span style=\"width:6px;height:6px;border-radius:50%;background:var(--blue);box-shadow:0 0 6px var(--blue);\"><\/span> CVE &amp; port scanning<\/span>\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<!-- SCAN -->\r\n<div id=\"scan-stage\" role=\"status\" aria-live=\"polite\">\r\n  <div class=\"eyebrow\">AssistYU Network Scan <span>\u00b7 real-time diagnostic<\/span><\/div>\r\n  <h1 class=\"hl\">Your connection is <span class=\"sw-t scanning\" id=\"sw\">being analyzed<\/span><\/h1>\r\n  <div class=\"scan-grid\">\r\n    <div class=\"radar-sec\" aria-hidden=\"true\">\r\n      <div class=\"radar-box\"><canvas id=\"radarCanvas\" width=\"640\" height=\"640\"><\/canvas><\/div>\r\n      <div class=\"rl\">Radar sweep <span class=\"live\">\u25cf live<\/span><\/div>\r\n    <\/div>\r\n    <div class=\"ensec\">\r\n      <div class=\"enb\" role=\"progressbar\" aria-label=\"Scan progress\" aria-valuemin=\"0\" aria-valuemax=\"100\" aria-valuenow=\"0\" id=\"enbwrap\">\r\n        <div class=\"enbf\" id=\"ebf\"><\/div>\r\n      <\/div>\r\n      <div class=\"enp\" id=\"enp\"><span class=\"pct\">0%<\/span><\/div>\r\n      <div class=\"en-status\" id=\"en-status\">Initializing scan\u2026<\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n\r\n<!-- VERDICT -->\r\n<div id=\"verdict-view\">\r\n  <div id=\"verdict-header\" class=\"verdict-header\">\r\n    <div class=\"vb dg\" id=\"vbadge\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M12 2 3 6v6c0 5.2 3.8 9.8 9 11 5.2-1.2 9-5.8 9-11V6l-9-4Z\"\/><path d=\"M12 8v5M12 16h.01\"\/><\/svg><\/div>\r\n    <div class=\"vht-title\" id=\"vMainTitle\">AssistYU Network Scan<\/div>\r\n    <div class=\"vht-desc\" id=\"vMainDesc\">Your network is exposed.<\/div>\r\n    <div class=\"vht-subdesc\" id=\"vMainSubDesc\">Real-time diagnostic of your IP exposure, browser fingerprint, and threat intelligence<\/div>\r\n    <div class=\"protect-toggle-row\" id=\"tgw\">\r\n      <span class=\"toggle-label\" id=\"toggle-label\">Protected mode<\/span>\r\n      <label class=\"swi\"><input type=\"checkbox\" id=\"ptog\" aria-label=\"Toggle protected mode\"><span class=\"sws\"><\/span><\/label>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <div class=\"hero-blocks\" id=\"hero-container\">\r\n    <div class=\"hero-block hero-left exposed\" id=\"hero-left\">\r\n      <span class=\"threats-label danger\" id=\"threats-label\">THREATS DETECTED<\/span>\r\n      <div class=\"threats-count\"><span class=\"num\" id=\"threats-num\">0<\/span><\/div>\r\n      <div class=\"threats-detail\" id=\"vtitle\">issues found on your current connection<\/div>\r\n      <div class=\"threats-badges\">\r\n        <span class=\"badge crit\" id=\"vbr-crit\"><span class=\"dot\"><\/span><span id=\"crit-n\">0<\/span> critical<\/span>\r\n        <span class=\"badge warn\" id=\"vbr-warn\"><span class=\"dot\"><\/span><span id=\"warn-n\">0<\/span> warning<\/span>\r\n      <\/div>\r\n    <\/div>\r\n    <div class=\"hero-block hero-right exposed\" id=\"hero-right\">\r\n      <div class=\"gauge-wrap\">\r\n        <div class=\"gauge-ring\">\r\n          <svg viewBox=\"0 0 120 120\">\r\n            <circle class=\"g-bg\" cx=\"60\" cy=\"60\" r=\"50\"\/>\r\n            <circle class=\"g-fill\" id=\"rg-fill\" cx=\"60\" cy=\"60\" r=\"50\" stroke-dasharray=\"314.16\" stroke-dashoffset=\"314.16\"\/>\r\n          <\/svg>\r\n          <div class=\"g-inner\"><\/div>\r\n          <div class=\"g-num\">\r\n            <span class=\"g-num-val\" id=\"rg-num\">0<\/span>\r\n            <span class=\"g-num-of\">\/100<\/span>\r\n          <\/div>\r\n        <\/div>\r\n        <div class=\"gauge-info\">\r\n          <div class=\"gauge-grade\" id=\"rg-grade\">Grade \u2014<\/div>\r\n          <div class=\"gauge-tags\" id=\"rg-sub\"><\/div>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <div class=\"rsec\">\r\n    <div class=\"slab\">Network &amp; identity<\/div>\r\n    <div class=\"g3\" id=\"gnet\"><\/div>\r\n\r\n    <div class=\"map-section\">\r\n      <div class=\"mapc\">\r\n        <div class=\"maph\">\r\n          <div class=\"maph-l\">\r\n            <svg class=\"map-label-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M12 22s7-6.2 7-12a7 7 0 1 0-14 0c0 5.8 7 12 7 12Z\"\/><circle cx=\"12\" cy=\"10\" r=\"2.5\"\/><\/svg>\r\n            <span class=\"map-label-text\">Location: <span class=\"hl\" id=\"map-label-loc\">\u2014<\/span><\/span>\r\n          <\/div>\r\n          <div class=\"maph-r\">\r\n            <button type=\"button\" class=\"precise-btn\" id=\"preciseBtn\" title=\"Pinpoint your exact location (GPS \/ Wi-Fi)\">\r\n              <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"3\"\/><path d=\"M12 2v3M12 19v3M2 12h3M19 12h3\"\/><\/svg>\r\n              Precise location\r\n            <\/button>\r\n            <div class=\"maph-z\">\r\n              <button type=\"button\" id=\"zoomOut\" aria-label=\"Zoom out map\">&#x2212;<\/button>\r\n              <button type=\"button\" id=\"zoomIn\" aria-label=\"Zoom in map\">&#x2b;<\/button>\r\n            <\/div>\r\n          <\/div>\r\n        <\/div>\r\n        <div class=\"mapw\" id=\"mapw\">\r\n          <div id=\"mapLeaf\"><\/div>\r\n          <div class=\"map-acc\" id=\"map-acc\">Accuracy: <b>\u2014<\/b><\/div>\r\n          <div class=\"map-loc\" id=\"map-loc\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"10\" r=\"3\"\/><path d=\"M12 2a8 8 0 0 0-8 8c0 5.4 8 12 8 12s8-6.6 8-12a8 8 0 0 0-8-8Z\"\/><\/svg><div><div class=\"map-loc-t\" id=\"map-loc-t\">\u2014<\/div><div class=\"map-loc-s\" id=\"map-loc-s\">Approximate coordinates<\/div><\/div><\/div>\r\n          <div class=\"map-mask\" id=\"map-mask\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M12 2 3 6v6c0 5.2 3.8 9.8 9 11 5.2-1.2 9-5.8 9-11V6l-9-4Z\"\/><path d=\"M9 12l2 2 4-4\"\/><\/svg><div class=\"map-mask-t\">Location masked<\/div><div class=\"map-mask-s\">Protected by AssistYU tunnel<\/div><\/div>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n\r\n    <div class=\"slab\">Threat intelligence<\/div>\r\n    <div class=\"g3\" id=\"gth\"><\/div>\r\n\r\n    <div class=\"slab\">Device fingerprint<\/div>\r\n    <div class=\"g2\" id=\"gdev\"><\/div>\r\n\r\n    <div class=\"slab\">Security checks<\/div>\r\n    <div class=\"g2\" id=\"gsec\"><\/div>\r\n  <\/div>\r\n\r\n  <div class=\"cta-block\">\r\n    <div class=\"cta-hero\">\r\n      <div class=\"cta-copy\">\r\n        <div class=\"cta-badge\"><span class=\"cta-badge-dot\"><\/span>Protect your network<\/div>\r\n        <div class=\"cta-headline\">Your scan found <em>vulnerabilities<\/em>.<br>Fix them now.<\/div>\r\n        <div class=\"cta-desc\">Encrypt your traffic, mask your IP and block WebRTC leaks with one toggle. This scan ran entirely in your browser \u2014 nothing was sent to AssistYU servers.<\/div>\r\n        <div class=\"cta-trust\">\r\n          <span>100% client-side<\/span>\r\n          <span class=\"cta-trust-sep\"><\/span>\r\n          <span>Zero data stored<\/span>\r\n          <span class=\"cta-trust-sep\"><\/span>\r\n          <span>No account needed<\/span>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"cta-actions-col\">\r\n        <a href=\"https:\/\/assistyu.com\/security-products\/\" target=\"_blank\" rel=\"noopener\" class=\"cta-btn\">\r\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M12 2 3 6v6c0 5.2 3.8 9.8 9 11 5.2-1.2 9-5.8 9-11V6l-9-4Z\"\/><path d=\"M9 12l2 2 4-4\"\/><\/svg>\r\n          Get AssistYU Protection\r\n        <\/a>\r\n        <a href=\"https:\/\/assistyu.com\/contact\/\" target=\"_blank\" rel=\"noopener\" class=\"cta-link\">\r\n          Talk to an expert\r\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M5 12h14M12 5l7 7-7 7\"\/><\/svg>\r\n        <\/a>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n<\/div>\r\n<\/main>\r\n\r\n<!-- PHONE PILL -->\r\n<div class=\"phone-pill\" id=\"phone-pill\">\r\n  <button type=\"button\" class=\"pp-icon\" id=\"pp-icon\" aria-label=\"Show phone number\" aria-expanded=\"false\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><path d=\"M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 22 16.92z\"\/><\/svg><\/button>\r\n  <a href=\"tel:+34951550227\" class=\"pp-text\" id=\"pp-text\">+34 9 515 502 27<\/a>\r\n<\/div>\r\n<div class=\"pov\" id=\"pov\">\r\n  <div class=\"povs\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M12 2 3 6v6c0 5.2 3.8 9.8 9 11 5.2-1.2 9-5.8 9-11V6l-9-4Z\"\/><path d=\"M9 12l2 2 4-4\"\/><\/svg><\/div>\r\n  <div class=\"povt\">Protected mode active<\/div>\r\n  <div class=\"povd\">AssistYU is masking your IP, blocking WebRTC leaks and hiding your network fingerprint.<\/div>\r\n<\/div>\r\n<\/div>\r\n\r\n<!-- Leaflet library -->\r\n<script src=\"https:\/\/unpkg.com\/leaflet@1.9.4\/dist\/leaflet.js\"><\/script>\r\n<script>\r\n\/* Fallback: if unpkg is blocked, load Leaflet (JS + CSS) from other CDNs *\/\r\n(function () {\r\n  function addCss(href) { var l = document.createElement('link'); l.rel = 'stylesheet'; l.href = href; document.head.appendChild(l); }\r\n  addCss('https:\/\/cdn.jsdelivr.net\/npm\/leaflet@1.9.4\/dist\/leaflet.css');\r\n  if (typeof L !== 'undefined') return;\r\n  var urls = ['https:\/\/cdn.jsdelivr.net\/npm\/leaflet@1.9.4\/dist\/leaflet.js', 'https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/leaflet\/1.9.4\/leaflet.js'];\r\n  (function next(i) {\r\n    if (typeof L !== 'undefined' || i >= urls.length) return;\r\n    var s = document.createElement('script'); s.src = urls[i];\r\n    s.onerror = function () { next(i + 1); };\r\n    document.head.appendChild(s);\r\n  })(0);\r\n})();\r\n<\/script>\r\n<script>\r\ndocument.addEventListener('DOMContentLoaded', function() {\r\n  (function() {\r\n    \/* ============================= RADAR CANVAS ============================= *\/\r\n    var cv = document.getElementById('radarCanvas');\r\n    var ctx = cv.getContext('2d');\r\n    var W = cv.width, H = cv.height, cx = W \/ 2, cy = H \/ 2, R = W \/ 2 - 20;\r\n    var sweepAngle = 0, trailLen = 1.1;\r\n    \/\/ Blips are FIXED on the radar (a = their own fixed angle). Only the sweep rotates.\r\n    var blipsData = [\r\n      { a: 0.35, r: 0.65, c: 'cyan' }, { a: 1.8, r: 0.45, c: 'amber' },\r\n      { a: 2.8, r: 0.80, c: 'cyan' }, { a: 3.8, r: 0.35, c: 'danger' },\r\n      { a: 0.9, r: 0.55, c: 'cyan' }, { a: 4.5, r: 0.70, c: 'amber' },\r\n      { a: 5.2, r: 0.50, c: 'cyan' }, { a: 2.0, r: 0.88, c: 'danger' }\r\n    ];\r\n    var blipAlpha = [0,0,0,0,0,0,0,0], blipTarget = [1,1,1,1,1,1,1,1];\r\n    var radarRunning = true;\r\n\r\n    function drawRadar(t) {\r\n      if (!radarRunning) return;\r\n      ctx.clearRect(0, 0, W, H);\r\n      var grd = ctx.createRadialGradient(cx, cy, 0, cx, cy, R * 1.1);\r\n      grd.addColorStop(0, 'rgba(79,110,247,0.04)'); grd.addColorStop(1, 'transparent');\r\n      ctx.fillStyle = grd; ctx.fillRect(0, 0, W, H);\r\n      ctx.strokeStyle = 'rgba(79,110,247,0.25)'; ctx.lineWidth = 1;\r\n      [1, 0.834, 0.667, 0.5].forEach(function(s) { ctx.beginPath(); ctx.arc(cx, cy, R * s, 0, Math.PI * 2); ctx.stroke(); });\r\n      ctx.strokeStyle = 'rgba(79,110,247,0.15)'; ctx.lineWidth = 1;\r\n      ctx.beginPath(); ctx.moveTo(cx - R, cy); ctx.lineTo(cx + R, cy); ctx.stroke();\r\n      ctx.beginPath(); ctx.moveTo(cx, cy - R); ctx.lineTo(cx, cy + R); ctx.stroke();\r\n      ctx.strokeStyle = 'rgba(79,110,247,0.06)';\r\n      var d = R * 0.707;\r\n      ctx.beginPath(); ctx.moveTo(cx - d, cy - d); ctx.lineTo(cx + d, cy + d); ctx.stroke();\r\n      ctx.beginPath(); ctx.moveTo(cx + d, cy - d); ctx.lineTo(cx - d, cy + d); ctx.stroke();\r\n      var segs = 60;\r\n      for (var i = 0; i < segs; i++) {\r\n        var frac = i \/ segs, ang = sweepAngle - frac * trailLen, alpha = (1 - frac) * 0.30;\r\n        ctx.beginPath(); ctx.moveTo(cx, cy); ctx.arc(cx, cy, R, ang - 0.025, ang + 0.025); ctx.closePath();\r\n        ctx.fillStyle = 'rgba(79,110,247,' + alpha + ')'; ctx.fill();\r\n      }\r\n      ctx.save(); ctx.translate(cx, cy); ctx.rotate(sweepAngle);\r\n      var ag = ctx.createLinearGradient(0, 0, R, 0);\r\n      ag.addColorStop(0, 'rgba(79,110,247,0.7)'); ag.addColorStop(0.7, 'rgba(79,110,247,0.15)'); ag.addColorStop(1, 'rgba(79,110,247,0)');\r\n      ctx.beginPath(); ctx.moveTo(0, 0); ctx.lineTo(R, 0); ctx.strokeStyle = ag; ctx.lineWidth = 3; ctx.stroke();\r\n      ctx.beginPath(); ctx.moveTo(0, 0); ctx.lineTo(R, 0); ctx.strokeStyle = 'rgba(79,110,247,0.9)'; ctx.lineWidth = 1.5; ctx.stroke();\r\n      ctx.restore();\r\n      var pulseTime = (t % 3000) \/ 3000;\r\n      for (var p = 0; p < 3; p++) {\r\n        var pt = (pulseTime + p \/ 3) % 1, pr = R * pt, pa = (1 - pt) * 0.25;\r\n        ctx.beginPath(); ctx.arc(cx, cy, pr, 0, Math.PI * 2); ctx.strokeStyle = 'rgba(79,110,247,' + pa + ')'; ctx.lineWidth = 1; ctx.stroke();\r\n      }\r\n      var bColors = { cyan: '79,110,247', amber: '255,184,77', danger: '255,61,104' };\r\n      for (var i = 0; i < blipsData.length; i++) {\r\n        var b = blipsData[i];\r\n        \/\/ FIXED position: the blip never moves with the sweep\r\n        var bx = cx + Math.cos(b.a) * R * b.r, by = cy + Math.sin(b.a) * R * b.r;\r\n        \/\/ lights up right after the sweep passes over it, then fades\r\n        var dist = ((sweepAngle - b.a) % (Math.PI * 2) + Math.PI * 2) % (Math.PI * 2);\r\n        blipTarget[i] = dist < 0.3 ? 1 : 0.15;\r\n        blipAlpha[i] += (blipTarget[i] - blipAlpha[i]) * 0.08;\r\n        var a = blipAlpha[i], rgb = bColors[b.c];\r\n        ctx.beginPath(); ctx.arc(bx, by, 8, 0, Math.PI * 2); ctx.fillStyle = 'rgba(' + rgb + ',' + (a * 0.3) + ')'; ctx.fill();\r\n        ctx.beginPath(); ctx.arc(bx, by, 3.5, 0, Math.PI * 2); ctx.fillStyle = 'rgba(' + rgb + ',' + a + ')'; ctx.fill();\r\n        ctx.beginPath(); ctx.arc(bx, by, 1.5, 0, Math.PI * 2); ctx.fillStyle = 'rgba(255,255,255,' + (a * 0.7) + ')'; ctx.fill();\r\n      }\r\n      ctx.beginPath(); ctx.arc(cx, cy, 5, 0, Math.PI * 2); ctx.fillStyle = 'rgba(79,110,247,1)'; ctx.fill();\r\n      ctx.beginPath(); ctx.arc(cx, cy, 12, 0, Math.PI * 2); ctx.fillStyle = 'rgba(79,110,247,0.15)'; ctx.fill();\r\n      ctx.beginPath(); ctx.arc(cx, cy, 22, 0, Math.PI * 2); ctx.fillStyle = 'rgba(79,110,247,0.06)'; ctx.fill();\r\n      sweepAngle += 0.025;\r\n      requestAnimationFrame(drawRadar);\r\n    }\r\n\r\n    \/* ============================= SCAN STEPS ============================= *\/\r\n    var STEPS = [\r\n      { l: 'Resolving public IP' }, { l: 'Fingerprinting ISP' },\r\n      { l: 'Triangulating location (multi-source)' }, { l: 'Checking encryption' },\r\n      { l: 'Testing VPN \/ DC' }, { l: 'WebRTC leak scan' },\r\n      { l: 'Analyzing connection type' }, { l: 'Measuring network speed' },\r\n      { l: 'Device fingerprint' }, { l: 'Canvas fingerprint' },\r\n      { l: 'Audio fingerprint' }, { l: 'Enumerating fonts' },\r\n      { l: 'Checking IP blacklists' }, { l: 'VPN \/ proxy detection' },\r\n      { l: 'Scanning open ports & CVEs' }, { l: 'Cross-checking timezone' },\r\n      { l: 'Evaluating data exposure' }, { l: 'Computing risk score' },\r\n      { l: 'Compiling threat report' }, { l: 'Generating security verdict' }\r\n    ];\r\n    var si = 0, sd = 700;\r\n    var bf, pbar, enpEl, statusEl, D;\r\n\r\n    document.getElementById('startBtn').addEventListener('click', function() {\r\n      document.getElementById('start-view').style.display = 'none';\r\n      document.getElementById('scan-stage').style.display = 'block';\r\n      si = 0;\r\n      bf = document.getElementById('ebf');\r\n      pbar = document.getElementById('enbwrap');\r\n      enpEl = document.getElementById('enp');\r\n      statusEl = document.getElementById('en-status');\r\n      radarRunning = true;\r\n      requestAnimationFrame(drawRadar);\r\n      var tm = setInterval(function() {\r\n        si++;\r\n        if (si < STEPS.length) {\r\n          var p = Math.round(((si + 1) \/ STEPS.length) * 100);\r\n          bf.style.width = p + '%'; pbar.setAttribute('aria-valuenow', p);\r\n          enpEl.innerHTML = '<span class=\"pct\">' + p + '%<\/span>';\r\n          statusEl.textContent = STEPS[si] ? STEPS[si].l + '\u2026' : 'Scanning\u2026';\r\n        } else {\r\n          clearInterval(tm);\r\n          bf.style.width = '100%'; pbar.setAttribute('aria-valuenow', 100);\r\n          enpEl.innerHTML = '<span class=\"pct\">100%<\/span>';\r\n          statusEl.className = 'en-status done';\r\n          statusEl.innerHTML = 'Generating report \u2014 almost there\u2026';\r\n          setTimeout(function() { startDataCollection(); }, 800);\r\n        }\r\n      }, sd);\r\n    });\r\n\r\n    \/* ================= GEO CONSENSUS HELPERS (multi-source, accurate) ================= *\/\r\n    \/\/ FIX: accepts IPv4 AND IPv6 (previously IPv6 users got \"Location unavailable\")\r\n    function isValidIP(ip) {\r\n      if (typeof ip !== 'string') return false;\r\n      if (\/^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$\/.test(ip)) return true;\r\n      return ip.indexOf(':') > -1 && \/^[0-9a-f:.]+$\/i.test(ip);\r\n    }\r\n    function median(arr) {\r\n      var a = arr.slice().sort(function (x, y) { return x - y; });\r\n      var m = Math.floor(a.length \/ 2);\r\n      return a.length % 2 ? a[m] : (a[m - 1] + a[m]) \/ 2;\r\n    }\r\n    function distM(la1, lo1, la2, lo2) {\r\n      var Rk = 6371000, dLa = (la2 - la1) * Math.PI \/ 180, dLo = (lo2 - lo1) * Math.PI \/ 180;\r\n      var s = Math.sin(dLa \/ 2) * Math.sin(dLa \/ 2) + Math.cos(la1 * Math.PI \/ 180) * Math.cos(la2 * Math.PI \/ 180) * Math.sin(dLo \/ 2) * Math.sin(dLo \/ 2);\r\n      return 2 * Rk * Math.asin(Math.sqrt(s));\r\n    }\r\n    \/\/ fetch JSON with a hard timeout so one slow API can never block the scan\r\n    function fetchJSON(url, ms) {\r\n      var ctl = (typeof AbortController !== 'undefined') ? new AbortController() : null;\r\n      var timer = setTimeout(function () { if (ctl) ctl.abort(); }, ms || 7000);\r\n      return fetch(url, { cache: 'no-store', signal: ctl ? ctl.signal : undefined })\r\n        .then(function (r) { clearTimeout(timer); if (!r.ok) throw new Error('http ' + r.status); return r.json(); })\r\n        .catch(function (e) { clearTimeout(timer); throw e; });\r\n    }\r\n    function num(v) { var n = parseFloat(v); return isFinite(n) ? n : NaN; }\r\n\r\n    \/\/ Free, key-less, CORS-enabled geolocation sources. Normalized output.\r\n    var GEO_SOURCES = [\r\n      { name: 'ipwho.is', url: 'https:\/\/ipwho.is\/', map: function (j) {\r\n          if (j.success === false || !isValidIP(j.ip)) return null;\r\n          return { ip: j.ip, lat: num(j.latitude), lon: num(j.longitude), city: j.city, region: j.region,\r\n            country: j.country, cISO: j.country_code,\r\n            isp: j.connection && (j.connection.isp || j.connection.org), org: j.connection && j.connection.org,\r\n            asn: j.connection && j.connection.asn ? 'AS' + j.connection.asn : null,\r\n            tz: j.timezone && j.timezone.id, acc: null }; } },\r\n      { name: 'ipapi.co', url: 'https:\/\/ipapi.co\/json\/', map: function (j) {\r\n          if (j.error || !isValidIP(j.ip)) return null;\r\n          return { ip: j.ip, lat: num(j.latitude), lon: num(j.longitude), city: j.city, region: j.region,\r\n            country: j.country_name, cISO: j.country_code, isp: j.org, org: j.org, asn: j.asn, tz: j.timezone, acc: null }; } },\r\n      { name: 'geojs.io', url: 'https:\/\/get.geojs.io\/v1\/ip\/geo.json', map: function (j) {\r\n          if (!isValidIP(j.ip)) return null;\r\n          return { ip: j.ip, lat: num(j.latitude), lon: num(j.longitude), city: j.city, region: j.region,\r\n            country: j.country, cISO: j.country_code, isp: j.organization_name, org: j.organization,\r\n            asn: j.asn ? 'AS' + j.asn : null, tz: j.timezone, acc: j.accuracy ? +j.accuracy * 1000 : null }; } },\r\n      { name: 'reallyfreegeoip.org', url: 'https:\/\/reallyfreegeoip.org\/json\/', map: function (j) {\r\n          if (!isValidIP(j.ip)) return null;\r\n          return { ip: j.ip, lat: num(j.latitude), lon: num(j.longitude), city: j.city, region: j.region_name,\r\n            country: j.country_name, cISO: j.country_code, isp: null, org: null, asn: null, tz: j.time_zone, acc: null }; } },\r\n      { name: 'ipinfo.io', url: 'https:\/\/ipinfo.io\/json', map: function (j) {\r\n          if (!isValidIP(j.ip) || !j.loc) return null;\r\n          var p = String(j.loc).split(',');\r\n          var asn = null, org = j.org || null;\r\n          if (org) { var m = org.match(\/^(AS\\d+)\\s*(.*)$\/); if (m) { asn = m[1]; org = m[2] || org; } }\r\n          return { ip: j.ip, lat: num(p[0]), lon: num(p[1]), city: j.city, region: j.region,\r\n            country: j.country, cISO: j.country, isp: org, org: org, asn: asn, tz: j.timezone, acc: null }; } },\r\n      { name: 'ipapi.is', url: 'https:\/\/api.ipapi.is\/', map: function (j) {\r\n          if (!isValidIP(j.ip) || !j.location) return null;\r\n          var l = j.location;\r\n          return { ip: j.ip, lat: num(l.latitude), lon: num(l.longitude), city: l.city, region: l.state,\r\n            country: l.country, cISO: l.country_code,\r\n            isp: (j.company && j.company.name) || (j.asn && j.asn.org) || null,\r\n            org: (j.asn && j.asn.org) || null, asn: j.asn && j.asn.asn ? 'AS' + j.asn.asn : null,\r\n            tz: l.timezone, acc: null }; } },\r\n      { name: 'freeipapi.com', url: 'https:\/\/free.freeipapi.com\/api\/json', map: function (j) {\r\n          if (!isValidIP(j.ipAddress)) return null;\r\n          return { ip: j.ipAddress, lat: num(j.latitude), lon: num(j.longitude), city: j.cityName, region: j.regionName,\r\n            country: j.countryName, cISO: j.countryCode,\r\n            isp: j.asnOrganization || null, org: j.asnOrganization || null, asn: j.asn ? 'AS' + String(j.asn).replace(\/^AS\/i, '') : null,\r\n            tz: (j.timeZones && j.timeZones[0]) || j.timeZone || null, acc: null }; } }\r\n    ];\r\n    \/\/ Query all sources, reconcile by median consensus. Returns a promise.\r\n    \/\/ Same services, but queried by IP address (different URLs \u2014 works when the \"my IP\" endpoints are blocked)\r\n    var IP_URLS = {\r\n      'ipwho.is': 'https:\/\/ipwho.is\/{ip}',\r\n      'ipapi.co': 'https:\/\/ipapi.co\/{ip}\/json\/',\r\n      'geojs.io': 'https:\/\/get.geojs.io\/v1\/ip\/geo\/{ip}.json',\r\n      'reallyfreegeoip.org': 'https:\/\/reallyfreegeoip.org\/json\/{ip}',\r\n      'ipinfo.io': 'https:\/\/ipinfo.io\/{ip}\/json',\r\n      'ipapi.is': 'https:\/\/api.ipapi.is\/?q={ip}',\r\n      'freeipapi.com': 'https:\/\/free.freeipapi.com\/api\/json\/{ip}'\r\n    };\r\n    IP_URLS['ipwhois.app'] = 'https:\/\/ipwhois.app\/json\/{ip}';\r\n    IP_URLS['ip.sb'] = 'https:\/\/api.ip.sb\/geoip\/{ip}';\r\n    IP_URLS['geolocation-db.com'] = 'https:\/\/geolocation-db.com\/json\/{ip}';\r\n    GEO_SOURCES.push(\r\n      { name: 'ipwhois.app', url: 'https:\/\/ipwhois.app\/json\/', map: function (j) {\r\n          if (j.success === false || !isValidIP(j.ip)) return null;\r\n          return { ip: j.ip, lat: num(j.latitude), lon: num(j.longitude), city: j.city, region: j.region, country: j.country, cISO: j.country_code, isp: j.isp, org: j.org, asn: j.asn, tz: j.timezone, acc: null }; } },\r\n      { name: 'ip.sb', url: 'https:\/\/api.ip.sb\/geoip', map: function (j) {\r\n          if (!isValidIP(j.ip)) return null;\r\n          return { ip: j.ip, lat: num(j.latitude), lon: num(j.longitude), city: j.city, region: j.region, country: j.country, cISO: j.country_code, isp: j.isp || j.organization, org: j.organization, asn: j.asn ? 'AS' + j.asn : null, tz: j.timezone, acc: null }; } },\r\n      { name: 'geolocation-db.com', url: 'https:\/\/geolocation-db.com\/json\/', map: function (j) {\r\n          var ip = j.IPv4 || j.IPv6; if (!isValidIP(ip)) return null;\r\n          return { ip: ip, lat: num(j.latitude), lon: num(j.longitude), city: j.city, region: j.state, country: j.country_name, cISO: j.country_code, isp: null, org: null, asn: null, tz: null, acc: null }; } }\r\n    );\r\n\r\n    \/* Last-resort location: browser timezone -> city -> coordinates (works even if every IP API is blocked) *\/\r\n    function geocodeName(q) {\r\n      return fetchJSON('https:\/\/geocoding-api.open-meteo.com\/v1\/search?count=1&language=en&name=' + encodeURIComponent(q), 7000).then(function (j) {\r\n        var r = j && j.results && j.results[0]; if (!r) throw new Error('none');\r\n        return { lat: r.latitude, lon: r.longitude, city: r.name, region: r.admin1, country: r.country, cISO: r.country_code };\r\n      }).catch(function () {\r\n        return fetchJSON('https:\/\/nominatim.openstreetmap.org\/search?format=jsonv2&limit=1&addressdetails=1&q=' + encodeURIComponent(q), 8000).then(function (j) {\r\n          var r = j && j[0]; if (!r) throw new Error('none'); var a = r.address || {};\r\n          return { lat: +r.lat, lon: +r.lon, city: a.city || a.town || a.village || r.name, region: a.state, country: a.country, cISO: (a.country_code || '').toUpperCase() };\r\n        });\r\n      });\r\n    }\r\n    function tzFallback() {\r\n      var tz = ''; try { tz = Intl.DateTimeFormat().resolvedOptions().timeZone || ''; } catch (e) {}\r\n      var name = tz.split('\/').pop().replace(\/_\/g, ' ');\r\n      if (!name || \/^(UTC|GMT|Etc)\/i.test(tz)) return Promise.resolve(null);\r\n      return geocodeName(name).then(function (r) { r.accM = 40000; r.tz = tz; return r; }).catch(function () { return null; });\r\n    }\r\n    function resolveGeoWithFallback() {\r\n      return resolveGeoConsensus().then(function (g) {\r\n        if (g.ok) return g;\r\n        return tzFallback().then(function (f) {\r\n          if (!f) return g;\r\n          f.ok = false; f.ip = g.ip || null; f.all = g.all; return f;\r\n        });\r\n      });\r\n    }\r\n\r\n    function runSources(ipForPath) {\r\n      return Promise.all(GEO_SOURCES.map(function (s) {\r\n        var url = ipForPath ? IP_URLS[s.name].replace('{ip}', encodeURIComponent(ipForPath)) : s.url;\r\n        return fetchJSON(url, 7000)\r\n          .then(function (j) { var v = s.map(j); if (!v || !isFinite(v.lat) || !isFinite(v.lon)) throw new Error('no coordinates'); v.name = s.name; return v; })\r\n          .catch(function (e) {\r\n            try { console.warn('[AssistYU geo] ' + s.name + ' failed:', e && e.message ? e.message : e); } catch (x) {}\r\n            return { name: s.name, fail: true };\r\n          });\r\n      }));\r\n    }\r\n    \/\/ Get the public IP from several independent endpoints (first one that answers wins)\r\n    function getPublicIP() {\r\n      var tries = [\r\n        function () { return fetchJSON('https:\/\/api64.ipify.org?format=json', 6000).then(function (j) { return j.ip; }); },\r\n        function () { return fetchJSON('https:\/\/api.ipify.org?format=json', 6000).then(function (j) { return j.ip; }); },\r\n        function () { return fetch('https:\/\/www.cloudflare.com\/cdn-cgi\/trace', { cache: 'no-store' }).then(function (r) { return r.text(); }).then(function (t) { var m = t.match(\/ip=(\\S+)\/); return m && m[1]; }); },\r\n        function () { return fetchJSON('https:\/\/api.country.is\/', 6000).then(function (j) { return j.ip; }); }\r\n      ];\r\n      var p = Promise.reject(new Error('start'));\r\n      tries.forEach(function (t) {\r\n        p = p.catch(function () { return t().then(function (ip) { if (!isValidIP(ip)) throw new Error('bad ip'); return ip; }); });\r\n      });\r\n      return p;\r\n    }\r\n    function resolveGeoConsensus() {\r\n      return runSources(null).then(function (results) {\r\n        if (results.some(function (r) { return !r.fail; })) return results;\r\n        \/\/ every direct endpoint failed -> get the IP another way, then geolocate that IP\r\n        return getPublicIP().then(function (ip) {\r\n          return runSources(ip).then(function (r2) { r2.ipFound = ip; return r2; });\r\n        }).catch(function () { return results; });\r\n      }).then(function (results) {\r\n        var ok = results.filter(function (r) { return !r.fail; });\r\n        if (!ok.length) return { ok: false, ip: results.ipFound || null, sources: results, all: results };\r\n\r\n        \/\/ 1) rough median of ALL sources\r\n        var mLat = median(ok.map(function (r) { return r.lat; }));\r\n        var mLon = median(ok.map(function (r) { return r.lon; }));\r\n        \/\/ 2) OUTLIER REJECTION: keep only sources within max(2*MAD, 25km) of the median\r\n        var dists = ok.map(function (r) { return distM(mLat, mLon, r.lat, r.lon); });\r\n        var mad = median(dists);\r\n        var keepThresh = Math.max(mad * 2, 25000);\r\n        var cluster = ok.filter(function (r) { return distM(mLat, mLon, r.lat, r.lon) <= keepThresh; });\r\n        if (cluster.length < 1) cluster = ok;\r\n\r\n        \/\/ 3) consensus = median of the tight cluster\r\n        var cLat = median(cluster.map(function (r) { return r.lat; }));\r\n        var cLon = median(cluster.map(function (r) { return r.lon; }));\r\n        \/\/ 4) accuracy = spread of the KEPT cluster, capped sensibly\r\n        var spread = cluster.length > 1\r\n          ? Math.max.apply(null, cluster.map(function (r) { return distM(cLat, cLon, r.lat, r.lon); }))\r\n          : 0;\r\n        var reported = Math.min.apply(null, cluster.map(function (r) { return r.acc || 999999; }));\r\n        if (!isFinite(reported)) reported = 0;\r\n        var accM = spread > 0 ? Math.max(spread, 3000) : (reported && reported < 60000 ? reported : 5000);\r\n        accM = Math.min(accM, 60000);\r\n\r\n        \/\/ richest record for text fields (prefer one with isp\/asn, and one with a city)\r\n        var best = cluster.filter(function (r) { return r.isp && r.city; })[0] || cluster.filter(function (r) { return r.isp; })[0] || cluster[0];\r\n        var cityRec = cluster.filter(function (r) { return r.city; })[0] || best;\r\n        return {\r\n          ok: true, ip: best.ip, lat: cLat, lon: cLon, accM: accM,\r\n          city: best.city || cityRec.city, region: best.region || cityRec.region, country: best.country || cityRec.country, cISO: best.cISO || cityRec.cISO,\r\n          isp: best.isp, org: best.org, asn: best.asn, tz: best.tz || cityRec.tz,\r\n          sources: cluster, all: results\r\n        };\r\n      });\r\n    }\r\n\r\n    \/* ============================= DATA COLLECTION ============================= *\/\r\n    function startDataCollection() {\r\n      D = {\r\n        ip: null, city: null, region: null, country: null, cISO: null, lat: null, lon: null, locAcc: null,\r\n        geoSources: [], isp: null, org: null, asn: null, tz: null, approx: false,\r\n        proto: location.protocol === 'https:' ? 'https' : 'http',\r\n        dnt: navigator.doNotTrack === '1' || window.doNotTrack === '1' || navigator.doNotTrack === 'yes',\r\n        ua: navigator.userAgent, lang: navigator.language,\r\n        langs: navigator.languages ? Array.from(navigator.languages) : [],\r\n        sW: screen.width, sH: screen.height, cd: screen.colorDepth, pr: window.devicePixelRatio || 1,\r\n        wIPs: [], gpu: null, ipOK: false,\r\n        hc: navigator.hardwareConcurrency || null, dm: navigator.deviceMemory || null,\r\n        mt: navigator.maxTouchPoints || 0, ck: navigator.cookieEnabled,\r\n        pc: navigator.plugins ? navigator.plugins.length : 0,\r\n        effType: null, downlink: null, rtt: null, saveData: false, online: navigator.onLine,\r\n        webdriver: !!navigator.webdriver, brTz: null, tzMatch: null,\r\n        battLevel: null, battCharging: null, langMatch: null,\r\n        shodanPorts: [], shodanVulns: [], shodanTags: [], shodanCpes: [], shodanOK: false,\r\n        vpnDetected: false, proxyDetected: false, torDetected: false, hostingDetected: false,\r\n        blacklisted: false, blacklistCount: 0, blacklistSources: '',\r\n        canvasHash: null, audioHash: null, fontCount: 0, fontList: '',\r\n        speedMbps: null, speedMs: null, speedBytes: 0, riskScore: 0, riskGrade: 'F'\r\n      };\r\n\r\n      \/* canvas fingerprint *\/\r\n      try {\r\n        var cc = document.createElement('canvas'); cc.width = 280; cc.height = 60;\r\n        var cctx = cc.getContext('2d');\r\n        cctx.textBaseline = 'top'; cctx.font = '14px Arial';\r\n        cctx.fillStyle = '#f60'; cctx.fillRect(0, 0, 280, 60);\r\n        cctx.fillStyle = '#069'; cctx.fillText('AssistYU fingerprint', 2, 2);\r\n        cctx.fillStyle = 'rgba(102,204,0,0.7)'; cctx.fillText('AssistYU fingerprint', 4, 4);\r\n        D.canvasHash = cc.toDataURL().slice(-128);\r\n        var h = 0;\r\n        for (var ci = 0; ci < D.canvasHash.length; ci++) { h = ((h << 5) - h) + D.canvasHash.charCodeAt(ci); h |= 0; }\r\n        D.canvasHash = h.toString(36);\r\n      } catch (e) {}\r\n\r\n      \/* audio *\/\r\n      try {\r\n        var Ac = window.OfflineAudioContext || window.webkitOfflineAudioContext;\r\n        if (Ac) {\r\n          var ac = new Ac(1, 44100, 44100);\r\n          var osc = ac.createOscillator(); osc.type = 'triangle';\r\n          osc.frequency.setValueAtTime(10000, ac.currentTime);\r\n          var comp = ac.createDynamicsCompressor();\r\n          osc.connect(comp); comp.connect(ac.destination); osc.start(0);\r\n          ac.startRendering().then(function(buf) {\r\n            var d = buf.getChannelData(0).slice(4500, 5000), sum = 0;\r\n            for (var ai = 0; ai < d.length; ai++) sum += Math.abs(d[ai]);\r\n            D.audioHash = Math.round(sum * 1000).toString(36);\r\n          }).catch(function() {});\r\n        }\r\n      } catch (e) {}\r\n\r\n      \/* fonts *\/\r\n      try {\r\n        var testFonts = ['Arial','Verdana','Helvetica','Times New Roman','Courier New','Georgia','Palatino','Garamond','Comic Sans MS','Impact','Lucida Console','Tahoma','Trebuchet MS','Calibri','Cambria','Segoe UI','Roboto','Open Sans','Lato','Ubuntu','Fira Code','Consolas','Menlo','Monaco'];\r\n        var tc = document.createElement('span');\r\n        tc.style.cssText = 'position:absolute;left:-9999px;font-size:72px;font-weight:bold;letter-spacing:0;opacity:0;';\r\n        tc.textContent = 'mmmmmmmmmmlli';\r\n        document.body.appendChild(tc);\r\n        var baseW = tc.offsetWidth, found = [];\r\n        testFonts.forEach(function(f) { tc.style.fontFamily = '\"' + f + '\",monospace'; if (tc.offsetWidth !== baseW) found.push(f); });\r\n        document.body.removeChild(tc);\r\n        D.fontCount = found.length; D.fontList = found.join(', ');\r\n      } catch (e) {}\r\n\r\n      \/* IP geo \u2014 MULTI-SOURCE CONSENSUS + timezone fallback *\/\r\n      var ipF = resolveGeoWithFallback().then(function (g) {\r\n        D.geoSources = g.all || g.sources || [];\r\n        if (g.ok) {\r\n          D.ip = g.ip; D.city = g.city; D.region = g.region; D.country = g.country; D.cISO = g.cISO;\r\n          D.lat = g.lat; D.lon = g.lon; D.locAcc = g.accM;\r\n          D.isp = g.isp; D.org = g.org; D.asn = g.asn; D.tz = g.tz;\r\n          D.ipOK = true;\r\n        } else {\r\n          D.ipOK = false;\r\n          if (g.ip && isValidIP(g.ip)) { D.ip = g.ip; D.ipOK = true; }\r\n          if (typeof g.lat === 'number' && typeof g.lon === 'number') {\r\n            D.lat = g.lat; D.lon = g.lon; D.locAcc = g.accM; D.city = g.city || null; D.region = g.region || null;\r\n            D.country = g.country || null; D.cISO = g.cISO || null; D.tz = D.tz || g.tz || null; D.approx = true;\r\n          }\r\n        }\r\n      }).catch(function () { D.ipOK = false; });\r\n\r\n      \/* WebRTC *\/\r\n      var wP = new Promise(function(res) {\r\n        try {\r\n          var pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] });\r\n          var f = new Set(); pc.createDataChannel('');\r\n          pc.onicecandidate = function(e) {\r\n            if (!e.candidate) { pc.close(); res(Array.from(f)); return; }\r\n            var ip = e.candidate.candidate.split(' ')[4];\r\n            if (ip && (ip.match(\/^(\\d{1,3}\\.){3}\\d{1,3}$\/) || ip.indexOf(':') > -1)) { if (!ip.startsWith('0.0.0.0')) f.add(ip); }\r\n          };\r\n          pc.createOffer().then(function(o) { pc.setLocalDescription(o); });\r\n          setTimeout(function() { res(Array.from(f)); try { pc.close(); } catch (e) {} }, 1400);\r\n        } catch (err) { res([]); }\r\n      });\r\n\r\n      \/* connection API *\/\r\n      try {\r\n        var conn = navigator.connection || navigator.mozConnection || navigator.webkitConnection;\r\n        if (conn) { D.effType = conn.effectiveType || null; D.downlink = conn.downlink != null ? conn.downlink : null; D.rtt = conn.rtt != null ? conn.rtt : null; D.saveData = !!conn.saveData; }\r\n      } catch (e) {}\r\n\r\n      \/* speed test *\/\r\n      var speedP = new Promise(function(res) {\r\n        try {\r\n          var chunks = [\r\n            { url: 'https:\/\/speed.cloudflare.com\/__down?bytes=5000000', size: 5000000 },\r\n            { url: 'https:\/\/speed.cloudflare.com\/__down?bytes=10000000', size: 10000000 },\r\n            { url: 'https:\/\/speed.cloudflare.com\/__down?bytes=10000000', size: 10000000 }\r\n          ];\r\n          var totalBytes = 0, t0 = 0, done = false;\r\n          function finish() {\r\n            if (done) return; done = true;\r\n            var elapsed = (performance.now() - t0) \/ 1000;\r\n            if (elapsed > 0.5 && totalBytes > 0) { D.speedMbps = ((totalBytes * 8) \/ elapsed \/ 1000000).toFixed(1); D.speedMs = Math.round(elapsed * 1000); D.speedBytes = totalBytes; }\r\n            res();\r\n          }\r\n          var timeout = setTimeout(finish, 12000);\r\n          t0 = performance.now();\r\n          var chain = Promise.resolve();\r\n          chunks.forEach(function(c) {\r\n            chain = chain.then(function() {\r\n              if (done) return;\r\n              return fetch(c.url, { cache: 'no-store' }).then(function(r) { return r.arrayBuffer(); }).then(function(buf) { if (!done) totalBytes += buf.byteLength; }).catch(function() {});\r\n            });\r\n          });\r\n          chain.then(function() { clearTimeout(timeout); finish(); });\r\n        } catch (e) { res(); }\r\n      });\r\n\r\n      \/* timezone *\/\r\n      try { D.brTz = Intl.DateTimeFormat().resolvedOptions().timeZone || null; } catch (e) {}\r\n\r\n      \/* battery *\/\r\n      var battP = new Promise(function(res) {\r\n        try {\r\n          if (navigator.getBattery) { navigator.getBattery().then(function(b) { D.battLevel = b.level != null ? Math.round(b.level * 100) : null; D.battCharging = !!b.charging; res(); }).catch(function() { res(); }); }\r\n          else { res(); }\r\n        } catch (e) { res(); }\r\n      });\r\n\r\n      \/* GPU *\/\r\n      try {\r\n        var glCanvas = document.createElement('canvas');\r\n        var gl = glCanvas.getContext('webgl') || glCanvas.getContext('experimental-webgl');\r\n        if (gl) { var db = gl.getExtension('WEBGL_debug_renderer_info'); if (db) D.gpu = gl.getParameter(db.UNMASKED_RENDERER_WEBGL); }\r\n      } catch (e) {}\r\n\r\n      var shodanP = ipF.then(function() {\r\n        if (!D.ip || !isValidIP(D.ip)) return;\r\n        return fetch('https:\/\/internetdb.shodan.io\/' + D.ip, { cache: 'no-store' }).then(function(r) { return r.json(); }).then(function(j) {\r\n          D.shodanPorts = j.ports || []; D.shodanVulns = j.vulns || []; D.shodanTags = j.tags || []; D.shodanCpes = j.cpes || []; D.shodanOK = true;\r\n        }).catch(function() {});\r\n      });\r\n\r\n      var blacklistP = ipF.then(function() {\r\n        if (!D.ip || !isValidIP(D.ip)) return;\r\n        return fetch('https:\/\/hackmyip.com\/api\/blacklist?ip=' + D.ip, { cache: 'no-store' }).then(function(r) { return r.json(); }).then(function(j) {\r\n          if (j && j.blacklisted !== undefined) { D.blacklisted = !!j.blacklisted; D.blacklistCount = j.listed_on || 0; D.blacklistSources = j.sources ? j.sources.join(', ') : ''; }\r\n        }).catch(function() {});\r\n      });\r\n\r\n      var ipprivP = ipF.then(function() {\r\n        if (!D.ip || !isValidIP(D.ip)) return;\r\n        return fetch('https:\/\/api.ippriv.com\/api\/security\/' + D.ip, { cache: 'no-store' }).then(function(r) { return r.json(); }).then(function(j) {\r\n          if (j) { D.vpnDetected = !!j.isVPN; D.proxyDetected = !!j.isProxy; D.torDetected = !!j.isTor; D.hostingDetected = !!j.isHosting; }\r\n        }).catch(function() {});\r\n      });\r\n\r\n      Promise.all([ipF, wP, battP, shodanP, blacklistP, ipprivP, speedP]).then(function(r) {\r\n        D.wIPs = r[1];\r\n        if (D.tz && D.brTz) {\r\n          var ipCity = D.tz.split('\/').pop().replace(\/_\/g, ' ');\r\n          var brCity = D.brTz.split('\/').pop().replace(\/_\/g, ' ');\r\n          D.tzMatch = ipCity.toLowerCase() === brCity.toLowerCase();\r\n        }\r\n        if (D.cISO && D.lang) { var langCountry = D.lang.split('-')[1]; if (langCountry) D.langMatch = langCountry.toUpperCase() === D.cISO.toUpperCase(); }\r\n        D.riskScore = calcRisk();\r\n        D.riskGrade = D.riskScore >= 80 ? 'F' : D.riskScore >= 60 ? 'D' : D.riskScore >= 40 ? 'C' : D.riskScore >= 20 ? 'B' : 'A';\r\n        setTimeout(reveal, Math.max(0, STEPS.length * sd + 500));\r\n      });\r\n    }\r\n\r\n    function calcRisk() {\r\n      var s = 0;\r\n      if (D.ipOK && D.ip) s += 8;\r\n      if (D.ipOK && (D.city || D.region || D.country)) s += 10;\r\n      if (D.isp) s += 3;\r\n      if (D.proto !== 'https') s += 12;\r\n      if (D.wIPs.length > 0) s += 15;\r\n      if (D.gpu) s += 4;\r\n      if (D.hc) s += 3;\r\n      if (D.dm) s += 2;\r\n      if (D.canvasHash) s += 5;\r\n      if (D.audioHash) s += 4;\r\n      if (D.fontCount > 15) s += 3;\r\n      if (D.webdriver) s += 10;\r\n      if (D.tzMatch === false) s += 6;\r\n      if (D.langMatch === false) s += 4;\r\n      if (D.vpnDetected) s += 8;\r\n      if (D.proxyDetected) s += 6;\r\n      if (D.torDetected) s += 10;\r\n      if (D.hostingDetected) s += 5;\r\n      if (D.blacklisted) s += Math.min(D.blacklistCount * 2, 12);\r\n      if (D.shodanVulns.length > 0) s += Math.min(D.shodanVulns.length * 3, 12);\r\n      if (D.shodanPorts.length > 5) s += 3;\r\n      if (!D.dnt) s += 2;\r\n      if (D.ck) s += 2;\r\n      if (D.pc > 0) s += 2;\r\n      if (!D.online) s += 10;\r\n      return Math.min(s, 100);\r\n    }\r\n\r\n    function ua2os(u) { if (\/Windows NT 10\/.test(u)) return 'Windows 10\/11'; if (\/Windows NT\/.test(u)) return 'Windows'; if (\/Mac OS X\/.test(u)) return 'macOS'; if (\/Android\/.test(u)) return 'Android ' + (u.match(\/Android\\s([\\d.]+)\/) || ['',''])[1]; if (\/iPhone|iPad|iPod\/.test(u)) return 'iOS'; if (\/Linux\/.test(u)) return 'Linux'; return 'Unknown'; }\r\n    function ua2br(u) { if (\/Edg\\\/\/.test(u)) return 'Edge ' + (u.match(\/Edg\\\/([\\d.]+)\/) || ['',''])[1]; if (\/OPR\\\/\/.test(u)) return 'Opera ' + (u.match(\/OPR\\\/([\\d.]+)\/) || ['',''])[1]; if (\/Chrome\\\/\/.test(u) && !\/Chromium\/.test(u)) return 'Chrome ' + (u.match(\/Chrome\\\/([\\d.]+)\/) || ['',''])[1]; if (\/Firefox\\\/\/.test(u)) return 'Firefox ' + (u.match(\/Firefox\\\/([\\d.]+)\/) || ['',''])[1]; if (\/Safari\\\/\/.test(u) && !\/Chrome\/.test(u)) return 'Safari'; return 'Unknown'; }\r\n\r\n    var HOST = ['amazon','aws','google cloud','microsoft','azure','digitalocean','ovh','hetzner','linode','vultr','cloudflare','datacamp','leaseweb','choopa','contabo','oracle cloud','scaleway','hosting','colo','datacenter','alibaba'];\r\n\r\n    function mkC(ico, lbl, vid, sid, cls) {\r\n      return '<div class=\"card c-' + (cls || 'cyan') + '\" data-p=\"' + vid + '\"><div class=\"ci\">' + ico + '<\/div><div class=\"cb\"><div class=\"cl\">' + lbl + '<\/div><div class=\"cv\" id=\"' + vid + '\">\u2014<\/div><div class=\"cs\" id=\"' + sid + '\"><\/div><\/div><\/div>';\r\n    }\r\n    var IC = {\r\n      g: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"9\"\/><path d=\"M2.5 12h19M12 2.5c2.5 2.7 3.8 6 3.8 9.5s-1.3 6.8-3.8 9.5c-2.5-2.7-3.8-6-3.8-9.5S9.5 5.2 12 2.5Z\"\/><\/svg>',\r\n      s: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><rect x=\"2\" y=\"7\" width=\"20\" height=\"4\" rx=\"1\"\/><rect x=\"2\" y=\"13\" width=\"20\" height=\"4\" rx=\"1\"\/><\/svg>',\r\n      m: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M12 22s7-6.2 7-12a7 7 0 1 0-14 0c0 5.8 7 12 7 12Z\"\/><circle cx=\"12\" cy=\"10\" r=\"2.5\"\/><\/svg>',\r\n      w: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M5 12.5a11 11 0 0 1 14 0M8 15.8a6.5 6.5 0 0 1 8 0M11.5 19a2 2 0 0 1 1 0\"\/><\/svg>',\r\n      l: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><rect x=\"4\" y=\"10\" width=\"16\" height=\"10\" rx=\"2\"\/><path d=\"M8 10V7a4 4 0 0 1 8 0v3\"\/><\/svg>',\r\n      sh: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M12 2 3 6v6c0 5.2 3.8 9.8 9 11 5.2-1.2 9-5.8 9-11V6l-9-4Z\"\/><\/svg>',\r\n      ch: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M4 4h16v12H8l-4 4V4Z\"\/><\/svg>',\r\n      mo: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><rect x=\"3\" y=\"4\" width=\"18\" height=\"12\" rx=\"2\"\/><path d=\"M8 20h12M12 16v4\"\/><\/svg>',\r\n      cp: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"2\"\/><rect x=\"9\" y=\"9\" width=\"6\" height=\"6\"\/><path d=\"M9 1v3M15 1v3M9 20v3M15 20v3M1 9h3M1 15h3M20 9h3M20 15h3\"\/><\/svg>',\r\n      z: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\"\/><\/svg>',\r\n      ck: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M22 11.08V12a10 10 0 1 1-5.93-9.14\"\/><polyline points=\"22 4 12 14.01 9 11.01\"\/><\/svg>',\r\n      e: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8S1 12 1 12z\"\/><circle cx=\"12\" cy=\"12\" r=\"3\"\/><\/svg>',\r\n      f: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M12 11c0 5-2 8-2 8\"\/><path d=\"M16 11c0 3-1 5-2 7\"\/><path d=\"M8 11c0 3 1 5 2 7\"\/><path d=\"M4 11a8 8 0 0 1 16 0\"\/><\/svg>',\r\n      r: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"2\"\/><path d=\"M4.93 19.07a10 10 0 0 1 0-14.14M7.76 16.24a6 6 0 0 1 0-8.48M16.24 7.76a6 6 0 0 1 0 8.48M19.07 4.93a10 10 0 0 1 0 14.14\"\/><\/svg>',\r\n      tz: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><path d=\"M12 6v6l4 2\"\/><\/svg>',\r\n      bt: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><rect x=\"2\" y=\"7\" width=\"18\" height=\"12\" rx=\"2\"\/><path d=\"M22 11v4\"\/><\/svg>',\r\n      bot: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><rect x=\"4\" y=\"8\" width=\"16\" height=\"12\" rx=\"2\"\/><path d=\"M9 8V6a3 3 0 0 1 6 0v2\"\/><circle cx=\"9\" cy=\"14\" r=\"1\"\/><circle cx=\"15\" cy=\"14\" r=\"1\"\/><\/svg>',\r\n      port: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><rect x=\"2\" y=\"2\" width=\"20\" height=\"8\" rx=\"2\"\/><rect x=\"2\" y=\"14\" width=\"20\" height=\"8\" rx=\"2\"\/><path d=\"M6 6h.01M6 18h.01\"\/><\/svg>',\r\n      vuln: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\"\/><path d=\"M9 12l2 2 4-4\"\/><\/svg>',\r\n      blk: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><circle cx=\"12\" cy=\"12\" r=\"10\"\/><path d=\"M4.93 4.93l14.14 14.14\"\/><\/svg>',\r\n      vpn: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z\"\/><\/svg>',\r\n      lang: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M5 8l6 6\"\/><path d=\"M4 14l6-6 2-3\"\/><path d=\"M2 5h12\"\/><path d=\"M7 2v3\"\/><path d=\"M22 22l-5-10-5 10\"\/><path d=\"M14 18h6\"\/><\/svg>',\r\n      cnv: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"\/><circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"\/><path d=\"M21 15l-5-5L5 21\"\/><\/svg>',\r\n      aud: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M9 18V5l12-2v13\"\/><circle cx=\"6\" cy=\"18\" r=\"3\"\/><circle cx=\"18\" cy=\"16\" r=\"3\"\/><\/svg>',\r\n      fn: '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><polyline points=\"4 7 4 4 20 4 20 7\"\/><line x1=\"9\" y1=\"20\" x2=\"15\" y2=\"20\"\/><line x1=\"12\" y1=\"4\" x2=\"12\" y2=\"20\"\/><\/svg>'\r\n    };\r\n\r\n    var ORIG = {};\r\n    function setOrig(id, cardCls, valCls) { ORIG[id] = { card: cardCls, val: valCls }; }\r\n\r\n    \/* ============================= MAP (Leaflet, self-healing) ============================= *\/\r\n    var LMap = null, LMarker = null, LCircle = null, tileLayer = null, tileIdx = -1, mapReady = false, frameMode = false;\r\n    var lastPt = null, baseSub = '', preciseLabel = null, geoWatch = null;\r\n    \/* FIXED: Carto's dark tiles now require a paid API key (free anonymous access\r\n       was discontinued), which was silently rendering a watermarked placeholder\r\n       instead of failing with a real HTTP error \u2014 so the fallback logic below\r\n       never triggered. OpenStreetMap (with the existing .ayu-osm-dark CSS filter\r\n       for the dark theme) is now the primary source; Esri remains the fallback.\r\n       Both are free, key-less, and already whitelisted in the CSP. *\/\r\n    var TILES = [\r\n      { u: 'https:\/\/{s}.tile.openstreetmap.org\/{z}\/{x}\/{y}.png', o: { subdomains: 'abc', maxZoom: 19, className: 'ayu-osm-dark', attribution: '&copy; OpenStreetMap contributors' } },\r\n      { u: 'https:\/\/server.arcgisonline.com\/ArcGIS\/rest\/services\/World_Street_Map\/MapServer\/tile\/{z}\/{y}\/{x}', o: { maxZoom: 19, attribution: 'Tiles &copy; Esri' } }\r\n    ];\r\n    function loadLeaflet() {\r\n      return new Promise(function (res) {\r\n        var t = 0;\r\n        (function w() { if (window.L) return res(true); t += 100; if (t > 8000) return res(false); setTimeout(w, 100); })();\r\n      });\r\n    }\r\n    function showFrame() { \/* ultimate fallback: OpenStreetMap embed (no library needed) *\/\r\n      frameMode = true;\r\n      var w = document.getElementById('mapw'), f = document.getElementById('mapFrame');\r\n      if (!f) {\r\n        f = document.createElement('iframe'); f.id = 'mapFrame'; f.title = 'Map';\r\n        f.style.cssText = 'position:absolute;inset:0;width:100%;height:100%;border:0;z-index:1;background:#0b1130';\r\n        w.appendChild(f);\r\n      }\r\n      var p = lastPt || { lat: 20, lon: 0, accM: 0 }, d = p.accM ? Math.max(p.accM \/ 111000 * 2, 0.01) : 60;\r\n      var bb = [p.lon - d, p.lat - d * 0.6, p.lon + d, p.lat + d * 0.6].map(function (v) { return v.toFixed(5); }).join('%2C');\r\n      f.src = 'https:\/\/www.openstreetmap.org\/export\/embed.html?bbox=' + bb + '&layer=mapnik' + (p.accM ? '&marker=' + p.lat + '%2C' + p.lon : '');\r\n    }\r\n    function nextTiles() {\r\n      if (tileLayer) { try { LMap.removeLayer(tileLayer); } catch (e) {} tileLayer = null; }\r\n      tileIdx++;\r\n      if (tileIdx >= TILES.length) { showFrame(); return; }\r\n      var T = TILES[tileIdx], idx = tileIdx, loads = 0, errs = 0;\r\n      tileLayer = L.tileLayer(T.u, T.o).addTo(LMap);\r\n      tileLayer.on('tileload', function () { loads++; });\r\n      tileLayer.on('tileerror', function () { errs++; if (!loads && errs >= 3 && idx === tileIdx) nextTiles(); });\r\n      setTimeout(function () { if (!loads && idx === tileIdx) nextTiles(); }, 6000);\r\n    }\r\n    function initLeaflet() {\r\n      LMap = L.map('mapLeaf', { zoomControl: false, attributionControl: true, worldCopyJump: true, minZoom: 2 }).setView([20, 0], 2);\r\n      nextTiles();\r\n      if (window.ResizeObserver) { try { new ResizeObserver(function () { if (LMap) LMap.invalidateSize(); }).observe(document.getElementById('mapw')); } catch (e) {} }\r\n      window.addEventListener('resize', function () { if (LMap) LMap.invalidateSize(); });\r\n      mapReady = true;\r\n    }\r\n    function fmtAcc(accM) {\r\n      return accM >= 1000 ? (accM \/ 1000).toFixed(accM < 10000 ? 1 : 0) + ' km' : Math.round(accM) + ' m';\r\n    }\r\n    \/* mode: 'precise' (GPS) | 'ip' (IP consensus) | 'approx' (timezone estimate) | 'none' (nothing known yet) *\/\r\n    function renderMapPoint(lat, lon, accM, label, mode) {\r\n      var precise = mode === 'precise';\r\n      lastPt = { lat: lat, lon: lon, accM: mode === 'none' ? 0 : accM };\r\n      var kinds = { precise: ' \u00b7 GPS\/device precise', ip: ' \u00b7 IP-based estimate', approx: ' \u00b7 timezone-based estimate' };\r\n      document.getElementById('map-loc-t').textContent = label || 'Unknown location';\r\n      document.getElementById('map-label-loc').textContent = mode === 'none' ? 'Locating\u2026' : (label || 'Unknown location');\r\n      baseSub = mode === 'none' ? 'Waiting for a location \u2014 click \"Precise location\"'\r\n        : Math.abs(lat).toFixed(precise ? 6 : 4) + '\u00b0' + (lat >= 0 ? 'N' : 'S') + ', ' + Math.abs(lon).toFixed(precise ? 6 : 4) + '\u00b0' + (lon >= 0 ? 'E' : 'W') + (kinds[mode] || '');\r\n      document.getElementById('map-loc-s').textContent = baseSub;\r\n      var badge = document.getElementById('map-acc');\r\n      badge.innerHTML = mode === 'none' ? 'Accuracy: <b>\u2014<\/b>' : 'Accuracy: <b>\u00b1' + fmtAcc(accM) + '<\/b>';\r\n      badge.className = 'map-acc' + (precise ? ' precise' : '');\r\n\r\n      if (frameMode) { showFrame(); return; }\r\n      loadLeaflet().then(function (ok) {\r\n        if (!ok) { showFrame(); return; }\r\n        if (!LMap) initLeaflet();\r\n        if (frameMode) { showFrame(); return; }\r\n        if (LMarker) { LMap.removeLayer(LMarker); LMarker = null; }\r\n        if (LCircle) { LMap.removeLayer(LCircle); LCircle = null; }\r\n        if (mode === 'none') { LMap.setView([20, 0], 2); return; }\r\n        var color = precise ? '#22e6a8' : (mode === 'approx' ? '#ffb84d' : '#4f6ef7');\r\n        LCircle = L.circle([lat, lon], { radius: accM, color: color, fillColor: color, fillOpacity: 0.12, weight: 1 }).addTo(LMap);\r\n        LMarker = L.circleMarker([lat, lon], { radius: 7, color: color, fillColor: color, fillOpacity: 1, weight: 2 }).addTo(LMap);\r\n        LMap.invalidateSize();\r\n        try { LMap.fitBounds(LCircle.getBounds(), { maxZoom: precise ? 18 : 13, padding: [40, 40] }); } catch (e) { LMap.setView([lat, lon], precise ? 17 : 10); }\r\n        setTimeout(function () { if (LMap) LMap.invalidateSize(); }, 250);\r\n      });\r\n    }\r\n\r\n    var PRECISE_ICON = '<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><circle cx=\"12\" cy=\"12\" r=\"3\"\/><path d=\"M12 2v3M12 19v3M2 12h3M19 12h3\"\/><\/svg>';\r\n    \/* Precise location: GPS\/Wi-Fi with progressive refinement; falls back to low-accuracy mode *\/\r\n    function requestPrecise(auto) {\r\n      var btn = document.getElementById('preciseBtn'), sub = document.getElementById('map-loc-s');\r\n      function reset(t) { if (btn) { btn.disabled = false; btn.innerHTML = PRECISE_ICON + ' ' + t; } }\r\n      function note(t) { if (sub && !best) sub.textContent = baseSub + ' \u00b7 ' + t; }\r\n      if (!navigator.geolocation) { if (sub && !auto) sub.textContent = baseSub + ' \u00b7 GPS not supported by this browser'; return; }\r\n      if (geoWatch !== null) { navigator.geolocation.clearWatch(geoWatch); geoWatch = null; }\r\n      if (btn) { btn.disabled = true; btn.innerHTML = PRECISE_ICON + ' Locating\u2026'; }\r\n      var best = null, done = false, lowTried = false, labelAsked = false, timer = null;\r\n\r\n      function paint() { renderMapPoint(best.lat, best.lon, best.acc, preciseLabel || 'Your location', 'precise'); }\r\n      function card() {\r\n        var locEl = document.getElementById('v-loc'), pt = document.getElementById('ptog');\r\n        if (locEl && best && preciseLabel && !(pt && pt.checked)) {\r\n          locEl.textContent = preciseLabel;\r\n          var ls = document.getElementById('v-loc-s'); if (ls) ls.textContent = 'GPS \/ Wi-Fi precise \u00b7 \u00b1' + fmtAcc(best.acc);\r\n        }\r\n      }\r\n      function reverse() {\r\n        if (labelAsked) return; labelAsked = true;\r\n        fetchJSON('https:\/\/nominatim.openstreetmap.org\/reverse?format=jsonv2&zoom=18&lat=' + best.lat + '&lon=' + best.lon, 8000)\r\n          .then(function (j) {\r\n            var a = j.address || {};\r\n            preciseLabel = [a.road || a.pedestrian || a.suburb || a.neighbourhood, a.city || a.town || a.village || a.county, a.country].filter(Boolean).join(', ') || 'Your location';\r\n          })\r\n          .catch(function () { preciseLabel = 'Your precise location'; })\r\n          .then(function () { if (best) { paint(); card(); } });\r\n      }\r\n      function stop() { if (timer) clearTimeout(timer); if (geoWatch !== null) { navigator.geolocation.clearWatch(geoWatch); geoWatch = null; } }\r\n      function finish() { if (done) return; done = true; stop(); reset(best ? 'Precise on' : 'Precise location'); }\r\n      function fix(pos) {\r\n        var c = pos.coords; if (best && c.accuracy >= best.acc) return;\r\n        best = { lat: c.latitude, lon: c.longitude, acc: c.accuracy || 50 };\r\n        paint(); reverse(); card();\r\n        if (best.acc <= 20) finish();\r\n      }\r\n      function fail(err) {\r\n        if (done) return;\r\n        if (err && err.code === 1) {\r\n          done = true; stop(); reset('Precise location');\r\n          note('GPS blocked \u2014 allow Location for this site (lock icon in the address bar), then click \"Precise location\"');\r\n          return;\r\n        }\r\n        if (!lowTried && !best) {\r\n          lowTried = true; stop();\r\n          navigator.geolocation.getCurrentPosition(function (p) { fix(p); finish(); }, function () {\r\n            if (done) return; done = true; reset('Precise location'); note('GPS unavailable on this device \u2014 showing network estimate');\r\n          }, { enableHighAccuracy: false, timeout: 12000, maximumAge: 300000 });\r\n          return;\r\n        }\r\n        finish();\r\n      }\r\n      geoWatch = navigator.geolocation.watchPosition(fix, fail, { enableHighAccuracy: true, timeout: 20000, maximumAge: 0 });\r\n      timer = setTimeout(function () { if (best) finish(); }, 15000);\r\n    }\r\n    document.getElementById('preciseBtn').addEventListener('click', function () { requestPrecise(false); });\r\n    document.getElementById('zoomIn').addEventListener('click', function(){ if (LMap) LMap.zoomIn(); });\r\n    document.getElementById('zoomOut').addEventListener('click', function(){ if (LMap) LMap.zoomOut(); });\r\n\r\n    \/* ============================= REVEAL ============================= *\/\r\n    function reveal() {\r\n      radarRunning = false;\r\n      document.getElementById('scan-stage').style.display = 'none';\r\n      var org = ((D.isp || '') + ' ' + (D.org || '')).toLowerCase();\r\n      var hosted = HOST.some(function(k) { return org.indexOf(k) > -1; });\r\n      var leak = D.wIPs.length > 0;\r\n      var enc = D.proto === 'https';\r\n      var track = !D.dnt;\r\n      var isVpn = D.vpnDetected || D.proxyDetected || D.torDetected;\r\n\r\n      \/* gauge *\/\r\n      var rgFill = document.getElementById('rg-fill');\r\n      var rgNum = document.getElementById('rg-num');\r\n      var rgGrade = document.getElementById('rg-grade');\r\n      var rgSub = document.getElementById('rg-sub');\r\n      var circumference = 314.16;\r\n      var offset = circumference - (D.riskScore \/ 100) * circumference;\r\n      var gColor = D.riskScore >= 60 ? 'var(--danger)' : D.riskScore >= 30 ? 'var(--amber)' : 'var(--safe)';\r\n      setTimeout(function() { rgFill.style.strokeDashoffset = offset; rgFill.style.stroke = gColor; }, 100);\r\n      rgNum.textContent = D.riskScore;\r\n      var gradeText = D.riskGrade === 'F' ? 'Critical exposure' : D.riskGrade === 'D' ? 'High exposure' : D.riskGrade === 'C' ? 'Moderate exposure' : D.riskGrade === 'B' ? 'Low exposure' : 'Minimal exposure';\r\n      rgGrade.innerHTML = 'Grade ' + D.riskGrade + ' <span class=\"sub\">' + gradeText + '<\/span>';\r\n      rgGrade.style.color = gColor;\r\n\r\n      var rgParts = [];\r\n      if (leak) rgParts.push('WebRTC leak');\r\n      if (D.vpnDetected) rgParts.push('VPN detected');\r\n      if (D.torDetected) rgParts.push('Tor exit');\r\n      if (D.blacklisted) rgParts.push('On ' + D.blacklistCount + ' blacklists');\r\n      if (D.shodanVulns.length) rgParts.push(D.shodanVulns.length + ' CVEs');\r\n      if (D.webdriver) rgParts.push('Automation');\r\n      if (!enc) rgParts.push('Unencrypted');\r\n      rgSub.innerHTML = rgParts.length ? rgParts.map(function(t) {\r\n        var cls = 'tag';\r\n        if (t.indexOf('leak') > -1 || t.indexOf('Tor') > -1 || t.indexOf('CVEs') > -1 || t.indexOf('Unencrypted') > -1) cls += ' danger';\r\n        else if (t.indexOf('On ') > -1 || t.indexOf('Automation') > -1) cls += ' warn';\r\n        else cls += ' safe';\r\n        return '<span class=\"' + cls + '\">' + t + '<\/span>';\r\n      }).join('') : '<span class=\"tag safe\">No critical signals<\/span>';\r\n\r\n      updateHeroBlocks();\r\n\r\n      \/* cards *\/\r\n      var ipCls = D.ipOK && D.ip ? 'danger' : 'cyan';\r\n      var ispCls = D.ipOK && D.isp ? 'warn' : 'cyan';\r\n      var locCls = D.ipOK && (D.city || D.region || D.country) ? 'danger' : 'cyan';\r\n\r\n      document.getElementById('gnet').innerHTML = [\r\n        mkC(IC.g, 'Public IP address', 'v-ip', 'v-ip-s', ipCls),\r\n        mkC(IC.s, 'Internet provider (ISP)', 'v-isp', 'v-isp-s', ispCls),\r\n        mkC(IC.m, 'Approximate location', 'v-loc', 'v-loc-s', locCls)\r\n      ].join('');\r\n      setOrig('v-ip', ipCls, ipCls === 'danger' ? 'risk' : '');\r\n      setOrig('v-isp', ispCls, ispCls === 'warn' ? 'warn' : '');\r\n      setOrig('v-loc', locCls, locCls === 'danger' ? 'risk' : '');\r\n\r\n      var vpnCls = isVpn ? 'danger' : D.hostingDetected ? 'warn' : 'safe';\r\n      var blkCls = D.blacklisted ? 'danger' : 'safe';\r\n      var portCls = D.shodanPorts.length > 0 ? 'warn' : 'safe';\r\n      var vulnCls = D.shodanVulns.length > 0 ? 'danger' : 'safe';\r\n\r\n      document.getElementById('gth').innerHTML = [\r\n        mkC(IC.vpn, 'VPN \/ proxy \/ Tor', 'v-vpn', 'v-vpn-s', vpnCls),\r\n        mkC(IC.blk, 'IP blacklists', 'v-blk', 'v-blk-s', blkCls),\r\n        mkC(IC.port, 'Open ports', 'v-ports', 'v-ports-s', portCls),\r\n        mkC(IC.vuln, 'Known CVEs', 'v-vulns', 'v-vulns-s', vulnCls)\r\n      ].join('');\r\n      setOrig('v-vpn', vpnCls, isVpn ? 'risk' : 'safe');\r\n      setOrig('v-blk', blkCls, D.blacklisted ? 'risk' : 'safe');\r\n      setOrig('v-ports', portCls, D.shodanPorts.length > 0 ? 'warn' : 'safe');\r\n      setOrig('v-vulns', vulnCls, D.shodanVulns.length > 0 ? 'risk' : 'safe');\r\n\r\n      var brCls = 'warn', cpuCls = D.hc ? 'warn' : 'safe', memCls = D.dm ? 'warn' : 'safe';\r\n      var scrCls = 'warn', tchCls = 'cyan', battCls = 'cyan', tzCls = 'cyan';\r\n      var gpuCls = D.gpu ? 'warn' : 'cyan';\r\n      var connValCls = 'cyan';\r\n      if (D.speedMbps != null) { var sp = parseFloat(D.speedMbps); connValCls = sp >= 50 ? 'safe' : sp >= 10 ? 'cyan' : sp >= 2 ? 'warn' : 'danger'; }\r\n      else if (D.saveData) { connValCls = 'safe'; } else if (D.effType === 'slow-2g' || D.effType === '2g') { connValCls = 'warn'; }\r\n      var cnvCls = D.canvasHash ? 'warn' : 'cyan', audCls = D.audioHash ? 'warn' : 'cyan', fnCls = D.fontCount > 15 ? 'warn' : 'cyan';\r\n\r\n      document.getElementById('gdev').innerHTML = [\r\n        mkC(IC.mo, 'Browser & OS', 'v-br', 'v-br-s', brCls),\r\n        mkC(IC.cp, 'CPU cores', 'v-cpu', 'v-cpu-s', cpuCls),\r\n        mkC(IC.f, 'Device memory', 'v-mem', 'v-mem-s', memCls),\r\n        mkC(IC.z, 'Graphics processor', 'v-gpu', 'v-gpu-s', gpuCls),\r\n        mkC(IC.mo, 'Screen resolution', 'v-scr', 'v-scr-s', scrCls),\r\n        mkC(IC.r, 'Touch support', 'v-tch', 'v-tch-s', tchCls),\r\n        mkC(IC.bt, 'Battery level', 'v-bat', 'v-bat-s', battCls),\r\n        mkC(IC.tz, 'Browser timezone', 'v-tz', 'v-tz-s', tzCls),\r\n        mkC(IC.cnv, 'Canvas fingerprint', 'v-cnv', 'v-cnv-s', cnvCls),\r\n        mkC(IC.aud, 'Audio fingerprint', 'v-aud', 'v-aud-s', audCls),\r\n        mkC(IC.fn, 'Font enumeration', 'v-fn', 'v-fn-s', fnCls)\r\n      ].join('');\r\n      setOrig('v-br', brCls, 'warn');\r\n      setOrig('v-cpu', cpuCls, cpuCls === 'warn' ? 'warn' : 'safe');\r\n      setOrig('v-mem', memCls, memCls === 'warn' ? 'warn' : 'safe');\r\n      setOrig('v-gpu', gpuCls, gpuCls === 'warn' ? 'warn' : '');\r\n      setOrig('v-scr', scrCls, 'warn');\r\n      setOrig('v-tch', tchCls, '');\r\n      setOrig('v-bat', battCls, '');\r\n      setOrig('v-tz', tzCls, '');\r\n      setOrig('v-cnv', cnvCls, 'warn');\r\n      setOrig('v-aud', audCls, 'warn');\r\n      setOrig('v-fn', fnCls, '');\r\n\r\n      var encCls = enc ? 'safe' : 'danger';\r\n      var netCls = hosted ? 'warn' : 'danger';\r\n      var webCls = leak ? 'danger' : 'safe';\r\n      var dntCls = track ? 'warn' : 'safe';\r\n      var ckCls = D.ck ? 'warn' : 'safe';\r\n      var plgCls = D.pc > 0 ? 'warn' : 'safe';\r\n      var wdCls = D.webdriver ? 'danger' : 'safe';\r\n      var tzmCls = D.tzMatch === false ? 'warn' : D.tzMatch === true ? 'safe' : 'cyan';\r\n      var langCls = D.langMatch === false ? 'warn' : D.langMatch === true ? 'safe' : 'cyan';\r\n\r\n      document.getElementById('gsec').innerHTML = [\r\n        mkC(IC.l, 'Traffic encryption', 'v-enc', 'v-enc-s', encCls),\r\n        mkC(IC.sh, 'Network type', 'v-nty', 'v-nty-s', netCls),\r\n        mkC(IC.ch, 'WebRTC leak test', 'v-wrtc', 'v-wrtc-s', webCls),\r\n        mkC(IC.w, 'Connection quality', 'v-conn', 'v-conn-s', connValCls),\r\n        mkC(IC.e, 'Do not track \/ tracking', 'v-dnt', 'v-dnt-s', dntCls),\r\n        mkC(IC.ck, 'Cookies enabled', 'v-ck', 'v-ck-s', ckCls),\r\n        mkC(IC.f, 'Plugins installed', 'v-plg', 'v-plg-s', plgCls),\r\n        mkC(IC.bot, 'Automation detected', 'v-wd', 'v-wd-s', wdCls),\r\n        mkC(IC.tz, 'Timezone cross-check', 'v-tzm', 'v-tzm-s', tzmCls),\r\n        mkC(IC.lang, 'Language vs location', 'v-lang', 'v-lang-s', langCls)\r\n      ].join('');\r\n      setOrig('v-enc', encCls, enc ? 'safe' : 'risk');\r\n      setOrig('v-nty', netCls, hosted ? 'warn' : 'risk');\r\n      setOrig('v-wrtc', webCls, leak ? 'risk' : 'safe');\r\n      setOrig('v-conn', connValCls, connValCls === 'safe' ? 'safe' : '');\r\n      setOrig('v-dnt', dntCls, track ? 'warn' : 'safe');\r\n      setOrig('v-ck', ckCls, D.ck ? 'warn' : 'safe');\r\n      setOrig('v-plg', plgCls, D.pc > 0 ? 'warn' : 'safe');\r\n      setOrig('v-wd', wdCls, D.webdriver ? 'risk' : 'safe');\r\n      setOrig('v-tzm', tzmCls, D.tzMatch === false ? 'warn' : D.tzMatch === true ? 'safe' : '');\r\n      setOrig('v-lang', langCls, D.langMatch === false ? 'warn' : D.langMatch === true ? 'safe' : '');\r\n\r\n      \/* populate card values *\/\r\n      var ipEl = document.getElementById('v-ip');\r\n      ipEl.textContent = D.ip || 'Unavailable';\r\n      if (ORIG['v-ip'].val) ipEl.classList.add(ORIG['v-ip'].val);\r\n      document.getElementById('v-ip-s').textContent = D.ipOK ? 'Visible to every site you visit' : 'Could not resolve';\r\n\r\n      var ispEl = document.getElementById('v-isp');\r\n      ispEl.textContent = D.isp || 'Unavailable';\r\n      if (ORIG['v-isp'].val) ispEl.classList.add(ORIG['v-isp'].val);\r\n      var ispSub = D.asn || '';\r\n      if (D.org && D.org !== D.isp) {\r\n        var orgClean = D.org.replace(\/2g\\\/3g\\\/4g\\s*\/gi, '').replace(\/Mobile Costumers\/gi, '').replace(\/Mobile Customers\/gi, '').replace(\/Customers\/gi, '').trim();\r\n        if (orgClean) ispSub += (ispSub ? ' \u00b7 ' : '') + orgClean;\r\n      }\r\n      document.getElementById('v-isp-s').textContent = ispSub;\r\n\r\n      var lp = [D.city, D.region, D.country].filter(Boolean);\r\n      var locEl = document.getElementById('v-loc');\r\n      locEl.textContent = lp.length ? lp.join(', ') : 'Unavailable';\r\n      if (ORIG['v-loc'].val) locEl.classList.add(ORIG['v-loc'].val);\r\n      var okCount = (D.geoSources || []).filter(function(s){ return !s.fail; }).length;\r\n      document.getElementById('v-loc-s').textContent =\r\n        (D.tz ? 'Timezone: ' + D.tz : '') +\r\n        (okCount ? (D.tz ? ' \u00b7 ' : '') + 'Consensus of ' + okCount + ' sources' : '');\r\n\r\n      var vpnEl = document.getElementById('v-vpn');\r\n      if (isVpn) {\r\n        var vpnParts = [];\r\n        if (D.vpnDetected) vpnParts.push('VPN');\r\n        if (D.proxyDetected) vpnParts.push('Proxy');\r\n        if (D.torDetected) vpnParts.push('Tor');\r\n        vpnEl.textContent = 'Detected: ' + vpnParts.join(', '); vpnEl.className = 'cv risk';\r\n      } else if (D.hostingDetected) { vpnEl.textContent = 'Datacenter \/ hosting'; vpnEl.className = 'cv warn'; }\r\n      else { vpnEl.textContent = 'Not detected'; vpnEl.className = 'cv safe'; }\r\n      document.getElementById('v-vpn-s').textContent = isVpn ? 'Your IP is associated with anonymizer infrastructure' : 'No VPN, proxy or Tor exit detected on this IP';\r\n\r\n      var blkEl = document.getElementById('v-blk');\r\n      blkEl.textContent = D.blacklisted ? 'Listed on ' + D.blacklistCount + ' blocklist' + (D.blacklistCount !== 1 ? 's' : '') : 'Clean \u2014 not listed';\r\n      blkEl.className = 'cv ' + (D.blacklisted ? 'risk' : 'safe');\r\n      document.getElementById('v-blk-s').textContent = D.blacklisted ? 'Found on: ' + D.blacklistSources : 'Not found on major spam\/abuse DNS blocklists';\r\n\r\n      var portsEl = document.getElementById('v-ports');\r\n      portsEl.textContent = D.shodanPorts.length > 0 ? D.shodanPorts.length + ' open port' + (D.shodanPorts.length !== 1 ? 's' : '') : 'No open ports detected';\r\n      portsEl.className = 'cv ' + (D.shodanPorts.length > 0 ? 'warn' : 'safe');\r\n      document.getElementById('v-ports-s').textContent = D.shodanPorts.length > 0 ? 'Ports: ' + D.shodanPorts.slice(0, 12).join(', ') + (D.shodanPorts.length > 12 ? ' +' + (D.shodanPorts.length - 12) + ' more' : '') : 'Shodan InternetDB shows no open ports';\r\n\r\n      var vulnEl = document.getElementById('v-vulns');\r\n      vulnEl.textContent = D.shodanVulns.length > 0 ? D.shodanVulns.length + ' vulnerabilit' + (D.shodanVulns.length !== 1 ? 'ies' : 'y') : 'No known CVEs';\r\n      vulnEl.className = 'cv ' + (D.shodanVulns.length > 0 ? 'risk' : 'safe');\r\n      document.getElementById('v-vulns-s').textContent = D.shodanVulns.length > 0 ? 'CVEs: ' + D.shodanVulns.slice(0, 6).join(', ') + (D.shodanVulns.length > 6 ? ' +' + (D.shodanVulns.length - 6) + ' more' : '') : 'No known vulnerabilities found on Shodan';\r\n\r\n      var brEl = document.getElementById('v-br');\r\n      brEl.textContent = ua2br(D.ua); brEl.classList.add('warn');\r\n      document.getElementById('v-br-s').textContent = ua2os(D.ua) + ' \u00b7 ' + D.lang + (D.langs.length > 1 ? ' \u00b7 ' + D.langs.join(', ') : '');\r\n\r\n      var cpuEl = document.getElementById('v-cpu');\r\n      cpuEl.textContent = D.hc ? D.hc + ' cores' : 'Unavailable';\r\n      if (ORIG['v-cpu'].val) cpuEl.classList.add(ORIG['v-cpu'].val);\r\n      document.getElementById('v-cpu-s').textContent = D.hc ? 'Exposed via navigator.hardwareConcurrency \u2014 adds to your fingerprint' : 'Not exposed \u2014 this browser hides it';\r\n\r\n      var memEl = document.getElementById('v-mem');\r\n      memEl.textContent = D.dm ? D.dm + ' GB' : 'Unavailable';\r\n      if (ORIG['v-mem'].val) memEl.classList.add(ORIG['v-mem'].val);\r\n      document.getElementById('v-mem-s').textContent = D.dm ? 'Exposed via navigator.deviceMemory \u2014 adds to your fingerprint' : 'Not supported \u2014 Firefox\/Safari hide this';\r\n\r\n      var scrEl = document.getElementById('v-scr');\r\n      scrEl.textContent = D.sW + '\u00d7' + D.sH; scrEl.classList.add('warn');\r\n      document.getElementById('v-scr-s').textContent = D.pr + 'x pixel ratio \u00b7 ' + D.cd + '-bit color depth \u2014 a fingerprinting signal';\r\n\r\n      var gpuEl = document.getElementById('v-gpu');\r\n      gpuEl.textContent = D.gpu || 'Unavailable';\r\n      if (ORIG['v-gpu'].val) gpuEl.classList.add(ORIG['v-gpu'].val);\r\n      document.getElementById('v-gpu-s').textContent = D.gpu ? D.gpu + ' \u2014 WebGL renderer exposed, strong fingerprinting signal' : 'GPU info hidden by browser';\r\n\r\n      document.getElementById('v-tch').textContent = D.mt + ' touch point' + (D.mt !== 1 ? 's' : '');\r\n      document.getElementById('v-tch-s').textContent = D.mt > 0 ? 'Touch-enabled device' : 'No touch input detected';\r\n\r\n      var batEl = document.getElementById('v-bat');\r\n      batEl.textContent = D.battLevel != null ? D.battLevel + '%' : 'Unavailable';\r\n      if (ORIG['v-bat'].val) batEl.classList.add(ORIG['v-bat'].val);\r\n      document.getElementById('v-bat-s').textContent = D.battLevel != null ? (D.battCharging ? 'Charging' : 'On battery \u2014 ' + D.battLevel + '% remaining') : 'Battery API not supported by this browser';\r\n\r\n      var tzEl = document.getElementById('v-tz');\r\n      tzEl.textContent = D.brTz || 'Unavailable';\r\n      if (ORIG['v-tz'].val) tzEl.classList.add(ORIG['v-tz'].val);\r\n      document.getElementById('v-tz-s').textContent = D.brTz ? (D.tz ? 'IP timezone: ' + D.tz : '') : 'Browser does not expose timezone';\r\n\r\n      var cnvEl = document.getElementById('v-cnv');\r\n      cnvEl.textContent = D.canvasHash ? 'Hash: ' + D.canvasHash : 'Unavailable';\r\n      if (ORIG['v-cnv'].val) cnvEl.classList.add(ORIG['v-cnv'].val);\r\n      document.getElementById('v-cnv-s').textContent = D.canvasHash ? 'Canvas rendering hash computed \u2014 unique per device\/GPU\/driver combination' : 'Canvas fingerprint not available';\r\n\r\n      var audEl = document.getElementById('v-aud');\r\n      audEl.textContent = D.audioHash ? 'Hash: ' + D.audioHash : 'Unavailable';\r\n      if (ORIG['v-aud'].val) audEl.classList.add(ORIG['v-aud'].val);\r\n      document.getElementById('v-aud-s').textContent = D.audioHash ? 'AudioContext oscillator hash \u2014 adds another dimension to your fingerprint' : 'Audio fingerprint not available';\r\n\r\n      var fnEl = document.getElementById('v-fn');\r\n      fnEl.textContent = D.fontCount + ' font' + (D.fontCount !== 1 ? 's' : '') + ' detected';\r\n      if (ORIG['v-fn'].val) fnEl.classList.add(ORIG['v-fn'].val);\r\n      document.getElementById('v-fn-s').textContent = D.fontCount > 0 ? D.fontCount + ' unique system fonts found \u2014 font list is a strong fingerprinting signal' : 'Font enumeration not available';\r\n\r\n      var eC = document.getElementById('v-enc');\r\n      eC.textContent = enc ? 'TLS \/ HTTPS' : 'Unencrypted'; eC.className = 'cv ' + (enc ? 'safe' : 'risk');\r\n      document.getElementById('v-enc-s').textContent = enc ? 'Connection is encrypted end-to-end with TLS' : 'Data sent in plain text \u2014 ISP can read everything';\r\n      var nC = document.getElementById('v-nty');\r\n      nC.textContent = hosted ? 'Datacenter \/ Cloud' : 'Residential ISP'; nC.className = 'cv ' + (hosted ? 'warn' : 'risk');\r\n      document.getElementById('v-nty-s').textContent = hosted ? 'Possibly behind a VPN or proxy' : 'Your real ISP network \u2014 no VPN detected';\r\n      var wC = document.getElementById('v-wrtc');\r\n      wC.textContent = leak ? 'Leak: ' + D.wIPs[0] : 'No leak detected'; wC.className = 'cv ' + (leak ? 'risk' : 'safe');\r\n      document.getElementById('v-wrtc-s').textContent = leak ? 'Your local IP is exposed to any website with WebRTC' : 'WebRTC cannot reach your local network';\r\n\r\n      var connEl = document.getElementById('v-conn');\r\n      var connSub = document.getElementById('v-conn-s');\r\n      if (D.speedMbps != null) {\r\n        connEl.textContent = D.speedMbps + ' Mbps';\r\n        var connParts = [];\r\n        if (D.effType) connParts.push(D.effType.toUpperCase());\r\n        if (D.rtt != null) connParts.push('RTT ~' + D.rtt + 'ms');\r\n        if (D.speedMs) connParts.push('Test: ' + (D.speedMs \/ 1000).toFixed(1) + 's');\r\n        if (D.speedBytes >= 1000000) connParts.push((D.speedBytes \/ 1000000).toFixed(1) + ' MB downloaded');\r\n        connSub.textContent = connParts.filter(Boolean).join(' \u00b7 ');\r\n      } else if (D.effType) {\r\n        connEl.textContent = D.effType.toUpperCase() + (D.downlink != null ? ' \u00b7 ~' + D.downlink + ' Mbps' : '');\r\n        connSub.textContent = D.rtt != null ? '~' + D.rtt + 'ms round-trip' + (D.saveData ? ' \u00b7 Data saver ON' : '') : 'Network Information API estimate \u2014 speed test failed';\r\n      } else { connEl.textContent = 'Unavailable'; connSub.textContent = 'Speed test and Network Information API both unavailable'; }\r\n      if (ORIG['v-conn'].val) connEl.classList.add(ORIG['v-conn'].val);\r\n\r\n      var dC = document.getElementById('v-dnt');\r\n      dC.textContent = track ? 'Not set' : 'Do Not Track active'; dC.className = 'cv ' + (track ? 'warn' : 'safe');\r\n      document.getElementById('v-dnt-s').textContent = track ? 'Your browser does not request sites not to track you' : 'Browser signals sites not to track you';\r\n      var ckC = document.getElementById('v-ck');\r\n      ckC.textContent = D.ck ? 'Enabled' : 'Disabled'; ckC.className = 'cv ' + (D.ck ? 'warn' : 'safe');\r\n      document.getElementById('v-ck-s').textContent = D.ck ? 'Sites can store cookies \u2014 can be used for tracking' : 'Cookies are blocked by browser settings';\r\n      var plgEl = document.getElementById('v-plg');\r\n      plgEl.textContent = D.pc + ' plugin' + (D.pc !== 1 ? 's' : '');\r\n      if (ORIG['v-plg'].val) plgEl.classList.add(ORIG['v-plg'].val);\r\n      document.getElementById('v-plg-s').textContent = D.pc > 0 ? 'Browser plugins can increase your fingerprint surface' : 'No plugins detected \u2014 lower fingerprint risk';\r\n\r\n      var wdEl = document.getElementById('v-wd');\r\n      wdEl.textContent = D.webdriver ? 'Detected \u2014 automated browser' : 'Not detected'; wdEl.className = 'cv ' + (D.webdriver ? 'risk' : 'safe');\r\n      document.getElementById('v-wd-s').textContent = D.webdriver ? 'navigator.webdriver is true \u2014 this browser is controlled by automation' : 'No automation framework detected';\r\n\r\n      var tzmEl = document.getElementById('v-tzm');\r\n      if (D.tzMatch === true) { tzmEl.textContent = 'Timezones match'; tzmEl.className = 'cv safe'; }\r\n      else if (D.tzMatch === false) { tzmEl.textContent = 'Mismatch \u2014 possible VPN'; tzmEl.className = 'cv warn'; }\r\n      else { tzmEl.textContent = 'Insufficient data'; tzmEl.className = 'cv'; }\r\n      if (ORIG['v-tzm'].val) tzmEl.classList.add(ORIG['v-tzm'].val);\r\n      document.getElementById('v-tzm-s').textContent = D.tzMatch === true ? 'Browser and IP timezones align \u2014 consistent location' : D.tzMatch === false ? 'Browser timezone ' + D.brTz + ' differs from IP timezone ' + D.tz + ' \u2014 may indicate VPN or proxy' : 'Could not compare timezones';\r\n\r\n      var langEl = document.getElementById('v-lang');\r\n      if (D.langMatch === true) { langEl.textContent = 'Language matches region'; langEl.className = 'cv safe'; }\r\n      else if (D.langMatch === false) { langEl.textContent = 'Mismatch \u2014 suspicious'; langEl.className = 'cv warn'; }\r\n      else { langEl.textContent = 'Insufficient data'; langEl.className = 'cv'; }\r\n      if (ORIG['v-lang'].val) langEl.classList.add(ORIG['v-lang'].val);\r\n      document.getElementById('v-lang-s').textContent = D.langMatch === true ? 'Browser language is consistent with IP geolocation' : D.langMatch === false ? 'Browser language ' + D.lang + ' does not match expected language for ' + D.cISO + ' \u2014 may indicate spoofing' : 'Could not compare language to location';\r\n\r\n      \/* map \u2014 always rendered: GPS > IP consensus > timezone estimate > world view *\/\r\n      document.getElementById('verdict-view').style.display = 'block';\r\n      var hasLoc = typeof D.lat === 'number' && typeof D.lon === 'number' && isFinite(D.lat) && isFinite(D.lon);\r\n      if (hasLoc) {\r\n        var locStr = [D.city, D.region, D.country].filter(Boolean).join(', ') || 'Approximate location';\r\n        setTimeout(function(){ renderMapPoint(D.lat, D.lon, D.locAcc || 5000, locStr, D.approx ? 'approx' : 'ip'); }, 200);\r\n      } else {\r\n        setTimeout(function(){ renderMapPoint(20, 0, 0, 'Location unavailable', 'none'); }, 200);\r\n      }\r\n      \/\/ Upgrade to true GPS\/Wi-Fi precision; silent if denied, the estimate stays on the map\r\n      setTimeout(function(){ requestPrecise(true); }, 900);\r\n    }\r\n\r\n    function updateHeroBlocks() {\r\n      var critical = 0, warning = 0;\r\n      if (D.ipOK && D.ip) critical++;\r\n      if (D.ipOK && (D.city || D.region || D.country)) critical++;\r\n      if (D.proto !== 'https') critical++;\r\n      if (D.wIPs.length > 0) critical++;\r\n      if (D.webdriver) critical++;\r\n      if (D.torDetected) critical++;\r\n      if (D.shodanVulns.length > 0) critical++;\r\n      if (D.blacklisted) critical++;\r\n      if (D.ipOK && D.isp) warning++;\r\n      if (D.hostingDetected) warning++;\r\n      if (!D.dnt) warning++;\r\n      if (D.ck) warning++;\r\n      if (D.pc > 0) warning++;\r\n      if (D.hc) warning++;\r\n      if (D.gpu) warning++;\r\n      if (D.tzMatch === false) warning++;\r\n      if (D.langMatch === false) warning++;\r\n      if (D.vpnDetected) warning++;\r\n      if (D.proxyDetected) warning++;\r\n      if (D.shodanPorts.length > 0) warning++;\r\n      if (D.canvasHash) warning++;\r\n      if (D.fontCount > 15) warning++;\r\n      if (!D.online) critical++;\r\n      var total = critical + warning;\r\n      var isExposed = total > 0;\r\n\r\n      var left = document.getElementById('hero-left');\r\n      var right = document.getElementById('hero-right');\r\n      var label = document.getElementById('threats-label');\r\n      var numEl = document.getElementById('threats-num');\r\n      var titleEl = document.getElementById('vtitle');\r\n      var critBadge = document.getElementById('vbr-crit');\r\n      var warnBadge = document.getElementById('vbr-warn');\r\n      var critN = document.getElementById('crit-n');\r\n      var warnN = document.getElementById('warn-n');\r\n      var toggleLabel = document.getElementById('toggle-label');\r\n      var toggleWrap = document.getElementById('tgw');\r\n      var badge = document.getElementById('vbadge');\r\n      var mainTitle = document.getElementById('vMainTitle');\r\n      var mainDesc = document.getElementById('vMainDesc');\r\n      var mainSubDesc = document.getElementById('vMainSubDesc');\r\n      var sw = document.getElementById('sw');\r\n\r\n      if (isExposed) {\r\n        left.className = 'hero-block hero-left exposed';\r\n        right.className = 'hero-block hero-right exposed';\r\n        label.className = 'threats-label danger';\r\n        label.textContent = 'THREATS DETECTED';\r\n        numEl.className = 'num'; numEl.textContent = total;\r\n        titleEl.innerHTML = 'issues found on your current connection';\r\n        critN.textContent = critical; warnN.textContent = warning;\r\n        critBadge.style.display = critical > 0 ? 'inline-flex' : 'none';\r\n        warnBadge.style.display = warning > 0 ? 'inline-flex' : 'none';\r\n        toggleLabel.textContent = 'Protected mode'; toggleLabel.className = 'toggle-label';\r\n        toggleWrap.className = 'protect-toggle-row';\r\n        badge.className = 'vb dg';\r\n        mainTitle.textContent = 'AssistYU Network Scan';\r\n        mainDesc.textContent = 'Your network is exposed.';\r\n        mainSubDesc.textContent = 'Real-time diagnostic of your IP exposure, browser fingerprint, and threat intelligence';\r\n        sw.textContent = 'exposed'; sw.className = 'sw-t exposed';\r\n        document.querySelector('.verdict-header').className = 'verdict-header exposed';\r\n      } else {\r\n        left.className = 'hero-block hero-left protected';\r\n        right.className = 'hero-block hero-right protected';\r\n        label.className = 'threats-label safe'; label.textContent = 'PROTECTED';\r\n        numEl.className = 'num safe'; numEl.textContent = '0';\r\n        titleEl.innerHTML = 'Your traffic is <span class=\"highlight\">encrypted end-to-end<\/span>';\r\n        critBadge.style.display = 'none'; warnBadge.style.display = 'none';\r\n        toggleLabel.textContent = 'Protected mode'; toggleLabel.className = 'toggle-label active';\r\n        toggleWrap.className = 'protect-toggle-row on';\r\n        badge.className = 'vb sg';\r\n        mainTitle.textContent = 'AssistYU Network Scan';\r\n        mainDesc.textContent = \"You're protected.\";\r\n        mainSubDesc.textContent = 'Your connection is secured with end-to-end encryption';\r\n        sw.textContent = 'protected'; sw.className = 'sw-t protected';\r\n        document.querySelector('.verdict-header').className = 'verdict-header protected';\r\n      }\r\n    }\r\n\r\n    var OV = {};\r\n    document.getElementById('ptog').addEventListener('change', function(e) {\r\n      var left = document.getElementById('hero-left');\r\n      var right = document.getElementById('hero-right');\r\n      var label = document.getElementById('threats-label');\r\n      var numEl = document.getElementById('threats-num');\r\n      var titleEl = document.getElementById('vtitle');\r\n      var critBadge = document.getElementById('vbr-crit');\r\n      var warnBadge = document.getElementById('vbr-warn');\r\n      var toggleLabel = document.getElementById('toggle-label');\r\n      var toggleWrap = document.getElementById('tgw');\r\n      var badge = document.getElementById('vbadge');\r\n      var mainTitle = document.getElementById('vMainTitle');\r\n      var mainDesc = document.getElementById('vMainDesc');\r\n      var mainSubDesc = document.getElementById('vMainSubDesc');\r\n      var sw = document.getElementById('sw');\r\n      var cards = document.querySelectorAll('[data-p]');\r\n      var mapMask = document.getElementById('map-mask');\r\n\r\n      var critical = parseInt(document.getElementById('crit-n').textContent) || 0;\r\n      var warning = parseInt(document.getElementById('warn-n').textContent) || 0;\r\n      var total = critical + warning;\r\n      var isExposed = total > 0;\r\n\r\n      if (e.target.checked) {\r\n        left.className = 'hero-block hero-left protected';\r\n        right.className = 'hero-block hero-right protected';\r\n        label.className = 'threats-label safe'; label.textContent = 'PROTECTED';\r\n        numEl.className = 'num safe'; numEl.textContent = '0';\r\n        titleEl.innerHTML = 'Your traffic is <span class=\"highlight\">encrypted end-to-end<\/span>';\r\n        critBadge.style.display = 'none'; warnBadge.style.display = 'none';\r\n        toggleLabel.textContent = 'Protected mode'; toggleLabel.className = 'toggle-label active';\r\n        toggleWrap.className = 'protect-toggle-row on';\r\n        badge.className = 'vb sg';\r\n        mainTitle.textContent = 'AssistYU Network Scan';\r\n        mainDesc.textContent = \"You're protected.\";\r\n        mainSubDesc.textContent = 'Your connection is secured with end-to-end encryption';\r\n        sw.textContent = 'protected'; sw.className = 'sw-t protected';\r\n        document.querySelector('.verdict-header').className = 'verdict-header protected';\r\n        if (mapMask) mapMask.classList.add('show');\r\n        document.getElementById('rg-fill').style.stroke = 'var(--safe)';\r\n        document.getElementById('rg-fill').style.strokeDashoffset = '0';\r\n        document.getElementById('rg-num').textContent = '0';\r\n        document.getElementById('rg-grade').innerHTML = 'Grade A <span class=\"sub\">Fully protected<\/span>';\r\n        document.getElementById('rg-grade').style.color = 'var(--safe)';\r\n        document.getElementById('rg-sub').innerHTML = '<span class=\"tag safe\">Protected mode masks all exposure signals<\/span>';\r\n\r\n        cards.forEach(function(c) {\r\n          var v = c.querySelector('.cv'), id = c.dataset.p;\r\n          if (v && id) {\r\n            if (!OV[id]) OV[id] = v.textContent;\r\n            if (id === 'v-ip') { v.textContent = '\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022'; v.className = 'cv mask'; }\r\n            else if (id === 'v-loc') { v.textContent = 'Location masked'; v.className = 'cv mask'; }\r\n            else if (id === 'v-wrtc') { v.textContent = 'Blocked'; v.className = 'cv safe'; }\r\n            else if (id === 'v-nty') { v.textContent = 'VPN \/ masked'; v.className = 'cv safe'; }\r\n            else if (id === 'v-enc') { v.textContent = 'TLS + AssistYU tunnel'; v.className = 'cv safe'; }\r\n            else if (id === 'v-dnt') { v.textContent = 'Tracking blocked'; v.className = 'cv safe'; }\r\n            else if (id === 'v-ck') { v.textContent = 'Cookies blocked'; v.className = 'cv safe'; }\r\n            else if (id === 'v-wd') { v.textContent = 'Spoofed \u2014 undetectable'; v.className = 'cv safe'; }\r\n            else if (id === 'v-tzm') { v.textContent = 'Consistent \u2014 masked'; v.className = 'cv safe'; }\r\n            else if (id === 'v-lang') { v.textContent = 'Consistent \u2014 masked'; v.className = 'cv safe'; }\r\n            else if (id === 'v-vpn') { v.textContent = 'All anonymizer traffic hidden'; v.className = 'cv safe'; }\r\n            else if (id === 'v-blk') { v.textContent = 'Masked \u2014 not scannable'; v.className = 'cv safe'; }\r\n            else if (id === 'v-ports') { v.textContent = 'Hidden \u2014 no scan possible'; v.className = 'cv safe'; }\r\n            else if (id === 'v-vulns') { v.textContent = 'Hidden \u2014 no scan possible'; v.className = 'cv safe'; }\r\n            c.classList.remove('c-danger', 'c-warn', 'c-cyan', 'c-safe');\r\n            c.classList.add('c-safe', 'prot');\r\n          }\r\n        });\r\n        document.getElementById('v-nty-s').textContent = 'Hidden behind encrypted tunnel';\r\n        document.getElementById('v-enc-s').textContent = 'Double encryption layer active';\r\n        document.getElementById('v-dnt-s').textContent = 'AssistYU blocks tracking cookies and fingerprinting';\r\n        document.getElementById('v-wd-s').textContent = 'Automation signature masked by AssistYU';\r\n        document.getElementById('v-tzm-s').textContent = 'Location fingerprint hidden';\r\n        document.getElementById('v-lang-s').textContent = 'Language fingerprint hidden';\r\n        document.getElementById('v-vpn-s').textContent = 'All network intelligence masked';\r\n        document.getElementById('v-blk-s').textContent = 'IP reputation hidden from scanners';\r\n        document.getElementById('v-ports-s').textContent = 'Port scan results hidden';\r\n        document.getElementById('v-vulns-s').textContent = 'Vulnerability data hidden';\r\n      } else {\r\n        left.className = 'hero-block hero-left exposed';\r\n        right.className = 'hero-block hero-right exposed';\r\n        label.className = 'threats-label danger';\r\n        label.textContent = isExposed ? 'THREATS DETECTED' : 'PROTECTED';\r\n        numEl.className = isExposed ? 'num' : 'num safe';\r\n        numEl.textContent = isExposed ? total : '0';\r\n        if (isExposed) {\r\n          titleEl.innerHTML = 'issues found on your current connection';\r\n          critBadge.style.display = critical > 0 ? 'inline-flex' : 'none';\r\n          warnBadge.style.display = warning > 0 ? 'inline-flex' : 'none';\r\n          document.getElementById('crit-n').textContent = critical;\r\n          document.getElementById('warn-n').textContent = warning;\r\n        } else {\r\n          titleEl.innerHTML = 'Your traffic is <span class=\"highlight\">encrypted end-to-end<\/span>';\r\n          critBadge.style.display = 'none'; warnBadge.style.display = 'none';\r\n        }\r\n        toggleLabel.textContent = 'Protected mode'; toggleLabel.className = 'toggle-label';\r\n        toggleWrap.className = 'protect-toggle-row';\r\n        badge.className = isExposed ? 'vb dg' : 'vb sg';\r\n        mainTitle.textContent = 'AssistYU Network Scan';\r\n        mainDesc.textContent = isExposed ? 'Your network is exposed.' : \"You're protected.\";\r\n        mainSubDesc.textContent = isExposed ? 'Real-time diagnostic of your IP exposure, browser fingerprint, and threat intelligence' : 'Your connection is secured with end-to-end encryption';\r\n        sw.textContent = isExposed ? 'exposed' : 'protected';\r\n        sw.className = isExposed ? 'sw-t exposed' : 'sw-t protected';\r\n        document.querySelector('.verdict-header').className = isExposed ? 'verdict-header exposed' : 'verdict-header protected';\r\n        if (mapMask) mapMask.classList.remove('show');\r\n\r\n        var gColor = D.riskScore >= 60 ? 'var(--danger)' : D.riskScore >= 30 ? 'var(--amber)' : 'var(--safe)';\r\n        var circumference = 314.16;\r\n        var offset = circumference - (D.riskScore \/ 100) * circumference;\r\n        document.getElementById('rg-fill').style.strokeDashoffset = offset;\r\n        document.getElementById('rg-fill').style.stroke = gColor;\r\n        document.getElementById('rg-num').textContent = D.riskScore;\r\n        var gradeText = D.riskGrade === 'F' ? 'Critical exposure' : D.riskGrade === 'D' ? 'High exposure' : D.riskGrade === 'C' ? 'Moderate exposure' : D.riskGrade === 'B' ? 'Low exposure' : 'Minimal exposure';\r\n        document.getElementById('rg-grade').innerHTML = 'Grade ' + D.riskGrade + ' <span class=\"sub\">' + gradeText + '<\/span>';\r\n        document.getElementById('rg-grade').style.color = gColor;\r\n\r\n        var rgParts = [];\r\n        if (D.wIPs.length > 0) rgParts.push('WebRTC leak');\r\n        if (D.vpnDetected) rgParts.push('VPN detected');\r\n        if (D.torDetected) rgParts.push('Tor exit');\r\n        if (D.blacklisted) rgParts.push('On ' + D.blacklistCount + ' blacklists');\r\n        if (D.shodanVulns.length) rgParts.push(D.shodanVulns.length + ' CVEs');\r\n        if (D.webdriver) rgParts.push('Automation');\r\n        if (D.proto !== 'https') rgParts.push('Unencrypted');\r\n        document.getElementById('rg-sub').innerHTML = rgParts.length ? rgParts.map(function(t) {\r\n          var cls = 'tag';\r\n          if (t.indexOf('leak') > -1 || t.indexOf('Tor') > -1 || t.indexOf('CVEs') > -1 || t.indexOf('Unencrypted') > -1) cls += ' danger';\r\n          else if (t.indexOf('On ') > -1 || t.indexOf('Automation') > -1) cls += ' warn';\r\n          else cls += ' safe';\r\n          return '<span class=\"' + cls + '\">' + t + '<\/span>';\r\n        }).join('') : '<span class=\"tag safe\">No critical signals<\/span>';\r\n\r\n        cards.forEach(function(c) {\r\n          var v = c.querySelector('.cv'), id = c.dataset.p;\r\n          if (v && id && OV[id] && ORIG[id]) {\r\n            v.textContent = OV[id]; v.className = 'cv';\r\n            if (ORIG[id].val) v.classList.add(ORIG[id].val);\r\n            c.classList.remove('prot', 'c-safe', 'c-danger', 'c-warn', 'c-cyan');\r\n            c.classList.add('c-' + ORIG[id].card);\r\n          }\r\n        });\r\n        document.getElementById('v-nty-s').textContent = D.hostingDetected ? 'Possibly behind a VPN or proxy' : 'Your real ISP network \u2014 no VPN detected';\r\n        document.getElementById('v-enc-s').textContent = D.proto === 'https' ? 'Encrypted end-to-end' : 'Visible to ISP';\r\n        document.getElementById('v-dnt-s').textContent = !D.dnt ? 'Sites can track you' : 'No tracking';\r\n      }\r\n    });\r\n\r\n    \/* phone pill *\/\r\n    (function() {\r\n      var pill = document.getElementById('phone-pill');\r\n      var icon = document.getElementById('pp-icon');\r\n      if (pill && icon) {\r\n        icon.addEventListener('click', function(e) {\r\n          e.stopPropagation();\r\n          var open = pill.classList.toggle('open');\r\n          icon.setAttribute('aria-expanded', open ? 'true' : 'false');\r\n        });\r\n        document.addEventListener('click', function(e) {\r\n          if (pill && !pill.contains(e.target)) { pill.classList.remove('open'); icon.setAttribute('aria-expanded', 'false'); }\r\n        });\r\n      }\r\n    })();\r\n  })();\r\n});\r\n\r\n\/* ============================================================\r\n   STATS COUNTERS + CLOCK (independent)\r\n   ============================================================ *\/\r\n(function() {\r\n  \"use strict\";\r\n  const storage = {\r\n    mem: {},\r\n    getItem: function(key) { try { return localStorage.getItem(key); } catch (_) { return storage.mem[key] || null; } },\r\n    setItem: function(key, val) { try { localStorage.setItem(key, val); } catch (_) { storage.mem[key] = val; } }\r\n  };\r\n  const DAY_MS = 24 * 60 * 60 * 1000;\r\n  const STORE_KEY = 'assistyu_network_scan_cycle_v1';\r\n  function mulberry32(seed) {\r\n    return function() {\r\n      seed |= 0; seed = seed + 0x6D2B79F5 | 0;\r\n      let t = Math.imul(seed ^ seed >>> 15, 1 | seed);\r\n      t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;\r\n      return ((t ^ t >>> 14) >>> 0) \/ 4294967296;\r\n    };\r\n  }\r\n  function hourlyWeights(seed) {\r\n    const rnd = mulberry32(seed ^ 0x9e3779b9); const w = [];\r\n    for (let h = 0; h < 24; h++) { const nightDip = (h >= 1 && h <= 6) ? 0.45 : 1; w.push(nightDip * (0.7 + rnd() * 0.6)); }\r\n    return w;\r\n  }\r\n  function loadCycle() {\r\n    const rightNow = Date.now(); let raw = null, cycle = null;\r\n    try { raw = storage.getItem(STORE_KEY); } catch (e) {}\r\n    if (raw) { try { cycle = JSON.parse(raw); } catch (e) { cycle = null; } }\r\n    if (!cycle || (rightNow - cycle.start) >= DAY_MS) {\r\n      const seed = Math.floor(Math.random() * 4294967295); const rnd = mulberry32(seed);\r\n      cycle = { start: rightNow, seed: seed, target: Math.floor(5000 + rnd() * 15000), issueRatio: 0.10 + rnd() * 0.25, speedAvg: 20 + rnd() * 60, riskAvg: 10 + rnd() * 50 };\r\n      try { storage.setItem(STORE_KEY, JSON.stringify(cycle)); } catch (e) {}\r\n    }\r\n    return cycle;\r\n  }\r\n  function cycleProgress(cycle) {\r\n    const elapsed = Date.now() - cycle.start;\r\n    const weights = hourlyWeights(cycle.seed);\r\n    const total = weights.reduce(function(a, b) { return a + b; }, 0);\r\n    const hoursElapsed = Math.min(24, elapsed \/ 3600000);\r\n    const fullHours = Math.floor(hoursElapsed); const partial = hoursElapsed - fullHours;\r\n    let sum = 0;\r\n    for (let i = 0; i < fullHours && i < 24; i++) sum += weights[i];\r\n    if (fullHours < 24) sum += weights[fullHours] * partial;\r\n    const frac = Math.min(1, sum \/ total);\r\n    const scans = Math.round(cycle.target * frac);\r\n    const issues = Math.round(scans * cycle.issueRatio);\r\n    const speed = cycle.speedAvg + (Math.random() - 0.5) * 10;\r\n    const risk = cycle.riskAvg + (Math.random() - 0.5) * 15;\r\n    return { scans, issues, speed: Math.max(1, Math.round(speed)), risk: Math.max(0, Math.round(risk)) };\r\n  }\r\n  function animateCount(el, from, to, dur) {\r\n    if (from === to) { el.textContent = to.toLocaleString(); return; }\r\n    let t0 = null;\r\n    function step(ts) {\r\n      if (!t0) t0 = ts;\r\n      const p = Math.min(1, (ts - t0) \/ dur);\r\n      const eased = 1 - Math.pow(1 - p, 3);\r\n      el.textContent = Math.round(from + (to - from) * eased).toLocaleString();\r\n      if (p < 1) requestAnimationFrame(step);\r\n    }\r\n    requestAnimationFrame(step);\r\n  }\r\n  let diagCycle = loadCycle();\r\n  const statScansEl = document.getElementById('statScans');\r\n  const statIssuesEl = document.getElementById('statIssues');\r\n  const statSpeedEl = document.getElementById('statSpeed');\r\n  const statRiskEl = document.getElementById('statRisk');\r\n  let lastScans = 0, lastIssues = 0, lastSpeed = 0, lastRisk = 0;\r\n  function refreshStats() {\r\n    if (Date.now() - diagCycle.start >= DAY_MS) { diagCycle = loadCycle(); lastScans = 0; lastIssues = 0; lastSpeed = 0; lastRisk = 0; }\r\n    const p = cycleProgress(diagCycle);\r\n    animateCount(statScansEl, lastScans, p.scans, 1100);\r\n    animateCount(statIssuesEl, lastIssues, p.issues, 1100);\r\n    animateCount(statSpeedEl, lastSpeed, p.speed, 1100);\r\n    animateCount(statRiskEl, lastRisk, p.risk, 1100);\r\n    lastScans = p.scans; lastIssues = p.issues; lastSpeed = p.speed; lastRisk = p.risk;\r\n  }\r\n  refreshStats();\r\n  setInterval(refreshStats, 7000);\r\n  document.addEventListener('visibilitychange', function() { if (!document.hidden) refreshStats(); });\r\n  const clockEl = document.getElementById('lastUpdate');\r\n  if (clockEl) {\r\n    setInterval(function() {\r\n      const d = new Date();\r\n      clockEl.textContent = String(d.getHours()).padStart(2, '0') + ':' + String(d.getMinutes()).padStart(2, '0') + ':' + String(d.getSeconds()).padStart(2, '0');\r\n    }, 1000);\r\n  }\r\n})();\r\n<\/script>\r\n\r\n<!-- ========================================================================\r\n     ASSISTYU PROTECTED MODE \u2014 LICENSE CTA POPUP\r\n     ======================================================================== -->\r\n\r\n<style>\r\n  \/* Prevent page scrolling only while the license popup is visible. *\/\r\n  html.ayu-license-open,\r\n  body.ayu-license-open {\r\n    overflow: hidden !important;\r\n  }\r\n\r\n  \/* Make the existing Protected Mode row feel clickable without changing it. *\/\r\n  #tgw {\r\n    cursor: pointer;\r\n    transition: border-color .25s ease, box-shadow .25s ease, transform .25s ease;\r\n  }\r\n\r\n  #tgw:hover {\r\n    border-color: rgba(79,110,247,.48);\r\n    box-shadow: 0 7px 28px rgba(0,0,0,.34), 0 0 26px rgba(79,110,247,.08);\r\n    transform: translateY(-1px);\r\n  }\r\n\r\n  \/* Main overlay *\/\r\n  .ayu-license-modal {\r\n    position: fixed;\r\n    inset: 0;\r\n    z-index: 99999;\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    padding: 24px;\r\n    background:\r\n      radial-gradient(circle at 16% 14%, rgba(79,110,247,.12), transparent 30%),\r\n      radial-gradient(circle at 84% 86%, rgba(138,107,255,.09), transparent 28%),\r\n      rgba(3,5,12,.88);\r\n    -webkit-backdrop-filter: blur(14px);\r\n    backdrop-filter: blur(14px);\r\n    opacity: 0;\r\n    visibility: hidden;\r\n    pointer-events: none;\r\n    transition: opacity .26s ease, visibility .26s ease;\r\n  }\r\n\r\n  .ayu-license-modal.is-open {\r\n    opacity: 1;\r\n    visibility: visible;\r\n    pointer-events: auto;\r\n  }\r\n\r\n  \/* Dialog shell *\/\r\n  .ayu-license-dialog {\r\n    position: relative;\r\n    width: min(980px, 100%);\r\n    max-height: min(760px, 92vh);\r\n    overflow: auto;\r\n    border: 1px solid rgba(79,110,247,.34);\r\n    border-radius: 24px;\r\n    color: var(--ayu-text-primary, #fff);\r\n    background:\r\n      radial-gradient(80% 95% at 0% 0%, rgba(79,110,247,.16), transparent 58%),\r\n      radial-gradient(65% 75% at 100% 100%, rgba(34,230,168,.065), transparent 58%),\r\n      linear-gradient(145deg, rgba(11,17,48,.98), rgba(6,8,21,.985));\r\n    box-shadow:\r\n      0 40px 120px rgba(0,0,0,.72),\r\n      0 0 0 1px rgba(255,255,255,.025),\r\n      inset 0 1px 0 rgba(255,255,255,.045);\r\n    transform: translateY(18px) scale(.985);\r\n    transition: transform .3s cubic-bezier(.2,.8,.2,1);\r\n    isolation: isolate;\r\n  }\r\n\r\n  .ayu-license-modal.is-open .ayu-license-dialog {\r\n    transform: none;\r\n  }\r\n\r\n  .ayu-license-dialog::before {\r\n    content: '';\r\n    position: absolute;\r\n    inset: 0;\r\n    z-index: -1;\r\n    border-radius: inherit;\r\n    pointer-events: none;\r\n    background: repeating-linear-gradient(\r\n      0deg,\r\n      transparent,\r\n      transparent 4px,\r\n      rgba(255,255,255,.008) 4px,\r\n      rgba(255,255,255,.008) 5px\r\n    );\r\n  }\r\n\r\n  .ayu-license-close {\r\n    position: absolute;\r\n    top: 17px;\r\n    right: 17px;\r\n    z-index: 5;\r\n    width: 39px;\r\n    height: 39px;\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    padding: 0;\r\n    border: 1px solid rgba(79,110,247,.24);\r\n    border-radius: 11px;\r\n    color: var(--ayu-text-tertiary, #bcc4f0);\r\n    background: rgba(6,8,21,.72);\r\n    transition: color .2s ease, border-color .2s ease, background .2s ease;\r\n  }\r\n\r\n  .ayu-license-close:hover {\r\n    color: #fff;\r\n    border-color: rgba(79,110,247,.52);\r\n    background: rgba(79,110,247,.1);\r\n  }\r\n\r\n  .ayu-license-close svg {\r\n    width: 18px;\r\n    height: 18px;\r\n  }\r\n\r\n  .ayu-license-grid {\r\n    display: grid;\r\n    grid-template-columns: 1.08fr .92fr;\r\n    min-height: 540px;\r\n  }\r\n\r\n  \/* Left information side *\/\r\n  .ayu-license-story {\r\n    padding: 48px 42px 42px;\r\n  }\r\n\r\n  .ayu-license-eyebrow {\r\n    display: inline-flex;\r\n    align-items: center;\r\n    gap: 8px;\r\n    padding: 7px 13px;\r\n    border: 1px solid rgba(255,184,77,.25);\r\n    border-radius: 999px;\r\n    color: var(--amber, #ffb84d);\r\n    background: rgba(255,184,77,.075);\r\n    font-family: var(--font-mono, monospace);\r\n    font-size: 9px;\r\n    font-weight: 700;\r\n    letter-spacing: 1.4px;\r\n    text-transform: uppercase;\r\n  }\r\n\r\n  .ayu-license-eyebrow-dot {\r\n    width: 6px;\r\n    height: 6px;\r\n    border-radius: 50%;\r\n    background: var(--amber, #ffb84d);\r\n    box-shadow: 0 0 9px var(--amber, #ffb84d);\r\n    animation: ayuLicensePulse 1.7s ease-in-out infinite;\r\n  }\r\n\r\n  @keyframes ayuLicensePulse {\r\n    0%,100% { opacity: 1; }\r\n    50% { opacity: .4; }\r\n  }\r\n\r\n  .ayu-license-title {\r\n    max-width: 560px;\r\n    margin-top: 18px;\r\n    font-family: var(--font-display, sans-serif);\r\n    font-size: clamp(30px, 4vw, 47px);\r\n    font-weight: 700;\r\n    line-height: 1.08;\r\n    letter-spacing: -.035em;\r\n  }\r\n\r\n  .ayu-license-title span {\r\n    color: var(--safe, #22e6a8);\r\n    text-shadow: 0 0 28px rgba(34,230,168,.12);\r\n  }\r\n\r\n  .ayu-license-lead {\r\n    max-width: 570px;\r\n    margin-top: 15px;\r\n    color: var(--ayu-text-secondary, #d4daff);\r\n    font-family: var(--font-body, sans-serif);\r\n    font-size: 14px;\r\n    line-height: 1.7;\r\n  }\r\n\r\n  .ayu-license-findings {\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 15px;\r\n    margin-top: 23px;\r\n    padding: 15px;\r\n    border: 1px solid rgba(255,61,104,.25);\r\n    border-radius: 14px;\r\n    background:\r\n      radial-gradient(80% 150% at 0% 50%, rgba(255,61,104,.11), transparent 70%),\r\n      rgba(255,61,104,.045);\r\n  }\r\n\r\n  .ayu-license-findings-number {\r\n    min-width: 54px;\r\n    color: var(--danger, #ff3d68);\r\n    font-family: var(--font-display, sans-serif);\r\n    font-size: 38px;\r\n    font-weight: 700;\r\n    line-height: 1;\r\n    text-align: center;\r\n    text-shadow: 0 0 22px rgba(255,61,104,.18);\r\n  }\r\n\r\n  .ayu-license-findings-copy strong {\r\n    display: block;\r\n    color: #fff;\r\n    font-family: var(--font-display, sans-serif);\r\n    font-size: 13px;\r\n    font-weight: 700;\r\n  }\r\n\r\n  .ayu-license-findings-copy span {\r\n    display: block;\r\n    margin-top: 4px;\r\n    color: var(--ayu-text-tertiary, #bcc4f0);\r\n    font-size: 10px;\r\n    line-height: 1.45;\r\n  }\r\n\r\n  .ayu-license-benefits {\r\n    display: grid;\r\n    grid-template-columns: 1fr 1fr;\r\n    gap: 12px 18px;\r\n    margin-top: 23px;\r\n    list-style: none;\r\n  }\r\n\r\n  .ayu-license-benefits li {\r\n    display: flex;\r\n    align-items: flex-start;\r\n    gap: 9px;\r\n    color: var(--ayu-text-secondary, #d4daff);\r\n    font-size: 11px;\r\n    line-height: 1.45;\r\n  }\r\n\r\n  .ayu-license-benefits svg {\r\n    width: 16px;\r\n    height: 16px;\r\n    min-width: 16px;\r\n    margin-top: 1px;\r\n    color: var(--safe, #22e6a8);\r\n  }\r\n\r\n  .ayu-license-note {\r\n    margin-top: 21px;\r\n    color: var(--ayu-text-tertiary, #bcc4f0);\r\n    font-family: var(--font-mono, monospace);\r\n    font-size: 9px;\r\n    line-height: 1.55;\r\n  }\r\n\r\n  \/* Right license\/contact panel *\/\r\n  .ayu-license-panel {\r\n    display: flex;\r\n    flex-direction: column;\r\n    justify-content: center;\r\n    margin: 24px 24px 24px 0;\r\n    padding: 30px;\r\n    border: 1px solid rgba(79,110,247,.22);\r\n    border-radius: 19px;\r\n    background:\r\n      radial-gradient(100% 80% at 100% 0%, rgba(138,107,255,.08), transparent 60%),\r\n      linear-gradient(145deg, rgba(6,8,21,.78), rgba(9,13,36,.72));\r\n    box-shadow: inset 0 1px 0 rgba(255,255,255,.03), 0 16px 45px rgba(0,0,0,.2);\r\n  }\r\n\r\n  .ayu-license-lock {\r\n    width: 47px;\r\n    height: 47px;\r\n    display: flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    border: 1px solid rgba(34,230,168,.3);\r\n    border-radius: 13px;\r\n    color: var(--safe, #22e6a8);\r\n    background: rgba(34,230,168,.085);\r\n    box-shadow: 0 0 25px rgba(34,230,168,.1);\r\n  }\r\n\r\n  .ayu-license-lock svg {\r\n    width: 22px;\r\n    height: 22px;\r\n  }\r\n\r\n  .ayu-license-panel h3 {\r\n    margin-top: 16px;\r\n    font-family: var(--font-display, sans-serif);\r\n    font-size: 22px;\r\n    font-weight: 700;\r\n  }\r\n\r\n  .ayu-license-panel-intro {\r\n    margin-top: 7px;\r\n    color: var(--ayu-text-tertiary, #bcc4f0);\r\n    font-size: 11px;\r\n    line-height: 1.55;\r\n  }\r\n\r\n  .ayu-license-form {\r\n    margin-top: 19px;\r\n  }\r\n\r\n  .ayu-license-label {\r\n    display: block;\r\n    margin-bottom: 8px;\r\n    color: var(--ayu-text-secondary, #d4daff);\r\n    font-family: var(--font-mono, monospace);\r\n    font-size: 9px;\r\n    font-weight: 700;\r\n    letter-spacing: 1px;\r\n    text-transform: uppercase;\r\n  }\r\n\r\n  .ayu-license-input-wrap {\r\n    position: relative;\r\n  }\r\n\r\n  .ayu-license-input {\r\n    width: 100%;\r\n    height: 50px;\r\n    padding: 0 45px 0 14px;\r\n    border: 1px solid rgba(79,110,247,.32);\r\n    border-radius: 11px;\r\n    outline: none;\r\n    color: #fff;\r\n    background: rgba(3,5,15,.68);\r\n    font-family: var(--font-mono, monospace);\r\n    font-size: 12px;\r\n    font-weight: 600;\r\n    letter-spacing: .5px;\r\n    transition: border-color .2s ease, box-shadow .2s ease;\r\n  }\r\n\r\n  .ayu-license-input::placeholder {\r\n    color: #6f7aa4;\r\n  }\r\n\r\n  .ayu-license-input:focus {\r\n    border-color: var(--cyan, #4f6ef7);\r\n    box-shadow: 0 0 0 3px rgba(79,110,247,.11), 0 0 24px rgba(79,110,247,.08);\r\n  }\r\n\r\n  .ayu-license-key-icon {\r\n    position: absolute;\r\n    top: 50%;\r\n    right: 14px;\r\n    width: 18px;\r\n    height: 18px;\r\n    color: var(--ayu-text-tertiary, #bcc4f0);\r\n    transform: translateY(-50%);\r\n    pointer-events: none;\r\n  }\r\n\r\n  .ayu-license-verify {\r\n    width: 100%;\r\n    margin-top: 10px;\r\n    padding: 14px 16px;\r\n    border: 1px solid rgba(34,230,168,.37);\r\n    border-radius: 11px;\r\n    color: #fff;\r\n    background: linear-gradient(135deg, rgba(34,230,168,.18), rgba(79,110,247,.21));\r\n    font-family: var(--font-display, sans-serif);\r\n    font-size: 13px;\r\n    font-weight: 700;\r\n    transition: transform .25s ease, border-color .25s ease, box-shadow .25s ease;\r\n  }\r\n\r\n  .ayu-license-verify:hover {\r\n    border-color: rgba(34,230,168,.68);\r\n    box-shadow: 0 9px 30px rgba(34,230,168,.12);\r\n    transform: translateY(-1px);\r\n  }\r\n\r\n  .ayu-license-verify:disabled {\r\n    opacity: .6;\r\n    cursor: wait;\r\n    transform: none;\r\n  }\r\n\r\n  .ayu-license-status {\r\n    display: none;\r\n    margin-top: 10px;\r\n    padding: 10px 11px;\r\n    border-radius: 8px;\r\n    font-size: 10px;\r\n    line-height: 1.5;\r\n  }\r\n\r\n  .ayu-license-status.is-visible { display: block; }\r\n  .ayu-license-status.is-error { color: #ff9fb3; border: 1px solid rgba(255,61,104,.22); background: rgba(255,61,104,.07); }\r\n  .ayu-license-status.is-info { color: #c4ccff; border: 1px solid rgba(79,110,247,.24); background: rgba(79,110,247,.08); }\r\n  .ayu-license-status.is-success { color: var(--safe, #22e6a8); border: 1px solid rgba(34,230,168,.24); background: rgba(34,230,168,.07); }\r\n\r\n  .ayu-license-divider {\r\n    display: flex;\r\n    align-items: center;\r\n    gap: 10px;\r\n    margin: 19px 0;\r\n    color: #7680a8;\r\n    font-family: var(--font-mono, monospace);\r\n    font-size: 8px;\r\n    font-weight: 600;\r\n    letter-spacing: 1px;\r\n    text-transform: uppercase;\r\n  }\r\n\r\n  .ayu-license-divider::before,\r\n  .ayu-license-divider::after {\r\n    content: '';\r\n    height: 1px;\r\n    flex: 1;\r\n    background: rgba(79,110,247,.17);\r\n  }\r\n\r\n  .ayu-license-actions {\r\n    display: grid;\r\n    gap: 9px;\r\n  }\r\n\r\n  .ayu-license-primary,\r\n  .ayu-license-secondary {\r\n    width: 100%;\r\n    display: inline-flex;\r\n    align-items: center;\r\n    justify-content: center;\r\n    gap: 9px;\r\n    border-radius: 11px;\r\n    text-align: center;\r\n    transition: transform .24s ease, border-color .24s ease, background .24s ease, color .24s ease;\r\n  }\r\n\r\n  .ayu-license-primary {\r\n    padding: 13px 15px;\r\n    border: 1px solid rgba(79,110,247,.4);\r\n    color: #fff;\r\n    background: linear-gradient(135deg, rgba(79,110,247,.17), rgba(138,107,255,.13));\r\n    font-family: var(--font-display, sans-serif);\r\n    font-size: 12px;\r\n    font-weight: 700;\r\n  }\r\n\r\n  .ayu-license-primary:hover {\r\n    border-color: rgba(79,110,247,.7);\r\n    background: linear-gradient(135deg, rgba(79,110,247,.25), rgba(138,107,255,.2));\r\n    box-shadow: 0 8px 26px rgba(79,110,247,.16);\r\n    transform: translateY(-1px);\r\n  }\r\n\r\n  .ayu-license-primary svg {\r\n    width: 16px;\r\n    height: 16px;\r\n    color: var(--cyan, #4f6ef7);\r\n  }\r\n\r\n  .ayu-license-secondary {\r\n    padding: 11px 14px;\r\n    border: 1px solid rgba(79,110,247,.18);\r\n    color: var(--ayu-text-secondary, #d4daff);\r\n    background: rgba(6,8,21,.3);\r\n    font-family: var(--font-body, sans-serif);\r\n    font-size: 11px;\r\n    font-weight: 600;\r\n  }\r\n\r\n  .ayu-license-secondary:hover {\r\n    color: #fff;\r\n    border-color: rgba(79,110,247,.38);\r\n    background: rgba(79,110,247,.075);\r\n  }\r\n\r\n  .ayu-license-support {\r\n    margin-top: 14px;\r\n    color: var(--ayu-text-tertiary, #bcc4f0);\r\n    font-family: var(--font-mono, monospace);\r\n    font-size: 9px;\r\n    line-height: 1.5;\r\n    text-align: center;\r\n  }\r\n\r\n  .ayu-license-support b {\r\n    color: #fff;\r\n  }\r\n\r\n  @media (max-width: 850px) {\r\n    .ayu-license-grid { grid-template-columns: 1fr; }\r\n    .ayu-license-story { padding: 45px 30px 18px; }\r\n    .ayu-license-panel { margin: 16px 22px 22px; }\r\n  }\r\n\r\n  @media (max-width: 560px) {\r\n    .ayu-license-modal { padding: 9px; }\r\n    .ayu-license-dialog { max-height: 96vh; border-radius: 19px; }\r\n    .ayu-license-story { padding: 50px 20px 14px; }\r\n    .ayu-license-panel { margin: 14px; padding: 22px; }\r\n    .ayu-license-title { font-size: clamp(28px, 9vw, 38px); }\r\n    .ayu-license-benefits { grid-template-columns: 1fr; }\r\n    .ayu-license-findings { align-items: flex-start; }\r\n    .ayu-license-close { top: 12px; right: 12px; }\r\n  }\r\n\r\n  \/* HIGH-CONTRAST POPUP TEXT *\/\r\n  .ayu-license-modal {\r\n    color-scheme: dark;\r\n    color: #ffffff !important;\r\n  }\r\n\r\n  .ayu-license-modal .ayu-license-dialog {\r\n    color: #ffffff !important;\r\n    background:\r\n      radial-gradient(80% 95% at 0% 0%, rgba(79,110,247,.20), transparent 58%),\r\n      radial-gradient(65% 75% at 100% 100%, rgba(34,230,168,.075), transparent 58%),\r\n      linear-gradient(145deg, #0b1130 0%, #080c23 52%, #060815 100%) !important;\r\n  }\r\n\r\n  .ayu-license-modal .ayu-license-title,\r\n  .ayu-license-modal .ayu-license-panel h3,\r\n  .ayu-license-modal .ayu-license-findings-copy strong {\r\n    color: #ffffff !important;\r\n    -webkit-text-fill-color: #ffffff !important;\r\n  }\r\n\r\n  .ayu-license-modal .ayu-license-title span {\r\n    color: #22e6a8 !important;\r\n    -webkit-text-fill-color: #22e6a8 !important;\r\n  }\r\n\r\n  .ayu-license-modal .ayu-license-lead {\r\n    color: #e2e6ff !important;\r\n    -webkit-text-fill-color: #e2e6ff !important;\r\n  }\r\n\r\n  .ayu-license-modal .ayu-license-panel-intro,\r\n  .ayu-license-modal .ayu-license-findings-copy span,\r\n  .ayu-license-modal .ayu-license-benefits li {\r\n    color: #cbd3ff !important;\r\n    -webkit-text-fill-color: #cbd3ff !important;\r\n  }\r\n\r\n  .ayu-license-modal .ayu-license-note,\r\n  .ayu-license-modal .ayu-license-support,\r\n  .ayu-license-modal .ayu-license-divider {\r\n    color: #aeb9e9 !important;\r\n    -webkit-text-fill-color: #aeb9e9 !important;\r\n  }\r\n\r\n  .ayu-license-modal .ayu-license-label {\r\n    color: #e8ebff !important;\r\n    -webkit-text-fill-color: #e8ebff !important;\r\n  }\r\n\r\n  .ayu-license-modal .ayu-license-eyebrow {\r\n    color: #ffca7a !important;\r\n    -webkit-text-fill-color: #ffca7a !important;\r\n  }\r\n\r\n  .ayu-license-modal .ayu-license-findings-number {\r\n    color: #ff5b7d !important;\r\n    -webkit-text-fill-color: #ff5b7d !important;\r\n  }\r\n\r\n  .ayu-license-modal .ayu-license-input {\r\n    color: #ffffff !important;\r\n    -webkit-text-fill-color: #ffffff !important;\r\n    caret-color: #22e6a8;\r\n    background: #050819 !important;\r\n  }\r\n\r\n  .ayu-license-modal .ayu-license-input::placeholder {\r\n    color: #8996c8 !important;\r\n    -webkit-text-fill-color: #8996c8 !important;\r\n    opacity: 1 !important;\r\n  }\r\n\r\n  .ayu-license-modal .ayu-license-verify,\r\n  .ayu-license-modal .ayu-license-primary {\r\n    color: #ffffff !important;\r\n    -webkit-text-fill-color: #ffffff !important;\r\n  }\r\n\r\n  .ayu-license-modal .ayu-license-secondary {\r\n    color: #dce2ff !important;\r\n    -webkit-text-fill-color: #dce2ff !important;\r\n  }\r\n\r\n  .ayu-license-modal .ayu-license-secondary:hover {\r\n    color: #ffffff !important;\r\n    -webkit-text-fill-color: #ffffff !important;\r\n  }\r\n\r\n  .ayu-license-modal .ayu-license-close {\r\n    color: #d4daff !important;\r\n    -webkit-text-fill-color: #d4daff !important;\r\n  }\r\n\r\n  .ayu-license-modal .ayu-license-status.is-error {\r\n    color: #ffb2c2 !important;\r\n    -webkit-text-fill-color: #ffb2c2 !important;\r\n  }\r\n\r\n  .ayu-license-modal .ayu-license-status.is-info {\r\n    color: #d5dbff !important;\r\n    -webkit-text-fill-color: #d5dbff !important;\r\n  }\r\n\r\n  .ayu-license-modal .ayu-license-status.is-success {\r\n    color: #55f0bd !important;\r\n    -webkit-text-fill-color: #55f0bd !important;\r\n  }\r\n\r\n  @media (prefers-reduced-motion: reduce) {\r\n    .ayu-license-modal,\r\n    .ayu-license-dialog,\r\n    .ayu-license-eyebrow-dot { animation: none !important; transition: none !important; }\r\n  }\r\n<\/style>\r\n\r\n<div class=\"ayu-license-modal\" id=\"ayuLicenseModal\" aria-hidden=\"true\">\r\n  <section class=\"ayu-license-dialog\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"ayuLicenseTitle\" aria-describedby=\"ayuLicenseDescription\">\r\n    <button type=\"button\" class=\"ayu-license-close\" id=\"ayuLicenseClose\" aria-label=\"Close license window\">\r\n      <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M6 6l12 12M18 6 6 18\"\/><\/svg>\r\n    <\/button>\r\n\r\n    <div class=\"ayu-license-grid\">\r\n      <div class=\"ayu-license-story\">\r\n        <div class=\"ayu-license-eyebrow\"><span class=\"ayu-license-eyebrow-dot\"><\/span>Protected mode \u00b7 License required<\/div>\r\n\r\n        <h2 class=\"ayu-license-title\" id=\"ayuLicenseTitle\">Activate AssistYU protection. <span>Reduce your exposure.<\/span><\/h2>\r\n\r\n        <p class=\"ayu-license-lead\" id=\"ayuLicenseDescription\">Protected Mode requires a valid AssistYU license and the corresponding security product. Enter your license if you are already a customer, or contact our security team to get the protection recommended for this report.<\/p>\r\n\r\n        <div class=\"ayu-license-findings\">\r\n          <div class=\"ayu-license-findings-number\" id=\"ayuLicenseFindingCount\">0<\/div>\r\n          <div class=\"ayu-license-findings-copy\">\r\n            <strong>issues detected on your current connection<\/strong>\r\n            <span id=\"ayuLicenseFindingDetails\">Review the findings behind this window and speak with our team for an appropriate remediation plan.<\/span>\r\n          <\/div>\r\n        <\/div>\r\n\r\n        <ul class=\"ayu-license-benefits\">\r\n          <li><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M5 12l4 4L19 6\"\/><\/svg>Encrypted network traffic<\/li>\r\n          <li><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M5 12l4 4L19 6\"\/><\/svg>Public IP and location masking<\/li>\r\n          <li><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M5 12l4 4L19 6\"\/><\/svg>WebRTC leak mitigation<\/li>\r\n          <li><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M5 12l4 4L19 6\"\/><\/svg>Guided setup and human support<\/li>\r\n        <\/ul>\r\n\r\n        <p class=\"ayu-license-note\">Protected Mode cannot be enabled by a visual website switch alone. Protection requires a verified license plus installation and configuration of the relevant AssistYU security product.<\/p>\r\n      <\/div>\r\n\r\n      <aside class=\"ayu-license-panel\">\r\n        <div class=\"ayu-license-lock\">\r\n          <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><rect x=\"4\" y=\"10\" width=\"16\" height=\"10\" rx=\"2\"\/><path d=\"M8 10V7a4 4 0 0 1 8 0v3M12 14v2\"\/><\/svg>\r\n        <\/div>\r\n\r\n        <h3>Already have a license?<\/h3>\r\n        <p class=\"ayu-license-panel-intro\">Enter the activation key supplied by AssistYU. The key is only sent to your configured secure verification endpoint.<\/p>\r\n\r\n        <form class=\"ayu-license-form\" id=\"ayuLicenseForm\" novalidate>\r\n          <label class=\"ayu-license-label\" for=\"ayuLicenseKey\">AssistYU license key<\/label>\r\n          <div class=\"ayu-license-input-wrap\">\r\n            <input class=\"ayu-license-input\" id=\"ayuLicenseKey\" name=\"licenseKey\" type=\"password\" autocomplete=\"off\" spellcheck=\"false\" maxlength=\"80\" placeholder=\"AYU-XXXX-XXXX-XXXX\">\r\n            <svg class=\"ayu-license-key-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><circle cx=\"8\" cy=\"15\" r=\"4\"\/><path d=\"M11 12l8-8M15 8l3 3M18 5l2 2\"\/><\/svg>\r\n          <\/div>\r\n          <button type=\"submit\" class=\"ayu-license-verify\" id=\"ayuLicenseVerify\">Verify license &amp; continue<\/button>\r\n          <div class=\"ayu-license-status\" id=\"ayuLicenseStatus\" role=\"status\" aria-live=\"polite\"><\/div>\r\n        <\/form>\r\n\r\n        <div class=\"ayu-license-divider\">Need a license or assistance?<\/div>\r\n\r\n        <div class=\"ayu-license-actions\">\r\n          <a class=\"ayu-license-primary\" href=\"https:\/\/assistyu.com\/contact\/\" target=\"_blank\" rel=\"noopener\">\r\n            Contact the security team\r\n            <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\"><path d=\"M5 12h14M12 5l7 7-7 7\"\/><\/svg>\r\n          <\/a>\r\n          <a class=\"ayu-license-secondary\" href=\"https:\/\/assistyu.com\/security-products\/\" target=\"_blank\" rel=\"noopener\">View AssistYU security products<\/a>\r\n          <a class=\"ayu-license-secondary\" href=\"tel:+34951550227\">Call +34 9 515 502 27<\/a>\r\n        <\/div>\r\n\r\n        <p class=\"ayu-license-support\">Assisted onboarding \u00b7 <b>Human support<\/b> \u00b7 Secure activation<\/p>\r\n      <\/aside>\r\n    <\/div>\r\n  <\/section>\r\n<\/div>\r\n\r\n<script>\r\n(function () {\r\n  'use strict';\r\n\r\n  \/*\r\n   * Optional secure verification endpoint.\r\n   * Leave empty until your server endpoint is ready.\r\n   * Expected POST body:\r\n   *   { \"licenseKey\": \"AYU-...\", \"context\": \"network-scan\" }\r\n   * Expected JSON response:\r\n   *   { \"valid\": true, \"activationUrl\": \"https:\/\/your-secure-installer-url\" }\r\n   *\r\n   * IMPORTANT: never place valid license keys or secret validation logic here.\r\n   *\/\r\n  var ASSISTYU_LICENSE_VERIFY_ENDPOINT = '';\r\n\r\n  var modal = document.getElementById('ayuLicenseModal');\r\n  var dialog = modal ? modal.querySelector('.ayu-license-dialog') : null;\r\n  var closeButton = document.getElementById('ayuLicenseClose');\r\n  var form = document.getElementById('ayuLicenseForm');\r\n  var keyInput = document.getElementById('ayuLicenseKey');\r\n  var verifyButton = document.getElementById('ayuLicenseVerify');\r\n  var statusBox = document.getElementById('ayuLicenseStatus');\r\n  var findingCount = document.getElementById('ayuLicenseFindingCount');\r\n  var findingDetails = document.getElementById('ayuLicenseFindingDetails');\r\n  var returnFocus = null;\r\n\r\n  if (!modal || !dialog) return;\r\n\r\n  function readNumber(id) {\r\n    var element = document.getElementById(id);\r\n    var number = element ? parseInt(element.textContent, 10) : 0;\r\n    return isFinite(number) ? number : 0;\r\n  }\r\n\r\n  function updateFindingSummary() {\r\n    var displayedTotal = readNumber('threats-num');\r\n    var critical = readNumber('crit-n');\r\n    var warning = readNumber('warn-n');\r\n    var total = displayedTotal || critical + warning;\r\n\r\n    findingCount.textContent = total;\r\n\r\n    if (total > 0) {\r\n      findingDetails.textContent = critical + ' critical and ' + warning + ' warning signal' + (warning === 1 ? '' : 's') + ' were identified in your verdict.';\r\n    } else {\r\n      findingDetails.textContent = 'Enter your license or contact AssistYU to review the protection available for your connection.';\r\n    }\r\n  }\r\n\r\n  function showStatus(message, type) {\r\n    statusBox.textContent = message;\r\n    statusBox.className = 'ayu-license-status is-visible ' + (type || 'is-info');\r\n  }\r\n\r\n  function openModal(trigger) {\r\n    updateFindingSummary();\r\n    returnFocus = trigger || document.activeElement;\r\n    modal.classList.add('is-open');\r\n    modal.setAttribute('aria-hidden', 'false');\r\n    document.documentElement.classList.add('ayu-license-open');\r\n    document.body.classList.add('ayu-license-open');\r\n\r\n    window.setTimeout(function () {\r\n      if (keyInput) keyInput.focus();\r\n    }, 120);\r\n  }\r\n\r\n  function closeModal() {\r\n    modal.classList.remove('is-open');\r\n    modal.setAttribute('aria-hidden', 'true');\r\n    document.documentElement.classList.remove('ayu-license-open');\r\n    document.body.classList.remove('ayu-license-open');\r\n\r\n    var protectedToggle = document.getElementById('ptog');\r\n    if (protectedToggle) protectedToggle.checked = false;\r\n\r\n    if (returnFocus && typeof returnFocus.focus === 'function') {\r\n      returnFocus.focus();\r\n    }\r\n  }\r\n\r\n  function validKeyFormat(key) {\r\n    return \/^[A-Z0-9][A-Z0-9-]{10,79}$\/i.test(key) && key.indexOf('-') !== -1;\r\n  }\r\n\r\n  function verifyLicense(event) {\r\n    event.preventDefault();\r\n\r\n    var key = keyInput.value.trim();\r\n\r\n    if (!key) {\r\n      showStatus('Enter the license key supplied by AssistYU.', 'is-error');\r\n      keyInput.focus();\r\n      return;\r\n    }\r\n\r\n    if (!validKeyFormat(key)) {\r\n      showStatus('This license-key format is not recognized. Check the key or contact the AssistYU security team.', 'is-error');\r\n      return;\r\n    }\r\n\r\n    if (!ASSISTYU_LICENSE_VERIFY_ENDPOINT) {\r\n      showStatus('Secure license verification is not connected on this page yet. Please contact AssistYU to verify your license and complete protected-mode installation.', 'is-info');\r\n      return;\r\n    }\r\n\r\n    verifyButton.disabled = true;\r\n    verifyButton.textContent = 'Verifying securely\u2026';\r\n\r\n    fetch(ASSISTYU_LICENSE_VERIFY_ENDPOINT, {\r\n      method: 'POST',\r\n      headers: {\r\n        'Content-Type': 'application\/json',\r\n        'Accept': 'application\/json'\r\n      },\r\n      credentials: 'same-origin',\r\n      body: JSON.stringify({\r\n        licenseKey: key,\r\n        context: 'network-scan'\r\n      })\r\n    })\r\n      .then(function (response) {\r\n        if (!response.ok) throw new Error('Verification service unavailable');\r\n        return response.json();\r\n      })\r\n      .then(function (result) {\r\n        if (result && result.valid) {\r\n          showStatus('License verified. Continue to the secure AssistYU installer to enable protection.', 'is-success');\r\n          verifyButton.textContent = 'License verified';\r\n\r\n          if (result.activationUrl) {\r\n            window.setTimeout(function () {\r\n              window.location.href = result.activationUrl;\r\n            }, 900);\r\n          }\r\n        } else {\r\n          showStatus((result && result.message) || 'The license could not be verified. Contact AssistYU if you believe this is an error.', 'is-error');\r\n          verifyButton.disabled = false;\r\n          verifyButton.textContent = 'Verify license & continue';\r\n        }\r\n      })\r\n      .catch(function () {\r\n        showStatus('The verification service could not be reached. Try again or contact AssistYU for assisted activation.', 'is-error');\r\n        verifyButton.disabled = false;\r\n        verifyButton.textContent = 'Verify license & continue';\r\n      });\r\n  }\r\n\r\n  function focusableElements() {\r\n    return Array.prototype.slice.call(\r\n      dialog.querySelectorAll('a[href], button:not([disabled]), input:not([disabled]), [tabindex]:not([tabindex=\"-1\"])')\r\n    ).filter(function (element) {\r\n      return element.offsetParent !== null;\r\n    });\r\n  }\r\n\r\n  \/*\r\n   * Capture the click before the old demo-safe-mode listener can run.\r\n   * No original scan\/verdict code has to be removed or changed.\r\n   *\/\r\n  document.addEventListener('click', function (event) {\r\n    var target = event.target;\r\n    var toggleRow = target && target.closest ? target.closest('#tgw') : null;\r\n\r\n    if (!toggleRow) return;\r\n\r\n    event.preventDefault();\r\n    event.stopPropagation();\r\n    event.stopImmediatePropagation();\r\n\r\n    var checkbox = document.getElementById('ptog');\r\n    if (checkbox) checkbox.checked = false;\r\n\r\n    openModal(toggleRow);\r\n  }, true);\r\n\r\n  \/* Also block any programmatic\/user change before the old handler receives it. *\/\r\n  document.addEventListener('change', function (event) {\r\n    if (!event.target || event.target.id !== 'ptog') return;\r\n\r\n    event.preventDefault();\r\n    event.stopPropagation();\r\n    event.stopImmediatePropagation();\r\n    event.target.checked = false;\r\n    openModal(document.getElementById('tgw'));\r\n  }, true);\r\n\r\n  \/* Give the existing row accessible button behavior without changing its HTML. *\/\r\n  var toggleRow = document.getElementById('tgw');\r\n  if (toggleRow) {\r\n    toggleRow.setAttribute('role', 'button');\r\n    toggleRow.setAttribute('tabindex', '0');\r\n    toggleRow.setAttribute('aria-haspopup', 'dialog');\r\n    toggleRow.setAttribute('aria-controls', 'ayuLicenseModal');\r\n    toggleRow.setAttribute('aria-label', 'Protected Mode. AssistYU license required.');\r\n\r\n    toggleRow.addEventListener('keydown', function (event) {\r\n      if (event.key === 'Enter' || event.key === ' ') {\r\n        event.preventDefault();\r\n        openModal(toggleRow);\r\n      }\r\n    });\r\n  }\r\n\r\n  closeButton.addEventListener('click', closeModal);\r\n  form.addEventListener('submit', verifyLicense);\r\n\r\n  modal.addEventListener('mousedown', function (event) {\r\n    if (event.target === modal) closeModal();\r\n  });\r\n\r\n  document.addEventListener('keydown', function (event) {\r\n    if (!modal.classList.contains('is-open')) return;\r\n\r\n    if (event.key === 'Escape') {\r\n      event.preventDefault();\r\n      closeModal();\r\n      return;\r\n    }\r\n\r\n    if (event.key !== 'Tab') return;\r\n\r\n    var nodes = focusableElements();\r\n    if (!nodes.length) return;\r\n\r\n    var first = nodes[0];\r\n    var last = nodes[nodes.length - 1];\r\n\r\n    if (event.shiftKey && document.activeElement === first) {\r\n      event.preventDefault();\r\n      last.focus();\r\n    } else if (!event.shiftKey && document.activeElement === last) {\r\n      event.preventDefault();\r\n      first.focus();\r\n    }\r\n  });\r\n})();\r\n<\/script>\r\n<\/body>\r\n<\/html>\t\t\t\t<\/div>\n\t\t\n<\/div>\n<footer class=\"elementor-element elementor-element-49b1d2b e-con-full e-flex e-con e-parent\" data-id=\"49b1d2b\" data-element_type=\"container\" data-e-type=\"container\" data-settings=\"{&quot;background_background&quot;:&quot;gradient&quot;}\">\n\t\t<div class=\"elementor-element elementor-element-57fe517 e-con-full e-flex e-con e-child\" data-id=\"57fe517\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-64952fc e-con-full e-flex e-con e-child\" data-id=\"64952fc\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-a6f2202 elementor-widget elementor-widget-int-logo\" data-id=\"a6f2202\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"int-logo.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t        <div class=\"tg-logo\">\r\n            <a href=\"https:\/\/assistyu.com\/\"><img decoding=\"async\" data-src=\"https:\/\/assistyu.com\/wp-content\/uploads\/2024\/03\/AssistYu-no-background-2.png\" alt=\"\" title=\"\" src=\"data:image\/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==\" class=\"lazyload\" style=\"--smush-placeholder-width: 292px; --smush-placeholder-aspect-ratio: 292\/100;\"><\/a>\r\n        <\/div>\r\n        \t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a192034 elementor-mobile-align-center elementor-icon-list--layout-inline elementor-list-item-link-full_width elementor-widget elementor-widget-icon-list\" data-id=\"a192034\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-list.default\">\n\t\t\t\t\t\t\t<ul class=\"elementor-icon-list-items elementor-inline-items\">\n\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/maps.app.goo.gl\/PnxnHJXGZ3isdPbH6\" target=\"_blank\" rel=\"noopener\">\n\n\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">Estrategias de Marketing LE Paradise - AssistYu<\/span>\n\t\t\t\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t<\/ul>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-2b25de6 e-con-full e-flex e-con e-child\" data-id=\"2b25de6\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-2e0876b e-con-full e-flex e-con e-child\" data-id=\"2e0876b\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-2f7bae8 elementor-mobile-align-center elementor-icon-list--layout-inline elementor-list-item-link-full_width elementor-widget elementor-widget-icon-list\" data-id=\"2f7bae8\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-list.default\">\n\t\t\t\t\t\t\t<ul class=\"elementor-icon-list-items elementor-inline-items\">\n\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"tel:34951550227\">\n\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-icon\">\n\t\t\t\t\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-fas-phone-alt\" viewBox=\"0 0 512 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M497.39 361.8l-112-48a24 24 0 0 0-28 6.9l-49.6 60.6A370.66 370.66 0 0 1 130.6 204.11l60.6-49.6a23.94 23.94 0 0 0 6.9-28l-48-112A24.16 24.16 0 0 0 122.6.61l-104 24A24 24 0 0 0 0 48c0 256.5 207.9 464 464 464a24 24 0 0 0 23.4-18.6l24-104a24.29 24.29 0 0 0-14.01-27.6z\"><\/path><\/svg>\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">+34 951 550 227<\/span>\n\t\t\t\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"mailto:office@assistyu.com\">\n\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-icon\">\n\t\t\t\t\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-fas-envelope\" viewBox=\"0 0 512 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M502.3 190.8c3.9-3.1 9.7-.2 9.7 4.7V400c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V195.6c0-5 5.7-7.8 9.7-4.7 22.4 17.4 52.1 39.5 154.1 113.6 21.1 15.4 56.7 47.8 92.2 47.6 35.7.3 72-32.8 92.3-47.6 102-74.1 131.6-96.3 154-113.7zM256 320c23.2.4 56.6-29.2 73.4-41.4 132.7-96.3 142.8-104.7 173.4-128.7 5.8-4.5 9.2-11.5 9.2-18.9v-19c0-26.5-21.5-48-48-48H48C21.5 64 0 85.5 0 112v19c0 7.4 3.4 14.3 9.2 18.9 30.6 23.9 40.7 32.4 173.4 128.7 16.8 12.2 50.2 41.8 73.4 41.4z\"><\/path><\/svg>\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">office@assistyu.com<\/span>\n\t\t\t\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/maps.app.goo.gl\/PnxnHJXGZ3isdPbH6\" target=\"_blank\" rel=\"noopener\">\n\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-icon\">\n\t\t\t\t\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-fas-map-marker-alt\" viewBox=\"0 0 384 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M172.268 501.67C26.97 291.031 0 269.413 0 192 0 85.961 85.961 0 192 0s192 85.961 192 192c0 77.413-26.97 99.031-172.268 309.67-9.535 13.774-29.93 13.773-39.464 0zM192 272c44.183 0 80-35.817 80-80s-35.817-80-80-80-80 35.817-80 80 35.817 80 80 80z\"><\/path><\/svg>\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">C. Lope de Vega 60, 29631 Benalmadena<\/span>\n\t\t\t\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t<\/ul>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e32a1f3 elementor-icon-list--layout-inline elementor-align-center elementor-hidden-mobile elementor-list-item-link-full_width elementor-widget elementor-widget-icon-list\" data-id=\"e32a1f3\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"icon-list.default\">\n\t\t\t\t\t\t\t<ul class=\"elementor-icon-list-items elementor-inline-items\">\n\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/assistyu.com\/services\/\">\n\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-icon\">\n\t\t\t\t\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-fas-greater-than-equal\" viewBox=\"0 0 448 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M55.22 107.69l175.56 68.09-175.44 68.05c-18.39 6.03-27.88 24.39-21.2 41l12.09 30.08c6.68 16.61 26.99 25.19 45.38 19.15L393.02 214.2c13.77-4.52 22.98-16.61 22.98-30.17v-15.96c0-13.56-9.21-25.65-22.98-30.17L91.3 17.92c-18.29-6-38.51 2.53-45.15 19.06L34.12 66.9c-6.64 16.53 2.81 34.79 21.1 40.79zM424 400H24c-13.25 0-24 10.74-24 24v48c0 13.25 10.75 24 24 24h400c13.25 0 24-10.75 24-24v-48c0-13.26-10.75-24-24-24z\"><\/path><\/svg>\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">Services<\/span>\n\t\t\t\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/assistyu.com\/security-products\/\">\n\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-icon\">\n\t\t\t\t\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-fas-greater-than-equal\" viewBox=\"0 0 448 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M55.22 107.69l175.56 68.09-175.44 68.05c-18.39 6.03-27.88 24.39-21.2 41l12.09 30.08c6.68 16.61 26.99 25.19 45.38 19.15L393.02 214.2c13.77-4.52 22.98-16.61 22.98-30.17v-15.96c0-13.56-9.21-25.65-22.98-30.17L91.3 17.92c-18.29-6-38.51 2.53-45.15 19.06L34.12 66.9c-6.64 16.53 2.81 34.79 21.1 40.79zM424 400H24c-13.25 0-24 10.74-24 24v48c0 13.25 10.75 24 24 24h400c13.25 0 24-10.75 24-24v-48c0-13.26-10.75-24-24-24z\"><\/path><\/svg>\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">Products<\/span>\n\t\t\t\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/assistyu.com\/small-business\/\">\n\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-icon\">\n\t\t\t\t\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-fas-greater-than-equal\" viewBox=\"0 0 448 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M55.22 107.69l175.56 68.09-175.44 68.05c-18.39 6.03-27.88 24.39-21.2 41l12.09 30.08c6.68 16.61 26.99 25.19 45.38 19.15L393.02 214.2c13.77-4.52 22.98-16.61 22.98-30.17v-15.96c0-13.56-9.21-25.65-22.98-30.17L91.3 17.92c-18.29-6-38.51 2.53-45.15 19.06L34.12 66.9c-6.64 16.53 2.81 34.79 21.1 40.79zM424 400H24c-13.25 0-24 10.74-24 24v48c0 13.25 10.75 24 24 24h400c13.25 0 24-10.75 24-24v-48c0-13.26-10.75-24-24-24z\"><\/path><\/svg>\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">Small Business<\/span>\n\t\t\t\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/assistyu.com\/partnerships\/\">\n\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-icon\">\n\t\t\t\t\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-fas-greater-than-equal\" viewBox=\"0 0 448 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M55.22 107.69l175.56 68.09-175.44 68.05c-18.39 6.03-27.88 24.39-21.2 41l12.09 30.08c6.68 16.61 26.99 25.19 45.38 19.15L393.02 214.2c13.77-4.52 22.98-16.61 22.98-30.17v-15.96c0-13.56-9.21-25.65-22.98-30.17L91.3 17.92c-18.29-6-38.51 2.53-45.15 19.06L34.12 66.9c-6.64 16.53 2.81 34.79 21.1 40.79zM424 400H24c-13.25 0-24 10.74-24 24v48c0 13.25 10.75 24 24 24h400c13.25 0 24-10.75 24-24v-48c0-13.26-10.75-24-24-24z\"><\/path><\/svg>\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">Partnership<\/span>\n\t\t\t\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t\t\t<li class=\"elementor-icon-list-item elementor-inline-item\">\n\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/assistyu.com\/contact\/\">\n\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-icon\">\n\t\t\t\t\t\t\t<svg aria-hidden=\"true\" class=\"e-font-icon-svg e-fas-greater-than-equal\" viewBox=\"0 0 448 512\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M55.22 107.69l175.56 68.09-175.44 68.05c-18.39 6.03-27.88 24.39-21.2 41l12.09 30.08c6.68 16.61 26.99 25.19 45.38 19.15L393.02 214.2c13.77-4.52 22.98-16.61 22.98-30.17v-15.96c0-13.56-9.21-25.65-22.98-30.17L91.3 17.92c-18.29-6-38.51 2.53-45.15 19.06L34.12 66.9c-6.64 16.53 2.81 34.79 21.1 40.79zM424 400H24c-13.25 0-24 10.74-24 24v48c0 13.25 10.75 24 24 24h400c13.25 0 24-10.75 24-24v-48c0-13.26-10.75-24-24-24z\"><\/path><\/svg>\t\t\t\t\t\t<\/span>\n\t\t\t\t\t\t\t\t\t\t<span class=\"elementor-icon-list-text\">Contact Us<\/span>\n\t\t\t\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t<\/li>\n\t\t\t\t\t\t<\/ul>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2a77cf4 elementor-widget-divider--view-line elementor-widget elementor-widget-divider\" data-id=\"2a77cf4\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"divider.default\">\n\t\t\t\t\t\t\t<div class=\"elementor-divider\">\n\t\t\t<span class=\"elementor-divider-separator\">\n\t\t\t\t\t\t<\/span>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t<div class=\"elementor-element elementor-element-e0be51b e-con-full e-flex e-con e-child\" data-id=\"e0be51b\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t<div class=\"elementor-element elementor-element-56db23f e-con-full e-flex e-con e-child\" data-id=\"56db23f\" data-element_type=\"container\" data-e-type=\"container\">\n\t\t\t\t<div class=\"elementor-element elementor-element-5a7b618 elementor-widget elementor-widget-int-footer-nav\" data-id=\"5a7b618\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"int-footer-nav.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\r\n        <div class=\"tg-copyright-right text-center text-md-end\">\r\n                    <a class=\"text-anim-2\" href=\"https:\/\/assistyu.com\/security-insights\/\">Insights<\/a>\r\n                    <a class=\"text-anim-2\" href=\"https:\/\/assistyu.com\/about-assistyu\/\">About Us<\/a>\r\n                    <a class=\"text-anim-2\" href=\"https:\/\/assistyu.com\/documentation-and-guides\/\">Documentation<\/a>\r\n                    <a class=\"text-anim-2\" href=\"https:\/\/assistyu.com\/consent\/\">Consent Agreement<\/a>\r\n                    <a class=\"text-anim-2\" href=\"https:\/\/assistyu.com\/privacy-policy\/\">Privacy Policy<\/a>\r\n                    <a class=\"text-anim-2\" href=\"https:\/\/assistyu.com\/legal-notice-terms-conditions\/\">Terms &amp; Conditions<\/a>\r\n                    <a class=\"text-anim-2\" href=\"https:\/\/assistyu.com\/delivery-refunds-policy\/\">Delivery &amp; Refunds<\/a>\r\n                <\/div>\r\n        \t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e366338 elementor-widget elementor-widget-text-editor\" data-id=\"e366338\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t\t\t\t\t\t<p>Copyright @ 2026 <a href=\"https:\/\/assistyu.com\/\">AssistYu<\/a>. All Rights Reserved<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<\/footer>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>AssistYU \u2014 Network Scan Network Security Scan Real-time diagnostic of your IP exposure, browser fingerprint, open ports, blacklists, and threat intelligence \u2014 entirely client-side, zero data stored. Start Security Scan IP &amp; location Threat intel Browser fingerprint Speed test Risk score Engine Active Heuristics Live IP Geolocation Ready Threat Intel Online Bus UPDATED &#8211;:&#8211;:&#8211; \u25b2 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":6825,"parent":6769,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"elementor_header_footer","meta":{"inline_featured_image":false,"footnotes":""},"class_list":["post-7083","page","type-page","status-publish","has-post-thumbnail","hentry"],"_links":{"self":[{"href":"https:\/\/assistyu.com\/fr\/wp-json\/wp\/v2\/pages\/7083","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/assistyu.com\/fr\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/assistyu.com\/fr\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/assistyu.com\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/assistyu.com\/fr\/wp-json\/wp\/v2\/comments?post=7083"}],"version-history":[{"count":56,"href":"https:\/\/assistyu.com\/fr\/wp-json\/wp\/v2\/pages\/7083\/revisions"}],"predecessor-version":[{"id":8007,"href":"https:\/\/assistyu.com\/fr\/wp-json\/wp\/v2\/pages\/7083\/revisions\/8007"}],"up":[{"embeddable":true,"href":"https:\/\/assistyu.com\/fr\/wp-json\/wp\/v2\/pages\/6769"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/assistyu.com\/fr\/wp-json\/wp\/v2\/media\/6825"}],"wp:attachment":[{"href":"https:\/\/assistyu.com\/fr\/wp-json\/wp\/v2\/media?parent=7083"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}