Spaces:
Running
Running
File size: 7,623 Bytes
54e2b8c 5ada4ba 54e2b8c c780a69 5ada4ba 3603cde 5ada4ba c780a69 5ada4ba c780a69 5ada4ba 3603cde 54e2b8c 3603cde 7b958aa 5ada4ba 18e8518 54e2b8c 5ada4ba 54e2b8c 5ada4ba 54e2b8c c780a69 3603cde 54e2b8c c780a69 3603cde 54e2b8c 3603cde 7b958aa 3603cde 54e2b8c 3603cde 54e2b8c 3603cde 54e2b8c 3603cde 54e2b8c 3603cde 54e2b8c 3603cde 54e2b8c 3603cde 54e2b8c c780a69 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | <!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Sài Gòn Sync - The World's Most Accurate Clock</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@700;800&family=Inter:wght@400;600;800&display=swap');
body { margin: 0; padding: 0; width: 100vw; height: 100vh; overflow: hidden; background-color: #050508; color: #fff; font-family: 'Inter', sans-serif; display: flex; align-items: center; justify-content: center; }
.bg-glow { position: fixed; width: 60vw; height: 60vw; background: radial-gradient(circle, rgba(99, 102, 241, 0.15) 0%, rgba(0,0,0,0) 70%); top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 0; }
.main-container { position: relative; z-index: 10; width: 100%; max-width: 700px; display: flex; flex-direction: column; align-items: center; padding: 20px; }
.brand-title { font-family: 'JetBrains Mono', monospace; font-size: 10px; letter-spacing: 5px; font-weight: 800; background: linear-gradient(to right, #6366f1, #a5b4fc, #6366f1); -webkit-background-clip: text; -webkit-text-fill-color: transparent; text-transform: uppercase; margin-bottom: 30px; text-align: center; }
.tz-select { background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.1); color: #a5b4fc; padding: 6px 18px; border-radius: 12px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 25px; outline: none; cursor: pointer; transition: 0.3s; }
.clock-wrapper { display: flex; align-items: center; justify-content: center; font-family: 'JetBrains Mono', monospace; font-size: clamp(3.5rem, 18vw, 7.5rem); font-weight: 800; line-height: 1; gap: 4px; margin-bottom: 15px; }
.digit-column { height: 1.1em; overflow: hidden; position: relative; width: 0.65em; text-align: center; }
.digit-strip { transition: transform 0.6s cubic-bezier(0.16, 1, 0.3, 1); }
.digit-val { height: 1.1em; display: flex; align-items: center; justify-content: center; color: #fff; text-shadow: 0 0 30px rgba(99, 102, 241, 0.4); }
.sep { color: #4f46e5; opacity: 0.8; margin: 0 4px; padding-bottom: 15px; }
.stats-bar { background: rgba(255, 255, 255, 0.02); backdrop-filter: blur(25px); border: 1px solid rgba(255, 255, 255, 0.05); border-radius: 24px; padding: 15px 40px; display: flex; gap: 40px; margin-top: 40px; }
.stat-box { display: flex; flex-direction: column; align-items: center; }
.stat-label { font-size: 7px; text-transform: uppercase; letter-spacing: 2px; color: #4f46e5; margin-bottom: 4px; font-weight: 600; }
.stat-data { font-family: 'JetBrains Mono', monospace; font-size: 13px; font-weight: 700; }
#countdown-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: #000; display: none; z-index: 100; flex-direction: column; align-items: center; justify-content: center; }
#countdown-num { font-size: 18rem; font-weight: 900; color: #f87171; text-shadow: 0 0 60px rgba(248, 113, 113, 0.6); }
</style>
</head>
<body onclick="lockScreen()">
<div class="bg-glow"></div>
<div id="countdown-overlay"><div class="text-white text-2xl tracking-[15px] mb-10 font-black">HAPPY NEW YEAR</div><div id="countdown-num">10</div></div>
<div class="main-container">
<div class="brand-title">Đồng hồ chính xác nhất thế giới</div>
<select id="timezone-selector" class="tz-select" onchange="changeTimezone()">
<option value="Asia/Ho_Chi_Minh">🇻🇳 Sài Gòn (GMT+7)</option>
<option value="Asia/Singapore">🇸🇬 Singapore (GMT+8)</option>
<option value="Asia/Tokyo">🇯🇵 Tokyo (GMT+9)</option>
<option value="Europe/London">🇬🇧 London (GMT+0)</option>
<option value="America/New_York">🇺🇸 New York (GMT-5)</option>
</select>
<div class="clock-wrapper">
<div class="digit-column"><div class="digit-strip" id="h1"></div></div>
<div class="digit-column"><div class="digit-strip" id="h2"></div></div>
<div class="sep">:</div>
<div class="digit-column"><div class="digit-strip" id="m1"></div></div>
<div class="digit-column"><div class="digit-strip" id="m2"></div></div>
<div class="sep">:</div>
<div class="digit-column"><div class="digit-strip" id="s1"></div></div>
<div class="digit-column"><div class="digit-strip" id="s2"></div></div>
</div>
<div id="full-date" class="text-gray-500 text-[11px] tracking-[5px] uppercase font-bold">---</div>
<div class="stats-bar">
<div class="stat-box"><span class="stat-label">Network Ping</span><span class="stat-data" id="v-ping">--</span></div>
<div class="stat-box"><span class="stat-label">Time Offset</span><span class="stat-data" id="v-offset">--</span></div>
<div class="stat-box"><span class="stat-label">Server IP</span><span class="stat-data" id="v-ip">--</span></div>
</div>
</div>
<script>
let serverOffset = 0, selectedTimezone = 'Asia/Ho_Chi_Minh', wakeLock = null;
const API_URL = 'https://tuhbooh-networttools.hf.space';
function createStrips() {
['h1','h2','m1','m2','s1','s2'].forEach(id => {
const s = document.getElementById(id); s.innerHTML = '';
for(let i=0; i<=9; i++) { const d = document.createElement('div'); d.className = 'digit-val'; d.innerText = i; s.appendChild(d); }
});
}
function setDigit(id, val) { document.getElementById(id).style.transform = `translateY(-${val * 1.1}em)`; }
function changeTimezone() { selectedTimezone = document.getElementById('timezone-selector').value; }
async function lockScreen() { if(navigator.wakeLock) wakeLock = await navigator.wakeLock.request('screen'); }
async function sync() {
const start = performance.now();
try {
const r = await fetch(`${API_URL}?t=${Date.now()}`);
const d = await r.json();
const ping = performance.now() - start;
serverOffset = (d.ts * 1000 + ping/2) - Date.now();
document.getElementById('v-ping').innerText = Math.round(ping) + "ms";
document.getElementById('v-offset').innerText = Math.round(Math.abs(serverOffset)) + "ms";
document.getElementById('v-ip').innerText = d.ip;
} catch(e) {}
}
function update() {
const now = new Date(Date.now() + serverOffset);
const timeStr = now.toLocaleTimeString('en-GB', {timeZone: selectedTimezone, hour12:false, hour:'2-digit', minute:'2-digit', second:'2-digit'});
const [h, m, s] = timeStr.split(':');
setDigit('h1', h[0]); setDigit('h2', h[1]); setDigit('m1', m[0]); setDigit('m2', m[1]); setDigit('s1', s[0]); setDigit('s2', s[1]);
document.getElementById('full-date').innerText = new Intl.DateTimeFormat('vi-VN', {timeZone: selectedTimezone, weekday:'long', day:'numeric', month:'long', year:'numeric'}).format(now);
requestAnimationFrame(update);
}
createStrips(); sync();
setInterval(sync, 15000); // Sync mỗi 15s để ổn định
requestAnimationFrame(update);
</script>
</body>
</html> |