459 lines
34 KiB
HTML
459 lines
34 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>TrekMap — Wish It. Time It. Make It Happen.</title>
|
||
<meta name="description" content="A travel bucket list that lives on a world map — and an LED map on your wall that glows with everywhere you've been and everywhere you're going.">
|
||
<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='16' r='6' fill='%23E6B800'/%3E%3Ccircle cx='7' cy='9' r='2' fill='%23E6B800' opacity='.5'/%3E%3Ccircle cx='25' cy='23' r='2' fill='%23E6B800' opacity='.5'/%3E%3C/svg%3E">
|
||
<meta property="og:title" content="TrekMap">
|
||
<meta property="og:description" content="A travel bucket list you can hang on the wall.">
|
||
<style>
|
||
:root{
|
||
--midnight:#001F3F; --nightsky:#0B192C; --deep:#00162e;
|
||
--gold:#E6B800; --gold-soft:#f0cf4d; --mahogany:#6F4E37; --jungle:#1B4332;
|
||
--ink:#F4F1EA; --muted:#8FA3B8; --line:rgba(230,184,0,.16);
|
||
--max:1120px;
|
||
}
|
||
*,*::before,*::after{box-sizing:border-box}
|
||
html{scroll-behavior:smooth}
|
||
body{
|
||
margin:0; background:var(--midnight); color:var(--ink);
|
||
font:16px/1.65 ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
|
||
-webkit-font-smoothing:antialiased; overflow-x:hidden;
|
||
}
|
||
h1,h2,h3{line-height:1.08; letter-spacing:-.025em; margin:0; font-weight:700}
|
||
p{margin:0}
|
||
a{color:var(--gold); text-decoration:none}
|
||
a:focus-visible,button:focus-visible,summary:focus-visible{outline:2px solid var(--gold); outline-offset:3px; border-radius:6px}
|
||
.wrap{max-width:var(--max); margin:0 auto; padding:0 24px}
|
||
.eyebrow{font-size:.72rem; letter-spacing:.18em; text-transform:uppercase; color:var(--gold); font-weight:700}
|
||
.lede{color:var(--muted); font-size:1.08rem; max-width:34em}
|
||
|
||
/* ── nav ── */
|
||
header{position:fixed; inset:0 0 auto; z-index:50; backdrop-filter:blur(12px);
|
||
background:rgba(0,31,63,.72); border-bottom:1px solid rgba(255,255,255,.06)}
|
||
nav{display:flex; align-items:center; gap:28px; max-width:var(--max); margin:0 auto; padding:14px 24px}
|
||
.brand{display:flex; align-items:center; gap:10px; font-weight:800; letter-spacing:-.02em; font-size:1.05rem}
|
||
.brand i{width:10px; height:10px; border-radius:50%; background:var(--gold); box-shadow:0 0 12px var(--gold); display:block}
|
||
nav .links{display:flex; gap:24px; margin-left:auto; font-size:.9rem; color:var(--muted)}
|
||
nav .links a:hover{color:var(--ink)}
|
||
.btn{display:inline-block; background:var(--gold); color:#00162e; font-weight:700;
|
||
padding:11px 20px; border-radius:10px; border:0; cursor:pointer; font-size:.92rem;
|
||
transition:transform .15s ease, box-shadow .2s ease}
|
||
.btn:hover{transform:translateY(-1px); box-shadow:0 8px 26px rgba(230,184,0,.28)}
|
||
.btn.ghost{background:transparent; color:var(--ink); border:1px solid rgba(255,255,255,.18)}
|
||
.btn.ghost:hover{border-color:var(--gold); color:var(--gold); box-shadow:none}
|
||
|
||
/* ── hero ── */
|
||
.hero{position:relative; min-height:100svh; display:grid; align-items:center; padding:120px 0 80px; isolation:isolate}
|
||
#led{position:absolute; inset:0; width:100%; height:100%; z-index:-1; opacity:.95}
|
||
.hero::after{content:""; position:absolute; inset:0; z-index:-1; pointer-events:none;
|
||
background:radial-gradient(120% 90% at 18% 45%, rgba(0,22,46,.94) 0%, rgba(0,22,46,.72) 38%, transparent 72%)}
|
||
.hero-inner{max-width:38rem}
|
||
.hero h1{font-size:clamp(2.6rem,6.4vw,4.4rem); margin:18px 0 20px}
|
||
.hero h1 em{font-style:normal; color:var(--gold); display:block}
|
||
.cta-row{display:flex; gap:12px; flex-wrap:wrap; margin-top:32px}
|
||
.hint{margin-top:26px; font-size:.82rem; color:#5f7590; display:flex; align-items:center; gap:8px}
|
||
.hint b{color:var(--gold); font-weight:600}
|
||
|
||
/* ── sections ── */
|
||
section{padding:104px 0; scroll-margin-top:72px; border-top:1px solid rgba(255,255,255,.05)}
|
||
.sec-head{max-width:40rem; margin-bottom:52px}
|
||
.sec-head h2{font-size:clamp(1.9rem,4vw,2.7rem); margin:14px 0 14px}
|
||
|
||
.steps{display:grid; grid-template-columns:repeat(auto-fit,minmax(250px,1fr)); gap:20px}
|
||
.step{background:linear-gradient(180deg,var(--nightsky),rgba(11,25,44,.4));
|
||
border:1px solid var(--line); border-radius:16px; padding:28px; position:relative; overflow:hidden}
|
||
.step .n{font-size:.72rem; letter-spacing:.16em; color:var(--mahogany); font-weight:800}
|
||
.step h3{font-size:1.22rem; margin:10px 0 10px; color:var(--gold)}
|
||
.step p{color:var(--muted); font-size:.95rem}
|
||
.step::after{content:""; position:absolute; right:-40px; top:-40px; width:120px; height:120px;
|
||
background:radial-gradient(circle,rgba(230,184,0,.14),transparent 68%)}
|
||
|
||
/* ── pipeline ── */
|
||
.pipe{display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:12px; margin-top:8px}
|
||
.pipe div{background:var(--deep); border:1px solid rgba(255,255,255,.07); border-radius:12px;
|
||
padding:18px 16px; font-size:.86rem; color:var(--muted)}
|
||
.pipe div b{display:block; color:var(--ink); font-size:.95rem; margin-bottom:4px}
|
||
.pipe div span{color:var(--gold); font-size:.7rem; letter-spacing:.14em; font-weight:800}
|
||
|
||
/* ── hardware ── */
|
||
.skus{display:grid; grid-template-columns:repeat(auto-fit,minmax(280px,1fr)); gap:20px; align-items:stretch}
|
||
.sku{background:var(--nightsky); border:1px solid var(--line); border-radius:18px; padding:28px; position:relative; display:flex; flex-direction:column; height:100%}
|
||
.sku.featured{border-color:var(--gold); box-shadow:0 0 0 1px var(--gold), 0 24px 60px -30px rgba(230,184,0,.5)}
|
||
.sku .tag{position:absolute; top:-11px; left:28px; background:var(--gold); color:#00162e;
|
||
font-size:.66rem; font-weight:800; letter-spacing:.12em; padding:4px 10px; border-radius:100px}
|
||
.sku h3{font-size:1.3rem}
|
||
.sku .price{font-size:2.4rem; font-weight:800; margin:12px 0 2px; letter-spacing:-.03em}
|
||
.sku .price small{font-size:.8rem; font-weight:600; color:var(--muted); letter-spacing:0}
|
||
.sku p{color:var(--muted); font-size:.92rem; margin:12px 0 18px}
|
||
.sku ul{list-style:none; padding:0; margin:0 0 22px; flex:1 0 auto; font-size:.88rem; color:#B7C6D6}
|
||
.sku li{padding:7px 0 7px 22px; position:relative; border-top:1px solid rgba(255,255,255,.05)}
|
||
.sku .btn{margin-top:auto; text-align:center}
|
||
.sku li::before{content:"◆"; position:absolute; left:0; color:var(--gold); font-size:.62rem; top:9px}
|
||
.mini{display:grid; grid-template-columns:repeat(14,1fr); gap:3px; margin-bottom:20px}
|
||
.mini i{aspect-ratio:1; border-radius:50%; background:rgba(255,255,255,.07)}
|
||
.mini i.on{background:var(--gold); box-shadow:0 0 7px rgba(230,184,0,.85)}
|
||
.mini i.dim{background:rgba(230,184,0,.32)}
|
||
|
||
/* ── specs ── */
|
||
.specs{display:grid; grid-template-columns:repeat(auto-fit,minmax(180px,1fr)); gap:1px; background:rgba(255,255,255,.07);
|
||
border:1px solid rgba(255,255,255,.07); border-radius:16px; overflow:hidden}
|
||
.specs div{background:var(--midnight); padding:26px 22px}
|
||
.specs b{display:block; font-size:1.7rem; font-weight:800; color:var(--gold); letter-spacing:-.02em}
|
||
.specs span{font-size:.84rem; color:var(--muted)}
|
||
|
||
/* ── faq ── */
|
||
details{border-bottom:1px solid rgba(255,255,255,.08); padding:18px 0}
|
||
summary{cursor:pointer; font-weight:600; list-style:none; display:flex; justify-content:space-between; gap:16px; align-items:center}
|
||
summary::-webkit-details-marker{display:none}
|
||
summary::after{content:"+"; color:var(--gold); font-size:1.3rem; line-height:1; flex:none}
|
||
details[open] summary::after{content:"–"}
|
||
details p{color:var(--muted); font-size:.94rem; margin-top:12px; max-width:52em}
|
||
|
||
/* ── final cta ── */
|
||
.final{text-align:center; background:
|
||
radial-gradient(80% 120% at 50% 0%, rgba(230,184,0,.1), transparent 62%), var(--deep)}
|
||
.final h2{font-size:clamp(2rem,4.6vw,3rem); margin-bottom:16px}
|
||
.final .lede{margin:0 auto 30px}
|
||
form.reserve{display:flex; gap:10px; justify-content:center; flex-wrap:wrap; max-width:30rem; margin:0 auto}
|
||
form.reserve input{flex:1 1 220px; background:var(--nightsky); border:1px solid rgba(255,255,255,.16);
|
||
color:var(--ink); padding:13px 16px; border-radius:10px; font-size:.98rem; font-family:inherit}
|
||
form.reserve input::placeholder{color:#5f7590}
|
||
.said{color:var(--gold); font-weight:600}
|
||
|
||
footer{padding:44px 0; border-top:1px solid rgba(255,255,255,.06); color:#5f7590; font-size:.86rem}
|
||
.foot{display:flex; gap:18px; flex-wrap:wrap; align-items:center}
|
||
.foot .sp{margin-left:auto}
|
||
|
||
/* ── reveal ── */
|
||
.rev{opacity:1}
|
||
html.js .rev{opacity:0; transform:translateY(18px); transition:opacity .7s ease, transform .7s ease}
|
||
html.js .rev.in{opacity:1; transform:none}
|
||
@media (prefers-reduced-motion:reduce){
|
||
html.js .rev{opacity:1; transform:none; transition:none}
|
||
html{scroll-behavior:auto}
|
||
}
|
||
@media (max-width:720px){
|
||
nav .links{display:none}
|
||
nav .btn{margin-left:auto}
|
||
.hint{flex-wrap:wrap; row-gap:4px}
|
||
.hint .touch-hide{display:none}
|
||
section{padding:76px 0}
|
||
.sku p{min-height:0}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<header>
|
||
<nav>
|
||
<span class="brand"><i></i>TrekMap</span>
|
||
<span class="links">
|
||
<a href="#loop">The loop</a>
|
||
<a href="#ingest">Reel ingest</a>
|
||
<a href="#hardware">Hardware</a>
|
||
<a href="#faq">FAQ</a>
|
||
</span>
|
||
<a class="btn" href="#reserve">Reserve</a>
|
||
</nav>
|
||
</header>
|
||
|
||
<main>
|
||
<section class="hero">
|
||
<canvas id="led" aria-hidden="true"></canvas>
|
||
<div class="wrap hero-inner">
|
||
<span class="eyebrow">Pre-order · first production run</span>
|
||
<h1>Hang your travels <em>on the wall.</em></h1>
|
||
<p class="lede">TrekMap is 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. One list, two places:
|
||
your phone and your wall.</p>
|
||
<div class="cta-row">
|
||
<a class="btn" href="#reserve">Reserve a unit</a>
|
||
<a class="btn ghost" href="https://trekmap.co">Open the app</a>
|
||
</div>
|
||
<p class="hint"><b>●</b> bright = been there <span aria-hidden="true"> · </span> <b style="opacity:.45">●</b> dim = on the list <span class="touch-hide"> · move your cursor across the map</span></p>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="loop">
|
||
<div class="wrap">
|
||
<div class="sec-head rev">
|
||
<span class="eyebrow">How it works</span>
|
||
<h2>Wish it. Time it. Make it happen.</h2>
|
||
<p class="lede">Most travel apps are a log of where you’ve been. TrekMap is built around
|
||
the part that comes first — wanting to go.</p>
|
||
</div>
|
||
<div class="steps">
|
||
<article class="step rev"><span class="n">01 / WISH IT</span><h3>Save it in one tap</h3>
|
||
<p>Share an Instagram or TikTok reel straight from your phone. TrekMap watches the video,
|
||
reads the signs and the audio, works out the actual place, and files it with a cover photo.</p></article>
|
||
<article class="step rev"><span class="n">02 / TIME IT</span><h3>See it build up</h3>
|
||
<p>Countries glow by how badly you want to go. Explorer Mode splits 57 countries into
|
||
states, prefectures and nations, so progress is honest instead of a flag count.</p></article>
|
||
<article class="step rev"><span class="n">03 / MAKE IT HAPPEN</span><h3>Go, and light it up</h3>
|
||
<p>Flight-price thresholds nudge you when it’s time to book. Log the trip and the
|
||
country turns bright — in the app, and on the map on your wall.</p></article>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="ingest">
|
||
<div class="wrap">
|
||
<div class="sec-head rev">
|
||
<span class="eyebrow">The part nobody else does</span>
|
||
<h2>Share a reel. Get a pin.</h2>
|
||
<p class="lede">A 20-second clip of a restaurant with no caption and no tag still becomes a
|
||
real, mapped, searchable place.</p>
|
||
</div>
|
||
<div class="pipe rev">
|
||
<div><span>01</span><b>Download</b>Pulls the video and audio from the share sheet.</div>
|
||
<div><span>02</span><b>Scene detect</b>Splits it into frames worth reading.</div>
|
||
<div><span>03</span><b>Read it</b>Vision model reads signage; Whisper reads the voiceover.</div>
|
||
<div><span>04</span><b>Decide</b>Picks the actual venue, drops "a city over a close-up".</div>
|
||
<div><span>05</span><b>Enrich</b>Captions, embeds and geocodes it, then finds a cover photo.</div>
|
||
</div>
|
||
<p class="lede rev" style="margin-top:26px">Every saved spot is embedded as a vector, so you can
|
||
search your own list by vibe — “quiet places near water” — not just by name.</p>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="hardware">
|
||
<div class="wrap">
|
||
<div class="sec-head rev">
|
||
<span class="eyebrow">The hardware line</span>
|
||
<h2>Your list, in the room with you.</h2>
|
||
<p class="lede">Individually addressable LEDs, one per country or region, synced live from the
|
||
same account. Wishlist glows dim; visited burns bright.</p>
|
||
</div>
|
||
<div class="skus">
|
||
<article class="sku rev">
|
||
<div class="mini" data-mini="mini" aria-hidden="true"></div>
|
||
<h3>TrekMap Mini</h3>
|
||
<div class="price">$99 <small>pre-order</small></div>
|
||
<p>Picture-frame sized. Sits on a desk or a workbench and still shows the whole picture.</p>
|
||
<ul><li>Continental US, Canada, Mexico</li><li>One LED per state or region</li><li>WiFi or USB sync</li></ul>
|
||
<a class="btn ghost" href="#reserve">Reserve — $99</a>
|
||
</article>
|
||
<article class="sku featured rev">
|
||
<span class="tag">MOST POPULAR</span>
|
||
<div class="mini" data-mini="wall" aria-hidden="true"></div>
|
||
<h3>TrekMap</h3>
|
||
<div class="price">$199 <small>pre-order</small></div>
|
||
<p>The wall map. Laser-cut cell geometry, one lit cell per state, province and region.</p>
|
||
<ul><li>US, Canada, Mexico + islands</li><li>Laser-cut / 3D-printed cells</li><li>Live sync from the app</li></ul>
|
||
<a class="btn" href="#reserve">Reserve — $199</a>
|
||
</article>
|
||
<article class="sku rev">
|
||
<div class="mini" data-mini="globe" aria-hidden="true"></div>
|
||
<h3>TrekGlobe</h3>
|
||
<div class="price">$399 <small>pre-order</small></div>
|
||
<p>A full world globe on a walnut base with a brass meridian ring. Every country addressable.</p>
|
||
<ul><li>Per-country LEDs, whole planet</li><li>Walnut base, brass meridian</li><li>Librarian’s Midnight glass</li></ul>
|
||
<a class="btn ghost" href="#reserve">Reserve — $399</a>
|
||
</article>
|
||
</div>
|
||
<p class="hint rev" style="margin-top:28px">None of the three have shipped yet. Reserving costs
|
||
nothing today and holds your place in the first run at the launch price.</p>
|
||
</div>
|
||
</section>
|
||
|
||
<section>
|
||
<div class="wrap">
|
||
<div class="specs rev">
|
||
<div><b>57</b><span>Countries split to region level</span></div>
|
||
<div><b>3</b><span>Hardware form factors</span></div>
|
||
<div><b>ESP32-S3</b><span>Firmware on every unit</span></div>
|
||
<div><b>Zero</b><span>Paid map APIs — OpenStreetMap only</span></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="faq">
|
||
<div class="wrap" style="max-width:52rem">
|
||
<div class="sec-head rev"><span class="eyebrow">Questions</span><h2>Straight answers.</h2></div>
|
||
<div class="rev">
|
||
<details open><summary>Is the hardware shipping?</summary>
|
||
<p>Not yet — all three units are pre-launch. Reserving puts you in the first production
|
||
run at the launch price, and you’re not charged until it ships.</p></details>
|
||
<details><summary>Does the app work without buying hardware?</summary>
|
||
<p>Yes. The app at trekmap.co is the product; the LED map is a physical view of the same
|
||
data. Plenty of people will only ever use the app.</p></details>
|
||
<details><summary>Who can see my travel list?</summary>
|
||
<p>Only you, and friends you accept. Boards are private by default. You can publish an
|
||
individual spot to a public feed if you want to share one — notes, reminders and price
|
||
thresholds never leave your account.</p></details>
|
||
<details><summary>What if a reel is ambiguous?</summary>
|
||
<p>It gets dropped rather than guessed. A city-wide pin attached to a close-up of a plate
|
||
isn’t useful, so the pipeline throws those away instead of cluttering your map.</p></details>
|
||
<details><summary>How does the map know what I’ve visited?</summary>
|
||
<p>Your passport is a separate list from your wishes, so marking somewhere visited doesn’t
|
||
create an empty wish or change the glow. The hardware polls the same account and lights up to match.</p></details>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="final" id="reserve">
|
||
<div class="wrap">
|
||
<span class="eyebrow">Pre-order</span>
|
||
<h2 class="rev">Get in the first run.</h2>
|
||
<p class="lede rev">Leave an email. We’ll tell you the moment the run opens — no charge,
|
||
no newsletter, no other use for the address.</p>
|
||
<form class="reserve rev" id="reserveForm" novalidate>
|
||
<input type="email" name="email" placeholder="you@example.com" aria-label="Email address" required>
|
||
<button class="btn" type="submit">Reserve my unit</button>
|
||
</form>
|
||
<p class="hint rev" style="justify-content:center; margin-top:18px">
|
||
Or just email <a href="mailto:hello.trekmap@corben.world">hello.trekmap@corben.world</a></p>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<footer>
|
||
<div class="wrap foot">
|
||
<span class="brand" style="font-size:.95rem"><i></i>TrekMap</span>
|
||
<span>A travel bucket list you can hang on the wall.</span>
|
||
<span class="sp"><a href="https://trekmap.co">trekmap.co</a></span>
|
||
</div>
|
||
</footer>
|
||
<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 the reveal animation only now that JS is definitely running — without
|
||
// this, a script failure would leave the page's content invisible.
|
||
if (!reduce) document.documentElement.classList.add("js");
|
||
|
||
/* ── scroll reveal ─────────────────────────────────────────────── */
|
||
var revs = 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*70); io.unobserve(e.target); }
|
||
});
|
||
},{threshold:.14, rootMargin:"0px 0px -40px 0px"});
|
||
revs.forEach(function(el){ io.observe(el); });
|
||
// Safety net: anything the observer somehow misses still becomes visible.
|
||
setTimeout(function(){ revs.forEach(function(el){
|
||
if (el.getBoundingClientRect().top < innerHeight*2) el.classList.add("in");
|
||
}); }, 2500);
|
||
} else { revs.forEach(function(el){ el.classList.add("in"); }); }
|
||
|
||
/* ── LED world map ─────────────────────────────────────────────────
|
||
MASK is the real Natural Earth country geometry from the TrekMap
|
||
repo, rasterised to a MASK_W x MASK_H grid. Each land cell becomes
|
||
one addressable "LED", exactly like the physical product. */
|
||
var MASK = window.__TREKMAP_MASK__, MASK_W = 150, MASK_H = 66;
|
||
var cv = document.getElementById("led");
|
||
if (!cv || !MASK) return;
|
||
var ctx = cv.getContext("2d", {alpha:true});
|
||
|
||
var cells = []; // {gx,gy,state} state: 0 off, 1 wished, 2 visited
|
||
var 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});
|
||
}
|
||
}
|
||
// A believable travel history: a scatter of visited, a wider scatter wished.
|
||
function seed(){
|
||
cells.forEach(function(c){ c.s = 0; });
|
||
for (var i=0;i<cells.length;i++){
|
||
var r = Math.random();
|
||
if (r < 0.055) cells[i].s = 2;
|
||
else if (r < 0.20) cells[i].s = 1;
|
||
}
|
||
}
|
||
seed();
|
||
|
||
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 grid, biased right so the copy on the left sits over empty ocean.
|
||
var scale = Math.max(cw/(MASK_W*0.86), ch/(MASK_H*1.5));
|
||
gap = Math.max(scale, 4.2);
|
||
dot = Math.max(gap*0.30, 1.15);
|
||
ox = cw - MASK_W*gap*0.94; oy = (ch - MASK_H*gap)/2;
|
||
if (ox > cw*0.12) ox = cw*0.12;
|
||
}
|
||
layout();
|
||
addEventListener("resize", layout);
|
||
|
||
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 t = 0;
|
||
function frame(){
|
||
t += 0.016;
|
||
ctx.clearRect(0,0,cw,ch);
|
||
var reach = Math.max(gap*7, 90), 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 base = c.s === 2 ? 0.92 : c.s === 1 ? 0.30 : 0.085;
|
||
// wished cells breathe slowly, like the real firmware's idle pulse
|
||
if (c.s === 1 && !reduce) base += Math.sin(t*1.1 + c.p)*0.085;
|
||
|
||
// cursor acts like a hand passing over the physical map
|
||
var dx = px-mx, dy = py-my, d2 = dx*dx+dy*dy;
|
||
if (d2 < reach2){ base += (1 - d2/reach2)*0.55; }
|
||
|
||
if (base <= 0.02) continue;
|
||
var a = base > 1 ? 1 : base;
|
||
var warm = c.s === 2 || base > 0.6;
|
||
ctx.beginPath();
|
||
ctx.arc(px, py, dot*(warm ? 1.22 : 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){ // one static paint, no loop
|
||
mx = my = -9999; t = 0;
|
||
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 = "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]
|
||
};
|
||
document.querySelectorAll("[data-mini]").forEach(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 ───────────────────────────────────────────────── */
|
||
var f = document.getElementById("reserveForm");
|
||
if (f) f.addEventListener("submit", function(e){
|
||
e.preventDefault();
|
||
var v = f.querySelector("input").value.trim();
|
||
if (!v || v.indexOf("@") < 1){ f.querySelector("input").focus(); return; }
|
||
f.innerHTML = "<p class='said'>You’re on the list — we’ll email " + v.replace(/[<>&]/g,"") + " when the run opens.</p>";
|
||
});
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|