Run details
- Model
- nex-agi/nex-n2.6
- Route
- OpenRouter API, one user message
- Served by
- Nex AGI
- Effort
- high, OpenRouter's default for this model
- Limits
- 60 min · 235,929 output tokens (the model's limit)
- Date
- 10 Nov 2026
- Time
- 9 min 25 s
- Size
- 63 kB
- Tokens
- 98 in, 64,759 out (44,161 of them thinking)
- List price
- $0.026 at today's price ($0.12 in / $0.40 out per M)
- Paid
- $0.026
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
63 kB 970 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, handbuilt in Copenhagen</title>
<meta name="description" content="Lumen Cycles hand-builds custom cargo bikes to order in Copenhagen. Three frames, honest pricing, service for life.">
<link rel="icon" href="data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><circle cx='16' cy='21' r='8.5' fill='none' stroke='%231C1B16' stroke-width='2.5'/><path d='M16 9.5V4M21.5 11l3.5-4M10.5 11L7 7' stroke='%23D8451A' stroke-width='2.5' stroke-linecap='round' fill='none'/></svg>">
<style>
/* ============ tokens & base ============ */
:root{
--paper:#F4F0E7; --paper2:#ECE5D5; --panel:#EFE9DB;
--ink:#1C1B16; --ink2:#4B473C; --soft:#77705F;
--line:#DCD4C2; --line2:#B9AF9A;
--accent:#D8451A; --accent-d:#B93A12;
--dark:#17221B; --darkline:rgba(237,231,218,.16); --cream:#FFF6EA;
--sans:-apple-system,BlinkMacSystemFont,"Helvetica Neue","Segoe UI",Arial,sans-serif;
--serif:"Iowan Old Style","Palatino Linotype",Palatino,Georgia,"Times New Roman",serif;
--mono:ui-monospace,"SF Mono","Cascadia Mono","Roboto Mono",Consolas,"Courier New",monospace;
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{background:var(--paper);color:var(--ink);font-family:var(--sans);font-size:16.5px;line-height:1.65;-webkit-font-smoothing:antialiased}
body::after{content:"";position:fixed;inset:0;z-index:2000;pointer-events:none;opacity:.045;
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.9' numOctaves='2'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E")}
::selection{background:var(--accent);color:var(--cream)}
img,svg{display:block}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:none;cursor:pointer}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
section[id],div[id="build"]{scroll-margin-top:88px}
.container{max-width:1180px;margin:0 auto;padding:0 28px}
.sec{padding:104px 0}
.sec-tint{background:var(--paper2);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.w100{width:100%}
.eyebrow{display:flex;align-items:center;gap:12px;font-family:var(--mono);font-size:11px;letter-spacing:.2em;color:var(--soft);text-transform:uppercase;margin-bottom:18px}
.eyebrow::before{content:"";width:26px;height:2px;background:var(--accent);flex:none}
.eyebrow.sm{margin-bottom:10px}
.sec-title{font-size:clamp(30px,4vw,44px);line-height:1.08;letter-spacing:-.02em;font-weight:700}
.sec-head{margin-bottom:56px;max-width:720px}
.sec-lead{margin-top:18px;color:var(--ink2);font-size:17px;max-width:600px}
/* buttons */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;padding:15px 26px;border-radius:2px;font-weight:600;font-size:15px;letter-spacing:.01em;border:1px solid transparent;cursor:pointer;transition:background .2s,color .2s,border-color .2s}
.btn:active{transform:translateY(1px)}
.btn .ar{transition:transform .2s;display:inline-block}
.btn:hover .ar{transform:translateX(4px)}
.btn-accent{background:var(--accent);color:var(--cream)}
.btn-accent:hover{background:var(--accent-d)}
.btn-ink{background:var(--ink);color:var(--paper)}
.btn-ink:hover{background:#33312A}
.btn-ghost{border-color:var(--ink);color:var(--ink)}
.btn-ghost:hover{background:var(--ink);color:var(--paper)}
.btn-ghost-l{border-color:rgba(255,246,234,.7);color:var(--cream)}
.btn-ghost-l:hover{background:var(--cream);color:var(--accent)}
/* ============ topbar & header ============ */
.topbar{background:var(--paper2);border-bottom:1px solid var(--line)}
.topbar-in{display:flex;justify-content:space-between;gap:16px;padding:8px 0;font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;color:var(--soft)}
.site-header{position:sticky;top:0;z-index:500;background:rgba(244,240,231,.92);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);border-bottom:1px solid transparent;transition:border-color .25s}
.site-header.scrolled{border-bottom-color:var(--line)}
.header-in{display:flex;align-items:center;justify-content:space-between;height:70px}
.logo{display:flex;align-items:center;gap:10px;font-weight:700;letter-spacing:.1em;font-size:15px}
.logo em{font-style:normal;color:var(--soft);font-weight:500}
.nav{display:flex;align-items:center;gap:30px}
.nav a{font-size:13.5px;font-weight:500;color:var(--ink2);letter-spacing:.02em;padding:4px 0;border-bottom:1.5px solid transparent;transition:color .2s,border-color .2s}
.nav a:hover{color:var(--ink);border-bottom-color:var(--accent)}
.nav .btn{padding:10px 18px;font-size:13.5px}
.nav-toggle{display:none;flex-direction:column;gap:6px;padding:10px}
.nav-toggle span{display:block;width:22px;height:2px;background:var(--ink);transition:transform .25s,opacity .25s}
.nav-toggle.open span:nth-child(1){transform:translateY(4px) rotate(45deg)}
.nav-toggle.open span:nth-child(2){transform:translateY(-4px) rotate(-45deg)}
/* ============ hero ============ */
.hero{padding:64px 0 96px}
.hero-grid{display:grid;grid-template-columns:1.02fr .98fr;gap:56px;align-items:center}
h1{font-size:clamp(40px,5.4vw,70px);line-height:1.02;letter-spacing:-.035em;font-weight:700}
h1 .fx{font-family:var(--serif);font-style:italic;font-weight:400;letter-spacing:-.01em}
.hero-lead{margin-top:22px;color:var(--ink2);font-size:18px;max-width:520px}
.cta-row{display:flex;flex-wrap:wrap;gap:14px;margin:32px 0 40px}
.facts{display:flex;flex-wrap:wrap;gap:28px 36px;border-top:1px solid var(--line);padding-top:22px}
.fact strong{display:block;font-size:21px;font-weight:700;font-variant-numeric:tabular-nums;letter-spacing:-.01em}
.fact span{font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--soft)}
/* schematic */
.schem-frame{border:1px solid var(--line2);background:var(--panel);padding:20px 18px 14px;position:relative}
.schem-meta{display:flex;justify-content:space-between;gap:12px;font-family:var(--mono);font-size:10px;letter-spacing:.14em;color:var(--soft);margin-bottom:6px}
.schem{width:100%;height:auto}
.schem-caption{display:flex;gap:14px;border-top:1px solid var(--line2);margin-top:10px;padding-top:12px;min-height:70px}
.schem-caption .cap-n{font-family:var(--mono);font-size:12px;font-weight:700;color:var(--accent);letter-spacing:.08em;padding-top:3px}
.schem-caption p{font-size:14px;line-height:1.55;color:var(--ink2)}
.schem-caption.show{animation:fin .35s ease}
.schem .t,.msvg .t{stroke:var(--ink);fill:none;stroke-linecap:round;stroke-linejoin:round}
.w1{stroke-width:1.4}.w2{stroke-width:2.2}.w3{stroke-width:3.2}.w4{stroke-width:4.2}.w5{stroke-width:5}.w6{stroke-width:6}.w7{stroke-width:7}.w9{stroke-width:9}
.tire{stroke-width:10}
.fill-ink{fill:var(--ink);stroke:none}
.boxfill{fill:var(--panel);stroke:var(--ink);stroke-width:3.2;stroke-linejoin:round}
.hl{fill:var(--accent);stroke:none}
.gnd{stroke:var(--line2);stroke-width:2;fill:none}
.hatch{stroke:var(--line2);stroke-width:1.6;fill:none}
.dim{stroke:#A79D89;stroke-width:1.3;fill:none}
.dtxt{font-family:var(--mono);font-size:10.5px;fill:#7A7263;letter-spacing:2px}
.draw{stroke-dasharray:1;stroke-dashoffset:1;animation:draw 1s cubic-bezier(.55,.06,.28,.99) forwards}
@keyframes draw{to{stroke-dashoffset:0}}
.fade{opacity:0;animation:fin .7s ease forwards 1.15s}
@keyframes fin{to{opacity:1}}
.spin{animation:rot 22s linear infinite;transform-box:view-box}
.spin.fast{animation-duration:8s}
.spin.slow{animation-duration:17s}
@keyframes rot{to{transform:rotate(360deg)}}
.hs{cursor:pointer;outline:none}
.hs-hit{fill:transparent;stroke:none}
.hs-dot{fill:var(--ink);stroke:var(--paper);stroke-width:2;transition:fill .2s}
.hs-ring{fill:none;stroke:var(--accent);stroke-width:1.5;opacity:0;transform-box:fill-box;transform-origin:center}
.hs:hover .hs-dot,.hs.active .hs-dot{fill:var(--accent)}
.hs.active .hs-ring,.hs:focus-visible .hs-ring{opacity:1;animation:ping 1.8s ease-out infinite}
@keyframes ping{0%{transform:scale(.6);opacity:.9}100%{transform:scale(2.6);opacity:0}}
/* ticker */
.ticker{background:var(--ink);color:var(--paper);overflow:hidden;padding:13px 0}
.ticker-track{display:flex;width:max-content;animation:tick 34s linear infinite}
.ticker-set{display:flex;align-items:center;white-space:nowrap;font-family:var(--mono);font-size:11.5px;letter-spacing:.18em}
.ticker-set span{padding:0 22px}
.ticker-set i{color:var(--accent);font-style:normal}
@keyframes tick{to{transform:translateX(-50%)}}
/* ============ models ============ */
.models-grid{display:grid;grid-template-columns:1.08fr .92fr;gap:56px;align-items:start}
.model-row{width:100%;text-align:left;display:grid;grid-template-columns:52px 1fr auto 26px;gap:16px;align-items:center;padding:24px 10px;border-top:1px solid var(--line);transition:background .2s,box-shadow .2s,padding .2s}
.model-row:last-of-type{border-bottom:1px solid var(--line)}
.model-row .idx{font-family:var(--mono);font-size:13px;color:var(--soft);transition:color .2s}
.model-row h3{font-size:22px;font-weight:700;letter-spacing:-.01em}
.model-row p{font-size:14px;color:var(--soft);margin-top:3px}
.model-row .price{font-family:var(--mono);font-size:14px;color:var(--ink2);white-space:nowrap}
.model-row .go{opacity:0;transform:translateX(-6px);transition:opacity .2s,transform .2s;color:var(--accent);font-weight:700}
.model-row:hover{background:var(--panel)}
.model-row:hover .go,.model-row.active .go{opacity:1;transform:none}
.model-row.active{box-shadow:inset 3px 0 0 var(--accent);padding-left:18px;background:var(--panel)}
.model-row.active .idx{color:var(--accent)}
.spec-panel{border:1px solid var(--ink);background:var(--panel);padding:26px;position:sticky;top:96px}
.spec-top{display:flex;justify-content:space-between;align-items:baseline;gap:12px;border-bottom:1px solid var(--line2);padding-bottom:14px}
.spec-top .no{font-family:var(--mono);font-size:11px;letter-spacing:.16em;color:var(--soft)}
.spec-top h3{font-size:24px;letter-spacing:-.01em}
.spec-price{font-family:var(--mono);font-size:15px;color:var(--accent);font-weight:700}
.msvg{width:100%;height:auto;margin:16px 0 6px}
.spec-row{display:flex;justify-content:space-between;gap:16px;border-top:1px solid var(--line);padding:9px 0;font-size:14.5px}
.spec-row dt{font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--soft);padding-top:3px;flex:none}
.spec-row dd{font-weight:600;text-align:right;font-variant-numeric:tabular-nums}
.spec-row.wide dd{font-weight:500}
.spec-panel .btn{margin-top:18px}
/* ============ process ============ */
.proc-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:40px}
.step{border-top:2px solid var(--ink);padding-top:18px}
.step .num{font-family:var(--mono);font-size:13px;color:var(--accent);font-weight:700;letter-spacing:.1em}
.step h3{font-size:20px;margin:10px 0 8px;letter-spacing:-.01em}
.step p{font-size:14.5px;color:var(--ink2)}
.step .when{display:block;margin-top:14px;font-family:var(--mono);font-size:11px;letter-spacing:.16em;color:var(--soft)}
/* ============ configurator ============ */
.build-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:56px;align-items:start}
.opt{border:none;margin-bottom:30px}
.opt legend{font-family:var(--mono);font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--soft);margin-bottom:14px}
.pills{display:flex;flex-wrap:wrap;gap:10px}
.pill{position:relative;display:inline-flex}
.pill input{position:absolute;opacity:0;pointer-events:none}
.pill span{display:inline-flex;align-items:baseline;gap:10px;border:1px solid var(--line2);background:transparent;padding:11px 16px;border-radius:2px;font-size:14px;cursor:pointer;transition:border-color .2s,background .2s,color .2s}
.pill span em{font-style:normal;font-family:var(--mono);font-size:11.5px;color:var(--soft);transition:color .2s}
.pill span:hover{border-color:var(--ink)}
.pill input:checked + span{background:var(--ink);color:var(--paper);border-color:var(--ink)}
.pill input:checked + span em{color:rgba(244,240,231,.65)}
.pill input:focus-visible + span{outline:2px solid var(--accent);outline-offset:2px}
.summary{border:1px solid var(--ink);background:var(--panel);padding:28px;position:sticky;top:96px}
.summary .lab{font-family:var(--mono);font-size:11px;letter-spacing:.18em;color:var(--soft);text-transform:uppercase}
#cfgLine{margin-top:12px;font-size:15px;line-height:1.6;color:var(--ink2);min-height:48px}
.sum-div{border-top:1px solid var(--line2);margin:18px 0}
.total-row{display:flex;justify-content:space-between;align-items:baseline;gap:12px}
#cfgTotal{font-size:40px;font-weight:800;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.lead-row{display:flex;justify-content:space-between;gap:12px;margin-top:10px;font-size:14.5px}
.lead-row strong{font-variant-numeric:tabular-nums}
.deposit{margin-top:14px;font-size:13px;color:var(--soft)}
.summary .btn{margin-top:20px}
.summary .btn + .btn{margin-top:10px}
.est-note{margin-top:16px;font-family:var(--mono);font-size:10px;letter-spacing:.12em;color:var(--soft)}
/* ============ workshop (dark) ============ */
.ws{background:var(--dark);color:#EDE7DA}
.ws .eyebrow{color:rgba(237,231,218,.6)}
.ws-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:64px;align-items:start}
.ws p.muted{color:rgba(237,231,218,.72);margin-top:18px;max-width:540px}
.principles{margin-top:38px}
.principle{display:grid;grid-template-columns:46px 1fr;gap:14px;border-top:1px solid var(--darkline);padding:17px 0}
.principle .pn{font-family:var(--mono);font-size:13px;color:var(--accent);font-weight:700}
.principle h3{font-size:17px;font-weight:700}
.principle p{font-size:14.5px;color:rgba(237,231,218,.62);margin-top:3px}
.visit-card{border:1px solid rgba(237,231,218,.28);background:rgba(255,255,255,.03);padding:28px}
.vrow{display:flex;justify-content:space-between;gap:18px;border-top:1px solid var(--darkline);padding:11px 0;font-size:14.5px}
.vrow:first-of-type{border-top:none;padding-top:0}
.vrow dt{font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:rgba(237,231,218,.5);padding-top:3px;flex:none}
.vrow dd{text-align:right;color:rgba(237,231,218,.9)}
.mmap{width:100%;height:auto;margin-top:20px;border-top:1px solid var(--darkline);padding-top:18px}
.mtxt{font-family:var(--mono);font-size:9px;fill:rgba(237,231,218,.6);letter-spacing:1.5px}
.msvg-d .t{stroke:#EDE7DA;fill:none;stroke-linecap:round;stroke-linejoin:round}
.ws-note{margin-top:14px;font-size:13px;color:rgba(237,231,218,.55)}
.visit-card .btn{margin-top:20px}
/* ============ riders ============ */
.q-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:44px}
.q-grid blockquote{font-family:var(--serif);font-size:19px;line-height:1.55}
.q-grid blockquote::before{content:"“";display:block;font-size:46px;line-height:.6;color:var(--accent);margin-bottom:16px;font-style:normal}
.q-grid cite{display:block;margin-top:18px;font-style:normal;font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--soft);line-height:1.9}
.q-grid cite strong{color:var(--ink);font-weight:700}
.q-grid blockquote:nth-child(2){margin-top:48px}
.q-grid blockquote:nth-child(3){margin-top:96px}
/* ============ faq ============ */
.faq-wrap{max-width:780px;margin:0 auto}
.faq-item{border-top:1px solid var(--line)}
.faq-item:last-child{border-bottom:1px solid var(--line)}
.faq-q{width:100%;display:flex;justify-content:space-between;align-items:center;gap:20px;padding:22px 4px;text-align:left}
.faq-q h3{font-size:17px;font-weight:600;letter-spacing:-.005em}
.faq-ic{position:relative;width:16px;height:16px;flex:none}
.faq-ic::before,.faq-ic::after{content:"";position:absolute;background:var(--accent);left:50%;top:50%;transition:transform .3s}
.faq-ic::before{width:16px;height:2px;transform:translate(-50%,-50%)}
.faq-ic::after{width:2px;height:16px;transform:translate(-50%,-50%)}
.faq-item.open .faq-ic::after{transform:translate(-50%,-50%) rotate(90deg)}
.faq-a{max-height:0;overflow:hidden;transition:max-height .35s ease}
.faq-a p{padding:0 4px 24px;color:var(--ink2);font-size:15px;max-width:640px}
/* ============ cta band ============ */
.cta{background:var(--accent);color:var(--cream);padding:96px 0}
.cta-in{display:flex;justify-content:space-between;align-items:center;gap:40px;flex-wrap:wrap}
.cta h2{font-size:clamp(36px,4.6vw,56px);letter-spacing:-.025em;line-height:1.05}
.cta p{margin-top:14px;color:rgba(255,246,234,.85);max-width:440px}
.cta-btns{display:flex;gap:14px;flex-wrap:wrap}
/* ============ footer ============ */
.footer{background:#16150F;color:rgba(244,240,232,.8);padding:72px 0 32px}
.f-grid{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:44px}
.f-brand p{margin-top:16px;font-size:14px;color:rgba(244,240,232,.5);max-width:260px}
.f-col h4{font-family:var(--mono);font-size:10.5px;letter-spacing:.18em;color:rgba(244,240,232,.45);text-transform:uppercase;margin-bottom:16px;font-weight:500}
.f-col ul{list-style:none}
.f-col li{font-size:14px;padding:4px 0;color:rgba(244,240,232,.75)}
.f-col a{border-bottom:1px solid transparent;transition:color .2s,border-color .2s}
.f-col a:hover{color:var(--cream);border-bottom-color:var(--accent)}
.f-bottom{display:flex;justify-content:space-between;gap:16px;flex-wrap:wrap;border-top:1px solid rgba(244,240,232,.12);margin-top:56px;padding-top:24px;font-family:var(--mono);font-size:10.5px;letter-spacing:.12em;color:rgba(244,240,232,.42)}
/* ============ modal ============ */
.overlay{position:fixed;inset:0;z-index:1000;background:rgba(20,19,15,.55);backdrop-filter:blur(3px);display:flex;align-items:center;justify-content:center;padding:20px;opacity:0;pointer-events:none;transition:opacity .25s}
.overlay.open{opacity:1;pointer-events:auto}
.modal{background:var(--paper);border:1px solid var(--ink);max-width:480px;width:100%;padding:34px;position:relative;max-height:90vh;overflow:auto;transform:translateY(12px);transition:transform .25s}
.overlay.open .modal{transform:none}
.modal-x{position:absolute;top:14px;right:14px;width:34px;height:34px;display:flex;align-items:center;justify-content:center;border:1px solid var(--line2);border-radius:2px;transition:background .2s,color .2s}
.modal-x:hover{background:var(--ink);color:var(--paper)}
.modal h3{font-size:26px;letter-spacing:-.02em;margin-bottom:8px}
.modal-sub{font-size:14.5px;color:var(--ink2)}
.modal-sum{font-family:var(--mono);font-size:12.5px;line-height:1.7;background:var(--paper2);border-left:3px solid var(--accent);padding:14px 16px;margin-top:18px;white-space:pre-wrap}
.field{margin-top:16px}
.field label{display:flex;justify-content:space-between;font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--soft);margin-bottom:7px}
.field label span{text-transform:none;letter-spacing:.04em}
.field input,.field textarea{width:100%;padding:12px 14px;border:1px solid var(--line2);background:#FAF6EC;font:inherit;font-size:15px;color:var(--ink);border-radius:2px;resize:vertical}
.field input:focus,.field textarea:focus{outline:none;border-color:var(--ink);box-shadow:0 0 0 1px var(--ink)}
.modal form .btn{margin-top:22px}
.form-note{margin-top:12px;font-size:12.5px;color:var(--soft)}
.ok{text-align:center;padding:12px 0 4px}
.ok-svg{width:64px;height:64px;margin:0 auto 18px}
.ok-c,.ok-k{fill:none;stroke:var(--accent);stroke-linecap:round;stroke-linejoin:round}
.ok-c{stroke-width:3}.ok-k{stroke-width:4}
.ok h4{font-size:22px;letter-spacing:-.01em}
.ok p{margin:10px 0 22px;font-size:14.5px;color:var(--ink2)}
/* ============ reveal & motion ============ */
.reveal{opacity:0;transform:translateY(18px);transition:opacity .7s ease,transform .7s ease}
.reveal.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){
html{scroll-behavior:auto}
.draw{animation:none;stroke-dashoffset:0}
.fade,.fade45{animation:none;opacity:1;stroke-opacity:.45}
.spin,.hs-ring,.ticker-track{animation:none}
.reveal{opacity:1;transform:none;transition:none}
.schem-caption.show{animation:none}
}
/* ============ responsive ============ */
@media (max-width:1020px){
.hero-grid,.models-grid,.ws-grid,.build-grid{grid-template-columns:1fr;gap:44px}
.spec-panel,.summary{position:static}
.proc-grid{grid-template-columns:1fr 1fr;gap:32px}
.q-grid{grid-template-columns:1fr;gap:36px}
.q-grid blockquote:nth-child(2),.q-grid blockquote:nth-child(3){margin-top:0}
.f-grid{grid-template-columns:1fr 1fr}
}
@media (max-width:880px){
.nav{display:none;position:absolute;top:100%;left:0;right:0;background:var(--paper);border-bottom:1px solid var(--line);flex-direction:column;align-items:stretch;gap:0;padding:10px 28px 22px}
.nav.open{display:flex}
.nav a{padding:14px 0;border-bottom:1px solid var(--line);font-size:15px}
.nav .btn{margin-top:16px}
.nav-toggle{display:flex}
}
@media (max-width:640px){
.sec{padding:76px 0}
.hero{padding:44px 0 72px}
.proc-grid{grid-template-columns:1fr}
.topbar-in .tb-r{display:none}
.model-row{grid-template-columns:36px 1fr auto;row-gap:2px}
.model-row .go{display:none}
.container{padding:0 20px}
.f-grid{grid-template-columns:1fr}
}
</style>
</head>
<body>
<div id="top"></div>
<!-- topbar -->
<div class="topbar">
<div class="container topbar-in">
<span>REFSHALEVEJ 167A · 1432 KØBENHAVN K</span>
<span class="tb-r">WORKSHOP THU–SAT · TEST RIDES DAILY · +45 31 62 08 40</span>
</div>
</div>
<!-- header -->
<header class="site-header" id="siteHeader">
<div class="container header-in">
<a class="logo" href="#top" aria-label="Lumen Cycles — home">
<svg width="26" height="26" viewBox="0 0 32 32" aria-hidden="true"><circle cx="16" cy="21" r="8.5" fill="none" stroke="var(--ink)" stroke-width="2.4"/><circle cx="16" cy="21" r="1.8" fill="var(--ink)"/><path d="M16 9.5V4M21.5 11l3.5-4M10.5 11L7 7" stroke="var(--accent)" stroke-width="2.4" stroke-linecap="round" fill="none"/></svg>
LUMEN <em>CYCLES</em>
</a>
<nav class="nav" id="siteNav" aria-label="Main">
<a href="#bikes">Bikes</a>
<a href="#process">Process</a>
<a href="#build">Build & price</a>
<a href="#workshop">Workshop</a>
<a href="#faq">FAQ</a>
<button class="btn btn-ink js-modal" data-mode="visit">Book a visit</button>
</nav>
<button class="nav-toggle" id="navToggle" aria-label="Menu" aria-expanded="false"><span></span><span></span></button>
</div>
</header>
<main>
<!-- ============ HERO ============ -->
<section class="hero">
<div class="container hero-grid">
<div>
<p class="eyebrow reveal">Custom cargo bikes · Copenhagen · Est. 2016</p>
<h1 class="reveal">A cargo bike built <span class="fx">around you.</span></h1>
<p class="hero-lead reveal">Lumen Cycles hand-builds cargo bikes to order in our Copenhagen workshop — sized to your streets, your cargo and your family. One frame at a time, and no two alike.</p>
<div class="cta-row reveal">
<a class="btn btn-accent" href="#build">Start your build <span class="ar">→</span></a>
<button class="btn btn-ghost js-modal" data-mode="testride">Book a test ride</button>
</div>
<div class="facts reveal">
<div class="fact"><strong>€3,400</strong><span>entry price, built to order</span></div>
<div class="fact"><strong>6–8 wks</strong><span>deposit to delivery</span></div>
<div class="fact"><strong>500+</strong><span>Lumens on the road</span></div>
<div class="fact"><strong>5 yr</strong><span>frame warranty</span></div>
</div>
</div>
<div class="schem-frame reveal">
<div class="schem-meta"><span>DRAWING N° 031 — LONG JOHN</span><span>SCALE 1:8 · REFSHALEØEN</span></div>
<svg class="schem" viewBox="0 0 920 560" role="img" aria-label="Annotated technical drawing of a Lumen Long John cargo bike">
<defs>
<marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6.5" markerHeight="6.5" orient="auto-start-reverse"><path d="M0 0 L10 5 L0 10 Z" fill="#A79D89"/></marker>
</defs>
<!-- ground -->
<line class="gnd" x1="56" y1="500" x2="864" y2="500"/>
<path class="hatch fade" d="M90 502l-9 9M146 502l-9 9M202 502l-9 9M258 502l-9 9M314 502l-9 9M370 502l-9 9M426 502l-9 9M482 502l-9 9M538 502l-9 9M594 502l-9 9M650 502l-9 9M706 502l-9 9M762 502l-9 9M818 502l-9 9"/>
<!-- rear wheel -->
<circle class="t tire draw" pathLength="1" style="animation-delay:.05s" cx="672" cy="412" r="88"/>
<circle class="t w2 draw" pathLength="1" style="animation-delay:.15s" cx="672" cy="412" r="69"/>
<g class="spin slow" style="transform-origin:672px 412px"><path class="t w2" d="M694 412H740M688 396L720 364M672 390V344M656 396L624 364M650 412H604M656 428L624 460M672 434V480M688 428L720 460"/></g>
<circle class="t w3 draw" pathLength="1" style="animation-delay:.3s" cx="672" cy="412" r="20"/>
<circle class="fill-ink fade" cx="672" cy="412" r="9"/>
<!-- front wheel -->
<circle class="t tire draw" pathLength="1" style="animation-delay:.1s" cx="190" cy="444" r="56"/>
<circle class="t w2 draw" pathLength="1" style="animation-delay:.2s" cx="190" cy="444" r="43"/>
<g class="spin" style="transform-origin:190px 444px"><path class="t w2" d="M199 444H231M196 438L219 415M190 435V403M184 438L161 415M181 444H149M184 450L161 473M190 453V485M196 450L219 473"/></g>
<circle class="fill-ink fade" cx="190" cy="444" r="7"/>
<!-- fenders -->
<path class="t w3 draw" pathLength="1" style="animation-delay:.5s" d="M582 379 Q672 249 762 379"/>
<path class="t w3 draw" pathLength="1" style="animation-delay:.55s" d="M133 423 Q190 341 247 423"/>
<!-- box -->
<rect class="boxfill draw" pathLength="1" style="animation-delay:.15s" x="252" y="300" width="248" height="86"/>
<path class="t w1 fade" opacity=".45" d="M283 300V386M314 300V386M345 300V386M376 300V386M407 300V386M438 300V386M469 300V386"/>
<line class="t w1 fade" opacity=".7" x1="252" y1="312" x2="500" y2="312"/>
<circle class="hl fade" cx="250" cy="318" r="5.5"/>
<!-- battery -->
<rect class="t w3 draw" pathLength="1" style="animation-delay:.6s" x="310" y="394" width="140" height="18" rx="4"/>
<path class="t w1 fade" opacity=".5" d="M326 394V412M358 394V412M390 394V412M422 394V412"/>
<!-- frame -->
<line class="t w7 draw" pathLength="1" style="animation-delay:.25s" x1="190" y1="444" x2="236" y2="300"/>
<line class="t w5 draw" pathLength="1" style="animation-delay:.3s" x1="236" y1="300" x2="236" y2="286"/>
<path class="t w6 draw" pathLength="1" style="animation-delay:.32s" d="M206 290 Q236 277 266 290"/>
<line class="t w7 draw" pathLength="1" style="animation-delay:.35s" x1="496" y1="352" x2="560" y2="380"/>
<line class="t w7 draw" pathLength="1" style="animation-delay:.4s" x1="560" y1="380" x2="592" y2="262"/>
<line class="t w5 draw" pathLength="1" style="animation-delay:.45s" x1="560" y1="380" x2="672" y2="412"/>
<line class="t w5 draw" pathLength="1" style="animation-delay:.45s" x1="592" y1="268" x2="664" y2="404"/>
<circle class="t w5 draw" pathLength="1" style="animation-delay:.5s" cx="560" cy="380" r="13"/>
<circle class="t w2 draw" pathLength="1" style="animation-delay:.5s" cx="560" cy="380" r="26"/>
<g class="spin fast" style="transform-origin:560px 380px"><path class="t w2 fade" d="M560 358V366M560 394V402M538 380H546M574 380H582"/></g>
<line class="t w6 draw" pathLength="1" style="animation-delay:.55s" x1="560" y1="380" x2="592" y2="414"/>
<rect class="fill-ink fade" x="580" y="409" width="26" height="9" rx="2"/>
<path class="t w2 fade" d="M562 356L672 402M562 404L672 422"/>
<line class="t w5 draw" pathLength="1" style="animation-delay:.5s" x1="590" y1="262" x2="590" y2="252"/>
<path class="t w9 draw" pathLength="1" style="animation-delay:.55s" d="M564 251 L620 249"/>
<!-- kickstand -->
<path class="t w4 draw" pathLength="1" style="animation-delay:.65s" d="M470 386L452 496M442 496H462"/>
<!-- dimensions -->
<g class="fade">
<line class="dim" x1="134" y1="504" x2="134" y2="536"/>
<line class="dim" x1="760" y1="504" x2="760" y2="536"/>
<line class="dim" x1="134" y1="532" x2="760" y2="532" marker-start="url(#arr)" marker-end="url(#arr)"/>
<text class="dtxt" x="447" y="522" text-anchor="middle">184 CM</text>
<line class="dim" x1="252" y1="296" x2="252" y2="270"/>
<line class="dim" x1="500" y1="296" x2="500" y2="270"/>
<line class="dim" x1="252" y1="274" x2="500" y2="274" marker-start="url(#arr)" marker-end="url(#arr)"/>
<text class="dtxt" x="376" y="264" text-anchor="middle">100 CM</text>
</g>
<!-- hotspots -->
<g class="hs fade" data-hs="0" tabindex="0" role="button" aria-label="Motor details"><circle class="hs-hit" cx="704" cy="450" r="18"/><circle class="hs-ring" cx="704" cy="450" r="6"/><circle class="hs-dot" cx="704" cy="450" r="4.5"/></g>
<g class="hs fade" data-hs="1" tabindex="0" role="button" aria-label="Cargo box details"><circle class="hs-hit" cx="376" cy="343" r="18"/><circle class="hs-ring" cx="376" cy="343" r="6"/><circle class="hs-dot" cx="376" cy="343" r="4.5"/></g>
<g class="hs fade" data-hs="2" tabindex="0" role="button" aria-label="Fit details"><circle class="hs-hit" cx="592" cy="250" r="18"/><circle class="hs-ring" cx="592" cy="250" r="6"/><circle class="hs-dot" cx="592" cy="250" r="4.5"/></g>
<g class="hs fade" data-hs="3" tabindex="0" role="button" aria-label="Battery details"><circle class="hs-hit" cx="380" cy="403" r="18"/><circle class="hs-ring" cx="380" cy="403" r="6"/><circle class="hs-dot" cx="380" cy="403" r="4.5"/></g>
<g class="hs fade" data-hs="4" tabindex="0" role="button" aria-label="Steering details"><circle class="hs-hit" cx="236" cy="330" r="18"/><circle class="hs-ring" cx="236" cy="330" r="6"/><circle class="hs-dot" cx="236" cy="330" r="4.5"/></g>
</svg>
<div class="schem-caption show" id="schemCaption"><span class="cap-n" id="capN">02</span><p id="capText"></p></div>
</div>
</div>
</section>
<!-- ticker -->
<div class="ticker" aria-hidden="true">
<div class="ticker-track">
<div class="ticker-set"><span>HAND-BUILT IN COPENHAGEN</span><i>·</i><span>500+ BIKES ON THE ROAD</span><i>·</i><span>FROM €3,400 — NO HIDDEN FEES</span><i>·</i><span>5-YEAR FRAME WARRANTY</span><i>·</i><span>TEST RIDES DAILY ON REFSHALEØEN</span><i>·</i><span>SERVICE FOR LIFE</span><i>·</i></div>
<div class="ticker-set"><span>HAND-BUILT IN COPENHAGEN</span><i>·</i><span>500+ BIKES ON THE ROAD</span><i>·</i><span>FROM €3,400 — NO HIDDEN FEES</span><i>·</i><span>5-YEAR FRAME WARRANTY</span><i>·</i><span>TEST RIDES DAILY ON REFSHALEØEN</span><i>·</i><span>SERVICE FOR LIFE</span><i>·</i></div>
</div>
</div>
<!-- ============ MODELS ============ -->
<section class="sec" id="bikes">
<div class="container">
<div class="sec-head reveal">
<p class="eyebrow">The range</p>
<h2 class="sec-title">Three frames. One workshop.</h2>
<p class="sec-lead">Every Lumen starts as one of three proven long-john platforms, then gets cut, boxed and geared around you. Prices are entry points — your build is quoted fixed before we weld.</p>
</div>
<div class="models-grid">
<div class="reveal">
<button class="model-row" data-model="city" aria-pressed="false">
<span class="idx">01</span>
<span><h3>City Hauler</h3><p>The everyday workhorse for shops, tools and tight streets.</p></span>
<span class="price">from €3,400</span>
<span class="go">→</span>
</button>
<button class="model-row" data-model="longjohn" aria-pressed="true">
<span class="idx">02</span>
<span><h3>Long John</h3><p>The classic. Kids, cargo and the weekly shop — in one run.</p></span>
<span class="price">from €3,900</span>
<span class="go">→</span>
</button>
<button class="model-row" data-model="cruiser" aria-pressed="false">
<span class="idx">03</span>
<span><h3>Family Cruiser</h3><p>Longest box, bench seats, canopy-ready. The family infrastructure.</p></span>
<span class="price">from €4,600</span>
<span class="go">→</span>
</button>
</div>
<div class="spec-panel reveal">
<div class="spec-top"><div><span class="no" id="spIdx">N° 02</span><h3 id="spName">Long John</h3></div><span class="spec-price" id="spPrice">from €3,900</span></div>
<svg class="msvg msvg-d" viewBox="0 0 720 340" role="img" aria-label="Side profile of the selected model">
<defs><clipPath id="boxClip"><rect id="clipRect" x="170" y="204" width="225" height="62"/></clipPath></defs>
<line class="gnd" x1="36" y1="312" x2="684" y2="312"/>
<path class="hatch" d="M60 314l-8 8M120 314l-8 8M180 314l-8 8M240 314l-8 8M300 314l-8 8M360 314l-8 8M420 314l-8 8M480 314l-8 8M540 314l-8 8M600 314l-8 8M660 314l-8 8"/>
<!-- wheels -->
<circle class="t tire" cx="150" cy="272" r="42"/>
<circle class="t w2" cx="150" cy="272" r="33"/>
<g class="spin" style="transform-origin:150px 272px"><path class="t w2" d="M158 272H181M156 266L172 250M150 264V241M144 266L128 250M142 272H119M144 278L128 294M150 280V303M156 278L172 294"/></g>
<circle class="fill-ink" cx="150" cy="272" r="6"/>
<circle class="t tire" cx="540" cy="252" r="56"/>
<circle class="t w2" cx="540" cy="252" r="45"/>
<g class="spin slow" style="transform-origin:540px 252px"><path class="t w2" d="M550 252H583M547 245L570 222M540 242V209M533 245L510 222M530 252H497M533 259L510 282M540 262V295M547 259L570 282"/></g>
<circle class="fill-ink" cx="540" cy="252" r="8"/>
<!-- fork & bars -->
<line class="t w5" x1="150" y1="272" x2="178" y2="198"/>
<line class="t w4" x1="178" y1="198" x2="182" y2="190"/>
<line class="t w5" x1="160" y1="188" x2="204" y2="188"/>
<!-- canopy -->
<path id="canopyPath" class="t w3" d="M174 204 Q298 96 391 204" style="display:none"/>
<!-- box -->
<rect id="boxRect" class="boxfill" x="170" y="204" width="225" height="62"/>
<g clip-path="url(#boxClip)"><path class="t w1" opacity=".45" d="M198 204V266M226 204V266M254 204V266M282 204V266M310 204V266M338 204V266M366 204V266M394 204V266M422 204V266"/></g>
<circle class="hl" cx="172" cy="208" r="4"/>
<!-- frame -->
<line id="mainTube" class="t w6" x1="393" y1="248" x2="452" y2="264"/>
<circle class="t w4" cx="452" cy="264" r="11"/>
<circle class="t w2" cx="452" cy="264" r="17"/>
<line class="t w5" x1="452" y1="264" x2="472" y2="288"/>
<rect class="fill-ink" x="464" y="284" width="22" height="7" rx="2"/>
<line class="t w6" x1="452" y1="264" x2="474" y2="184"/>
<line class="t w7" x1="458" y1="178" x2="494" y2="178"/>
<line class="t w4" x1="474" y1="190" x2="534" y2="248"/>
<line class="t w4" x1="452" y1="264" x2="540" y2="252"/>
<path class="t w4" d="M408 266L396 310M388 310H404"/>
<!-- box dimension -->
<line class="dim" x1="170" y1="202" x2="170" y2="190"/>
<line class="dim" id="dimTick2" x1="395" y1="202" x2="395" y2="190"/>
<line class="dim" id="dimLine" x1="170" y1="194" x2="395" y2="194" marker-start="url(#arr)" marker-end="url(#arr)"/>
<text class="dtxt" id="dimText" x="282" y="186" text-anchor="middle">128 CM</text>
</svg>
<dl>
<div class="spec-row"><dt>Cargo volume</dt><dd id="spVol">180 L</dd></div>
<div class="spec-row"><dt>Max payload</dt><dd id="spPay">100 kg</dd></div>
<div class="spec-row"><dt>Wheels</dt><dd id="spWheels">20″ front · 28″ rear</dd></div>
<div class="spec-row"><dt>Weight</dt><dd id="spWeight">from 20.8 kg</dd></div>
<div class="spec-row"><dt>Gearing</dt><dd id="spGears">Deore 10-speed or Enviolo automatic</dd></div>
<div class="spec-row"><dt>Brakes</dt><dd id="spBrakes">Hydraulic disc, 180 mm</dd></div>
<div class="spec-row wide"><dt>Best for</dt><dd id="spBest">Kindergarten runs, family weekends, one-trip shopping.</dd></div>
</dl>
<button class="btn btn-ink w100" id="cfgLink" data-config-model="longjohn">Configure this model <span class="ar">→</span></button>
</div>
</div>
</div>
</section>
<!-- ============ PROCESS ============ -->
<section class="sec sec-tint" id="process">
<div class="container">
<div class="sec-head reveal">
<p class="eyebrow">How it works</p>
<h2 class="sec-title">From first coffee to first ride.</h2>
<p class="sec-lead">Four steps, one workshop, zero call centres. Most builds finish in eight weeks.</p>
</div>
<div class="proc-grid">
<div class="step reveal"><span class="num">01</span><h3>Say hej</h3><p>Tell us what you carry. We’ll match you to a frame and take you for a test ride along the harbour.</p><span class="when">Day 1</span></div>
<div class="step reveal"><span class="num">02</span><h3>Design & fit</h3><p>Sizing, box size, motor, colour. You approve the drawing before we cut a single tube.</p><span class="when">Week 1</span></div>
<div class="step reveal"><span class="num">03</span><h3>The build</h3><p>Frame welded, box fitted, wheels laced, cables routed — photographed at every stage.</p><span class="when">Weeks 2–7</span></div>
<div class="step reveal"><span class="num">04</span><h3>Delivery & first service</h3><p>We fit you on the finished bike, ride it out the door, and see you again at 500 km — free.</p><span class="when">Week 8</span></div>
</div>
</div>
</section>
<!-- ============ BUILD & PRICE ============ -->
<section class="sec" id="build">
<div class="container">
<div class="sec-head reveal">
<p class="eyebrow">Build & price</p>
<h2 class="sec-title">Spec your Lumen.</h2>
<p class="sec-lead">Honest, fixed pricing — the number you see is the number you pay. Change your mind as often as you like; the estimate updates live.</p>
</div>
<div class="build-grid">
<form id="cfgForm" class="reveal">
<fieldset class="opt"><legend>01 · Frame</legend>
<div class="pills">
<label class="pill"><input type="radio" name="model" value="city" data-price="3400" data-short="City Hauler"><span>City Hauler <em>€3,400</em></span></label>
<label class="pill"><input type="radio" name="model" value="longjohn" data-price="3900" data-short="Long John" checked><span>Long John <em>€3,900</em></span></label>
<label class="pill"><input type="radio" name="model" value="cruiser" data-price="4600" data-short="Family Cruiser"><span>Family Cruiser <em>€4,600</em></span></label>
</div>
</fieldset>
<fieldset class="opt"><legend>02 · Drive</legend>
<div class="pills">
<label class="pill"><input type="radio" name="drive" value="pedal" data-price="0" data-short="Pure pedal"><span>Pure pedal · Deore 10-speed <em>included</em></span></label>
<label class="pill"><input type="radio" name="drive" value="enviolo" data-price="750" data-short="Enviolo hub"><span>Enviolo automatic hub <em>+€750</em></span></label>
<label class="pill"><input type="radio" name="drive" value="steps" data-price="1150" data-short="Shimano STEPS"><span>Shimano STEPS Cargo <em>+€1,150</em></span></label>
<label class="pill"><input type="radio" name="drive" value="bosch" data-price="1450" data-short="Bosch Cargo Line" checked><span>Bosch Cargo Line <em>+€1,450</em></span></label>
</div>
</fieldset>
<fieldset class="opt"><legend>03 · Cargo box</legend>
<div class="pills">
<label class="pill"><input type="radio" name="box" value="birch" data-price="0" data-short="Birch box" checked><span>Birch ply, oiled <em>included</em></span></label>
<label class="pill"><input type="radio" name="box" value="paint" data-price="240" data-short="Painted ply"><span>Marine ply, painted <em>+€240</em></span></label>
<label class="pill"><input type="radio" name="box" value="oak" data-price="520" data-short="Oak box"><span>Solid oak, hand-oiled <em>+€520</em></span></label>
</div>
</fieldset>
<fieldset class="opt"><legend>04 · Canopy</legend>
<div class="pills">
<label class="pill"><input type="radio" name="canopy" value="none" data-price="0" data-short="No canopy" checked><span>No canopy <em>included</em></span></label>
<label class="pill"><input type="radio" name="canopy" value="rain" data-price="380" data-short="Rain canopy"><span>Rain canopy <em>+€380</em></span></label>
<label class="pill"><input type="radio" name="canopy" value="full" data-price="560" data-short="Full canopy"><span>Full family canopy <em>+€560</em></span></label>
</div>
</fieldset>
<fieldset class="opt"><legend>05 · Finish</legend>
<div class="pills">
<label class="pill"><input type="radio" name="coat" value="std" data-price="0" data-short="Standard colour" checked><span>Standard colours (6) <em>included</em></span></label>
<label class="pill"><input type="radio" name="coat" value="ral" data-price="180" data-short="Custom RAL"><span>Custom RAL match <em>+€180</em></span></label>
</div>
</fieldset>
<fieldset class="opt"><legend>06 · Extras</legend>
<div class="pills">
<label class="pill"><input type="checkbox" name="extras" value="lock" data-price="90" data-short="Abus disc lock"><span>Abus disc lock <em>+€90</em></span></label>
<label class="pill"><input type="checkbox" name="extras" value="bench" data-price="160" data-short="Extra child bench"><span>Extra child bench <em>+€160</em></span></label>
<label class="pill"><input type="checkbox" name="extras" value="winter" data-price="140" data-short="Winter tyres"><span>Studded winter tyres <em>+€140</em></span></label>
</div>
</fieldset>
</form>
<div class="summary reveal">
<span class="lab">Your Lumen — summary</span>
<p id="cfgLine">Long John · Bosch Cargo Line · Birch box · No canopy · Standard colour</p>
<div class="sum-div"></div>
<div class="total-row"><span class="lab">Estimate</span><span id="cfgTotal">€0</span></div>
<div class="lead-row"><span class="lab">Lead time</span><strong id="cfgLead">6–8 weeks</strong></div>
<p class="deposit">€200 refundable deposit · quote locked for 60 days · EU shipping flat €190.</p>
<button class="btn btn-accent w100" id="reserveBtn">Reserve this build <span class="ar">→</span></button>
<button class="btn btn-ghost w100 js-modal" data-mode="visit">Book a workshop visit</button>
<p class="est-note">EST. N° L-2025-031 · VALID 60 DAYS · VAT INCLUDED</p>
</div>
</div>
</div>
</section>
<!-- ============ WORKSHOP ============ -->
<section class="sec ws" id="workshop">
<div class="container ws-grid">
<div class="reveal">
<p class="eyebrow">The workshop</p>
<h2 class="sec-title">Built on Refshaleøen.</h2>
<p class="muted">Our workshop is a former shipyard hall on Refshaleøen — steel, salt air and the harbour fifty metres away. Frames are welded, boxed and wired under one roof by four people whose names are on the door. Come see a frame in the jig, or take the test fleet out along the water.</p>
<div class="principles">
<div class="principle"><span class="pn">01</span><div><h3>Fit before specs</h3><p>We start with your body, your route and what you actually carry — then choose the frame, not the other way round.</p></div></div>
<div class="principle"><span class="pn">02</span><div><h3>Honest materials</h3><p>CroMo steel, birch ply and components we can service for a decade. Nothing sealed, nothing disposable.</p></div></div>
<div class="principle"><span class="pn">03</span><div><h3>One roof, no middlemen</h3><p>The people who weld your frame also lace your wheels and bleed your brakes. You can watch.</p></div></div>
<div class="principle"><span class="pn">04</span><div><h3>Service for life</h3><p>First service free at 500 km, same-week slots after that — for as long as you ride the bike.</p></div></div>
</div>
</div>
<div class="visit-card reveal">
<dl>
<div class="vrow"><dt>Visit</dt><dd>Hall 7, Refshalevej 167A<br>1432 København K</dd></div>
<div class="vrow"><dt>Hours</dt><dd>Thu–Fri 10–17 · Sat 10–14<br>Sun–Wed by appointment</dd></div>
<div class="vrow"><dt>Call</dt><dd>+45 31 62 08 40</dd></div>
<div class="vrow"><dt>Write</dt><dd>hej@lumencycles.dk</dd></div>
</dl>
<svg class="mmap msvg-d" viewBox="0 0 320 190" role="img" aria-label="Stylised map of the workshop location on Refshaleøen">
<path class="t w2" d="M212 0C204 42 236 66 226 104 219 132 236 156 228 190"/>
<path stroke="rgba(237,231,218,.3)" stroke-width="1.5" fill="none" d="M244 18l14-10M258 44l16-11M250 78l16-11M262 112l16-11M252 146l16-11M262 172l14-10"/>
<path stroke="rgba(237,231,218,.22)" stroke-width="1.5" fill="none" d="M0 52H196M0 108H190M46 0V190M118 0V190"/>
<path stroke="var(--accent)" stroke-width="2" fill="none" stroke-dasharray="3 6" d="M28 168C70 150 96 122 128 92"/>
<circle cx="128" cy="92" r="10" fill="none" stroke="var(--accent)" opacity=".55"/>
<circle cx="128" cy="92" r="5" fill="var(--accent)"/>
<text class="mtxt" x="140" y="88">LUMEN — HALL 7</text>
<text class="mtxt" x="24" y="184">FROM NYHAVN · FERRY 991</text>
</svg>
<p class="ws-note">Six-bike test fleet — ride the harbour loop any Saturday, no appointment needed.</p>
<button class="btn btn-ghost-l js-modal" data-mode="visit">Book a visit <span class="ar">→</span></button>
</div>
</div>
</section>
<!-- ============ RIDERS ============ -->
<section class="sec sec-tint" id="riders">
<div class="container">
<div class="sec-head reveal">
<p class="eyebrow">Riders</p>
<h2 class="sec-title">What the city says.</h2>
</div>
<div class="q-grid">
<blockquote class="reveal">Three winters of kindergarten runs, sleet and salt — the Lumen hasn’t missed a morning. The oak box just keeps looking better.<cite><strong>Mette F.</strong><br>Family Cruiser · Nørrebro</cite></blockquote>
<blockquote class="reveal">I sold my van after two months. Four deliveries a day across Indre By and I’m still home for lunch.<cite><strong>Jonas K.</strong><br>City Hauler · Courier</cite></blockquote>
<blockquote class="reveal">They designed the box around my double bass. Try finding that in a catalogue.<cite><strong>Astrid L.</strong><br>Long John · Custom build</cite></blockquote>
</div>
</div>
</section>
<!-- ============ FAQ ============ -->
<section class="sec" id="faq">
<div class="container">
<div class="sec-head reveal" style="margin-left:auto;margin-right:auto;text-align:left">
<p class="eyebrow">Good to know</p>
<h2 class="sec-title">Questions, answered.</h2>
</div>
<div class="faq-wrap reveal">
<div class="faq-item"><h3><button class="faq-q" aria-expanded="false"><span>Do I need a test ride before ordering?</span><span class="faq-ic" aria-hidden="true"></span></button></h3><div class="faq-a"><p>You can order straight away, but we recommend it. Test rides run Thursday to Saturday from the workshop — bring the kids, the dog or the tools you actually carry.</p></div></div>
<div class="faq-item"><h3><button class="faq-q" aria-expanded="false"><span>How long does a custom build take?</span><span class="faq-ic" aria-hidden="true"></span></button></h3><div class="faq-a"><p>Six to eight weeks from deposit to delivery. Custom paint or an oak box can add up to two weeks. You’ll get build photos at welding, box-fit and final assembly.</p></div></div>
<div class="faq-item"><h3><button class="faq-q" aria-expanded="false"><span>What if something needs fixing?</span><span class="faq-ic" aria-hidden="true"></span></button></h3><div class="faq-a"><p>Your first service at 500 km is free. After that, same-week workshop slots for life — most repairs are done while you wait, coffee in hand.</p></div></div>
<div class="faq-item"><h3><button class="faq-q" aria-expanded="false"><span>Do you ship outside Copenhagen?</span><span class="faq-ic" aria-hidden="true"></span></button></h3><div class="faq-a"><p>Anywhere in the EU. Bikes leave partially assembled in a crate, with a video call for final setup. Shipping is a flat €190.</p></div></div>
<div class="faq-item"><h3><button class="faq-q" aria-expanded="false"><span>How far does the e-assist actually go?</span><span class="faq-ic" aria-hidden="true"></span></button></h3><div class="faq-a"><p>40–90 km on a charge, depending on load and hills. With 60 kg of cargo in city traffic, plan on about 55 km.</p></div></div>
<div class="faq-item"><h3><button class="faq-q" aria-expanded="false"><span>Can I pay in instalments?</span><span class="faq-ic" aria-hidden="true"></span></button></h3><div class="faq-a"><p>Yes — a 30/70 split, or 24–36-month financing through our partner. Ask at your visit or in the message field when you reserve.</p></div></div>
</div>
</div>
</section>
<!-- ============ CTA ============ -->
<section class="cta">
<div class="container cta-in reveal">
<div>
<h2>Ready when you are.</h2>
<p>Book a test ride, or spec your build online — we’ll hold your slot for 14 days, deposit-free.</p>
</div>
<div class="cta-btns">
<a class="btn btn-ink" href="#build">Start your build <span class="ar">→</span></a>
<button class="btn btn-ghost-l js-modal" data-mode="testride">Book a test ride</button>
</div>
</div>
</section>
</main>
<!-- ============ FOOTER ============ -->
<footer class="footer">
<div class="container">
<div class="f-grid">
<div class="f-brand">
<a class="logo" href="#top" style="color:var(--cream)">
<svg width="26" height="26" viewBox="0 0 32 32" aria-hidden="true"><circle cx="16" cy="21" r="8.5" fill="none" stroke="var(--cream)" stroke-width="2.4"/><circle cx="16" cy="21" r="1.8" fill="var(--cream)"/><path d="M16 9.5V4M21.5 11l3.5-4M10.5 11L7 7" stroke="var(--accent)" stroke-width="2.4" stroke-linecap="round" fill="none"/></svg>
LUMEN <em style="color:rgba(244,240,232,.5)">CYCLES</em>
</a>
<p>Custom cargo bikes, hand-built in Copenhagen since 2016. One frame at a time, and no two alike.</p>
</div>
<div class="f-col">
<h4>Visit</h4>
<ul>
<li>Hall 7, Refshalevej 167A</li>
<li>1432 København K</li>
<li>Thu–Fri 10–17 · Sat 10–14</li>
<li>Sun–Wed by appointment</li>
</ul>
</div>
<div class="f-col">
<h4>Contact</h4>
<ul>
<li><a href="mailto:hej@lumencycles.dk">hej@lumencycles.dk</a></li>
<li><a href="tel:+4531620840">+45 31 62 08 40</a></li>
<li>Reply within one working day</li>
</ul>
</div>
<div class="f-col">
<h4>Follow</h4>
<ul>
<li><a href="https://www.instagram.com/lumencycles" target="_blank" rel="noopener">Instagram</a></li>
<li><a href="https://www.facebook.com/lumencycles" target="_blank" rel="noopener">Facebook</a></li>
<li><a href="https://www.youtube.com/@lumencycles" target="_blank" rel="noopener">YouTube</a></li>
</ul>
</div>
</div>
<div class="f-bottom">
<span>© <span id="year">2025</span> LUMEN CYCLES APS · CVR 41 29 87 03</span>
<span>NO COOKIES · NO TRACKERS · JUST BIKES</span>
</div>
</div>
</footer>
<!-- ============ MODAL ============ -->
<div class="overlay" id="overlay" aria-hidden="true">
<div class="modal" role="dialog" aria-modal="true" aria-labelledby="modalTitle">
<button class="modal-x" id="modalClose" aria-label="Close"><svg width="14" height="14" viewBox="0 0 14 14"><path d="M1 1L13 13M13 1L1 13" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg></button>
<p class="eyebrow sm">Lumen Cycles</p>
<h3 id="modalTitle">Book a visit</h3>
<p class="modal-sub" id="modalSub"></p>
<pre class="modal-sum" id="modalSummary" hidden></pre>
<div id="formWrap">
<form id="reserveForm">
<div class="field"><label for="mName">Name</label><input id="mName" required autocomplete="name" placeholder="Your name"></div>
<div class="field"><label for="mEmail">Email</label><input id="mEmail" type="email" required autocomplete="email" placeholder="you@example.dk"></div>
<div class="field"><label for="mPhone">Phone <span>optional</span></label><input id="mPhone" type="tel" autocomplete="tel" placeholder="+45 …"></div>
<div class="field"><label for="mMsg">Message <span>optional</span></label><textarea id="mMsg" rows="4"></textarea></div>
<button class="btn btn-accent w100" id="sendBtn" type="submit">Send request</button>
<p class="form-note">No newsletters, no spam — just a reply from a human in the workshop.</p>
</form>
</div>
<div id="successWrap" hidden class="ok">
<svg class="ok-svg" viewBox="0 0 64 64"><circle class="ok-c" pathLength="1" cx="32" cy="32" r="28"/><path class="ok-k" pathLength="1" d="M20 33 L29 42 L45 24"/></svg>
<h4>Tak — request received.</h4>
<p>We’ll reply within one working day. If it’s urgent, call the workshop: +45 31 62 08 40.</p>
<button class="btn btn-ink" id="okClose">Close</button>
</div>
</div>
</div>
<script>
(function(){
'use strict';
var $ = function(s){ return document.querySelector(s); };
var $$ = function(s){ return Array.prototype.slice.call(document.querySelectorAll(s)); };
/* year */
$('#year').textContent = new Date().getFullYear();
/* header scroll state */
var header = $('#siteHeader');
function onScroll(){ header.classList.toggle('scrolled', window.scrollY > 10); }
window.addEventListener('scroll', onScroll, {passive:true}); onScroll();
/* mobile nav */
var navToggle = $('#navToggle'), nav = $('#siteNav');
navToggle.addEventListener('click', function(){
var open = nav.classList.toggle('open');
navToggle.classList.toggle('open', open);
navToggle.setAttribute('aria-expanded', open);
});
$$('#siteNav a, #siteNav button').forEach(function(el){
el.addEventListener('click', function(){
nav.classList.remove('open'); navToggle.classList.remove('open'); navToggle.setAttribute('aria-expanded','false');
});
});
/* reveal on scroll */
var io = new IntersectionObserver(function(entries){
entries.forEach(function(e){ if(e.isIntersecting){ e.target.classList.add('in'); io.unobserve(e.target); } });
}, {threshold:.12, rootMargin:'0px 0px -6% 0px'});
$$('.reveal').forEach(function(el){ io.observe(el); });
/* schematic hotspots */
var HS = [
'Bosch Cargo Line motor — 85 Nm tuned for loaded starts. Takes 60 kg of cargo up the Amagerbrogade bridge without a wobble.',
'180-litre birch ply box — hand-fitted and oiled. Add a lockable lid, or swap box sizes in a day if your life changes.',
'Fit session included — saddle height, reach and crank length dialled to the rider, not to a catalogue.',
'500 Wh battery under the box floor — low and centred, so a fully loaded bike still steers like a bike.',
'Direct-steer front end, low step-over — stable from walking pace, crisp and light at 25 km/h.'
];
var hsEls = $$('.hs'), capN = $('#capN'), capText = $('#capText'), cap = $('#schemCaption');
function setHS(i){
hsEls.forEach(function(el){ el.classList.toggle('active', +el.dataset.hs === i); });
capN.textContent = '0' + (i+1);
capText.textContent = HS[i];
cap.classList.remove('show'); void cap.offsetWidth; cap.classList.add('show');
}
hsEls.forEach(function(el){
var i = +el.dataset.hs;
el.addEventListener('click', function(){ setHS(i); });
el.addEventListener('keydown', function(e){ if(e.key==='Enter'||e.key===' '){ e.preventDefault(); setHS(i); } });
});
setHS(1);
/* models */
var MODELS = {
city:{idx:'01',name:'City Hauler',W:160,rear:330,cm:'90 CM',canopy:false,vol:'110 L',pay:'80 kg',wheels:'20″ front · 28″ rear',weight:'from 19.4 kg',gears:'Shimano Deore, 10-speed',brakes:'Hydraulic disc, 180 mm',price:'from €3,400',best:'Couriers, tradespeople and the big weekly shop.'},
longjohn:{idx:'02',name:'Long John',W:225,rear:395,cm:'128 CM',canopy:false,vol:'180 L',pay:'100 kg',wheels:'20″ front · 28″ rear',weight:'from 20.8 kg',gears:'Deore 10-speed or Enviolo automatic',brakes:'Hydraulic disc, 180 mm',price:'from €3,900',best:'Kindergarten runs, family weekends, one-trip shopping.'},
cruiser:{idx:'03',name:'Family Cruiser',W:260,rear:430,cm:'146 CM',canopy:true,vol:'210 L',pay:'120 kg',wheels:'20″ front · 28″ rear',weight:'from 22.1 kg',gears:'Enviolo automatic + belt drive',brakes:'Hydraulic disc, 203 mm',price:'from €4,600',best:'Two kids plus bags — the full family infrastructure.'}
};
var S = {
clip:$('#clipRect'), box:$('#boxRect'), canopy:$('#canopyPath'), main:$('#mainTube'),
dl:$('#dimLine'), dt:$('#dimTick2'), dtx:$('#dimText'),
idx:$('#spIdx'), name:$('#spName'), vol:$('#spVol'), pay:$('#spPay'), wheels:$('#spWheels'),
weight:$('#spWeight'), gears:$('#spGears'), brakes:$('#spBrakes'), price:$('#spPrice'), best:$('#spBest'),
rows:$$('.model-row'), cfgBtn:$('#cfgLink')
};
var curModel = 'longjohn';
function setModel(k){
curModel = k;
var m = MODELS[k];
S.clip.setAttribute('width', m.W);
S.box.setAttribute('width', m.W);
S.main.setAttribute('x1', m.rear - 2);
S.dl.setAttribute('x2', m.rear);
S.dt.setAttribute('x1', m.rear); S.dt.setAttribute('x2', m.rear);
S.dtx.setAttribute('x', 170 + m.W/2); S.dtx.textContent = m.cm;
if(m.canopy){ S.canopy.style.display=''; S.canopy.setAttribute('d','M174 204 Q'+(170+m.W/2)+' 96 '+(170+m.W-4)+' 204'); }
else { S.canopy.style.display='none'; }
S.idx.textContent = 'N° ' + m.idx; S.name.textContent = m.name;
S.vol.textContent = m.vol; S.pay.textContent = m.pay; S.wheels.textContent = m.wheels;
S.weight.textContent = m.weight; S.gears.textContent = m.gears; S.brakes.textContent = m.brakes;
S.price.textContent = m.price; S.best.textContent = m.best;
S.rows.forEach(function(r){ var on = r.dataset.model === k; r.classList.toggle('active', on); r.setAttribute('aria-pressed', on); });
S.cfgBtn.dataset.configModel = k;
}
S.rows.forEach(function(r){ r.addEventListener('click', function(){ setModel(r.dataset.model); }); });
setModel('longjohn');
/* configurator */
var cfgForm = $('#cfgForm'), totalEl = $('#cfgTotal'), leadEl = $('#cfgLead'), lineEl = $('#cfgLine');
function getVal(n){ return cfgForm.querySelector('input[name="'+n+'"]:checked'); }
var shown = 0, tweenRaf = null;
function fmt(v){ return '€' + Math.round(v).toLocaleString('en-US'); }
function tween(to){
if(tweenRaf) cancelAnimationFrame(tweenRaf);
var from = shown, t0 = performance.now(), D = 420;
function step(t){
var p = Math.min(1, (t - t0)/D), e = 1 - Math.pow(1-p, 3);
shown = from + (to - from) * e;
totalEl.textContent = fmt(shown);
if(p < 1) tweenRaf = requestAnimationFrame(step);
}
tweenRaf = requestAnimationFrame(step);
}
function recalc(){
var groups = ['model','drive','box','canopy','coat'].map(getVal);
var total = groups.reduce(function(s,i){ return s + (+i.dataset.price); }, 0);
$$('#cfgForm input[name="extras"]:checked').forEach(function(x){ total += (+x.dataset.price); });
lineEl.textContent = groups.map(function(i){ return i.dataset.short; }).join(' · ');
var a = 6, b = 8;
if(getVal('coat').value === 'ral'){ a += 2; b += 2; }
if(getVal('box').value === 'oak'){ a += 1; b += 1; }
if(getVal('canopy').value === 'full'){ a += 1; b += 1; }
leadEl.textContent = a + '–' + b + ' weeks';
tween(total);
}
cfgForm.addEventListener('change', recalc);
recalc();
/* "configure this model" → preselect + scroll */
$$('[data-config-model]').forEach(function(b){
b.addEventListener('click', function(){
var k = b.dataset.configModel || curModel;
var r = cfgForm.querySelector('input[name="model"][value="'+k+'"]');
if(r){ r.checked = true; recalc(); }
document.getElementById('build').scrollIntoView({behavior:'smooth'});
});
});
/* modal */
var overlay = $('#overlay'), mTitle = $('#modalTitle'), mSub = $('#modalSub'), mSum = $('#modalSummary'),
formWrap = $('#formWrap'), okWrap = $('#successWrap'), form = $('#reserveForm'),
msg = $('#mMsg'), sendBtn = $('#sendBtn'), lastFocus = null;
var MODES = {
visit:{t:'Book a workshop visit', s:'Refshalevej 167A, Hall 7 — the coffee is on. We’ll confirm a time within one working day.', sum:false},
testride:{t:'Book a test ride', s:'Test rides run Thursday to Saturday along the harbour. Bring the kids, the dog or the tools you actually carry.', sum:false},
reserve:{t:'Reserve your build slot', s:'A €200 deposit holds your place in the queue — fully refundable until we start welding.', sum:true}
};
function openModal(mode, summary){
var m = MODES[mode] || MODES.visit;
lastFocus = document.activeElement;
mTitle.textContent = m.t; mSub.textContent = m.s;
if(m.sum && summary){ mSum.textContent = summary; mSum.hidden = false; } else { mSum.hidden = true; }
formWrap.hidden = false; okWrap.hidden = true;
sendBtn.disabled = false; sendBtn.textContent = 'Send request';
form.reset();
if(m.sum && summary){ msg.value = summary + '\n\nNotes: '; }
overlay.classList.add('open'); overlay.setAttribute('aria-hidden','false');
document.body.style.overflow = 'hidden';
setTimeout(function(){ var f = form.querySelector('input'); if(f) f.focus(); }, 80);
}
function closeModal(){
overlay.classList.remove('open'); overlay.setAttribute('aria-hidden','true');
document.body.style.overflow = '';
if(lastFocus) lastFocus.focus();
}
$$('.js-modal').forEach(function(b){ b.addEventListener('click', function(){ openModal(b.dataset.mode); }); });
overlay.addEventListener('click', function(e){ if(e.target === overlay) closeModal(); });
$('#modalClose').addEventListener('click', closeModal);
document.addEventListener('keydown', function(e){ if(e.key === 'Escape' && overlay.classList.contains('open')) closeModal(); });
form.addEventListener('submit', function(e){
e.preventDefault();
if(!form.checkValidity()){ form.reportValidity(); return; }
sendBtn.disabled = true; sendBtn.textContent = 'Sending…';
setTimeout(function(){ formWrap.hidden = true; okWrap.hidden = false; }, 900);
});
$('#okClose').addEventListener('click', closeModal);
/* reserve button → summary into modal */
$('#reserveBtn').addEventListener('click', function(){
var g = ['model','drive','box','canopy','coat'].map(function(n){ return getVal(n).dataset.short; });
var extras = $$('#cfgForm input[name="extras"]:checked').map(function(x){ return x.dataset.short; });
var lines = ['Model: '+g[0], 'Drive: '+g[1], 'Box: '+g[2], 'Canopy: '+g[3], 'Finish: '+g[4]];
if(extras.length) lines.push('Extras: '+extras.join(', '));
lines.push('Estimate: '+totalEl.textContent+' ('+leadEl.textContent+')');
openModal('reserve', lines.join('\n'));
});
/* faq accordion */
$$('.faq-item').forEach(function(item){
var btn = item.querySelector('.faq-q'), panel = item.querySelector('.faq-a');
btn.addEventListener('click', function(){
var wasOpen = item.classList.contains('open');
$$('.faq-item.open').forEach(function(o){
o.classList.remove('open');
o.querySelector('.faq-a').style.maxHeight = null;
o.querySelector('.faq-q').setAttribute('aria-expanded','false');
});
if(!wasOpen){
item.classList.add('open');
panel.style.maxHeight = panel.scrollHeight + 'px';
btn.setAttribute('aria-expanded','true');
}
});
});
})();
</script>
</body>
</html>

