Auto — EV Dealership Landing
An ultra-clean, Tesla-style landing page for a fictional electric-vehicle maker built in pure HTML, CSS, and vanilla JavaScript. It pairs a minimal white aesthetic with electric-blue accents, animated range and charging stats, a tabbed model lineup, a live charging-curve simulator with an animated SVG battery ring, a performance and autonomy feature grid, and a fully interactive build configurator that updates a running price summary. Scroll reveal, a sticky blurred nav, and a mobile menu round it out.
MCP
Code
:root {
/* EV / Tesla-style override — white, minimal, electric blue */
--blue: #2b7fff;
--blue-d: #1c63d6;
--blue-l: #6aa6ff;
--blue-50: #eef4ff;
--ink: #0c1120;
--ink-2: #2a3142;
--muted: #6b7384;
--steel: #8a929d;
--bg: #ffffff;
--bg-2: #f6f8fc;
--surface: #ffffff;
--line: rgba(12, 17, 32, 0.08);
--line-2: rgba(12, 17, 32, 0.14);
--ok: #2f9e6f;
--warn: #e0962a;
--r-sm: 8px;
--r-md: 14px;
--r-lg: 20px;
--r-xl: 28px;
--shadow-1: 0 1px 2px rgba(12, 17, 32, 0.05), 0 4px 16px rgba(12, 17, 32, 0.05);
--shadow-2: 0 8px 40px rgba(12, 17, 32, 0.1);
--shadow-blue: 0 10px 40px rgba(43, 127, 255, 0.28);
--font: "Inter", system-ui, -apple-system, sans-serif;
--nav-h: 64px;
}
* {
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
scroll-padding-top: var(--nav-h);
}
body {
margin: 0;
font-family: var(--font);
background: var(--bg);
color: var(--ink);
line-height: 1.5;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
}
h1, h2, h3, h4, h5 {
margin: 0;
letter-spacing: -0.02em;
line-height: 1.1;
}
p { margin: 0; }
a { color: inherit; text-decoration: none; }
.tnum { font-variant-numeric: tabular-nums; }
/* ============ BUTTONS ============ */
.btn {
--pad-y: 11px;
--pad-x: 20px;
display: inline-flex;
align-items: center;
justify-content: center;
gap: 8px;
padding: var(--pad-y) var(--pad-x);
border: 1px solid transparent;
border-radius: 999px;
font: inherit;
font-weight: 600;
font-size: 14px;
cursor: pointer;
transition: transform 0.15s ease, background 0.2s ease, box-shadow 0.2s ease, color 0.2s;
white-space: nowrap;
}
.btn:active { transform: translateY(1px) scale(0.99); }
.btn:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.btn--solid {
background: var(--blue);
color: #fff;
box-shadow: 0 4px 14px rgba(43, 127, 255, 0.3);
}
.btn--solid:hover { background: var(--blue-d); box-shadow: var(--shadow-blue); transform: translateY(-1px); }
.btn--ghost {
background: rgba(12, 17, 32, 0.04);
color: var(--ink);
border-color: var(--line-2);
}
.btn--ghost:hover { background: rgba(12, 17, 32, 0.07); }
.btn--lg { --pad-y: 14px; --pad-x: 28px; font-size: 15px; }
.btn--sm { --pad-y: 8px; --pad-x: 14px; font-size: 13px; }
.btn--block { width: 100%; }
/* ============ NAV ============ */
.nav {
position: sticky;
top: 0;
z-index: 50;
background: rgba(255, 255, 255, 0.72);
backdrop-filter: saturate(160%) blur(16px);
-webkit-backdrop-filter: saturate(160%) blur(16px);
border-bottom: 1px solid transparent;
transition: border-color 0.3s, box-shadow 0.3s;
}
.nav.is-scrolled {
border-bottom-color: var(--line);
box-shadow: 0 1px 0 var(--line);
}
.nav__inner {
max-width: 1180px;
margin: 0 auto;
height: var(--nav-h);
padding: 0 24px;
display: flex;
align-items: center;
gap: 24px;
}
.brand {
display: inline-flex;
align-items: center;
gap: 9px;
font-weight: 800;
font-size: 19px;
letter-spacing: -0.03em;
}
.brand__mark {
display: grid;
place-items: center;
width: 32px;
height: 32px;
border-radius: 9px;
color: #fff;
background: linear-gradient(140deg, var(--blue), var(--blue-d));
box-shadow: 0 4px 12px rgba(43, 127, 255, 0.4);
}
.nav__links {
display: flex;
gap: 6px;
margin-left: 12px;
margin-right: auto;
}
.nav__links a {
padding: 8px 14px;
border-radius: 999px;
font-size: 14px;
font-weight: 500;
color: var(--ink-2);
transition: background 0.2s, color 0.2s;
}
.nav__links a:hover { background: var(--blue-50); color: var(--blue-d); }
.nav__actions { display: flex; gap: 10px; }
.nav__toggle {
display: none;
flex-direction: column;
gap: 5px;
width: 42px;
height: 42px;
align-items: center;
justify-content: center;
border: 1px solid var(--line-2);
border-radius: 12px;
background: #fff;
cursor: pointer;
}
.nav__toggle span {
width: 18px;
height: 2px;
border-radius: 2px;
background: var(--ink);
transition: transform 0.25s, opacity 0.2s;
}
.nav__toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav__toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav__toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
.mobile-nav {
display: flex;
flex-direction: column;
gap: 4px;
padding: 12px 20px 20px;
border-bottom: 1px solid var(--line);
background: #fff;
}
.mobile-nav a {
padding: 13px 12px;
border-radius: 12px;
font-weight: 600;
color: var(--ink-2);
}
.mobile-nav a:hover { background: var(--bg-2); }
.mobile-nav .btn { margin-top: 8px; }
/* ============ LAYOUT ============ */
.section {
max-width: 1180px;
margin: 0 auto;
padding: clamp(56px, 9vw, 110px) 24px;
}
.section__head {
max-width: 680px;
margin: 0 auto clamp(32px, 5vw, 56px);
text-align: center;
}
.section__head h2 {
font-size: clamp(28px, 5vw, 46px);
font-weight: 800;
}
.kicker {
display: inline-block;
margin-bottom: 14px;
padding: 5px 14px;
border-radius: 999px;
background: var(--blue-50);
color: var(--blue-d);
font-size: 12.5px;
font-weight: 700;
letter-spacing: 0.04em;
text-transform: uppercase;
}
.lead {
margin-top: 16px;
color: var(--muted);
font-size: clamp(15px, 2vw, 18px);
}
/* ============ HERO ============ */
.hero {
position: relative;
overflow: hidden;
padding: clamp(56px, 10vw, 100px) 24px clamp(40px, 6vw, 70px);
background: linear-gradient(180deg, #fff 0%, var(--bg-2) 100%);
}
.hero__bg { position: absolute; inset: 0; pointer-events: none; }
.orb {
position: absolute;
border-radius: 50%;
filter: blur(70px);
opacity: 0.5;
}
.orb--1 {
width: 520px; height: 520px;
top: -180px; right: -120px;
background: radial-gradient(circle, rgba(43,127,255,0.55), transparent 70%);
}
.orb--2 {
width: 420px; height: 420px;
bottom: -160px; left: -120px;
background: radial-gradient(circle, rgba(106,166,255,0.4), transparent 70%);
}
.grid-lines {
position: absolute; inset: 0;
background-image:
linear-gradient(var(--line) 1px, transparent 1px),
linear-gradient(90deg, var(--line) 1px, transparent 1px);
background-size: 48px 48px;
mask-image: radial-gradient(ellipse 70% 60% at 50% 30%, #000 30%, transparent 75%);
-webkit-mask-image: radial-gradient(ellipse 70% 60% at 50% 30%, #000 30%, transparent 75%);
opacity: 0.7;
}
.hero__inner {
position: relative;
max-width: 920px;
margin: 0 auto;
text-align: center;
}
.eyebrow {
display: inline-block;
padding: 6px 16px;
border-radius: 999px;
border: 1px solid var(--line-2);
background: rgba(255,255,255,0.7);
color: var(--blue-d);
font-size: 13px;
font-weight: 600;
}
.hero__title {
margin: 22px 0 0;
font-size: clamp(44px, 11vw, 96px);
font-weight: 800;
letter-spacing: -0.045em;
}
.grad {
background: linear-gradient(120deg, var(--blue), var(--blue-l));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.hero__sub {
max-width: 560px;
margin: 22px auto 0;
color: var(--muted);
font-size: clamp(16px, 2.2vw, 19px);
}
.hero__cta {
display: flex;
gap: 12px;
justify-content: center;
flex-wrap: wrap;
margin-top: 30px;
}
/* hero car (pure CSS) */
.hero__car { margin-top: clamp(28px, 5vw, 50px); }
.car-stage {
position: relative;
width: min(560px, 92%);
height: 200px;
margin: 0 auto;
}
.car-body {
position: absolute;
left: 50%;
bottom: 34px;
transform: translateX(-50%);
width: 460px;
max-width: 100%;
height: 120px;
background: linear-gradient(180deg, #2a3142 0%, #0c1120 100%);
border-radius: 90px 110px 26px 26px / 120px 120px 26px 26px;
box-shadow: inset 0 2px 8px rgba(255,255,255,0.08);
}
.car-body::before {
content: "";
position: absolute;
top: 16px; left: 50%;
transform: translateX(-50%);
width: 56%; height: 46px;
background: linear-gradient(180deg, var(--blue-l), var(--blue));
border-radius: 60px 60px 8px 8px;
opacity: 0.85;
}
.car-body::after {
content: "";
position: absolute;
bottom: -16px; left: 14%;
width: 72%; height: 34px;
background:
radial-gradient(circle at 16% 60%, #0c1120 36%, transparent 38%),
radial-gradient(circle at 84% 60%, #0c1120 36%, transparent 38%);
}
.car-glow {
position: absolute;
left: 50%; bottom: 16px;
transform: translateX(-50%);
width: 460px; max-width: 100%; height: 60px;
background: radial-gradient(ellipse at center, rgba(43,127,255,0.45), transparent 70%);
filter: blur(14px);
animation: pulse 3.2s ease-in-out infinite;
}
.car-shadow {
position: absolute;
left: 50%; bottom: 12px;
transform: translateX(-50%);
width: 380px; max-width: 86%; height: 22px;
background: radial-gradient(ellipse at center, rgba(12,17,32,0.22), transparent 70%);
filter: blur(6px);
}
@keyframes pulse {
0%, 100% { opacity: 0.5; }
50% { opacity: 0.95; }
}
/* hero stats */
.stats {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 14px;
margin-top: clamp(34px, 5vw, 56px);
}
.stat {
padding: 22px 16px;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--r-lg);
box-shadow: var(--shadow-1);
transition: transform 0.2s, box-shadow 0.2s, border-color 0.2s;
}
.stat:hover {
transform: translateY(-3px);
border-color: var(--blue-l);
box-shadow: var(--shadow-2);
}
.stat__num {
font-size: clamp(24px, 4vw, 34px);
font-weight: 800;
letter-spacing: -0.03em;
font-variant-numeric: tabular-nums;
color: var(--ink);
}
.stat__label {
margin-top: 4px;
font-size: 13px;
color: var(--muted);
font-weight: 500;
}
/* ============ MODELS ============ */
.model-tabs {
display: inline-flex;
gap: 4px;
padding: 5px;
margin: 0 auto clamp(28px, 4vw, 44px);
border-radius: 999px;
background: var(--bg-2);
border: 1px solid var(--line);
width: max-content;
max-width: 100%;
}
.models { text-align: center; }
.model-tab {
padding: 10px 26px;
border: none;
border-radius: 999px;
background: transparent;
font: inherit;
font-weight: 600;
font-size: 15px;
color: var(--muted);
cursor: pointer;
transition: background 0.2s, color 0.2s, box-shadow 0.2s;
}
.model-tab.is-active {
background: #fff;
color: var(--ink);
box-shadow: var(--shadow-1);
}
.model-tab:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.model-stage { text-align: left; }
.model-card {
display: grid;
grid-template-columns: 1.1fr 1fr;
align-items: stretch;
border: 1px solid var(--line);
border-radius: var(--r-xl);
overflow: hidden;
background: var(--surface);
box-shadow: var(--shadow-2);
animation: fadeUp 0.4s ease;
}
@keyframes fadeUp {
from { opacity: 0; transform: translateY(12px); }
to { opacity: 1; transform: translateY(0); }
}
.model-card__visual {
position: relative;
min-height: 320px;
display: flex;
align-items: flex-end;
padding: 22px;
}
.visual--aero { background: linear-gradient(135deg, #0c1120, #1c63d6); }
.visual--range { background: linear-gradient(135deg, #11203b, #2b7fff); }
.visual--haul { background: linear-gradient(135deg, #0c1120, #3a4a66); }
.model-card__visual::after {
content: "";
position: absolute;
left: 8%; right: 8%; bottom: 26%;
height: 130px;
background: linear-gradient(180deg, rgba(255,255,255,0.14), rgba(255,255,255,0));
border-radius: 80px 100px 20px 20px / 110px 110px 20px 20px;
box-shadow: 0 30px 60px rgba(0,0,0,0.3);
}
.model-card__badge {
position: relative;
z-index: 1;
padding: 6px 14px;
border-radius: 999px;
background: rgba(255,255,255,0.16);
border: 1px solid rgba(255,255,255,0.28);
color: #fff;
font-size: 12px;
font-weight: 700;
letter-spacing: 0.05em;
text-transform: uppercase;
backdrop-filter: blur(6px);
}
.model-card__body {
padding: clamp(28px, 4vw, 48px);
display: flex;
flex-direction: column;
justify-content: center;
}
.model-card__body h3 { font-size: clamp(26px, 4vw, 36px); font-weight: 800; }
.model-card__tag { margin-top: 8px; color: var(--muted); font-size: 16px; }
.spec-grid {
list-style: none;
margin: 26px 0;
padding: 0;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 14px;
}
.spec-grid li {
padding: 14px 16px;
background: var(--bg-2);
border-radius: var(--r-md);
border: 1px solid var(--line);
}
.spec-grid b {
display: block;
font-size: 21px;
font-weight: 800;
font-variant-numeric: tabular-nums;
}
.spec-grid span { font-size: 12.5px; color: var(--muted); font-weight: 500; }
/* ============ CHARGING ============ */
.charging { background: var(--bg-2); max-width: 100%; }
.charging > * { max-width: 1180px; margin-left: auto; margin-right: auto; }
.charge-panel {
display: grid;
grid-template-columns: 360px 1fr;
gap: 24px;
align-items: stretch;
}
.charge-sim {
display: flex;
flex-direction: column;
align-items: center;
gap: 18px;
padding: 30px 26px;
background: linear-gradient(170deg, #0c1120, #16203a);
border-radius: var(--r-xl);
color: #fff;
box-shadow: var(--shadow-2);
}
.charge-sim__head {
display: flex;
align-items: center;
gap: 9px;
font-size: 14px;
font-weight: 600;
width: 100%;
}
.charge-sim__stall {
margin-left: auto;
font-size: 12px;
color: var(--blue-l);
font-variant-numeric: tabular-nums;
}
.dot {
width: 9px; height: 9px; border-radius: 50%;
background: var(--blue);
}
.dot--live {
background: #43e08e;
box-shadow: 0 0 0 0 rgba(67,224,142,0.6);
animation: blink 1.6s infinite;
}
@keyframes blink {
0% { box-shadow: 0 0 0 0 rgba(67,224,142,0.6); }
70% { box-shadow: 0 0 0 8px rgba(67,224,142,0); }
100% { box-shadow: 0 0 0 0 rgba(67,224,142,0); }
}
.charge-ring { position: relative; width: 180px; height: 180px; }
.charge-ring svg { transform: rotate(-90deg); }
.ring-bg { fill: none; stroke: rgba(255,255,255,0.12); stroke-width: 9; }
.ring-fg {
fill: none;
stroke: var(--blue);
stroke-width: 9;
stroke-linecap: round;
stroke-dasharray: 326.7;
stroke-dashoffset: 326.7;
transition: stroke-dashoffset 0.4s ease;
filter: drop-shadow(0 0 6px rgba(43,127,255,0.7));
}
.charge-ring__pct {
position: absolute;
inset: 0;
display: grid;
place-content: center;
font-size: 44px;
font-weight: 800;
font-variant-numeric: tabular-nums;
}
.charge-ring__pct i { font-size: 18px; font-style: normal; color: var(--blue-l); margin-left: 2px; }
.charge-sim__foot {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 10px;
width: 100%;
text-align: center;
}
.charge-sim__foot div {
padding: 12px 6px;
background: rgba(255,255,255,0.06);
border-radius: var(--r-md);
}
.charge-sim__foot b {
display: block;
font-size: 19px;
font-weight: 800;
font-variant-numeric: tabular-nums;
}
.charge-sim__foot span { font-size: 11px; color: var(--steel); }
.charge-feats {
display: grid;
grid-template-rows: repeat(3, 1fr);
gap: 16px;
}
.feat {
display: flex;
flex-direction: column;
gap: 6px;
padding: 22px 24px;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--r-lg);
box-shadow: var(--shadow-1);
transition: transform 0.2s, box-shadow 0.2s;
}
.feat:hover { transform: translateY(-3px); box-shadow: var(--shadow-2); }
.feat__ico { font-size: 26px; }
.feat h4 { font-size: 17px; font-weight: 700; }
.feat p { color: var(--muted); font-size: 14.5px; }
/* ============ FEATURES ============ */
.feature-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 18px;
}
.card {
padding: 28px;
background: var(--surface);
border: 1px solid var(--line);
border-radius: var(--r-lg);
box-shadow: var(--shadow-1);
transition: transform 0.2s, box-shadow 0.2s, border-color 0.2s;
}
.card:hover {
transform: translateY(-4px);
border-color: var(--blue-l);
box-shadow: var(--shadow-2);
}
.card h3 { font-size: 20px; font-weight: 700; }
.card p { margin-top: 10px; color: var(--muted); font-size: 15px; }
.card--wide {
grid-column: span 2;
background: linear-gradient(150deg, #0c1120, #1c63d6);
color: #fff;
border-color: transparent;
}
.card--wide p { color: rgba(255,255,255,0.78); }
.card--accent {
background: var(--blue-50);
border-color: rgba(43,127,255,0.25);
}
.chips { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 18px; }
.chip {
padding: 6px 13px;
border-radius: 999px;
background: rgba(255,255,255,0.16);
border: 1px solid rgba(255,255,255,0.24);
font-size: 12.5px;
font-weight: 600;
}
/* ============ ORDER ============ */
.order { max-width: 1180px; }
.order__card {
display: grid;
grid-template-columns: 1.3fr 0.9fr;
gap: 0;
border: 1px solid var(--line);
border-radius: var(--r-xl);
overflow: hidden;
box-shadow: var(--shadow-2);
background: var(--surface);
}
.order__copy { padding: clamp(30px, 4vw, 52px); }
.order__copy h2 { font-size: clamp(28px, 4vw, 42px); font-weight: 800; }
.config { margin-top: 30px; display: flex; flex-direction: column; gap: 22px; }
.config__row { display: flex; flex-direction: column; gap: 10px; }
.config__label {
font-size: 12.5px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--muted);
}
.seg {
display: inline-flex;
flex-wrap: wrap;
gap: 8px;
}
.seg__btn {
padding: 11px 18px;
border: 1px solid var(--line-2);
border-radius: 999px;
background: #fff;
font: inherit;
font-weight: 600;
font-size: 14px;
color: var(--ink-2);
cursor: pointer;
transition: all 0.18s ease;
}
.seg__btn:hover { border-color: var(--blue-l); }
.seg__btn.is-active {
background: var(--blue);
border-color: var(--blue);
color: #fff;
box-shadow: 0 4px 12px rgba(43,127,255,0.3);
}
.seg__btn:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
.swatches { display: inline-flex; gap: 12px; flex-wrap: wrap; }
.sw {
width: 38px; height: 38px;
border-radius: 50%;
border: 2px solid var(--line-2);
cursor: pointer;
position: relative;
transition: transform 0.15s, box-shadow 0.2s;
}
.sw:hover { transform: scale(1.08); }
.sw.is-active { box-shadow: 0 0 0 3px #fff, 0 0 0 5px var(--blue); border-color: #fff; }
.sw:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; }
.sw--white { background: #f4f6fa; }
.sw--silver { background: linear-gradient(135deg, #cfd6e0, #9aa4b3); }
.sw--blue { background: linear-gradient(135deg, var(--blue-l), var(--blue-d)); }
.sw--black { background: linear-gradient(135deg, #2a3142, #0c1120); }
.sw--red { background: linear-gradient(135deg, #ff6a6a, #d4493e); }
.order__summary {
padding: clamp(30px, 4vw, 46px);
background: var(--bg-2);
border-left: 1px solid var(--line);
display: flex;
flex-direction: column;
}
.order__summary h3 { font-size: 20px; font-weight: 700; }
.summary-list {
list-style: none;
margin: 20px 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 12px;
}
.summary-list li {
display: flex;
justify-content: space-between;
gap: 12px;
font-size: 14.5px;
padding-bottom: 12px;
border-bottom: 1px dashed var(--line-2);
}
.summary-list li span:first-child { color: var(--muted); }
.summary-list li span:last-child { font-weight: 600; font-variant-numeric: tabular-nums; }
.summary-total {
display: flex;
justify-content: space-between;
align-items: baseline;
margin-top: auto;
padding-top: 18px;
border-top: 2px solid var(--line-2);
}
.summary-total span { color: var(--muted); font-weight: 600; }
.summary-total strong {
font-size: 28px;
font-weight: 800;
font-variant-numeric: tabular-nums;
}
.summary-fine { margin: 12px 0 18px; font-size: 12px; color: var(--steel); }
/* ============ FOOTER ============ */
.footer {
background: #0c1120;
color: rgba(255,255,255,0.72);
padding: clamp(48px, 7vw, 72px) 24px 28px;
}
.footer__inner {
max-width: 1180px;
margin: 0 auto;
display: grid;
grid-template-columns: 1.6fr repeat(3, 1fr);
gap: 36px;
}
.footer__brand .brand { color: #fff; }
.footer__brand p { margin-top: 14px; max-width: 280px; font-size: 14px; }
.footer__col h5 {
color: #fff;
font-size: 13px;
text-transform: uppercase;
letter-spacing: 0.06em;
margin-bottom: 14px;
}
.footer__col a {
display: block;
padding: 6px 0;
font-size: 14.5px;
color: rgba(255,255,255,0.7);
transition: color 0.2s;
}
.footer__col a:hover { color: var(--blue-l); }
.footer__bar {
max-width: 1180px;
margin: 40px auto 0;
padding-top: 22px;
border-top: 1px solid rgba(255,255,255,0.1);
display: flex;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
font-size: 13px;
color: rgba(255,255,255,0.5);
}
/* ============ TOAST ============ */
.toast {
position: fixed;
left: 50%;
bottom: 28px;
transform: translate(-50%, 24px);
z-index: 100;
padding: 13px 22px;
background: #0c1120;
color: #fff;
border-radius: 999px;
font-size: 14px;
font-weight: 600;
box-shadow: var(--shadow-2);
opacity: 0;
pointer-events: none;
transition: opacity 0.25s, transform 0.25s;
}
.toast.is-show { opacity: 1; transform: translate(-50%, 0); }
/* ============ REVEAL ============ */
.reveal {
opacity: 0;
transform: translateY(22px);
transition: opacity 0.6s ease, transform 0.6s ease;
}
.reveal.is-in { opacity: 1; transform: none; }
/* ============ RESPONSIVE ============ */
@media (max-width: 900px) {
.nav__links, .nav__actions { display: none; }
.nav__toggle { display: flex; }
.model-card, .charge-panel, .order__card, .feature-grid { grid-template-columns: 1fr; }
.card--wide { grid-column: span 1; }
.feature-grid { grid-template-columns: repeat(2, 1fr); }
.model-card__visual { min-height: 220px; }
.order__summary { border-left: none; border-top: 1px solid var(--line); }
}
@media (max-width: 640px) {
.stats { grid-template-columns: repeat(2, 1fr); }
.feature-grid { grid-template-columns: 1fr; }
.footer__inner { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 520px) {
.section { padding: 52px 18px; }
.nav__inner { padding: 0 16px; }
.hero { padding: 48px 18px 36px; }
.footer__inner { grid-template-columns: 1fr; gap: 26px; }
.footer__bar { flex-direction: column; }
.charge-sim__foot { gap: 6px; }
.spec-grid { grid-template-columns: 1fr 1fr; }
.car-stage { height: 150px; }
}
@media (prefers-reduced-motion: reduce) {
* { scroll-behavior: auto !important; }
.reveal { opacity: 1; transform: none; transition: none; }
.car-glow, .dot--live { animation: none; }
}(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-show");
clearTimeout(toastTimer);
toastTimer = setTimeout(function () {
toastEl.classList.remove("is-show");
}, 2600);
}
/* ---------- nav: scroll state + mobile toggle ---------- */
var nav = document.getElementById("nav");
var navToggle = document.getElementById("navToggle");
var mobileNav = document.getElementById("mobileNav");
function onScroll() {
if (!nav) return;
nav.classList.toggle("is-scrolled", window.scrollY > 8);
}
window.addEventListener("scroll", onScroll, { passive: true });
onScroll();
function closeMobile() {
if (!mobileNav) return;
mobileNav.hidden = true;
navToggle.setAttribute("aria-expanded", "false");
navToggle.setAttribute("aria-label", "Open menu");
}
if (navToggle && mobileNav) {
navToggle.addEventListener("click", function () {
var open = mobileNav.hidden;
mobileNav.hidden = !open;
navToggle.setAttribute("aria-expanded", String(open));
navToggle.setAttribute("aria-label", open ? "Close menu" : "Open menu");
});
mobileNav.addEventListener("click", function (e) {
if (e.target.closest("a")) closeMobile();
});
}
/* ---------- scroll reveal ---------- */
var revealEls = Array.prototype.slice.call(document.querySelectorAll("[data-reveal]"));
if ("IntersectionObserver" in window) {
var io = new IntersectionObserver(
function (entries) {
entries.forEach(function (en, i) {
if (en.isIntersecting) {
var el = en.target;
setTimeout(function () {
el.classList.add("is-in");
}, Math.min(i * 60, 240));
io.unobserve(el);
}
});
},
{ threshold: 0.12, rootMargin: "0px 0px -40px 0px" }
);
revealEls.forEach(function (el) {
io.observe(el);
});
} else {
revealEls.forEach(function (el) {
el.classList.add("is-in");
});
}
/* ---------- animated stat counters ---------- */
var counters = Array.prototype.slice.call(document.querySelectorAll("[data-count]"));
function fmt(el, val) {
var decimals = parseInt(el.getAttribute("data-decimals") || "0", 10);
var thousands = el.getAttribute("data-thousands") === "1";
var prefix = el.getAttribute("data-prefix") || "";
var suffix = el.getAttribute("data-suffix") || "";
var num = decimals ? val.toFixed(decimals) : Math.round(val).toString();
if (thousands) num = Math.round(val).toLocaleString("en-US");
el.textContent = prefix + num + suffix;
}
function animateCount(el) {
var target = parseFloat(el.getAttribute("data-count"));
var dur = 1400;
var start = performance.now();
function step(now) {
var t = Math.min((now - start) / dur, 1);
var eased = 1 - Math.pow(1 - t, 3);
fmt(el, target * eased);
if (t < 1) requestAnimationFrame(step);
else fmt(el, target);
}
requestAnimationFrame(step);
}
if ("IntersectionObserver" in window && counters.length) {
var cio = new IntersectionObserver(
function (entries) {
entries.forEach(function (en) {
if (en.isIntersecting) {
animateCount(en.target);
cio.unobserve(en.target);
}
});
},
{ threshold: 0.5 }
);
counters.forEach(function (el) {
cio.observe(el);
});
} else {
counters.forEach(function (el) {
fmt(el, parseFloat(el.getAttribute("data-count")));
});
}
/* ---------- model tabs ---------- */
var tabs = Array.prototype.slice.call(document.querySelectorAll(".model-tab"));
var panels = Array.prototype.slice.call(document.querySelectorAll(".model-card"));
tabs.forEach(function (tab) {
tab.addEventListener("click", function () {
var key = tab.getAttribute("data-model");
tabs.forEach(function (t) {
var on = t === tab;
t.classList.toggle("is-active", on);
t.setAttribute("aria-selected", String(on));
});
panels.forEach(function (p) {
var on = p.getAttribute("data-panel") === key;
p.hidden = !on;
p.classList.toggle("is-active", on);
});
});
});
// "Order X" buttons inside model cards -> sync configurator + scroll
document.querySelectorAll("[data-order]").forEach(function (btn) {
btn.addEventListener("click", function () {
var model = btn.getAttribute("data-order");
selectModelInConfig(model);
toast("Loaded " + model + " into your build");
});
});
/* ---------- charging simulator ---------- */
var ringFg = document.getElementById("ringFg");
var chargePct = document.getElementById("chargePct");
var chargeRange = document.getElementById("chargeRange");
var chargeKw = document.getElementById("chargeKw");
var chargeEta = document.getElementById("chargeEta");
var chargeState = document.getElementById("chargeState");
var chargeReset = document.getElementById("chargeReset");
var CIRC = 2 * Math.PI * 52; // ~326.7
var chargeTimer = null;
var pct = 18;
function renderCharge() {
var clamped = Math.max(0, Math.min(100, pct));
if (ringFg) ringFg.style.strokeDashoffset = String(CIRC * (1 - clamped / 100));
if (chargePct) chargePct.textContent = Math.round(clamped);
// range added since 18% baseline, ~4 mi per %
if (chargeRange) chargeRange.textContent = Math.round(Math.max(0, clamped - 18) * 4);
// kW tapers as battery fills (charge curve)
var kw = clamped < 60 ? 250 : Math.round(250 - (clamped - 60) * 4.4);
if (chargeKw) chargeKw.textContent = Math.max(40, kw);
// eta to 80%
if (chargeEta) {
if (clamped >= 80) {
chargeEta.textContent = "Done";
} else {
var mins = Math.ceil((80 - clamped) * 0.32);
var mm = String(mins % 60).padStart(2, "0");
chargeEta.textContent = "00:" + mm;
}
}
if (chargeState) chargeState.textContent = clamped >= 80 ? "Ready to drive" : "Charging";
}
function startCharge() {
if (chargeTimer) clearInterval(chargeTimer);
chargeTimer = setInterval(function () {
if (pct >= 80) {
clearInterval(chargeTimer);
chargeTimer = null;
renderCharge();
toast("Charged to 80% — ready to roll");
return;
}
pct += pct < 60 ? 1.6 : 0.9; // realistic taper
if (pct > 80) pct = 80;
renderCharge();
}, 120);
}
if (chargeReset) {
chargeReset.addEventListener("click", function () {
pct = 18;
renderCharge();
startCharge();
toast("Charging session restarted");
});
}
// kick off the sim when it enters view
var chargePanel = document.querySelector(".charge-panel");
if (chargePanel && "IntersectionObserver" in window) {
var sio = new IntersectionObserver(
function (entries) {
entries.forEach(function (en) {
if (en.isIntersecting) {
renderCharge();
startCharge();
sio.unobserve(en.target);
}
});
},
{ threshold: 0.4 }
);
sio.observe(chargePanel);
} else {
renderCharge();
}
/* ---------- configurator ---------- */
var config = {
model: { label: "Aero", price: 48990 },
pack: { label: "Standard", price: 0 },
fsd: { label: "Autopilot", price: 0 },
paint: { label: "Pearl White", price: 0 },
};
var summaryList = document.getElementById("summaryList");
var totalPrice = document.getElementById("totalPrice");
function money(n) {
return "$" + n.toLocaleString("en-US");
}
function renderSummary() {
if (!summaryList) return;
var rows = [
["Model", config.model.label, config.model.price],
["Range pack", config.pack.label, config.pack.price],
["Autonomy", config.fsd.label, config.fsd.price],
["Paint", config.paint.label, config.paint.price],
];
summaryList.innerHTML = rows
.map(function (r) {
var add = r[2] > 0 ? "+" + money(r[2]) : "Included";
return (
'<li><span>' + r[0] + ": " + r[1] + "</span><span>" + add + "</span></li>"
);
})
.join("");
var total =
config.model.price + config.pack.price + config.fsd.price + config.paint.price;
if (totalPrice) totalPrice.textContent = money(total);
}
function setOption(group, btn) {
config[group] = {
label: btn.getAttribute("data-val"),
price: parseInt(btn.getAttribute("data-price") || "0", 10),
};
var siblings = document.querySelectorAll('[data-cfg="' + group + '"]');
siblings.forEach(function (s) {
s.classList.toggle("is-active", s === btn);
});
renderSummary();
}
document.querySelectorAll("[data-cfg]").forEach(function (btn) {
btn.addEventListener("click", function () {
setOption(btn.getAttribute("data-cfg"), btn);
});
});
// sync configurator model when chosen from model cards
function selectModelInConfig(modelName) {
var btn = document.querySelector('[data-cfg="model"][data-val="' + modelName + '"]');
if (btn) setOption("model", btn);
var order = document.getElementById("order");
if (order) order.scrollIntoView({ behavior: "smooth", block: "start" });
}
var reserveBtn = document.getElementById("reserveBtn");
if (reserveBtn) {
reserveBtn.addEventListener("click", function () {
toast(
"Reservation placed — Voltway " +
config.model.label +
" in " +
config.paint.label
);
});
}
renderSummary();
})();<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Voltway — Electric Vehicles</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&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="style.css" />
</head>
<body>
<!-- ============ NAV ============ -->
<header class="nav" id="nav">
<div class="nav__inner">
<a class="brand" href="#top" aria-label="Voltway home">
<span class="brand__mark" aria-hidden="true">
<svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2 4 14h7l-1 8 9-12h-7l1-8Z"/></svg>
</span>
<span class="brand__name">Voltway</span>
</a>
<nav class="nav__links" aria-label="Primary">
<a href="#models">Models</a>
<a href="#charging">Charging</a>
<a href="#features">Performance</a>
<a href="#order">Order</a>
</nav>
<div class="nav__actions">
<a class="btn btn--ghost" href="#order">Find a center</a>
<a class="btn btn--solid" href="#order">Order now</a>
</div>
<button class="nav__toggle" id="navToggle" aria-label="Open menu" aria-expanded="false" aria-controls="mobileNav">
<span></span><span></span><span></span>
</button>
</div>
<div class="mobile-nav" id="mobileNav" hidden>
<a href="#models">Models</a>
<a href="#charging">Charging</a>
<a href="#features">Performance</a>
<a href="#order">Order</a>
<a class="btn btn--solid btn--block" href="#order">Order now</a>
</div>
</header>
<main id="top">
<!-- ============ HERO ============ -->
<section class="hero" id="hero">
<div class="hero__bg" aria-hidden="true">
<div class="orb orb--1"></div>
<div class="orb orb--2"></div>
<div class="grid-lines"></div>
</div>
<div class="hero__inner">
<p class="eyebrow reveal" data-reveal>New · 2026 Lineup</p>
<h1 class="hero__title reveal" data-reveal>
Drive the<br /><span class="grad">current.</span>
</h1>
<p class="hero__sub reveal" data-reveal>
All-electric, software-defined vehicles built for the long road. Zero emissions,
industry-leading range, and a charging network that goes everywhere you do.
</p>
<div class="hero__cta reveal" data-reveal>
<a class="btn btn--solid btn--lg" href="#order">Configure yours</a>
<a class="btn btn--ghost btn--lg" href="#models">Explore models</a>
</div>
<div class="hero__car reveal" data-reveal aria-hidden="true">
<div class="car-stage">
<div class="car-body"></div>
<div class="car-glow"></div>
<div class="car-shadow"></div>
</div>
</div>
<div class="stats reveal" data-reveal>
<div class="stat">
<div class="stat__num" data-count="402" data-suffix=" mi">0</div>
<div class="stat__label">EPA range</div>
</div>
<div class="stat">
<div class="stat__num" data-count="2.9" data-decimals="1" data-suffix="s">0</div>
<div class="stat__label">0–60 mph</div>
</div>
<div class="stat">
<div class="stat__num" data-count="15" data-prefix="+" data-suffix=" mi/min">0</div>
<div class="stat__label">Peak charge</div>
</div>
<div class="stat">
<div class="stat__num" data-count="60000" data-thousands="1" data-prefix="$">0</div>
<div class="stat__label">Supercharge points</div>
</div>
</div>
</div>
</section>
<!-- ============ MODELS ============ -->
<section class="section models" id="models">
<div class="section__head reveal" data-reveal>
<p class="kicker">The lineup</p>
<h2>Three vehicles. One platform.</h2>
<p class="lead">Every Voltway shares the same 800-volt architecture and over-the-air software. Pick the silhouette.</p>
</div>
<div class="model-tabs reveal" data-reveal role="tablist" aria-label="Model selector">
<button class="model-tab is-active" role="tab" aria-selected="true" data-model="aero">Aero</button>
<button class="model-tab" role="tab" aria-selected="false" data-model="range">Range</button>
<button class="model-tab" role="tab" aria-selected="false" data-model="haul">Haul</button>
</div>
<div class="model-stage reveal" data-reveal>
<div class="model-card is-active" data-panel="aero">
<div class="model-card__visual visual--aero"><span class="model-card__badge">Sedan</span></div>
<div class="model-card__body">
<h3>Voltway Aero</h3>
<p class="model-card__tag">The aerodynamic flagship sedan.</p>
<ul class="spec-grid">
<li><b>358 mi</b><span>Range</span></li>
<li><b>3.1s</b><span>0–60</span></li>
<li><b>155 mph</b><span>Top speed</span></li>
<li><b>$48,990</b><span>From</span></li>
</ul>
<a class="btn btn--solid" href="#order" data-order="Aero">Order Aero</a>
</div>
</div>
<div class="model-card" data-panel="range" hidden>
<div class="model-card__visual visual--range"><span class="model-card__badge">SUV</span></div>
<div class="model-card__body">
<h3>Voltway Range</h3>
<p class="model-card__tag">Seven seats. The longest legs in the family.</p>
<ul class="spec-grid">
<li><b>402 mi</b><span>Range</span></li>
<li><b>3.8s</b><span>0–60</span></li>
<li><b>149 mph</b><span>Top speed</span></li>
<li><b>$61,490</b><span>From</span></li>
</ul>
<a class="btn btn--solid" href="#order" data-order="Range">Order Range</a>
</div>
</div>
<div class="model-card" data-panel="haul" hidden>
<div class="model-card__visual visual--haul"><span class="model-card__badge">Truck</span></div>
<div class="model-card__body">
<h3>Voltway Haul</h3>
<p class="model-card__tag">11,000 lb tow rating. Built like a tool.</p>
<ul class="spec-grid">
<li><b>340 mi</b><span>Range</span></li>
<li><b>2.9s</b><span>0–60</span></li>
<li><b>11k lb</b><span>Towing</span></li>
<li><b>$72,990</b><span>From</span></li>
</ul>
<a class="btn btn--solid" href="#order" data-order="Haul">Order Haul</a>
</div>
</div>
</div>
</section>
<!-- ============ CHARGING ============ -->
<section class="section charging" id="charging">
<div class="section__head reveal" data-reveal>
<p class="kicker">Voltway Network</p>
<h2>Charge in minutes, not hours.</h2>
<p class="lead">60,000+ fast-charge stalls across the country, planned automatically into every route.</p>
</div>
<div class="charge-panel reveal" data-reveal>
<div class="charge-sim">
<div class="charge-sim__head">
<span class="dot dot--live"></span>
<span id="chargeState">Charging</span>
<span class="charge-sim__stall">Stall 07 · 250 kW</span>
</div>
<div class="charge-ring" role="img" aria-label="Battery charge level">
<svg viewBox="0 0 120 120" width="180" height="180">
<circle cx="60" cy="60" r="52" class="ring-bg" />
<circle cx="60" cy="60" r="52" class="ring-fg" id="ringFg" />
</svg>
<div class="charge-ring__pct"><span id="chargePct">18</span><i>%</i></div>
</div>
<div class="charge-sim__foot">
<div><b id="chargeRange">112</b><span>mi added</span></div>
<div><b id="chargeKw">248</b><span>kW</span></div>
<div><b id="chargeEta">14:20</b><span>to 80%</span></div>
</div>
<button class="btn btn--ghost btn--sm" id="chargeReset">Restart sim</button>
</div>
<div class="charge-feats">
<article class="feat">
<span class="feat__ico">⚡</span>
<h4>250 kW peak</h4>
<p>Add up to 200 miles of range in 15 minutes at a V4 Supercharger.</p>
</article>
<article class="feat">
<span class="feat__ico">🗺️</span>
<h4>Trip planner</h4>
<p>Navigation preconditions the battery and routes you stall-to-stall, automatically.</p>
</article>
<article class="feat">
<span class="feat__ico">🔌</span>
<h4>Plug & charge</h4>
<p>Pull up, plug in, drive off. Billing handled silently in the background.</p>
</article>
</div>
</div>
</section>
<!-- ============ PERFORMANCE / AUTONOMY ============ -->
<section class="section features" id="features">
<div class="section__head reveal" data-reveal>
<p class="kicker">Performance & autonomy</p>
<h2>Hardware ahead of the road.</h2>
</div>
<div class="feature-grid">
<article class="card card--wide reveal" data-reveal>
<h3>Full Self-Driving (Supervised)</h3>
<p>Eight cameras, a 360° vision stack, and the V5 inference computer. Navigate on-ramp to off-ramp with the driver supervising.</p>
<div class="chips">
<span class="chip">8 cameras</span>
<span class="chip">360° vision</span>
<span class="chip">OTA updates</span>
</div>
</article>
<article class="card reveal" data-reveal>
<h3>Dual-motor AWD</h3>
<p>Independent front and rear motors deliver torque vectoring and instant grip in any weather.</p>
</article>
<article class="card reveal" data-reveal>
<h3>Glass roof</h3>
<p>A single pane of UV-tinted glass from windshield to trunk for an airy, panoramic cabin.</p>
</article>
<article class="card reveal" data-reveal>
<h3>15" center display</h3>
<p>A responsive touchscreen running the full Voltway OS, gaming, streaming, and navigation.</p>
</article>
<article class="card card--accent reveal" data-reveal>
<h3>5-star safety</h3>
<p>Lowest rollover risk in class and a rigid battery floor that lowers the center of gravity.</p>
</article>
</div>
</section>
<!-- ============ ORDER / CTA ============ -->
<section class="section order" id="order">
<div class="order__card reveal" data-reveal>
<div class="order__copy">
<p class="kicker">Configure</p>
<h2>Build your Voltway.</h2>
<p class="lead">Reserve today with a fully refundable deposit. Estimated delivery 4–8 weeks.</p>
<div class="config">
<div class="config__row">
<span class="config__label">Model</span>
<div class="seg" role="group" aria-label="Choose model">
<button class="seg__btn is-active" data-cfg="model" data-val="Aero" data-price="48990">Aero</button>
<button class="seg__btn" data-cfg="model" data-val="Range" data-price="61490">Range</button>
<button class="seg__btn" data-cfg="model" data-val="Haul" data-price="72990">Haul</button>
</div>
</div>
<div class="config__row">
<span class="config__label">Range pack</span>
<div class="seg" role="group" aria-label="Choose range pack">
<button class="seg__btn is-active" data-cfg="pack" data-val="Standard" data-price="0">Standard</button>
<button class="seg__btn" data-cfg="pack" data-val="Long Range" data-price="6000">Long Range</button>
</div>
</div>
<div class="config__row">
<span class="config__label">Autonomy</span>
<div class="seg" role="group" aria-label="Choose autonomy">
<button class="seg__btn is-active" data-cfg="fsd" data-val="Autopilot" data-price="0">Autopilot</button>
<button class="seg__btn" data-cfg="fsd" data-val="FSD" data-price="8000">Full Self-Driving</button>
</div>
</div>
<div class="config__row config__row--color">
<span class="config__label">Paint</span>
<div class="swatches" role="group" aria-label="Choose paint">
<button class="sw sw--white is-active" data-cfg="paint" data-val="Pearl White" data-price="0" aria-label="Pearl White"></button>
<button class="sw sw--silver" data-cfg="paint" data-val="Liquid Silver" data-price="1500" aria-label="Liquid Silver"></button>
<button class="sw sw--blue" data-cfg="paint" data-val="Voltage Blue" data-price="1500" aria-label="Voltage Blue"></button>
<button class="sw sw--black" data-cfg="paint" data-val="Obsidian" data-price="1000" aria-label="Obsidian"></button>
<button class="sw sw--red" data-cfg="paint" data-val="Signal Red" data-price="2000" aria-label="Signal Red"></button>
</div>
</div>
</div>
</div>
<aside class="order__summary" aria-live="polite">
<h3>Your build</h3>
<ul class="summary-list" id="summaryList"></ul>
<div class="summary-total">
<span>Est. price</span>
<strong id="totalPrice">$48,990</strong>
</div>
<p class="summary-fine">Excludes taxes, fees, and incentives. Deposit fully refundable.</p>
<button class="btn btn--solid btn--block btn--lg" id="reserveBtn">Reserve now</button>
</aside>
</div>
</section>
</main>
<!-- ============ FOOTER ============ -->
<footer class="footer">
<div class="footer__inner">
<div class="footer__brand">
<span class="brand">
<span class="brand__mark" aria-hidden="true">
<svg viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M13 2 4 14h7l-1 8 9-12h-7l1-8Z"/></svg>
</span>
<span class="brand__name">Voltway</span>
</span>
<p>The current that moves you forward. Fictional EV maker, real-feeling demo.</p>
</div>
<nav class="footer__col" aria-label="Vehicles">
<h5>Vehicles</h5>
<a href="#models">Aero</a><a href="#models">Range</a><a href="#models">Haul</a>
</nav>
<nav class="footer__col" aria-label="Charging">
<h5>Charging</h5>
<a href="#charging">Network</a><a href="#charging">Home charging</a><a href="#charging">Trip planner</a>
</nav>
<nav class="footer__col" aria-label="Company">
<h5>Company</h5>
<a href="#top">About</a><a href="#order">Find a center</a><a href="#order">Careers</a>
</nav>
</div>
<div class="footer__bar">
<span>© 2026 Voltway Motors (fictional). All rights reserved.</span>
<span>Privacy · Terms · Recalls</span>
</div>
</footer>
<div class="toast" id="toast" role="status" aria-live="polite"></div>
<script src="script.js"></script>
</body>
</html>EV Dealership Landing
A complete, single-screen marketing landing for Voltway, a fictional electric-vehicle brand. The design leans into a futuristic, minimal language: a near-white canvas, generous whitespace, an Inter type scale, and a single electric-blue accent doing all the heavy lifting. The hero opens with a CSS-rendered car silhouette, glowing orbs over a faint grid, and four headline stats — EPA range, 0–60, peak charge rate, and network size — that count up the first time they scroll into view, all rendered with tabular figures.
The page is genuinely interactive. The model section uses a pill tab switcher to swap between the Aero sedan, Range SUV, and Haul truck, each with its own spec grid and gradient vehicle plate. The charging section runs a live simulator: an animated SVG ring fills along a realistic charge curve, the kW rate tapers as the pack fills, and miles-added and time-to-80% update in real time, with a restart control. Down in the order section, a build configurator lets you pick model, range pack, autonomy package, and paint — every choice re-prices a live summary panel, and the model cards can push a selection straight into it.
Everything is vanilla: a small toast() helper for confirmations, an IntersectionObserver for scroll reveal and lazy-started animations, a sticky nav that gains a border on scroll, and an accessible mobile menu. It degrades gracefully without IntersectionObserver, respects prefers-reduced-motion, and stays usable down to 360px with a mobile-first layout, keyboard-reachable controls, and WCAG AA contrast.
Illustrative UI only — fictional shop/dealership, not a real service system.