Spaces:
Running
Running
Update index.html
Browse files- index.html +50 -50
index.html
CHANGED
|
@@ -3,59 +3,51 @@
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
| 6 |
-
<title>Sài Gòn Sync -
|
| 7 |
<script src="https://cdn.tailwindcss.com"></script>
|
| 8 |
<style>
|
| 9 |
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@700;800&family=Inter:wght@400;600;800&display=swap');
|
| 10 |
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; }
|
| 11 |
.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; }
|
| 12 |
-
.main-container { position: relative; z-index: 10; width: 100%; max-width: 600px; display: flex; flex-direction: column; align-items: center; padding: 20px; }
|
|
|
|
|
|
|
| 13 |
|
| 14 |
-
/* Dropdown Style */
|
| 15 |
-
.tz-select {
|
| 16 |
-
background: rgba(255, 255, 255, 0.05);
|
| 17 |
-
border: 1px solid rgba(255, 255, 255, 0.1);
|
| 18 |
-
color: #a5b4fc;
|
| 19 |
-
padding: 5px 15px;
|
| 20 |
-
border-radius: 10px;
|
| 21 |
-
font-size: 10px;
|
| 22 |
-
font-weight: 700;
|
| 23 |
-
text-transform: uppercase;
|
| 24 |
-
letter-spacing: 1px;
|
| 25 |
-
margin-bottom: 15px;
|
| 26 |
-
outline: none;
|
| 27 |
-
cursor: pointer;
|
| 28 |
-
transition: all 0.3s;
|
| 29 |
-
}
|
| 30 |
-
.tz-select:hover { background: rgba(99, 102, 241, 0.2); border-color: rgba(99, 102, 241, 0.5); }
|
| 31 |
-
.tz-select option { background: #0a0a0f; color: #fff; }
|
| 32 |
-
|
| 33 |
.clock-wrapper { display: flex; align-items: center; justify-content: center; font-family: 'JetBrains Mono', monospace; font-size: clamp(3rem, 15vw, 6.5rem); font-weight: 800; line-height: 1; gap: 4px; margin-bottom: 10px; }
|
| 34 |
.digit-column { height: 1.1em; overflow: hidden; position: relative; width: 0.65em; text-align: center; }
|
| 35 |
.digit-strip { transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1); }
|
| 36 |
.digit-val { height: 1.1em; display: flex; align-items: center; justify-content: center; color: #fff; text-shadow: 0 0 20px rgba(255, 255, 255, 0.3); }
|
| 37 |
.sep { color: #4f46e5; opacity: 0.8; margin: 0 2px; padding-bottom: 10px; }
|
|
|
|
| 38 |
.stats-bar { background: rgba(255, 255, 255, 0.03); backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 20px; padding: 12px 30px; display: flex; gap: 30px; margin-top: 30px; }
|
| 39 |
.stat-box { display: flex; flex-direction: column; align-items: center; }
|
| 40 |
.stat-label { font-size: 8px; text-transform: uppercase; letter-spacing: 2px; color: #6366f1; margin-bottom: 2px; }
|
| 41 |
-
.stat-data { font-family: 'JetBrains Mono', monospace; font-size: 12px; font-weight: 600; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
</style>
|
| 43 |
</head>
|
| 44 |
<body onclick="lockScreen()">
|
| 45 |
<div class="bg-glow"></div>
|
| 46 |
-
|
| 47 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
<select id="timezone-selector" class="tz-select" onchange="changeTimezone()">
|
| 49 |
<option value="Asia/Ho_Chi_Minh">🇻🇳 Sài Gòn (GMT+7)</option>
|
| 50 |
<option value="Asia/Singapore">🇸🇬 Singapore (GMT+8)</option>
|
| 51 |
<option value="Asia/Tokyo">🇯🇵 Tokyo (GMT+9)</option>
|
| 52 |
-
<option value="Asia/Seoul">🇰🇷 Seoul (GMT+9)</option>
|
| 53 |
<option value="Europe/London">🇬🇧 London (GMT+0)</option>
|
| 54 |
-
<option value="Europe/Paris">🇫🇷 Paris (GMT+1)</option>
|
| 55 |
<option value="America/New_York">🇺🇸 New York (GMT-5)</option>
|
| 56 |
-
<option value="America/Los_Angeles">🇺🇸 Los Angeles (GMT-8)</option>
|
| 57 |
-
<option value="Australia/Sydney">🇦🇺 Sydney (GMT+11)</option>
|
| 58 |
-
<option value="Asia/Bangkok">🇹🇭 Bangkok (GMT+7)</option>
|
| 59 |
</select>
|
| 60 |
|
| 61 |
<div class="clock-wrapper">
|
|
@@ -88,24 +80,14 @@
|
|
| 88 |
const strip = document.getElementById(id);
|
| 89 |
for(let i=0; i<=9; i++) {
|
| 90 |
const div = document.createElement('div');
|
| 91 |
-
div.className = 'digit-val';
|
| 92 |
-
div.innerText = i;
|
| 93 |
-
strip.appendChild(div);
|
| 94 |
}
|
| 95 |
});
|
| 96 |
}
|
| 97 |
|
| 98 |
-
function setDigit(id, val) {
|
| 99 |
-
|
| 100 |
-
}
|
| 101 |
-
|
| 102 |
-
function changeTimezone() {
|
| 103 |
-
selectedTimezone = document.getElementById('timezone-selector').value;
|
| 104 |
-
}
|
| 105 |
-
|
| 106 |
-
async function lockScreen() {
|
| 107 |
-
if ('wakeLock' in navigator) { try { wakeLock = await navigator.wakeLock.request('screen'); } catch(e){} }
|
| 108 |
-
}
|
| 109 |
|
| 110 |
async function sync() {
|
| 111 |
const start = performance.now();
|
|
@@ -114,8 +96,17 @@
|
|
| 114 |
const d = await r.json();
|
| 115 |
const ping = Math.round(performance.now() - start);
|
| 116 |
serverOffset = (d.ts * 1000 + ping/2) - Date.now();
|
| 117 |
-
|
| 118 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 119 |
document.getElementById('v-ip').innerText = d.ip;
|
| 120 |
} catch(e){}
|
| 121 |
}
|
|
@@ -123,13 +114,22 @@
|
|
| 123 |
function update() {
|
| 124 |
const now = new Date(Date.now() + serverOffset);
|
| 125 |
|
| 126 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 127 |
const formatter = new Intl.DateTimeFormat('en-GB', {
|
| 128 |
-
timeZone: selectedTimezone,
|
| 129 |
-
hour: '2-digit', minute: '2-digit', second: '2-digit',
|
| 130 |
-
hour12: false
|
| 131 |
});
|
| 132 |
-
|
| 133 |
const parts = formatter.formatToParts(now);
|
| 134 |
const h = parts.find(p => p.type === 'hour').value;
|
| 135 |
const m = parts.find(p => p.type === 'minute').value;
|
|
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
| 6 |
+
<title>Sài Gòn Sync - Premium Countdown</title>
|
| 7 |
<script src="https://cdn.tailwindcss.com"></script>
|
| 8 |
<style>
|
| 9 |
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@700;800&family=Inter:wght@400;600;800&display=swap');
|
| 10 |
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; }
|
| 11 |
.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; }
|
| 12 |
+
.main-container { position: relative; z-index: 10; width: 100%; max-width: 600px; display: flex; flex-direction: column; align-items: center; padding: 20px; transition: all 0.5s; }
|
| 13 |
+
|
| 14 |
+
.tz-select { background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.1); color: #a5b4fc; padding: 5px 15px; border-radius: 10px; font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 15px; outline: none; cursor: pointer; }
|
| 15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
.clock-wrapper { display: flex; align-items: center; justify-content: center; font-family: 'JetBrains Mono', monospace; font-size: clamp(3rem, 15vw, 6.5rem); font-weight: 800; line-height: 1; gap: 4px; margin-bottom: 10px; }
|
| 17 |
.digit-column { height: 1.1em; overflow: hidden; position: relative; width: 0.65em; text-align: center; }
|
| 18 |
.digit-strip { transition: transform 0.5s cubic-bezier(0.16, 1, 0.3, 1); }
|
| 19 |
.digit-val { height: 1.1em; display: flex; align-items: center; justify-content: center; color: #fff; text-shadow: 0 0 20px rgba(255, 255, 255, 0.3); }
|
| 20 |
.sep { color: #4f46e5; opacity: 0.8; margin: 0 2px; padding-bottom: 10px; }
|
| 21 |
+
|
| 22 |
.stats-bar { background: rgba(255, 255, 255, 0.03); backdrop-filter: blur(20px); border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 20px; padding: 12px 30px; display: flex; gap: 30px; margin-top: 30px; }
|
| 23 |
.stat-box { display: flex; flex-direction: column; align-items: center; }
|
| 24 |
.stat-label { font-size: 8px; text-transform: uppercase; letter-spacing: 2px; color: #6366f1; margin-bottom: 2px; }
|
| 25 |
+
.stat-data { font-family: 'JetBrains Mono', monospace; font-size: 12px; font-weight: 600; transition: color 0.3s; }
|
| 26 |
+
|
| 27 |
+
/* Countdown Overlay */
|
| 28 |
+
#countdown-overlay {
|
| 29 |
+
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
|
| 30 |
+
background: rgba(0,0,0,0.9); display: none; z-index: 100;
|
| 31 |
+
flex-direction: column; align-items: center; justify-content: center;
|
| 32 |
+
}
|
| 33 |
+
#countdown-num { font-size: 15rem; font-weight: 900; color: #f87171; text-shadow: 0 0 50px rgba(248, 113, 113, 0.5); font-family: 'JetBrains Mono'; }
|
| 34 |
</style>
|
| 35 |
</head>
|
| 36 |
<body onclick="lockScreen()">
|
| 37 |
<div class="bg-glow"></div>
|
| 38 |
+
|
| 39 |
+
<div id="countdown-overlay">
|
| 40 |
+
<div class="text-white text-xl tracking-[10px] mb-8 font-bold">HAPPY NEW YEAR IN</div>
|
| 41 |
+
<div id="countdown-num">10</div>
|
| 42 |
+
</div>
|
| 43 |
+
|
| 44 |
+
<div class="main-container" id="main-ui">
|
| 45 |
<select id="timezone-selector" class="tz-select" onchange="changeTimezone()">
|
| 46 |
<option value="Asia/Ho_Chi_Minh">🇻🇳 Sài Gòn (GMT+7)</option>
|
| 47 |
<option value="Asia/Singapore">🇸🇬 Singapore (GMT+8)</option>
|
| 48 |
<option value="Asia/Tokyo">🇯🇵 Tokyo (GMT+9)</option>
|
|
|
|
| 49 |
<option value="Europe/London">🇬🇧 London (GMT+0)</option>
|
|
|
|
| 50 |
<option value="America/New_York">🇺🇸 New York (GMT-5)</option>
|
|
|
|
|
|
|
|
|
|
| 51 |
</select>
|
| 52 |
|
| 53 |
<div class="clock-wrapper">
|
|
|
|
| 80 |
const strip = document.getElementById(id);
|
| 81 |
for(let i=0; i<=9; i++) {
|
| 82 |
const div = document.createElement('div');
|
| 83 |
+
div.className = 'digit-val'; div.innerText = i; strip.appendChild(div);
|
|
|
|
|
|
|
| 84 |
}
|
| 85 |
});
|
| 86 |
}
|
| 87 |
|
| 88 |
+
function setDigit(id, val) { document.getElementById(id).style.transform = `translateY(-${val * 1.1}em)`; }
|
| 89 |
+
function changeTimezone() { selectedTimezone = document.getElementById('timezone-selector').value; }
|
| 90 |
+
async function lockScreen() { if ('wakeLock' in navigator) { try { wakeLock = await navigator.wakeLock.request('screen'); } catch(e){} } }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
|
| 92 |
async function sync() {
|
| 93 |
const start = performance.now();
|
|
|
|
| 96 |
const d = await r.json();
|
| 97 |
const ping = Math.round(performance.now() - start);
|
| 98 |
serverOffset = (d.ts * 1000 + ping/2) - Date.now();
|
| 99 |
+
const offsetAbs = Math.round(Math.abs(serverOffset));
|
| 100 |
+
|
| 101 |
+
const elPing = document.getElementById('v-ping');
|
| 102 |
+
const elOffset = document.getElementById('v-offset');
|
| 103 |
+
|
| 104 |
+
elPing.innerText = ping + "ms";
|
| 105 |
+
elPing.style.color = ping < 150 ? "#4ade80" : (ping < 400 ? "#facc15" : "#f87171");
|
| 106 |
+
|
| 107 |
+
elOffset.innerText = offsetAbs + "ms";
|
| 108 |
+
elOffset.style.color = offsetAbs < 10 ? "#4ade80" : (offsetAbs < 200 ? "#facc15" : "#f87171");
|
| 109 |
+
|
| 110 |
document.getElementById('v-ip').innerText = d.ip;
|
| 111 |
} catch(e){}
|
| 112 |
}
|
|
|
|
| 114 |
function update() {
|
| 115 |
const now = new Date(Date.now() + serverOffset);
|
| 116 |
|
| 117 |
+
// Logic Countdown năm mới
|
| 118 |
+
const nextYear = now.getFullYear() + 1;
|
| 119 |
+
const newYearTime = new Date(`Jan 1, ${nextYear} 00:00:00`).toLocaleString("en-US", {timeZone: selectedTimezone});
|
| 120 |
+
const diff = (new Date(newYearTime) - now) / 1000;
|
| 121 |
+
|
| 122 |
+
const overlay = document.getElementById('countdown-overlay');
|
| 123 |
+
if (diff > 0 && diff <= 10) {
|
| 124 |
+
overlay.style.display = 'flex';
|
| 125 |
+
document.getElementById('countdown-num').innerText = Math.ceil(diff);
|
| 126 |
+
} else {
|
| 127 |
+
overlay.style.display = 'none';
|
| 128 |
+
}
|
| 129 |
+
|
| 130 |
const formatter = new Intl.DateTimeFormat('en-GB', {
|
| 131 |
+
timeZone: selectedTimezone, hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false
|
|
|
|
|
|
|
| 132 |
});
|
|
|
|
| 133 |
const parts = formatter.formatToParts(now);
|
| 134 |
const h = parts.find(p => p.type === 'hour').value;
|
| 135 |
const m = parts.find(p => p.type === 'minute').value;
|