trekmap-preorder/index.html

573 lines
42 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<title>TrekMap — Hang your travels on the wall</title>
<meta name="description" content="A travel bucket list that lives on a world map — and an LED map that glows with everywhere you've been and everywhere you're going. Reserve the first production run.">
<meta property="og:title" content="TrekMap — Hang your travels on the wall">
<meta property="og:description" content="A travel bucket list that lives on a world map, and an LED map on your wall that glows with it.">
<meta property="og:type" content="website">
<meta name="theme-color" content="#001F3F">
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%23001F3F'/%3E%3Ccircle cx='16' cy='13' r='5' fill='%23E6B800'/%3E%3Cpath d='M4 25c4-6 8-6 12 0s8 6 12 0v7H4z' fill='%231B4332'/%3E%3C/svg%3E">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,500;9..144,700&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
<style>
:root{
--midnight:#001F3F; --nightsky:#0B192C; --deep:#00162e; --abyss:#000d1c;
--gold:#E6B800; --gold-soft:#f0cf4d; --mahogany:#6F4E37; --jungle:#1B4332;
--teal:#3FD9B4; --ink:#F4F1EA; --muted:#8FA3B8; --line:rgba(230,184,0,.16);
--max:1140px;
}
*,*::before,*::after{box-sizing:border-box}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
margin:0;background:var(--midnight);color:var(--ink);
font:16px/1.65 Inter,ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,sans-serif;
-webkit-font-smoothing:antialiased;overflow-x:hidden;
}
h1,h2,h3{font-family:Fraunces,Georgia,serif;line-height:1.04;letter-spacing:-.02em;margin:0;font-weight:700}
p{margin:0}
a{color:var(--gold);text-decoration:none}
a:focus-visible,button:focus-visible,summary:focus-visible,input:focus-visible{outline:2px solid var(--gold);outline-offset:3px;border-radius:6px}
img{max-width:100%;height:auto;display:block}
.wrap{max-width:var(--max);margin:0 auto;padding:0 24px}
.eyebrow{font-size:.7rem;letter-spacing:.2em;text-transform:uppercase;color:var(--gold);font-weight:600}
.lede{color:var(--muted);font-size:1.06rem;max-width:36em}
/* ── nav ── */
header{position:fixed;inset:0 0 auto;z-index:60;backdrop-filter:blur(14px);
background:rgba(0,22,46,.62);border-bottom:1px solid rgba(255,255,255,.06);transition:background .3s}
nav{display:flex;align-items:center;gap:28px;max-width:var(--max);margin:0 auto;padding:13px 24px}
.brand{display:flex;align-items:center;gap:10px;font-family:Fraunces,serif;font-weight:700;font-size:1.12rem;letter-spacing:-.02em;color:var(--ink)}
.brand svg{width:28px;height:28px;flex:none}
nav .links{display:flex;gap:26px;margin-left:auto;font-size:.9rem;color:var(--muted)}
nav .links a{color:var(--muted)}
nav .links a:hover{color:var(--ink)}
@media(max-width:820px){nav .links{display:none}}
.btn{display:inline-flex;align-items:center;gap:8px;background:var(--gold);color:#00162e;font-weight:600;
padding:11px 20px;border-radius:10px;font-size:.92rem;border:0;cursor:pointer;transition:transform .15s,box-shadow .15s}
.btn:hover{transform:translateY(-1px);box-shadow:0 8px 24px rgba(230,184,0,.28)}
.btn.ghost{background:transparent;color:var(--ink);border:1px solid rgba(244,241,234,.22)}
.btn.ghost:hover{border-color:var(--gold);box-shadow:none}
/* ── globe scroll story ── */
.story{position:relative}
.story .sticky{position:sticky;top:0;height:100svh;overflow:hidden;display:flex;align-items:center;justify-content:center}
.globewrap{position:absolute;inset:0;will-change:transform}
#globe{width:100%;height:100%;display:block}
.intro{position:absolute;inset:0;display:flex;align-items:center;z-index:3;will-change:transform,opacity}
.intro .wrap{width:100%}
.intro h1{font-size:clamp(2.4rem,6vw,4.4rem);max-width:13ch;margin:.5rem 0 0}
.intro h1 em{font-style:normal;color:var(--gold);display:block}
.intro .lede{margin-top:18px;font-size:1.08rem;max-width:30em}
.intro::before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
background:radial-gradient(70% 60% at 22% 50%,rgba(0,22,46,.94),rgba(0,22,46,.6) 45%,transparent 72%)}
@media(max-width:820px){.intro::before{background:linear-gradient(180deg,rgba(0,22,46,.9),rgba(0,22,46,.55) 60%,transparent)}}
.chapters{position:absolute;inset:0;z-index:4;pointer-events:none}
.chapter{position:absolute;top:50%;width:min(400px,42vw);transform:translateY(28px);opacity:0;
background:rgba(0,13,28,.72);backdrop-filter:blur(10px);border:1px solid var(--line);
border-radius:16px;padding:26px 26px 28px;margin-top:-120px;will-change:transform,opacity}
.chapter.left{left:max(24px,calc(50vw - var(--max)/2))}
.chapter.right{right:max(24px,calc(50vw - var(--max)/2))}
.chapter .coord{font-size:.66rem;letter-spacing:.16em;color:var(--gold);opacity:.8;font-weight:600}
.chapter h2{font-size:1.5rem;margin:12px 0 10px}
.chapter .cbody{color:var(--muted);font-size:.95rem}
@media(max-width:820px){
.chapter{width:auto;left:20px;right:20px;top:auto;bottom:12vh;margin-top:0;padding:20px}
.chapter.left,.chapter.right{left:20px;right:20px}
}
.cue{position:absolute;left:50%;bottom:26px;transform:translateX(-50%);z-index:5;
font-size:.68rem;letter-spacing:.22em;text-transform:uppercase;color:var(--muted);opacity:.6}
.cue::after{content:"";display:block;width:1px;height:26px;margin:8px auto 0;
background:linear-gradient(var(--gold),transparent);animation:cue 2.2s ease-in-out infinite}
@keyframes cue{0%,100%{opacity:.2;transform:scaleY(.5)}50%{opacity:1;transform:scaleY(1)}}
/* LED wall-map band in the hardware section */
.ledband{position:relative;height:230px;margin:44px 0 8px;border:1px solid var(--line);
border-radius:16px;overflow:hidden;background:linear-gradient(180deg,#00162e,#000d1c)}
.ledband canvas{position:absolute;inset:0;width:100%;height:100%}
.ledcap{position:absolute;left:0;right:0;bottom:12px;text-align:center;font-size:.72rem;
letter-spacing:.1em;color:var(--muted);opacity:.75}
/* ── hero ── */
.hero{position:relative;min-height:100svh;display:flex;align-items:center;overflow:hidden;
background:radial-gradient(120% 80% at 78% 45%,rgba(11,25,44,.2),var(--midnight) 70%)}
.hero .wrap{position:relative;z-index:2;padding-top:96px;padding-bottom:60px}
.hero::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
background:linear-gradient(90deg,var(--midnight) 8%,rgba(0,31,63,.86) 34%,rgba(0,31,63,.15) 62%,transparent 82%)}
@media(max-width:820px){.hero::after{background:linear-gradient(180deg,rgba(0,31,63,.72) 0%,rgba(0,31,63,.9) 55%,var(--midnight) 92%)}}
h1{font-size:clamp(2.5rem,6.4vw,4.6rem);max-width:13ch;margin:.5rem 0 0}
h1 em{font-style:normal;color:var(--gold);display:block}
.hero .lede{margin-top:20px;font-size:1.12rem}
.cta-row{display:flex;gap:12px;flex-wrap:wrap;margin-top:30px}
.legend{display:flex;gap:22px;flex-wrap:wrap;margin-top:34px;font-size:.82rem;color:var(--muted)}
.legend b{display:inline-flex;align-items:center;gap:8px;font-weight:400}
.legend i{width:8px;height:8px;border-radius:50%;display:block}
.legend .w{background:rgba(230,184,0,.55);box-shadow:0 0 8px rgba(230,184,0,.45)}
.legend .v{background:#ffd54a;box-shadow:0 0 10px rgba(255,213,74,.9)}
.legend .o{background:rgba(143,163,184,.32)}
.scrollcue{position:absolute;left:50%;bottom:26px;transform:translateX(-50%);z-index:3;
font-size:.68rem;letter-spacing:.22em;text-transform:uppercase;color:var(--muted);opacity:.6}
.scrollcue::after{content:"";display:block;width:1px;height:26px;margin:8px auto 0;
background:linear-gradient(var(--gold),transparent);animation:cue 2.2s ease-in-out infinite}
@keyframes cue{0%,100%{opacity:.2;transform:scaleY(.5)}50%{opacity:1;transform:scaleY(1)}}
/* ── sections ── */
section{position:relative;padding:92px 0}
.sec-head{max-width:34ch}
.sec-head h2{font-size:clamp(1.9rem,4vw,3rem);margin:.5rem 0 14px}
/* Wide variant: heading left, supporting line right, so a short headline
doesn't leave half the row empty on desktop. */
.sec-head.wide{max-width:none;display:grid;gap:10px 56px;align-items:end}
@media(min-width:900px){.sec-head.wide{grid-template-columns:minmax(0,1.05fr) minmax(0,1fr)}
.sec-head.wide .eyebrow{grid-column:1/-1}
.sec-head.wide h2{margin-bottom:0}
.sec-head.wide .lede{padding-bottom:6px}}
/* reveal */
.rev{opacity:1;transform:none}
html.js .rev{opacity:0;transform:translateY(22px);transition:opacity .7s cubic-bezier(.22,.7,.3,1),transform .7s cubic-bezier(.22,.7,.3,1)}
html.js .rev.in{opacity:1;transform:none}
/* ── the loop ── */
.loop{display:grid;gap:1px;background:var(--line);border:1px solid var(--line);border-radius:16px;overflow:hidden;margin-top:52px}
@media(min-width:880px){.loop{grid-template-columns:repeat(3,1fr)}}
.step{background:var(--deep);padding:34px 30px 38px;position:relative;transition:background .4s}
.step:hover{background:#001a36}
.step .n{font-family:Fraunces,serif;font-size:.78rem;letter-spacing:.16em;color:var(--gold);opacity:.75}
.step h3{font-size:1.42rem;margin:14px 0 10px}
.step p{color:var(--muted);font-size:.96rem}
.step .art{height:84px;margin:24px 0 0;position:relative}
/* wish: a reel resolves into a pinned place */
.wish{display:flex;align-items:center;gap:14px;height:100%}
.reel{width:50px;height:74px;border-radius:8px;flex:none;position:relative;
background:linear-gradient(160deg,#22405f,#0d2138);border:1px solid rgba(230,184,0,.3)}
.reel::after{content:"";position:absolute;left:52%;top:50%;width:0;height:0;transform:translate(-50%,-50%);
border-left:10px solid var(--gold);border-top:6.5px solid transparent;border-bottom:6.5px solid transparent}
.trail{flex:1;height:1px;background:repeating-linear-gradient(90deg,rgba(230,184,0,.5) 0 5px,transparent 5px 11px)}
.step.in .trail{animation:trail 3.2s linear infinite}
@keyframes trail{to{background-position:22px 0}}
.place{flex:none;display:flex;align-items:center;gap:8px;font-size:.78rem;color:var(--muted);
border:1px solid var(--line);border-radius:8px;padding:7px 10px;background:rgba(230,184,0,.05)}
.place i{width:9px;height:9px;border-radius:50%;background:var(--gold);flex:none}
.step.in .place i{animation:pulse 3.2s ease-out infinite}
@keyframes pulse{0%,40%{box-shadow:0 0 0 0 rgba(230,184,0,.5)}70%{box-shadow:0 0 0 10px rgba(230,184,0,0)}100%{box-shadow:0 0 0 0 rgba(230,184,0,0)}}
/* time: heat bars */
.bars{display:flex;align-items:flex-end;gap:7px;height:100%}
.bars i{flex:1;background:linear-gradient(var(--gold),rgba(230,184,0,.18));border-radius:3px 3px 0 0;height:12%;
transform-origin:bottom;transition:height .8s cubic-bezier(.3,.9,.3,1)}
.step.in .bars i{height:var(--h)}
/* make: fare ticket */
.fare{position:absolute;inset:auto 0 4px 0;border:1px dashed rgba(230,184,0,.4);border-radius:10px;padding:12px 14px;
display:flex;justify-content:space-between;align-items:center;background:rgba(230,184,0,.05)}
.fare .rt{font-family:Fraunces,serif;font-size:.98rem}
.fare .pr{color:var(--teal);font-weight:600;font-size:1.05rem}
.step.in .fare{animation:tick 3.6s ease-in-out infinite}
@keyframes tick{0%,100%{transform:translateY(0)}50%{transform:translateY(-5px)}}
/* ── app showcase ── */
.showcase{display:grid;gap:44px;align-items:center}
@media(min-width:900px){.showcase{grid-template-columns:.85fr 1.15fr}}
.frame{position:relative;border-radius:14px;overflow:hidden;border:1px solid rgba(244,241,234,.12);
box-shadow:0 40px 90px rgba(0,0,0,.55),0 0 0 1px rgba(230,184,0,.08);background:var(--deep)}
.frame .bar{display:flex;gap:6px;padding:10px 13px;background:#04182f;border-bottom:1px solid rgba(255,255,255,.06)}
.frame .bar i{width:9px;height:9px;border-radius:50%;background:rgba(244,241,234,.18)}
.frame img{width:100%}
.feat{display:grid;gap:20px;margin-top:8px}
.feat div{padding-left:18px;border-left:2px solid var(--line)}
.feat h4{margin:0 0 5px;font-size:1rem;font-weight:600;font-family:Inter,sans-serif}
.feat p{color:var(--muted);font-size:.93rem}
/* ── hardware ── */
.skus{display:grid;gap:18px;margin-top:48px}
@media(min-width:820px){.skus{grid-template-columns:repeat(3,1fr)}}
.sku{border:1px solid var(--line);border-radius:16px;padding:26px 24px 28px;background:linear-gradient(180deg,rgba(11,25,44,.7),rgba(0,22,46,.5));
display:flex;flex-direction:column;transition:border-color .3s,transform .3s}
.sku:hover{border-color:rgba(230,184,0,.44);transform:translateY(-3px)}
.sku.pick{border-color:rgba(230,184,0,.5);box-shadow:0 0 0 1px rgba(230,184,0,.16),0 20px 50px rgba(0,0,0,.4)}
.sku .tag{position:absolute;margin-top:-40px;background:var(--gold);color:#00162e;font-size:.64rem;font-weight:700;
letter-spacing:.12em;text-transform:uppercase;padding:4px 9px;border-radius:5px}
.sku h3{font-size:1.3rem}
.sku .mat{color:var(--muted);font-size:.86rem;margin-top:6px}
.sku .price{font-family:Fraunces,serif;font-size:2.2rem;margin:18px 0 4px}
.sku .price span{font-size:.9rem;color:var(--muted);font-family:Inter,sans-serif}
.strip{display:flex;gap:3px;margin:20px 0 22px;height:9px}
.strip i{flex:1;border-radius:2px;background:rgba(143,163,184,.15)}
.strip i.dim{background:rgba(230,184,0,.32)}
.strip i.on{background:var(--gold);box-shadow:0 0 8px rgba(230,184,0,.75)}
.sku ul{list-style:none;padding:0;margin:0 0 24px;color:var(--muted);font-size:.9rem;display:grid;gap:9px}
.sku li{padding-left:18px;position:relative}
.sku li::before{content:"";position:absolute;left:0;top:8px;width:6px;height:6px;border-radius:50%;background:var(--gold);opacity:.75}
.sku .btn{width:100%;justify-content:center;margin-top:auto}
/* ── reserve ── */
#reserve{background:linear-gradient(180deg,transparent,rgba(11,25,44,.55) 30%,rgba(11,25,44,.55));padding-top:40px}
.reserve-card{border:1px solid var(--line);border-radius:20px;padding:40px 38px;background:rgba(0,22,46,.72);
max-width:640px;margin:34px auto 0;text-align:center;backdrop-filter:blur(6px)}
.reserve-card h2{font-size:clamp(1.7rem,3.4vw,2.4rem)}
.picks{display:flex;gap:8px;justify-content:center;flex-wrap:wrap;margin:26px 0 22px}
.picks label{cursor:pointer}
.picks input{position:absolute;opacity:0;pointer-events:none}
.picks span{display:block;padding:9px 16px;border:1px solid rgba(244,241,234,.18);border-radius:9px;font-size:.88rem;color:var(--muted);transition:.2s}
.picks input:checked+span{border-color:var(--gold);color:var(--ink);background:rgba(230,184,0,.1)}
.picks input:focus-visible+span{outline:2px solid var(--gold);outline-offset:2px}
form.rf{display:flex;gap:10px;flex-wrap:wrap;justify-content:center}
form.rf input[type=email]{flex:1;min-width:230px;background:rgba(0,13,28,.8);border:1px solid rgba(244,241,234,.18);
color:var(--ink);padding:13px 16px;border-radius:10px;font-size:.95rem;font-family:inherit}
form.rf input[type=email]::placeholder{color:#5d738c}
.fineprint{color:var(--muted);font-size:.82rem;margin-top:16px}
.said{color:var(--gold);font-size:1.05rem;padding:12px 0}
.err{color:#ff8f8f;font-size:.85rem;margin-top:10px;min-height:1.2em}
/* ── faq ── */
.faq{max-width:760px;margin:44px auto 0;border-top:1px solid var(--line)}
details{border-bottom:1px solid var(--line)}
summary{cursor:pointer;padding:20px 40px 20px 0;font-weight:500;position:relative;list-style:none;font-size:1.02rem}
summary::-webkit-details-marker{display:none}
summary::after{content:"";position:absolute;right:8px;top:27px;width:9px;height:9px;border-right:1.5px solid var(--gold);
border-bottom:1.5px solid var(--gold);transform:rotate(45deg);transition:transform .25s}
details[open] summary::after{transform:rotate(-135deg)}
details p{color:var(--muted);padding:0 0 22px;font-size:.95rem;max-width:62ch}
/* ── footer ── */
footer.f{border-top:1px solid var(--line);padding:40px 0 54px;color:var(--muted);font-size:.88rem}
footer.f .row{display:flex;gap:20px;flex-wrap:wrap;align-items:center;justify-content:space-between}
footer.f a{color:var(--muted)}
footer.f a:hover{color:var(--gold)}
@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
</style>
</head>
<body>
<header>
<nav>
<a class="brand" href="#top" data-track="nav-brand">
<svg viewBox="0 0 32 32" aria-hidden="true"><rect width="32" height="32" rx="7" fill="#04182f" stroke="rgba(230,184,0,.35)"/><circle cx="16" cy="12.5" r="4.6" fill="#E6B800"/><path d="M3 25c4.2-6.4 8.4-6.4 12.6 0s8.4 6.4 12.6 0v7H3z" fill="#1B4332"/><path d="M3 27.5c4.2-5 8.4-5 12.6 0s8.4 5 12.6 0" stroke="#3FD9B4" stroke-width="1" fill="none" opacity=".55"/></svg>
TrekMap
</a>
<div class="links">
<a href="#story" data-track="nav-story">The story</a>
<a href="#app" data-track="nav-app">The app</a>
<a href="#hardware" data-track="nav-hardware">Hardware</a>
<a href="#faq" data-track="nav-faq">FAQ</a>
</div>
<a class="btn" href="#reserve" data-track="nav-reserve">Reserve</a>
</nav>
</header>
<section class="story" id="story">
<div class="sticky">
<div class="globewrap" id="globewrap"><canvas id="globe" aria-hidden="true"></canvas></div>
<div class="intro" id="intro">
<div class="wrap">
<p class="eyebrow">Pre-order · first production run</p>
<h1>Hang your travels <em>on the wall.</em></h1>
<p class="lede">A travel bucket list that lives on a world map — and an LED map that glows with everywhere you&rsquo;ve been and everywhere you&rsquo;re going.</p>
<div class="cta-row">
<a class="btn" href="#reserve" data-track="hero-reserve">Reserve your map</a>
<a class="btn ghost" href="https://trekmap.co" data-track="hero-app">Open the app</a>
</div>
<div class="legend">
<b><i class="v"></i> full gold — been there</b>
<b><i class="w"></i> ember — on the list</b>
</div>
</div>
</div>
<div class="chapters" id="chapters"></div>
<div class="cue" id="cue" aria-hidden="true">Scroll</div>
</div>
</section>
<section id="app">
<div class="wrap showcase">
<div class="rev">
<p class="eyebrow">The app</p>
<h2 style="font-size:clamp(1.8rem,3.6vw,2.6rem);margin:.5rem 0 16px">Your whole travel life, on one glowing map.</h2>
<div class="feat">
<div><h4>Drop a wish anywhere</h4><p>Pins glow amber until the day you go, then turn teal for good.</p></div>
<div><h4>Explore what people actually did</h4><p>A feed of real places pinned by other travellers — searchable by vibe, not by hotel star rating.</p></div>
<div><h4>Flight Tracker &amp; Trek Journal</h4><p>Watch fares to your saved places, and keep the story of the trip once you're back.</p></div>
</div>
<div class="cta-row"><a class="btn ghost" href="https://trekmap.co" data-track="app-open">Try it free — no account needed</a></div>
</div>
<div class="frame rev">
<div class="bar" aria-hidden="true"><i></i><i></i><i></i></div>
<img src="app-shot.jpg" width="1500" height="791" alt="The TrekMap app showing the Explore map with community pins across the eastern United States" loading="lazy">
</div>
</div>
</section>
<section id="hardware">
<div class="wrap">
<div class="sec-head wide rev">
<p class="eyebrow">The hardware</p>
<h2>One LED per region. Yours lit the way you travelled.</h2>
<p class="lede">The map syncs over Wi-Fi with your list. Wishes breathe amber. Places you've been sit bright and steady. It is the only wall art that is out of date the moment you land somewhere new — in a good way.</p>
</div>
<div class="ledband rev" aria-hidden="true"><canvas id="led"></canvas>
<p class="ledcap">One LED per region &middot; full gold = been there &middot; ember = on the list</p></div>
<div class="skus">
<div class="sku rev">
<h3>TrekMap Mini</h3>
<p class="mat">Desktop frame · US, CA, MX</p>
<div class="price">$99 <span>+ shipping</span></div>
<div class="strip" data-mini="mini" aria-hidden="true"></div>
<ul><li>Birch frame, 12&Prime; wide</li><li>State-level LEDs</li><li>USB-C, sits on a shelf</li></ul>
<a class="btn ghost" href="#reserve" data-track="sku-mini">Reserve the Mini</a>
</div>
<div class="sku pick rev">
<span class="tag">Most reserved</span>
<h3>TrekMap</h3>
<p class="mat">Wall map · one LED per region</p>
<div class="price">$199 <span>+ shipping</span></div>
<div class="strip" data-mini="wall" aria-hidden="true"></div>
<ul><li>24&Prime; wall map, matte print</li><li>Full world, region-level LEDs</li><li>Explorer Mode across 57 countries</li></ul>
<a class="btn" href="#reserve" data-track="sku-wall">Reserve the map</a>
</div>
<div class="sku rev">
<h3>TrekGlobe</h3>
<p class="mat">Walnut base · brass meridian</p>
<div class="price">$399 <span>+ shipping</span></div>
<div class="strip" data-mini="globe" aria-hidden="true"></div>
<ul><li>Solid walnut, turned brass</li><li>Lit globe, spins freely</li><li>Numbered first run</li></ul>
<a class="btn ghost" href="#reserve" data-track="sku-globe">Reserve the Globe</a>
</div>
</div>
</div>
</section>
<section id="reserve">
<div class="wrap">
<div class="reserve-card rev">
<p class="eyebrow">Reserve</p>
<h2>Lock the launch price.</h2>
<p class="lede" style="margin:14px auto 0;text-align:center">No charge today. We email you when the first run opens, and you decide then.</p>
<form class="rf" id="reserveForm" method="POST" action="/forms/reserve" novalidate>
<div class="picks" role="radiogroup" aria-label="Which one">
<label><input type="radio" name="tier" value="TrekMap Mini — $99"><span>Mini · $99</span></label>
<label><input type="radio" name="tier" value="TrekMap — $199" checked><span>TrekMap · $199</span></label>
<label><input type="radio" name="tier" value="TrekGlobe — $399"><span>TrekGlobe · $399</span></label>
</div>
<input type="email" name="email" placeholder="you@example.com" required autocomplete="email" aria-label="Email address">
<button class="btn" type="submit" data-track="reserve-submit">Reserve</button>
<p class="err" id="rerr" role="alert"></p>
</form>
<p class="fineprint">First run is limited. No spam, no sharing your address — one email when it opens.</p>
</div>
</div>
</section>
<section id="faq" style="padding-top:20px">
<div class="wrap">
<div class="sec-head rev" style="margin:0 auto;text-align:center;max-width:40ch">
<p class="eyebrow">Questions</p>
<h2>The honest answers.</h2>
</div>
<div class="faq rev">
<details><summary>Is the hardware actually built yet?</summary><p>Not yet — that is what this page is for. The app is live and free to use today at trekmap.co. The maps are in development and reserving one tells us how many to make in the first run. You are not charged now.</p></details>
<details><summary>Do I need the map to use the app?</summary><p>No. The app works completely on its own — the wall map is the physical twin of the list you already keep in it.</p></details>
<details><summary>How does it know where a reel was filmed?</summary><p>TrekMap watches the video: signage, landmarks, spoken audio and the caption. It proposes the place and you confirm. If it guesses wrong you can correct it in a tap.</p></details>
<details><summary>What is Explorer Mode?</summary><p>Instead of colouring in a whole country because you changed planes there, Explorer Mode splits 57 countries into states, prefectures and regions — so the map reflects what you have actually seen.</p></details>
<details><summary>When does it ship?</summary><p>We are not going to invent a date. Reserve, and you will get a real one before anybody is asked for money.</p></details>
</div>
</div>
</section>
<footer class="f">
<div class="wrap row">
<span>TrekMap — a travel bucket list you can hang on the wall.</span>
<span>
<a href="https://trekmap.co" data-track="foot-app">The app</a> ·
<a href="mailto:contact@trekmap.co" data-track="foot-email">contact@trekmap.co</a>
</span>
</div>
</footer>
<script src="d3geo.min.js" defer></script>
<script src="globe.js" defer></script>
<script>window.__TREKMAP_MASK__="000000000000000000000000000000001000111011100011111111111111111111100000000000001111000000000000000000000000000000011110000000000000000000000000000000\n000000000000000000000000011100000001001111100111111111111111111111000000000000000100000000000000000000010000000000000111000000000000000000000000000000\n000000000000000000000000000110000001011111000000000111111111111111100000000000000000000000000000000100000000000111111111110000000000000000000000000000\n000000000000000000000001101011101111001110100000000011111111111110000000000000000000000000000000010000001000011111111111111111111000001000000000000000\n000000001110000000000000000011110001101111111110000010111111111101000000000000000000111100000000000000011011111111111111111111111111111111111100000000\n100000111111111111111111111000100000100110001110000001111111101000000000000000000111111111100100001111101111111111111111111111111111111111111111111111\n111100101111111111111111111111111111111100001111100001111111100001000000000000001111111110110111111111110111111111111111111111111111111111111111111111\n000000001111111111111111111111111111110110001111000000111100000000111000000000011111011111011111111111111111111111111111111111111111111111111111111110\n000000111111111111111111111111111111000000111001000000111000000000000000000001111100111111111111111111111111111111111111111111111111111111111111111100\n000001111110100111111111111111111111000000011100000000001000000000000000001000111110100111111111111111111111111111111111111111111111111111100011000000\n000000000110000000011111111111111111000000011111100000000000000000000000000000001100011111111111111111111111111111111111111111111111110000000110000000\n000000001000000000011111111111111111111000011111100000000000000000000000010000101000111111111111111111111111111111111111111111111111000000001110000000\n000001000000000000000111111111111111111110111111111000000000000000000001001000011111111111111111111111111111111111111111111111111111001000001100000000\n110000000000000000000011111111111111111110111111111100000000000000000001011001111111111111111111111111111111111111111111111111111111111000001000000000\n000000000000000000000011111111111111111111111110100100000000000000000000000111111111111111111111111111111111111111111111111111111111111000000000000000\n000000000000000000000001111111111111111111111111000000000000000000000000001111111111111111111111111111111111111111111111111111111111100000000000000000\n000000000000000000000001111111111111111111111111100000000000000000000000000111110111111001011110011111111111111111111111111111111111000000000000000000\n000000000000000000000001111111111111111111111100000000000000000000000000111111011011111000001110111111111111111111111111111111111110001100000000000000\n000000000000000000000001111111111111111111111100000000000000000000000001111100001101111011001110001111111111111111111111111111111000000000000000000000\n000000000000000000000001111111111111111111110000000000000000000000000001111000100000101111111111011111111111111111111111111110010000010000000000000000\n000000000000000000000000111111111111111111100000000000000000000000000001110000000000111111111111011111111111111111111111111111001000010000000000000000\n000000000000000000000000011111111111111111100000000000000000000000000000111111110000010000111111111111111111111111111111111110001011100000000000000000\n000000000000000000000000001111111111111111000000000000000000000000000001111111110000000000111111111111111111111111111111111110000100000000000000000000\n000000000000000000000000000011111111111110000000000000000000000000000001111111111101111111111111111111111111111111111111111111000000000000000000000000\n000000000000000000000000000111111110000000000000000000000000000000000011111111111111111110111110111111111111111111111111111111000000000000000000000000\n000000000000000000000000000011111100000001100000000000000000000000000111111111111111111110111111000111111111111111111111111110000000000000000000000000\n000000000000000000000000000010111100000000100000000000000000000000000111111111111111111111011111001000011111111111111111111101000000000000000000000000\n000000000000000000000000000000011100000001000000000000000000000000001111111111111111111111011111111100001111111111111111110000000000000000000000000000\n000000000000000000000000000000011110011000010000000000000000000000001111111111111111111111001111111100000111111000111110000000000000000000000000000000\n000000000000000000000000000000001111110000101001000000000000000000001111111111111111111111101111111000000111110000111110100001000000000000000000000000\n000000000000000000000000000000000010110000000000000000000000000001001111111111111111111111100111100000000011100000101111000001000000000000000000000000\n000000000000000000000000000000000000011100000000000000000000000000001111111111111111111111110110000000000011000000001111000001000000000000000000000000\n000000000000000000000000000000000000000100000000000000000000000000001111111111111111111111111000000000000011000000001011100000000000000000000000000000\n000000000000000000000000000000000000000100001111100000000000000000000111111111111111111111111111000000000001000000000000000010100000000000000000000000\n000000000000000000000000000000000000000001111111110000000000000000000011111111111111111111111111000000000000100000001000000000110000000000000000000000\n000000000000000000000000000000000000000000011111111100000000000000000001111001111111111111111110000000000000000000000100000100000000000000000000000000\n000000000000000000000000000000000000000000011111111111000000000000000000000000011111111111111110000000000000000000010100001100000000000000000000000000\n000000000000000000000000000000000000000000111111111111000000000000000000000000011111111111111100000000000000000000001000111100000000000000000000000000\n000000000000000000000000000000000000000001111111111111100000000000000000000000011111111111111000000000000000000000000110111100000000000000000000000000\n000000000000000000000000000000000000000001111111111111110000000000000000000000011111111111110000000000000000000000000110011001000010110000000000000000\n000000000000000000000000000000000000000001111111111111111110000000000000000000001111111111100000000000000000000000000010000000000000111100100000000000\n000000000000000000000000000000000000000000111111111111111111000000000000000000001111111111100000000000000000000000000001010000000000011100000000000000\n000000000000000000000000000000000000000000111111111111111111000000000000000000001111111111100000000000000000000000000000000001010000001010000000000000\n000000000000000000000000000000000000000000011111111111111111000000000000000000000111111111110000000000000000000000000000000000000000000000000000000000\n000000000000000000000000000000000000000000011111111111111110000000000000000000001111111111110001000000000000000000000000000000000111001000000000000000\n000000000000000000000000000000000000000000001111111111111110000000000000000000001111111111110001000000000000000000000000000000011111001100000000100000\n000000000000000000000000000000000000000000000111111111111110000000000000000000001111111111100111000000000000000000000000000000011111101100000000000000\n000000000000000000000000000000000000000000000011111111111100000000000000000000001111111111000110000000000000000000000000000000111111111100000000000000\n000000000000000000000000000000000000000000000011111111111100000000000000000000000111111111000110000000000000000000000000000111111111111110000000000000\n000000000000000000000000000000000000000000000011111111110000000000000000000000000111111111000110000000000000000000000000001111111111111111000000000000\n000000000000000000000000000000000000000000000011111111100000000000000000000000000111111110000000000000000000000000000000000111111111111111100000000000\n000000000000000000000000000000000000000000000111111111100000000000000000000000000111111110000000000000000000000000000000000111111111111111100000000000\n000000000000000000000000000000000000000000000111111111000000000000000000000000000011111100000000000000000000000000000000000111111111111111100000000000\n000000000000000000000000000000000000000000000111111110000000000000000000000000000001111000000000000000000000000000000000000111111011111111100000000000\n000000000000000000000000000000000000000000000111111110000000000000000000000000000001110000000000000000000000000000000000000110000001111111000000000000\n000000000000000000000000000000000000000000000111111000000000000000000000000000000000000000000000000000000000000000000000000000000000011111000000000100\n000000000000000000000000000000000000000000001111111000000000000000000000000000000000000000000000000000000000000000000000000000000000001100000000000010\n000000000000000000000000000000000000000000001111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010\n000000000000000000000000000000000000000000000111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000001000\n000000000000000000000000000000000000000000001111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000\n000000000000000000000000000000000000000000001110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000\n000000000000000000000000000000000000000000011110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\n000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";</script>
<script>
(function(){
"use strict";
var reduce = matchMedia("(prefers-reduced-motion: reduce)").matches;
// Arm reveals only once JS is running, so a script failure can't leave the page blank.
if (!reduce) document.documentElement.classList.add("js");
/* ── scroll reveal ─────────────────────────────────────────── */
var revs = [].slice.call(document.querySelectorAll(".rev"));
if ("IntersectionObserver" in window && !reduce){
var io = new IntersectionObserver(function(es){
es.forEach(function(e,i){
if(e.isIntersecting){ setTimeout(function(){ e.target.classList.add("in"); }, i*80); io.unobserve(e.target); }
});
},{threshold:.12, rootMargin:"0px 0px -50px 0px"});
revs.forEach(function(el){ io.observe(el); });
// Backstop. Fast scrolling can carry an element past the observer without a
// qualifying frame, and the cost of that is invisible content — far worse
// than a missed animation. Anything at or above the fold gets revealed on
// every scroll settle, whatever the observer did or didn't see.
var sweepPending = false;
function sweep(){
sweepPending = false;
for (var i = revs.length - 1; i >= 0; i--){
var el = revs[i];
if (el.classList.contains("in")) { revs.splice(i,1); continue; }
if (el.getBoundingClientRect().top < innerHeight*1.15){ el.classList.add("in"); io.unobserve(el); revs.splice(i,1); }
}
}
// rAF-coalesced rather than time-debounced: a fast flick can outrun a timer
// and strand a section at opacity 0. The list shrinks as items reveal, so
// this costs nothing once the page has been read through.
function queueSweep(){
if (sweepPending || !revs.length) return;
sweepPending = true;
requestAnimationFrame(sweep);
}
addEventListener("scroll", queueSweep, {passive:true});
addEventListener("resize", queueSweep, {passive:true});
setTimeout(sweep, 1200);
} else { revs.forEach(function(el){ el.classList.add("in"); }); }
/* ── LED world map ───────────────────────────────────────────
MASK is real Natural Earth country geometry rasterised to a
MASK_W x MASK_H grid. Each land cell is one addressable LED,
exactly like the physical product. Scrolling the hero lights
the map up the way a real trip history fills in over years. */
var MASK = window.__TREKMAP_MASK__, MASK_W = 150, MASK_H = 66;
var cv = document.getElementById("led");
if (cv && MASK){
var ctx = cv.getContext("2d", {alpha:true});
var cells = [], rows = MASK.split("\n");
for (var y=0; y<rows.length; y++)
for (var x=0; x<rows[y].length; x++)
if (rows[y][x] === "1") cells.push({gx:x, gy:y, s:0, p:Math.random()*6.28, r:Math.random()});
// A believable travel history: a scatter visited, a wider scatter wished.
cells.forEach(function(c){ c.s = c.r < 0.055 ? 2 : c.r < 0.20 ? 1 : 0; });
var dpr=1, cw=0, ch=0, gap=0, ox=0, oy=0, dot=0;
function layout(){
dpr = Math.min(devicePixelRatio || 1, 2);
cw = cv.clientWidth; ch = cv.clientHeight;
cv.width = Math.floor(cw*dpr); cv.height = Math.floor(ch*dpr);
ctx.setTransform(dpr,0,0,dpr,0,0);
// Fit the whole world inside the band, centred — this is the wall map.
gap = Math.min(cw/(MASK_W+2), ch/(MASK_H+2));
dot = Math.max(gap*0.34, 1);
ox = (cw - MASK_W*gap)/2; oy = (ch - MASK_H*gap)/2 - ch*0.04;
}
layout();
addEventListener("resize", layout, {passive:true});
var mx=-9999, my=-9999;
if (!reduce){
addEventListener("pointermove", function(e){ mx=e.clientX; my=e.clientY; }, {passive:true});
addEventListener("pointerleave", function(){ mx=my=-9999; });
}
var lit = 1; // the band shows the finished map, not a scroll reveal
var t = 0;
function frame(){
t += 0.016;
ctx.clearRect(0,0,cw,ch);
var reach = Math.max(gap*6, 60), reach2 = reach*reach;
for (var i=0;i<cells.length;i++){
var c = cells[i];
var px = ox + c.gx*gap, py = oy + c.gy*gap;
if (px < -20 || px > cw+20 || py < -20 || py > ch+20) continue;
var st = c.s;
var base = st === 2 ? 0.92 : st === 1 ? 0.30 : 0.085;
if (st === 1 && !reduce) base += Math.sin(t*1.1 + c.p)*0.085; // idle pulse, like the firmware
var dx = px-mx, dy = py-my, d2 = dx*dx+dy*dy; // cursor = a hand passing over the map
if (d2 < reach2) base += (1 - d2/reach2)*0.55;
if (base <= 0.02) continue;
var a = base > 1 ? 1 : base;
ctx.beginPath();
if (st === 2){ // been there — full gold
ctx.arc(px, py, dot*1.24, 0, 6.2832);
ctx.fillStyle = "rgba(255,213,74," + a + ")";
if (a > 0.55){ ctx.shadowColor = "rgba(255,213,74,.85)"; ctx.shadowBlur = dot*4; } else ctx.shadowBlur = 0;
} else {
var warm = base > 0.6;
ctx.arc(px, py, dot*(warm?1.2:1), 0, 6.2832);
ctx.fillStyle = warm ? "rgba(240,207,77," + a + ")" : "rgba(230,184,0," + (a*0.8) + ")";
if (warm && a > 0.55){ ctx.shadowColor = "rgba(230,184,0,.85)"; ctx.shadowBlur = dot*4; } else ctx.shadowBlur = 0;
}
ctx.fill();
}
ctx.shadowBlur = 0;
requestAnimationFrame(frame);
}
if (reduce){
lit = 1;
ctx.clearRect(0,0,cw,ch);
cells.forEach(function(c){
var a = c.s === 2 ? 0.92 : c.s === 1 ? 0.30 : 0.085;
ctx.beginPath(); ctx.arc(ox + c.gx*gap, oy + c.gy*gap, dot, 0, 6.2832);
ctx.fillStyle = c.s === 2 ? "rgba(255,213,74," + a + ")" : "rgba(230,184,0," + a + ")";
ctx.fill();
});
} else requestAnimationFrame(frame);
}
/* ── per-SKU mini LED strips ─────────────────────────────── */
var PATTERNS = {
mini: [0,0,1,2,1,0,0,1,0,0,2,1,0,0,0,1,2,1,1,2,0,1,1,0,1,2,1,0],
wall: [0,1,2,2,1,1,2,0,1,2,1,1,2,0,1,2,1,2,2,1,1,2,1,1,2,1,2,1],
globe: [1,2,1,0,2,1,1,2,0,1,2,1,0,2,2,1,2,1,1,2,1,0,2,1,1,2,1,2]
};
[].forEach.call(document.querySelectorAll("[data-mini]"), function(el){
var p = PATTERNS[el.getAttribute("data-mini")] || PATTERNS.mini;
el.innerHTML = p.map(function(v){ return "<i class='" + (v===2?"on":v===1?"dim":"") + "'></i>"; }).join("");
});
/* ── reserve form ─────────────────────────────────────────
Posts to the site's own /forms/<name> endpoint, which stores the
submission and fires form.submitted. The previous version called
preventDefault and printed a thank-you without sending anything
anywhere, so every reservation was silently thrown away. */
var f = document.getElementById("reserveForm"), errEl = document.getElementById("rerr");
if (f) f.addEventListener("submit", function(e){
e.preventDefault();
var input = f.querySelector("input[type=email]");
var email = (input.value || "").trim();
if (!/^[^@\s]+@[^@\s.]+\.[^@\s]+$/.test(email)){
errEl.textContent = "That email doesn't look right.";
input.focus(); return;
}
errEl.textContent = "";
var tierEl = f.querySelector("input[name=tier]:checked");
var btn = f.querySelector("button");
btn.disabled = true; btn.textContent = "Reserving…";
fetch("/forms/reserve", {
method: "POST",
headers: {"Content-Type":"application/json", "Accept":"application/json"},
body: JSON.stringify({ email: email, tier: tierEl ? tierEl.value : "", source: "preorder.trekmap.co" })
}).then(function(r){
if (!r.ok) throw new Error("http " + r.status);
var card = f.parentNode;
f.outerHTML = "<p class='said'>You're on the list — we'll email " +
email.replace(/[<>&"]/g, "") + " when the first run opens.</p>";
var fp = card.querySelector(".fineprint"); if (fp) fp.textContent = "Reserved. Nothing has been charged.";
}).catch(function(){
btn.disabled = false; btn.textContent = "Reserve";
errEl.innerHTML = "Something went wrong — email <a href='mailto:contact@trekmap.co'>contact@trekmap.co</a> and we'll add you.";
});
});
})();
</script>
</body>
</html>