Skip to content

Commit d9beac9

Browse files
authored
Update index.html
1 parent ce59852 commit d9beac9

File tree

1 file changed

+257
-60
lines changed

1 file changed

+257
-60
lines changed

index.html

Lines changed: 257 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,95 +1,292 @@
11
<!DOCTYPE html>
22
<html lang="en">
33
<head>
4-
<meta charset="UTF-8" />
5-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6-
7-
<!-- TikTok Pixel Code Start -->
4+
<!-- TikTok Pixel Code Start -->
85
<script>
96
!function (w, d, t) {
107
w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];ttq.methods=["page","track","identify","instances","debug","on","off","once","ready","alias","group","enableCookie","disableCookie","holdConsent","revokeConsent","grantConsent"],ttq.setAndDefer=function(t,e){t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};for(var i=0;i<ttq.methods.length;i++)ttq.setAndDefer(ttq,ttq.methods[i]);ttq.instance=function(t){for(
118
var e=ttq._i[t]||[],n=0;n<ttq.methods.length;n++)ttq.setAndDefer(e,ttq.methods[n]);return e},ttq.load=function(e,n){var r="https://analytics.tiktok.com/i18n/pixel/events.js",o=n&&n.partner;ttq._i=ttq._i||{},ttq._i[e]=[],ttq._i[e]._u=r,ttq._t=ttq._t||{},ttq._t[e]=+new Date,ttq._o=ttq._o||{},ttq._o[e]=n||{};n=document.createElement("script")
129
;n.type="text/javascript",n.async=!0,n.src=r+"?sdkid="+e+"&lib="+t;e=document.getElementsByTagName("script")[0];e.parentNode.insertBefore(n,e)};
13-
14-
1510
ttq.load('D29K96JC77U9TM7VT9MG');
1611
ttq.page();
1712
}(window, document, 'ttq');
1813
</script>
1914
<!-- TikTok Pixel Code End -->
20-
15+
16+
<meta charset="UTF-8" />
2117
<title>NightClub Simulator VR</title>
18+
<meta name="viewport" content="width=device-width, initial-scale=1" />
19+
<meta name="description" content="NightClub Simulator VR — Join the beta for free and win a FREE game key!" />
20+
<link rel="preload" as="image" href="bg.png" />
2221
<style>
2322
:root {
24-
--primary: #5865f2; /* Discord blurple */
25-
--highlight: #ffcc00;
26-
--accent: #ff3366;
23+
--fg: #ffffff;
24+
--glow1: rgba(255, 208, 77, 0.95);
25+
--glow2: rgba(255, 104, 174, 0.9);
26+
--accent1: #ffd84d;
27+
--accent2: #ff68ae;
28+
--accent3: #8cebff;
29+
}
30+
* { box-sizing: border-box; }
31+
html, body {
32+
height: 100%;
33+
margin: 0;
34+
-webkit-font-smoothing: antialiased;
35+
-moz-osx-font-smoothing: grayscale;
36+
text-rendering: optimizeLegibility;
2737
}
28-
html, body {height: 100%; margin: 0;}
2938
body {
30-
height: 100vh; width: 100vw;
31-
background: url('bg.png') no-repeat center center/cover;
32-
display: flex; align-items: center; justify-content: center;
33-
color: #fff; font-family: 'Segoe UI', Roboto, Arial, sans-serif;
34-
position: relative; overflow: hidden;
39+
min-height: 100svh;
40+
background: url('bg.png') no-repeat center center / cover fixed;
41+
display: grid;
42+
place-items: center;
43+
color: var(--fg);
44+
font-family: Inter, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji","Segoe UI Emoji";
45+
position: relative;
46+
overflow: hidden;
47+
}
48+
.overlay {
49+
position: absolute; inset: 0;
50+
background: radial-gradient(120% 120% at 50% 50%, rgba(0,0,0,0.25), rgba(0,0,0,0.72) 55%, rgba(0,0,0,0.88));
51+
pointer-events: none;
52+
}
53+
main.content {
54+
position: relative; z-index: 1;
55+
text-align: center;
56+
width: min(92vw, 560px);
57+
padding: 6vh 4vw;
58+
animation: fadeUp 700ms ease-out both;
3559
}
36-
.overlay {position: absolute; inset: 0; background: rgba(0,0,0,.6);}
37-
.content {position: relative; z-index: 1; text-align: center; width: 90vw; max-width: 460px;}
38-
.title {
39-
font-size: 2.6rem; font-weight: 800; letter-spacing: 1.5px;
40-
margin: 3.5rem 0 1.25rem;
41-
background: linear-gradient(90deg, var(--highlight), var(--accent));
42-
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
43-
text-shadow: 0 0 20px rgba(255, 204, 0, 0.6);
44-
opacity: 0; transform: translateY(16px) scale(.98);
45-
animation: fadeUp .8s cubic-bezier(.2,.9,.2,1) .1s forwards;
60+
h1.title {
61+
margin: 0 0 1rem;
62+
font-size: clamp(1.8rem, 6.2vw, 3rem);
63+
font-weight: 800;
64+
letter-spacing: 0.04em;
65+
line-height: 1.1;
66+
background: linear-gradient(92deg, var(--accent1), var(--accent2) 55%, var(--accent3));
67+
-webkit-background-clip: text;
68+
background-clip: text;
69+
-webkit-text-fill-color: transparent;
70+
text-shadow:
71+
0 0 24px var(--glow2),
72+
0 0 48px rgba(140, 235, 255, 0.35);
73+
filter: drop-shadow(0 8px 28px rgba(0,0,0,0.45));
74+
animation: glowPulse 2400ms ease-in-out infinite;
4675
}
4776
.beta-text {
48-
font-size: 1.2rem; line-height: 1.45; font-weight: 700;
49-
letter-spacing: .4px; margin: 0 0 2rem;
77+
margin: 0.5rem 0 2rem;
78+
font-size: clamp(1rem, 4.5vw, 1.25rem);
79+
font-weight: 600;
80+
line-height: 1.35;
81+
letter-spacing: 0.02em;
82+
background: linear-gradient(92deg, #fff, #ffe3f3 60%, #e7ffff);
83+
-webkit-background-clip: text;
84+
background-clip: text;
85+
-webkit-text-fill-color: transparent;
86+
text-shadow:
87+
0 0 18px rgba(255,255,255,0.18),
88+
0 0 36px rgba(255,255,255,0.12);
89+
opacity: 0;
90+
animation: fadeIn 900ms 220ms ease-out forwards, shine 2200ms 300ms ease-in-out both;
91+
background-size: 200% auto;
5092
}
51-
.line {
52-
display: block; opacity: 0; transform: translateY(14px) scale(.98);
53-
background: linear-gradient(90deg, var(--accent), var(--highlight));
54-
-webkit-background-clip: text; -webkit-text-fill-color: transparent;
55-
text-shadow: 0 0 15px rgba(255, 51, 102, 0.6);
56-
animation: fadeUp .9s cubic-bezier(.2,.9,.2,1) forwards, glow 1.8s ease-in-out .9s 1;
93+
.beta-text .free {
94+
position: relative;
95+
font-weight: 950;
96+
letter-spacing: 0.02em;
97+
background: linear-gradient(92deg, var(--accent1), var(--accent2));
98+
-webkit-background-clip: text;
99+
background-clip: text;
100+
-webkit-text-fill-color: transparent;
101+
text-shadow:
102+
0 0 1px #000,
103+
0 0 2px #000,
104+
0 0 3px var(--glow1),
105+
0 0 5px var(--glow2),
106+
0 0 12px var(--glow2),
107+
0 0 22px var(--glow1),
108+
0 0 34px rgba(255, 255, 255, 0.25);
109+
animation:
110+
freePulse 2200ms ease-in-out infinite,
111+
freeFlicker 2600ms ease-in-out infinite;
112+
white-space: nowrap;
113+
display: inline-block;
57114
}
58-
.line:nth-child(1) {animation-delay: .25s, 1.05s;}
59-
.line:nth-child(2) {animation-delay: .45s, 1.25s;}
60-
.discord-btn {
61-
padding: 1rem 2.2rem; font-size: 1.15rem; font-weight: 800; letter-spacing: .8px;
62-
background: linear-gradient(90deg, var(--primary) 0%, #36393f 100%);
63-
color: #fff; border: 0; border-radius: 999px; cursor: pointer;
64-
box-shadow: 0 8px 24px rgba(88,101,242,.25);
65-
transition: transform .12s ease, filter .25s ease;
66-
opacity: 0; transform: translateY(14px) scale(.98);
67-
animation: fadeUp .8s cubic-bezier(.2,.9,.2,1) .75s forwards;
115+
a.discord-btn {
116+
display: inline-block;
117+
padding: 0.95rem 2.2rem;
118+
font-size: clamp(0.95rem, 4.2vw, 1.15rem);
119+
font-weight: 800;
120+
letter-spacing: 0.04em;
121+
color: #fff;
122+
text-decoration: none;
123+
background: linear-gradient(90deg, #5865f2 0%, #3b48c7 100%);
124+
border-radius: 999px;
125+
box-shadow:
126+
0 0 0 rgba(88, 101, 242, 0.0),
127+
0 10px 24px rgba(88, 101, 242, 0.35),
128+
inset 0 0 0 1px rgba(255,255,255,0.08);
129+
transform: translateZ(0);
130+
transition: transform 120ms ease, box-shadow 200ms ease, filter 200ms ease;
131+
will-change: transform, box-shadow, filter;
132+
animation: btnBreath 2600ms ease-in-out infinite;
68133
}
69-
.discord-btn:hover {transform: translateY(-2px) scale(1.04); filter: brightness(1.06);}
70-
@keyframes fadeUp {to {opacity: 1; transform: translateY(0) scale(1);}}
71-
@keyframes glow {
72-
0% {text-shadow: 0 0 0 rgba(255,255,255,0);}
73-
30% {text-shadow: 0 0 20px rgba(255, 204, 0, .9), 0 0 40px rgba(255, 51, 102, .5);}
74-
60% {text-shadow: 0 0 15px rgba(255, 204, 0, .6), 0 0 25px rgba(255, 51, 102, .3);}
75-
100% {text-shadow: 0 0 15px rgba(255, 51, 102, 0.6);}
134+
a.discord-btn:hover {
135+
transform: translateY(-2px) scale(1.03);
136+
filter: saturate(1.15);
76137
}
77-
@media (max-width:600px) {
78-
.title {font-size: 2.1rem; margin-top: 2.4rem;}
79-
.beta-text {font-size: 1rem;}
80-
.discord-btn {font-size: 1rem; padding: .9rem 1.6rem;}
138+
a.discord-btn:active {
139+
transform: translateY(0.5px) scale(0.99);
140+
filter: saturate(1);
81141
}
142+
@keyframes fadeUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
143+
@keyframes fadeIn { from { opacity: 0; filter: blur(6px); transform: translateY(6px); } to { opacity: 1; filter: blur(0); transform: translateY(0);} }
144+
@keyframes glowPulse { 0%, 100% { text-shadow: 0 0 24px var(--glow2), 0 0 48px rgba(140,235,255,0.35); } 50% { text-shadow: 0 0 32px rgba(255, 208, 77, 0.9), 0 0 56px rgba(140,235,255,0.55); } }
145+
@keyframes freePulse { 0%, 100% { transform: scale(1); filter: brightness(1); } 50% { transform: scale(1.06); filter: brightness(1.15); } }
146+
@keyframes freeFlicker { 0%, 100% { opacity: 1; } 42% { opacity: 0.95; } 44% { opacity: 0.6; } 46% { opacity: 1; } 72% { opacity: 0.92; } 74% { opacity: 0.65; } 76% { opacity: 1; } }
147+
@keyframes btnBreath { 0%, 100% { box-shadow: 0 0 0 rgba(88, 101, 242, 0.0), 0 10px 24px rgba(88, 101, 242, 0.35), inset 0 0 0 1px rgba(255,255,255,0.08); transform: translateZ(0) scale(1); } 50% { box-shadow: 0 0 24px rgba(88, 101, 242, 0.45), 0 18px 40px rgba(88, 101, 242, 0.55), inset 0 0 0 1px rgba(255,255,255,0.12); transform: translateZ(0) scale(1.03); } }
148+
@keyframes shine { 0% { background-position: -120% 0; } 100% { background-position: 220% 0; } }
149+
#test-panel { position: fixed; left: 10px; bottom: 10px; z-index: 9999; background: rgba(0,0,0,0.72); color: #eaf7ff; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; border: 1px solid rgba(255,255,255,0.12); border-radius: 8px; padding: 10px 12px; max-width: 86vw; font-size: 12px; display: none; white-space: pre-wrap; line-height: 1.35; }
150+
@media (prefers-reduced-motion: reduce) { * { animation: none !important; transition: none !important; } }
151+
noscript { position: fixed; top: 0; left: 0; right: 0; background: #111; color: #fff; padding: 8px 12px; font-size: 14px; text-align: center; }
82152
</style>
83153
</head>
84154
<body>
85155
<div class="overlay" aria-hidden="true"></div>
86156
<main class="content" role="main">
87-
<h1 class="title">NightClub Simulator VR</h1>
88-
<p class="beta-text" aria-live="polite">
89-
<span class="line">Join The Beta Test FOR FREE!</span>
90-
<span class="line">And get ready to win the FREE Game Key!</span>
157+
<h1 class="title" data-testid="title">NightClub Simulator VR</h1>
158+
<p class="beta-text" data-testid="beta">
159+
Join The Beta Test <span class="free">FOR FREE!</span><br />
160+
And get ready to win the <span class="free">FREE</span> Game Key!
91161
</p>
92-
<button class="discord-btn" onclick="window.open('https://discord.gg/74K429PbSH','_blank')" aria-label="Join our Discord on a new tab">Join Discord</button>
162+
<a
163+
class="discord-btn"
164+
data-testid="discord"
165+
href="https://discord.gg/74K429PbSH"
166+
target="_blank"
167+
rel="noopener noreferrer"
168+
aria-label="Join our Discord server"
169+
>Join Discord</a>
93170
</main>
171+
<noscript>JavaScript is disabled. Visual effects and diagnostics are limited.</noscript>
172+
<script id="page-logic">
173+
(function () {
174+
"use strict";
175+
function isMetaMaskConnectError(msg) {
176+
if (!msg) return false;
177+
const s = String(msg).toLowerCase();
178+
return (s.includes("metamask") && (s.includes("failed to connect") || s.includes("connect") || s.includes("request"))) ||
179+
(s.includes("ethereum") && (s.includes("connect") || s.includes("request")));
180+
}
181+
function handleGlobalError(ev) {
182+
const msg = ev.message || (ev.error && ev.error.message) || "";
183+
if (isMetaMaskConnectError(msg)) {
184+
ev.preventDefault?.();
185+
ev.stopImmediatePropagation?.();
186+
window.__ignoredMetaMaskErrors = (window.__ignoredMetaMaskErrors || 0) + 1;
187+
console.warn("[notice] Ignored MetaMask-related error:", msg);
188+
}
189+
}
190+
function handleRejection(ev) {
191+
const reason = ev.reason && (ev.reason.message || ev.reason.toString()) || "";
192+
if (isMetaMaskConnectError(reason)) {
193+
ev.preventDefault?.();
194+
ev.stopImmediatePropagation?.();
195+
window.__ignoredMetaMaskErrors = (window.__ignoredMetaMaskErrors || 0) + 1;
196+
console.warn("[notice] Ignored MetaMask-related rejection:", reason);
197+
}
198+
}
199+
window.addEventListener("error", handleGlobalError, true);
200+
window.addEventListener("unhandledrejection", handleRejection, true);
201+
const img = new Image();
202+
img.src = "bg.png";
203+
})();
204+
</script>
205+
<script id="tests">
206+
(function (){
207+
"use strict";
208+
const tests = [];
209+
function test(name, fn) { tests.push({name, fn}); }
210+
function assert(cond, msg) { if (!cond) throw new Error(msg || "Assertion failed"); }
211+
const $ = (sel) => document.querySelector(sel);
212+
test("Title exists and text matches", () => {
213+
const el = $('[data-testid="title"]');
214+
assert(!!el, "Title not found");
215+
assert(el.textContent.trim() === "NightClub Simulator VR", "Title text mismatch");
216+
});
217+
test("Beta text contains both lines and FREE markers", () => {
218+
const el = $('[data-testid="beta"]');
219+
assert(!!el, "Beta text not found");
220+
const txt = el.innerText.replace(/\s+/g,' ').trim().toLowerCase();
221+
assert(txt.includes("join the beta test"), "Missing first line");
222+
assert(txt.includes("get ready to win"), "Missing second line");
223+
assert((el.querySelectorAll(".free").length >= 2), "FREE markers not highlighted");
224+
});
225+
test("Discord button configured safely", () => {
226+
const a = $('[data-testid="discord"]');
227+
assert(!!a, "Discord button not found");
228+
assert(a.getAttribute("target") === "_blank", "Discord link should open in new tab");
229+
const rel = (a.getAttribute("rel") || "").toLowerCase();
230+
assert(rel.includes("noopener") && rel.includes("noreferrer"), "Missing noopener/noreferrer");
231+
});
232+
test("Discord URL is correct", () => {
233+
const a = $('[data-testid="discord"]');
234+
assert(!!a, "Discord button not found");
235+
assert(a.getAttribute("href") === "https://discord.gg/74K429PbSH", "Discord invite URL mismatch");
236+
});
237+
test("Background image style applied", () => {
238+
const bg = getComputedStyle(document.body).backgroundImage;
239+
assert(bg && bg !== "none", "Background image CSS not applied");
240+
assert(bg.toLowerCase().includes("bg.png"), "Background should reference bg.png");
241+
});
242+
test("No wallet-connection calls in page logic", () => {
243+
const script = document.getElementById("page-logic").textContent;
244+
const patterns = [
245+
/ethereum\s*\.\s*request\s*\(/i,
246+
/ethereum\s*\.\s*enable\s*\(/i,
247+
/eth_?request?accounts/i
248+
];
249+
const matched = patterns.some(p => p.test(script));
250+
assert(!matched, "Page logic should not attempt to connect to wallets");
251+
});
252+
test("MetaMask 'Failed to connect' error is suppressed", () => {
253+
const evt = new ErrorEvent("error", {
254+
message: "Failed to connect to MetaMask",
255+
cancelable: true,
256+
});
257+
window.dispatchEvent(evt);
258+
assert(evt.defaultPrevented === true, "MetaMask error should be prevented");
259+
assert((window.__ignoredMetaMaskErrors || 0) >= 1, "Suppression counter not increased");
260+
});
261+
test("MetaMask rejection is suppressed", () => {
262+
const ev = new PromiseRejectionEvent("unhandledrejection", {
263+
reason: new Error("Failed to connect to MetaMask"),
264+
cancelable: true
265+
});
266+
window.dispatchEvent(ev);
267+
assert(ev.defaultPrevented === true, "MetaMask rejection should be prevented");
268+
});
269+
const results = [];
270+
let pass = 0, fail = 0;
271+
for (const t of tests) {
272+
try {
273+
t.fn();
274+
results.push(`✅ ${t.name}`);
275+
pass++;
276+
} catch (e) {
277+
results.push(`❌ ${t.name}${e.message}`);
278+
fail++;
279+
}
280+
}
281+
const summary = `Tests: ${pass + fail}, Passed: ${pass}, Failed: ${fail}\n` + results.join("\n");
282+
console.log(summary);
283+
if (new URLSearchParams(location.search).get("test") === "1") {
284+
const panel = document.getElementById("test-panel");
285+
panel.style.display = "block";
286+
panel.textContent = summary;
287+
}
288+
})();
289+
</script>
290+
<div id="test-panel" aria-live="polite" aria-atomic="true"></div>
94291
</body>
95292
</html>

0 commit comments

Comments
 (0)