Run details
- Model
- nvidia/nemotron-3-ultra-550b-a55b:free
- Route
- OpenRouter API, one user message
- Reasoning
- provider default, 413 reasoning tokens
- Limits
- 60 min · 65,536 output tokens
- Date
- 21 Oct 2026
- Time
- 4 min 25 s
- Size
- 73 kB
- Tokens
- 106 in, 24,111 out
- List price
- $0.058 ($0.6 in / $2.4 out per M)
- Paid
- $0 (free route)
Exact prompt
Build the landing page for Lumen Cycles, a Copenhagen workshop that builds custom cargo bikes to order. Make it look like a real brand you would trust with 4,000 euros. It must be one complete, self-contained HTML file: inline all CSS and JavaScript, and make no network requests of any kind (no CDNs, web fonts or remote images). Reply with the file in a single ```html code block.
Source
73 kB 1,160 lines Raw
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lumen Cycles — Custom Cargo Bikes, Built in Copenhagen</title>
<meta name="description" content="Lumen Cycles builds custom cargo bikes to order in our Copenhagen workshop. Designed for your life, built to last generations.">
<style>
:root {
--bg: #0a0a0a;
--bg-elevated: #121212;
--fg: #f5f5f0;
--fg-muted: #8a8a83;
--accent: #c9853a;
--accent-dim: #9d662d;
--accent-glow: rgba(201, 133, 58, 0.15);
--card: #181818;
--border: #2a2a2a;
--border-bright: #3a3a3a;
--focus: #c9853a;
--shadow: rgba(0,0,0,0.5);
--shadow-strong: rgba(0,0,0,0.7);
--transition-fast: 150ms ease;
--transition-base: 300ms ease;
--transition-slow: 600ms ease;
--container: 1200px;
--space-xs: 4px;
--space-sm: 8px;
--space-md: 16px;
--space-lg: 24px;
--space-xl: 40px;
--space-2xl: 64px;
--space-3xl: 96px;
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 16px;
}
@media (prefers-color-scheme: light) {
:root {
--bg: #fafafa;
--bg-elevated: #ffffff;
--fg: #1a1a1a;
--fg-muted: #6a6a63;
--accent: #b8762e;
--accent-dim: #9d662d;
--accent-glow: rgba(184, 118, 46, 0.12);
--card: #ffffff;
--border: #e5e5e0;
--border-bright: #d5d5cf;
--shadow: rgba(0,0,0,0.08);
--shadow-strong: rgba(0,0,0,0.15);
}
}
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
body {
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
background: var(--bg);
color: var(--fg);
line-height: 1.6;
overflow-x: hidden;
}
::selection { background: var(--accent); color: #000; }
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--border-bright); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--accent); }
a { color: inherit; text-decoration: none; }
img, svg { display: block; max-width: 100%; }
button { font: inherit; cursor: pointer; border: none; background: none; }
input, textarea { font: inherit; background: var(--card); border: 1px solid var(--border); color: var(--fg); padding: var(--space-md); border-radius: var(--radius-md); width: 100%; }
input:focus, textarea:focus { outline: 2px solid var(--focus); outline-offset: 2px; border-color: var(--focus); }
label { display: block; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--fg-muted); margin-bottom: var(--space-xs); }
.container { width: 100%; max-width: var(--container); margin: 0 auto; padding: 0 var(--space-lg); }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0; }
/* --- Reveal Animations --- */
.reveal { opacity: 0; transform: translateY(30px); transition: opacity var(--transition-slow), transform var(--transition-slow); }
.reveal.visible { opacity: 1; transform: translateY(0); }
.reveal-delay-1 { transition-delay: 100ms; }
.reveal-delay-2 { transition-delay: 200ms; }
.reveal-delay-3 { transition-delay: 300ms; }
.reveal-delay-4 { transition-delay: 400ms; }
/* --- Header --- */
header { position: fixed; top: 0; left: 0; right: 0; z-index: 100; padding: var(--space-md) 0; background: linear-gradient(180deg, rgba(10,10,10,0.95) 0%, transparent 100%); backdrop-filter: blur(20px); border-bottom: 1px solid transparent; transition: border-color var(--transition-base), background var(--transition-base); }
@media (prefers-color-scheme: light) { header { background: linear-gradient(180deg, rgba(250,250,250,0.95) 0%, transparent 100%); } }
header.scrolled { border-color: var(--border); background: var(--bg); }
.header-inner { display: flex; align-items: center; justify-content: space-between; gap: var(--space-lg); }
.logo { display: flex; align-items: center; gap: var(--space-sm); font-weight: 600; font-size: 1.125rem; letter-spacing: -0.02em; }
.logo-mark { width: 32px; height: 32px; flex-shrink: 0; }
.logo-mark path { transition: stroke var(--transition-base); }
.logo:hover .logo-mark path { stroke: var(--accent); }
nav { display: none; }
@media (min-width: 768px) { nav { display: flex; gap: var(--space-xl); } }
nav a { font-size: 0.875rem; font-weight: 500; color: var(--fg-muted); transition: color var(--transition-fast); position: relative; }
nav a::after { content: ''; position: absolute; bottom: -4px; left: 0; width: 0; height: 1px; background: var(--accent); transition: width var(--transition-base); }
nav a:hover { color: var(--fg); }
nav a:hover::after { width: 100%; }
.header-cta { display: flex; align-items: center; gap: var(--space-sm); padding: var(--space-sm) var(--space-lg); background: var(--accent); color: #000; font-weight: 600; font-size: 0.875rem; border-radius: var(--radius-md); transition: background var(--transition-fast), transform var(--transition-fast), box-shadow var(--transition-fast); }
.header-cta:hover { background: #d9944a; transform: translateY(-1px); box-shadow: 0 8px 24px var(--accent-glow); }
.header-cta:active { transform: translateY(0); }
.mobile-menu-btn { display: flex; flex-direction: column; gap: 5px; padding: var(--space-sm); }
.mobile-menu-btn span { width: 24px; height: 2px; background: var(--fg); border-radius: 1px; transition: var(--transition-base); }
@media (min-width: 768px) { .mobile-menu-btn { display: none; } }
/* Mobile Menu */
.mobile-menu { position: fixed; top: 0; right: 0; bottom: 0; width: 100%; max-width: 320px; background: var(--bg-elevated); border-left: 1px solid var(--border); padding: var(--space-2xl) var(--space-lg); z-index: 200; transform: translateX(100%); transition: transform var(--transition-slow); display: flex; flex-direction: column; }
.mobile-menu.open { transform: translateX(0); }
.mobile-menu nav { display: flex; flex-direction: column; gap: var(--space-md); margin-top: var(--space-xl); }
.mobile-menu nav a { font-size: 1.25rem; font-weight: 500; }
.mobile-menu .header-cta { width: 100%; justify-content: center; margin-top: auto; }
.mobile-menu-close { position: absolute; top: var(--space-lg); right: var(--space-lg); width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; border-radius: 50%; }
.mobile-menu-close:hover { background: var(--card); }
.mobile-menu-close::before, .mobile-menu-close::after { content: ''; position: absolute; width: 20px; height: 2px; background: var(--fg); border-radius: 1px; }
.mobile-menu-close::before { transform: rotate(45deg); }
.mobile-menu-close::after { transform: rotate(-45deg); }
.menu-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 150; opacity: 0; visibility: hidden; transition: opacity var(--transition-base), visibility var(--transition-base); }
.menu-overlay.visible { opacity: 1; visibility: visible; }
/* --- Hero --- */
.hero { min-height: 100vh; display: flex; align-items: center; position: relative; padding: calc(80px + var(--space-3xl)) 0 var(--space-3xl); overflow: hidden; }
.hero::before { content: ''; position: absolute; inset: 0; background: radial-gradient(ellipse 80% 60% at 50% 20%, var(--accent-glow) 0%, transparent 70%); pointer-events: none; }
.hero-grid { display: grid; grid-template-columns: 1fr; gap: var(--space-2xl); align-items: center; }
@media (min-width: 960px) { .hero-grid { grid-template-columns: 1.1fr 0.9fr; } }
.hero-content { position: relative; z-index: 1; }
.hero-badge { display: inline-flex; align-items: center; gap: var(--space-sm); font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.15em; font-weight: 600; color: var(--accent); margin-bottom: var(--space-lg); }
.hero-badge::before { content: ''; width: 8px; height: 8px; background: var(--accent); border-radius: 50%; animation: pulse 2s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.4; transform: scale(0.8); } }
.hero h1 { font-size: clamp(2.5rem, 6vw, 4.5rem); font-weight: 700; line-height: 1.05; letter-spacing: -0.03em; margin-bottom: var(--space-lg); color: var(--fg); }
.hero h1 span { color: var(--accent); }
.hero p { font-size: clamp(1.125rem, 2.5vw, 1.375rem); color: var(--fg-muted); max-width: 540px; margin-bottom: var(--space-xl); line-height: 1.7; }
.hero-ctas { display: flex; flex-wrap: wrap; gap: var(--space-md); }
.btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-sm); padding: var(--space-md) var(--space-xl); font-weight: 600; font-size: 0.9375rem; border-radius: var(--radius-md); transition: all var(--transition-base); white-space: nowrap; }
.btn-primary { background: var(--accent); color: #000; }
.btn-primary:hover { background: #d9944a; transform: translateY(-2px); box-shadow: 0 12px 32px var(--accent-glow); }
.btn-primary:active { transform: translateY(0); }
.btn-secondary { border: 1px solid var(--border-bright); color: var(--fg); background: transparent; }
.btn-secondary:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-glow); }
.btn-secondary:active { transform: scale(0.98); }
.hero-visual { position: relative; display: flex; justify-content: center; align-items: center; }
.bike-stage { position: relative; width: 100%; max-width: 600px; aspect-ratio: 4/3; }
.bike-svg { width: 100%; height: 100%; filter: drop-shadow(0 40px 60px var(--shadow-strong)); }
.bike-svg .bike-part { transform-origin: center; transition: transform var(--transition-slow), opacity var(--transition-slow); opacity: 0; }
.bike-svg.loaded .frame { animation: slideInFrame 1.2s cubic-bezier(0.16, 1, 0.3, 1) forwards; }
.bike-svg.loaded .cargo-box { animation: slideInCargo 1s cubic-bezier(0.16, 1, 0.3, 1) 0.2s forwards; }
.bike-svg.loaded .wheel { animation: spinIn 1.4s cubic-bezier(0.16, 1, 0.3, 1) 0.1s forwards; }
.bike-svg.loaded .wheel-rear { animation-delay: 0.15s; }
.bike-svg.loaded .details { animation: fadeInUp 0.8s ease 0.6s forwards; }
.bike-svg.loaded .accent-line { animation: drawLine 1.5s ease 0.4s forwards; }
@keyframes slideInFrame { from { transform: translateX(-60px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
@keyframes slideInCargo { from { transform: translateX(60px); opacity: 0; } to { transform: translateX(0); opacity: 1; } }
@keyframes spinIn { from { transform: rotate(-180deg) scale(0.5); opacity: 0; } to { transform: rotate(0) scale(1); opacity: 1; } }
@keyframes fadeInUp { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
@keyframes drawLine { from { stroke-dashoffset: 1000; } to { stroke-dashoffset: 0; } }
/* Floating specs */
.spec-callout { position: absolute; display: flex; flex-direction: column; gap: 2px; padding: var(--space-md) var(--space-lg); background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-md); box-shadow: 0 20px 40px var(--shadow-strong); backdrop-filter: blur(20px); animation: float 6s ease-in-out infinite; }
.spec-callout:nth-child(2) { animation-delay: -2s; }
.spec-callout:nth-child(3) { animation-delay: -4s; }
@keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-12px); } }
.spec-callout .label { font-size: 0.625rem; text-transform: uppercase; letter-spacing: 0.1em; font-weight: 600; color: var(--accent); }
.spec-callout .value { font-size: 1.125rem; font-weight: 700; letter-spacing: -0.02em; }
.spec-1 { top: 15%; left: -10%; }
.spec-2 { top: 55%; right: -12%; }
.spec-3 { bottom: 15%; left: 5%; }
@media (max-width: 959px) { .spec-callout { display: none; } }
/* --- Section Base --- */
section { padding: var(--space-3xl) 0; position: relative; }
.section-header { text-align: center; max-width: 640px; margin: 0 auto var(--space-3xl); }
.section-tag { display: inline-block; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.15em; font-weight: 600; color: var(--accent); margin-bottom: var(--space-md); }
.section-header h2 { font-size: clamp(2rem, 4vw, 3rem); font-weight: 700; line-height: 1.15; letter-spacing: -0.02em; color: var(--fg); }
.section-header p { margin-top: var(--space-md); font-size: 1.125rem; color: var(--fg-muted); line-height: 1.7; }
/* --- Philosophy --- */
.philosophy { background: var(--bg-elevated); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.philosophy-grid { display: grid; grid-template-columns: 1fr; gap: var(--space-xl); }
@media (min-width: 768px) { .philosophy-grid { grid-template-columns: repeat(3, 1fr); } }
.philosophy-card { padding: var(--space-xl); background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-lg); transition: border-color var(--transition-base), transform var(--transition-base), box-shadow var(--transition-base); position: relative; overflow: hidden; }
.philosophy-card::before { content: ''; position: absolute; top: 0; left: 0; right: 0; height: 3px; background: linear-gradient(90deg, var(--accent), transparent); transform: scaleX(0); transform-origin: left; transition: transform var(--transition-slow); }
.philosophy-card:hover { border-color: var(--border-bright); transform: translateY(-4px); box-shadow: 0 24px 48px var(--shadow); }
.philosophy-card:hover::before { transform: scaleX(1); }
.philosophy-icon { width: 48px; height: 48px; margin-bottom: var(--space-lg); opacity: 0.8; transition: opacity var(--transition-base); }
.philosophy-card:hover .philosophy-icon { opacity: 1; }
.philosophy-card h3 { font-size: 1.25rem; font-weight: 600; margin-bottom: var(--space-md); letter-spacing: -0.01em; }
.philosophy-card p { color: var(--fg-muted); line-height: 1.7; font-size: 0.9375rem; }
/* --- Process --- */
.process { background: var(--bg); }
.process-steps { display: grid; grid-template-columns: 1fr; gap: var(--space-xl); counter-reset: step; }
@media (min-width: 768px) { .process-steps { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .process-steps { grid-template-columns: repeat(4, 1fr); } }
.process-step { position: relative; padding: var(--space-xl); padding-left: calc(var(--space-xl) + 48px); }
.process-step::before { counter-increment: step; content: '0' counter(step); position: absolute; left: var(--space-xl); top: var(--space-xl); font-size: 3rem; font-weight: 700; color: var(--accent); opacity: 0.15; line-height: 1; font-family: 'SF Mono', 'Monaco', 'Inconsolata', monospace; }
.step-icon { width: 40px; height: 40px; margin-bottom: var(--space-md); opacity: 0.7; }
.process-step h3 { font-size: 1.25rem; font-weight: 600; margin-bottom: var(--space-sm); }
.process-step p { color: var(--fg-muted); font-size: 0.9375rem; line-height: 1.7; }
.process-connector { display: none; }
@media (min-width: 1024px) {
.process-steps { position: relative; }
.process-steps::before { content: ''; position: absolute; top: 60px; left: 50%; transform: translateX(-50%); width: 1px; height: calc(100% - 120px); background: linear-gradient(180deg, transparent, var(--border), transparent); z-index: 0; }
.process-step { padding-top: var(--space-2xl); z-index: 1; }
.process-step::before { left: 50%; transform: translateX(-50%); top: 0; font-size: 2.5rem; }
}
/* --- Models --- */
.models { background: var(--bg-elevated); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.models-grid { display: grid; grid-template-columns: 1fr; gap: var(--space-xl); }
@media (min-width: 768px) { .models-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .models-grid { grid-template-columns: repeat(3, 1fr); } }
.model-card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; transition: transform var(--transition-base), border-color var(--transition-base), box-shadow var(--transition-base); display: flex; flex-direction: column; }
.model-card:hover { transform: translateY(-4px); border-color: var(--border-bright); box-shadow: 0 24px 48px var(--shadow); }
.model-visual { aspect-ratio: 4/3; background: linear-gradient(180deg, var(--bg-elevated), var(--card)); position: relative; overflow: hidden; }
.model-visual svg { width: 100%; height: 100%; object-fit: cover; transition: transform var(--transition-slow); }
.model-card:hover .model-visual svg { transform: scale(1.05); }
.model-info { padding: var(--space-xl); display: flex; flex-direction: column; flex: 1; }
.model-category { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.1em; font-weight: 600; color: var(--accent); margin-bottom: var(--space-xs); }
.model-info h3 { font-size: 1.375rem; font-weight: 600; margin-bottom: var(--space-sm); letter-spacing: -0.01em; }
.model-info > p { color: var(--fg-muted); font-size: 0.9375rem; line-height: 1.7; margin-bottom: var(--space-lg); flex: 1; }
.model-specs { display: flex; flex-wrap: wrap; gap: var(--space-md); margin-bottom: var(--space-lg); padding-top: var(--space-lg); border-top: 1px solid var(--border); }
.spec-item { display: flex; align-items: center; gap: var(--space-xs); font-size: 0.8125rem; color: var(--fg-muted); }
.spec-item strong { color: var(--fg); font-weight: 600; }
.model-price { font-size: 1.5rem; font-weight: 700; letter-spacing: -0.02em; margin-bottom: var(--space-md); }
.model-price span { font-size: 1rem; font-weight: 400; color: var(--fg-muted); }
.btn-model { width: 100%; padding: var(--space-md); text-align: center; border: 1px solid var(--border-bright); border-radius: var(--radius-md); font-weight: 600; font-size: 0.9375rem; color: var(--fg); transition: all var(--transition-base); }
.btn-model:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-glow); }
/* --- Workshop / Trust --- */
.workshop { background: var(--bg); }
.workshop-grid { display: grid; grid-template-columns: 1fr; gap: var(--space-2xl); align-items: start; }
@media (min-width: 960px) { .workshop-grid { grid-template-columns: 1.2fr 0.8fr; } }
.workshop-content { padding-right: var(--space-xl); }
.workshop-stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-lg); margin: var(--space-2xl) 0; }
.stat { padding: var(--space-lg); background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-md); }
.stat-value { font-size: 2.5rem; font-weight: 700; color: var(--accent); line-height: 1; font-family: 'SF Mono', 'Monaco', 'Inconsolata', monospace; }
.stat-label { font-size: 0.875rem; color: var(--fg-muted); margin-top: var(--space-xs); }
.workshop-details { display: grid; grid-template-columns: 1fr; gap: var(--space-md); }
@media (min-width: 480px) { .workshop-details { grid-template-columns: repeat(2, 1fr); } }
.detail-item { display: flex; align-items: flex-start; gap: var(--space-md); padding: var(--space-md); background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-md); transition: border-color var(--transition-base); }
.detail-item:hover { border-color: var(--border-bright); }
.detail-icon { width: 24px; height: 24px; flex-shrink: 0; margin-top: 2px; opacity: 0.6; }
.detail-item strong { display: block; font-size: 0.9375rem; margin-bottom: 2px; }
.detail-item span { font-size: 0.875rem; color: var(--fg-muted); line-height: 1.5; }
.workshop-visual { position: relative; }
.workshop-image { aspect-ratio: 4/5; background: linear-gradient(135deg, var(--card) 0%, var(--bg-elevated) 100%); border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; position: relative; }
.workshop-image svg { width: 100%; height: 100%; object-fit: cover; opacity: 0.9; }
.workshop-badge { position: absolute; bottom: var(--space-xl); right: var(--space-xl); background: var(--accent); color: #000; padding: var(--space-md) var(--space-lg); border-radius: var(--radius-md); font-weight: 600; font-size: 0.875rem; box-shadow: 0 16px 40px var(--accent-glow); animation: float 4s ease-in-out infinite; }
/* --- Testimonials --- */
.testimonials { background: var(--bg-elevated); border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.testimonials-track { display: grid; grid-template-columns: 1fr; gap: var(--space-xl); }
@media (min-width: 768px) { .testimonials-track { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .testimonials-track { grid-template-columns: repeat(3, 1fr); } }
.testimonial { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-lg); padding: var(--space-xl); transition: border-color var(--transition-base); }
.testimonial:hover { border-color: var(--border-bright); }
.testimonial-header { display: flex; align-items: center; gap: var(--space-md); margin-bottom: var(--space-lg); }
.testimonial-avatar { width: 48px; height: 48px; border-radius: 50%; background: linear-gradient(135deg, var(--accent), var(--accent-dim)); display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 1.125rem; color: #000; flex-shrink: 0; }
.testimonial-meta h4 { font-weight: 600; font-size: 0.9375rem; }
.testimonial-meta p { font-size: 0.8125rem; color: var(--fg-muted); }
.testimonial-text { font-size: 1rem; line-height: 1.7; color: var(--fg-muted); margin-bottom: var(--space-lg); }
.testimonial-bike { font-size: 0.8125rem; color: var(--accent); font-weight: 500; }
/* --- CTA Section --- */
.cta { background: var(--bg); position: relative; overflow: hidden; }
.cta::before { content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 600px; height: 600px; background: radial-gradient(circle, var(--accent-glow) 0%, transparent 70%); pointer-events: none; }
.cta-inner { position: relative; text-align: center; max-width: 720px; margin: 0 auto; padding: var(--space-2xl) 0; }
.cta h2 { font-size: clamp(2rem, 4vw, 3rem); font-weight: 700; line-height: 1.15; letter-spacing: -0.02em; margin-bottom: var(--space-md); }
.cta p { font-size: 1.125rem; color: var(--fg-muted); margin-bottom: var(--space-xl); max-width: 540px; margin-left: auto; margin-right: auto; line-height: 1.7; }
.cta-form { display: grid; grid-template-columns: 1fr; gap: var(--space-md); max-width: 520px; margin: 0 auto; text-align: left; }
@media (min-width: 560px) { .cta-form { grid-template-columns: 1fr 1fr auto; align-items: end; } }
.form-group { display: flex; flex-direction: column; gap: var(--space-xs); }
.cta-form .btn-primary { height: 100%; min-height: 52px; padding: var(--space-md) var(--space-2xl); white-space: normal; }
.form-note { grid-column: 1 / -1; font-size: 0.75rem; color: var(--fg-muted); text-align: center; }
@media (min-width: 560px) { .form-note { grid-column: 1 / 4; } }
/* --- Footer --- */
footer { background: var(--bg-elevated); border-top: 1px solid var(--border); padding: var(--space-3xl) 0 var(--space-xl); }
.footer-grid { display: grid; grid-template-columns: 1fr; gap: var(--space-2xl); margin-bottom: var(--space-2xl); }
@media (min-width: 768px) { .footer-grid { grid-template-columns: 2fr repeat(3, 1fr); } }
.footer-brand { max-width: 320px; }
.footer-brand .logo { margin-bottom: var(--space-md); }
.footer-brand p { color: var(--fg-muted); font-size: 0.9375rem; line-height: 1.7; margin-bottom: var(--space-lg); }
.social-links { display: flex; gap: var(--space-md); }
.social-links a { width: 40px; height: 40px; border-radius: 50%; border: 1px solid var(--border); display: flex; align-items: center; justify-content: center; transition: all var(--transition-base); }
.social-links a:hover { border-color: var(--accent); background: var(--accent-glow); transform: translateY(-2px); }
.social-links svg { width: 20px; height: 20px; }
.footer-nav h4 { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.1em; font-weight: 600; color: var(--accent); margin-bottom: var(--space-lg); }
.footer-nav ul { list-style: none; display: flex; flex-direction: column; gap: var(--space-sm); }
.footer-nav a { font-size: 0.9375rem; color: var(--fg-muted); transition: color var(--transition-fast); }
.footer-nav a:hover { color: var(--accent); }
.footer-bottom { padding-top: var(--space-xl); border-top: 1px solid var(--border); display: flex; flex-direction: column; align-items: center; gap: var(--space-md); text-align: center; }
@media (min-width: 768px) { .footer-bottom { flex-direction: row; justify-content: space-between; text-align: left; } }
.footer-bottom p { font-size: 0.875rem; color: var(--fg-muted); }
.footer-legal { display: flex; gap: var(--space-xl); font-size: 0.8125rem; color: var(--fg-muted); }
.footer-legal a:hover { color: var(--accent); }
/* --- Reduced Motion --- */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
.reveal { opacity: 1; transform: none; }
.bike-svg .bike-part { opacity: 1; }
}
/* --- Focus Visible --- */
:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; border-radius: var(--radius-sm); }
/* --- Form States --- */
.form-group input[aria-invalid="true"], .form-group textarea[aria-invalid="true"] { border-color: #c0392b; }
.form-error { font-size: 0.8125rem; color: #e74c3c; min-height: 20px; }
.form-success { grid-column: 1 / -1; padding: var(--space-lg); background: rgba(39, 174, 96, 0.1); border: 1px solid #27ae60; border-radius: var(--radius-md); color: #2ecc71; text-align: center; animation: fadeInUp 0.4s ease; }
</style>
</head>
<body>
<!-- Header -->
<header id="header" role="banner">
<div class="container header-inner">
<a href="#" class="logo" aria-label="Lumen Cycles - Home">
<svg class="logo-mark" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<circle cx="16" cy="16" r="14" stroke="currentColor" stroke-width="1.5"/>
<path d="M16 6V22M6 16H22" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
<circle cx="16" cy="16" r="6" stroke="currentColor" stroke-width="1.5"/>
</svg>
Lumen Cycles
</a>
<nav id="nav" aria-label="Main navigation">
<a href="#philosophy">Philosophy</a>
<a href="#process">Process</a>
<a href="#models">Models</a>
<a href="#workshop">Workshop</a>
<a href="#contact">Configure</a>
</nav>
<a href="#contact" class="header-cta">Configure Yours</a>
<button class="mobile-menu-btn" aria-label="Open menu" aria-expanded="false" aria-controls="mobile-menu" id="menu-btn">
<span></span><span></span><span></span>
</button>
</div>
</header>
<div class="menu-overlay" id="menu-overlay" aria-hidden="true"></div>
<aside class="mobile-menu" id="mobile-menu" role="dialog" aria-modal="true" aria-label="Menu">
<button class="mobile-menu-close" aria-label="Close menu" id="menu-close"></button>
<nav>
<a href="#philosophy">Philosophy</a>
<a href="#process">Process</a>
<a href="#models">Models</a>
<a href="#workshop">Workshop</a>
<a href="#contact">Configure</a>
</nav>
<a href="#contact" class="header-cta">Configure Yours</a>
</aside>
<!-- Hero -->
<main id="main">
<section class="hero" aria-labelledby="hero-title">
<div class="container hero-grid">
<div class="hero-content reveal">
<p class="hero-badge">Copenhagen Workshop · Since 2019</p>
<h1 id="hero-title">Cargo bikes built<br><span>for your life</span></h1>
<p>Every Lumen starts as a conversation. We design, weld, and assemble each bike by hand in our Copenhagen workshop — tailored to how you move, what you carry, and where you ride.</p>
<div class="hero-ctas">
<a href="#contact" class="btn btn-primary">Start Your Build</a>
<a href="#models" class="btn btn-secondary">Explore Models</a>
</div>
</div>
<div class="hero-visual reveal reveal-delay-1">
<div class="bike-stage">
<svg class="bike-svg" id="bike-svg" viewBox="0 0 600 450" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" aria-label="Lumen cargo bike illustration">
<defs>
<linearGradient id="frameGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#2a2a2a"/>
<stop offset="100%" stop-color="#1a1a1a"/>
</linearGradient>
<linearGradient id="accentGrad" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#c9853a"/>
<stop offset="100%" stop-color="#e8a85a"/>
</linearGradient>
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="3" result="blur"/>
<feMerge><feMergeNode in="blur"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</deffs>
<!-- Frame -->
<g class="bike-part frame" filter="url(#glow)">
<path d="M120 280 L200 220 L320 220 L380 280 L320 340 L200 340 Z" stroke="url(#frameGrad)" stroke-width="8" fill="none" stroke-linejoin="round" stroke-linecap="round"/>
<path d="M200 220 L200 140" stroke="url(#frameGrad)" stroke-width="6" fill="none" stroke-linecap="round"/>
<path d="M320 220 L320 160" stroke="url(#frameGrad)" stroke-width="6" fill="none" stroke-linecap="round"/>
<path d="M120 280 L80 360" stroke="url(#frameGrad)" stroke-width="8" fill="none" stroke-linecap="round"/>
<path d="M380 280 L420 360" stroke="url(#frameGrad)" stroke-width="8" fill="none" stroke-linecap="round"/>
<!-- Head tube -->
<path d="M200 140 L180 100" stroke="url(#frameGrad)" stroke-width="10" fill="none" stroke-linecap="round"/>
<!-- Fork -->
<path d="M180 100 L150 40" stroke="url(#frameGrad)" stroke-width="6" fill="none" stroke-linecap="round"/>
<path d="M180 100 L210 40" stroke="url(#frameGrad)" stroke-width="6" fill="none" stroke-linecap="round"/>
<!-- Handlebars -->
<path d="M140 100 L220 100" stroke="url(#frameGrad)" stroke-width="4" fill="none" stroke-linecap="round"/>
<!-- Seat post -->
<path d="M320 160 L320 100" stroke="url(#frameGrad)" stroke-width="5" fill="none" stroke-linecap="round"/>
<!-- Saddle -->
<ellipse cx="320" cy="95" rx="22" ry="4" fill="#1a1a1a" stroke="#333" stroke-width="1"/>
</g>
<!-- Cargo Box -->
<g class="bike-part cargo-box">
<rect x="80" y="180" width="180" height="100" rx="8" fill="url(#frameGrad)" stroke="#333" stroke-width="1.5"/>
<rect x="90" y="190" width="160" height="80" rx="4" fill="none" stroke="#3a3a3a" stroke-width="1" stroke-dasharray="8 4"/>
<!-- Lumen logo on box -->
<g transform="translate(170 230) scale(0.8)">
<circle cx="0" cy="0" r="18" stroke="#c9853a" stroke-width="1.5" fill="none"/>
<path d="M0 -10V10M-10 0H10" stroke="#c9853a" stroke-width="1.5" stroke-linecap="round"/>
</g>
<!-- Cargo straps -->
<path d="M90 230 L90 270" stroke="#4a4a4a" stroke-width="3" stroke-linecap="round"/>
<path d="M250 230 L250 270" stroke="#4a4a4a" stroke-width="3" stroke-linecap="round"/>
<path d="M90 230 L250 230" stroke="#4a4a4a" stroke-width="3" stroke-linecap="round"/>
<path d="M90 270 L250 270" stroke="#4a4a4a" stroke-width="3" stroke-linecap="round"/>
</g>
<!-- Wheels -->
<g class="bike-part wheel wheel-front" transform="translate(120 360)">
<circle r="70" stroke="#1a1a1a" stroke-width="4" fill="none"/>
<circle r="60" stroke="#2a2a2a" stroke-width="2" fill="none"/>
<g stroke="#333" stroke-width="1.5">
<circle r="12" fill="none"/>
<path d="M0 -60V-12M0 12V60M-60 0H-12M12 0H60" stroke-linecap="round"/>
<g transform="rotate(45)"><path d="M0 -60V-12M0 12V60M-60 0H-12M12 0H60" stroke-linecap="round"/></g>
</g>
<!-- Tire -->
<circle r="72" stroke="#0a0a0a" stroke-width="6" fill="none"/>
<!-- Hub -->
<circle r="10" fill="#c9853a"/>
<circle r="6" fill="#1a1a1a"/>
</g>
<g class="bike-part wheel wheel-rear" transform="translate(380 360)">
<circle r="70" stroke="#1a1a1a" stroke-width="4" fill="none"/>
<circle r="60" stroke="#2a2a2a" stroke-width="2" fill="none"/>
<g stroke="#333" stroke-width="1.5">
<circle r="12" fill="none"/>
<path d="M0 -60V-12M0 12V60M-60 0H-12M12 0H60" stroke-linecap="round"/>
<g transform="rotate(45)"><path d="M0 -60V-12M0 12V60M-60 0H-12M12 0H60" stroke-linecap="round"/></g>
</g>
<circle r="72" stroke="#0a0a0a" stroke-width="6" fill="none"/>
<circle r="10" fill="#c9853a"/>
<circle r="6" fill="#1a1a1a"/>
<!-- Belt drive -->
<ellipse cx="0" cy="0" rx="35" ry="35" fill="none" stroke="#2a2a2a" stroke-width="8" stroke-linecap="round"/>
</g>
<!-- Details -->
<g class="bike-part details" opacity="0">
<!-- Lights -->
<circle cx="150" cy="95" r="6" fill="#fff" opacity="0.9" filter="url(#glow)"/>
<circle cx="410" cy="355" r="5" fill="#e74c3c" opacity="0.9"/>
<!-- Chainring -->
<g transform="translate(320 280)">
<circle r="35" stroke="#c9853a" stroke-width="3" fill="none" opacity="0.6"/>
<g stroke="#c9853a" stroke-width="2">
<path d="M0 -35V-25M0 25V35M-35 0H-25M25 0H35"/>
<g transform="rotate(45)"><path d="M0 -35V-25M0 25V35M-35 0H-25M25 0H35"/></g>
</g>
</g>
<!-- Kickstand -->
<path d="M200 340 L180 390" stroke="#4a4a4a" stroke-width="5" stroke-linecap="round"/>
</g>
<!-- Accent line -->
<path class="bike-part accent-line" d="M60 400 Q300 300 540 400" stroke="url(#accentGrad)" stroke-width="2" fill="none" stroke-dasharray="1000" stroke-dashoffset="1000" stroke-linecap="round"/>
</svg>
<div class="spec-callout spec-1"><span class="label">Payload</span><span class="value">200 kg</span></div>
<div class="spec-callout spec-2"><span class="label">Range</span><span class="value">120 km</span></div>
<div class="spec-callout spec-3"><span class="label">Warranty</span><span class="value">10 Years</span></div>
</div>
</div>
</div>
</section>
<!-- Philosophy -->
<section id="philosophy" class="philosophy" aria-labelledby="philosophy-title">
<div class="container">
<header class="section-header reveal">
<span class="section-tag">Our Approach</span>
<h2 id="philosophy-title">Three principles guide every build</h2>
<p>We don't build for the showroom. We build for the streets of Copenhagen — and wherever life takes you.</p>
</header>
<div class="philosophy-grid">
<article class="philosophy-card reveal">
<svg class="philosophy-icon" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M24 4L6 16v16l18 12 18-12V16L24 4z"/><path d="M24 16v20M6 16l18 12 18-12"/></svg>
<h3>Fit for Purpose</h3>
<p>No two riders are alike. We measure, discuss, and prototype until the geometry matches your body, your cargo, and your daily route.</p>
</article>
<article class="philosophy-card reveal reveal-delay-1">
<svg class="philosophy-icon" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M24 4L6 16v16l18 12 18-12V16L24 4z"/><path d="M24 16v20M6 16l18 12 18-12"/></svg>
<h3>Materials That Last</h3>
<p>Columbus Life tubing, stainless hardware, powder coat inside and out. Every component chosen to survive Danish winters and decades of use.</p>
</article>
<article class="philosophy-card reveal reveal-delay-2">
<svg class="philosophy-icon" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><circle cx="24" cy="24" r="20"/><path d="M24 10v14l7 7"/></svg>
<h3>Service for Life</h3>
<p>Your Lumen leaves with a 10-year frame warranty and lifetime access to our workshop. We're here for every adjustment, repair, and upgrade.</p>
</article>
</div>
</div>
</section>
<!-- Process -->
<section id="process" class="process" aria-labelledby="process-title">
<div class="container">
<header class="section-header reveal">
<span class="section-tag">How It Works</span>
<h2 id="process-title">From conversation to Copenhagen streets</h2>
<p>Four steps. Zero compromise. Your bike ships ready to ride.</p>
</header>
<div class="process-steps">
<article class="process-step reveal">
<svg class="step-icon" viewBox="0 0 40 40" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M20 6L8 18v14l12 12 12-12V18L20 6z"/><path d="M20 18v14M8 18l12 12 12-12"/></svg>
<h3>Consultation</h3>
<p>We meet — in our workshop or via video — to understand your routes, loads, and preferences. You'll leave with a geometry sheet and build spec.</p>
</article>
<article class="process-step reveal reveal-delay-1">
<svg class="step-icon" viewBox="0 0 40 40" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><rect x="6" y="10" width="28" height="24" rx="2"/><path d="M14 18h12M14 24h8M14 30h6"/></svg>
<h3>Design & Quote</h3>
<p>We model your frame in CAD, select components, and present a fixed price. No surprises. Approve the render, and we order tubing.</p>
</article>
<article class="process-step reveal reveal-delay-2">
<svg class="step-icon" viewBox="0 0 40 40" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M20 6L8 14v12l12 8 12-8V14L20 6z"/><path d="M20 14v18M8 14l12 8 12-8"/></svg>
<h3>Hand-Built in Copenhagen</h3>
<p>Each frame is mitered, TIG-welded, heat-treated, and powder-coated in our workshop. Assembly takes two weeks — one mechanic, one bike.</p>
</article>
<article class="process-step reveal reveal-delay-3">
<svg class="step-icon" viewBox="0 0 40 40" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><circle cx="20" cy="20" r="16"/><path d="M20 8v12l7 7"/></svg>
<h3>Delivery & First Ride</h3>
<p>We hand over your Lumen with a fit session, maintenance walkthrough, and your first service booked. Then you ride.</p>
</article>
</div>
</div>
</section>
<!-- Models -->
<section id="models" class="models" aria-labelledby="models-title">
<div class="container">
<header class="section-header reveal">
<span class="section-tag">Starting Points</span>
<h2 id="models-title">Three platforms. Infinite configurations.</h2>
<p>Every model is a foundation. You choose drivetrain, assist, colors, and cargo layout.</p>
</header>
<div class="models-grid">
<!-- Long John -->
<article class="model-card reveal">
<div class="model-visual">
<svg viewBox="0 0 400 300" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<defs><linearGradient id="ljGrad" x1="0%" y1="100%" x2="100%" y2="0%"><stop offset="0%" stop-color="#1a1a1a"/><stop offset="100%" stop-color="#2a2a2a"/></linearGradient></defs>
<rect width="400" height="300" fill="url(#ljGrad)"/>
<!-- Long John frame -->
<g stroke="#3a3a3a" stroke-width="6" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path d="M80 180 L140 130 L260 130 L300 180 L260 220 L140 220 Z"/>
<path d="M140 130 L140 80"/>
<path d="M260 130 L260 100"/>
<path d="M80 180 L40 240"/>
<path d="M300 180 L340 240"/>
<path d="M140 80 L110 50"/>
<path d="M140 80 L170 50"/>
<path d="M110 50 L170 50"/>
<path d="M260 100 L260 70"/>
<ellipse cx="260" cy="65" rx="18" ry="3" fill="#1a1a1a" stroke="#333" stroke-width="1"/>
</g>
<!-- Cargo box -->
<rect x="60" y="100" width="160" height="80" rx="6" fill="#1a1a1a" stroke="#333" stroke-width="1.5"/>
<rect x="70" y="110" width="140" height="60" rx="3" fill="none" stroke="#3a3a3a" stroke-width="1" stroke-dasharray="6 3"/>
<!-- Wheels -->
<g transform="translate(80 240)">
<circle r="55" stroke="#1a1a1a" stroke-width="3" fill="none"/>
<circle r="48" stroke="#2a2a2a" stroke-width="1.5" fill="none"/>
<g stroke="#333" stroke-width="1"><circle r="10" fill="none"/><path d="M0 -48V-10M0 10V48M-48 0H-10M10 0H48"/><g transform="rotate(45)"><path d="M0 -48V-10M0 10V48M-48 0H-10M10 0H48"/></g></g>
<circle r="58" stroke="#0a0a0a" stroke-width="4" fill="none"/>
<circle r="8" fill="#c9853a"/><circle r="5" fill="#1a1a1a"/>
</g>
<g transform="translate(300 240)">
<circle r="55" stroke="#1a1a1a" stroke-width="3" fill="none"/>
<circle r="48" stroke="#2a2a2a" stroke-width="1.5" fill="none"/>
<g stroke="#333" stroke-width="1"><circle r="10" fill="none"/><path d="M0 -48V-10M0 10V48M-48 0H-10M10 0H48"/><g transform="rotate(45)"><path d="M0 -48V-10M0 10V48M-48 0H-10M10 0H48"/></g></g>
<circle r="58" stroke="#0a0a0a" stroke-width="4" fill="none"/>
<circle r="8" fill="#c9853a"/><circle r="5" fill="#1a1a1a"/>
<ellipse cx="0" cy="0" rx="28" ry="28" fill="none" stroke="#2a2a2a" stroke-width="6"/>
</g>
</svg>
</div>
<div class="model-info">
<span class="model-category">Long John Classic</span>
<h3>Lumen Long</h3>
<p>The original Copenhagen cargo geometry. Low center of gravity, linked steering, and a box that carries kids, groceries, or a week's camping gear.</p>
<div class="model-specs">
<span class="spec-item"><strong>Box:</strong> 85 × 55 cm</span>
<span class="spec-item"><strong>Load:</strong> 150 kg</span>
<span class="spec-item"><strong>Weight:</strong> 28 kg</span>
</div>
<div class="model-price">From €4,200<span>+ VAT</span></div>
<button class="btn-model" type="button">Configure This Model</button>
</div>
</article>
<!-- Front Loader -->
<article class="model-card reveal reveal-delay-1">
<div class="model-visual">
<svg viewBox="0 0 400 300" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<defs><linearGradient id="flGrad" x1="0%" y1="100%" x2="100%" y2="0%"><stop offset="0%" stop-color="#1a1a1a"/><stop offset="100%" stop-color="#2a2a2a"/></linearGradient></defs>
<rect width="400" height="300" fill="url(#flGrad)"/>
<g stroke="#3a3a3a" stroke-width="6" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path d="M80 200 L140 150 L300 150 L340 200 L300 240 L140 240 Z"/>
<path d="M140 150 L140 90"/>
<path d="M300 150 L300 110"/>
<path d="M80 200 L40 260"/>
<path d="M340 200 L380 260"/>
<path d="M140 90 L110 60"/>
<path d="M140 90 L170 60"/>
<path d="M110 60 L170 60"/>
<path d="M300 110 L300 80"/>
<ellipse cx="300" cy="75" rx="18" ry="3" fill="#1a1a1a" stroke="#333" stroke-width="1"/>
</g>
<!-- Front cargo platform -->
<g transform="translate(100 90)">
<path d="M0 0 L-40 -40 L100 -40 L140 0 Z" fill="#1a1a1a" stroke="#333" stroke-width="1.5"/>
<rect x="0" y="-35" width="100" height="25" rx="2" fill="none" stroke="#3a3a3a" stroke-width="1" stroke-dasharray="6 3"/>
</g>
<!-- Wheels -->
<g transform="translate(80 260)">
<circle r="55" stroke="#1a1a1a" stroke-width="3" fill="none"/>
<circle r="48" stroke="#2a2a2a" stroke-width="1.5" fill="none"/>
<g stroke="#333" stroke-width="1"><circle r="10" fill="none"/><path d="M0 -48V-10M0 10V48M-48 0H-10M10 0H48"/><g transform="rotate(45)"><path d="M0 -48V-10M0 10V48M-48 0H-10M10 0H48"/></g></g>
<circle r="58" stroke="#0a0a0a" stroke-width="4" fill="none"/>
<circle r="8" fill="#c9853a"/><circle r="5" fill="#1a1a1a"/>
</g>
<g transform="translate(300 260)">
<circle r="55" stroke="#1a1a1a" stroke-width="3" fill="none"/>
<circle r="48" stroke="#2a2a2a" stroke-width="1.5" fill="none"/>
<g stroke="#333" stroke-width="1"><circle r="10" fill="none"/><path d="M0 -48V-10M0 10V48M-48 0H-10M10 0H48"/><g transform="rotate(45)"><path d="M0 -48V-10M0 10V48M-48 0H-10M10 0H48"/></g></g>
<circle r="58" stroke="#0a0a0a" stroke-width="4" fill="none"/>
<circle r="8" fill="#c9853a"/><circle r="5" fill="#1a1a1a"/>
<ellipse cx="0" cy="0" rx="28" ry="28" fill="none" stroke="#2a2a2a" stroke-width="6"/>
</g>
</svg>
</div>
<div class="model-info">
<span class="model-category">Front Loader</span>
<h3>Lumen Front</h3>
<p>Shorter wheelbase, direct steering, and a modular front platform. Ideal for dense urban streets and riders who want car-like handling with cargo capacity.</p>
<div class="model-specs">
<span class="spec-item"><strong>Platform:</strong> 100 × 60 cm</span>
<span class="spec-item"><strong>Load:</strong> 120 kg</span>
<span class="spec-item"><strong>Weight:</strong> 25 kg</span>
</div>
<div class="model-price">From €3,800<span>+ VAT</span></div>
<button class="btn-model" type="button">Configure This Model</button>
</div>
</article>
<!-- Compact -->
<article class="model-card reveal reveal-delay-2">
<div class="model-visual">
<svg viewBox="0 0 400 300" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<defs><linearGradient id="cGrad" x1="0%" y1="100%" x2="100%" y2="0%"><stop offset="0%" stop-color="#1a1a1a"/><stop offset="100%" stop-color="#2a2a2a"/></linearGradient></defs>
<rect width="400" height="300" fill="url(#cGrad)"/>
<g stroke="#3a3a3a" stroke-width="6" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path d="M100 200 L160 150 L280 150 L320 200 L280 240 L160 240 Z"/>
<path d="M160 150 L160 90"/>
<path d="M280 150 L280 110"/>
<path d="M100 200 L70 250"/>
<path d="M320 200 L350 250"/>
<path d="M160 90 L135 65"/>
<path d="M160 90 L185 65"/>
<path d="M135 65 L185 65"/>
<path d="M280 110 L280 80"/>
<ellipse cx="280" cy="75" rx="18" ry="3" fill="#1a1a1a" stroke="#333" stroke-width="1"/>
</g>
<!-- Rear rack -->
<g transform="translate(280 150)">
<rect x="0" y="-50" width="60" height="100" rx="3" fill="#1a1a1a" stroke="#333" stroke-width="1.5"/>
<path d="M10 -50V-80M50 -50V-80" stroke="#3a3a3a" stroke-width="3" stroke-linecap="round"/>
<path d="M10 -80H50" stroke="#3a3a3a" stroke-width="3" stroke-linecap="round"/>
</g>
<!-- Front basket mount -->
<g transform="translate(160 90)">
<path d="M-15 0 L-25 -20 L25 -20 L15 0" fill="none" stroke="#3a3a3a" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<!-- Wheels -->
<g transform="translate(100 250)">
<circle r="55" stroke="#1a1a1a" stroke-width="3" fill="none"/>
<circle r="48" stroke="#2a2a2a" stroke-width="1.5" fill="none"/>
<g stroke="#333" stroke-width="1"><circle r="10" fill="none"/><path d="M0 -48V-10M0 10V48M-48 0H-10M10 0H48"/><g transform="rotate(45)"><path d="M0 -48V-10M0 10V48M-48 0H-10M10 0H48"/></g></g>
<circle r="58" stroke="#0a0a0a" stroke-width="4" fill="none"/>
<circle r="8" fill="#c9853a"/><circle r="5" fill="#1a1a1a"/>
</g>
<g transform="translate(300 250)">
<circle r="55" stroke="#1a1a1a" stroke-width="3" fill="none"/>
<circle r="48" stroke="#2a2a2a" stroke-width="1.5" fill="none"/>
<g stroke="#333" stroke-width="1"><circle r="10" fill="none"/><path d="M0 -48V-10M0 10V48M-48 0H-10M10 0H48"/><g transform="rotate(45)"><path d="M0 -48V-10M0 10V48M-48 0H-10M10 0H48"/></g></g>
<circle r="58" stroke="#0a0a0a" stroke-width="4" fill="none"/>
<circle r="8" fill="#c9853a"/><circle r="5" fill="#1a1a1a"/>
<ellipse cx="0" cy="0" rx="28" ry="28" fill="none" stroke="#2a2a2a" stroke-width="6"/>
</g>
</svg>
</div>
<div class="model-info">
<span class="model-category">Compact Utility</span>
<h3>Lumen Compact</h3>
<p>Standard wheelbase, integrated rear rack, and front basket mounts. The daily driver that fits in an apartment elevator and carries a week of groceries.</p>
<div class="model-specs">
<span class="spec-item"><strong>Rack:</strong> MIK HD compatible</span>
<span class="spec-item"><strong>Load:</strong> 100 kg</span>
<span class="spec-item"><strong>Weight:</strong> 21 kg</span>
</div>
<div class="model-price">From €3,200<span>+ VAT</span></div>
<button class="btn-model" type="button">Configure This Model</button>
</div>
</article>
</div>
</div>
</section>
<!-- Workshop / Trust -->
<section id="workshop" class="workshop" aria-labelledby="workshop-title">
<div class="container workshop-grid">
<div class="workshop-content">
<header class="section-header reveal" style="text-align: left; margin-bottom: var(--space-xl);">
<span class="section-tag" style="display: inline-block;">Refshaleøen, Copenhagen</span>
<h2 id="workshop-title">Where every Lumen is born</h2>
<p>Our 200 m² workshop on Refshaleøen houses a frame jig, TIG station, powder-coat line, and a test track around the harbor. Three frame builders. One standard.</p>
</header>
<div class="workshop-stats">
<div class="stat reveal"><span class="stat-value">47</span><span class="stat-label">Frames built in 2024</span></div>
<div class="stat reveal reveal-delay-1"><span class="stat-value">0</span><span class="stat-label">Frames outsourced</span></div>
<div class="stat reveal reveal-delay-2"><span class="stat-value">10</span><span class="stat-label">Year frame warranty</span></div>
<div class="stat reveal reveal-delay-3"><span class="stat-value">3</span><span class="stat-label">Full-time builders</span></div>
</div>
<div class="workshop-details">
<article class="detail-item reveal">
<svg class="detail-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5"/></svg>
<div><strong>Columbus Life Tubing</strong><span>Spirit/HSS double-butted chromoly. Chosen for ride quality, fatigue life, and repairability.</span></div>
</article>
<article class="detail-item reveal reveal-delay-1">
<svg class="detail-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
<div><strong>4-Week Lead Time</strong><span>From deposit to delivery. We batch in fours to keep quality high and wait times honest.</span></div>
</article>
<article class="detail-item reveal reveal-delay-2">
<svg class="detail-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M20 6L9 17l-5-5"/></svg>
<div><strong>ISO 4210 Certified</strong><span>Every frame passes EN 15194 and ISO 4210 fatigue testing before it leaves the jig.</span></div>
</article>
<article class="detail-item reveal reveal-delay-3">
<svg class="detail-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/></svg>
<div><strong>Personal Handover</strong><span>Pick up in Copenhagen or we ship EU-wide in a reusable flight case. First service included.</span></div>
</article>
</div>
</div>
<div class="workshop-visual reveal">
<div class="workshop-image">
<svg viewBox="0 0 400 500" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" aria-label="Lumen workshop interior illustration">
<defs>
<linearGradient id="wsBg" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" stop-color="#121212"/>
<stop offset="100%" stop-color="#0a0a0a"/>
</linearGradient>
<linearGradient id="wsAccent" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#c9853a"/>
<stop offset="100%" stop-color="#e8a85a"/>
</linearGradient>
</defs>
<rect width="400" height="500" fill="url(#wsBg)"/>
<!-- Workbenches -->
<g stroke="#2a2a2a" stroke-width="2" fill="none">
<rect x="30" y="60" width="160" height="80" rx="4"/>
<rect x="210" y="60" width="160" height="80" rx="4"/>
<rect x="30" y="160" width="340" height="100" rx="4"/>
</g>
<!-- Frame jig -->
<g transform="translate(80 180)" stroke="#c9853a" stroke-width="3" fill="none" opacity="0.6">
<rect x="0" y="0" width="120" height="100" rx="4"/>
<path d="M60 0V-20M0 50H-20M120 50H140M60 100V120" stroke-width="2"/>
<circle cx="60" cy="50" r="25" fill="none" stroke-dasharray="8 4"/>
</g>
<!-- Tools on wall -->
<g transform="translate(320 100)" stroke="#3a3a3a" stroke-width="2" fill="none" stroke-linecap="round">
<path d="M0 0V-40M-10 -30H10"/>
<path d="M30 0V-50M20 -40H40" transform="rotate(90)"/>
<circle cx="-30" cy="-20" r="12"/>
<path d="M-30 -32V-8"/>
</g>
<!-- Frames hanging -->
<g transform="translate(50 300)" stroke="#3a3a3a" stroke-width="4" fill="none" stroke-linecap="round" stroke-linejoin="round">
<path d="M0 0 L40 -50 L120 -50 L140 0 L120 40 L40 40 Z"/>
<path d="M40 -50 L40 -80"/>
<path d="M120 -50 L120 -70"/>
</g>
<g transform="translate(220 300)" stroke="#3a3a3a" stroke-width="4" fill="none" stroke-linecap="round" stroke-linejoin="round" opacity="0.7">
<path d="M0 0 L40 -50 L120 -50 L140 0 L120 40 L40 40 Z"/>
<path d="M40 -50 L40 -80"/>
<path d="M120 -50 L120 -70"/>
</g>
<!-- Floor pattern -->
<g stroke="#1a1a1a" stroke-width="1" opacity="0.5">
<line x1="0" y1="450" x2="400" y2="450"/>
<line x1="0" y1="470" x2="400" y2="470"/>
<line x1="0" y1="490" x2="400" y2="490"/>
</g>
<!-- Overhead lights -->
<g transform="translate(0 20)">
<ellipse cx="100" cy="0" rx="60" ry="8" fill="url(#wsAccent)" opacity="0.15"/>
<ellipse cx="300" cy="0" rx="60" ry="8" fill="url(#wsAccent)" opacity="0.15"/>
</g>
</svg>
<div class="workshop-badge">Open for visits · Thu–Sat 10–17</div>
</div>
</div>
</div>
</section>
<!-- Testimonials -->
<section class="testimonials" aria-labelledby="testimonials-title">
<div class="container">
<header class="section-header reveal">
<span class="section-tag">Rider Stories</span>
<h2 id="testimonials-title">Built for real lives</h2>
</header>
<div class="testimonials-track">
<article class="testimonial reveal">
<header class="testimonial-header">
<div class="testimonial-avatar">MA</div>
<div class="testimonial-meta">
<h4>Mette Andersen</h4>
<p>Copenhagen, 2 kids</p>
</div>
</header>
<p class="testimonial-text">"The Long replaced our second car. School runs, grocery hauls, weekend trips to the summer house — it handles all of it. The linked steering took one ride to feel natural."</p>
<p class="testimonial-bike">Rides: Lumen Long · Bosch Cargo Line</p>
</article>
<article class="testimonial reveal reveal-delay-1">
<header class="testimonial-header">
<div class="testimonial-avatar">JN</div>
<div class="testimonial-meta">
<h4>Jonas Nielsen</h4>
<p>Frederiksberg, photographer</p>
</div>
</header>
<p class="testimonial-text">"I needed something that fits in my building's elevator but carries lighting kits. The Compact with a custom rack system is perfect. The ride quality surprises me every time."</p>
<p class="testimonial-bike">Rides: Lumen Compact · Shimano EP801</p>
</article>
<article class="testimonial reveal reveal-delay-2">
<header class="testimonial-header">
<div class="testimonial-avatar">SH</div>
<div class="testimonial-meta">
<h4>Sofie Hansen</h4>
<p>Aarhus, bakery owner</p>
</div>
</header>
<p class="testimonial-text">"Delivering 80 kg of sourdough three times a week. The Front's platform is rock solid at speed, and the Bosch motor makes hills feel flat. Best business investment I've made."</p>
<p class="testimonial-bike">Rides: Lumen Front · Bosch Cargo Line Speed</p>
</article>
</div>
</div>
</section>
<!-- CTA / Contact -->
<section id="contact" class="cta" aria-labelledby="contact-title">
<div class="container cta-inner">
<header class="reveal">
<h2 id="contact-title">Start your build</h2>
<p>Tell us what you carry, where you ride, and what matters to you. We'll reply within 24 hours with a build proposal and timeline.</p>
</header>
<form class="cta-form reveal reveal-delay-1" id="contact-form" novalidate>
<div class="form-group">
<label for="name">Full Name</label>
<input type="text" id="name" name="name" required autocomplete="name" placeholder="Your name">
<span class="form-error" id="name-error" aria-live="polite"></span>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" required autocomplete="email" placeholder="you@example.com">
<span class="form-error" id="email-error" aria-live="polite"></span>
</div>
<div class="form-group" style="grid-column: 1 / -1;">
<label for="message">What are you building for?</label>
<textarea id="message" name="message" rows="4" required placeholder="Kids, groceries, business, adventures — tell us the story."></textarea>
<span class="form-error" id="message-error" aria-live="polite"></span>
</div>
<button type="submit" class="btn btn-primary">Send Inquiry</button>
<p class="form-note">No spam. No newsletter unless you ask. Your data stays in Copenhagen.</p>
</form>
<div id="form-success" class="form-success" style="display: none;" aria-live="polite"></div>
</div>
</section>
</main>
<!-- Footer -->
<footer role="contentinfo">
<div class="container">
<div class="footer-grid">
<div class="footer-brand">
<a href="#" class="logo" aria-label="Lumen Cycles - Home">
<svg class="logo-mark" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<circle cx="16" cy="16" r="14" stroke="currentColor" stroke-width="1.5"/>
<path d="M16 6V22M6 16H22" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
<circle cx="16" cy="16" r="6" stroke="currentColor" stroke-width="1.5"/>
</svg>
Lumen Cycles
</a>
<p>Custom cargo bikes, hand-built in Copenhagen. Designed for your life, built to last generations.</p>
<div class="social-links">
<a href="#" aria-label="Instagram"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2" y="2" width="20" height="20" rx="5"/><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"/><line x1="17.5" y1="6.5" x2="17.51" y2="6.5"/></svg></a>
<a href="#" aria-label="YouTube"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2.5 17a24.12 24.12 0 0 1 0-10 2 2 0 0 1 1.4-1.4 49.56 49.56 0 0 1 16.2 0A2 2 0 0 1 21.5 7a24.12 24.12 0 0 1 0 10 2 2 0 0 1-1.4 1.4 49.55 49.55 0 0 1-16.2 0A2 2 0 0 1 2.5 17"/><polygon points="10 15 15.5 12 10 9 10 15"/></svg></a>
<a href="#" aria-label="LinkedIn"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"/><rect x="2" y="9" width="4" height="12"/><circle cx="4" cy="4" r="2"/></svg></a>
</div>
</div>
<nav class="footer-nav" aria-label="Company">
<h4>Company</h4>
<ul>
<li><a href="#philosophy">Philosophy</a></li>
<li><a href="#process">Process</a></li>
<li><a href="#workshop">Workshop</a></li>
<li><a href="#">Journal</a></li>
<li><a href="#">Careers</a></li>
</ul>
</nav>
<nav class="footer-nav" aria-label="Models">
<h4>Models</h4>
<ul>
<li><a href="#models">Lumen Long</a></li>
<li><a href="#models">Lumen Front</a></li>
<li><a href="#models">Lumen Compact</a></li>
<li><a href="#">Compare</a></li>
<li><a href="#contact">Custom Build</a></li>
</ul>
</nav>
<nav class="footer-nav" aria-label="Support">
<h4>Support</h4>
<ul>
<li><a href="#">Warranty</a></li>
<li><a href="#">Service & Repair</a></li>
<li><a href="#">Shipping</a></li>
<li><a href="#">FAQ</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</nav>
</div>
<div class="footer-bottom">
<p>© 2025 Lumen Cycles ApS. CVR: 41234567. Refshalevej 121, 1432 Copenhagen K.</p>
<div class="footer-legal">
<a href="#">Privacy</a>
<a href="#">Terms</a>
<a href="#">Cookie Policy</a>
</div>
</div>
</div>
</footer>
<script>
// --- Initialize ---
document.addEventListener('DOMContentLoaded', () => {
initHeader();
initMobileMenu();
initRevealObserver();
initBikeAnimation();
initContactForm();
initSmoothScroll();
});
// --- Header scroll state ---
function initHeader() {
const header = document.getElementById('header');
let lastScroll = 0;
window.addEventListener('scroll', () => {
const currentScroll = window.scrollY;
if (currentScroll > 50) {
header.classList.add('scrolled');
} else {
header.classList.remove('scrolled');
}
lastScroll = currentScroll;
}, { passive: true });
}
// --- Mobile Menu ---
function initMobileMenu() {
const btn = document.getElementById('menu-btn');
const menu = document.getElementById('mobile-menu');
const overlay = document.getElementById('menu-overlay');
const closeBtn = document.getElementById('menu-close');
const links = menu.querySelectorAll('a');
function openMenu() {
menu.classList.add('open');
overlay.classList.add('visible');
btn.setAttribute('aria-expanded', 'true');
overlay.setAttribute('aria-hidden', 'false');
document.body.style.overflow = 'hidden';
// Focus first link
setTimeout(() => menu.querySelector('nav a')?.focus(), 300);
}
function closeMenu() {
menu.classList.remove('open');
overlay.classList.remove('visible');
btn.setAttribute('aria-expanded', 'false');
overlay.setAttribute('aria-hidden', 'true');
document.body.style.overflow = '';
}
btn.addEventListener('click', openMenu);
closeBtn.addEventListener('click', closeMenu);
overlay.addEventListener('click', closeMenu);
links.forEach(link => link.addEventListener('click', closeMenu));
// ESC key
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && menu.classList.contains('open')) closeMenu();
});
}
// --- Intersection Observer for Reveal ---
function initRevealObserver() {
const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (prefersReduced) {
document.querySelectorAll('.reveal').forEach(el => el.classList.add('visible'));
return;
}
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
observer.unobserve(entry.target);
}
});
}, { threshold: 0.1, rootMargin: '0px 0px -50px 0px' });
document.querySelectorAll('.reveal').forEach(el => observer.observe(el));
}
// --- Bike SVG Animation ---
function initBikeAnimation() {
const bikeSvg = document.getElementById('bike-svg');
if (!bikeSvg) return;
// Trigger animation when hero is visible
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
bikeSvg.classList.add('loaded');
observer.unobserve(entry.target);
}
});
}, { threshold: 0.3 });
observer.observe(document.querySelector('.hero'));
}
// --- Contact Form ---
function initContactForm() {
const form = document.getElementById('contact-form');
const successEl = document.getElementById('form-success');
if (!form) return;
const validators = {
name: (v) => v.trim().length >= 2 || 'Please enter your name',
email: (v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v) || 'Please enter a valid email',
message: (v) => v.trim().length >= 20 || 'Tell us a bit more (at least 20 characters)'
};
function showError(field, message) {
const input = form.querySelector(`#${field}`);
const errorEl = form.querySelector(`#${field}-error`);
if (input && errorEl) {
input.setAttribute('aria-invalid', 'true');
errorEl.textContent = message;
}
}
function clearError(field) {
const input = form.querySelector(`#${field}`);
const errorEl = form.querySelector(`#${field}-error`);
if (input && errorEl) {
input.removeAttribute('aria-invalid');
errorEl.textContent = '';
}
}
form.addEventListener('submit', async (e) => {
e.preventDefault();
let valid = true;
Object.keys(validators).forEach(field => {
const input = form.querySelector(`#${field}`);
if (input) {
const error = validators[field](input.value);
if (error !== true) {
showError(field, error);
valid = false;
} else {
clearError(field);
}
}
});
if (!valid) return;
// Simulate submission
const submitBtn = form.querySelector('button[type="submit"]');
const originalText = submitBtn.textContent;
submitBtn.disabled = true;
submitBtn.textContent = 'Sending…';
await new Promise(r => setTimeout(r, 1500));
form.style.display = 'none';
successEl.style.display = 'block';
successEl.innerHTML = `
<strong>Thank you.</strong> We've received your inquiry and will reply within 24 hours.
<br><br>
<button type="button" class="btn btn-secondary" style="margin-top: var(--space-md);" onclick="resetForm()">Start Another</button>
`;
});
// Real-time validation
Object.keys(validators).forEach(field => {
const input = form.querySelector(`#${field}`);
if (input) {
input.addEventListener('blur', () => {
const error = validators[field](input.value);
if (error !== true) showError(field, error);
else clearError(field);
});
input.addEventListener('input', () => {
if (input.hasAttribute('aria-invalid')) {
const error = validators[field](input.value);
if (error === true) clearError(field);
}
});
}
});
// Expose reset globally
window.resetForm = () => {
form.reset();
form.style.display = 'grid';
successEl.style.display = 'none';
successEl.innerHTML = '';
Object.keys(validators).forEach(clearError);
};
}
// --- Smooth Scroll with Offset ---
function initSmoothScroll() {
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
const targetId = this.getAttribute('href');
if (targetId === '#') return;
const target = document.querySelector(targetId);
if (target) {
e.preventDefault();
const header = document.getElementById('header');
const offset = header?.offsetHeight || 80;
const targetPosition = target.getBoundingClientRect().top + window.scrollY - offset;
window.scrollTo({ top: targetPosition, behavior: 'smooth' });
target.focus({ preventScroll: true });
}
});
});
}
</script>
</body>
</html>

