← back to Model Arena
data/artifacts/15bc10e7ee25/grok.html
831 lines
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Grandmillennial — Designer Wallcoverings</title>
<style>
:root {
--bg: #f3efe6;
--surface: #faf7f0;
--card: #fffcf6;
--ink: #1c1a17;
--muted: #6e675c;
--line: #d9d0c0;
--accent: #8b3a3a;
--accent-soft: #c4a484;
--sage: #6b7a5a;
--blush: #d4a5a5;
--navy: #2c3a4a;
--gold: #b8956c;
--shadow: 0 18px 48px rgba(28, 26, 23, 0.10), 0 4px 12px rgba(28, 26, 23, 0.06);
--radius: 18px;
--ease: cubic-bezier(.22, 1, .36, 1);
--font-display: 'Didot', 'Bodoni MT', 'Playfair Display', Georgia, serif;
--font-body: Georgia, 'Times New Roman', serif;
--font-ui: -apple-system, 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
}
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body {
height: 100%;
background: var(--bg);
color: var(--ink);
font-family: var(--font-body);
-webkit-font-smoothing: antialiased;
}
body {
display: flex;
flex-direction: column;
min-height: 100vh;
overflow-x: hidden;
}
/* ——— Header ——— */
header.app-header {
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
padding: 1.1rem 1.5rem;
background: var(--bg);
border-bottom: 1px solid var(--line);
position: relative;
z-index: 10;
}
header.app-header .wordmark {
font-family: var(--font-display);
font-size: 13px;
font-weight: 400;
letter-spacing: 0.28em;
text-transform: uppercase;
color: #1c1a17;
line-height: 1;
}
/* ——— Stage ——— */
.stage {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 1.25rem 1rem 1.5rem;
gap: 1.1rem;
min-height: 0;
}
.carousel {
width: min(380px, 100%);
aspect-ratio: 4 / 5;
position: relative;
border-radius: var(--radius);
overflow: hidden;
box-shadow: var(--shadow);
background: var(--card);
touch-action: pan-y;
user-select: none;
}
.track {
display: flex;
height: 100%;
width: 100%;
transition: transform 0.55s var(--ease);
will-change: transform;
}
.slide {
flex: 0 0 100%;
width: 100%;
height: 100%;
position: relative;
display: flex;
flex-direction: column;
overflow: hidden;
}
/* ——— Cover ——— */
.slide-cover {
background:
radial-gradient(ellipse 80% 60% at 50% 100%, rgba(184, 149, 108, 0.12), transparent 70%),
linear-gradient(165deg, #faf7f0 0%, #efe8d8 55%, #e8dfce 100%);
align-items: center;
justify-content: center;
text-align: center;
padding: 2rem;
}
.cover-ornament {
width: 64px;
height: 64px;
margin-bottom: 1.5rem;
opacity: 0.85;
}
.cover-kicker {
font-family: var(--font-ui);
font-size: 10px;
letter-spacing: 0.22em;
text-transform: uppercase;
color: var(--muted);
margin-bottom: 0.85rem;
}
.cover-title {
font-family: var(--font-display);
font-size: clamp(42px, 12vw, 56px);
font-weight: 400;
letter-spacing: -0.03em;
line-height: 1.05;
color: var(--ink);
margin-bottom: 0.75rem;
}
.cover-rule {
width: 48px;
height: 1px;
background: var(--gold);
margin: 0 auto 0.9rem;
}
.cover-sub {
font-family: var(--font-body);
font-size: 14px;
font-style: italic;
color: var(--muted);
line-height: 1.5;
max-width: 24ch;
}
/* ——— Lookbook cards ——— */
.slide-look {
background: var(--card);
flex-direction: column;
}
.look-visual {
flex: 0 0 56%;
position: relative;
overflow: hidden;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0;
border-bottom: 1px solid var(--line);
}
.swatch {
position: relative;
overflow: hidden;
min-height: 0;
}
.swatch-label {
position: absolute;
bottom: 8px;
left: 8px;
font-family: var(--font-ui);
font-size: 8px;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--surface);
background: rgba(28, 26, 23, 0.55);
padding: 3px 7px;
border-radius: 2px;
backdrop-filter: blur(4px);
}
.room {
position: relative;
overflow: hidden;
min-height: 0;
}
.look-copy {
flex: 1 1 auto;
display: flex;
flex-direction: column;
justify-content: center;
gap: 0.45rem;
padding: 1.15rem 1.35rem 1.25rem;
min-height: 0;
overflow: hidden;
}
.look-copy .eyebrow {
font-family: var(--font-ui);
font-size: 9px;
letter-spacing: 0.2em;
text-transform: uppercase;
color: var(--accent);
flex-shrink: 0;
}
.look-copy h2 {
font-family: var(--font-display);
font-size: clamp(22px, 5.5vw, 28px);
font-weight: 400;
letter-spacing: -0.02em;
line-height: 1.15;
color: var(--ink);
flex-shrink: 0;
}
.look-copy p {
font-family: var(--font-body);
font-size: 13px;
line-height: 1.55;
color: var(--muted);
font-style: italic;
max-width: 36ch;
flex-shrink: 1;
overflow: hidden;
}
/* ——— CTA ——— */
.slide-cta {
background:
radial-gradient(ellipse 90% 70% at 50% 0%, rgba(139, 58, 58, 0.08), transparent 60%),
linear-gradient(180deg, #faf7f0 0%, #efe6d4 100%);
align-items: center;
justify-content: center;
text-align: center;
padding: 2.5rem 2rem;
}
.cta-kicker {
font-family: var(--font-ui);
font-size: 10px;
letter-spacing: 0.22em;
text-transform: uppercase;
color: var(--muted);
margin-bottom: 1rem;
}
.cta-title {
font-family: var(--font-display);
font-size: clamp(28px, 8vw, 36px);
font-weight: 400;
letter-spacing: -0.02em;
line-height: 1.15;
color: var(--ink);
margin-bottom: 0.85rem;
}
.cta-body {
font-size: 14px;
line-height: 1.6;
color: var(--muted);
max-width: 28ch;
margin: 0 auto 1.75rem;
font-style: italic;
}
.cta-btn {
display: inline-block;
font-family: var(--font-ui);
font-size: 11px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--surface);
background: var(--ink);
padding: 0.95rem 1.75rem;
border: none;
border-radius: 2px;
cursor: pointer;
transition: transform 0.35s var(--ease), background 0.25s ease;
}
.cta-btn:hover { background: var(--accent); transform: translateY(-1px); }
.cta-btn:active { transform: translateY(0); }
.cta-fine {
margin-top: 1.25rem;
font-family: var(--font-ui);
font-size: 10px;
letter-spacing: 0.12em;
color: var(--muted);
text-transform: uppercase;
}
/* ——— Dots + nav ——— */
.controls {
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
width: min(380px, 100%);
}
.nav-btn {
width: 36px;
height: 36px;
border-radius: 50%;
border: 1px solid var(--line);
background: var(--surface);
color: var(--ink);
cursor: pointer;
display: grid;
place-items: center;
transition: background 0.25s ease, border-color 0.25s ease;
flex-shrink: 0;
}
.nav-btn:hover { background: var(--card); border-color: var(--gold); }
.nav-btn:disabled { opacity: 0.35; cursor: default; }
.nav-btn svg { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 1.5; }
.dots {
display: flex;
gap: 7px;
align-items: center;
}
.dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--line);
border: none;
padding: 0;
cursor: pointer;
transition: background 0.3s var(--ease), transform 0.3s var(--ease);
}
.dot[aria-current="true"] {
background: var(--ink);
transform: scale(1.25);
}
.slide-count {
font-family: var(--font-ui);
font-size: 10px;
letter-spacing: 0.14em;
color: var(--muted);
text-align: center;
min-width: 3.5rem;
}
/* ============================================
PATTERN + ROOM DRAWINGS (CSS / SVG only)
============================================ */
/* --- Slide 1: Chintz Rose --- */
.pat-chintz {
background-color: #f2e6d8;
background-image:
radial-gradient(ellipse 14px 10px at 30% 35%, #c45c5c 0 40%, transparent 42%),
radial-gradient(ellipse 10px 8px at 38% 42%, #d4a5a5 0 45%, transparent 48%),
radial-gradient(ellipse 8px 12px at 22% 48%, #6b7a5a 0 40%, transparent 43%),
radial-gradient(ellipse 12px 9px at 70% 60%, #b84a4a 0 38%, transparent 42%),
radial-gradient(ellipse 9px 7px at 78% 68%, #c4a484 0 42%, transparent 46%),
radial-gradient(ellipse 7px 11px at 62% 72%, #6b7a5a 0 38%, transparent 42%),
radial-gradient(ellipse 11px 8px at 50% 20%, #a84848 0 36%, transparent 40%),
radial-gradient(ellipse 6px 9px at 55% 28%, #7a8a68 0 40%, transparent 44%),
radial-gradient(ellipse 10px 8px at 18% 78%, #c45c5c 0 38%, transparent 42%),
radial-gradient(ellipse 8px 6px at 85% 25%, #d4a5a5 0 40%, transparent 45%),
radial-gradient(circle 3px at 45% 55%, #8b3a3a 0 50%, transparent 55%),
radial-gradient(circle 2.5px at 65% 40%, #6b7a5a 0 50%, transparent 55%),
radial-gradient(circle 2px at 25% 25%, #b8956c 0 50%, transparent 55%);
background-size: 120px 120px, 120px 120px, 120px 120px, 120px 120px, 120px 120px, 120px 120px, 120px 120px, 120px 120px, 120px 120px, 120px 120px, 60px 60px, 80px 80px, 70px 70px;
}
.room-chintz {
background: linear-gradient(180deg, #e8dfd0 0%, #ddd2c0 100%);
position: relative;
}
.room-chintz .wall {
position: absolute; inset: 0 0 32% 0;
background-color: #f0e4d4;
background-image:
radial-gradient(ellipse 7px 5px at 25% 30%, rgba(196, 92, 92, 0.55) 0 40%, transparent 42%),
radial-gradient(ellipse 5px 7px at 40% 50%, rgba(107, 122, 90, 0.5) 0 38%, transparent 42%),
radial-gradient(ellipse 6px 4px at 70% 25%, rgba(184, 74, 74, 0.5) 0 40%, transparent 44%),
radial-gradient(ellipse 5px 6px at 55% 70%, rgba(212, 165, 165, 0.45) 0 40%, transparent 44%),
radial-gradient(ellipse 4px 5px at 85% 55%, rgba(107, 122, 90, 0.4) 0 38%, transparent 42%);
background-size: 55px 55px;
}
.room-chintz .wainscot {
position: absolute; left: 0; right: 0; bottom: 28%; height: 8%;
background: linear-gradient(180deg, #c9bba5, #b8a88e);
border-top: 2px solid #a89878;
}
.room-chintz .floor {
position: absolute; left: 0; right: 0; bottom: 0; height: 28%;
background:
repeating-linear-gradient(90deg, #c4a882 0 18%, #b89870 18% 20%, #c4a882 20% 38%, #b09068 38% 40%);
background-size: 40px 100%;
}
.room-chintz .sofa {
position: absolute; left: 12%; right: 12%; bottom: 22%; height: 28%;
background: #2c3a4a;
border-radius: 6px 6px 2px 2px;
box-shadow: inset 0 8px 0 #3a4a5c;
}
.room-chintz .sofa::before {
content: '';
position: absolute; left: 8%; right: 8%; top: -18%; height: 30%;
background: #8b3a3a;
border-radius: 3px;
opacity: 0.9;
}
.room-chintz .sofa::after {
content: '';
position: absolute; left: 15%; width: 22%; top: -8%; height: 35%;
background: #d4a5a5;
border-radius: 2px;
box-shadow: 30px 2px 0 #6b7a5a;
}
.room-chintz .lamp {
position: absolute; right: 14%; bottom: 48%; width: 4%; height: 22%;
background: #b8956c;
border-radius: 1px;
}
.room-chintz .lamp::before {
content: '';
position: absolute; left: 50%; transform: translateX(-50%); bottom: 100%;
width: 280%; height: 55%;
background: #f5f0e6;
clip-path: polygon(15% 100%, 85% 100%, 100% 0, 0 0);
}
.room-chintz .frame {
position: absolute; left: 18%; top: 12%; width: 22%; height: 20%;
border: 2px solid #b8956c;
background: #e8dcc8;
box-shadow: inset 0 0 0 3px #f0e8d8;
}
/* --- Slide 2: Ribbon Trellis --- */
.pat-trellis {
background-color: #f7f3ea;
background-image:
linear-gradient(45deg, transparent 46%, #8b9a7a 46% 48%, transparent 48% 52%, #8b9a7a 52% 54%, transparent 54%),
linear-gradient(-45deg, transparent 46%, #8b9a7a 46% 48%, transparent 48% 52%, #8b9a7a 52% 54%, transparent 54%),
radial-gradient(circle 5px at 50% 50%, #c45c6a 0 55%, transparent 58%);
background-size: 48px 48px, 48px 48px, 48px 48px;
}
.room-trellis {
background: #e6e0d2;
position: relative;
}
.room-trellis .wall {
position: absolute; inset: 0 0 30% 0;
background-color: #f4f0e6;
background-image:
linear-gradient(45deg, transparent 46%, rgba(107, 122, 90, 0.35) 46% 48%, transparent 48% 52%, rgba(107, 122, 90, 0.35) 52% 54%, transparent 54%),
linear-gradient(-45deg, transparent 46%, rgba(107, 122, 90, 0.35) 46% 48%, transparent 48% 52%, rgba(107, 122, 90, 0.35) 52% 54%, transparent 54%),
radial-gradient(circle 2.5px at 50% 50%, rgba(196, 92, 106, 0.5) 0 55%, transparent 58%);
background-size: 22px 22px;
}
.room-trellis .chair-rail {
position: absolute; left: 0; right: 0; bottom: 30%; height: 3px;
background: #a89878;
}
.room-trellis .floor {
position: absolute; left: 0; right: 0; bottom: 0; height: 30%;
background: linear-gradient(180deg, #c8b89a, #b8a688);
}
.room-trellis .table {
position: absolute; left: 22%; right: 22%; bottom: 24%; height: 6%;
background: #5a4030;
border-radius: 1px;
box-shadow: 0 4px 0 #4a3428;
}
.room-trellis .table::before {
content: '';
position: absolute; left: 8%; right: 8%; bottom: 100%; height: 180%;
background: radial-gradient(ellipse at 50% 80%, #e8d8c0 0 40%, transparent 42%),
radial-gradient(circle at 30% 40%, #c45c6a 0 12%, transparent 14%),
radial-gradient(circle at 55% 35%, #6b7a5a 0 10%, transparent 12%),
radial-gradient(circle at 70% 50%, #d4a5a5 0 8%, transparent 10%),
#f0e8d8;
border-radius: 40% 40% 8% 8%;
border: 1px solid #d0c0a8;
}
.room-trellis .table::after {
content: '';
position: absolute; left: 42%; width: 16%; top: 100%; height: 280%;
background: #5a4030;
clip-path: polygon(20% 0, 80% 0, 100% 100%, 0 100%);
}
.room-trellis .curtain-l,
.room-trellis .curtain-r {
position: absolute; top: 0; width: 14%; height: 70%;
background: linear-gradient(90deg, #8b3a3a, #a04848 40%, #8b3a3a);
opacity: 0.85;
}
.room-trellis .curtain-l { left: 0; border-radius: 0 0 40% 0; }
.room-trellis .curtain-r { right: 0; border-radius: 0 0 0 40%; background: linear-gradient(-90deg, #8b3a3a, #a04848 40%, #8b3a3a); }
/* --- Slide 3: Chinoiserie Toile --- */
.pat-toile {
background-color: #eef1f0;
background-image:
radial-gradient(ellipse 18px 28px at 28% 40%, transparent 40%, #3a5a6a 41% 43%, transparent 44%),
radial-gradient(ellipse 12px 20px at 72% 55%, transparent 38%, #3a5a6a 39% 41%, transparent 42%),
radial-gradient(circle 8px at 50% 22%, transparent 50%, #3a5a6a 51% 58%, transparent 60%),
radial-gradient(ellipse 6px 14px at 35% 70%, #3a5a6a 0 30%, transparent 32%),
radial-gradient(ellipse 5px 12px at 65% 30%, #3a5a6a 0 28%, transparent 30%),
radial-gradient(ellipse 20px 6px at 50% 80%, transparent 40%, #3a5a6a 41% 44%, transparent 45%),
radial-gradient(circle 3px at 20% 25%, #3a5a6a 0 50%, transparent 55%),
radial-gradient(circle 2.5px at 80% 75%, #3a5a6a 0 50%, transparent 55%);
background-size: 100px 110px;
}
.room-toile {
background: #dfe4e2;
position: relative;
}
.room-toile .wall {
position: absolute; inset: 0 0 28% 0;
background-color: #e8eef0;
background-image:
radial-gradient(ellipse 9px 14px at 30% 35%, transparent 40%, rgba(44, 58, 74, 0.35) 41% 44%, transparent 45%),
radial-gradient(ellipse 6px 10px at 70% 55%, transparent 38%, rgba(44, 58, 74, 0.3) 39% 42%, transparent 43%),
radial-gradient(circle 4px at 50% 20%, transparent 48%, rgba(44, 58, 74, 0.3) 50% 58%, transparent 60%),
radial-gradient(ellipse 3px 7px at 40% 70%, rgba(44, 58, 74, 0.28) 0 30%, transparent 32%);
background-size: 48px 52px;
}
.room-toile .floor {
position: absolute; left: 0; right: 0; bottom: 0; height: 28%;
background:
linear-gradient(180deg, rgba(28,26,23,0.06), transparent 30%),
repeating-linear-gradient(90deg, #b0a890 0 12px, #a89878 12px 14px);
}
.room-toile .bed {
position: absolute; left: 10%; right: 10%; bottom: 18%; height: 32%;
background: #f5f2ea;
border-radius: 4px 4px 0 0;
box-shadow: 0 -2px 0 #d8d0c0;
}
.room-toile .bed::before {
content: '';
position: absolute; left: 0; right: 0; top: 0; height: 35%;
background: linear-gradient(180deg, #2c3a4a, #3a4a5c);
border-radius: 4px 4px 0 0;
}
.room-toile .bed::after {
content: '';
position: absolute; left: 8%; right: 8%; top: 28%; height: 18%;
background: #c45c5c;
border-radius: 2px;
opacity: 0.85;
box-shadow: 0 8px 0 0 #d4c8b0;
}
.room-toile .headboard {
position: absolute; left: 18%; right: 18%; bottom: 48%; height: 22%;
background: #2c3a4a;
border-radius: 50% 50% 0 0 / 60% 60% 0 0;
border: 2px solid #b8956c;
border-bottom: none;
}
.room-toile .nightstand {
position: absolute; right: 6%; bottom: 26%; width: 12%; height: 14%;
background: #5a4030;
border-radius: 1px;
}
.room-toile .nightstand::before {
content: '';
position: absolute; left: 20%; right: 20%; bottom: 100%; height: 70%;
background: #e8e0d0;
border-radius: 50% 50% 2px 2px;
border: 1px solid #c8b8a0;
}
/* cover monogram SVG sizing */
.cover-ornament svg { width: 100%; height: 100%; }
</style>
</head>
<body>
<header class="app-header">
<div class="wordmark">Designer Wallcoverings</div>
</header>
<main class="stage">
<div class="carousel" id="carousel" aria-roledescription="carousel" aria-label="Grandmillennial lookbook">
<div class="track" id="track">
<!-- COVER -->
<section class="slide slide-cover" aria-label="Cover">
<div class="cover-ornament" aria-hidden="true">
<svg viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="32" cy="32" r="30" stroke="#b8956c" stroke-width="0.75"/>
<circle cx="32" cy="32" r="26" stroke="#b8956c" stroke-width="0.5" stroke-dasharray="2 3"/>
<path d="M32 14c-2 6-8 10-8 18 0 6 3.5 10 8 12 4.5-2 8-6 8-12 0-8-6-12-8-18z" fill="#8b3a3a" opacity="0.85"/>
<path d="M24 30c4 2 8 2 16 0" stroke="#6b7a5a" stroke-width="1.2" stroke-linecap="round"/>
<path d="M26 36c3 1.5 6 1.5 12 0" stroke="#6b7a5a" stroke-width="1" stroke-linecap="round"/>
<circle cx="32" cy="22" r="2" fill="#c4a484"/>
</svg>
</div>
<p class="cover-kicker">Lookbook No. 07</p>
<h1 class="cover-title">Grand­millennial</h1>
<div class="cover-rule"></div>
<p class="cover-sub">Heirloom florals, ribbon trellis & chinoiserie — collected, not curated.</p>
</section>
<!-- SLIDE 1 — Chintz -->
<section class="slide slide-look" aria-label="English Chintz">
<div class="look-visual">
<div class="swatch pat-chintz">
<span class="swatch-label">Pattern</span>
</div>
<div class="room room-chintz">
<div class="wall"></div>
<div class="frame"></div>
<div class="wainscot"></div>
<div class="floor"></div>
<div class="sofa"></div>
<div class="lamp"></div>
<span class="swatch-label">Vignette</span>
</div>
</div>
<div class="look-copy">
<span class="eyebrow">01 — English Chintz</span>
<h2>Rose & Vine</h2>
<p>Pair cabbage-rose chintz with navy velvet and a single brass lamp — grandmother’s garden, edited.</p>
</div>
</section>
<!-- SLIDE 2 — Trellis -->
<section class="slide slide-look" aria-label="Ribbon Trellis">
<div class="look-visual">
<div class="swatch pat-trellis">
<span class="swatch-label">Pattern</span>
</div>
<div class="room room-trellis">
<div class="wall"></div>
<div class="curtain-l"></div>
<div class="curtain-r"></div>
<div class="chair-rail"></div>
<div class="floor"></div>
<div class="table"></div>
<span class="swatch-label">Vignette</span>
</div>
</div>
<div class="look-copy">
<span class="eyebrow">02 — Ribbon Trellis</span>
<h2>Lattice & Bow</h2>
<p>Sage lattice with coral knots behind a mahogany pedestal — structure that still feels soft.</p>
</div>
</section>
<!-- SLIDE 3 — Toile -->
<section class="slide slide-look" aria-label="Chinoiserie Toile">
<div class="look-visual">
<div class="swatch pat-toile">
<span class="swatch-label">Pattern</span>
</div>
<div class="room room-toile">
<div class="wall"></div>
<div class="headboard"></div>
<div class="bed"></div>
<div class="nightstand"></div>
<div class="floor"></div>
<span class="swatch-label">Vignette</span>
</div>
</div>
<div class="look-copy">
<span class="eyebrow">03 — Chinoiserie Toile</span>
<h2>Pagoda Mist</h2>
<p>Indigo storybook scenes on pearl ground; finish with a lacquer nightstand and coral bolster.</p>
</div>
</section>
<!-- CTA -->
<section class="slide slide-cta" aria-label="Call to action">
<p class="cta-kicker">The Collection</p>
<h2 class="cta-title">Paper the room<br>you grew up wanting.</h2>
<p class="cta-body">Three exclusive Grandmillennial grounds, hand-finished in our atelier.</p>
<button class="cta-btn" type="button" id="ctaBtn">Request Swatches</button>
<p class="cta-fine">Designer Wallcoverings · Est. MCMLxxxiv</p>
</section>
</div>
</div>
<div class="controls">
<button class="nav-btn" id="prev" aria-label="Previous slide" type="button">
<svg viewBox="0 0 24 24"><path d="M15 6l-6 6 6 6"/></svg>
</button>
<div class="dots" id="dots" role="tablist" aria-label="Slides"></div>
<span class="slide-count" id="count" aria-live="polite">01 / 05</span>
<button class="nav-btn" id="next" aria-label="Next slide" type="button">
<svg viewBox="0 0 24 24"><path d="M9 6l6 6-6 6"/></svg>
</button>
</div>
</main>
<script>
(function () {
var track = document.getElementById('track');
var carousel = document.getElementById('carousel');
var prev = document.getElementById('prev');
var next = document.getElementById('next');
var dotsWrap = document.getElementById('dots');
var count = document.getElementById('count');
var slides = track.children;
var total = slides.length;
var index = 0;
var startX = 0;
var deltaX = 0;
var dragging = false;
for (var i = 0; i < total; i++) {
var b = document.createElement('button');
b.className = 'dot';
b.type = 'button';
b.setAttribute('role', 'tab');
b.setAttribute('aria-label', 'Go to slide ' + (i + 1));
b.dataset.i = i;
if (i === 0) b.setAttribute('aria-current', 'true');
b.addEventListener('click', function (e) {
go(+e.currentTarget.dataset.i);
});
dotsWrap.appendChild(b);
}
var dots = dotsWrap.children;
function pad(n) { return (n < 10 ? '0' : '') + n; }
function go(i) {
index = Math.max(0, Math.min(total - 1, i));
track.style.transform = 'translateX(' + (-index * 100) + '%)';
for (var d = 0; d < dots.length; d++) {
if (d === index) dots[d].setAttribute('aria-current', 'true');
else dots[d].removeAttribute('aria-current');
}
count.textContent = pad(index + 1) + ' / ' + pad(total);
prev.disabled = index === 0;
next.disabled = index === total - 1;
}
prev.addEventListener('click', function () { go(index - 1); });
next.addEventListener('click', function () { go(index + 1); });
document.getElementById('ctaBtn').addEventListener('click', function () {
go(0);
});
carousel.addEventListener('touchstart', function (e) {
startX = e.touches[0].clientX;
deltaX = 0;
dragging = true;
track.style.transition = 'none';
}, { passive: true });
carousel.addEventListener('touchmove', function (e) {
if (!dragging) return;
deltaX = e.touches[0].clientX - startX;
var pct = (deltaX / carousel.offsetWidth) * 100;
track.style.transform = 'translateX(calc(' + (-index * 100) + '% + ' + pct + '%))';
}, { passive: true });
carousel.addEventListener('touchend', function () {
if (!dragging) return;
dragging = false;
track.style.transition = '';
if (deltaX < -50) go(index + 1);
else if (deltaX > 50) go(index - 1);
else go(index);
});
// pointer (mouse drag)
carousel.addEventListener('pointerdown', function (e) {
if (e.pointerType === 'touch') return;
startX = e.clientX;
deltaX = 0;
dragging = true;
track.style.transition = 'none';
carousel.setPointerCapture(e.pointerId);
});
carousel.addEventListener('pointermove', function (e) {
if (!dragging || e.pointerType === 'touch') return;
deltaX = e.clientX - startX;
var pct = (deltaX / carousel.offsetWidth) * 100;
track.style.transform = 'translateX(calc(' + (-index * 100) + '% + ' + pct + '%))';
});
carousel.addEventListener('pointerup', function (e) {
if (e.pointerType === 'touch') return;
if (!dragging) return;
dragging = false;
track.style.transition = '';
if (deltaX < -50) go(index + 1);
else if (deltaX > 50) go(index - 1);
else go(index);
});
document.addEventListener('keydown', function (e) {
if (e.key === 'ArrowRight') go(index + 1);
if (e.key === 'ArrowLeft') go(index - 1);
});
go(0);
})();
</script>
</body>
</html>