Shop — Sale / Deals Landing
A high-energy sale and deals landing page for a fictional tech store, built with plain HTML, CSS, and vanilla JavaScript. It pairs a bold dark hero and a live sale countdown with deal-category tiles, a horizontal doorbusters rail, and a responsive grid of discount cards showing percent-off, original and sale prices, star ratings, and stock chips. Interactions include a sort-by-discount toggle, copy-coupon button, and add-to-cart toasts that update a cart badge.
MCP
Code
:root {
--bg: #ffffff;
--surface: #f7f8fb;
--ink: #16181d;
--muted: #6b7280;
--brand: #3457ff;
--brand-d: #2742d6;
--sale: #e0245e;
--sale-d: #c01448;
--ok: #1f9d55;
--line: rgba(16, 18, 29, .1);
--line-2: rgba(16, 18, 29, .06);
--ink-900: #0c0d12;
--shadow-sm: 0 1px 2px rgba(16, 18, 29, .06), 0 1px 3px rgba(16, 18, 29, .08);
--shadow-md: 0 6px 16px rgba(16, 18, 29, .1);
--shadow-lg: 0 18px 48px rgba(16, 18, 29, .16);
--radius: 16px;
--radius-sm: 10px;
--maxw: 1180px;
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
margin: 0;
font-family: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
background: var(--bg);
color: var(--ink);
line-height: 1.5;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
@media (prefers-reduced-motion: reduce) {
html { scroll-behavior: auto; }
* { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}
a { color: inherit; text-decoration: none; }
:focus-visible {
outline: 3px solid var(--brand);
outline-offset: 2px;
border-radius: 6px;
}
img, svg { display: block; }
/* ---------- Coupon strip ---------- */
.coupon-strip {
background: linear-gradient(90deg, var(--sale), #ff6a3d);
color: #fff;
text-align: center;
font-size: .9rem;
padding: 9px 16px;
}
.coupon-strip p { margin: 0; }
.coupon-spark { margin-right: 4px; }
.coupon-code {
display: inline-flex;
align-items: center;
gap: 6px;
margin: 0 2px;
padding: 2px 8px 2px 10px;
border: 1.5px dashed rgba(255, 255, 255, .7);
border-radius: 999px;
background: rgba(255, 255, 255, .14);
color: #fff;
font: inherit;
font-weight: 800;
letter-spacing: .04em;
cursor: pointer;
transition: background .15s ease, transform .12s ease;
}
.coupon-code:hover { background: rgba(255, 255, 255, .26); }
.coupon-code:active { transform: scale(.96); }
.coupon-code__hint {
font-size: .68rem;
font-weight: 700;
letter-spacing: .06em;
text-transform: uppercase;
padding: 1px 6px;
border-radius: 999px;
background: rgba(0, 0, 0, .2);
}
.coupon-code.is-copied .coupon-code__hint { background: var(--ok); }
/* ---------- Header ---------- */
.site-header {
position: sticky;
top: 0;
z-index: 40;
display: flex;
align-items: center;
gap: 18px;
padding: 14px clamp(16px, 4vw, 40px);
background: rgba(255, 255, 255, .9);
backdrop-filter: saturate(1.4) blur(10px);
border-bottom: 1px solid var(--line);
}
.brand {
display: inline-flex;
align-items: center;
gap: 8px;
font-weight: 900;
font-size: 1.3rem;
letter-spacing: -.02em;
}
.brand__mark {
display: grid;
place-items: center;
width: 30px;
height: 30px;
border-radius: 9px;
background: linear-gradient(135deg, var(--brand), #7a5cff);
color: #fff;
font-size: .8rem;
}
.site-nav {
display: flex;
gap: 22px;
margin-left: auto;
font-weight: 600;
font-size: .94rem;
color: var(--muted);
}
.site-nav a { transition: color .15s ease; }
.site-nav a:hover { color: var(--ink); }
.cart-btn {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
width: 44px;
height: 44px;
border: 1px solid var(--line);
border-radius: 12px;
background: #fff;
color: var(--ink);
cursor: pointer;
transition: border-color .15s ease, box-shadow .15s ease, transform .12s ease;
}
.cart-btn:hover { border-color: var(--brand); box-shadow: var(--shadow-sm); }
.cart-btn:active { transform: scale(.95); }
.cart-count {
position: absolute;
top: -6px;
right: -6px;
min-width: 20px;
height: 20px;
padding: 0 5px;
border-radius: 999px;
background: var(--sale);
color: #fff;
font-size: .72rem;
font-weight: 800;
display: grid;
place-items: center;
transform: scale(0);
transition: transform .2s cubic-bezier(.34, 1.56, .64, 1);
}
.cart-count.is-on { transform: scale(1); }
/* ---------- Hero ---------- */
.hero {
position: relative;
overflow: hidden;
background:
radial-gradient(1200px 600px at 85% -20%, rgba(122, 92, 255, .18), transparent 60%),
radial-gradient(900px 500px at 10% 120%, rgba(224, 36, 94, .14), transparent 55%),
linear-gradient(180deg, #0c0d12, #14162a);
color: #fff;
}
.hero__glow {
position: absolute;
inset: 0;
background-image:
radial-gradient(circle at 1px 1px, rgba(255, 255, 255, .08) 1px, transparent 0);
background-size: 26px 26px;
mask-image: radial-gradient(700px 400px at 70% 30%, #000, transparent 75%);
pointer-events: none;
}
.hero__inner {
position: relative;
max-width: var(--maxw);
margin: 0 auto;
padding: clamp(48px, 8vw, 88px) clamp(16px, 4vw, 40px);
text-align: center;
}
.hero__eyebrow {
display: inline-block;
margin: 0 0 18px;
padding: 6px 14px;
border-radius: 999px;
background: rgba(255, 255, 255, .1);
border: 1px solid rgba(255, 255, 255, .18);
font-size: .78rem;
font-weight: 700;
letter-spacing: .08em;
text-transform: uppercase;
}
.hero__title {
margin: 0 auto 16px;
max-width: 16ch;
font-size: clamp(2.1rem, 6.5vw, 4.4rem);
font-weight: 900;
line-height: 1.05;
letter-spacing: -.03em;
}
.hero__big {
background: linear-gradient(100deg, #ff8a5c, var(--sale) 55%, #ff5e8a);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.hero__sub {
margin: 0 auto 30px;
max-width: 50ch;
color: rgba(255, 255, 255, .78);
font-size: clamp(1rem, 2.2vw, 1.18rem);
}
.hero__sub strong { color: #fff; }
/* Countdown */
.countdown {
display: inline-flex;
align-items: center;
gap: 6px;
margin: 0 auto 30px;
padding: 14px 18px;
border-radius: var(--radius);
background: rgba(255, 255, 255, .06);
border: 1px solid rgba(255, 255, 255, .16);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, .12);
}
.countdown__unit {
display: flex;
flex-direction: column;
align-items: center;
min-width: 58px;
}
.countdown__num {
font-size: clamp(1.6rem, 5vw, 2.4rem);
font-weight: 900;
font-variant-numeric: tabular-nums;
letter-spacing: -.02em;
line-height: 1;
color: #fff;
}
.countdown__label {
margin-top: 6px;
font-size: .66rem;
font-weight: 700;
letter-spacing: .12em;
text-transform: uppercase;
color: rgba(255, 255, 255, .6);
}
.countdown__sep {
font-size: 1.6rem;
font-weight: 800;
color: rgba(255, 255, 255, .4);
transform: translateY(-7px);
}
.hero__cta {
display: flex;
flex-wrap: wrap;
gap: 12px;
justify-content: center;
margin-bottom: 30px;
}
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: 13px 26px;
border-radius: 12px;
border: 1px solid transparent;
font: inherit;
font-weight: 700;
font-size: 1rem;
cursor: pointer;
transition: transform .12s ease, box-shadow .15s ease, background .15s ease, border-color .15s ease;
}
.btn:active { transform: translateY(1px) scale(.99); }
.btn--primary {
background: linear-gradient(180deg, #ff6a86, var(--sale));
color: #fff;
box-shadow: 0 10px 26px rgba(224, 36, 94, .4);
}
.btn--primary:hover { box-shadow: 0 14px 32px rgba(224, 36, 94, .55); }
.btn--ghost {
background: rgba(255, 255, 255, .08);
border-color: rgba(255, 255, 255, .26);
color: #fff;
}
.btn--ghost:hover { background: rgba(255, 255, 255, .16); }
.trust {
list-style: none;
display: flex;
flex-wrap: wrap;
justify-content: center;
gap: 10px 24px;
margin: 0;
padding: 0;
font-size: .9rem;
color: rgba(255, 255, 255, .8);
}
.trust li { display: inline-flex; align-items: center; gap: 7px; }
/* ---------- Section shells ---------- */
.section-title {
font-size: clamp(1.4rem, 3.4vw, 2rem);
font-weight: 800;
letter-spacing: -.02em;
margin: 0 0 18px;
}
.section-title--light { color: #fff; }
.fire { margin-right: 4px; }
.cats {
max-width: var(--maxw);
margin: 0 auto;
padding: clamp(40px, 6vw, 64px) clamp(16px, 4vw, 40px) 8px;
}
.cats__grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 14px;
}
.cat {
position: relative;
display: flex;
flex-direction: column;
gap: 4px;
padding: 20px 18px;
border-radius: var(--radius);
background:
linear-gradient(160deg, color-mix(in srgb, var(--c1) 14%, #fff), color-mix(in srgb, var(--c2) 8%, #fff));
border: 1px solid var(--line);
overflow: hidden;
transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.cat::after {
content: "";
position: absolute;
right: -30px;
bottom: -30px;
width: 110px;
height: 110px;
border-radius: 50%;
background: radial-gradient(circle, var(--c1), transparent 70%);
opacity: .35;
}
.cat:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-md);
border-color: color-mix(in srgb, var(--c1) 50%, transparent);
}
.cat__icon { font-size: 1.9rem; }
.cat__name { font-weight: 800; font-size: 1.05rem; }
.cat__off {
font-size: .82rem;
font-weight: 700;
color: color-mix(in srgb, var(--c1) 75%, #16181d);
}
/* ---------- Doorbusters rail ---------- */
.doorbusters {
margin: clamp(40px, 6vw, 64px) 0 0;
padding: clamp(32px, 5vw, 52px) 0 clamp(40px, 5vw, 56px);
background:
radial-gradient(800px 400px at 90% -30%, rgba(224, 36, 94, .35), transparent 60%),
linear-gradient(180deg, #1a1228, #120c1f);
overflow: hidden;
}
.doorbusters__head {
max-width: var(--maxw);
margin: 0 auto;
padding: 0 clamp(16px, 4vw, 40px);
}
.doorbusters__head .section-title { margin-bottom: 6px; }
.doorbusters__note { margin: 0 0 22px; color: rgba(255, 255, 255, .66); font-size: .95rem; }
.rail {
display: flex;
gap: 16px;
overflow-x: auto;
scroll-snap-type: x mandatory;
padding: 4px clamp(16px, 4vw, 40px) 14px;
max-width: var(--maxw);
margin: 0 auto;
scrollbar-width: thin;
scrollbar-color: rgba(255, 255, 255, .3) transparent;
}
.rail::-webkit-scrollbar { height: 8px; }
.rail::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, .25); border-radius: 999px; }
.db-card {
scroll-snap-align: start;
flex: 0 0 230px;
display: flex;
flex-direction: column;
border-radius: var(--radius);
background: #fff;
border: 1px solid rgba(255, 255, 255, .12);
box-shadow: var(--shadow-md);
overflow: hidden;
}
.db-card .thumb { height: 130px; }
/* ---------- Deals grid ---------- */
.deals-section {
max-width: var(--maxw);
margin: 0 auto;
padding: clamp(40px, 6vw, 64px) clamp(16px, 4vw, 40px) 24px;
}
.deals-section__bar {
display: flex;
flex-wrap: wrap;
align-items: flex-end;
justify-content: space-between;
gap: 16px;
margin-bottom: 22px;
}
.deals-section__bar .section-title { margin-bottom: 4px; }
.result-count { margin: 0; color: var(--muted); font-size: .9rem; font-weight: 500; }
.sort { display: flex; align-items: center; gap: 10px; }
.sort__label {
font-size: .82rem;
font-weight: 700;
letter-spacing: .04em;
text-transform: uppercase;
color: var(--muted);
}
.sort__toggle {
display: inline-flex;
padding: 4px;
background: var(--surface);
border: 1px solid var(--line);
border-radius: 999px;
gap: 2px;
}
.sort__btn {
border: 0;
background: transparent;
color: var(--muted);
font: inherit;
font-weight: 700;
font-size: .85rem;
padding: 7px 14px;
border-radius: 999px;
cursor: pointer;
white-space: nowrap;
transition: background .15s ease, color .15s ease;
}
.sort__btn:hover { color: var(--ink); }
.sort__btn.is-active {
background: #fff;
color: var(--brand);
box-shadow: var(--shadow-sm);
}
.product-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 18px;
}
/* ---------- Product card ---------- */
.card {
position: relative;
display: flex;
flex-direction: column;
background: #fff;
border: 1px solid var(--line);
border-radius: var(--radius);
overflow: hidden;
transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.card:hover {
transform: translateY(-4px);
box-shadow: var(--shadow-lg);
border-color: rgba(52, 87, 255, .35);
}
.thumb {
position: relative;
height: 160px;
display: grid;
place-items: center;
font-size: 3.2rem;
background: linear-gradient(150deg, var(--t1, #eef1ff), var(--t2, #f7e9f1));
}
.thumb__emoji { filter: drop-shadow(0 8px 14px rgba(16, 18, 29, .18)); }
.badge-off {
position: absolute;
top: 12px;
left: 12px;
padding: 5px 10px;
border-radius: 999px;
background: var(--sale);
color: #fff;
font-size: .78rem;
font-weight: 900;
letter-spacing: .01em;
box-shadow: 0 4px 12px rgba(224, 36, 94, .4);
}
.badge-stock {
position: absolute;
top: 12px;
right: 12px;
padding: 4px 9px;
border-radius: 999px;
font-size: .68rem;
font-weight: 800;
letter-spacing: .04em;
text-transform: uppercase;
background: rgba(255, 255, 255, .92);
color: var(--ok);
border: 1px solid rgba(31, 157, 85, .3);
}
.badge-stock.is-low { color: var(--sale); border-color: rgba(224, 36, 94, .3); }
.card__body {
display: flex;
flex-direction: column;
gap: 8px;
padding: 14px 14px 16px;
flex: 1;
}
.card__brand {
font-size: .72rem;
font-weight: 700;
letter-spacing: .08em;
text-transform: uppercase;
color: var(--muted);
}
.card__name {
font-size: 1rem;
font-weight: 700;
line-height: 1.3;
margin: 0;
}
.rating {
display: flex;
align-items: center;
gap: 6px;
font-size: .82rem;
color: var(--muted);
}
.rating__stars { color: #f5a623; letter-spacing: .5px; font-size: .9rem; }
.rating__count { font-weight: 500; }
.price-row {
display: flex;
align-items: baseline;
gap: 9px;
margin-top: 2px;
}
.price-now { font-size: 1.32rem; font-weight: 900; color: var(--ink); letter-spacing: -.01em; }
.price-was {
font-size: .92rem;
color: var(--muted);
text-decoration: line-through;
text-decoration-color: rgba(224, 36, 94, .6);
}
.price-save {
font-size: .78rem;
font-weight: 800;
color: var(--ok);
}
.card__cta {
margin-top: auto;
width: 100%;
padding: 11px 14px;
border: 0;
border-radius: 11px;
background: var(--brand);
color: #fff;
font: inherit;
font-weight: 700;
font-size: .94rem;
cursor: pointer;
transition: background .15s ease, transform .12s ease;
}
.card__cta:hover { background: var(--brand-d); }
.card__cta:active { transform: scale(.98); }
.card__cta.is-added { background: var(--ok); }
/* ---------- Footer ---------- */
.site-footer {
text-align: center;
padding: 40px 16px;
color: var(--muted);
font-size: .88rem;
border-top: 1px solid var(--line);
background: var(--surface);
}
/* ---------- Toast ---------- */
.toast-wrap {
position: fixed;
left: 50%;
bottom: 24px;
transform: translateX(-50%);
z-index: 80;
display: flex;
flex-direction: column;
gap: 10px;
align-items: center;
pointer-events: none;
}
.toast {
display: inline-flex;
align-items: center;
gap: 10px;
padding: 12px 18px;
border-radius: 12px;
background: var(--ink-900);
color: #fff;
font-weight: 600;
font-size: .92rem;
box-shadow: var(--shadow-lg);
opacity: 0;
transform: translateY(14px) scale(.96);
transition: opacity .25s ease, transform .25s ease;
}
.toast.is-show { opacity: 1; transform: translateY(0) scale(1); }
.toast__dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--ok);
}
/* ---------- Responsive ---------- */
@media (max-width: 640px) {
.site-nav { display: none; }
.countdown__unit { min-width: 46px; }
.countdown { gap: 3px; padding: 12px; }
.product-grid { grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 12px; }
.thumb { height: 130px; font-size: 2.6rem; }
}
@media (max-width: 400px) {
.product-grid { grid-template-columns: 1fr; }
.hero__cta { flex-direction: column; }
.hero__cta .btn { width: 100%; }
}(function () {
"use strict";
/* ---------- data (fictional) ---------- */
var DEALS = [
{ id: "p1", brand: "Aurora", name: "Pulse ANC Headphones", emoji: "🎧", now: 119, was: 199, rating: 4.7, reviews: 2143, stock: "in", t1: "#eef1ff", t2: "#e3e9ff" },
{ id: "p2", brand: "Nimbus", name: "Track Air Earbuds", emoji: "🎵", now: 59, was: 129, rating: 4.5, reviews: 980, stock: "low", t1: "#fdeef5", t2: "#ffe5d6" },
{ id: "p3", brand: "Volt", name: "Glide Pro Smartwatch", emoji: "⌚", now: 149, was: 299, rating: 4.8, reviews: 4012, stock: "in", t1: "#e6fbf2", t2: "#defaf0" },
{ id: "p4", brand: "Hex", name: "Quantum Gaming Mouse", emoji: "🖱️", now: 39, was: 69, rating: 4.6, reviews: 1567, stock: "in", t1: "#f3e9ff", t2: "#fbe6ff" },
{ id: "p5", brand: "Cobalt", name: "Vista 4K Webcam", emoji: "📷", now: 79, was: 119, rating: 4.4, reviews: 612, stock: "in", t1: "#e6f4ff", t2: "#dbeeff" },
{ id: "p6", brand: "Lumen", name: "Beam Smart Bulb 4-pack", emoji: "💡", now: 29, was: 75, rating: 4.3, reviews: 3389, stock: "low", t1: "#fff4e0", t2: "#ffe9c7" },
{ id: "p7", brand: "Forge", name: "Stratus Mechanical Keyboard", emoji: "⌨️", now: 89, was: 149, rating: 4.9, reviews: 2870, stock: "in", t1: "#eef1ff", t2: "#efe6ff" },
{ id: "p8", brand: "Drift", name: "Carry Power Bank 20K", emoji: "🔋", now: 34, was: 59, rating: 4.5, reviews: 1102, stock: "in", t1: "#e9fbf4", t2: "#e3f7ff" }
];
var DOORBUSTERS = [
{ id: "d1", brand: "Aurora", name: "Studio Over-Ear", emoji: "🎧", now: 99, was: 249, rating: 4.8, reviews: 5210, stock: "low", t1: "#0c0d12", t2: "#1b1340" },
{ id: "d2", brand: "Volt", name: "Edge Tablet 11\"", emoji: "📱", now: 199, was: 449, rating: 4.7, reviews: 1880, stock: "low", t1: "#2a0f23", t2: "#421030" },
{ id: "d3", brand: "Hex", name: "Apex Console Bundle", emoji: "🎮", now: 279, was: 499, rating: 4.9, reviews: 9120, stock: "low", t1: "#0e1f33", t2: "#10283f" },
{ id: "d4", brand: "Lumen", name: "Halo Mesh Wi-Fi 3-pack", emoji: "📡", now: 129, was: 279, rating: 4.6, reviews: 740, stock: "low", t1: "#1a1228", t2: "#2a1b3d" },
{ id: "d5", brand: "Forge", name: "Bolt Ultrawide Monitor", emoji: "🖥️", now: 349, was: 699, rating: 4.8, reviews: 1320, stock: "low", t1: "#10182e", t2: "#101a33" }
];
var FEATURED_ORDER = DEALS.map(function (d) { return d.id; });
/* ---------- helpers ---------- */
function money(n) {
return "$" + Number(n).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
function pctOff(now, was) {
return Math.round((1 - now / was) * 100);
}
function stars(rating) {
var full = Math.round(rating);
var s = "";
for (var i = 0; i < 5; i++) s += i < full ? "★" : "☆";
return s;
}
function el(tag, cls, html) {
var n = document.createElement(tag);
if (cls) n.className = cls;
if (html != null) n.innerHTML = html;
return n;
}
/* ---------- toast ---------- */
var toastWrap = document.getElementById("toastWrap");
function toast(msg) {
var t = el("div", "toast");
t.appendChild(el("span", "toast__dot"));
t.appendChild(el("span", null, msg));
toastWrap.appendChild(t);
requestAnimationFrame(function () { t.classList.add("is-show"); });
setTimeout(function () {
t.classList.remove("is-show");
setTimeout(function () { if (t.parentNode) t.parentNode.removeChild(t); }, 300);
}, 2300);
}
/* ---------- cart ---------- */
var cartCount = 0;
var cartCountEl = document.getElementById("cartCount");
var cartBtn = document.getElementById("cartBtn");
function addToCart(name) {
cartCount += 1;
cartCountEl.textContent = String(cartCount);
cartCountEl.classList.add("is-on");
cartBtn.setAttribute("aria-label", "Open cart, " + cartCount + (cartCount === 1 ? " item" : " items"));
// little bounce
cartCountEl.style.transform = "scale(1.3)";
setTimeout(function () { cartCountEl.style.transform = ""; }, 160);
toast("Added “" + name + "” to cart");
}
cartBtn.addEventListener("click", function () {
if (cartCount === 0) toast("Your cart is empty — grab a deal!");
else toast(cartCount + (cartCount === 1 ? " item" : " items") + " in your cart");
});
/* ---------- card factory ---------- */
function buildCard(p, isList) {
var off = pctOff(p.now, p.was);
var card = el("article", "card");
card.setAttribute("role", "listitem");
var thumb = el("div", "thumb");
thumb.style.setProperty("--t1", p.t1);
thumb.style.setProperty("--t2", p.t2);
thumb.appendChild(el("span", "thumb__emoji", p.emoji));
thumb.appendChild(el("span", "badge-off", "-" + off + "%"));
var stockChip = el("span", "badge-stock" + (p.stock === "low" ? " is-low" : ""),
p.stock === "low" ? "Low stock" : "In stock");
thumb.appendChild(stockChip);
card.appendChild(thumb);
var body = el("div", "card__body");
body.appendChild(el("span", "card__brand", p.brand));
body.appendChild(el("h3", "card__name", p.name));
var rating = el("div", "rating");
rating.setAttribute("aria-label", p.rating + " out of 5 stars, " + p.reviews + " reviews");
rating.appendChild(el("span", "rating__stars", stars(p.rating)));
rating.appendChild(el("span", "rating__count", p.rating.toFixed(1) + " (" + p.reviews.toLocaleString("en-US") + ")"));
body.appendChild(rating);
var priceRow = el("div", "price-row");
priceRow.appendChild(el("span", "price-now", money(p.now)));
priceRow.appendChild(el("span", "price-was", money(p.was)));
body.appendChild(priceRow);
body.appendChild(el("span", "price-save", "You save " + money(p.was - p.now)));
var cta = el("button", "card__cta", "Add to cart");
cta.type = "button";
cta.addEventListener("click", function () {
addToCart(p.name);
cta.classList.add("is-added");
cta.textContent = "Added ✓";
setTimeout(function () {
cta.classList.remove("is-added");
cta.textContent = "Add to cart";
}, 1400);
});
body.appendChild(cta);
card.appendChild(body);
return card;
}
/* ---------- render grid ---------- */
var grid = document.getElementById("productGrid");
var resultCount = document.getElementById("resultCount");
var currentSort = "featured";
function sortedDeals() {
var arr = DEALS.slice();
if (currentSort === "discount") {
arr.sort(function (a, b) { return pctOff(b.now, b.was) - pctOff(a.now, a.was); });
} else if (currentSort === "price") {
arr.sort(function (a, b) { return a.now - b.now; });
} else {
arr.sort(function (a, b) { return FEATURED_ORDER.indexOf(a.id) - FEATURED_ORDER.indexOf(b.id); });
}
return arr;
}
function renderGrid() {
grid.innerHTML = "";
var arr = sortedDeals();
arr.forEach(function (p) { grid.appendChild(buildCard(p)); });
resultCount.textContent = "Showing " + arr.length + " deals";
}
/* ---------- render doorbusters ---------- */
var rail = document.getElementById("doorbusterRail");
function renderRail() {
DOORBUSTERS.forEach(function (p) {
var card = buildCard(p);
card.classList.add("db-card");
rail.appendChild(card);
});
}
/* ---------- sort toggle ---------- */
var sortBtns = Array.prototype.slice.call(document.querySelectorAll(".sort__btn"));
sortBtns.forEach(function (btn) {
btn.addEventListener("click", function () {
if (btn.dataset.sort === currentSort) return;
currentSort = btn.dataset.sort;
sortBtns.forEach(function (b) {
var on = b === btn;
b.classList.toggle("is-active", on);
b.setAttribute("aria-pressed", on ? "true" : "false");
});
renderGrid();
var labels = { featured: "Featured", discount: "biggest discount", price: "lowest price" };
toast("Sorted by " + labels[currentSort]);
});
});
/* ---------- copy coupon ---------- */
var copyBtn = document.getElementById("copyCoupon");
var couponHint = document.getElementById("couponHint");
var COUPON = "VOLT15";
copyBtn.addEventListener("click", function () {
function done() {
copyBtn.classList.add("is-copied");
couponHint.textContent = "Copied!";
toast("Coupon " + COUPON + " copied to clipboard");
setTimeout(function () {
copyBtn.classList.remove("is-copied");
couponHint.textContent = "Copy";
}, 1800);
}
if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(COUPON).then(done).catch(fallback);
} else {
fallback();
}
function fallback() {
var ta = document.createElement("textarea");
ta.value = COUPON;
ta.setAttribute("readonly", "");
ta.style.position = "absolute";
ta.style.left = "-9999px";
document.body.appendChild(ta);
ta.select();
try { document.execCommand("copy"); } catch (e) { /* noop */ }
document.body.removeChild(ta);
done();
}
});
/* ---------- countdown ---------- */
// Ends at the next upcoming midnight (local). Falls back to +1 day if already passed.
var deadline = new Date();
deadline.setHours(24, 0, 0, 0); // next midnight
var dEls = {
d: document.getElementById("cdDays"),
h: document.getElementById("cdHours"),
m: document.getElementById("cdMins"),
s: document.getElementById("cdSecs")
};
function pad(n) { return String(n).padStart(2, "0"); }
function tick() {
var diff = deadline.getTime() - Date.now();
if (diff <= 0) {
// roll the sale forward 24h so the demo never flatlines
deadline.setTime(deadline.getTime() + 24 * 3600 * 1000);
diff = deadline.getTime() - Date.now();
}
var secs = Math.floor(diff / 1000);
var days = Math.floor(secs / 86400); secs -= days * 86400;
var hrs = Math.floor(secs / 3600); secs -= hrs * 3600;
var mins = Math.floor(secs / 60); secs -= mins * 60;
dEls.d.textContent = pad(days);
dEls.h.textContent = pad(hrs);
dEls.m.textContent = pad(mins);
dEls.s.textContent = pad(secs);
}
/* ---------- init ---------- */
renderRail();
renderGrid();
tick();
setInterval(tick, 1000);
})();<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Mega Sale — Up to 60% Off | Volt</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=Inter:wght@400;500;600;700;800;900&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<!-- Coupon strip -->
<div class="coupon-strip" role="region" aria-label="Promo coupon">
<p>
<span class="coupon-spark" aria-hidden="true">⚡</span>
Extra <strong>15% off</strong> orders over $75 with code
<button class="coupon-code" id="copyCoupon" type="button" aria-label="Copy coupon code VOLT15">
<span class="coupon-code__text">VOLT15</span>
<span class="coupon-code__hint" id="couponHint">Copy</span>
</button>
— ends at midnight.
</p>
</div>
<!-- Header -->
<header class="site-header">
<a href="#" class="brand" aria-label="Volt home">
<span class="brand__mark" aria-hidden="true">▲</span>
<span class="brand__name">Volt</span>
</a>
<nav class="site-nav" aria-label="Primary">
<a href="#deals">Deals</a>
<a href="#doorbusters">Doorbusters</a>
<a href="#grid">All offers</a>
</nav>
<button class="cart-btn" id="cartBtn" type="button" aria-label="Open cart, 0 items">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="9" cy="21" r="1"></circle><circle cx="20" cy="21" r="1"></circle><path d="M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6"></path></svg>
<span class="cart-count" id="cartCount" aria-hidden="true">0</span>
</button>
</header>
<main>
<!-- Hero -->
<section class="hero" id="deals" aria-labelledby="heroTitle">
<div class="hero__glow" aria-hidden="true"></div>
<div class="hero__inner">
<p class="hero__eyebrow">Seasonal Mega Sale · Limited time</p>
<h1 class="hero__title" id="heroTitle">
Up to <span class="hero__big">60% off</span><br />everything in tech.
</h1>
<p class="hero__sub">Thousands of deals drop today. Stack code <strong>VOLT15</strong> for an extra 15% — while the clock runs.</p>
<div class="countdown" role="timer" aria-live="off" aria-label="Sale ends in">
<div class="countdown__unit"><span class="countdown__num" id="cdDays">00</span><span class="countdown__label">Days</span></div>
<span class="countdown__sep" aria-hidden="true">:</span>
<div class="countdown__unit"><span class="countdown__num" id="cdHours">00</span><span class="countdown__label">Hrs</span></div>
<span class="countdown__sep" aria-hidden="true">:</span>
<div class="countdown__unit"><span class="countdown__num" id="cdMins">00</span><span class="countdown__label">Min</span></div>
<span class="countdown__sep" aria-hidden="true">:</span>
<div class="countdown__unit"><span class="countdown__num" id="cdSecs">00</span><span class="countdown__label">Sec</span></div>
</div>
<div class="hero__cta">
<a href="#grid" class="btn btn--primary">Shop all deals</a>
<a href="#doorbusters" class="btn btn--ghost">See doorbusters</a>
</div>
<ul class="trust" aria-label="Store guarantees">
<li><span aria-hidden="true">🚚</span> Free shipping over $50</li>
<li><span aria-hidden="true">🔒</span> Secure checkout</li>
<li><span aria-hidden="true">↩️</span> 30-day returns</li>
</ul>
</div>
</section>
<!-- Deal categories -->
<section class="cats" aria-labelledby="catsTitle">
<h2 class="section-title" id="catsTitle">Shop the deal categories</h2>
<div class="cats__grid">
<a class="cat" href="#grid" style="--c1:#3457ff;--c2:#7a5cff;">
<span class="cat__icon" aria-hidden="true">🎧</span>
<span class="cat__name">Audio</span>
<span class="cat__off">Up to 45% off</span>
</a>
<a class="cat" href="#grid" style="--c1:#e0245e;--c2:#ff6a3d;">
<span class="cat__icon" aria-hidden="true">📱</span>
<span class="cat__name">Phones</span>
<span class="cat__off">Up to 30% off</span>
</a>
<a class="cat" href="#grid" style="--c1:#1f9d55;--c2:#3ad1a3;">
<span class="cat__icon" aria-hidden="true">⌚</span>
<span class="cat__name">Wearables</span>
<span class="cat__off">Up to 50% off</span>
</a>
<a class="cat" href="#grid" style="--c1:#9333ea;--c2:#d946ef;">
<span class="cat__icon" aria-hidden="true">🎮</span>
<span class="cat__name">Gaming</span>
<span class="cat__off">Up to 40% off</span>
</a>
<a class="cat" href="#grid" style="--c1:#f59e0b;--c2:#fbbf24;">
<span class="cat__icon" aria-hidden="true">💻</span>
<span class="cat__name">Laptops</span>
<span class="cat__off">Up to 35% off</span>
</a>
<a class="cat" href="#grid" style="--c1:#0ea5e9;--c2:#38bdf8;">
<span class="cat__icon" aria-hidden="true">🏠</span>
<span class="cat__name">Smart home</span>
<span class="cat__off">Up to 60% off</span>
</a>
</div>
</section>
<!-- Doorbusters rail -->
<section class="doorbusters" id="doorbusters" aria-labelledby="dbTitle">
<div class="doorbusters__head">
<h2 class="section-title section-title--light" id="dbTitle">
<span class="fire" aria-hidden="true">🔥</span> Doorbusters
</h2>
<p class="doorbusters__note">Lowest prices of the season — while supplies last.</p>
</div>
<div class="rail" id="doorbusterRail" role="list" aria-label="Doorbuster deals">
<!-- doorbuster cards injected by JS -->
</div>
</section>
<!-- Product grid -->
<section class="deals-section" id="grid" aria-labelledby="gridTitle">
<div class="deals-section__bar">
<div>
<h2 class="section-title" id="gridTitle">Today’s deals</h2>
<p class="result-count" id="resultCount">Showing 8 deals</p>
</div>
<div class="sort">
<span class="sort__label" id="sortLabel">Sort</span>
<div class="sort__toggle" role="group" aria-labelledby="sortLabel">
<button type="button" class="sort__btn is-active" data-sort="featured" aria-pressed="true">Featured</button>
<button type="button" class="sort__btn" data-sort="discount" aria-pressed="false">Biggest discount</button>
<button type="button" class="sort__btn" data-sort="price" aria-pressed="false">Lowest price</button>
</div>
</div>
</div>
<div class="product-grid" id="productGrid" aria-live="polite">
<!-- product cards injected by JS -->
</div>
</section>
</main>
<footer class="site-footer">
<p>Volt · Illustrative storefront demo. Fictional products & prices — no real checkout.</p>
</footer>
<!-- Toast region -->
<div class="toast-wrap" id="toastWrap" role="status" aria-live="polite" aria-atomic="true"></div>
<script src="script.js"></script>
</body>
</html>Sale / Deals Landing
A deal-driven storefront landing built for a fictional tech brand, “Volt.” A sticky coupon strip and a bold dark hero set the tone, with a four-segment countdown that ticks every second toward the next midnight and rolls forward so the demo never flatlines. Below the fold, gradient deal-category tiles, a scroll-snapping “doorbusters” rail, and a responsive product grid carry the offers. Each card surfaces a percent-off badge, struck-through original price next to the sale price, a “you save” line, star rating with review count, and an in-stock / low-stock chip.
Every control actually works. The sort toggle reorders the grid by Featured, biggest discount, or lowest price; the coupon code copies to the clipboard (with a textarea fallback) and confirms via toast; and Add to cart buttons animate, fire a toast, and bump an accessible cart badge. Prices are formatted as currency, the layout collapses gracefully to a single column near 360px, and focus-visible rings plus aria labels keep it keyboard- and screen-reader-friendly.
The palette stays clean — white surfaces, ink text, a single blue brand accent, and a hot-pink sale color — so the energy comes from contrast and motion rather than clutter. No frameworks, no build step, no external images: product visuals are emoji on soft gradient tiles.
Illustrative storefront UI only — fictional products, prices, and reviews. No real checkout.