Run details
- Model
- openai/gpt-6.1-sol
- Route
- OpenRouter API, one user message
- Reasoning
- provider default, 323 reasoning tokens
- Limits
- 60 min · 60,000 output tokens
- Date
- 21 Oct 2026
- Time
- 4 min 58 s
- Size
- 47 kB
- Tokens
- 93 in, 15,610 out
- List price
- $0.16 ($2 in / $10 out per M)
- Paid
- $0.16
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
47 kB 670 lines Raw
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#f4f2e9">
<meta name="description" content="Lumen Cycles. Custom cargo bikes, built to order in Copenhagen. A little more room for everyday life.">
<title>Lumen Cycles — Room for everyday life.</title>
<style>
:root{--paper:#f4f2e9;--ink:#263629;--muted:#687064;--line:#d6d8cb;--orange:#e96b36;--pale:#e6e8db;--white:#fffef8;--radius:3px}
*{box-sizing:border-box}
html{scroll-behavior:smooth;scroll-padding-top:95px}
body{margin:0;background:var(--paper);color:var(--ink);font-family:Arial,Helvetica,sans-serif;-webkit-font-smoothing:antialiased}
button,input,select{font:inherit}
button,a{-webkit-tap-highlight-color:transparent}
button{cursor:pointer}
a{color:inherit}
::selection{background:var(--orange);color:var(--paper)}
:focus-visible{outline:3px solid var(--orange);outline-offset:5px}
.wrap{max-width:1440px;margin:auto;padding:0 5.2%}
.eyebrow{font-size:11px;letter-spacing:1.9px;text-transform:uppercase;font-weight:700}
.topbar{border-bottom:1px solid var(--line);background:var(--paper);position:relative;z-index:10}
.nav{height:94px;display:flex;align-items:center;justify-content:space-between;gap:30px}
.logo{text-decoration:none;display:flex;align-items:center;gap:10px}
.logo svg{width:33px;height:36px}
.wordmark{font-size:29px;font-weight:800;letter-spacing:-1.8px}
.wordmark small{display:block;font-size:8px;letter-spacing:4.1px;text-transform:uppercase;font-weight:600;margin-top:0;padding-left:2px}
.navlinks{display:flex;align-items:center;gap:34px}
.navlinks a{font-size:12px;text-decoration:none}
.navlinks a:not(.nav-cta):hover{text-decoration:underline;text-underline-offset:5px}
.nav-cta{border:1px solid var(--ink);padding:13px 18px;display:flex;gap:22px;align-items:center}
.nav-cta:hover{background:var(--ink);color:var(--paper)}
.menu-toggle{display:none;background:none;border:1px solid var(--line);padding:10px}
.hero{padding-top:31px}
.hero-top{display:flex;justify-content:space-between;align-items:center}
.status{display:flex;align-items:center;gap:8px;font-size:11px}
.status:before{content:"";height:6px;width:6px;border-radius:50%;background:#647d41}
.hero-grid{display:grid;grid-template-columns:43% 57%;align-items:center;min-height:596px}
.hero-copy{position:relative;z-index:2;padding:40px 0 54px}
h1{font-size:clamp(60px,6.8vw,98px);font-weight:500;line-height:.99;letter-spacing:-6px;margin:0 0 28px}
h1 em{font-family:Georgia,'Times New Roman',serif;font-weight:400;color:var(--orange);letter-spacing:-5px}
.hero-copy>p{font-size:15px;line-height:1.75;max-width:320px;color:var(--muted);margin-bottom:28px}
.button{display:inline-flex;align-items:center;justify-content:space-between;gap:35px;background:var(--ink);color:var(--paper);padding:17px 23px;border:1px solid var(--ink);text-decoration:none;font-size:12px;min-height:49px;transition:background .2s,transform .2s}
.button:hover{background:#40533b;transform:translateY(-2px)}
.button.orange{background:var(--orange);border-color:var(--orange);color:var(--ink)}
.button.orange:hover{background:#f28050}
.button.light{background:transparent;color:var(--ink)}
.button.light:hover{background:var(--pale)}
.hero-note{font-size:10px!important;margin:13px 0 0!important;letter-spacing:.3px}
.hero-art{position:relative;align-self:stretch;display:flex;align-items:center;margin-left:-45px}
.hero-art:before{content:"";position:absolute;width:88%;aspect-ratio:1;border-radius:50%;background:#e3e6d8;right:0;top:32px}
.bike-art{width:115%;max-width:none;position:relative;overflow:visible;margin-left:-5%;margin-top:16px}
.art-label{position:absolute;right:0;bottom:39px;text-align:right;font-size:10px;line-height:1.9}
.art-label strong{display:block;font-size:12px;font-weight:500}
.hand-note{position:absolute;right:5%;top:75px;font:italic 18px Georgia,serif;transform:rotate(-7deg)}
.hand-note svg{display:block;margin:7px 0 0 45px}
.hero-bottom{border-top:1px solid var(--line);border-bottom:1px solid var(--line);display:grid;grid-template-columns:repeat(4,1fr);padding:22px 0}
.hero-bottom>div{font-size:11px;border-right:1px solid var(--line);padding:0 26px;display:flex;align-items:center;gap:12px}
.hero-bottom>div:first-child{padding-left:0}
.hero-bottom>div:last-child{border:0}
.hero-bottom svg{width:22px;height:22px;flex-shrink:0;stroke:var(--ink);fill:none;stroke-width:1.3}
.section{padding-top:100px;padding-bottom:100px}
.section-heading{display:flex;justify-content:space-between;gap:40px;align-items:end;margin-bottom:41px}
.section-heading h2,h2{font-size:clamp(35px,4vw,55px);line-height:1.08;letter-spacing:-2px;font-weight:400;margin:17px 0 0}
.section-heading>p{max-width:290px;font-size:13px;line-height:1.8;color:var(--muted);margin:0}
.cards{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.card-visual{height:260px;background:var(--pale);overflow:hidden;position:relative}
.card-visual svg{width:100%;height:100%}
.card-number{position:absolute;top:17px;left:18px;font-size:10px;letter-spacing:1px;z-index:1}
.card h3{font-weight:400;font-size:20px;letter-spacing:-.5px;margin:22px 0 10px}
.card p{font-size:12px;color:var(--muted);line-height:1.85;margin:0;max-width:310px}
.manifesto{background:var(--ink);color:var(--paper);padding:73px 0}
.manifesto-grid{display:grid;grid-template-columns:1fr 2fr;gap:70px}
.manifesto .eyebrow{color:#c4cbb8;padding-top:7px}
.manifesto blockquote{font-size:clamp(27px,3.2vw,44px);font-weight:400;line-height:1.3;letter-spacing:-1.2px;margin:0;max-width:760px}
.manifesto blockquote em{font-family:Georgia,serif;color:#eaaa7c;font-weight:400}
.signature{font-size:11px;margin-top:25px;color:#c4cbb8}
.process-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:45px;margin-top:43px}
.step{border-top:1px solid var(--line);padding-top:20px}
.step>span{font-size:11px;color:var(--orange)}
.step h3{font-size:19px;letter-spacing:-.4px;font-weight:400;margin:32px 0 12px}
.step p{font-size:12px;line-height:1.85;color:var(--muted);max-width:300px}
.build-section{background:#e8eadf;border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.build-grid{display:grid;grid-template-columns:1fr 1fr;gap:8%;align-items:start}
.build-intro>p{font-size:13px;line-height:1.9;color:var(--muted);max-width:365px;margin:24px 0 30px}
.build-preview{height:220px;position:relative;margin:20px 0}
.build-preview svg{width:100%;height:100%;overflow:visible}
.build-details{display:grid;grid-template-columns:1fr 1fr;gap:15px;font-size:11px;padding-top:20px;border-top:1px solid #c8cebd}
.build-details span{color:var(--muted);display:block;font-size:10px;margin-bottom:7px}
.configurator{padding:29px;background:var(--paper);border:1px solid #d0d5c4}
.config-top{display:flex;justify-content:space-between;align-items:center;border-bottom:1px solid var(--line);padding-bottom:20px;margin-bottom:25px}
.config-top strong{font-size:19px;font-weight:400;letter-spacing:-.5px}
.config-top span{font-size:10px;color:var(--muted)}
fieldset{border:0;padding:0;margin:0 0 25px;min-width:0}
legend{font-size:11px;font-weight:600;margin-bottom:12px}
.option-grid{display:grid;grid-template-columns:1fr 1fr;gap:9px}
.option{position:relative;cursor:pointer}
.option input{position:absolute;opacity:0;inset:0;width:100%;height:100%;margin:0;cursor:pointer}
.option>span{padding:14px 12px;display:block;border:1px solid var(--line);font-size:11px;min-height:62px}
.option small{display:block;color:var(--muted);font-size:10px;margin-top:7px}
.option input:checked+span{border-color:var(--ink);box-shadow:inset 0 0 0 1px var(--ink);background:#e8eadf}
.option input:focus-visible+span{outline:3px solid var(--orange);outline-offset:3px}
.color-options{display:flex;align-items:center;gap:11px}
.color-option{position:relative;display:block;height:30px;width:30px;cursor:pointer}
.color-option input{position:absolute;opacity:0;inset:0;margin:0;cursor:pointer;width:100%;height:100%}
.color-option span{display:block;width:24px;height:24px;border-radius:50%;background:var(--swatch);margin:3px}
.color-option input:checked+span{outline:1px solid var(--ink);outline-offset:3px}
.color-option input:focus-visible+span{outline:3px solid var(--orange);outline-offset:3px}
.color-name{font-size:10px;color:var(--muted);margin-left:6px}
.total-row{border-top:1px solid var(--line);padding:22px 0;display:flex;justify-content:space-between;align-items:center;gap:20px}
.total-row span{font-size:11px;line-height:1.7}
.total-row small{display:block;color:var(--muted);font-size:9px}
.total-row output{font-size:30px;letter-spacing:-1px;white-space:nowrap}
.configurator .button{width:100%}
.config-footnote{font-size:9px;text-align:center;color:var(--muted);line-height:1.7;margin:12px 0 0}
.saved-message{font-size:11px;color:var(--ink);line-height:1.7;margin:13px 0 0}
.visit-grid{display:grid;grid-template-columns:1.05fr 1fr;gap:8%;align-items:center}
.workshop{position:relative;aspect-ratio:1.18;background:#d9dbcf;overflow:hidden}
.workshop>svg{width:100%;height:100%}
.workshop-tag{position:absolute;left:22px;bottom:22px;background:var(--paper);padding:12px 16px;font-size:10px;letter-spacing:.5px}
.visit-copy>p{font-size:13px;line-height:1.9;color:var(--muted);max-width:350px;margin:25px 0}
.visit-meta{border-top:1px solid var(--line);border-bottom:1px solid var(--line);padding:18px 0;display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-bottom:25px;font-size:11px;line-height:1.8}
.visit-meta strong{display:block;font-weight:500;margin-bottom:7px}
.visit-meta span{color:var(--muted)}
.faq{padding-top:0;display:grid;grid-template-columns:1fr 1.5fr;gap:10%}
.faq h2{font-size:39px}
details{border-bottom:1px solid var(--line)}
details:first-child{border-top:1px solid var(--line)}
summary{padding:21px 28px 21px 0;cursor:pointer;font-size:13px;list-style:none;position:relative}
summary::-webkit-details-marker{display:none}
summary:after{content:"+";position:absolute;right:4px;top:18px;font-size:21px;font-weight:300}
details[open] summary:after{content:"−"}
details p{font-size:12px;line-height:1.9;color:var(--muted);padding:0 30px 20px 0;margin:0}
.footer{background:var(--ink);color:var(--paper);padding:48px 0 23px}
.footer-top{display:flex;justify-content:space-between;align-items:center;padding-bottom:43px;gap:30px}
.footer-line{font-size:25px;letter-spacing:-.8px;font-weight:400}
.footer-bottom{border-top:1px solid #51604d;padding-top:22px;display:flex;justify-content:space-between;gap:20px;color:#b9c2ae;font-size:9px}
.footer-bottom a{text-decoration:none}
dialog{background:var(--paper);color:var(--ink);border:1px solid var(--ink);padding:36px;max-width:470px;width:calc(100% - 32px)}
dialog::backdrop{background:#18251899;backdrop-filter:blur(4px)}
.dialog-close{position:absolute;right:13px;top:10px;border:0;background:none;font-size:25px;color:var(--ink)}
dialog h2{font-size:35px;padding-right:10px}
dialog p{font-size:12px;line-height:1.8;color:var(--muted)}
dialog label{display:block;font-size:11px;margin:22px 0 9px}
dialog input,dialog select{display:block;width:100%;background:var(--white);border:1px solid var(--line);padding:13px;color:var(--ink);border-radius:0}
dialog .button{width:100%;margin-top:23px}
.dialog-result{padding-top:10px}
@media(min-width:1440px){.hero-grid{min-height:650px}}
@media(max-width:1000px){
h1{font-size:73px;letter-spacing:-4.5px}.hero-grid{grid-template-columns:45% 55%;min-height:540px}
.hero-art:before{top:75px}.hand-note{top:80px;right:0;font-size:15px}.hero-bottom>div{padding:0 13px;font-size:10px}
.card-visual{height:220px}.build-grid{gap:4%}.configurator{padding:22px}.hero-copy>p{max-width:280px}
}
@media(max-width:720px){
.wrap{padding-left:6%;padding-right:6%}.nav{height:76px}.wordmark{font-size:26px}.navlinks{gap:18px}
.navlinks a:not(.nav-cta){display:none}.nav-cta{font-size:11px!important;padding:11px 13px;gap:16px}
.hero{padding-top:24px}.hero-top>.eyebrow{font-size:9px;letter-spacing:1.3px}.status{font-size:9px}
.hero-grid{display:flex;flex-direction:column;min-height:0;align-items:stretch}
.hero-copy{padding:47px 0 5px}h1{font-size:clamp(63px,13vw,90px);line-height:.99;letter-spacing:-4px;margin-bottom:23px}
.hero-copy>p{max-width:330px;font-size:14px;margin-bottom:24px}h1 em{letter-spacing:-4px}
.hero-art{min-height:340px;margin:0 -2% 10px;align-self:auto}.hero-art:before{width:77%;top:0;right:5%}
.bike-art{width:106%;margin:0 0 0 -3%}.hand-note{top:16px;right:6%;font-size:16px}
.art-label{bottom:5px;right:4%;font-size:9px}.art-label strong{font-size:11px}
.hero-bottom{grid-template-columns:1fr 1fr;row-gap:22px;padding:22px 0}
.hero-bottom>div{padding:0 10px!important;font-size:10px}.hero-bottom>div:nth-child(2){border:0}
.hero-bottom>div:nth-child(odd){padding-left:0!important}
.section{padding-top:65px;padding-bottom:65px}.section-heading{display:block;margin-bottom:30px}
.section-heading>p{margin-top:22px;max-width:340px}.section-heading h2,h2{font-size:39px}
.cards{grid-template-columns:1fr;gap:32px}.card-visual{height:280px}.card p{max-width:100%}.card h3{margin-top:17px}
.manifesto{padding:48px 0}.manifesto-grid{grid-template-columns:1fr;gap:27px}.manifesto blockquote{font-size:30px}
.process-grid{grid-template-columns:1fr;gap:24px;margin-top:32px}.step h3{margin-top:18px}.step p{max-width:100%}
.build-grid{grid-template-columns:1fr;gap:32px}.build-intro>p{max-width:100%}.build-preview{height:210px}
.build-details{padding-bottom:5px}.configurator{padding:23px}.visit-grid{grid-template-columns:1fr;gap:35px}
.workshop{aspect-ratio:1.22}.visit-copy>p{max-width:100%}
.faq{grid-template-columns:1fr;gap:30px;padding-top:0}.faq h2{font-size:36px}
.footer-top{align-items:start;flex-direction:column;gap:25px;padding-bottom:30px}.footer-line{font-size:25px}
.footer-bottom{flex-wrap:wrap;line-height:1.7;font-size:9px}
}
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}*{transition:none!important}}
</style>
</head>
<body>
<header class="topbar">
<div class="wrap nav">
<a class="logo" href="#" aria-label="Lumen Cycles home">
<svg viewBox="0 0 34 38" fill="none" aria-hidden="true"><path d="M5 6v25h23M13 6v17h15M21 6v9h7" stroke="currentColor" stroke-width="3.5"/></svg>
<span class="wordmark">lumen<small>cycles / copenhagen</small></span>
</a>
<nav class="navlinks" aria-label="Main navigation">
<a href="#bike">The bike</a>
<a href="#process">Our approach</a>
<a href="#workshop">The workshop</a>
<a class="nav-cta" href="#build">Build yours <span aria-hidden="true">↗</span></a>
</nav>
</div>
</header>
<main>
<section class="hero wrap" aria-labelledby="hero-title">
<div class="hero-top">
<span class="eyebrow">Built here. Ridden everywhere.</span>
<span class="status">Made to order in Copenhagen</span>
</div>
<div class="hero-grid">
<div class="hero-copy">
<h1 id="hero-title">Room for<br>everyday<br><em>life.</em></h1>
<p>The school run. The big shop. The long way home. A custom cargo bike for everything you carry.</p>
<a class="button" href="#build">Find your everyday <span aria-hidden="true">↗</span></a>
<p class="hero-note">Built to order from €3,990 · Never off the shelf.</p>
</div>
<div class="hero-art">
<span class="hand-note">A little more possibility.
<svg width="60" height="46" viewBox="0 0 60 46" fill="none" aria-hidden="true"><path d="M6 3C40 0 52 16 39 38m-8-10 8 12 12-8" stroke="currentColor" stroke-width="1.2"/></svg>
</span>
<svg class="bike-art" viewBox="0 0 820 520" role="img" aria-label="Forest green Lumen cargo bike with a birch passenger box, brown saddle and cream-wall tires">
<defs>
<linearGradient id="boxFront" x1="0" y1="0" x2="1" y2=".8"><stop stop-color="#c69a68"/><stop offset="1" stop-color="#b78351"/></linearGradient>
<linearGradient id="boxSide" x1="0" y1="0" x2="1" y2="1"><stop stop-color="#e7c69c"/><stop offset="1" stop-color="#cfaa7e"/></linearGradient>
<linearGradient id="metal" x1="0" x2="1"><stop stop-color="#d5d7cb"/><stop offset=".5" stop-color="#8b9386"/><stop offset="1" stop-color="#e3e5da"/></linearGradient>
<filter id="shadow"><feGaussianBlur stdDeviation="7"/></filter>
<g id="rearWheel">
<circle r="79" fill="#333a30"/><circle r="72" fill="#c8bc9d"/><circle r="66" fill="#e4e6da"/>
<g stroke="#9b9f91" stroke-width=".9">
<path d="M0-66V66M-66 0H66M-46-46 46 46M-46 46 46-46M-25-61 25 61M-61-25 61 25M-61 25 61-25M-25 61 25-61"/>
<path d="m-13-65 26 130m-78-52 130-26m-101-42 72 110m-91-19 110-72m-116 23 122 20m-51-71-20 122"/>
</g>
<circle r="64" fill="none" stroke="#dddcd0" stroke-width="2"/>
<circle r="9" fill="#6c7467"/><circle r="4" fill="#c2c6ba"/>
</g>
<g id="frontWheel">
<circle r="64" fill="#333a30"/><circle r="57" fill="#c8bc9d"/><circle r="51" fill="#e4e6da"/>
<g stroke="#969d8e" stroke-width=".8"><path d="M0-51V51M-51 0H51M-36-36 36 36M-36 36 36-36M-19-47 38 94M-47-19 94 38M-47 19 94-38M-19 47 38-94"/></g>
<circle r="50" fill="none" stroke="#deded2" stroke-width="2"/><circle r="6" fill="#b5baac"/>
</g>
</defs>
<ellipse cx="426" cy="424" rx="320" ry="12" fill="#576048" opacity=".17" filter="url(#shadow)"/>
<!-- wheels and mudguards -->
<use href="#rearWheel" transform="translate(173 335)"/>
<use href="#frontWheel" transform="translate(663 350)"/>
<path d="M88 335a85 85 0 0 1 170-2M596 337a68 68 0 0 1 132 0" fill="none" stroke="#48543e" stroke-width="6" stroke-linecap="round"/>
<path d="m110 280 21 70m98-69-19 68m405-54 33 58m57-51-34 49" stroke="#79816f" fill="none" stroke-width="1.5"/>
<!-- rear rack -->
<g stroke="#394b34" stroke-width="4" fill="none" stroke-linejoin="round">
<path d="M90 250h137l-14-12H98zM104 251l66 85m43-86-39 86"/>
</g>
<!-- frame -->
<g fill="none" stroke="#3d563b" stroke-linejoin="round" stroke-linecap="round">
<path d="m173 335 98-127 42 130z" stroke-width="10"/>
<path d="m271 208 95 46-53 84 282 13 53-32" stroke-width="13"/>
<path d="m282 226 67 42" stroke-width="8"/>
<path d="m313 338 45-150" stroke-width="10"/>
<path d="m602 329 61 21-26-106" stroke-width="8"/>
</g>
<!-- chain drive -->
<path d="m174 325 134-5a19 19 0 0 1 0 38l-134-13a10 10 0 0 1 0-20Z" fill="#586449" stroke="#a7ab97" stroke-width="2"/>
<circle cx="310" cy="339" r="20" fill="#394831"/><circle cx="310" cy="339" r="13" fill="none" stroke="#8e9683" stroke-width="2"/>
<path d="m310 339 24 16" stroke="#a5ac9c" stroke-width="5"/><path d="m326 355 22 1" stroke="#303b2c" stroke-width="6"/>
<!-- saddle and handlebars -->
<path d="m270 209-10-44" stroke="url(#metal)" stroke-width="7"/>
<path d="M235 156c9-4 30-3 43 1l9 8c-7 8-26 6-47 3-9-1-13-9-5-12Z" fill="#79543b"/>
<path d="m358 189 9-51 13-11" fill="none" stroke="url(#metal)" stroke-width="7"/>
<path d="m348 127 40-4 8 7" fill="none" stroke="#35402e" stroke-width="7" stroke-linecap="round"/>
<path d="M352 134c-11 38 26 53 8 99M389 131c20 35-12 83-27 115" fill="none" stroke="#4c5547" stroke-width="1.5"/>
<!-- cargo box -->
<path d="m406 239 207-17 56 37-208 30z" fill="#876744"/>
<path d="m414 244 194-15 47 30-192 23z" fill="#665d42"/>
<path d="m406 239 55 50 16 57-58-47z" fill="url(#boxFront)" stroke="#a57c4f" stroke-width="1"/>
<path d="m461 289 208-30-25 79-167 8z" fill="url(#boxSide)" stroke="#b18c61" stroke-width="1"/>
<path d="m406 239 55 50 208-30" fill="none" stroke="#efd4ae" stroke-width="5" stroke-linejoin="round"/>
<path d="m481 295 160-23m-158 32 154-23m-151 32 148-23m-145 32 142-23m-138 32 133-23" stroke="#a6794b" opacity=".15" fill="none"/>
<g fill="#9b7a54"><circle cx="475" cy="302" r="2"/><circle cx="481" cy="334" r="2"/><circle cx="652" cy="275" r="2"/><circle cx="636" cy="327" r="2"/></g>
<text x="539" y="320" font-family="Arial,sans-serif" font-size="13" font-weight="700" letter-spacing="3" fill="#6b6247" transform="rotate(-8 539 320)">LUMEN</text>
<!-- cargo: groceries and a small plant -->
<path d="m484 263-3-47 46-6 10 45" fill="#b8aa85"/>
<path d="M490 217c-5-28 27-32 27-5" stroke="#948b6a" stroke-width="3" fill="none"/>
<path d="m502 216-8-44c-1-9 8-12 12-2l10 44" fill="#d6af72"/>
<path d="m499 180 7-2m-5 11 8-2m-6 11 8-2" stroke="#b58d58" stroke-width="2"/>
<path d="m554 259-2-29 28-3-3 29" fill="#ad795b"/>
<path d="m564 230 2-47m0 32c-28 0-29-19-25-23 18-2 25 11 25 23m0-13c25-2 29-18 24-23-17 0-23 13-24 23m0-9c-15-8-18-25-10-29 15 8 10 29 10 29" stroke="#536b40" stroke-width="2" fill="#6e8052"/>
<!-- front light and stand -->
<path d="m638 278 16-1" stroke="#48503e" stroke-width="3"/>
<rect x="648" y="268" width="13" height="13" rx="4" fill="#343d30"/><path d="M660 271v7" stroke="#e9d9a7" stroke-width="3"/>
<path d="m389 343-10 47m27-46 17 46m-52 0h15m30 0h14" stroke="#536047" stroke-width="4" fill="none" stroke-linecap="round"/>
<path d="m240 266 32-42" stroke="#c7cfb9" stroke-width="1" opacity=".4"/>
<text x="280" y="251" font-family="Arial,sans-serif" font-size="7" letter-spacing="2" fill="#d5dbca" transform="rotate(26 280 251)">LUMEN</text>
</svg>
<div class="art-label"><strong>The Lumen No. 01</strong>Birch box / Forest frame / Endless errands</div>
</div>
</div>
<div class="hero-bottom">
<div><svg viewBox="0 0 24 24" aria-hidden="true"><path d="m4 17 7-12 9 12H4Zm3 0v4m10-4v4M7 10l5 4 6-5"/></svg>Built by hand in Copenhagen</div>
<div><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3 4 6v6c0 5 8 9 8 9s8-4 8-9V6zM8 11l3 3 5-6"/></svg>5-year frame warranty</div>
<div><svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><path d="M12 6v6l4 2"/></svg>Made to order in 8–12 weeks</div>
<div><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 16 16 4l4 4L8 20H4zM13 7l4 4M4 4l4 4m8 8 4 4"/></svg>Standard parts. Long-term care.</div>
</div>
</section>
<section class="section wrap" id="bike">
<div class="section-heading">
<div><span class="eyebrow">Meet the Lumen No. 01</span><h2>Less car.<br>More Copenhagen.</h2></div>
<p>Not a second car on two wheels. A better way to move through your day — with room for the people and things that matter.</p>
</div>
<div class="cards">
<article class="card">
<div class="card-visual">
<span class="card-number">01 / CARRY MORE</span>
<svg viewBox="0 0 400 280" role="img" aria-label="Detail of the birch cargo box and its curved handhold">
<rect width="400" height="280" fill="#e3dfcf"/>
<path d="m37 119 211-36 121 64-216 49z" fill="#6b654c"/>
<path d="m43 120 110 76 216-49-34 137H69z" fill="#d1ae80"/>
<path d="m43 120 110 76 18 88H69z" fill="#b78856"/>
<path d="m153 196 216-49" stroke="#f0d7b4" stroke-width="7"/>
<path d="m43 120 110 76" stroke="#d8b48a" stroke-width="6"/>
<path d="m185 215 100-21" stroke="#b38a5d" stroke-width="1" opacity=".4"/>
<path d="m189 228 142-30m-139 41 139-30m-136 41 132-28m-128 39 124-27" stroke="#ab7b4e" opacity=".15"/>
<path d="m267 187 41-9" stroke="#88704e" stroke-width="9" stroke-linecap="round"/>
<path d="m267 185 41-9" stroke="#5b5943" stroke-width="5" stroke-linecap="round"/>
<circle cx="174" cy="211" r="2" fill="#8f734d"/><circle cx="348" cy="169" r="2" fill="#8f734d"/>
<text x="209" y="266" transform="rotate(-12 209 266)" fill="#6d654c" font-size="18" font-family="Arial" font-weight="bold" letter-spacing="4">LUMEN</text>
</svg>
</div>
<h3>Big on the little things.</h3>
<p>A weather-sealed birch box with space for the weekly shop, precious passengers, or one very lucky dog. Up to 80 kg of cargo.</p>
</article>
<article class="card">
<div class="card-visual">
<span class="card-number">02 / FEEL AT HOME</span>
<svg viewBox="0 0 400 280" role="img" aria-label="Detail of the comfortable brown saddle and green steel frame">
<rect width="400" height="280" fill="#dce1d3"/>
<path d="m144 305 58-159" stroke="#4c6144" stroke-width="23"/>
<path d="m200 155-15-58" stroke="#9da595" stroke-width="13"/>
<path d="m158 207 155 78m-113-80 90-74" fill="none" stroke="#40563b" stroke-width="19" stroke-linecap="round"/>
<path d="M115 81c20-10 78-10 112 0l38 17c9 9-13 18-39 18-36 0-80-5-109-12-15-3-16-17-2-23Z" fill="#77543b"/>
<path d="M114 83c41-9 84-6 118 4" fill="none" stroke="#a17a55" stroke-width="2"/>
<path d="m142 110 37 17 42-10" fill="none" stroke="#5a6351" stroke-width="4"/>
<circle cx="121" cy="94" r="2" fill="#c3b496"/><circle cx="248" cy="101" r="2" fill="#c3b496"/>
<path d="m298 68-10 68" stroke="#a1ab97" stroke-width="10"/>
<path d="m276 63 51 4" stroke="#4b4e39" stroke-width="14" stroke-linecap="round"/>
<path d="M319 74c28 39-36 84-11 132" stroke="#5b6350" stroke-width="2" fill="none"/>
<path d="m175 227 52 27" stroke="#819074" stroke-width="1.5"/>
</svg>
</div>
<h3>A bike, not a learning curve.</h3>
<p>A low centre of gravity, upright riding position and a frame sized to you. Stable when loaded. A pleasure when it isn’t.</p>
</article>
<article class="card">
<div class="card-visual">
<span class="card-number">03 / KEEP GOING</span>
<svg viewBox="0 0 400 280" role="img" aria-label="Detail of serviceable steel frame, chain and crank">
<rect width="400" height="280" fill="#e2e3d9"/>
<circle cx="28" cy="152" r="115" fill="none" stroke="#343e31" stroke-width="19"/>
<circle cx="28" cy="152" r="102" fill="none" stroke="#c3b99a" stroke-width="8"/>
<g stroke="#a5ab9b" stroke-width="1"><path d="M28 50v204M-74 152h204M-44 80l144 144m-144 0L100 80M-10 58l76 188M-66 114l188 76M-66 190l188-76M-10 246 66 58"/></g>
<path d="m27 153 158-178 47 191-205-13m205 13L370-7m-138 173 193 17" stroke="#40583c" stroke-width="16" fill="none" stroke-linejoin="round"/>
<path d="m29 142 194-3a29 29 0 0 1 0 58L29 164a11 11 0 0 1 0-22Z" fill="#59684e" stroke="#9da88f" stroke-width="2"/>
<circle cx="228" cy="168" r="26" fill="#303f2e"/><circle cx="228" cy="168" r="19" stroke="#7e8c72" stroke-width="2" fill="none"/>
<path d="m228 168 43 46" stroke="#a9b29e" stroke-width="8"/><path d="m256 216 43-1" stroke="#35432f" stroke-width="10" stroke-linecap="round"/>
<path d="m331 136 40 50m-26-52 42 54" stroke="#8e9a81" stroke-width="3"/>
<text x="187" y="62" fill="#cdd5c0" font-size="9" font-family="Arial" letter-spacing="3" transform="rotate(76 187 62)">LUMEN</text>
</svg>
</div>
<h3>Built for years, not seasons.</h3>
<p>Repairable steel. Familiar components. No proprietary surprises. Thoughtfully put together so any good bike shop can keep you rolling.</p>
</article>
</div>
</section>
<section class="manifesto">
<div class="wrap manifesto-grid">
<span class="eyebrow">A smaller kind of freedom</span>
<div>
<blockquote>We believe the best bike is the one that becomes part of your life. Not too precious. Not too complicated. <em>Just yours.</em></blockquote>
<div class="signature">The thinking behind every Lumen.</div>
</div>
</div>
</section>
<section class="section wrap" id="process">
<div class="section-heading">
<div><span class="eyebrow">From our hands to your handlebars</span><h2>A good fit starts<br>with a conversation.</h2></div>
<p>We’re a workshop, not a production line. Every build starts with how you live, what you carry and where you want to go.</p>
</div>
<div class="process-grid">
<article class="step"><span>01 — LET’S TALK</span><h3>You bring the everyday.</h3><p>Tell us about your routes, your riders and that awkward thing you always need to carry. We’ll find your frame size and the right setup.</p></article>
<article class="step"><span>02 — WE GET TO WORK</span><h3>One bike. Your name on it.</h3><p>Approve your detailed quote, choose your finish and leave a 30% deposit. We build, assemble and check your bike over 8–12 weeks.</p></article>
<article class="step"><span>03 — MAKE IT YOURS</span><h3>The beginning of a long ride.</h3><p>Collect at the workshop for a final fitting and a proper handover. Your first adjustment service is on us, within the first three months.</p></article>
</div>
</section>
<section class="section build-section" id="build">
<div class="wrap build-grid">
<div class="build-intro">
<span class="eyebrow">Your Lumen starts here</span>
<h2>A few choices.<br>A lot of possibility.</h2>
<p>Start with the essentials. We’ll work out the finer details together. Your estimate includes assembly, fitting and Danish VAT.</p>
<div class="build-preview">
<svg viewBox="0 0 600 270" role="img" aria-label="Preview of your selected cargo bike frame colour">
<ellipse cx="306" cy="248" rx="253" ry="6" fill="#cbd0bf"/>
<g fill="none">
<circle cx="103" cy="184" r="58" stroke="#333d30" stroke-width="10"/><circle cx="103" cy="184" r="51" stroke="#bcb391" stroke-width="4"/>
<circle cx="498" cy="194" r="47" stroke="#333d30" stroke-width="9"/><circle cx="498" cy="194" r="40" stroke="#bcb391" stroke-width="3"/>
<g stroke="#a2aa95" stroke-width="1"><path d="M103 132v104M51 184h104m-89-37 74 74m-74 0 74-74M498 153v82m-41-41h82m-70-29 58 58m-58 0 58-58"/></g>
</g>
<g id="preview-frame" stroke="#40563b" stroke-width="9" fill="none" stroke-linejoin="round" stroke-linecap="round">
<path d="m103 184 76-99 32 101zM179 85l75 35-43 66 236 8 35-19M211 186l37-119m210 107 40 20-16-78"/>
<path d="M44 179a60 60 0 0 1 118-8M451 181a49 49 0 0 1 92 0" stroke-width="4"/>
</g>
<path d="m107 181 102-9a14 14 0 1 1 0 28l-102-12z" fill="#59644c" stroke="#969f89"/>
<circle cx="211" cy="186" r="13" fill="#3b4733"/><path d="m211 186 21 16" stroke="#9aa58e" stroke-width="4"/><path d="M226 203h20" stroke="#37432f" stroke-width="5"/>
<path d="m179 85-8-33m77 15 8-36" stroke="#939f87" stroke-width="5"/>
<path d="M148 46c13-5 31-3 43 4 2 8-35 6-43 1Z" fill="#80583c"/>
<path d="m240 29 31-3" stroke="#35422f" stroke-width="6" stroke-linecap="round"/>
<path d="m286 119 161-15 52 27-165 29z" fill="#776b4b"/>
<path d="m286 119 48 41 12 37-51-30z" fill="#bb9162"/>
<path d="m334 160 165-29-18 57-135 9z" fill="#d6b388"/>
<path d="m286 119 48 41 165-29" fill="none" stroke="#edcfa6" stroke-width="4"/>
<text x="390" y="179" fill="#736345" font-size="10" font-family="Arial" letter-spacing="2" transform="rotate(-9 390 179)">LUMEN</text>
<path d="m273 192-8 40m26-40 9 40" fill="none" stroke="#5e6a51" stroke-width="3"/>
<g id="preview-motor" hidden><rect x="224" y="132" width="36" height="17" rx="5" fill="#303d2b"/><path d="m239 136-5 5h7l-5 5" fill="none" stroke="#c8cfba" stroke-width="1.5"/></g>
</svg>
</div>
<div class="build-details">
<div><span>Load capacity</span>80 kg in the box</div>
<div><span>Complete bike weight</span>From 32 kg</div>
<div><span>Frame</span>Repairable chromoly steel</div>
<div><span>Brakes</span>Hydraulic disc, front & rear</div>
</div>
</div>
<form class="configurator" id="build-form">
<div class="config-top"><strong>The No. 01, your way.</strong><span>01 / CONFIGURE</span></div>
<fieldset>
<legend>01. Choose your drive</legend>
<div class="option-grid">
<label class="option"><input type="radio" name="drive" value="classic" checked><span>Just you & the pedals<small>Human-powered · Included</small></span></label>
<label class="option"><input type="radio" name="drive" value="electric"><span>A little extra help<small>250 W electric assist · +€1,100</small></span></label>
</div>
</fieldset>
<fieldset>
<legend>02. Make room for</legend>
<div class="option-grid">
<label class="option"><input type="radio" name="cargo" value="goods" checked><span>The everyday haul<small>Open birch box · Included</small></span></label>
<label class="option"><input type="radio" name="cargo" value="family"><span>Your small people<small>Bench + two harnesses · +€240</small></span></label>
</div>
</fieldset>
<fieldset>
<legend>03. Find your colour</legend>
<div class="color-options">
<label class="color-option" style="--swatch:#40563b"><input type="radio" name="color" value="Forest" checked aria-label="Forest green"><span></span></label>
<label class="color-option" style="--swatch:#b7613f"><input type="radio" name="color" value="Terracotta" aria-label="Terracotta"><span></span></label>
<label class="color-option" style="--swatch:#d1c6a8"><input type="radio" name="color" value="Oat" aria-label="Oat"><span></span></label>
<span class="color-name" id="color-name">Forest — a Copenhagen classic</span>
</div>
</fieldset>
<div class="total-row">
<span>Your build estimate<small>Including 25% Danish VAT · Collection in Copenhagen</small></span>
<output id="total" aria-live="polite">€3,990</output>
</div>
<button type="submit" class="button">Save my build sheet <span aria-hidden="true">↓</span></button>
<p class="config-footnote">A starting point, not a commitment. No payment or email required.<br>Delivery and custom extras are quoted separately.</p>
<p id="save-message" class="saved-message" role="status" hidden></p>
</form>
</div>
</section>
<section class="section wrap" id="workshop">
<div class="visit-grid">
<div class="workshop">
<svg viewBox="0 0 600 510" role="img" aria-label="Illustration of the Lumen workshop: green doors, a workbench and a bike hanging ready for assembly">
<defs><pattern id="bricks" width="90" height="40" patternUnits="userSpaceOnUse"><path d="M0 0h90v40H0zM45 0v20M0 20h90M0 20v20M90 20v20" fill="none" stroke="#b3ac96" stroke-width="1" opacity=".4"/></pattern></defs>
<rect width="600" height="510" fill="#c8c3b0"/><rect width="600" height="440" fill="url(#bricks)"/>
<rect x="46" y="61" width="243" height="377" fill="#4c5a44"/><rect x="58" y="74" width="219" height="351" fill="#364b37"/>
<rect x="72" y="89" width="89" height="162" fill="#a6b1a0"/><rect x="174" y="89" width="89" height="162" fill="#9ca996"/>
<path d="M116 89v162m102-162v162M72 170h191" stroke="#526449" stroke-width="7"/>
<path d="m72 89 89 162m13-162 89 162" stroke="#c4cabc" stroke-width="17" opacity=".17"/>
<rect x="72" y="271" width="191" height="137" fill="#3d533c"/><path d="M165 270v137" stroke="#2f432f" stroke-width="5"/>
<rect x="245" y="262" width="5" height="28" rx="2" fill="#c4b18a"/>
<rect x="326" y="99" width="230" height="181" fill="#a5a892"/><rect x="337" y="110" width="208" height="159" fill="#6c795f"/>
<g stroke="#c1c4ac" stroke-width="3"><path d="M373 110v159m86-159v159m50-159v159M337 186h208"/></g>
<path d="M348 336h211v15H348z" fill="#9e7751"/><path d="m365 351-8 88m185-88 8 88" stroke="#45513c" stroke-width="9"/>
<path d="M375 352h156v57H375z" fill="#69745b"/><path d="M378 380h151" stroke="#4c5942"/><path d="M437 366h28m-28 28h28" stroke="#b6b79d" stroke-width="3"/>
<path d="M391 314v22h76v-22" fill="#b19870"/><path d="m405 313 2-39m18 39-5-29m25 29 8-37" stroke="#4d5842" stroke-width="5"/>
<path d="M490 330v-22l12-20 13 20v22" fill="#b1b69f"/>
<rect x="490" y="310" width="25" height="10" fill="#e8dcb7"/>
<path d="M0 440h600v70H0z" fill="#a9ad97"/><path d="M0 477h600M74 440l-25 70m183-70-5 70m175-70 12 70" stroke="#919a83" opacity=".6"/>
<g fill="none" stroke="#47553e" stroke-width="5"><circle cx="138" cy="408" r="49"/><circle cx="284" cy="408" r="49"/><path d="m138 408 48-74 33 74zm48-74 66 1 32 73m-65 0 33-73 3-28m-69 27-6-22"/></g>
<path d="M164 309h34m47-5h28" stroke="#74573a" stroke-width="7" stroke-linecap="round"/>
<rect x="71" y="28" width="192" height="33" fill="#e6dfcc"/>
<text x="104" y="51" font-family="Arial" font-size="19" font-weight="bold" letter-spacing="6" fill="#3c5038">LUMEN</text>
<path d="M315 0v53" stroke="#69745b" stroke-width="2"/><path d="m292 69 10-17h26l10 17z" fill="#43543c"/>
<path d="m304 70-43 86h108l-43-86" fill="#eee0b2" opacity=".09"/>
<path d="M28 406h32l-5 35H34z" fill="#a87c57"/><path d="M44 408v-47m0 21c-18 0-28-15-22-21 17 0 22 21 22 21m0-10c18-1 23-17 16-21-14 5-16 21-16 21" fill="#63744b" stroke="#63744b" stroke-width="2"/>
</svg>
<span class="workshop-tag">55°40′ N 12°33′ E / COPENHAGEN, DK</span>
</div>
<div class="visit-copy">
<span class="eyebrow">Come by. Take the long way.</span>
<h2>Real people.<br>A real workshop.</h2>
<p>There’s only so much a website can tell you. Meet the people behind your bike, see the details up close and find out how a loaded cargo bike actually feels.</p>
<div class="visit-meta">
<div><strong>Copenhagen, Denmark</strong><span>Workshop visits by appointment.<br>Location shared with your visit details.</span></div>
<div><strong>Make yourself at home</strong><span>45-minute workshop visit.<br>A conversation, a fitting, a first ride.</span></div>
</div>
<button type="button" class="button light" id="visit-button">Plan a workshop visit <span aria-hidden="true">↗</span></button>
</div>
</div>
</section>
<section class="section wrap faq" aria-labelledby="faq-title">
<div><span class="eyebrow">A few useful things</span><h2 id="faq-title">Before you<br>get rolling.</h2></div>
<div>
<details><summary>What’s included in the starting price?</summary><p>The €3,990 starting price includes the complete human-powered No. 01, an open birch cargo box, hydraulic disc brakes, mudguards, lights, a stand, assembly and a personal fitting at collection. Danish VAT is included. Electric assist, passenger seating, delivery and bespoke accessories cost extra.</p></details>
<details><summary>How does ordering and payment work?</summary><p>Your saved build is an estimate, not an order. After a fitting and a conversation, we provide a written specification and final quote. A 30% deposit confirms your production slot; the balance is due before collection. Changes, cancellation terms and your confirmed timing are agreed in writing before payment.</p></details>
<details><summary>Can I carry children?</summary><p>The optional family setup includes a bench and two harnesses. Passenger suitability depends on each child’s age, size and ability to sit unsupported; we discuss this during your fitting. Never carry passengers in an unequipped cargo box. The box load limit is 80 kg, including seats and accessories.</p></details>
<details><summary>What happens if something needs fixing?</summary><p>The frame is covered by a five-year warranty against manufacturing defects for the original owner. Wear, accidental damage and corrosion from neglect are excluded. Components carry their respective manufacturer warranties. We use standard service parts wherever possible, and your first adjustment service at our workshop is included within three months. Your statutory consumer rights are unaffected.</p></details>
<details><summary>Do you deliver outside Copenhagen?</summary><p>Workshop collection is included and gives us time for your final fitting and handover. Delivery elsewhere is arranged case by case, with packing, transport, local tax treatment and any import costs confirmed separately before you order.</p></details>
</div>
</section>
</main>
<footer class="footer">
<div class="wrap">
<div class="footer-top">
<a class="logo" href="#" aria-label="Lumen Cycles back to top">
<svg viewBox="0 0 34 38" fill="none" aria-hidden="true"><path d="M5 6v25h23M13 6v17h15M21 6v9h7" stroke="currentColor" stroke-width="3.5"/></svg>
<span class="wordmark">lumen<small>cycles / copenhagen</small></span>
</a>
<span class="footer-line">Good things are worth carrying.</span>
<a class="button orange" href="#build">Let’s build yours <span aria-hidden="true">↗</span></a>
</div>
<div class="footer-bottom">
<span>© <span id="year">2026</span> Lumen Cycles. Built with care in Copenhagen.</span>
<span>No trackers. No cookies. Just bikes.</span>
<a href="#">Back to the top ↑</a>
</div>
</div>
</footer>
<dialog id="visit-dialog" aria-labelledby="visit-title">
<button type="button" class="dialog-close" aria-label="Close visit planner">×</button>
<span class="eyebrow">See you at the workshop</span>
<h2 id="visit-title">Make time for<br>a first ride.</h2>
<p>Put together a visit note to save with your build. This offline planner doesn’t book an appointment or send your information.</p>
<form id="visit-form">
<label for="visit-name">Your name</label>
<input id="visit-name" name="name" autocomplete="given-name" placeholder="First name" required maxlength="80">
<label for="visit-interest">What would you like to explore?</label>
<select id="visit-interest" name="interest">
<option>Everyday cargo & errands</option>
<option>Riding with children</option>
<option>Electric assist</option>
<option>A custom project</option>
</select>
<button class="button" type="submit">Save my visit note <span aria-hidden="true">↓</span></button>
</form>
<p id="visit-result" class="dialog-result" role="status" hidden></p>
</dialog>
<script>
(function(){
'use strict';
const form = document.getElementById('build-form');
const total = document.getElementById('total');
const palette = {
Forest: {hex:'#40563b', note:'a Copenhagen classic'},
Terracotta: {hex:'#b7613f', note:'a little warmth for the road'},
Oat: {hex:'#d1c6a8', note:'quietly distinctive'}
};
const euro = value => '€' + value.toLocaleString('en-IE');
function selection(){
const values = new FormData(form);
return {
drive: values.get('drive'),
cargo: values.get('cargo'),
color: values.get('color'),
price: 3990 + (values.get('drive') === 'electric' ? 1100 : 0) + (values.get('cargo') === 'family' ? 240 : 0)
};
}
function update(){
const build = selection();
total.value = euro(build.price);
document.getElementById('color-name').textContent = build.color + ' — ' + palette[build.color].note;
document.getElementById('preview-frame').setAttribute('stroke', palette[build.color].hex);
document.getElementById('preview-motor').style.display = build.drive === 'electric' ? 'inline' : 'none';
document.getElementById('save-message').hidden = true;
}
function download(name, content){
const blob = new Blob([content], {type:'text/plain;charset=utf-8'});
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = name;
document.body.appendChild(link);
link.click();
link.remove();
setTimeout(() => URL.revokeObjectURL(url), 10000);
}
function buildText(){
const build = selection();
return [
'LUMEN CYCLES / COPENHAGEN',
'Your No. 01 — build estimate',
'Prepared: ' + new Date().toLocaleDateString('en-GB'),
'',
'Frame colour: ' + build.color,
'Drive: ' + (build.drive === 'electric' ? '250 W electric assist (+€1,100)' : 'Human-powered (included)'),
'Cargo: ' + (build.cargo === 'family' ? 'Birch box, bench and two harnesses (+€240)' : 'Open birch box (included)'),
'',
'Estimated total: ' + euro(build.price),
'Includes 25% Danish VAT, assembly and fitting.',
'Collection in Copenhagen included. Delivery and custom extras quoted separately.',
'',
'Estimated build time: 8–12 weeks after specification and deposit confirmation.',
'30% deposit after written quote approval; balance before collection.',
'',
'This is a saved estimate, not an order or a reservation.',
'No details have been sent to Lumen Cycles.',
'Next step: discuss frame fit, intended use and final specifications with the workshop.',
'Final pricing, availability and terms must be confirmed in writing.'
].join('\n');
}
form.addEventListener('change', update);
form.addEventListener('submit', function(event){
event.preventDefault();
download('lumen-my-build.txt', buildText());
const message = document.getElementById('save-message');
message.textContent = 'Your build sheet is ready. Keep the downloaded file for your workshop conversation. Nothing has been ordered or sent.';
message.hidden = false;
});
update();
document.getElementById('year').textContent = new Date().getFullYear();
const dialog = document.getElementById('visit-dialog');
document.getElementById('visit-button').addEventListener('click', () => dialog.showModal());
dialog.querySelector('.dialog-close').addEventListener('click', () => dialog.close());
dialog.addEventListener('click', function(event){
const box = dialog.getBoundingClientRect();
if(event.target === dialog && (event.clientX < box.left || event.clientX > box.right || event.clientY < box.top || event.clientY > box.bottom)) dialog.close();
});
document.getElementById('visit-form').addEventListener('submit', function(event){
event.preventDefault();
const name = document.getElementById('visit-name').value.trim();
if(!name){
document.getElementById('visit-name').setCustomValidity('Please enter your first name.');
document.getElementById('visit-name').reportValidity();
return;
}
const interest = document.getElementById('visit-interest').value;
download('lumen-workshop-visit.txt', [
'LUMEN CYCLES / WORKSHOP VISIT NOTE',
'',
'Name: ' + name,
'I would like to explore: ' + interest,
'Allow approximately 45 minutes for a workshop conversation, fitting and first ride.',
'',
'This note is for your own planning. No appointment has been booked.',
'No personal information has been transmitted.',
'Visit date and workshop location require direct confirmation.',
'',
'MY CURRENT BUILD',
'',
buildText()
].join('\n'));
const result = document.getElementById('visit-result');
result.textContent = 'Your visit note is ready to keep. An appointment has not been booked, and your details stay on this device.';
result.hidden = false;
});
document.getElementById('visit-name').addEventListener('input', function(){this.setCustomValidity('');});
})();
</script>
</body>
</html>

