Music — Music Festival Landing
A loud, poster-styled music festival landing built with vanilla HTML, CSS and JavaScript. A sunset-gradient hero stacks an Anton lineup-poster title over dates, location and a live countdown to gates, backed by a glowing CSS sun and grain. Below it sit a tiered headliner poster sized by billing, a day-tabbed stages schedule, a GA / VIP / Camping ticket band with live selection, a seamless scrolling artist marquee, an accordion FAQ and a sticky tickets bar.
MCP
الكود
:root{
--bg:#0c0608;
--bg-2:#140a0e;
--surface:#1a0f14;
--surface-2:#241419;
--text:#ffffff;
--muted:#d9c2c8;
--line:rgba(255,255,255,0.10);
--line-2:rgba(255,255,255,0.20);
--accent:#ffd23f; /* gold */
--sun-1:#ff5e3a;
--sun-2:#ff2d95;
--sun-3:#7b2ff7;
--r-sm:8px; --r-md:14px; --r-lg:20px; --r-full:999px;
--shadow:0 18px 50px rgba(0,0,0,.55);
--poster:linear-gradient(135deg,#ff5e3a,#ff2d95 52%,#7b2ff7);
}
*,*::before,*::after{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;
}
a{color:inherit;text-decoration:none}
img{max-width:100%}
.display{font-family:"Anton","Inter",sans-serif;font-weight:400;letter-spacing:.01em}
/* ===== buttons ===== */
.btn{
display:inline-flex;align-items:center;justify-content:center;gap:.5rem;
font-weight:800;font-size:.95rem;letter-spacing:.01em;
padding:.7rem 1.25rem;border-radius:var(--r-full);
background:var(--accent);color:#1a0a02;border:2px solid var(--accent);
cursor:pointer;transition:transform .12s ease,box-shadow .18s ease,background .15s ease;
box-shadow:0 6px 22px rgba(255,210,63,.28);
}
.btn:hover{transform:translateY(-2px);box-shadow:0 12px 30px rgba(255,210,63,.42)}
.btn:active{transform:translateY(0)}
.btn:focus-visible{outline:3px solid #fff;outline-offset:2px}
.btn-lg{padding:.95rem 1.9rem;font-size:1.05rem;text-transform:uppercase}
.btn-nav{padding:.55rem 1.1rem;font-size:.85rem}
.btn-ghost{background:transparent;color:#fff;border-color:var(--line-2);box-shadow:none}
.btn-ghost:hover{background:rgba(255,255,255,.08);border-color:#fff;box-shadow:none}
/* ===== nav ===== */
.nav{
position:sticky;top:0;z-index:40;
display:flex;align-items:center;gap:1.5rem;
padding:.85rem clamp(1rem,4vw,3rem);
background:rgba(12,6,8,.72);backdrop-filter:blur(14px);
border-bottom:1px solid var(--line);
}
.brand{
font-family:"Anton",sans-serif;font-size:1.55rem;letter-spacing:.04em;
display:inline-flex;align-items:center;gap:.55rem;
}
.brand-year{color:var(--accent)}
.brand-mark{
width:18px;height:18px;border-radius:50%;
background:radial-gradient(circle at 30% 30%,#ffe9a3,var(--accent) 45%,var(--sun-1));
box-shadow:0 0 16px rgba(255,210,63,.7);
}
.nav-links{margin-left:auto;display:flex;gap:1.4rem;font-weight:600;font-size:.9rem;color:var(--muted)}
.nav-links a:hover{color:#fff}
.btn-nav{margin-left:.25rem}
/* ===== hero ===== */
.hero{position:relative;overflow:hidden;padding:clamp(3rem,9vw,7rem) clamp(1rem,5vw,3rem) clamp(2.5rem,6vw,5rem);text-align:center}
.hero-sky{position:absolute;inset:0;z-index:0;
background:
radial-gradient(120% 80% at 50% 120%,var(--sun-1) 0%,var(--sun-2) 32%,var(--sun-3) 60%,#1a0a16 82%,var(--bg) 100%);
}
.hero-sky .sun{
position:absolute;left:50%;bottom:-14%;transform:translateX(-50%);
width:min(60vw,420px);aspect-ratio:1;border-radius:50%;
background:radial-gradient(circle,#ffe9a3 0%,var(--accent) 38%,rgba(255,210,63,0) 70%);
filter:blur(2px);animation:pulse 5s ease-in-out infinite;
}
@keyframes pulse{0%,100%{opacity:.85;transform:translateX(-50%) scale(1)}50%{opacity:1;transform:translateX(-50%) scale(1.05)}}
.hero-sky .grain{position:absolute;inset:0;opacity:.18;mix-blend-mode:overlay;
background-image:repeating-linear-gradient(0deg,transparent,transparent 2px,rgba(0,0,0,.5) 3px);}
.hero-inner{position:relative;z-index:1;max-width:920px;margin:0 auto}
.hero-kicker{font-weight:700;letter-spacing:.22em;text-transform:uppercase;font-size:.82rem;color:var(--accent)}
.hero-title{
font-family:"Anton",sans-serif;margin:.4rem 0 .6rem;
display:flex;flex-direction:column;line-height:.86;
font-size:clamp(3.5rem,17vw,11rem);letter-spacing:.005em;
text-shadow:0 6px 0 rgba(0,0,0,.25),0 16px 40px rgba(0,0,0,.5);
}
.hero-title span:nth-child(2){color:var(--accent)}
.hero-sub{max-width:620px;margin:.4rem auto 0;color:var(--muted);font-size:clamp(1rem,2.4vw,1.2rem);font-weight:500}
/* countdown */
.countdown{display:flex;align-items:center;justify-content:center;gap:.5rem;margin:2rem auto 0;flex-wrap:wrap}
.cd-unit{
display:flex;flex-direction:column;align-items:center;gap:.2rem;
background:rgba(0,0,0,.32);border:1px solid var(--line-2);
border-radius:var(--r-md);padding:.7rem 1rem;min-width:78px;backdrop-filter:blur(6px);
}
.cd-num{font-family:"Anton",sans-serif;font-size:2.2rem;line-height:1;color:#fff;font-variant-numeric:tabular-nums}
.cd-lbl{font-size:.68rem;letter-spacing:.18em;text-transform:uppercase;color:var(--muted);font-weight:700}
.cd-sep{font-family:"Anton",sans-serif;font-size:1.8rem;color:var(--accent);opacity:.7}
.hero-cta{display:flex;gap:1rem;justify-content:center;flex-wrap:wrap;margin-top:2rem}
/* ===== marquee ===== */
.marquee{overflow:hidden;border-top:2px solid var(--accent);border-bottom:2px solid var(--accent);
background:linear-gradient(90deg,var(--sun-1),var(--sun-2),var(--sun-3));padding:.7rem 0}
.marquee-track{display:inline-flex;align-items:center;gap:1.4rem;white-space:nowrap;will-change:transform;
font-family:"Anton",sans-serif;font-size:1.4rem;letter-spacing:.05em;color:#0c0608}
.marquee-track .dot{color:var(--accent);text-shadow:0 0 1px #000}
/* ===== shared section ===== */
.section-head{font-family:"Anton",sans-serif;font-size:clamp(2rem,6vw,3.4rem);text-align:center;line-height:1;margin:0 0 2rem}
.eyebrow{display:block;font-family:"Inter",sans-serif;font-weight:800;font-size:.8rem;letter-spacing:.24em;text-transform:uppercase;color:var(--accent);margin-bottom:.5rem}
.lineup,.schedule,.tickets,.faq{padding:clamp(3rem,7vw,5.5rem) clamp(1rem,5vw,3rem);max-width:1100px;margin:0 auto}
/* ===== lineup poster ===== */
.poster{
background:var(--poster);
border:3px solid var(--accent);border-radius:var(--r-lg);
padding:clamp(2rem,5vw,3.5rem) 1.5rem;text-align:center;box-shadow:var(--shadow);
}
.tier{display:flex;flex-wrap:wrap;justify-content:center;gap:.4rem 1.4rem;line-height:1;margin-bottom:1.1rem}
.tier:last-child{margin-bottom:0}
.act{font-family:"Anton",sans-serif;text-transform:uppercase;color:#fff;transition:color .15s,transform .15s;text-shadow:0 2px 8px rgba(0,0,0,.35)}
.act:hover{color:var(--accent);transform:scale(1.04)}
.tier-1 .act{font-size:clamp(2rem,8vw,4rem)}
.tier-2 .act{font-size:clamp(1.4rem,5vw,2.4rem)}
.tier-3 .act{font-size:clamp(1rem,3vw,1.5rem);opacity:.96}
.tier-4 .act{font-size:clamp(.78rem,2.2vw,1rem);opacity:.88;font-family:"Inter",sans-serif;font-weight:800;letter-spacing:.02em}
/* ===== schedule ===== */
.day-tabs{display:flex;gap:.5rem;justify-content:center;flex-wrap:wrap;margin-bottom:1.8rem}
.day-tab{
font-family:"Inter",sans-serif;font-weight:800;font-size:.92rem;
padding:.6rem 1.2rem;border-radius:var(--r-full);cursor:pointer;
background:var(--surface);color:var(--muted);border:1px solid var(--line-2);
transition:all .15s;
}
.day-tab:hover{color:#fff;border-color:var(--accent)}
.day-tab.is-active{background:var(--accent);color:#1a0a02;border-color:var(--accent)}
.day-tab:focus-visible{outline:3px solid #fff;outline-offset:2px}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:1rem}
.stage-card{
background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
padding:1.1rem 1.2rem;animation:fade .35s ease;
}
@keyframes fade{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
.stage-name{font-family:"Anton",sans-serif;font-size:1.2rem;color:var(--accent);letter-spacing:.03em;margin-bottom:.6rem;display:flex;align-items:center;gap:.5rem}
.stage-dot{width:10px;height:10px;border-radius:50%;background:var(--sun-2);box-shadow:0 0 8px var(--sun-2)}
.set-row{display:flex;justify-content:space-between;gap:1rem;padding:.5rem 0;border-top:1px dashed var(--line);font-size:.92rem}
.set-row:first-of-type{border-top:none}
.set-time{color:var(--muted);font-variant-numeric:tabular-nums;font-weight:600;white-space:nowrap}
.set-act{font-weight:700}
.set-row.is-headliner .set-act{color:var(--accent)}
/* ===== tickets ===== */
.tier-band{display:grid;grid-template-columns:repeat(3,1fr);gap:1.2rem;align-items:stretch}
.ticket{
position:relative;text-align:left;cursor:pointer;font-family:inherit;color:var(--text);
background:var(--surface);border:2px solid var(--line-2);border-radius:var(--r-lg);
padding:1.6rem 1.4rem;display:flex;flex-direction:column;gap:.5rem;
transition:transform .15s,border-color .15s,box-shadow .2s;
}
.ticket:hover{transform:translateY(-4px);border-color:var(--accent)}
.ticket:focus-visible{outline:3px solid #fff;outline-offset:2px}
.ticket[aria-checked="true"]{border-color:var(--accent);box-shadow:0 0 0 3px rgba(255,210,63,.25),var(--shadow)}
.ticket.is-featured{background:linear-gradient(180deg,rgba(255,45,149,.16),var(--surface))}
.t-flag{position:absolute;top:-12px;left:1.4rem;background:var(--accent);color:#1a0a02;font-size:.7rem;font-weight:800;letter-spacing:.1em;text-transform:uppercase;padding:.25rem .7rem;border-radius:var(--r-full)}
.t-name{font-family:"Anton",sans-serif;font-size:1.5rem;letter-spacing:.02em}
.t-price{color:var(--muted);font-size:.95rem}
.t-price b{color:#fff;font-size:1.7rem;font-family:"Anton",sans-serif;letter-spacing:.02em}
.t-list{list-style:none;margin:.4rem 0 0;padding:0;display:flex;flex-direction:column;gap:.4rem;flex:1}
.t-list li{position:relative;padding-left:1.4rem;font-size:.9rem;color:var(--muted)}
.t-list li::before{content:"✦";position:absolute;left:0;color:var(--accent)}
.t-pick{margin-top:.8rem;text-align:center;font-weight:800;text-transform:uppercase;font-size:.82rem;letter-spacing:.08em;
border:2px solid var(--line-2);border-radius:var(--r-full);padding:.55rem;transition:all .15s}
.ticket[aria-checked="true"] .t-pick{background:var(--accent);color:#1a0a02;border-color:var(--accent)}
.tickets-foot{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:1rem;margin-top:1.6rem;
background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-md);padding:1.1rem 1.4rem}
.tickets-foot p{margin:0;font-size:1rem}
.tickets-foot b{color:var(--accent)}
/* ===== faq ===== */
.faq-list{display:flex;flex-direction:column;gap:.75rem;max-width:760px;margin:0 auto}
.faq-item{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);overflow:hidden}
.faq-q{width:100%;text-align:left;font-family:inherit;font-weight:700;font-size:1.02rem;color:#fff;
background:none;border:none;cursor:pointer;padding:1.1rem 1.3rem;display:flex;justify-content:space-between;align-items:center;gap:1rem}
.faq-q::after{content:"+";font-family:"Anton",sans-serif;font-size:1.5rem;color:var(--accent);transition:transform .2s}
.faq-q[aria-expanded="true"]::after{transform:rotate(45deg)}
.faq-q:focus-visible{outline:3px solid var(--accent);outline-offset:-3px}
.faq-a{max-height:0;overflow:hidden;transition:max-height .28s ease}
.faq-a p{margin:0;padding:0 1.3rem 1.1rem;color:var(--muted);font-size:.95rem}
/* ===== footer ===== */
.footer{border-top:2px solid var(--accent);background:var(--bg-2);padding:2.5rem clamp(1rem,5vw,3rem) 6rem;margin-top:2rem}
.foot-top{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:1rem;max-width:1100px;margin:0 auto}
.brand-foot{font-size:1.3rem}
.foot-links{display:flex;gap:1.3rem;flex-wrap:wrap;font-weight:600;color:var(--muted);font-size:.9rem}
.foot-links a:hover{color:var(--accent)}
.foot-fine{max-width:1100px;margin:1.4rem auto 0;color:var(--muted);font-size:.82rem;opacity:.8}
/* ===== sticky bar ===== */
.sticky-bar{
position:fixed;left:0;right:0;bottom:0;z-index:50;
display:flex;align-items:center;justify-content:space-between;gap:1rem;
padding:.8rem clamp(1rem,5vw,3rem);
background:linear-gradient(90deg,var(--sun-1),var(--sun-2),var(--sun-3));
border-top:2px solid var(--accent);
transform:translateY(110%);transition:transform .3s ease;
}
.sticky-bar.is-visible{transform:translateY(0)}
.sb-info{display:flex;flex-direction:column;color:#fff;line-height:1.2}
.sb-info strong{font-family:"Anton",sans-serif;font-size:1.1rem;letter-spacing:.03em}
.sb-info span{font-size:.82rem;opacity:.92}
/* ===== toast ===== */
.toast{
position:fixed;left:50%;bottom:84px;transform:translateX(-50%) translateY(20px);
background:#1a0a02;color:#fff;font-weight:600;font-size:.9rem;
padding:.7rem 1.2rem;border-radius:var(--r-full);border:1px solid var(--accent);
box-shadow:var(--shadow);opacity:0;pointer-events:none;transition:opacity .25s,transform .25s;z-index:60;
}
.toast.is-visible{opacity:1;transform:translateX(-50%) translateY(0)}
/* ===== responsive ===== */
@media (max-width:760px){
.tier-band{grid-template-columns:1fr}
}
@media (max-width:520px){
.nav-links{display:none}
.nav{gap:.75rem}
.cd-unit{min-width:62px;padding:.55rem .7rem}
.cd-num{font-size:1.7rem}
.hero-cta{flex-direction:column;align-items:stretch}
.hero-cta .btn{width:100%}
.section-head{margin-bottom:1.4rem}
.tickets-foot{flex-direction:column;align-items:stretch;text-align:center}
.tickets-foot .btn{width:100%}
.toast{bottom:96px}
}
@media (prefers-reduced-motion:reduce){
*{animation-duration:.001ms!important;scroll-behavior:auto}
}(function () {
"use strict";
/* ---------- toast helper ---------- */
var toastEl = document.getElementById("toast");
var toastTimer;
function toast(msg) {
if (!toastEl) return;
toastEl.textContent = msg;
toastEl.classList.add("is-visible");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("is-visible");
}, 2200);
}
/* ---------- live countdown ---------- */
// Gates open Aug 14, 2026 12:00 (local).
var target = new Date(2026, 7, 14, 12, 0, 0).getTime();
var elDays = document.getElementById("cd-days");
var elHours = document.getElementById("cd-hours");
var elMins = document.getElementById("cd-mins");
var elSecs = document.getElementById("cd-secs");
function pad(n) { return n < 10 ? "0" + n : "" + n; }
function tick() {
var diff = target - Date.now();
if (diff <= 0) {
elDays.textContent = elHours.textContent = elMins.textContent = elSecs.textContent = "00";
var cd = document.getElementById("countdown");
if (cd) cd.setAttribute("aria-label", "The festival is live");
return;
}
var s = Math.floor(diff / 1000);
elDays.textContent = pad(Math.floor(s / 86400));
elHours.textContent = pad(Math.floor((s % 86400) / 3600));
elMins.textContent = pad(Math.floor((s % 3600) / 60));
elSecs.textContent = pad(s % 60);
}
tick();
setInterval(tick, 1000);
/* ---------- artist marquee (seamless scroll) ---------- */
var marquee = document.getElementById("marquee");
if (marquee) {
marquee.innerHTML += marquee.innerHTML; // duplicate for seamless loop
var mx = 0;
var half = marquee.scrollWidth / 2;
var paused = false;
marquee.parentElement.addEventListener("mouseenter", function () { paused = true; });
marquee.parentElement.addEventListener("mouseleave", function () { paused = false; });
function loop() {
if (!paused) {
mx -= 0.6;
if (Math.abs(mx) >= half) mx = 0;
marquee.style.transform = "translateX(" + mx + "px)";
}
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
}
/* ---------- schedule data + day tabs ---------- */
var SCHEDULE = {
fri: [
{ stage: "Solaris Main", sets: [
{ t: "9:30 PM", a: "Neon Tides", head: true },
{ t: "7:45 PM", a: "Golden Hour" },
{ t: "6:00 PM", a: "Coral Signal" },
{ t: "4:30 PM", a: "Marigold" }
]},
{ stage: "Dune Stage", sets: [
{ t: "10:00 PM", a: "Dusk Machine", head: true },
{ t: "8:15 PM", a: "Hollow Suns" },
{ t: "6:30 PM", a: "Driftwood" }
]},
{ stage: "Neon Tent", sets: [
{ t: "11:00 PM", a: "Cobalt Hum", head: true },
{ t: "9:00 PM", a: "Static Bloom" },
{ t: "7:00 PM", a: "Wireframe" }
]}
],
sat: [
{ stage: "Solaris Main", sets: [
{ t: "9:45 PM", a: "Velvet Static", head: true },
{ t: "8:00 PM", a: "Paper Lanterns" },
{ t: "6:15 PM", a: "Ember Riot" },
{ t: "4:45 PM", a: "Sun Cult" }
]},
{ stage: "Dune Stage", sets: [
{ t: "10:15 PM", a: "Tidal Glass", head: true },
{ t: "8:30 PM", a: "Pale Horizon" },
{ t: "6:45 PM", a: "Nightjar" }
]},
{ stage: "Neon Tent", sets: [
{ t: "11:30 PM", a: "Echo Parade", head: true },
{ t: "9:30 PM", a: "Saltwater Choir" },
{ t: "7:30 PM", a: "The Low Frequencies" }
]}
],
sun: [
{ stage: "Solaris Main", sets: [
{ t: "9:15 PM", a: "Midnight Reservoir", head: true },
{ t: "7:30 PM", a: "Saltwater Choir" },
{ t: "5:45 PM", a: "Static Bloom" },
{ t: "4:15 PM", a: "Marigold" }
]},
{ stage: "Dune Stage", sets: [
{ t: "9:45 PM", a: "Golden Hour", head: true },
{ t: "8:00 PM", a: "Ember Riot" },
{ t: "6:15 PM", a: "Driftwood" }
]},
{ stage: "Neon Tent", sets: [
{ t: "10:30 PM", a: "Sun Cult", head: true },
{ t: "8:45 PM", a: "Wireframe" },
{ t: "7:00 PM", a: "Nightjar" }
]}
]
};
var grid = document.getElementById("schedule-grid");
function renderDay(day) {
if (!grid) return;
var data = SCHEDULE[day] || [];
grid.innerHTML = data.map(function (col) {
var rows = col.sets.map(function (s) {
return '<div class="set-row' + (s.head ? " is-headliner" : "") + '">' +
'<span class="set-act">' + s.a + (s.head ? " ★" : "") + "</span>" +
'<span class="set-time">' + s.t + "</span></div>";
}).join("");
return '<div class="stage-card"><div class="stage-name"><span class="stage-dot"></span>' +
col.stage + "</div>" + rows + "</div>";
}).join("");
}
renderDay("fri");
var dayTabs = document.querySelectorAll(".day-tab");
dayTabs.forEach(function (tab) {
tab.addEventListener("click", function () {
dayTabs.forEach(function (t) {
t.classList.remove("is-active");
t.setAttribute("aria-selected", "false");
});
tab.classList.add("is-active");
tab.setAttribute("aria-selected", "true");
renderDay(tab.dataset.day);
});
});
/* ---------- ticket tier select ---------- */
var tickets = document.querySelectorAll(".ticket");
var selTier = document.getElementById("sel-tier");
var selPrice = document.getElementById("sel-price");
function selectTicket(btn) {
tickets.forEach(function (t) { t.setAttribute("aria-checked", "false"); });
btn.setAttribute("aria-checked", "true");
if (selTier) selTier.textContent = btn.querySelector(".t-name").textContent;
if (selPrice) selPrice.textContent = "$" + btn.dataset.price;
}
tickets.forEach(function (btn) {
btn.addEventListener("click", function () {
selectTicket(btn);
toast(btn.querySelector(".t-name").textContent + " pass selected");
});
});
var checkout = document.getElementById("checkout");
if (checkout) {
checkout.addEventListener("click", function () {
var name = selTier ? selTier.textContent : "your";
var price = selPrice ? selPrice.textContent : "";
toast("Heading to checkout — " + name + " " + price + " (demo)");
});
}
/* ---------- FAQ accordion ---------- */
document.querySelectorAll(".faq-q").forEach(function (q) {
q.addEventListener("click", function () {
var open = q.getAttribute("aria-expanded") === "true";
var ans = q.nextElementSibling;
q.setAttribute("aria-expanded", open ? "false" : "true");
ans.style.maxHeight = open ? "0" : ans.scrollHeight + "px";
});
});
/* ---------- lineup act -> toast ---------- */
document.querySelectorAll(".act").forEach(function (a) {
a.addEventListener("click", function (e) {
e.preventDefault();
toast("Set times for " + a.textContent.trim() + " — see the schedule");
});
});
/* ---------- sticky tickets bar ---------- */
var bar = document.getElementById("sticky-bar");
var hero = document.querySelector(".hero");
var ticketsSection = document.getElementById("tickets");
function updateBar() {
if (!bar || !hero) return;
var pastHero = window.scrollY > hero.offsetHeight - 80;
var inTickets = false;
if (ticketsSection) {
var r = ticketsSection.getBoundingClientRect();
inTickets = r.top < window.innerHeight && r.bottom > 0;
}
if (pastHero && !inTickets) bar.classList.add("is-visible");
else bar.classList.remove("is-visible");
}
window.addEventListener("scroll", updateBar, { passive: true });
window.addEventListener("resize", updateBar);
updateBar();
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>SOLARIS — Music Festival</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=Anton&family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<!-- ====== TOP NAV ====== -->
<header class="nav" id="top">
<a class="brand" href="#top">
<span class="brand-mark" aria-hidden="true"></span>
SOLARIS<span class="brand-year">'26</span>
</a>
<nav class="nav-links" aria-label="Primary">
<a href="#lineup">Lineup</a>
<a href="#schedule">Schedule</a>
<a href="#tickets">Tickets</a>
<a href="#faq">FAQ</a>
</nav>
<a href="#tickets" class="btn btn-nav">Get tickets</a>
</header>
<!-- ====== HERO ====== -->
<section class="hero">
<div class="hero-sky" aria-hidden="true">
<span class="sun"></span>
<span class="grain"></span>
</div>
<div class="hero-inner">
<p class="hero-kicker">Aug 14–16, 2026 · Mirage Valley, Nevada</p>
<h1 class="hero-title">
<span>SOLARIS</span>
<span>SOUND</span>
<span>FEST</span>
</h1>
<p class="hero-sub">Three days. Five stages. One endless sunset. Forty-plus artists across desert dunes and neon nights.</p>
<div class="countdown" id="countdown" aria-live="polite" aria-label="Time until gates open">
<div class="cd-unit"><span class="cd-num" id="cd-days">00</span><span class="cd-lbl">Days</span></div>
<div class="cd-sep">:</div>
<div class="cd-unit"><span class="cd-num" id="cd-hours">00</span><span class="cd-lbl">Hrs</span></div>
<div class="cd-sep">:</div>
<div class="cd-unit"><span class="cd-num" id="cd-mins">00</span><span class="cd-lbl">Min</span></div>
<div class="cd-sep">:</div>
<div class="cd-unit"><span class="cd-num" id="cd-secs">00</span><span class="cd-lbl">Sec</span></div>
</div>
<div class="hero-cta">
<a href="#tickets" class="btn btn-lg">Get tickets</a>
<a href="#lineup" class="btn btn-ghost btn-lg">See the lineup</a>
</div>
</div>
</section>
<!-- ====== ARTIST MARQUEE ====== -->
<section class="marquee" aria-label="Featured artists">
<div class="marquee-track" id="marquee">
<span>NEON TIDES</span><span class="dot">✦</span>
<span>VELVET STATIC</span><span class="dot">✦</span>
<span>MIDNIGHT RESERVOIR</span><span class="dot">✦</span>
<span>PAPER LANTERNS</span><span class="dot">✦</span>
<span>DUSK MACHINE</span><span class="dot">✦</span>
<span>GOLDEN HOUR</span><span class="dot">✦</span>
<span>CORAL SIGNAL</span><span class="dot">✦</span>
<span>HOLLOW SUNS</span><span class="dot">✦</span>
</div>
</section>
<!-- ====== LINEUP POSTER ====== -->
<section class="lineup" id="lineup">
<h2 class="section-head"><span class="eyebrow">The Lineup</span>2026 Artists</h2>
<div class="poster">
<div class="tier tier-1">
<a href="#" class="act">Neon Tides</a>
<a href="#" class="act">Velvet Static</a>
<a href="#" class="act">Midnight Reservoir</a>
</div>
<div class="tier tier-2">
<a href="#" class="act">Paper Lanterns</a>
<a href="#" class="act">Dusk Machine</a>
<a href="#" class="act">Golden Hour</a>
<a href="#" class="act">Coral Signal</a>
</div>
<div class="tier tier-3">
<a href="#" class="act">Hollow Suns</a>
<a href="#" class="act">Ember Riot</a>
<a href="#" class="act">Saltwater Choir</a>
<a href="#" class="act">The Low Frequencies</a>
<a href="#" class="act">Marigold</a>
<a href="#" class="act">Static Bloom</a>
</div>
<div class="tier tier-4">
<a href="#" class="act">Wireframe</a>
<a href="#" class="act">Pale Horizon</a>
<a href="#" class="act">Cobalt Hum</a>
<a href="#" class="act">Nightjar</a>
<a href="#" class="act">Echo Parade</a>
<a href="#" class="act">Tidal Glass</a>
<a href="#" class="act">Sun Cult</a>
<a href="#" class="act">Driftwood</a>
</div>
</div>
</section>
<!-- ====== SCHEDULE ====== -->
<section class="schedule" id="schedule">
<h2 class="section-head"><span class="eyebrow">Set Times</span>Stages & Schedule</h2>
<div class="day-tabs" role="tablist" aria-label="Festival days">
<button class="day-tab is-active" role="tab" aria-selected="true" data-day="fri">Fri · Aug 14</button>
<button class="day-tab" role="tab" aria-selected="false" data-day="sat">Sat · Aug 15</button>
<button class="day-tab" role="tab" aria-selected="false" data-day="sun">Sun · Aug 16</button>
</div>
<div class="grid" id="schedule-grid" role="tabpanel" aria-live="polite"></div>
</section>
<!-- ====== TICKETS ====== -->
<section class="tickets" id="tickets">
<h2 class="section-head"><span class="eyebrow">Passes</span>Pick Your Pass</h2>
<div class="tier-band" role="radiogroup" aria-label="Ticket tiers">
<button class="ticket" data-tier="ga" data-price="289" role="radio" aria-checked="false">
<span class="t-name">General Admission</span>
<span class="t-price"><b>$289</b> / 3-day</span>
<ul class="t-list">
<li>All-stage access</li>
<li>In/out re-entry</li>
<li>Festival app + map</li>
</ul>
<span class="t-pick">Select</span>
</button>
<button class="ticket is-featured" data-tier="vip" data-price="649" role="radio" aria-checked="true">
<span class="t-flag">Most popular</span>
<span class="t-name">VIP</span>
<span class="t-price"><b>$649</b> / 3-day</span>
<ul class="t-list">
<li>Front-of-stage VIP pits</li>
<li>Shaded lounge + fast lanes</li>
<li>Premium restrooms & bars</li>
<li>Exclusive set viewing decks</li>
</ul>
<span class="t-pick">Select</span>
</button>
<button class="ticket" data-tier="camp" data-price="429" role="radio" aria-checked="false">
<span class="t-name">Camping</span>
<span class="t-price"><b>$429</b> / 3-day</span>
<ul class="t-list">
<li>GA pass included</li>
<li>On-site tent plot</li>
<li>Showers + charging tents</li>
</ul>
<span class="t-pick">Select</span>
</button>
</div>
<div class="tickets-foot">
<p>Selected: <b id="sel-tier">VIP</b> — <b id="sel-price">$649</b> per person</p>
<button class="btn btn-lg" id="checkout">Checkout</button>
</div>
</section>
<!-- ====== FAQ ====== -->
<section class="faq" id="faq">
<h2 class="section-head"><span class="eyebrow">Good to know</span>FAQ</h2>
<div class="faq-list" id="faq-list">
<div class="faq-item">
<button class="faq-q" aria-expanded="false">What time do gates open?</button>
<div class="faq-a"><p>Gates open at 12:00 PM each day. Music runs until 2:00 AM Friday and Saturday, and midnight on Sunday.</p></div>
</div>
<div class="faq-item">
<button class="faq-q" aria-expanded="false">Is there in-and-out re-entry?</button>
<div class="faq-a"><p>Yes — all 3-day passes include same-day re-entry. Camping pass holders may move freely between the grounds and the campsite at any time.</p></div>
</div>
<div class="faq-item">
<button class="faq-q" aria-expanded="false">What can I bring?</button>
<div class="faq-a"><p>Empty reusable water bottles, sealed sunscreen, small bags, and a good attitude. No glass, no professional cameras, no outside alcohol.</p></div>
</div>
<div class="faq-item">
<button class="faq-q" aria-expanded="false">Are tickets refundable?</button>
<div class="faq-a"><p>Passes are non-refundable but fully transferable up to 48 hours before gates. Add-on insurance is available at checkout.</p></div>
</div>
</div>
</section>
<!-- ====== FOOTER ====== -->
<footer class="footer">
<div class="foot-top">
<span class="brand brand-foot"><span class="brand-mark" aria-hidden="true"></span>SOLARIS'26</span>
<nav class="foot-links" aria-label="Footer">
<a href="#lineup">Lineup</a>
<a href="#schedule">Schedule</a>
<a href="#tickets">Tickets</a>
<a href="#faq">FAQ</a>
<a href="#top">Back to top</a>
</nav>
</div>
<p class="foot-fine">Mirage Valley, Nevada · Aug 14–16, 2026 · A fictional festival. Illustrative UI only.</p>
</footer>
<!-- ====== STICKY TICKETS BAR ====== -->
<div class="sticky-bar" id="sticky-bar">
<div class="sb-info">
<strong>SOLARIS '26</strong>
<span>Aug 14–16 · from $289</span>
</div>
<a href="#tickets" class="btn">Get tickets</a>
</div>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>Music Festival Landing
A hype, gig-poster marketing page for a fictional desert festival called Solaris Sound Fest. The hero paints a sunset sky in CSS — an orange-to-magenta-to-violet gradient over near-black with a pulsing gold sun and film grain — then stacks a huge Anton lineup-poster title above the dates, location and a live, ticking countdown to the moment gates open. Twin CTAs jump to tickets and the lineup, and a gold-and-sunset artist marquee scrolls seamlessly beneath, pausing on hover.
The lineup is rendered as a true festival poster: four billing tiers whose font sizes shrink with the billing, from headliners down to a dense undercard row, each act tappable. The schedule offers Fri / Sat / Sun day tabs that swap a grid of per-stage set-time cards, with headliners starred and accent-colored. A GA / VIP / Camping ticket band behaves like a radio group — selecting a tier updates the running summary and price, and checkout fires an accessible toast. An accordion FAQ, a poster-style footer and a sticky “Tickets” bar that appears once you scroll past the hero round it out.
Everything is self-contained vanilla HTML, CSS and JavaScript with no frameworks or build step. The palette is a sunset gradient over black with a gold accent and loud Anton display type paired with Inter body text, tuned for an energetic, poster-like feel. The layout reflows cleanly down to roughly 360px and respects reduced-motion preferences.
Illustrative UI only — fictional artists, albums, tracks, and data. No real audio playback.