Game — Retro Arcade / Neon Landing
A loud 80s retro-arcade neon landing page with a glowing Tron-style perspective grid floor, a flickering neon title, a CRT scanline and vignette overlay, an INSERT COIN call to action, an animated high-score ticker, a swipeable arcade-cabinet game lineup carousel with hype bars, and a synthwave soundtrack teaser with a live bar visualizer. Built in vanilla HTML, CSS, and JavaScript with no frameworks, accessible focus states, and a fully responsive layout down to 360px wide.
MCP
Code
:root {
/* Retro arcade / neon — black + magenta/cyan, CRT glow */
--bg: #05030a;
--bg-2: #0a0716;
--panel: #0e0a1a;
--panel-2: #15102a;
--text: #f5f0ff;
--muted: #9a8fc0;
--line: rgba(245, 240, 255, 0.10);
--line-2: rgba(245, 240, 255, 0.20);
--accent: #ff2bd6; /* magenta */
--accent-2: #19f0ff; /* cyan */
--accent-3: #ffe93d; /* yellow */
--glow-m: 0 0 8px rgba(255, 43, 214, 0.7), 0 0 22px rgba(255, 43, 214, 0.4);
--glow-c: 0 0 8px rgba(25, 240, 255, 0.7), 0 0 22px rgba(25, 240, 255, 0.4);
--r-sm: 6px;
--r-md: 10px;
--r-lg: 16px;
--maxw: 1120px;
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
margin: 0;
background: var(--bg);
color: var(--text);
font-family: "Inter", system-ui, sans-serif;
line-height: 1.5;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
overflow-x: hidden;
}
h1, h2, h3 { margin: 0; font-family: "Orbitron", sans-serif; letter-spacing: 0.04em; }
a { color: inherit; text-decoration: none; }
button { font-family: inherit; cursor: pointer; }
:focus-visible {
outline: 2px solid var(--accent-2);
outline-offset: 3px;
border-radius: var(--r-sm);
}
/* ===== CRT OVERLAY ===== */
.crt {
position: fixed;
inset: 0;
z-index: 90;
pointer-events: none;
background:
repeating-linear-gradient(
to bottom,
rgba(0, 0, 0, 0) 0,
rgba(0, 0, 0, 0) 2px,
rgba(0, 0, 0, 0.28) 3px,
rgba(0, 0, 0, 0.28) 4px
);
mix-blend-mode: multiply;
}
.crt::after {
content: "";
position: absolute;
inset: 0;
background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0) 55%, rgba(0, 0, 0, 0.7) 100%);
}
/* ===== BUTTONS ===== */
.btn {
position: relative;
display: inline-flex;
align-items: center;
gap: 0.5rem;
border: 1px solid var(--line-2);
background: var(--panel-2);
color: var(--text);
font-family: "Orbitron", sans-serif;
font-weight: 700;
font-size: 0.9rem;
letter-spacing: 0.06em;
padding: 0.75rem 1.4rem;
border-radius: var(--r-sm);
transition: transform 0.12s ease, box-shadow 0.2s ease, border-color 0.2s ease, background 0.2s ease;
clip-path: polygon(10px 0, 100% 0, 100% calc(100% - 10px), calc(100% - 10px) 100%, 0 100%, 0 10px);
}
.btn--sm { padding: 0.55rem 1rem; font-size: 0.78rem; }
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }
.btn--ghost { background: transparent; color: var(--accent-2); border-color: rgba(25, 240, 255, 0.45); }
.btn--ghost:hover { box-shadow: var(--glow-c); border-color: var(--accent-2); }
.btn--coin {
background: linear-gradient(180deg, #3a0a30, #1a0518);
color: var(--accent);
border-color: var(--accent);
box-shadow: var(--glow-m);
text-shadow: 0 0 6px rgba(255, 43, 214, 0.6);
}
.btn--coin:hover { box-shadow: 0 0 14px rgba(255, 43, 214, 0.9), 0 0 30px rgba(255, 43, 214, 0.5); }
.btn__coin { animation: spinCoin 2.2s linear infinite; display: inline-block; }
@keyframes spinCoin { to { transform: rotateY(360deg); } }
.btn--play {
background: linear-gradient(180deg, #073640, #021820);
color: var(--accent-2);
border-color: var(--accent-2);
box-shadow: var(--glow-c);
text-shadow: 0 0 6px rgba(25, 240, 255, 0.6);
}
.btn--play:hover { box-shadow: 0 0 14px rgba(25, 240, 255, 0.9), 0 0 30px rgba(25, 240, 255, 0.5); }
/* ===== HERO ===== */
.hero {
position: relative;
min-height: 100vh;
display: flex;
flex-direction: column;
overflow: hidden;
background:
radial-gradient(ellipse 80% 60% at 50% 18%, rgba(255, 43, 214, 0.18), transparent 60%),
linear-gradient(180deg, #0a0518 0%, #05030a 55%);
}
.hero__sun {
position: absolute;
left: 50%;
top: 16%;
width: 360px;
height: 360px;
transform: translateX(-50%);
border-radius: 50%;
background: linear-gradient(180deg, var(--accent-3) 0%, var(--accent) 60%, transparent 70%);
filter: blur(2px);
opacity: 0.85;
-webkit-mask-image: repeating-linear-gradient(180deg, #000 0 14px, transparent 14px 20px);
mask-image: repeating-linear-gradient(180deg, #000 0 14px, transparent 14px 20px);
z-index: 0;
}
/* perspective grid floor */
.grid-floor {
position: absolute;
left: 50%;
bottom: 0;
width: 200%;
height: 46%;
transform: translateX(-50%);
perspective: 320px;
perspective-origin: 50% 0;
z-index: 0;
-webkit-mask-image: linear-gradient(180deg, transparent, #000 28%);
mask-image: linear-gradient(180deg, transparent, #000 28%);
}
.grid-floor__lines {
position: absolute;
inset: -50% 0 0 0;
transform: rotateX(70deg);
background-image:
linear-gradient(rgba(25, 240, 255, 0.55) 2px, transparent 2px),
linear-gradient(90deg, rgba(255, 43, 214, 0.5) 2px, transparent 2px);
background-size: 100% 44px, 44px 100%;
animation: gridRoll 1.1s linear infinite;
will-change: background-position;
}
@keyframes gridRoll { to { background-position: 0 44px, 0 0; } }
.nav {
position: relative;
z-index: 5;
max-width: var(--maxw);
width: 100%;
margin: 0 auto;
padding: 1.2rem 1.5rem;
display: flex;
align-items: center;
gap: 1rem;
}
.brand { display: inline-flex; align-items: center; gap: 0.55rem; font-family: "Orbitron", sans-serif; font-weight: 900; }
.brand__mark { color: var(--accent-2); text-shadow: var(--glow-c); letter-spacing: -2px; }
.brand__name { font-size: 1.05rem; letter-spacing: 0.08em; }
.brand__dot { color: var(--accent); }
.nav__links { display: flex; gap: 1.5rem; margin: 0 auto 0 2rem; padding: 0; list-style: none; }
.nav__links a { font-size: 0.85rem; font-weight: 600; color: var(--muted); transition: color 0.2s, text-shadow 0.2s; }
.nav__links a:hover { color: var(--accent-2); text-shadow: var(--glow-c); }
.hero__inner {
position: relative;
z-index: 5;
flex: 1;
max-width: var(--maxw);
width: 100%;
margin: 0 auto;
padding: 2rem 1.5rem 6rem;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
text-align: center;
}
.hero__kicker {
margin: 0 0 1rem;
font-family: "Orbitron", sans-serif;
font-size: 0.72rem;
letter-spacing: 0.4em;
color: var(--accent-2);
text-shadow: var(--glow-c);
}
.hero__title {
font-size: clamp(3rem, 12vw, 7.5rem);
font-weight: 900;
line-height: 0.95;
color: #fff;
text-shadow:
0 0 8px rgba(255, 43, 214, 0.9),
0 0 24px rgba(255, 43, 214, 0.7),
0 0 48px rgba(255, 43, 214, 0.45),
0 0 90px rgba(25, 240, 255, 0.35);
}
.hero__title.flick { opacity: 0.45; text-shadow: 0 0 4px rgba(255, 43, 214, 0.5); }
.hero__sub {
max-width: 560px;
margin: 1.3rem 0 0;
color: var(--muted);
font-size: 1.02rem;
}
.hero__cta { display: flex; gap: 1rem; margin-top: 2rem; flex-wrap: wrap; justify-content: center; }
.hero__stats { display: flex; gap: 2.4rem; margin-top: 3rem; flex-wrap: wrap; justify-content: center; }
.stat { text-align: center; }
.stat__num {
display: block;
font-family: "Orbitron", sans-serif;
font-weight: 900;
font-size: 2rem;
color: var(--accent-3);
text-shadow: 0 0 10px rgba(255, 233, 61, 0.6);
}
.stat__label { font-size: 0.7rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); }
/* ===== TICKER ===== */
.ticker {
position: relative;
z-index: 2;
display: flex;
align-items: stretch;
background: #0b0418;
border-top: 1px solid var(--line);
border-bottom: 1px solid var(--line);
overflow: hidden;
}
.ticker__tag {
flex: none;
display: flex;
align-items: center;
padding: 0 1.2rem;
font-family: "Orbitron", sans-serif;
font-weight: 700;
font-size: 0.8rem;
letter-spacing: 0.15em;
color: var(--bg);
background: var(--accent);
box-shadow: var(--glow-m);
}
.ticker__viewport { flex: 1; overflow: hidden; }
.ticker__track {
display: inline-flex;
gap: 2.5rem;
padding: 0.7rem 0;
white-space: nowrap;
animation: tickerScroll 26s linear infinite;
}
.ticker:hover .ticker__track { animation-play-state: paused; }
@keyframes tickerScroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.ticker__item { font-size: 0.85rem; color: var(--muted); font-family: "Orbitron", sans-serif; }
.ticker__item b { color: var(--accent-2); text-shadow: var(--glow-c); }
.ticker__item .score { color: var(--accent-3); }
/* ===== SECTION HEAD ===== */
.section__head {
max-width: var(--maxw);
margin: 0 auto;
padding: 4rem 1.5rem 1.5rem;
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: 1rem;
}
.section__title {
font-size: clamp(1.6rem, 4vw, 2.4rem);
font-weight: 900;
color: #fff;
text-shadow: 0 0 10px rgba(25, 240, 255, 0.6), 0 0 30px rgba(25, 240, 255, 0.3);
}
/* ===== CAROUSEL ===== */
.carousel__nav { display: flex; gap: 0.6rem; }
.cab-btn {
width: 44px; height: 44px;
display: grid; place-items: center;
background: var(--panel);
border: 1px solid var(--line-2);
color: var(--accent-2);
border-radius: var(--r-sm);
font-size: 1rem;
transition: box-shadow 0.2s, border-color 0.2s, transform 0.12s;
}
.cab-btn:hover { box-shadow: var(--glow-c); border-color: var(--accent-2); transform: translateY(-2px); }
.carousel { max-width: var(--maxw); margin: 0 auto; padding: 0 1.5rem; overflow: hidden; }
.carousel__track {
display: flex;
gap: 1.3rem;
transition: transform 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}
.cab {
flex: 0 0 calc((100% - 2.6rem) / 3);
position: relative;
background: linear-gradient(180deg, var(--panel-2), var(--panel));
border: 1px solid var(--line-2);
border-radius: var(--r-md);
padding: 1.2rem;
overflow: hidden;
transition: box-shadow 0.25s, border-color 0.25s, transform 0.2s;
clip-path: polygon(0 0, 100% 0, 100% calc(100% - 16px), calc(100% - 16px) 100%, 0 100%);
}
.cab:hover {
border-color: var(--accent);
box-shadow: var(--glow-m);
transform: translateY(-4px);
}
.cab__screen {
height: 150px;
border-radius: var(--r-sm);
border: 1px solid var(--line);
display: grid;
place-items: center;
font-family: "Orbitron", sans-serif;
font-weight: 900;
font-size: 2.4rem;
color: rgba(255, 255, 255, 0.92);
text-shadow: 0 0 14px currentColor;
position: relative;
overflow: hidden;
}
.cab__screen::after {
content: "";
position: absolute; inset: 0;
background: repeating-linear-gradient(to bottom, rgba(0,0,0,0) 0 2px, rgba(0,0,0,0.25) 3px 4px);
}
.cab__badge {
position: absolute; top: 0.9rem; right: 0.9rem;
font-family: "Orbitron", sans-serif;
font-size: 0.6rem; letter-spacing: 0.1em;
padding: 0.25rem 0.5rem;
border-radius: 99px;
background: var(--accent-3); color: #1a1500;
font-weight: 700;
z-index: 2;
}
.cab__name { margin-top: 0.9rem; font-family: "Orbitron", sans-serif; font-weight: 700; font-size: 1.05rem; }
.cab__genre { font-size: 0.75rem; color: var(--muted); margin-top: 0.2rem; letter-spacing: 0.08em; text-transform: uppercase; }
.cab__bar { height: 6px; background: rgba(255,255,255,0.08); border-radius: 99px; margin-top: 0.9rem; overflow: hidden; }
.cab__fill { height: 100%; width: 0; border-radius: 99px; background: linear-gradient(90deg, var(--accent-2), var(--accent)); transition: width 1s ease; box-shadow: var(--glow-c); }
.cab__meta { display: flex; justify-content: space-between; margin-top: 0.5rem; font-size: 0.7rem; color: var(--muted); }
.cab__meta b { color: var(--accent-2); }
.carousel__dots { display: flex; gap: 0.5rem; justify-content: center; margin-top: 1.6rem; }
.dot {
width: 11px; height: 11px; border-radius: 50%;
border: 1px solid var(--line-2); background: transparent;
padding: 0; transition: all 0.2s;
}
.dot[aria-selected="true"] { background: var(--accent); border-color: var(--accent); box-shadow: var(--glow-m); }
/* ===== SOUNDTRACK ===== */
.sound { max-width: var(--maxw); margin: 0 auto; padding: 4.5rem 1.5rem; }
.sound__panel {
display: grid;
grid-template-columns: 220px 1fr;
gap: 2rem;
align-items: center;
background: linear-gradient(135deg, rgba(255,43,214,0.08), rgba(25,240,255,0.06)), var(--panel);
border: 1px solid var(--line-2);
border-radius: var(--r-lg);
padding: 2rem;
box-shadow: inset 0 0 60px rgba(255, 43, 214, 0.06);
}
.sound__viz {
height: 170px;
display: flex;
align-items: flex-end;
gap: 5px;
padding: 0.6rem;
border-radius: var(--r-md);
border: 1px solid var(--line);
background: #07030f;
}
.sound__viz .bar {
flex: 1;
background: linear-gradient(180deg, var(--accent), var(--accent-2));
border-radius: 3px 3px 0 0;
box-shadow: 0 0 8px rgba(255,43,214,0.5);
transition: height 0.12s ease;
}
.sound__kicker { font-family: "Orbitron", sans-serif; font-size: 0.7rem; letter-spacing: 0.3em; color: var(--accent-3); margin: 0; }
.sound__title { font-size: clamp(1.6rem, 4vw, 2.3rem); font-weight: 900; margin: 0.4rem 0 0.6rem; color: #fff; text-shadow: var(--glow-m); }
.sound__track { color: var(--muted); font-size: 0.9rem; margin: 0 0 1.2rem; }
.sound__controls { display: flex; gap: 0.8rem; flex-wrap: wrap; }
/* ===== FOOTER ===== */
.foot { border-top: 1px solid var(--line); background: #07030f; }
.foot__neon {
text-align: center;
padding: 3rem 1.5rem 2rem;
font-family: "Orbitron", sans-serif;
font-weight: 900;
font-size: clamp(1.1rem, 3vw, 1.6rem);
color: var(--muted);
letter-spacing: 0.1em;
}
.foot__neon span { color: var(--accent); text-shadow: var(--glow-m); animation: blink 1.2s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0.25; } }
.foot__row {
max-width: var(--maxw);
margin: 0 auto;
padding: 1.6rem 1.5rem 3rem;
display: flex;
align-items: center;
justify-content: space-between;
gap: 1rem;
flex-wrap: wrap;
border-top: 1px solid var(--line);
}
.foot__links { display: flex; gap: 1.2rem; }
.foot__links a { font-size: 0.82rem; color: var(--muted); transition: color 0.2s, text-shadow 0.2s; }
.foot__links a:hover { color: var(--accent-2); text-shadow: var(--glow-c); }
.foot__copy { font-size: 0.72rem; color: var(--muted); }
/* ===== TOAST ===== */
.toast {
position: fixed;
left: 50%;
bottom: 28px;
transform: translate(-50%, 140%);
z-index: 100;
background: var(--panel-2);
border: 1px solid var(--accent);
color: var(--text);
font-family: "Orbitron", sans-serif;
font-size: 0.82rem;
letter-spacing: 0.04em;
padding: 0.85rem 1.3rem;
border-radius: var(--r-sm);
box-shadow: var(--glow-m);
opacity: 0;
transition: transform 0.32s cubic-bezier(0.22,1,0.36,1), opacity 0.32s;
max-width: 90vw;
}
.toast.show { transform: translate(-50%, 0); opacity: 1; }
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; }
}
/* ===== RESPONSIVE ===== */
@media (max-width: 900px) {
.cab { flex-basis: calc((100% - 1.3rem) / 2); }
.sound__panel { grid-template-columns: 1fr; }
.nav__links { display: none; }
}
@media (max-width: 520px) {
.cab { flex-basis: 100%; }
.hero__stats { gap: 1.4rem; }
.stat__num { font-size: 1.5rem; }
.nav { flex-wrap: wrap; }
.brand__name { font-size: 0.9rem; }
.foot__row { flex-direction: column; text-align: center; }
.section__head { padding-top: 3rem; }
.ticker__tag { font-size: 0.65rem; padding: 0 0.7rem; }
}(function () {
"use strict";
/* ---------- Toast helper ---------- */
var toastEl = document.getElementById("toast");
var toastTimer;
function toast(msg) {
if (!toastEl) return;
toastEl.textContent = msg;
toastEl.classList.add("show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("show");
}, 2600);
}
document.querySelectorAll("[data-toast]").forEach(function (btn) {
btn.addEventListener("click", function () {
toast(btn.getAttribute("data-toast"));
});
});
var reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
/* ---------- Title flicker ---------- */
var title = document.querySelector("[data-flicker]");
if (title && !reduced) {
setInterval(function () {
if (Math.random() > 0.78) {
title.classList.add("flick");
setTimeout(function () { title.classList.remove("flick"); }, 70 + Math.random() * 90);
}
}, 280);
}
/* ---------- Animated stat counters ---------- */
document.querySelectorAll("[data-count]").forEach(function (el) {
var target = parseInt(el.getAttribute("data-count"), 10) || 0;
var start = null;
function step(ts) {
if (!start) start = ts;
var p = Math.min((ts - start) / 1200, 1);
el.textContent = Math.round(target * (1 - Math.pow(1 - p, 3)));
if (p < 1) requestAnimationFrame(step);
}
requestAnimationFrame(step);
});
/* ---------- High-score ticker ---------- */
var scores = [
{ name: "AAA", game: "Neon Drift", score: 9820450 },
{ name: "ZX9", game: "Hollow Reign", score: 7714200 },
{ name: "VEX", game: "Ashen Vanguard", score: 6620980 },
{ name: "RGB", game: "Chrome Sunset", score: 5530110 },
{ name: "K1T", game: "Grid Runner X", score: 4488700 },
{ name: "NUL", game: "Pulse Raider", score: 3902560 },
{ name: "MEG", game: "Neon Drift", score: 3120440 },
{ name: "ORB", game: "Void Circuit", score: 2755300 }
];
var track = document.getElementById("tickerTrack");
if (track) {
function fmt(n) { return n.toLocaleString("en-US"); }
var html = scores.map(function (s, i) {
return '<span class="ticker__item">#' + (i + 1) +
' <b>' + s.name + '</b> · ' + s.game +
' · <span class="score">' + fmt(s.score) + '</span></span>';
}).join("");
track.innerHTML = html + html; /* duplicate for seamless loop */
}
/* ---------- Game lineup carousel ---------- */
var games = [
{ name: "Neon Drift", genre: "Synthwave Racer", glyph: "▲", color: "#ff2bd6", badge: "NEW", rating: 98, plays: "12.4M" },
{ name: "Hollow Reign", genre: "Dark Platformer", glyph: "✦", color: "#19f0ff", badge: "HOT", rating: 94, plays: "8.9M" },
{ name: "Ashen Vanguard", genre: "Mech Shooter", glyph: "◆", color: "#ffe93d", badge: "TOP", rating: 91, plays: "6.2M" },
{ name: "Grid Runner X", genre: "Endless Arcade", glyph: "●", color: "#ff2bd6", badge: "RETRO", rating: 88, plays: "5.5M" },
{ name: "Pulse Raider", genre: "Rhythm Combat", glyph: "■", color: "#19f0ff", badge: "BETA", rating: 86, plays: "3.9M" },
{ name: "Void Circuit", genre: "Puzzle Shooter", glyph: "✺", color: "#ffe93d", badge: "INDIE", rating: 90, plays: "2.7M" }
];
var cabTrack = document.getElementById("cabTrack");
var dotsWrap = document.getElementById("cabDots");
var carousel = document.getElementById("carousel");
var index = 0;
function perView() {
var w = window.innerWidth;
if (w <= 520) return 1;
if (w <= 900) return 2;
return 3;
}
if (cabTrack) {
cabTrack.innerHTML = games.map(function (g) {
return (
'<article class="cab" tabindex="0">' +
'<div class="cab__badge">' + g.badge + "</div>" +
'<div class="cab__screen" style="color:' + g.color +
';background:radial-gradient(circle at 50% 40%, ' + g.color + '22, #07030f 70%)">' + g.glyph + "</div>" +
'<div class="cab__name">' + g.name + "</div>" +
'<div class="cab__genre">' + g.genre + "</div>" +
'<div class="cab__bar"><div class="cab__fill" data-rating="' + g.rating + '"></div></div>' +
'<div class="cab__meta"><span>HYPE <b>' + g.rating + '%</b></span><span>' + g.plays + " plays</span></div>" +
"</article>"
);
}).join("");
/* dots */
var pages = Math.max(1, games.length - perView() + 1);
function buildDots() {
pages = Math.max(1, games.length - perView() + 1);
dotsWrap.innerHTML = "";
for (var i = 0; i < pages; i++) {
var d = document.createElement("button");
d.className = "dot";
d.setAttribute("role", "tab");
d.setAttribute("aria-label", "Slide " + (i + 1));
(function (i) { d.addEventListener("click", function () { go(i); }); })(i);
dotsWrap.appendChild(d);
}
}
function update() {
var card = cabTrack.querySelector(".cab");
if (!card) return;
var gap = 1.3 * 16;
var step = card.offsetWidth + gap;
cabTrack.style.transform = "translateX(" + (-index * step) + "px)";
dotsWrap.querySelectorAll(".dot").forEach(function (d, i) {
d.setAttribute("aria-selected", i === index ? "true" : "false");
});
}
function go(i) {
var max = Math.max(0, games.length - perView());
index = Math.max(0, Math.min(i, max));
update();
}
document.getElementById("nextCab").addEventListener("click", function () { go(index + 1); });
document.getElementById("prevCab").addEventListener("click", function () { go(index - 1); });
carousel.addEventListener("keydown", function (e) {
if (e.key === "ArrowRight") { e.preventDefault(); go(index + 1); }
if (e.key === "ArrowLeft") { e.preventDefault(); go(index - 1); }
});
buildDots();
update();
/* animate hype bars in once */
requestAnimationFrame(function () {
cabTrack.querySelectorAll(".cab__fill").forEach(function (f) {
f.style.width = f.getAttribute("data-rating") + "%";
});
});
var rt;
window.addEventListener("resize", function () {
clearTimeout(rt);
rt = setTimeout(function () { buildDots(); go(index); }, 150);
});
}
/* ---------- Soundtrack visualizer ---------- */
var viz = document.getElementById("viz");
var playBtn = document.getElementById("playBtn");
var nowPlaying = document.getElementById("nowPlaying");
var bars = [];
var playing = false;
var vizTimer;
var tracks = ['"Chrome Sunset"', '"Midnight Velocity"', '"Outrun Protocol"', '"Magenta Skies"'];
var trackIdx = 0;
if (viz) {
for (var b = 0; b < 28; b++) {
var bar = document.createElement("span");
bar.className = "bar";
bar.style.height = "20%";
viz.appendChild(bar);
bars.push(bar);
}
function animateViz() {
bars.forEach(function (bar) {
bar.style.height = (playing ? (12 + Math.random() * 88) : (8 + Math.random() * 14)) + "%";
});
}
animateViz();
if (!reduced) vizTimer = setInterval(animateViz, 130);
}
if (playBtn) {
playBtn.addEventListener("click", function () {
playing = !playing;
playBtn.textContent = playing ? "❚❚ PAUSE" : "▶ PREVIEW";
if (playing) {
trackIdx = (trackIdx + 1) % tracks.length;
nowPlaying.textContent = "NOW SPINNING — " + tracks[trackIdx] + " · Nullforge Audio";
toast("♪ Streaming preview — " + tracks[trackIdx]);
} else {
toast("Preview paused.");
}
});
}
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Neon Drift — Insert Coin</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@500;700;900&family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<!-- CRT overlay (scanlines + vignette) -->
<div class="crt" aria-hidden="true"></div>
<!-- ===== HERO ===== -->
<header class="hero">
<div class="grid-floor" aria-hidden="true"><div class="grid-floor__lines"></div></div>
<div class="hero__sun" aria-hidden="true"></div>
<nav class="nav">
<a class="brand" href="#top" id="top">
<span class="brand__mark" aria-hidden="true">◣◢</span>
<span class="brand__name">NULLFORGE<span class="brand__dot">.</span>ARCADE</span>
</a>
<ul class="nav__links">
<li><a href="#lineup">Games</a></li>
<li><a href="#scores">Scores</a></li>
<li><a href="#sound">Soundtrack</a></li>
</ul>
<button class="btn btn--ghost" data-toast="Free play unlocked — no quarters required.">Free Play</button>
</nav>
<div class="hero__inner">
<p class="hero__kicker">NULLFORGE PRESENTS · CAB-1986</p>
<h1 class="hero__title" data-flicker>NEON DRIFT</h1>
<p class="hero__sub">Outrun the synthwave horizon. Chain combos, dodge the grid, and burn your name into the leaderboard before the credits run dry.</p>
<div class="hero__cta">
<button class="btn btn--coin" data-toast="◉ COIN ACCEPTED — Press START to begin.">
<span class="btn__coin">◉</span> INSERT COIN
</button>
<button class="btn btn--play" data-toast="▶ Booting Neon Drift… buckle up.">PLAY NOW</button>
</div>
<div class="hero__stats">
<div class="stat"><span class="stat__num" data-count="4">0</span><span class="stat__label">Players Online (M)</span></div>
<div class="stat"><span class="stat__num" data-count="92">0</span><span class="stat__label">Metascore</span></div>
<div class="stat"><span class="stat__num" data-count="16">0</span><span class="stat__label">Neon Tracks</span></div>
</div>
</div>
</header>
<!-- ===== HIGH SCORE TICKER ===== -->
<section class="ticker" id="scores" aria-label="High score ticker">
<span class="ticker__tag">HI-SCORES</span>
<div class="ticker__viewport">
<div class="ticker__track" id="tickerTrack"></div>
</div>
</section>
<!-- ===== GAME LINEUP CAROUSEL ===== -->
<section class="lineup" id="lineup">
<div class="section__head">
<h2 class="section__title">ARCADE LINEUP</h2>
<div class="carousel__nav">
<button class="cab-btn" id="prevCab" aria-label="Previous game">◄</button>
<button class="cab-btn" id="nextCab" aria-label="Next game">►</button>
</div>
</div>
<div class="carousel" id="carousel" tabindex="0" aria-roledescription="carousel">
<div class="carousel__track" id="cabTrack">
<!-- cabinets injected by JS -->
</div>
</div>
<div class="carousel__dots" id="cabDots" role="tablist" aria-label="Choose game"></div>
</section>
<!-- ===== SOUNDTRACK TEASER ===== -->
<section class="sound" id="sound">
<div class="sound__panel">
<div class="sound__viz" id="viz" aria-hidden="true"></div>
<div class="sound__body">
<p class="sound__kicker">SYNTHWAVE OST · VOL. III</p>
<h2 class="sound__title">MIDNIGHT VELOCITY</h2>
<p class="sound__track" id="nowPlaying">NOW SPINNING — "Chrome Sunset" · Nullforge Audio</p>
<div class="sound__controls">
<button class="btn btn--play btn--sm" id="playBtn">▶ PREVIEW</button>
<button class="btn btn--ghost btn--sm" data-toast="Added to your wishlist — pre-order ships 1986.">+ WISHLIST OST</button>
</div>
</div>
</div>
</section>
<!-- ===== FOOTER ===== -->
<footer class="foot">
<div class="foot__neon">GAME OVER? <span>INSERT COIN TO CONTINUE</span></div>
<div class="foot__row">
<span class="brand__name">NULLFORGE<span class="brand__dot">.</span>ARCADE</span>
<nav class="foot__links">
<a href="#lineup">Games</a><a href="#scores">Leaderboard</a><a href="#sound">Soundtrack</a><a href="#top">Top</a>
</nav>
<span class="foot__copy">© 1986 Nullforge Interactive · Illustrative demo</span>
</div>
</footer>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>Retro Arcade / Neon Landing
A high-energy 80s arcade landing for the fictional studio Nullforge Interactive and its flagship racer Neon Drift. The hero pairs a flickering neon title with a perspective “Tron” grid floor that scrolls endlessly toward a pixel-masked synthwave sun, all behind a CRT scanline and vignette overlay for that cabinet-glass feel. Twin neon CTAs — a spinning INSERT COIN and a cyan PLAY NOW — anchor a row of animated stat counters.
Below the fold, a paused-on-hover high-score ticker loops the leaderboard, and an arcade lineup carousel presents six game cabinets with glowing screens, hype bars that fill on load, and keyboard arrow navigation plus dot pagination. A synthwave soundtrack teaser drives a live CSS bar visualizer that ramps up when you hit preview and cycles through track titles. A blinking INSERT COIN TO CONTINUE neon footer closes the page.
Everything is vanilla HTML, CSS, and JavaScript — no frameworks or build step. Interactions include the title flicker, scrolling grid, ticker, carousel, audio-style visualizer, animated counters, and a reusable toast() helper. The design respects prefers-reduced-motion, uses :focus-visible rings, and reflows cleanly from widescreen down to 360px.
Illustrative UI only — fictional games, studios, characters, and data. Not engine integrations.