|
|
<!DOCTYPE html> |
|
|
<html lang="en"> |
|
|
<head> |
|
|
<meta charset="UTF-8"> |
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
|
|
<title>SecureVPN - Fast & Secure Virtual Private Network</title> |
|
|
<script src="https://cdn.tailwindcss.com"></script> |
|
|
<script> |
|
|
tailwind.config = { |
|
|
theme: { |
|
|
extend: { |
|
|
colors: { |
|
|
'vpn-primary': '#4F46E5', |
|
|
'vpn-secondary': '#10B981', |
|
|
'vpn-accent': '#F59E0B', |
|
|
'vpn-dark': '#1E293B', |
|
|
'vpn-light': '#F8FAFC', |
|
|
'vpn-europe': '#3B82F6', |
|
|
'vpn-usa': '#EC4899', |
|
|
'vpn-asia': '#F97316', |
|
|
'vpn-oceania': '#14B8A6', |
|
|
'vpn-southamerica': '#8B5CF6', |
|
|
'vpn-africa': '#EF4444' |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
</script> |
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
|
|
|
|
|
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" /> |
|
|
<style> |
|
|
.gradient-bg { |
|
|
background: linear-gradient(135deg, #6B73FF 0%, #000DFF 100%); |
|
|
} |
|
|
.server-marker { |
|
|
width: 16px; |
|
|
height: 16px; |
|
|
background-color: #4F46E5; |
|
|
border-radius: 50%; |
|
|
border: 2px solid white; |
|
|
position: relative; |
|
|
z-index: 1000; |
|
|
} |
|
|
.server-marker.active { |
|
|
background-color: #10B981; |
|
|
box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.3); |
|
|
} |
|
|
.connection-animation { |
|
|
animation: pulse 2s infinite; |
|
|
} |
|
|
@keyframes pulse { |
|
|
0% { opacity: 0.7; } |
|
|
50% { opacity: 1; } |
|
|
100% { opacity: 0.7; } |
|
|
} |
|
|
.vpn-toggle { |
|
|
transition: all 0.3s ease; |
|
|
} |
|
|
.vpn-toggle.active { |
|
|
background-color: #10B981; |
|
|
} |
|
|
.speedometer { |
|
|
position: relative; |
|
|
width: 150px; |
|
|
height: 150px; |
|
|
} |
|
|
.speedometer-circle { |
|
|
position: absolute; |
|
|
width: 100%; |
|
|
height: 100%; |
|
|
border-radius: 50%; |
|
|
border: 10px solid #E5E7EB; |
|
|
} |
|
|
.speedometer-fill { |
|
|
position: absolute; |
|
|
width: 100%; |
|
|
height: 100%; |
|
|
border-radius: 50%; |
|
|
border: 10px solid transparent; |
|
|
border-top-color: #4F46E5; |
|
|
border-right-color: #4F46E5; |
|
|
transform: rotate(45deg); |
|
|
transition: transform 0.5s ease; |
|
|
} |
|
|
#server-map { |
|
|
height: 400px; |
|
|
width: 100%; |
|
|
border-radius: 0.75rem; |
|
|
z-index: 1; |
|
|
} |
|
|
.country-flag { |
|
|
width: 16px; |
|
|
height: 12px; |
|
|
display: inline-block; |
|
|
margin-right: 6px; |
|
|
background-size: cover; |
|
|
border: 1px solid #e5e7eb; |
|
|
} |
|
|
.region-tag { |
|
|
display: inline-block; |
|
|
padding: 2px 6px; |
|
|
border-radius: 4px; |
|
|
font-size: 10px; |
|
|
font-weight: bold; |
|
|
text-transform: uppercase; |
|
|
margin-left: 6px; |
|
|
} |
|
|
.region-europe { |
|
|
background-color: #3B82F6; |
|
|
color: white; |
|
|
} |
|
|
.region-usa { |
|
|
background-color: #EC4899; |
|
|
color: white; |
|
|
} |
|
|
.region-asia { |
|
|
background-color: #F97316; |
|
|
color: white; |
|
|
} |
|
|
.region-oceania { |
|
|
background-color: #14B8A6; |
|
|
color: white; |
|
|
} |
|
|
.region-southamerica { |
|
|
background-color: #8B5CF6; |
|
|
color: white; |
|
|
} |
|
|
.region-africa { |
|
|
background-color: #EF4444; |
|
|
color: white; |
|
|
} |
|
|
.server-card { |
|
|
transition: all 0.3s ease; |
|
|
} |
|
|
.server-card:hover { |
|
|
transform: translateY(-2px); |
|
|
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1); |
|
|
} |
|
|
.ping-indicator { |
|
|
width: 10px; |
|
|
height: 10px; |
|
|
border-radius: 50%; |
|
|
display: inline-block; |
|
|
margin-right: 4px; |
|
|
} |
|
|
.ping-excellent { |
|
|
background-color: #10B981; |
|
|
} |
|
|
.ping-good { |
|
|
background-color: #84CC16; |
|
|
} |
|
|
.ping-average { |
|
|
background-color: #F59E0B; |
|
|
} |
|
|
.ping-poor { |
|
|
background-color: #EF4444; |
|
|
} |
|
|
</style> |
|
|
</head> |
|
|
<body class="bg-vpn-light font-sans"> |
|
|
|
|
|
<header class="gradient-bg text-white shadow-lg"> |
|
|
<div class="container mx-auto px-4 py-4 flex justify-between items-center"> |
|
|
<div class="flex items-center space-x-2"> |
|
|
<i class="fas fa-lock text-2xl"></i> |
|
|
<h1 class="text-2xl font-bold">SecureVPN</h1> |
|
|
</div> |
|
|
<nav class="hidden md:flex space-x-8"> |
|
|
<a href="#" class="hover:text-gray-200 transition">Features</a> |
|
|
<a href="#" class="hover:text-gray-200 transition">Pricing</a> |
|
|
<a href="#" class="hover:text-gray-200 transition">Servers</a> |
|
|
<a href="#" class="hover:text-gray-200 transition">Support</a> |
|
|
</nav> |
|
|
<div class="flex items-center space-x-4"> |
|
|
<button class="px-4 py-2 rounded-full bg-white text-blue-600 font-medium hover:bg-gray-100 transition">Sign In</button> |
|
|
<button class="md:hidden text-2xl"> |
|
|
<i class="fas fa-bars"></i> |
|
|
</button> |
|
|
</div> |
|
|
</div> |
|
|
</header> |
|
|
|
|
|
|
|
|
<main class="container mx-auto px-4 py-8"> |
|
|
|
|
|
<div class="bg-white rounded-xl shadow-md overflow-hidden mb-8"> |
|
|
<div class="p-6 md:p-8"> |
|
|
<div class="flex flex-col md:flex-row justify-between items-start md:items-center mb-6"> |
|
|
<div> |
|
|
<h2 class="text-2xl font-bold text-gray-800">VPN Connection</h2> |
|
|
<p class="text-gray-600">Secure your internet connection with one click</p> |
|
|
</div> |
|
|
<div class="mt-4 md:mt-0 flex items-center space-x-4"> |
|
|
<div class="flex items-center space-x-2"> |
|
|
<div class="w-3 h-3 rounded-full bg-gray-300"></div> |
|
|
<span class="text-sm text-gray-600" id="connection-status">Disconnected</span> |
|
|
</div> |
|
|
<div class="relative"> |
|
|
<div class="vpn-toggle w-16 h-8 bg-gray-300 rounded-full flex items-center cursor-pointer" id="vpn-toggle"> |
|
|
<div class="w-6 h-6 bg-white rounded-full shadow-md transform translate-x-1 transition"></div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="flex flex-col lg:flex-row gap-8"> |
|
|
|
|
|
<div class="flex-1 relative"> |
|
|
<div id="server-map" class="bg-gray-100 rounded-xl"></div> |
|
|
|
|
|
<div class="mt-4"> |
|
|
<h3 class="text-lg font-semibold text-gray-800 mb-3">Server Locations</h3> |
|
|
<div class="flex flex-wrap gap-2 mb-4"> |
|
|
<button class="region-filter px-3 py-1 rounded-full text-xs font-medium bg-vpn-europe text-white" data-region="europe">Europe</button> |
|
|
<button class="region-filter px-3 py-1 rounded-full text-xs font-medium bg-vpn-usa text-white" data-region="usa">USA</button> |
|
|
<button class="region-filter px-3 py-1 rounded-full text-xs font-medium bg-vpn-asia text-white" data-region="asia">Asia</button> |
|
|
<button class="region-filter px-3 py-1 rounded-full text-xs font-medium bg-vpn-oceania text-white" data-region="oceania">Oceania</button> |
|
|
<button class="region-filter px-3 py-1 rounded-full text-xs font-medium bg-vpn-southamerica text-white" data-region="southamerica">South America</button> |
|
|
<button class="region-filter px-3 py-1 rounded-full text-xs font-medium bg-vpn-africa text-white" data-region="africa">Africa</button> |
|
|
<button class="region-filter px-3 py-1 rounded-full text-xs font-medium bg-gray-200 text-gray-800" data-region="all">All Regions</button> |
|
|
</div> |
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3" id="server-buttons-container"> |
|
|
|
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="flex-1"> |
|
|
<div class="bg-gray-50 rounded-xl p-6 h-full"> |
|
|
<div class="flex flex-col h-full"> |
|
|
<div class="mb-6"> |
|
|
<h3 class="text-lg font-semibold text-gray-800 mb-2">Current Connection</h3> |
|
|
<div class="flex items-center space-x-3"> |
|
|
<div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center"> |
|
|
<i class="fas fa-shield-alt text-blue-600"></i> |
|
|
</div> |
|
|
<div> |
|
|
<p class="font-medium" id="current-server">London #7</p> |
|
|
<p class="text-sm text-gray-600" id="server-ip">191.32.56.201</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="mb-6"> |
|
|
<h3 class="text-lg font-semibold text-gray-800 mb-4">Connection Speed</h3> |
|
|
<div class="flex justify-around items-center"> |
|
|
<div class="text-center"> |
|
|
<div class="speedometer mx-auto mb-2"> |
|
|
<div class="speedometer-circle"></div> |
|
|
<div class="speedometer-fill" id="download-speedometer"></div> |
|
|
</div> |
|
|
<p class="text-sm text-gray-600">Download</p> |
|
|
<p class="font-bold" id="download-speed">0 Mbps</p> |
|
|
</div> |
|
|
<div class="text-center"> |
|
|
<div class="speedometer mx-auto mb-2"> |
|
|
<div class="speedometer-circle"></div> |
|
|
<div class="speedometer-fill" id="upload-speedometer"></div> |
|
|
</div> |
|
|
<p class="text-sm text-gray-600">Upload</p> |
|
|
<p class="font-bold" id="upload-speed">0 Mbps</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
<div class="mt-auto"> |
|
|
<div class="flex justify-between items-center mb-2"> |
|
|
<span class="text-sm text-gray-600">Data Transferred</span> |
|
|
<span class="text-sm font-medium" id="data-transferred">0 MB</span> |
|
|
</div> |
|
|
<div class="w-full bg-gray-200 rounded-full h-2"> |
|
|
<div class="bg-blue-600 h-2 rounded-full" id="data-progress" style="width: 0%"></div> |
|
|
</div> |
|
|
<div class="flex justify-between items-center mt-4"> |
|
|
<span class="text-sm text-gray-600">Connection Time</span> |
|
|
<span class="text-sm font-medium" id="connection-time">00:00:00</span> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="mb-12"> |
|
|
<h2 class="text-2xl font-bold text-gray-800 mb-6">Why Choose SecureVPN?</h2> |
|
|
<div class="grid grid-cols-1 md:grid-cols-3 gap-6"> |
|
|
<div class="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition"> |
|
|
<div class="w-12 h-12 gradient-bg rounded-lg flex items-center justify-center text-white mb-4"> |
|
|
<i class="fas fa-bolt text-xl"></i> |
|
|
</div> |
|
|
<h3 class="text-xl font-semibold mb-2">Lightning Fast</h3> |
|
|
<p class="text-gray-600">Our high-speed servers ensure you can stream, download, and browse without any lag or buffering.</p> |
|
|
</div> |
|
|
<div class="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition"> |
|
|
<div class="w-12 h-12 gradient-bg rounded-lg flex items-center justify-center text-white mb-4"> |
|
|
<i class="fas fa-user-shield text-xl"></i> |
|
|
</div> |
|
|
<h3 class="text-xl font-semibold mb-2">Military Grade Encryption</h3> |
|
|
<p class="text-gray-600">256-bit AES encryption protects your data from hackers, ISPs, and government surveillance.</p> |
|
|
</div> |
|
|
<div class="bg-white p-6 rounded-xl shadow-sm hover:shadow-md transition"> |
|
|
<div class="w-12 h-12 gradient-bg rounded-lg flex items-center justify-center text-white mb-4"> |
|
|
<i class="fas fa-globe-americas text-xl"></i> |
|
|
</div> |
|
|
<h3 class="text-xl font-semibold mb-2">Global Network</h3> |
|
|
<p class="text-gray-600">Access content from anywhere with our network of 1500+ servers in 80+ countries worldwide.</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
|
|
|
|
|
|
<div class="mb-12"> |
|
|
<h2 class="text-2xl font-bold text-gray-800 mb-6">What Our Users Say</h2> |
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6"> |
|
|
<div class="bg-white p-6 rounded-xl shadow-sm"> |
|
|
<div class="flex items-center mb-4"> |
|
|
<div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center mr-3"> |
|
|
<i class="fas fa-user text-blue-600"></i> |
|
|
</div> |
|
|
<div> |
|
|
<p class="font-medium">Sarah Johnson</p> |
|
|
<div class="flex text-yellow-400"> |
|
|
<i class="fas fa-star"></i> |
|
|
<i class="fas fa-star"></i> |
|
|
<i class="fas fa-star"></i> |
|
|
<i class="fas fa-star"></i> |
|
|
<i class="fas fa-star"></i> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
<p class="text-gray-600">"I've tried several VPN services before, but SecureVPN is by far the fastest and most reliable. It's become an essential tool for my remote work."</p> |
|
|
</div> |
|
|
<div class="bg-white p-6 rounded-xl shadow-sm"> |
|
|
<div class="flex items-center mb-4"> |
|
|
<div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center mr-3"> |
|
|
<i class="fas fa-user text-blue-600"></i> |
|
|
</div> |
|
|
<div> |
|
|
<p class="font-medium">Michael Chen</p> |
|
|
<div class="flex text-yellow-400"> |
|
|
<i class="fas fa-star"></i> |
|
|
<i class="fas fa-star"></i> |
|
|
<i class="fas fa-star"></i> |
|
|
<i class="fas fa-star"></i> |
|
|
<i class="fas fa-star-half-alt"></i> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
<p class="text-gray-600">"As a frequent traveler, SecureVPN allows me to access my favorite shows and websites no matter where I am. The connection is always stable."</p> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</main> |
|
|
|
|
|
|
|
|
<footer class="bg-gray-800 text-white py-12"> |
|
|
<div class="container mx-auto px-4"> |
|
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-8 mb-8"> |
|
|
<div> |
|
|
<h3 class="text-xl font-bold mb-4 flex items-center"> |
|
|
<i class="fas fa-lock mr-2"></i> SecureVPN |
|
|
</h3> |
|
|
<p class="text-gray-400">Protecting your digital life since 2015 with fast, secure, and private VPN services.</p> |
|
|
</div> |
|
|
<div> |
|
|
<h4 class="font-semibold mb-4">Product</h4> |
|
|
<ul class="space-y-2"> |
|
|
<li><a href="#" class="text-gray-400 hover:text-white transition">Features</a></li> |
|
|
<li><a href="#" class="text-gray-400 hover:text-white transition">Pricing</a></li> |
|
|
<li><a href="#" class="text-gray-400 hover:text-white transition">Servers</a></li> |
|
|
<li><a href="#" class="text-gray-400 hover:text-white transition">Apps</a></li> |
|
|
</ul> |
|
|
</div> |
|
|
<div> |
|
|
<h4 class="font-semibold mb-4">Support</h4> |
|
|
<ul class="space-y-2"> |
|
|
<li><a href="#" class="text-gray-400 hover:text-white transition">Help Center</a></li> |
|
|
<li><a href="#" class="text-gray-400 hover:text-white transition">Tutorials</a></li> |
|
|
<li><a href="#" class="text-gray-400 hover:text-white transition">Contact Us</a></li> |
|
|
<li><a href="#" class="text-gray-400 hover:text-white transition">Status</a></li> |
|
|
</ul> |
|
|
</div> |
|
|
<div> |
|
|
<h4 class="font-semibold mb-4">Legal</h4> |
|
|
<ul class="space-y-2"> |
|
|
<li><a href="#" class="text-gray-400 hover:text-white transition">Privacy Policy</a></li> |
|
|
<li><a href="#" class="text-gray-400 hover:text-white transition">Terms of Service</a></li> |
|
|
<li><a href="#" class="text-gray-400 hover:text-white transition">DMCA</a></li> |
|
|
<li><a href="#" class="text-gray-400 hover:text-white transition">Refund Policy</a></li> |
|
|
</ul> |
|
|
</div> |
|
|
</div> |
|
|
<div class="pt-6 border-t border-gray-700 flex flex-col md:flex-row justify-between items-center"> |
|
|
<p class="text-gray-400 mb-4 md:mb-0">© 2023 SecureVPN. All rights reserved.</p> |
|
|
<div class="flex space-x-4"> |
|
|
<a href="#" class="text-gray-400 hover:text-white transition"><i class="fab fa-twitter"></i></a> |
|
|
<a href="#" class="text-gray-400 hover:text-white transition"><i class="fab fa-facebook"></i></a> |
|
|
<a href="#" class="text-gray-400 hover:text-white transition"><i class="fab fa-instagram"></i></a> |
|
|
<a href="#" class="text-gray-400 hover:text-white transition"><i class="fab fa-linkedin"></i></a> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</footer> |
|
|
|
|
|
|
|
|
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script> |
|
|
<script> |
|
|
|
|
|
const vpnToggle = document.getElementById('vpn-toggle'); |
|
|
const connectionStatus = document.getElementById('connection-status'); |
|
|
const currentServer = document.getElementById('current-server'); |
|
|
const serverIp = document.getElementById('server-ip'); |
|
|
const downloadSpeed = document.getElementById('download-speed'); |
|
|
const uploadSpeed = document.getElementById('upload-speed'); |
|
|
const downloadSpeedometer = document.getElementById('download-speedometer'); |
|
|
const uploadSpeedometer = document.getElementById('upload-speedometer'); |
|
|
const dataTransferred = document.getElementById('data-transferred'); |
|
|
const dataProgress = document.getElementById('data-progress'); |
|
|
const connectionTime = document.getElementById('connection-time'); |
|
|
const serverButtonsContainer = document.getElementById('server-buttons-container'); |
|
|
|
|
|
|
|
|
let isConnected = false; |
|
|
let connectionStartTime = null; |
|
|
let connectionInterval = null; |
|
|
let dataUsage = 0; |
|
|
let currentLocation = 'lon'; |
|
|
let map; |
|
|
let markers = []; |
|
|
let activeMarker = null; |
|
|
let connectionCircle = null; |
|
|
|
|
|
|
|
|
const serverDetails = { |
|
|
|
|
|
'nyc': { |
|
|
name: 'New York #5', |
|
|
ip: '104.18.23.156', |
|
|
coords: [40.7128, -74.0060], |
|
|
flag: 'https://flagcdn.com/us.svg', |
|
|
region: 'usa', |
|
|
ping: 28, |
|
|
load: 45 |
|
|
}, |
|
|
'la': { |
|
|
name: 'Los Angeles #3', |
|
|
ip: '185.143.223.41', |
|
|
coords: [34.0522, -118.2437], |
|
|
flag: 'https://flagcdn.com/us.svg', |
|
|
region: 'usa', |
|
|
ping: 42, |
|
|
load: 62 |
|
|
}, |
|
|
'chi': { |
|
|
name: 'Chicago #2', |
|
|
ip: '192.168.23.45', |
|
|
coords: [41.8781, -87.6298], |
|
|
flag: 'https://flagcdn.com/us.svg', |
|
|
region: 'usa', |
|
|
ping: 35, |
|
|
load: 38 |
|
|
}, |
|
|
'mia': { |
|
|
name: 'Miami #4', |
|
|
ip: '45.67.89.123', |
|
|
coords: [25.7617, -80.1918], |
|
|
flag: 'https://flagcdn.com/us.svg', |
|
|
region: 'usa', |
|
|
ping: 31, |
|
|
load: 52 |
|
|
}, |
|
|
'sf': { |
|
|
name: 'San Francisco #1', |
|
|
ip: '172.16.31.90', |
|
|
coords: [37.7749, -122.4194], |
|
|
flag: 'https://flagcdn.com/us.svg', |
|
|
region: 'usa', |
|
|
ping: 48, |
|
|
load: 57 |
|
|
}, |
|
|
'sea': { |
|
|
name: 'Seattle #3', |
|
|
ip: '78.141.211.34', |
|
|
coords: [47.6062, -122.3321], |
|
|
flag: 'https://flagcdn.com/us.svg', |
|
|
region: 'usa', |
|
|
ping: 52, |
|
|
load: 41 |
|
|
}, |
|
|
'dal': { |
|
|
name: 'Dallas #2', |
|
|
ip: '210.140.92.183', |
|
|
coords: [32.7767, -96.7970], |
|
|
flag: 'https://flagcdn.com/us.svg', |
|
|
region: 'usa', |
|
|
ping: 39, |
|
|
load: 47 |
|
|
}, |
|
|
|
|
|
|
|
|
'lon': { |
|
|
name: 'London #7', |
|
|
ip: '191.32.56.201', |
|
|
coords: [51.5074, -0.1278], |
|
|
flag: 'https://flagcdn.com/gb.svg', |
|
|
region: 'europe', |
|
|
ping: 22, |
|
|
load: 55 |
|
|
}, |
|
|
'ber': { |
|
|
name: 'Berlin #5', |
|
|
ip: '115.241.91.12', |
|
|
coords: [52.5200, 13.4050], |
|
|
flag: 'https://flagcdn.com/de.svg', |
|
|
region: 'europe', |
|
|
ping: 18, |
|
|
load: 48 |
|
|
}, |
|
|
'par': { |
|
|
name: 'Paris #4', |
|
|
ip: '203.116.223.15', |
|
|
coords: [48.8566, 2.3522], |
|
|
flag: 'https://flagcdn.com/fr.svg', |
|
|
region: 'europe', |
|
|
ping: 24, |
|
|
load: 61 |
|
|
}, |
|
|
'mad': { |
|
|
name: 'Madrid #3', |
|
|
ip: '217.172.190.47', |
|
|
coords: [40.4168, -3.7038], |
|
|
flag: 'https://flagcdn.com/es.svg', |
|
|
region: 'europe', |
|
|
ping: 31, |
|
|
load: 42 |
|
|
}, |
|
|
'rom': { |
|
|
name: 'Rome #2', |
|
|
ip: '176.31.128.1', |
|
|
coords: [41.9028, 12.4964], |
|
|
flag: 'https://flagcdn.com/it.svg', |
|
|
region: 'europe', |
|
|
ping: 29, |
|
|
load: 39 |
|
|
}, |
|
|
'ams': { |
|
|
name: 'Amsterdam #6', |
|
|
ip: '82.192.84.116', |
|
|
coords: [52.3676, 4.9041], |
|
|
flag: 'https://flagcdn.com/nl.svg', |
|
|
region: 'europe', |
|
|
ping: 15, |
|
|
load: 67 |
|
|
}, |
|
|
'sto': { |
|
|
name: 'Stockholm #3', |
|
|
ip: '31.15.32.10', |
|
|
coords: [59.3293, 18.0686], |
|
|
flag: 'https://flagcdn.com/se.svg', |
|
|
region: 'europe', |
|
|
ping: 21, |
|
|
load: 34 |
|
|
}, |
|
|
'vie': { |
|
|
name: 'Vienna #2', |
|
|
ip: '203.109.129.2', |
|
|
coords: [48.2082, 16.3738], |
|
|
flag: 'https://flagcdn.com/at.svg', |
|
|
region: 'europe', |
|
|
ping: 26, |
|
|
load: 29 |
|
|
}, |
|
|
'pra': { |
|
|
name: 'Prague #1', |
|
|
ip: '45.67.89.123', |
|
|
coords: [50.0755, 14.4378], |
|
|
flag: 'https://flagcdn.com/cz.svg', |
|
|
region: 'europe', |
|
|
ping: 23, |
|
|
load: 31 |
|
|
}, |
|
|
'bud': { |
|
|
name: 'Budapest #2', |
|
|
ip: '89.36.210.144', |
|
|
coords: [47.4979, 19.0402], |
|
|
flag: 'https://flagcdn.com/hu.svg', |
|
|
region: 'europe', |
|
|
ping: 27, |
|
|
load: 38 |
|
|
}, |
|
|
'war': { |
|
|
name: 'Warsaw #3', |
|
|
ip: '77.79.233.52', |
|
|
coords: [52.2297, 21.0122], |
|
|
flag: 'https://flagcdn.com/pl.svg', |
|
|
region: 'europe', |
|
|
ping: 24, |
|
|
load: 42 |
|
|
}, |
|
|
'lis': { |
|
|
name: 'Lisbon #1', |
|
|
ip: '194.79.52.94', |
|
|
coords: [38.7223, -9.1393], |
|
|
flag: 'https://flagcdn.com/pt.svg', |
|
|
region: 'europe', |
|
|
ping: 32, |
|
|
load: 29 |
|
|
}, |
|
|
'bru': { |
|
|
name: 'Brussels #4', |
|
|
ip: '193.191.177.141', |
|
|
coords: [50.8503, 4.3517], |
|
|
flag: 'https://flagcdn.com/be.svg', |
|
|
region: 'europe', |
|
|
ping: 19, |
|
|
load: 51 |
|
|
}, |
|
|
'zur': { |
|
|
name: 'Zurich #5', |
|
|
ip: '195.186.1.103', |
|
|
coords: [47.3769, 8.5417], |
|
|
flag: 'https://flagcdn.com/ch.svg', |
|
|
region: 'europe', |
|
|
ping: 17, |
|
|
load: 47 |
|
|
}, |
|
|
'cop': { |
|
|
name: 'Copenhagen #2', |
|
|
ip: '92.222.6.47', |
|
|
coords: [55.6761, 12.5683], |
|
|
flag: 'https://flagcdn.com/dk.svg', |
|
|
region: 'europe', |
|
|
ping: 20, |
|
|
load: 33 |
|
|
}, |
|
|
'hel': { |
|
|
name: 'Helsinki #3', |
|
|
ip: '91.152.177.84', |
|
|
coords: [60.1699, 24.9384], |
|
|
flag: 'https://flagcdn.com/fi.svg', |
|
|
region: 'europe', |
|
|
ping: 23, |
|
|
load: 28 |
|
|
}, |
|
|
'osl': { |
|
|
name: 'Oslo #1', |
|
|
ip: '185.75.56.215', |
|
|
coords: [59.9139, 10.7522], |
|
|
flag: 'https://flagcdn.com/no.svg', |
|
|
region: 'europe', |
|
|
ping: 22, |
|
|
load: 31 |
|
|
}, |
|
|
'dub': { |
|
|
name: 'Dublin #4', |
|
|
ip: '185.86.148.90', |
|
|
coords: [53.3498, -6.2603], |
|
|
flag: 'https://flagcdn.com/ie.svg', |
|
|
region: 'europe', |
|
|
ping: 25, |
|
|
load: 45 |
|
|
}, |
|
|
'ath': { |
|
|
name: 'Athens #2', |
|
|
ip: '62.103.203.104', |
|
|
coords: [37.9838, 23.7275], |
|
|
flag: 'https://flagcdn.com/gr.svg', |
|
|
region: 'europe', |
|
|
ping: 30, |
|
|
load: 39 |
|
|
}, |
|
|
'sof': { |
|
|
name: 'Sofia #1', |
|
|
ip: '87.121.78.4', |
|
|
coords: [42.6977, 23.3219], |
|
|
flag: 'https://flagcdn.com/bg.svg', |
|
|
region: 'europe', |
|
|
ping: 28, |
|
|
load: 27 |
|
|
}, |
|
|
'buc': { |
|
|
name: 'Bucharest #3', |
|
|
ip: '89.34.178.4', |
|
|
coords: [44.4268, 26.1025], |
|
|
flag: 'https://flagcdn.com/ro.svg', |
|
|
region: 'europe', |
|
|
ping: 26, |
|
|
load: 34 |
|
|
}, |
|
|
'zag': { |
|
|
name: 'Zagreb #2', |
|
|
ip: '78.134.0.1', |
|
|
coords: [45.8150, 15.9819], |
|
|
flag: 'https://flagcdn.com/hr.svg', |
|
|
region: 'europe', |
|
|
ping: 24, |
|
|
load: 29 |
|
|
}, |
|
|
'bel': { |
|
|
name: 'Belgrade #1', |
|
|
ip: '77.46.144.2', |
|
|
coords: [44.8206, 20.4622], |
|
|
flag: 'https://flagcdn.com/rs.svg', |
|
|
region: 'europe', |
|
|
ping: 27, |
|
|
load: 31 |
|
|
}, |
|
|
'brat': { |
|
|
name: 'Bratislava #2', |
|
|
ip: '158.195.224.1', |
|
|
coords: [48.1486, 17.1077], |
|
|
flag: 'https://flagcdn.com/sk.svg', |
|
|
region: 'europe', |
|
|
ping: 23, |
|
|
load: 26 |
|
|
}, |
|
|
'ljub': { |
|
|
name: 'Ljubljana #1', |
|
|
ip: '194.145.240.1', |
|
|
coords: [46.0569, 14.5058], |
|
|
flag: 'https://flagcdn.com/si.svg', |
|
|
region: 'europe', |
|
|
ping: 22, |
|
|
load: 24 |
|
|
}, |
|
|
'tal': { |
|
|
name: 'Tallinn #2', |
|
|
ip: '193.40.11.1', |
|
|
coords: [59.4370, 24.7536], |
|
|
flag: 'https://flagcdn.com/ee.svg', |
|
|
region: 'europe', |
|
|
ping: 25, |
|
|
load: 23 |
|
|
}, |
|
|
'rig': { |
|
|
name: 'Riga #1', |
|
|
ip: '195.13.195.1', |
|
|
coords: [56.9496, 24.1052], |
|
|
flag: 'https://flagcdn.com/lv.svg', |
|
|
region: 'europe', |
|
|
ping: 26, |
|
|
load: 25 |
|
|
}, |
|
|
'vil': { |
|
|
name: 'Vilnius #2', |
|
|
ip: '194.135.96.1', |
|
|
coords: [54.6872, 25.2797], |
|
|
flag: 'https://flagcdn.com/lt.svg', |
|
|
region: 'europe', |
|
|
ping: 24, |
|
|
load: 22 |
|
|
}, |
|
|
'rey': { |
|
|
name: 'Reykjavik #1', |
|
|
ip: '193.4.172.1', |
|
|
coords: [64.1466, -21.9426], |
|
|
flag: 'https://flagcdn.com/is.svg', |
|
|
region: 'europe', |
|
|
ping: 32, |
|
|
load: 19 |
|
|
}, |
|
|
'lux': { |
|
|
name: 'Luxembourg #2', |
|
|
ip: '194.154.224.1', |
|
|
coords: [49.6116, 6.1319], |
|
|
flag: 'https://flagcdn.com/lu.svg', |
|
|
region: 'europe', |
|
|
ping: 20, |
|
|
load: 28 |
|
|
}, |
|
|
'val': { |
|
|
name: 'Valletta #1', |
|
|
ip: '185.1.0.1', |
|
|
coords: [35.8989, 14.5146], |
|
|
flag: 'https://flagcdn.com/mt.svg', |
|
|
region: 'europe', |
|
|
ping: 31, |
|
|
load: 21 |
|
|
}, |
|
|
'mon': { |
|
|
name: 'Monaco #1', |
|
|
ip: '80.94.96.1', |
|
|
coords: [43.7384, 7.4246], |
|
|
flag: 'https://flagcdn.com/mc.svg', |
|
|
region: 'europe', |
|
|
ping: 29, |
|
|
load: 18 |
|
|
}, |
|
|
'and': { |
|
|
name: 'Andorra la Vella #1', |
|
|
ip: '85.94.160.1', |
|
|
coords: [42.5063, 1.5218], |
|
|
flag: 'https://flagcdn.com/ad.svg', |
|
|
region: 'europe', |
|
|
ping: 33, |
|
|
load: 17 |
|
|
}, |
|
|
'saraj': { |
|
|
name: 'Sarajevo #1', |
|
|
ip: '93.86.64.1', |
|
|
coords: [43.8563, 18.4131], |
|
|
flag: 'https://flagcdn.com/ba.svg', |
|
|
region: 'europe', |
|
|
ping: 28, |
|
|
load: 23 |
|
|
}, |
|
|
'pod': { |
|
|
name: 'Podgorica #1', |
|
|
ip: '194.106.144.1', |
|
|
coords: [42.4304, 19.2594], |
|
|
flag: 'https://flagcdn.com/me.svg', |
|
|
region: 'europe', |
|
|
ping: 27, |
|
|
load: 20 |
|
|
}, |
|
|
'pri': { |
|
|
name: 'Pristina #1', |
|
|
ip: '46.99.0.1', |
|
|
coords: [42.6629, 21.1655], |
|
|
flag: 'https://flagcdn.com/xk.svg', |
|
|
region: 'europe', |
|
|
ping: 29, |
|
|
load: 19 |
|
|
}, |
|
|
'tir': { |
|
|
name: 'Tirana #1', |
|
|
ip: '46.99.0.1', |
|
|
coords: [41.3275, 19.8187], |
|
|
flag: 'https://flagcdn.com/al.svg', |
|
|
region: 'europe', |
|
|
ping: 30, |
|
|
load: 22 |
|
|
}, |
|
|
'minsk': { |
|
|
name: 'Minsk #1', |
|
|
ip: '93.125.0.1', |
|
|
coords: [53.9045, 27.5615], |
|
|
flag: 'https://flagcdn.com/by.svg', |
|
|
region: 'europe', |
|
|
ping: 26, |
|
|
load: 25 |
|
|
}, |
|
|
'kiev': { |
|
|
name: 'Kyiv #2', |
|
|
ip: '93.183.211.1', |
|
|
coords: [50.4501, 30.5234], |
|
|
flag: 'https://flagcdn.com/ua.svg', |
|
|
region: 'europe', |
|
|
ping: 28, |
|
|
load: 31 |
|
|
}, |
|
|
'chis': { |
|
|
name: 'Chișinău #1', |
|
|
ip: '93.113.0.1', |
|
|
coords: [47.0105, 28.8638], |
|
|
flag: 'https://flagcdn.com/md.svg', |
|
|
region: 'europe', |
|
|
ping: 27, |
|
|
load: 24 |
|
|
}, |
|
|
|
|
|
|
|
|
'tok': { |
|
|
name: 'Tokyo #8', |
|
|
ip: '210.140.92.183', |
|
|
coords: [35.6762, 139.6503], |
|
|
flag: 'https://flagcdn.com/jp.svg', |
|
|
region: 'asia', |
|
|
ping: 68, |
|
|
load: 59 |
|
|
}, |
|
|
'sin': { |
|
|
name: 'Singapore #6', |
|
|
ip: '203.116.223.15', |
|
|
coords: [1.3521, 103.8198], |
|
|
flag: 'https://flagcdn.com/sg.svg', |
|
|
region: 'asia', |
|
|
ping: 72, |
|
|
load: 63 |
|
|
}, |
|
|
'syd': { |
|
|
name: 'Sydney #5', |
|
|
ip: '203.109.129.2', |
|
|
coords: [-33.8688, 151.2093], |
|
|
flag: 'https://flagcdn.com/au.svg', |
|
|
region: 'oceania', |
|
|
ping: 142, |
|
|
load: 41 |
|
|
}, |
|
|
'rio': { |
|
|
name: 'Rio de Janeiro #3', |
|
|
ip: '191.32.56.201', |
|
|
coords: [-22.9068, -43.1729], |
|
|
flag: 'https://flagcdn.com/br.svg', |
|
|
region: 'southamerica', |
|
|
ping: 98, |
|
|
load: 37 |
|
|
}, |
|
|
'cap': { |
|
|
name: 'Cape Town #2', |
|
|
ip: '115.241.91.12', |
|
|
coords: [-33.9249, 18.4241], |
|
|
flag: 'https://flagcdn.com/za.svg', |
|
|
region: 'africa', |
|
|
ping: 124, |
|
|
load: 28 |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
function initMap() { |
|
|
map = L.map('server-map').setView([50, 15], 3); |
|
|
|
|
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { |
|
|
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' |
|
|
}).addTo(map); |
|
|
|
|
|
|
|
|
for (const [code, details] of Object.entries(serverDetails)) { |
|
|
const markerColor = getRegionColor(details.region); |
|
|
const marker = L.circleMarker(details.coords, { |
|
|
radius: 8, |
|
|
fillColor: code === currentLocation ? '#10B981' : markerColor, |
|
|
color: '#fff', |
|
|
weight: 2, |
|
|
opacity: 1, |
|
|
fillOpacity: 0.8 |
|
|
}).addTo(map); |
|
|
|
|
|
marker.bindPopup(`<b>${details.name}</b><br>Ping: ${details.ping}ms<br>Load: ${details.load}%`); |
|
|
|
|
|
marker.on('click', () => { |
|
|
changeServerLocation(code); |
|
|
}); |
|
|
|
|
|
markers.push({ code, marker }); |
|
|
|
|
|
if (code === currentLocation) { |
|
|
activeMarker = marker; |
|
|
map.setView(details.coords, 4); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
connectionCircle = L.circle(serverDetails[currentLocation].coords, { |
|
|
color: '#3B82F6', |
|
|
fillColor: '#3B82F6', |
|
|
fillOpacity: 0.2, |
|
|
radius: 1000000 |
|
|
}).addTo(map); |
|
|
connectionCircle.setStyle({ opacity: 0 }); |
|
|
} |
|
|
|
|
|
|
|
|
function getRegionColor(region) { |
|
|
const colors = { |
|
|
'europe': '#3B82F6', |
|
|
'usa': '#EC4899', |
|
|
'asia': '#F97316', |
|
|
'oceania': '#14B8A6', |
|
|
'southamerica': '#8B5CF6', |
|
|
'africa': '#EF4444' |
|
|
}; |
|
|
return colors[region] || '#4F46E5'; |
|
|
} |
|
|
|
|
|
|
|
|
function getPingClass(ping) { |
|
|
if (ping < 30) return 'ping-excellent'; |
|
|
if (ping < 60) return 'ping-good'; |
|
|
if (ping < 100) return 'ping-average'; |
|
|
return 'ping-poor'; |
|
|
} |
|
|
|
|
|
|
|
|
function initServerCards() { |
|
|
for (const [code, details] of Object.entries(serverDetails)) { |
|
|
const card = document.createElement('div'); |
|
|
card.className = `server-card bg-white p-4 rounded-lg shadow-sm border border-gray-100 cursor-pointer server-card-${code} ${code === currentLocation ? 'border-blue-500' : ''}`; |
|
|
card.dataset.location = code; |
|
|
card.dataset.region = details.region; |
|
|
|
|
|
const pingClass = getPingClass(details.ping); |
|
|
const regionClass = `region-${details.region}`; |
|
|
|
|
|
card.innerHTML = ` |
|
|
<div class="flex justify-between items-start mb-2"> |
|
|
<div class="flex items-center"> |
|
|
<span class="country-flag" style="background-image: url(${details.flag})"></span> |
|
|
<span class="font-medium">${details.name.split(' #')[0]}</span> |
|
|
<span class="region-tag ${regionClass}">${details.region === 'europe' ? 'EU' : details.region.toUpperCase().substring(0, 3)}</span> |
|
|
</div> |
|
|
<span class="text-xs font-medium ${details.load < 50 ? 'text-green-600' : details.load < 75 ? 'text-yellow-600' : 'text-red-600'}">${details.load}% load</span> |
|
|
</div> |
|
|
<div class="flex justify-between items-center text-sm"> |
|
|
<span>${details.name}</span> |
|
|
<span class="flex items-center"> |
|
|
<span class="${pingClass} ping-indicator"></span> |
|
|
<span>${details.ping}ms</span> |
|
|
</span> |
|
|
</div> |
|
|
`; |
|
|
|
|
|
card.addEventListener('click', () => { |
|
|
changeServerLocation(code); |
|
|
}); |
|
|
|
|
|
serverButtonsContainer.appendChild(card); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function changeServerLocation(code) { |
|
|
currentLocation = code; |
|
|
const details = serverDetails[code]; |
|
|
|
|
|
|
|
|
markers.forEach(({ code: markerCode, marker }) => { |
|
|
if (markerCode === code) { |
|
|
marker.setStyle({ fillColor: '#10B981' }); |
|
|
activeMarker = marker; |
|
|
map.setView(details.coords, 4); |
|
|
} else { |
|
|
const regionColor = getRegionColor(serverDetails[markerCode].region); |
|
|
marker.setStyle({ fillColor: regionColor }); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
currentServer.textContent = details.name; |
|
|
serverIp.textContent = details.ip; |
|
|
|
|
|
|
|
|
document.querySelectorAll('.server-card').forEach(card => { |
|
|
if (card.dataset.location === code) { |
|
|
card.classList.add('border-blue-500'); |
|
|
} else { |
|
|
card.classList.remove('border-blue-500'); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
if (isConnected) { |
|
|
connectionCircle.setStyle({ opacity: 0 }); |
|
|
setTimeout(() => { |
|
|
connectionCircle.setLatLng(details.coords); |
|
|
connectionCircle.setStyle({ opacity: 0.7 }); |
|
|
}, 300); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
function filterServersByRegion(region) { |
|
|
document.querySelectorAll('.server-card').forEach(card => { |
|
|
if (region === 'all' || card.dataset.region === region) { |
|
|
card.classList.remove('hidden'); |
|
|
} else { |
|
|
card.classList.add('hidden'); |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
document.querySelectorAll('.region-filter').forEach(btn => { |
|
|
if (btn.dataset.region === region) { |
|
|
btn.classList.add('ring-2', 'ring-offset-2', 'ring-white'); |
|
|
} else { |
|
|
btn.classList.remove('ring-2', 'ring-offset-2', 'ring-white'); |
|
|
} |
|
|
}); |
|
|
} |
|
|
|
|
|
|
|
|
vpnToggle.addEventListener('click', () => { |
|
|
isConnected = !isConnected; |
|
|
|
|
|
if (isConnected) { |
|
|
|
|
|
vpnToggle.classList.add('active'); |
|
|
vpnToggle.querySelector('div').classList.add('translate-x-8'); |
|
|
connectionStatus.textContent = 'Connected'; |
|
|
connectionStatus.previousElementSibling.classList.remove('bg-gray-300'); |
|
|
connectionStatus.previousElementSibling.classList.add('bg-green-500'); |
|
|
|
|
|
|
|
|
connectionCircle.setStyle({ opacity: 0.7 }); |
|
|
|
|
|
|
|
|
connectionStartTime = new Date(); |
|
|
connectionInterval = setInterval(updateConnectionTime, 1000); |
|
|
|
|
|
|
|
|
simulateConnection(); |
|
|
} else { |
|
|
|
|
|
vpnToggle.classList.remove('active'); |
|
|
vpnToggle.querySelector('div').classList.remove('translate-x-8'); |
|
|
connectionStatus.textContent = 'Disconnected'; |
|
|
connectionStatus.previousElementSibling.classList.remove('bg-green-500'); |
|
|
connectionStatus.previousElementSibling.classList.add('bg-gray-300'); |
|
|
|
|
|
|
|
|
connectionCircle.setStyle({ opacity: 0 }); |
|
|
|
|
|
|
|
|
clearInterval(connectionInterval); |
|
|
connectionTime.textContent = '00:00:00'; |
|
|
|
|
|
|
|
|
downloadSpeed.textContent = '0 Mbps'; |
|
|
uploadSpeed.textContent = '0 Mbps'; |
|
|
downloadSpeedometer.style.transform = 'rotate(45deg)'; |
|
|
uploadSpeedometer.style.transform = 'rotate(45deg)'; |
|
|
} |
|
|
}); |
|
|
|
|
|
|
|
|
function updateConnectionTime() { |
|
|
const now = new Date(); |
|
|
const diff = Math.floor((now - connectionStartTime) / 1000); |
|
|
|
|
|
const hours = Math.floor(diff / 3600); |
|
|
const minutes = Math.floor((diff % 3600) / 60); |
|
|
const seconds = diff % 60; |
|
|
|
|
|
connectionTime.textContent = |
|
|
`${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; |
|
|
} |
|
|
|
|
|
|
|
|
function simulateConnection() { |
|
|
let download = 0; |
|
|
let upload = 0; |
|
|
dataUsage = 0; |
|
|
|
|
|
const speedInterval = setInterval(() => { |
|
|
if (!isConnected) { |
|
|
clearInterval(speedInterval); |
|
|
return; |
|
|
} |
|
|
|
|
|
|
|
|
download = Math.min(100, Math.max(10, download + (Math.random() * 4 - 2))); |
|
|
upload = Math.min(40, Math.max(5, upload + (Math.random() * 2 - 1))); |
|
|
|
|
|
|
|
|
downloadSpeed.textContent = `${download.toFixed(1)} Mbps`; |
|
|
uploadSpeed.textContent = `${upload.toFixed(1)} Mbps`; |
|
|
|
|
|
|
|
|
const downloadRotation = 45 + (download / 100 * 270); |
|
|
const uploadRotation = 45 + (upload / 40 * 270); |
|
|
downloadSpeedometer.style.transform = `rotate(${downloadRotation}deg)`; |
|
|
uploadSpeedometer.style.transform = `rotate(${uploadRotation}deg)`; |
|
|
|
|
|
|
|
|
dataUsage += (download + upload) / 8 / 10; |
|
|
dataTransferred.textContent = `${dataUsage.toFixed(1)} MB`; |
|
|
const progressPercent = Math.min(100, (dataUsage / 100) * 100); |
|
|
dataProgress.style.width = `${progressPercent}%`; |
|
|
}, 100); |
|
|
} |
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', () => { |
|
|
initMap(); |
|
|
initServerCards(); |
|
|
|
|
|
|
|
|
currentServer.textContent = serverDetails[currentLocation].name; |
|
|
serverIp.textContent = serverDetails[currentLocation].ip; |
|
|
|
|
|
|
|
|
document.querySelectorAll('.region-filter').forEach(btn => { |
|
|
btn.addEventListener('click', () => { |
|
|
filterServersByRegion(btn.dataset.region); |
|
|
}); |
|
|
}); |
|
|
}); |
|
|
</script> |
|
|
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=powerisx/povpn" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
|
|
</html> |