Run details
- Model
- deepseek/deepseek-v4.1-flash
- Route
- Command Code CLI
- Reasoning
- provider default
- Limits
- 60 min · 943,718 output tokens
- Date
- 2 Oct 2026
- Time
- 13 min 56 s
- Size
- 67 kB
- Tokens
- 1,228,655 in, 42,276 out
- List price
- $0.076 ($0.049 in / $0.375 out per M)
- Paid
- Not billed per run (CLI plan)
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). Save it as index.html in the current directory, then stop. Do not ask questions.
Source
67 kB 1,386 lines Raw
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Lumen Cycles — Custom cargo bikes, hand-built in Copenhagen</title>
<meta name="description" content="Lumen Cycles is a Copenhagen workshop building custom cargo bikes to order. Measured for your routes, welded in Nørrebro, serviced for life.">
<meta name="theme-color" content="#F4F0E7">
<meta name="color-scheme" content="light">
<style>
:root{
--paper:#F4F0E7;
--paper-2:#EAE3D6;
--paper-3:#FCFAF5;
--ink:#17170F;
--ink-soft:#45423A;
--muted:#78715F;
--line:#DCD4C4;
--line-soft:#E7E0D2;
--green:#1C4A3C;
--green-deep:#143A2E;
--brass:#B08A4E;
--brass-soft:#C9A97A;
--serif:"Iowan Old Style","Palatino Linotype",Palatino,"Book Antiqua",Georgia,"Times New Roman",serif;
--sans:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
--mono:ui-monospace,SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;
--shadow-sm:0 1px 2px rgba(23,23,15,.05),0 2px 8px rgba(23,23,15,.04);
--shadow-md:0 2px 6px rgba(23,23,15,.06),0 18px 40px -18px rgba(23,23,15,.28);
--shadow-lg:0 4px 12px rgba(23,23,15,.07),0 40px 80px -32px rgba(23,23,15,.42);
--r:14px;
--ease:cubic-bezier(.2,.7,.2,1);
}
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
html:focus-within{scroll-behavior:smooth}
body{
margin:0;
background:var(--paper);
color:var(--ink);
font-family:var(--sans);
font-size:17px;
line-height:1.62;
-webkit-font-smoothing:antialiased;
-moz-osx-font-smoothing:grayscale;
text-rendering:optimizeLegibility;
overflow-x:hidden;
}
/* paper grain — inline SVG data URI, no network */
body::after{
content:"";
position:fixed;
inset:0;
z-index:9999;
pointer-events:none;
opacity:.32;
mix-blend-mode:multiply;
background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E");
}
h1,h2,h3,h4{
font-family:var(--serif);
font-weight:400;
line-height:1.08;
letter-spacing:-.015em;
margin:0;
text-wrap:balance;
}
p{margin:0 0 1.1em}
p:last-child{margin-bottom:0}
a{color:inherit;text-decoration:none}
img,svg{display:block;max-width:100%}
button,input,select,textarea{font:inherit;color:inherit}
::selection{background:var(--green);color:var(--paper-3)}
:focus-visible{outline:2px solid var(--green);outline-offset:3px;border-radius:4px}
.skip{
position:absolute;left:12px;top:-60px;z-index:200;
background:var(--ink);color:var(--paper-3);
padding:.6rem 1rem;border-radius:8px;transition:top .2s var(--ease);
}
.skip:focus{top:12px}
.wrap{width:min(1180px,100% - 44px);margin-inline:auto}
.wrap-narrow{width:min(820px,100% - 44px);margin-inline:auto}
.eyebrow{
display:flex;align-items:center;gap:.7rem;
font-family:var(--sans);
font-size:.7rem;
letter-spacing:.2em;
text-transform:uppercase;
font-weight:600;
color:var(--muted);
margin:0 0 1.6rem;
}
.eyebrow::before{content:"";width:26px;height:1px;background:var(--brass);flex:none}
.eyebrow.center{justify-content:center}
.eyebrow.center::after{content:"";width:26px;height:1px;background:var(--brass);flex:none}
.sec{padding:clamp(72px,9vw,132px) 0;position:relative}
.sec-tight{padding:clamp(56px,6vw,88px) 0}
.rule{border-top:1px solid var(--line-soft)}
.h-xl{font-size:clamp(2.55rem,6.1vw,4.55rem)}
.h-lg{font-size:clamp(2rem,4.2vw,3.15rem)}
.h-md{font-size:clamp(1.4rem,2.3vw,1.9rem)}
.lede{font-size:clamp(1.05rem,1.5vw,1.22rem);color:var(--ink-soft);max-width:60ch}
.muted{color:var(--muted)}
.serif{font-family:var(--serif)}
/* ---------- buttons ---------- */
.btn{
--bg:var(--ink);--fg:var(--paper-3);--bd:var(--ink);
display:inline-flex;align-items:center;justify-content:center;gap:.6rem;
padding:.92rem 1.6rem;
background:var(--bg);color:var(--fg);border:1px solid var(--bd);
border-radius:999px;
font-size:.9rem;font-weight:600;letter-spacing:.005em;
cursor:pointer;
transition:transform .25s var(--ease),box-shadow .25s var(--ease),background .25s var(--ease),color .25s var(--ease),border-color .25s var(--ease);
box-shadow:var(--shadow-sm);
}
.btn:hover{transform:translateY(-2px);box-shadow:var(--shadow-md)}
.btn:active{transform:translateY(0)}
.btn--ghost{--bg:transparent;--fg:var(--ink);--bd:var(--line);box-shadow:none}
.btn--ghost:hover{--bg:var(--paper-3);--bd:var(--ink)}
.btn--green{--bg:var(--green);--bd:var(--green)}
.btn--green:hover{--bg:var(--green-deep);--bd:var(--green-deep)}
.btn--block{width:100%}
.btn .arw{transition:transform .25s var(--ease)}
.btn:hover .arw{transform:translateX(3px)}
/* ---------- header ---------- */
.announce{
background:var(--green);color:#EAF1EC;
font-size:.775rem;letter-spacing:.04em;
}
.announce .wrap{display:flex;align-items:center;justify-content:center;gap:1rem;min-height:38px;text-align:center}
.announce b{font-weight:600;color:#fff}
.announce .tick{width:6px;height:6px;border-radius:50%;background:var(--brass-soft);flex:none}
header.site{
position:sticky;top:0;z-index:100;
background:rgba(244,240,231,.82);
backdrop-filter:saturate(150%) blur(14px);
-webkit-backdrop-filter:saturate(150%) blur(14px);
border-bottom:1px solid transparent;
transition:border-color .3s var(--ease),box-shadow .3s var(--ease),background .3s var(--ease);
}
header.site.stuck{border-bottom-color:var(--line);box-shadow:0 8px 30px -22px rgba(23,23,15,.5);background:rgba(244,240,231,.94)}
.nav{display:flex;align-items:center;gap:2rem;min-height:74px}
.brand{display:flex;align-items:center;gap:.72rem;flex:none}
.brand .mark{width:30px;height:30px;color:var(--green)}
.brand .word{
font-family:var(--serif);font-size:1.32rem;letter-spacing:.005em;line-height:1;
}
.brand .word small{display:block;font-family:var(--sans);font-size:.56rem;letter-spacing:.34em;text-transform:uppercase;color:var(--muted);margin-top:4px}
.nav-links{display:flex;gap:1.9rem;margin-left:auto;align-items:center}
.nav-links a{font-size:.86rem;color:var(--ink-soft);position:relative;padding:.3rem 0;font-weight:500}
.nav-links a::after{
content:"";position:absolute;left:0;right:100%;bottom:0;height:1px;background:var(--ink);
transition:right .3s var(--ease);
}
.nav-links a:hover{color:var(--ink)}
.nav-links a:hover::after{right:0}
.nav-cta{display:flex;align-items:center;gap:.75rem;flex:none}
.nav-cta .btn{padding:.72rem 1.25rem;font-size:.83rem}
.burger{
display:none;width:44px;height:44px;border:1px solid var(--line);background:var(--paper-3);
border-radius:12px;cursor:pointer;align-items:center;justify-content:center;
}
.burger span{display:block;width:18px;height:1.5px;background:var(--ink);position:relative}
.burger span::before,.burger span::after{content:"";position:absolute;left:0;width:18px;height:1.5px;background:var(--ink);transition:transform .25s var(--ease),top .25s var(--ease)}
.burger span::before{top:-6px}
.burger span::after{top:6px}
.burger[aria-expanded="true"] span{background:transparent}
.burger[aria-expanded="true"] span::before{top:0;transform:rotate(45deg)}
.burger[aria-expanded="true"] span::after{top:0;transform:rotate(-45deg)}
.mobile-menu{
display:none;border-bottom:1px solid var(--line);background:var(--paper);
}
.mobile-menu.open{display:block}
.mobile-menu nav{display:flex;flex-direction:column;padding:.5rem 0 1.4rem}
.mobile-menu a{padding:.85rem 0;border-bottom:1px solid var(--line-soft);font-family:var(--serif);font-size:1.35rem}
.mobile-menu .btn{margin-top:1.2rem}
/* ---------- hero ---------- */
.hero{padding:clamp(44px,6vw,84px) 0 clamp(56px,7vw,96px);position:relative;overflow:hidden}
.hero::before{
content:"";position:absolute;z-index:0;
width:760px;height:760px;right:-260px;top:-300px;border-radius:50%;
background:radial-gradient(circle at 50% 50%,rgba(176,138,78,.20),rgba(176,138,78,0) 62%);
pointer-events:none;
}
.hero-grid{display:grid;grid-template-columns:minmax(0,1.02fr) minmax(0,1fr);gap:clamp(2rem,4vw,4.5rem);align-items:center;position:relative;z-index:1}
.hero h1{margin-bottom:1.4rem}
.hero h1 em{font-style:italic;color:var(--green)}
.hero .lede{max-width:46ch}
.hero-actions{display:flex;flex-wrap:wrap;gap:.85rem;margin-top:2.2rem}
.hero-trust{display:flex;flex-wrap:wrap;gap:.5rem 1.6rem;margin-top:2.4rem;padding-top:1.6rem;border-top:1px solid var(--line-soft)}
.hero-trust li{display:flex;align-items:center;gap:.5rem;font-size:.8rem;color:var(--muted);list-style:none}
.hero-trust svg{width:15px;height:15px;color:var(--green);flex:none}
.hero-trust ul{display:flex;flex-wrap:wrap;gap:.5rem 1.6rem;margin:0;padding:0}
.hero-panel{
position:relative;
background:linear-gradient(168deg,var(--paper-3) 0%, #EFE8DA 100%);
border:1px solid var(--line);
border-radius:24px;
padding:clamp(1.4rem,2.6vw,2.4rem);
box-shadow:var(--shadow-lg);
overflow:hidden;
}
.hero-panel::before{
content:"";position:absolute;inset:0;
background-image:linear-gradient(var(--line-soft) 1px,transparent 1px),linear-gradient(90deg,var(--line-soft) 1px,transparent 1px);
background-size:38px 38px;
opacity:.5;
-webkit-mask-image:radial-gradient(120% 100% at 50% 40%,#000 30%,transparent 78%);
mask-image:radial-gradient(120% 100% at 50% 40%,#000 30%,transparent 78%);
pointer-events:none;
}
.panel-top{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;position:relative}
.panel-top .tag{
font-family:var(--mono);font-size:.68rem;letter-spacing:.12em;text-transform:uppercase;color:var(--muted)
}
.panel-top .slot{
display:inline-flex;align-items:center;gap:.5rem;
font-size:.72rem;font-weight:600;color:var(--green);
background:rgba(28,74,60,.08);border:1px solid rgba(28,74,60,.18);
padding:.3rem .7rem;border-radius:999px;
}
.panel-art{position:relative;padding:clamp(1rem,3vw,2.2rem) 0 clamp(.5rem,1.5vw,1rem)}
.panel-art svg{width:100%;height:auto}
.panel-caption{
position:relative;display:flex;justify-content:space-between;align-items:flex-end;gap:1rem;
border-top:1px solid var(--line);padding-top:1.1rem;flex-wrap:wrap;
}
.panel-caption .spec{font-family:var(--mono);font-size:.72rem;color:var(--muted);letter-spacing:.03em;line-height:1.7}
.panel-caption .spec b{color:var(--ink);font-weight:600}
.panel-caption .price{font-family:var(--serif);font-size:1.4rem;white-space:nowrap}
/* ---------- stat strip ---------- */
.stats{border-top:1px solid var(--line);border-bottom:1px solid var(--line);background:var(--paper-2)}
.stats-grid{display:grid;grid-template-columns:repeat(4,1fr)}
.stat{padding:1.9rem 1.4rem;text-align:center;border-left:1px solid var(--line)}
.stat:first-child{border-left:0}
.stat b{display:block;font-family:var(--serif);font-size:clamp(1.5rem,2.6vw,2.05rem);letter-spacing:-.02em;line-height:1}
.stat span{display:block;margin-top:.5rem;font-size:.74rem;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
/* ---------- generic two-col ---------- */
.split{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:clamp(2rem,6vw,5.5rem);align-items:start}
.split--wide-left{grid-template-columns:minmax(0,1.15fr) minmax(0,.85fr)}
.principles{list-style:none;margin:2.4rem 0 0;padding:0;display:grid;gap:0}
.principles li{display:grid;grid-template-columns:auto 1fr;gap:1.1rem;padding:1.25rem 0;border-top:1px solid var(--line-soft)}
.principles li:last-child{border-bottom:1px solid var(--line-soft)}
.principles .n{font-family:var(--mono);font-size:.72rem;color:var(--brass);padding-top:.35rem;letter-spacing:.08em}
.principles h4{font-family:var(--sans);font-size:.95rem;font-weight:600;letter-spacing:0;margin-bottom:.25rem}
.principles p{font-size:.92rem;color:var(--ink-soft);margin:0}
.sig{margin-top:2.4rem;display:flex;align-items:center;gap:1.1rem}
.sig .avatar{
width:52px;height:52px;border-radius:50%;flex:none;
background:var(--green);color:#E9F0EA;
display:grid;place-items:center;font-family:var(--serif);font-size:1.15rem;
}
.sig p{margin:0;font-size:.86rem;color:var(--muted)}
.sig strong{display:block;font-family:var(--serif);font-size:1.05rem;color:var(--ink);font-weight:400}
/* workshop figure — inline SVG blueprint */
.figure{
border:1px solid var(--line);border-radius:20px;background:var(--paper-3);
box-shadow:var(--shadow-md);overflow:hidden;
}
.figure .fig-head{
display:flex;justify-content:space-between;align-items:center;gap:1rem;
padding:.85rem 1.2rem;border-bottom:1px solid var(--line-soft);
font-family:var(--mono);font-size:.66rem;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);
}
.figure .fig-body{padding:clamp(1rem,2.4vw,1.8rem)}
.fig-note{
padding:1rem 1.2rem;border-top:1px solid var(--line-soft);font-size:.82rem;color:var(--muted);
display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;
}
/* ---------- models ---------- */
.cards{display:grid;grid-template-columns:repeat(3,1fr);gap:1.4rem;margin-top:3.4rem}
.card{
background:var(--paper-3);border:1px solid var(--line);border-radius:20px;
padding:1.6rem;display:flex;flex-direction:column;
box-shadow:var(--shadow-sm);
transition:transform .35s var(--ease),box-shadow .35s var(--ease),border-color .35s var(--ease);
}
.card:hover{transform:translateY(-5px);box-shadow:var(--shadow-lg);border-color:#CFC5B2}
.card .thumb{
background:linear-gradient(170deg,#F7F3EA,#EBE4D5);border:1px solid var(--line-soft);
border-radius:14px;padding:.6rem .4rem;margin-bottom:1.4rem;
}
.card .thumb svg{width:100%;height:auto}
.card .kicker{font-family:var(--mono);font-size:.66rem;letter-spacing:.14em;text-transform:uppercase;color:var(--brass)}
.card h3{font-size:1.62rem;margin:.5rem 0 .35rem}
.card .blurb{font-size:.9rem;color:var(--ink-soft);min-height:4.4em}
.card ul{list-style:none;margin:1.1rem 0 1.4rem;padding:0;display:grid;gap:.45rem}
.card li{display:flex;gap:.6rem;font-size:.84rem;color:var(--ink-soft);align-items:flex-start}
.card li svg{width:14px;height:14px;color:var(--green);flex:none;margin-top:5px}
.card .foot{margin-top:auto;display:flex;align-items:center;justify-content:space-between;gap:1rem;border-top:1px solid var(--line-soft);padding-top:1.2rem}
.card .from{font-family:var(--serif);font-size:1.28rem;line-height:1.1}
.card .from small{display:block;font-family:var(--sans);font-size:.66rem;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);margin-bottom:.2rem}
.card .pick{
border:1px solid var(--line);background:transparent;border-radius:999px;
padding:.55rem 1rem;font-size:.8rem;font-weight:600;cursor:pointer;
transition:background .25s var(--ease),color .25s var(--ease),border-color .25s var(--ease);
}
.card .pick:hover{background:var(--ink);color:var(--paper-3);border-color:var(--ink)}
/* ---------- configurator ---------- */
.config{background:var(--ink);color:#EDE8DC;position:relative;overflow:hidden}
.config::before{
content:"";position:absolute;left:-180px;bottom:-260px;width:620px;height:620px;border-radius:50%;
background:radial-gradient(circle,rgba(28,74,60,.55),transparent 65%);pointer-events:none;
}
.config::after{
content:"";position:absolute;right:-160px;top:-200px;width:520px;height:520px;border-radius:50%;
background:radial-gradient(circle,rgba(176,138,78,.22),transparent 65%);pointer-events:none;
}
.config .eyebrow{color:rgba(237,232,220,.6)}
.config .lede{color:rgba(237,232,220,.72)}
.config-head{max-width:64ch;position:relative;z-index:1}
.config-head h2{color:#FCFAF5}
.config-grid{
display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);gap:clamp(2rem,4vw,3.4rem);
margin-top:3.2rem;position:relative;z-index:1;align-items:start;
}
.stage{
background:linear-gradient(170deg,rgba(252,250,245,.08),rgba(252,250,245,.02));
border:1px solid rgba(237,232,220,.16);border-radius:22px;
padding:clamp(1.2rem,2.6vw,2rem);
position:sticky;top:104px;
}
.stage .stage-art{
background:radial-gradient(120% 100% at 50% 30%,rgba(237,232,220,.96),rgba(226,219,205,.9));
border-radius:16px;padding:clamp(.9rem,2.4vw,1.8rem) .6rem;position:relative;overflow:hidden;
}
.stage .stage-art::before{
content:"";position:absolute;inset:0;
background-image:linear-gradient(rgba(23,23,15,.05) 1px,transparent 1px),linear-gradient(90deg,rgba(23,23,15,.05) 1px,transparent 1px);
background-size:30px 30px;
}
.stage .stage-art svg{position:relative;width:100%;height:auto;transition:color .5s var(--ease)}
.stage .stage-meta{display:flex;justify-content:space-between;align-items:flex-end;gap:1rem;margin-top:1.4rem;flex-wrap:wrap}
.stage .stage-meta .label{font-family:var(--mono);font-size:.66rem;letter-spacing:.14em;text-transform:uppercase;color:rgba(237,232,220,.55)}
.stage .stage-meta .val{font-family:var(--serif);font-size:1.25rem;color:#FCFAF5;margin-top:.3rem}
.stage .total{font-family:var(--serif);font-size:clamp(1.9rem,3.4vw,2.5rem);color:#FCFAF5;line-height:1}
.stage .total small{display:block;font-family:var(--sans);font-size:.66rem;letter-spacing:.14em;text-transform:uppercase;color:rgba(237,232,220,.55);margin-bottom:.45rem}
.stage .note{font-size:.78rem;color:rgba(237,232,220,.55);margin-top:1.1rem}
fieldset{border:0;margin:0 0 1.9rem;padding:0}
fieldset:last-of-type{margin-bottom:1.2rem}
legend{
font-family:var(--sans);font-size:.72rem;font-weight:600;letter-spacing:.16em;text-transform:uppercase;
color:rgba(237,232,220,.6);padding:0 0 .8rem;
}
.chips{display:flex;flex-wrap:wrap;gap:.55rem}
.chip input{position:absolute;opacity:0;width:1px;height:1px}
.chip label{
display:block;padding:.62rem 1.05rem;border:1px solid rgba(237,232,220,.22);border-radius:999px;
font-size:.83rem;cursor:pointer;color:rgba(237,232,220,.82);
transition:all .22s var(--ease);user-select:none;
}
.chip label:hover{border-color:rgba(237,232,220,.5);color:#FCFAF5}
.chip input:checked + label{background:#FCFAF5;border-color:#FCFAF5;color:var(--ink);font-weight:600}
.chip input:focus-visible + label{outline:2px solid var(--brass-soft);outline-offset:3px}
.chip .plus{font-family:var(--mono);font-size:.72rem;opacity:.7;margin-left:.35rem}
.swatches{display:flex;flex-wrap:wrap;gap:.75rem}
.sw input{position:absolute;opacity:0;width:1px;height:1px}
.sw label{
display:flex;flex-direction:column;gap:.5rem;align-items:center;cursor:pointer;
font-size:.7rem;color:rgba(237,232,220,.7);width:74px;text-align:center;
}
.sw .dot{
width:42px;height:42px;border-radius:50%;background:var(--c);
border:2px solid rgba(237,232,220,.3);
box-shadow:inset 0 -4px 8px rgba(0,0,0,.18);
transition:transform .25s var(--ease),box-shadow .25s var(--ease),border-color .25s var(--ease);
position:relative;
}
.sw .dot::after{
content:"";position:absolute;inset:-6px;border-radius:50%;border:1px solid transparent;transition:border-color .25s var(--ease);
}
.sw label:hover .dot{transform:scale(1.06)}
.sw input:checked + label{color:#FCFAF5}
.sw input:checked + label .dot{border-color:#FCFAF5}
.sw input:checked + label .dot::after{border-color:rgba(252,250,245,.45)}
.sw input:focus-visible + label .dot{outline:2px solid var(--brass-soft);outline-offset:4px}
/* ---------- steps ---------- */
.steps{list-style:none;margin:3.2rem 0 0;padding:0;display:grid;gap:0;counter-reset:s}
.steps li{
display:grid;grid-template-columns:76px minmax(0,1fr) minmax(0,.9fr);
gap:clamp(1rem,3vw,2.4rem);
padding:1.9rem 0;border-top:1px solid var(--line-soft);align-items:baseline;
}
.steps li:last-child{border-bottom:1px solid var(--line-soft)}
.steps .num{font-family:var(--mono);font-size:.8rem;color:var(--brass);letter-spacing:.1em}
.steps h3{font-size:1.3rem}
.steps .when{font-family:var(--mono);font-size:.7rem;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);margin-top:.5rem}
.steps p{font-size:.93rem;color:var(--ink-soft);margin:0}
/* ---------- testimonials ---------- */
.quotes{display:grid;grid-template-columns:repeat(3,1fr);gap:1.4rem;margin-top:3.2rem}
.quote{
background:var(--paper-3);border:1px solid var(--line);border-radius:20px;padding:1.8rem;
display:flex;flex-direction:column;gap:1.2rem;box-shadow:var(--shadow-sm);
}
.quote .stars{display:flex;gap:3px;color:var(--brass)}
.quote .stars svg{width:14px;height:14px}
.quote blockquote{margin:0;font-family:var(--serif);font-size:1.16rem;line-height:1.5;letter-spacing:-.01em}
.quote blockquote::before{content:"\201C"}
.quote blockquote::after{content:"\201D"}
.quote .who{margin-top:auto;display:flex;align-items:center;gap:.85rem;border-top:1px solid var(--line-soft);padding-top:1.2rem}
.quote .who .ib{
width:40px;height:40px;border-radius:50%;background:var(--paper-2);border:1px solid var(--line);
display:grid;place-items:center;font-family:var(--serif);font-size:.95rem;color:var(--green);flex:none;
}
.quote .who p{margin:0;font-size:.8rem;color:var(--muted);line-height:1.4}
.quote .who strong{display:block;color:var(--ink);font-size:.88rem;font-weight:600}
/* ---------- faq ---------- */
.faq{margin-top:3rem;border-top:1px solid var(--line-soft)}
.faq details{border-bottom:1px solid var(--line-soft)}
.faq summary{
list-style:none;cursor:pointer;padding:1.5rem 2.6rem 1.5rem 0;position:relative;
font-family:var(--serif);font-size:1.18rem;letter-spacing:-.01em;
transition:color .2s var(--ease);
}
.faq summary::-webkit-details-marker{display:none}
.faq summary:hover{color:var(--green)}
.faq summary::after{
content:"";position:absolute;right:.4rem;top:50%;width:13px;height:13px;margin-top:-7px;
background:
linear-gradient(var(--ink),var(--ink)) center/13px 1.5px no-repeat,
linear-gradient(var(--ink),var(--ink)) center/1.5px 13px no-repeat;
transition:transform .3s var(--ease),opacity .3s var(--ease);
}
.faq details[open] summary::after{transform:rotate(90deg);opacity:.5}
.faq .a{padding:0 4rem 1.7rem 0;color:var(--ink-soft);font-size:.95rem;animation:fade .35s var(--ease)}
@keyframes fade{from{opacity:0;transform:translateY(-6px)}to{opacity:1;transform:none}}
/* ---------- contact ---------- */
.contact{background:var(--paper-2);border-top:1px solid var(--line)}
.contact-grid{display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);gap:clamp(2rem,5vw,4.5rem)}
.contact-list{list-style:none;margin:2.2rem 0 0;padding:0;display:grid;gap:1.1rem}
.contact-list li{display:grid;grid-template-columns:auto 1fr;gap:.9rem;font-size:.9rem;color:var(--ink-soft)}
.contact-list svg{width:16px;height:16px;color:var(--green);margin-top:4px}
.contact-list strong{display:block;color:var(--ink);font-weight:600;font-size:.82rem;letter-spacing:.02em}
form.enquiry{background:var(--paper-3);border:1px solid var(--line);border-radius:22px;padding:clamp(1.4rem,3vw,2.2rem);box-shadow:var(--shadow-md)}
.field{margin-bottom:1.15rem}
.field label{display:block;font-size:.74rem;font-weight:600;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);margin-bottom:.5rem}
.field input,.field select,.field textarea{
width:100%;padding:.82rem .95rem;background:var(--paper);
border:1px solid var(--line);border-radius:11px;font-size:.94rem;
transition:border-color .2s var(--ease),background .2s var(--ease),box-shadow .2s var(--ease);
}
.field textarea{resize:vertical;min-height:96px}
.field input:focus,.field select:focus,.field textarea:focus{outline:none;border-color:var(--green);background:#fff;box-shadow:0 0 0 3px rgba(28,74,60,.12)}
.field .err{display:none;color:#A5342A;font-size:.76rem;margin-top:.4rem}
.field.invalid input,.field.invalid select,.field.invalid textarea{border-color:#A5342A;background:#FDF6F5}
.field.invalid .err{display:block}
.row{display:grid;grid-template-columns:1fr 1fr;gap:1rem}
.form-foot{display:flex;align-items:center;gap:1.2rem;flex-wrap:wrap;margin-top:1.5rem}
.form-foot .fineprint{font-size:.75rem;color:var(--muted);max-width:32ch}
.form-success{
display:none;text-align:center;padding:2.4rem 1rem;
}
.form-success.show{display:block;animation:fade .4s var(--ease)}
.form-success .tick{width:54px;height:54px;border-radius:50%;background:var(--green);color:#fff;display:grid;place-items:center;margin:0 auto 1.2rem}
.form-success .tick svg{width:26px;height:26px}
.form-success h3{font-size:1.5rem;margin-bottom:.6rem}
form.enquiry.sent{display:none}
/* ---------- footer ---------- */
footer.site{background:var(--ink);color:rgba(237,232,220,.7);padding:clamp(52px,6vw,80px) 0 2rem}
footer.site .fgrid{display:grid;grid-template-columns:minmax(0,1.4fr) repeat(3,minmax(0,1fr));gap:2.4rem}
footer.site .brand .mark{color:var(--brass-soft)}
footer.site .brand .word{color:#FCFAF5}
footer.site .brand .word small{color:rgba(237,232,220,.5)}
footer.site p{font-size:.86rem;max-width:34ch}
footer.site h4{font-family:var(--sans);font-size:.72rem;letter-spacing:.16em;text-transform:uppercase;color:rgba(237,232,220,.5);margin-bottom:1.1rem;font-weight:600}
footer.site ul{list-style:none;margin:0;padding:0;display:grid;gap:.7rem;font-size:.87rem}
footer.site ul a:hover{color:#FCFAF5}
.newsletter{display:flex;gap:.5rem;margin-top:1.2rem}
.newsletter input{
flex:1;min-width:0;background:rgba(237,232,220,.07);border:1px solid rgba(237,232,220,.2);
border-radius:10px;padding:.7rem .85rem;font-size:.85rem;color:#FCFAF5;
}
.newsletter input::placeholder{color:rgba(237,232,220,.4)}
.newsletter input:focus{outline:none;border-color:var(--brass-soft)}
.newsletter button{
background:#FCFAF5;color:var(--ink);border:0;border-radius:10px;padding:.7rem 1rem;font-size:.82rem;font-weight:600;cursor:pointer;
transition:background .2s var(--ease);
}
.newsletter button:hover{background:var(--brass-soft)}
.news-msg{font-size:.78rem;color:var(--brass-soft);margin-top:.7rem;min-height:1em}
.fbase{
margin-top:3.2rem;padding-top:1.6rem;border-top:1px solid rgba(237,232,220,.14);
display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;font-size:.76rem;color:rgba(237,232,220,.5);
}
.fbase .dots{display:flex;gap:1.2rem;flex-wrap:wrap}
.fbase a:hover{color:#FCFAF5}
/* ---------- reveal ---------- */
[data-reveal]{opacity:0;transform:translateY(20px);transition:opacity .8s var(--ease),transform .8s var(--ease)}
[data-reveal].in{opacity:1;transform:none}
.d1{transition-delay:.08s}.d2{transition-delay:.16s}.d3{transition-delay:.24s}.d4{transition-delay:.32s}
/* ---------- responsive ---------- */
@media (max-width:1080px){
.hero-grid{grid-template-columns:1fr}
.hero .lede{max-width:56ch}
.config-grid{grid-template-columns:1fr}
.stage{position:relative;top:auto}
footer.site .fgrid{grid-template-columns:1fr 1fr}
}
@media (max-width:900px){
.nav-links{display:none}
.nav-cta .btn{display:none}
.burger{display:flex}
.cards{grid-template-columns:1fr;max-width:520px}
.quotes{grid-template-columns:1fr;max-width:620px}
.split,.contact-grid,.split--wide-left{grid-template-columns:1fr}
.stats-grid{grid-template-columns:1fr 1fr}
.stat:nth-child(3){border-left:0}
.stat:nth-child(-n+2){border-bottom:1px solid var(--line)}
.steps li{grid-template-columns:56px 1fr;gap:1rem}
.steps li p{grid-column:2}
footer.site .fgrid{grid-template-columns:1fr}
}
@media (max-width:560px){
body{font-size:16px}
.row{grid-template-columns:1fr}
.announce .wrap{font-size:.72rem}
.hero-actions .btn{width:100%}
.fbase{flex-direction:column}
}
@media (prefers-reduced-motion:reduce){
html{scroll-behavior:auto}
*,*::before,*::after{animation-duration:.001ms !important;animation-iteration-count:1 !important;transition-duration:.001ms !important}
[data-reveal]{opacity:1;transform:none}
}
</style>
</head>
<body>
<a class="skip" href="#main">Skip to content</a>
<!-- inline SVG sprite: bike illustration, no external assets -->
<svg aria-hidden="true" focusable="false" style="position:absolute;width:0;height:0;overflow:hidden">
<symbol id="bike" viewBox="0 0 560 320">
<g fill="none" stroke-linecap="round" stroke-linejoin="round">
<ellipse cx="276" cy="302" rx="208" ry="7" fill="var(--ink,#17170F)" stroke="none" opacity=".08"/>
<!-- wheels -->
<circle cx="100" cy="240" r="52" stroke="var(--ink,#17170F)" stroke-width="11"/>
<circle cx="448" cy="240" r="52" stroke="var(--ink,#17170F)" stroke-width="11"/>
<circle cx="100" cy="240" r="41" stroke="var(--ink,#17170F)" stroke-width="3" opacity=".45"/>
<circle cx="448" cy="240" r="41" stroke="var(--ink,#17170F)" stroke-width="3" opacity=".45"/>
<g stroke="var(--ink,#17170F)" stroke-width="2" opacity=".26">
<path d="M76 216 L124 264 M124 216 L76 264 M100 206 L100 274"/>
<path d="M424 216 L472 264 M472 216 L424 264 M448 206 L448 274"/>
</g>
<circle cx="100" cy="240" r="6" fill="var(--ink,#17170F)" stroke="none"/>
<circle cx="448" cy="240" r="6" fill="var(--ink,#17170F)" stroke="none"/>
<!-- frame -->
<g stroke="var(--frame,#1C4A3C)" stroke-width="9">
<path d="M142 198 L372 240"/>
<path d="M130 148 Q 236 129 352 144"/>
<path d="M352 144 L372 240"/>
<path d="M372 240 L448 240"/>
<path d="M352 144 L448 240"/>
<path d="M130 148 L142 198"/>
<path d="M142 198 L100 240"/>
<path d="M352 144 L345 112"/>
<path d="M130 148 L127 124"/>
</g>
<!-- handlebar -->
<path d="M100 116 C 114 107, 150 107, 168 119" stroke="var(--frame,#1C4A3C)" stroke-width="9" fill="none"/>
<circle cx="100" cy="116" r="6.5" fill="var(--ink,#17170F)" stroke="none"/>
<circle cx="168" cy="119" r="6.5" fill="var(--ink,#17170F)" stroke="none"/>
<!-- saddle -->
<path d="M316 112 C 330 96, 366 96, 380 112 C 366 120, 330 120, 316 112 Z" fill="var(--ink,#17170F)" stroke="none"/>
<!-- cargo box -->
<rect x="176" y="176" width="152" height="58" rx="9" fill="var(--frame,#1C4A3C)" fill-opacity=".16" stroke="var(--frame,#1C4A3C)" stroke-width="7"/>
<g stroke="var(--frame,#1C4A3C)" stroke-width="4" opacity=".5">
<path d="M214 181 L214 229"/>
<path d="M252 181 L252 229"/>
<path d="M290 181 L290 229"/>
</g>
<rect x="296" y="198" width="20" height="7" rx="3.5" fill="#B08A4E" stroke="none"/>
<!-- drivetrain -->
<circle cx="372" cy="240" r="14" stroke="var(--ink,#17170F)" stroke-width="6"/>
<path d="M360 231 L384 249" stroke="var(--ink,#17170F)" stroke-width="6"/>
<circle cx="448" cy="240" r="9" stroke="var(--ink,#17170F)" stroke-width="4" opacity=".7"/>
<!-- brass kickstand -->
<path d="M300 236 L290 288" stroke="#B08A4E" stroke-width="6"/>
<path d="M282 288 L298 288" stroke="#B08A4E" stroke-width="6"/>
</g>
</symbol>
<symbol id="mark" viewBox="0 0 32 32">
<g fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round">
<circle cx="16" cy="16" r="7.4"/>
<path d="M16 3.4v3.2M16 25.4v3.2M3.4 16h3.2M25.4 16h3.2M7.1 7.1l2.3 2.3M22.6 22.6l2.3 2.3M24.9 7.1l-2.3 2.3M9.4 22.6l-2.3 2.3"/>
</g>
<circle cx="16" cy="16" r="2.1" fill="currentColor"/>
</symbol>
<symbol id="check" viewBox="0 0 20 20"><path d="M4 10.5l4 4 8-9" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/></symbol>
<symbol id="star" viewBox="0 0 20 20"><path d="M10 1.6l2.6 5.3 5.8.8-4.2 4.1 1 5.8-5.2-2.7-5.2 2.7 1-5.8L1.6 7.7l5.8-.8z" fill="currentColor"/></symbol>
</svg>
<div class="announce">
<div class="wrap">
<span class="tick" aria-hidden="true"></span>
<span>Spring 2027 build slots are open — <b>4 of 18 remaining</b>. Frames are welded one at a time in Nørrebro.</span>
</div>
</div>
<header class="site" id="top">
<div class="wrap nav">
<a class="brand" href="#top" aria-label="Lumen Cycles, home">
<svg class="mark" aria-hidden="true"><use href="#mark"/></svg>
<span class="word">Lumen Cycles<small>København · est. 2011</small></span>
</a>
<nav class="nav-links" aria-label="Primary">
<a href="#bikes">Bikes</a>
<a href="#configure">Configure</a>
<a href="#workshop">Workshop</a>
<a href="#process">Process</a>
<a href="#faq">Questions</a>
</nav>
<div class="nav-cta">
<a class="btn btn--green" href="#contact">Book a build call</a>
<button class="burger" type="button" aria-label="Menu" aria-expanded="false" aria-controls="mobile-menu"><span></span></button>
</div>
</div>
<div class="mobile-menu" id="mobile-menu">
<div class="wrap">
<nav aria-label="Mobile">
<a href="#bikes">Bikes</a>
<a href="#configure">Configure</a>
<a href="#workshop">Workshop</a>
<a href="#process">Process</a>
<a href="#faq">Questions</a>
<a href="#contact">Contact</a>
<a class="btn btn--green btn--block" href="#contact">Book a build call</a>
</nav>
</div>
</div>
</header>
<main id="main">
<!-- ============ HERO ============ -->
<section class="hero">
<div class="wrap hero-grid">
<div>
<p class="eyebrow">Nørrebro, København — hand-built since 2011</p>
<h1 class="h-xl">A cargo bike built around your life, not a <em>catalogue</em>.</h1>
<p class="lede">We measure, weld and finish every Lumen frame to order — against your routes, your cargo and your children. Twelve weeks in the workshop. Decades on the street.</p>
<div class="hero-actions">
<a class="btn btn--green" href="#configure">Configure your build <span class="arw" aria-hidden="true">→</span></a>
<a class="btn btn--ghost" href="#contact">Visit the workshop</a>
</div>
<div class="hero-trust">
<ul>
<li><svg aria-hidden="true"><use href="#check"/></svg> Frame welded in-house</li>
<li><svg aria-hidden="true"><use href="#check"/></svg> 10-year frame warranty</li>
<li><svg aria-hidden="true"><use href="#check"/></svg> Delivered across the EU</li>
</ul>
</div>
</div>
<div class="hero-panel">
<div class="panel-top">
<span class="tag">Build no. 1 384</span>
<span class="slot"><span class="tick" style="width:6px;height:6px;border-radius:50%;background:currentColor;display:block"></span> In the jig this week</span>
</div>
<div class="panel-art" style="--frame:#1C4A3C">
<svg viewBox="0 0 560 320" role="img" aria-label="Illustration of a Lumen Broen cargo bike in Fjord Green"><use href="#bike"/></svg>
</div>
<div class="panel-caption">
<div class="spec">
<b>Broen 2.4</b> · family long-john<br>
Belt drive · box & two child seats<br>
Steel, powder-coated Fjord Green
</div>
<div class="price">from €4,200</div>
</div>
</div>
</div>
</section>
<!-- ============ STATS ============ -->
<section class="stats" aria-label="Lumen in numbers">
<div class="wrap">
<div class="stats-grid">
<div class="stat" data-reveal><b>1,400+</b><span>Bikes on the road</span></div>
<div class="stat d1" data-reveal><b>12 weeks</b><span>Average build time</span></div>
<div class="stat d2" data-reveal><b>10 years</b><span>Frame warranty</span></div>
<div class="stat d3" data-reveal><b>48 hours</b><span>Service turnaround</span></div>
</div>
</div>
</section>
<!-- ============ WORKSHOP ============ -->
<section class="sec" id="workshop">
<div class="wrap split split--wide-left" style="align-items:center">
<div data-reveal>
<p class="eyebrow">The workshop</p>
<h2 class="h-lg">Four benches, two welders, no production line.</h2>
<p class="lede" style="margin-top:1.6rem">Lumen started in a courtyard off Jægersborggade with one torch and a borrowed tube bender. Fourteen years later we still build the same way: one bike at a time, by the people whose names are on the frame.</p>
<p class="muted" style="margin-top:1.4rem">Nothing here is white-labelled. We bend the tubes, mitre the joints, weld the frames and lace the wheels on Sankt Hans night and every ordinary Tuesday in between. When your bike needs attention in year nine, it comes back to this room — not to a distributor.</p>
<ul class="principles">
<li>
<span class="n">01</span>
<div>
<h4>Measured, not sized</h4>
<p>Reach, saddle height and cargo footprint are calculated from your body and your route, not picked from S–XL.</p>
</div>
</li>
<li>
<span class="n">02</span>
<div>
<h4>Repairable by design</h4>
<p>Standard bearings, serviceable cables, off-the-shelf rack hardware. Every part can be replaced in a decade.</p>
</div>
</li>
<li>
<span class="n">03</span>
<div>
<h4>Materials that age well</h4>
<p>Reynolds 631 steel, stainless fasteners and powder coat cured to survive Danish salt for a long, long time.</p>
</div>
</li>
</ul>
<div class="sig">
<span class="avatar" aria-hidden="true">MH</span>
<p><strong>Mads Holm</strong>Founder & frame builder</p>
</div>
</div>
<div data-reveal class="d1">
<div class="figure">
<div class="fig-head"><span>Frame jig — Broen 2.4</span><span>Scale 1:12</span></div>
<div class="fig-body" style="--frame:#1C4A3C">
<svg viewBox="0 0 560 320" role="img" aria-label="Technical line drawing of the Lumen Broen cargo bike frame"><use href="#bike"/></svg>
</div>
<div class="fig-note">
<span>Drawing rev. 24 · checked by MH</span>
<span>Tube set: Reynolds 631</span>
</div>
</div>
</div>
</div>
</section>
<!-- ============ BIKES ============ -->
<section class="sec rule" id="bikes">
<div class="wrap">
<div style="max-width:62ch" data-reveal>
<p class="eyebrow">Three starting points</p>
<h2 class="h-lg">Every Lumen begins as one of three frames — then becomes yours.</h2>
<p class="lede" style="margin-top:1.5rem">Pick the shape that fits your week. Colours, cargo, gearing and finish are all decided afterwards, with us, over coffee and a tape measure.</p>
</div>
<div class="cards">
<article class="card" data-reveal>
<div class="thumb" style="--frame:#23405C">
<svg viewBox="0 0 560 320" role="img" aria-label="Line illustration of the Kajen compact cargo bike"><use href="#bike"/></svg>
</div>
<span class="kicker">Compact · city</span>
<h3>Kajen</h3>
<p class="blurb">A nimble short-wheelbase cargo bike for tight streets, stairwells and one good crate of groceries. Rides like a bicycle, carries like a small car.</p>
<ul>
<li><svg aria-hidden="true"><use href="#check"/></svg> Carries up to 60 kg</li>
<li><svg aria-hidden="true"><use href="#check"/></svg> 8-speed hub, belt-ready</li>
<li><svg aria-hidden="true"><use href="#check"/></svg> Fits a standard bike rack</li>
</ul>
<div class="foot">
<div class="from"><small>From</small>€3,400</div>
<button class="pick" type="button" data-model="kajen">Configure</button>
</div>
</article>
<article class="card d1" data-reveal>
<div class="thumb" style="--frame:#1C4A3C">
<svg viewBox="0 0 560 320" role="img" aria-label="Line illustration of the Broen family long-john cargo bike"><use href="#bike"/></svg>
</div>
<span class="kicker">Family · long-john</span>
<h3>Broen</h3>
<p class="blurb">Our most-loved frame. A long-john with a low step-through, room for two children in front and a grown-up's worth of shopping behind them.</p>
<ul>
<li><svg aria-hidden="true"><use href="#check"/></svg> Carries up to 120 kg</li>
<li><svg aria-hidden="true"><use href="#check"/></svg> Two child seats + harnesses</li>
<li><svg aria-hidden="true"><use href="#check"/></svg> Belt drive, 5-year wear part</li>
</ul>
<div class="foot">
<div class="from"><small>From</small>€4,200</div>
<button class="pick" type="button" data-model="broen">Configure</button>
</div>
</article>
<article class="card d2" data-reveal>
<div class="thumb" style="--frame:#93342A">
<svg viewBox="0 0 560 320" role="img" aria-label="Line illustration of the Havnen heavy-duty cargo bike"><use href="#bike"/></svg>
</div>
<span class="kicker">Trade · heavy duty</span>
<h3>Havnen</h3>
<p class="blurb">Built for bakeries, couriers and workshops. Reinforced rear triangle, a flatbed-rated deck and braking that stays honest at 200 kg.</p>
<ul>
<li><svg aria-hidden="true"><use href="#check"/></svg> Rated to 200 kg payload</li>
<li><svg aria-hidden="true"><use href="#check"/></svg> Hydraulic disc brakes, 4-piston</li>
<li><svg aria-hidden="true"><use href="#check"/></svg> Fleet servicing available</li>
</ul>
<div class="foot">
<div class="from"><small>From</small>€5,100</div>
<button class="pick" type="button" data-model="havnen">Configure</button>
</div>
</article>
</div>
</div>
</section>
<!-- ============ CONFIGURATOR ============ -->
<section class="sec config" id="configure">
<div class="wrap">
<div class="config-head" data-reveal>
<p class="eyebrow">Build it</p>
<h2 class="h-lg">Configure a Lumen in thirty seconds.</h2>
<p class="lede" style="margin-top:1.5rem">A starting estimate, not a quote — every build is priced properly after we've talked through your routes and your cargo. The deposit is €400, refundable for fourteen days.</p>
</div>
<div class="config-grid">
<div class="stage" data-reveal>
<div class="stage-art" id="stageArt" style="--frame:#1C4A3C">
<svg viewBox="0 0 560 320" role="img" aria-label="Live preview of your configured Lumen cargo bike"><use href="#bike"/></svg>
</div>
<div class="stage-meta">
<div>
<div class="label">Your build</div>
<div class="val" id="stageName">Broen · Fjord Green</div>
<div class="label" style="margin-top:.6rem" id="stageSpec">Belt drive · Cargo box</div>
</div>
<div class="total"><small>Estimated</small><span id="price">€4,580</span></div>
</div>
<p class="note" id="priceNote">Includes assembly, first service and delivery within Denmark. EU shipping quoted separately.</p>
</div>
<div data-reveal class="d1">
<fieldset>
<legend>Frame</legend>
<div class="chips">
<span class="chip"><input type="radio" name="model" id="m-kajen" value="kajen"><label for="m-kajen">Kajen <span class="plus">€3,400</span></label></span>
<span class="chip"><input type="radio" name="model" id="m-broen" value="broen" checked><label for="m-broen">Broen <span class="plus">€4,200</span></label></span>
<span class="chip"><input type="radio" name="model" id="m-havnen" value="havnen"><label for="m-havnen">Havnen <span class="plus">€5,100</span></label></span>
</div>
</fieldset>
<fieldset>
<legend>Colour</legend>
<div class="swatches" id="swatches">
<span class="sw"><input type="radio" name="colour" id="c-green" value="green" checked><label for="c-green"><span class="dot" style="--c:#1C4A3C"></span>Fjord Green</label></span>
<span class="sw"><input type="radio" name="colour" id="c-blue" value="blue"><label for="c-blue"><span class="dot" style="--c:#23405C"></span>Havn Blue</label></span>
<span class="sw"><input type="radio" name="colour" id="c-red" value="red"><label for="c-red"><span class="dot" style="--c:#93342A"></span>Signal Red<span class="plus">+€180</span></label></span>
<span class="sw"><input type="radio" name="colour" id="c-oat" value="oat"><label for="c-oat"><span class="dot" style="--c:#B9AB8C"></span>Oat<span class="plus">+€180</span></label></span>
<span class="sw"><input type="radio" name="colour" id="c-midnight" value="midnight"><label for="c-midnight"><span class="dot" style="--c:#1E1E1B"></span>Midnight<span class="plus">+€180</span></label></span>
<span class="sw"><input type="radio" name="colour" id="c-brass" value="brass"><label for="c-brass"><span class="dot" style="--c:#B08A4E"></span>Raw Brass<span class="plus">+€420</span></label></span>
</div>
</fieldset>
<fieldset>
<legend>Drive</legend>
<div class="chips">
<span class="chip"><input type="radio" name="drive" id="d-chain" value="chain"><label for="d-chain">Chain <span class="plus">€0</span></label></span>
<span class="chip"><input type="radio" name="drive" id="d-belt" value="belt" checked><label for="d-belt">Gates belt <span class="plus">+€380</span></label></span>
</div>
</fieldset>
<fieldset>
<legend>Cargo</legend>
<div class="chips">
<span class="chip"><input type="radio" name="cargo" id="g-box" value="box" checked><label for="g-box">Cargo box <span class="plus">€0</span></label></span>
<span class="chip"><input type="radio" name="cargo" id="g-seats" value="seats"><label for="g-seats">Two child seats <span class="plus">+€290</span></label></span>
<span class="chip"><input type="radio" name="cargo" id="g-flatbed" value="flatbed"><label for="g-flatbed">Flatbed deck <span class="plus">+€150</span></label></span>
<span class="chip"><input type="radio" name="cargo" id="g-rack" value="rack"><label for="g-rack">Trade rack <span class="plus">+€220</span></label></span>
</div>
</fieldset>
<a class="btn btn--block" href="#contact" style="background:#FCFAF5;border-color:#FCFAF5;color:var(--ink)">Send this spec to the workshop <span class="arw" aria-hidden="true">→</span></a>
</div>
</div>
</div>
</section>
<!-- ============ PROCESS ============ -->
<section class="sec" id="process">
<div class="wrap">
<div style="max-width:60ch" data-reveal>
<p class="eyebrow">How a Lumen gets made</p>
<h2 class="h-lg">From first conversation to handover.</h2>
</div>
<ol class="steps">
<li data-reveal>
<span class="num">Step 01</span>
<div>
<h3>Conversation & fit</h3>
<p class="when">90 minutes · free</p>
</div>
<p>We meet at the workshop or over a call, walk through your week — school runs, deliveries, hills, the width of your stairwell — and decide which frame is worth building.</p>
</li>
<li data-reveal class="d1">
<span class="num">Step 02</span>
<div>
<h3>Design & measurement</h3>
<p class="when">1–2 weeks</p>
</div>
<p>You receive a drawing of your bike with tube lengths, cockpit reach, cargo footprint and a fixed price. Nothing is charged until you sign it off.</p>
</li>
<li data-reveal class="d2">
<span class="num">Step 03</span>
<div>
<h3>The build</h3>
<p class="when">12 weeks</p>
</div>
<p>Tube bending, mitring, welding and powder coat. You get photographs from the bench as it moves, and we check in once a month — no silence.</p>
</li>
<li data-reveal class="d3">
<span class="num">Step 04</span>
<div>
<h3>Handover</h3>
<p class="when">Half a day</p>
</div>
<p>Collect from Nørrebro or have it crated to your door anywhere in the EU. Either way we set the cockpit to your measurements and ride the first kilometre with you.</p>
</li>
<li data-reveal class="d4">
<span class="num">Step 05</span>
<div>
<h3>Service for life</h3>
<p class="when">Ongoing</p>
</div>
<p>First service at 500 km is on us. After that, 48-hour turnaround at the bench for anything — brakes, bearings, a new harness for a growing child.</p>
</li>
</ol>
</div>
</section>
<!-- ============ TESTIMONIALS ============ -->
<section class="sec rule" aria-label="What owners say">
<div class="wrap">
<div style="max-width:56ch" data-reveal>
<p class="eyebrow">Owners</p>
<h2 class="h-lg">Bought once, ridden daily.</h2>
</div>
<div class="quotes">
<figure class="quote" data-reveal>
<div class="stars" aria-label="Five out of five">
<svg><use href="#star"/></svg><svg><use href="#star"/></svg><svg><use href="#star"/></svg><svg><use href="#star"/></svg><svg><use href="#star"/></svg>
</div>
<blockquote>Both children, a week of shopping and a cello fit in one trip. Three winters in and the frame still looks like the day I collected it.</blockquote>
<div class="who">
<span class="ib" aria-hidden="true">AL</span>
<p><strong>Anna Lindqvist</strong>Broen 2.4 · Frederiksberg</p>
</div>
</figure>
<figure class="quote d1" data-reveal>
<div class="stars" aria-label="Five out of five">
<svg><use href="#star"/></svg><svg><use href="#star"/></svg><svg><use href="#star"/></svg><svg><use href="#star"/></svg><svg><use href="#star"/></svg>
</div>
<blockquote>We replaced a delivery van with two Havnens. Six hundred croissants a morning and the brakes don't flinch at the harbour wind.</blockquote>
<div class="who">
<span class="ib" aria-hidden="true">JP</span>
<p><strong>Jonas Pedersen</strong>Havnen × 2 · Nørrebro bakery</p>
</div>
</figure>
<figure class="quote d2" data-reveal>
<div class="stars" aria-label="Five out of five">
<svg><use href="#star"/></svg><svg><use href="#star"/></svg><svg><use href="#star"/></svg><svg><use href="#star"/></svg><svg><use href="#star"/></svg>
</div>
<blockquote>What convinced me was the drawing before the invoice. No catalogue, no upsell — just my street, my measurements, and a price that didn't move.</blockquote>
<div class="who">
<span class="ib" aria-hidden="true">SM</span>
<p><strong>Sofia Meyer</strong>Kajen · Aarhus</p>
</div>
</figure>
</div>
</div>
</section>
<!-- ============ FAQ ============ -->
<section class="sec rule" id="faq">
<div class="wrap split" style="align-items:start">
<div data-reveal>
<p class="eyebrow">Before you commit</p>
<h2 class="h-lg">The questions everyone asks.</h2>
<p class="muted" style="margin-top:1.6rem;max-width:34ch">Anything else, write to us — a person in the workshop answers, usually the same day. <a href="#contact" style="color:var(--green);border-bottom:1px solid currentColor">Ask a question</a>.</p>
</div>
<div class="faq d1" data-reveal>
<details open>
<summary>Why does a Lumen cost €4,000 and up?</summary>
<div class="a">Because a person bends, mitres and welds your frame for twelve weeks, and because the parts are chosen to still be serviceable in 2036. A €1,500 cargo bike is a different object — usually a mass-produced frame with our name nowhere near it. You are paying for fit, longevity and a workshop that will still answer the phone in a decade.</div>
</details>
<details>
<summary>Can I try one before ordering?</summary>
<div class="a">Yes. We keep a Broen and a Havnen in the workshop for test rides, and we run demo days in Copenhagen and Aarhus through spring. Bring your actual cargo — children, dog, bread trays — and ride your actual route if you like.</div>
</details>
<details>
<summary>How does the 10-year frame warranty work?</summary>
<div class="a">The frame and fork are warranted against defects in materials and workmanship for ten years to the original owner. Wear parts — tyres, brake pads, belts, cables — are excluded, as you'd expect. If something is our fault, we fix it at the bench and cover the return shipping.</div>
</details>
<details>
<summary>Do you deliver outside Denmark?</summary>
<div class="a">We crate and ship anywhere in the EU, and have sent bikes to Berlin, Malmö, Amsterdam and Lisbon. Shipping is quoted with your build, typically €180–€420 depending on distance. You're also very welcome to collect from Nørrebro and ride it home.</div>
</details>
<details>
<summary>What if my needs change — another child, a new job?</summary>
<div class="a">The frames are built to be reconfigured. Child seats come off, boxes become flatbeds, racks bolt on. Most owners change the cargo setup at least once in the first five years, and it's an afternoon's work, not a new bike.</div>
</details>
<details>
<summary>How do payments and deposits work?</summary>
<div class="a">A €400 deposit reserves your slot and is refundable within fourteen days, no questions asked. Half the balance is due when you approve the drawing, the rest on handover. We invoice in EUR or DKK and take bank transfer or card.</div>
</details>
</div>
</div>
</section>
<!-- ============ CONTACT ============ -->
<section class="sec contact" id="contact">
<div class="wrap contact-grid">
<div data-reveal>
<p class="eyebrow">Start a build</p>
<h2 class="h-lg">Tell us what you carry.</h2>
<p class="lede" style="margin-top:1.5rem">Send a few lines and we'll come back within two working days with the frame we'd recommend, a rough price and the next available build slot. No mailing list, no follow-up sequence.</p>
<ul class="contact-list">
<li>
<svg aria-hidden="true"><use href="#check"/></svg>
<span><strong>Workshop</strong>Jægersborggade 42, 2200 København N</span>
</li>
<li>
<svg aria-hidden="true"><use href="#check"/></svg>
<span><strong>Opening hours</strong>Tue–Fri 10–18 · Sat 10–14 · Closed Sun–Mon</span>
</li>
<li>
<svg aria-hidden="true"><use href="#check"/></svg>
<span><strong>Write</strong><a href="mailto:build@lumencycles.dk" style="border-bottom:1px solid currentColor">build@lumencycles.dk</a> · +45 35 55 04 20</span>
</li>
<li>
<svg aria-hidden="true"><use href="#check"/></svg>
<span><strong>Registration</strong>Lumen Cycles ApS · CVR 32 14 88 07</span>
</li>
</ul>
</div>
<div data-reveal class="d1">
<form class="enquiry" id="enquiry" novalidate>
<div class="row">
<div class="field">
<label for="f-name">Name</label>
<input id="f-name" name="name" type="text" autocomplete="name" placeholder="Anna Lindqvist" required>
<span class="err">Please tell us your name.</span>
</div>
<div class="field">
<label for="f-email">Email</label>
<input id="f-email" name="email" type="email" autocomplete="email" placeholder="anna@example.dk" required>
<span class="err">Please enter a valid email address.</span>
</div>
</div>
<div class="row">
<div class="field">
<label for="f-city">City</label>
<input id="f-city" name="city" type="text" autocomplete="address-level2" placeholder="København" required>
<span class="err">Where will the bike live?</span>
</div>
<div class="field">
<label for="f-model">Frame you're drawn to</label>
<select id="f-model" name="model">
<option>Not sure yet — advise me</option>
<option>Kajen — compact city</option>
<option>Broen — family long-john</option>
<option>Havnen — trade & heavy duty</option>
</select>
</div>
</div>
<div class="field">
<label for="f-msg">What will you carry, and where do you ride?</label>
<textarea id="f-msg" name="message" placeholder="Two children under six, a weekly shop, and a 6 km commute along Nørrebrogade…" required></textarea>
<span class="err">A sentence or two helps us answer properly.</span>
</div>
<div class="form-foot">
<button class="btn btn--green" type="submit">Request a build slot <span class="arw" aria-hidden="true">→</span></button>
<span class="fineprint">We reply within two working days. Never shared, never sold.</span>
</div>
</form>
<div class="form-success" id="enquirySuccess" role="status" aria-live="polite">
<div class="tick"><svg aria-hidden="true"><use href="#check"/></svg></div>
<h3>Thank you — it's with the workshop.</h3>
<p class="muted" style="max-width:38ch;margin-inline:auto">Mads or Ida will reply within two working days with a recommendation and your build slot. If it's urgent, call the bench on +45 35 55 04 20.</p>
</div>
</div>
</div>
</section>
</main>
<footer class="site">
<div class="wrap">
<div class="fgrid">
<div>
<a class="brand" href="#top" aria-label="Lumen Cycles, home">
<svg class="mark" aria-hidden="true"><use href="#mark"/></svg>
<span class="word">Lumen Cycles<small>København · est. 2011</small></span>
</a>
<p style="margin-top:1.4rem">Custom cargo bikes, measured, welded and finished to order in Nørrebro. Built to be ridden for decades, and repaired in the same room they were born in.</p>
</div>
<div>
<h4>Bikes</h4>
<ul>
<li><a href="#bikes">Kajen — compact city</a></li>
<li><a href="#bikes">Broen — family long-john</a></li>
<li><a href="#bikes">Havnen — trade</a></li>
<li><a href="#configure">Configure a build</a></li>
</ul>
</div>
<div>
<h4>Workshop</h4>
<ul>
<li><a href="#workshop">About us</a></li>
<li><a href="#process">The process</a></li>
<li><a href="#faq">Questions</a></li>
<li><a href="#contact">Book a build call</a></li>
</ul>
</div>
<div>
<h4>Occasional letters</h4>
<p style="font-size:.86rem">Build photographs and workshop news. Four or five a year, nothing else.</p>
<form class="newsletter" id="newsletter" novalidate>
<label class="sr-only" for="nl-email" style="position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)">Email address</label>
<input id="nl-email" type="email" placeholder="you@example.dk" aria-label="Email address">
<button type="submit">Join</button>
</form>
<p class="news-msg" id="newsMsg" role="status" aria-live="polite"></p>
</div>
</div>
<div class="fbase">
<span>© 2026 Lumen Cycles ApS · Jægersborggade 42, 2200 København N · CVR 32 14 88 07</span>
<span class="dots">
<a href="#top">Privacy</a>
<a href="#top">Terms of sale</a>
<a href="#top">Warranty</a>
<a href="#contact">Contact</a>
</span>
</div>
</div>
</footer>
<script>
(function () {
"use strict";
var reduceMotion = window.matchMedia && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
/* ---------- sticky header ---------- */
var header = document.querySelector("header.site");
function onScroll() {
if (window.scrollY > 8) header.classList.add("stuck");
else header.classList.remove("stuck");
}
onScroll();
window.addEventListener("scroll", onScroll, { passive: true });
/* ---------- mobile menu ---------- */
var burger = document.querySelector(".burger");
var mobileMenu = document.getElementById("mobile-menu");
burger.addEventListener("click", function () {
var open = burger.getAttribute("aria-expanded") === "true";
burger.setAttribute("aria-expanded", String(!open));
mobileMenu.classList.toggle("open", !open);
});
mobileMenu.addEventListener("click", function (e) {
if (e.target.tagName === "A") {
burger.setAttribute("aria-expanded", "false");
mobileMenu.classList.remove("open");
}
});
/* ---------- reveal on scroll ---------- */
var revealEls = Array.prototype.slice.call(document.querySelectorAll("[data-reveal]"));
if ("IntersectionObserver" in window && !reduceMotion) {
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) {
entry.target.classList.add("in");
io.unobserve(entry.target);
}
});
}, { rootMargin: "0px 0px -8% 0px", threshold: 0.08 });
revealEls.forEach(function (el) { io.observe(el); });
} else {
revealEls.forEach(function (el) { el.classList.add("in"); });
}
/* ---------- configurator ---------- */
var MODELS = {
kajen: { name: "Kajen", base: 3400, label: "Kajen compact · city" },
broen: { name: "Broen", base: 4200, label: "Broen 2.4 · family long-john" },
havnen: { name: "Havnen", base: 5100, label: "Havnen heavy duty · trade" }
};
var COLOURS = {
green: { name: "Fjord Green", hex: "#1C4A3C", add: 0 },
blue: { name: "Havn Blue", hex: "#23405C", add: 0 },
red: { name: "Signal Red", hex: "#93342A", add: 180 },
oat: { name: "Oat", hex: "#B9AB8C", add: 180 },
midnight: { name: "Midnight", hex: "#1E1E1B", add: 180 },
brass: { name: "Raw Brass", hex: "#B08A4E", add: 420 }
};
var DRIVES = {
chain: { name: "Chain drive", add: 0 },
belt: { name: "Gates belt drive", add: 380 }
};
var CARGO = {
box: { name: "Cargo box", add: 0 },
seats: { name: "Two child seats", add: 290 },
flatbed: { name: "Flatbed deck", add: 150 },
rack: { name: "Trade rack", add: 220 }
};
var stageArt = document.getElementById("stageArt");
var stageName = document.getElementById("stageName");
var stageSpec = document.getElementById("stageSpec");
var priceEl = document.getElementById("price");
var priceNote = document.getElementById("priceNote");
function euro(n) {
return "\u20AC" + n.toLocaleString("en-US");
}
function picked(name) {
var el = document.querySelector('input[name="' + name + '"]:checked');
return el ? el.value : null;
}
function update() {
var m = MODELS[picked("model")] || MODELS.broen;
var c = COLOURS[picked("colour")] || COLOURS.green;
var d = DRIVES[picked("drive")] || DRIVES.belt;
var g = CARGO[picked("cargo")] || CARGO.box;
var total = m.base + c.add + d.add + g.add;
stageArt.style.setProperty("--frame", c.hex);
stageName.textContent = m.name + " \u00B7 " + c.name;
stageSpec.textContent = d.name + " \u00B7 " + g.name;
priceEl.textContent = euro(total);
var extras = c.add + d.add + g.add;
priceNote.textContent = extras > 0
? "Base " + euro(m.base) + " plus " + euro(extras) + " in options. Includes assembly, first service and delivery within Denmark; EU shipping quoted separately."
: "Includes assembly, first service and delivery within Denmark. EU shipping quoted separately.";
}
Array.prototype.slice.call(document.querySelectorAll('input[name="model"], input[name="colour"], input[name="drive"], input[name="cargo"]'))
.forEach(function (input) { input.addEventListener("change", update); });
document.querySelectorAll(".card .pick").forEach(function (btn) {
btn.addEventListener("click", function () {
var id = btn.getAttribute("data-model");
var radio = document.querySelector('input[name="model"][value="' + id + '"]');
if (radio) radio.checked = true;
update();
var target = document.getElementById("configure");
if (target) target.scrollIntoView({ behavior: reduceMotion ? "auto" : "smooth", block: "start" });
});
});
update();
/* ---------- enquiry form ---------- */
var form = document.getElementById("enquiry");
var success = document.getElementById("enquirySuccess");
var emailRe = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
function fieldOf(el) { return el.closest(".field"); }
function setInvalid(el, bad) { fieldOf(el).classList.toggle("invalid", bad); }
Array.prototype.slice.call(form.querySelectorAll("input, textarea")).forEach(function (el) {
el.addEventListener("input", function () {
if (fieldOf(el).classList.contains("invalid")) {
var ok = el.value.trim().length > 0 && (el.type !== "email" || emailRe.test(el.value.trim()));
if (ok) setInvalid(el, false);
}
});
});
form.addEventListener("submit", function (e) {
e.preventDefault();
var name = form.querySelector("#f-name");
var email = form.querySelector("#f-email");
var city = form.querySelector("#f-city");
var msg = form.querySelector("#f-msg");
var badName = name.value.trim().length < 2;
var badEmail = !emailRe.test(email.value.trim());
var badCity = city.value.trim().length < 2;
var badMsg = msg.value.trim().length < 8;
setInvalid(name, badName);
setInvalid(email, badEmail);
setInvalid(city, badCity);
setInvalid(msg, badMsg);
if (badName || badEmail || badCity || badMsg) {
var first = form.querySelector(".field.invalid input, .field.invalid textarea");
if (first) first.focus();
return;
}
form.classList.add("sent");
success.classList.add("show");
success.scrollIntoView({ behavior: reduceMotion ? "auto" : "smooth", block: "center" });
});
/* ---------- newsletter ---------- */
var nl = document.getElementById("newsletter");
var nlMsg = document.getElementById("newsMsg");
nl.addEventListener("submit", function (e) {
e.preventDefault();
var input = document.getElementById("nl-email");
if (emailRe.test(input.value.trim())) {
nlMsg.textContent = "Thank you — you're on the list.";
input.value = "";
} else {
nlMsg.textContent = "Please check that email address.";
}
});
/* ---------- smooth anchor offset for sticky header ---------- */
document.querySelectorAll('a[href^="#"]').forEach(function (link) {
link.addEventListener("click", function (e) {
var id = link.getAttribute("href");
if (id === "#" || id.length < 2) return;
var target = document.querySelector(id);
if (!target) return;
e.preventDefault();
var top = target.getBoundingClientRect().top + window.scrollY - 84;
window.scrollTo({ top: top < 0 ? 0 : top, behavior: reduceMotion ? "auto" : "smooth" });
if (history.replaceState) history.replaceState(null, "", id);
});
});
})();
</script>
</body>
</html>

