/* The landing page (index.html): a story you scroll. A pinned stage inside a tall track; the
   scroll position drives every layer (assets/home.js). Only transform and opacity move, so the
   browser can hand the motion to the graphics chip. Loaded after /styles.css. */

:root {
  --pin: #222A1E; --pin-halo: #FFFFFF; --partial: #C9952B; --cat-water: #2F6E8E;
  --map-land: #E3E4DC; --map-land-2: #D8DCCF; --map-forest: #CFD8C6; --map-water: #BFD0D2;
  --map-contour: rgba(58, 70, 52, .13); --map-road: #FAFAF7; --map-road-case: rgba(30, 36, 32, .10);
  --map-label: rgba(30, 36, 32, .55); --map-water-label: rgba(40, 72, 84, .6);
}
@media (prefers-color-scheme: dark) {
  :root {
    --pin: #E8E4DC; --pin-halo: #1C2018;
    --map-land: #23281F; --map-land-2: #262C22; --map-forest: #243021; --map-water: #151D1D;
    --map-contour: rgba(232, 228, 220, .07); --map-road: rgba(232, 228, 220, .16); --map-road-case: rgba(0, 0, 0, .3);
    --map-label: rgba(232, 228, 220, .5); --map-water-label: rgba(150, 190, 200, .45);
  }
}

/* The track: its height is the story's length. It is taller by the footer's height, so the
   stage stays pinned while the footer rises over the last page. 1616vh = home.js's ALL units
   (about 1033vh each) plus one screen: change the two together. */
.track { position: relative; height: calc(1616vh + var(--footH, 0px)); }
/* 100dvh: the visible screen at every moment; the story is placed within 100svh (home.js), so nothing
   moves when a phone's browser bar changes. Safari 26 never draws a pinned stage behind its toolbar; the
   strips there show the page background (html, below), a plain grey by the owner's choice (2026-09-28). */
.stage { position: sticky; top: 0; height: 100vh; height: 100dvh; overflow: hidden; background: var(--bg); }
/* Past the page's end (under a phone browser's toolbar, and the overscroll) the browser paints the
   page's own background: on this page that is the footer's colour, so the footer runs to the edge. */
html { background: var(--surface); }
/* The story's layers sit in main, which JS sizes and shrinks on a short desktop window (layout());
   --vw is 1% of that width, so sizes that follow the width shrink with it. */
.stage > main { position: absolute; left: 0; top: 0; width: 100%; height: 100%; transform-origin: 0 0; }
.el { position: absolute; left: 0; top: 0; will-change: transform, opacity; }

.top { position: absolute; z-index: 20; top: 0; left: 0; right: 0; transition: color .3s ease; }
.top.ondark .brand, .top.ondark .lang-pick summary { color: #F0EEE8; }
.top.ondark .lang-pick summary:hover, .top.ondark .lang-pick[open] summary { background: rgba(240, 238, 232, .14); }

/* Captions: one line at a time, like a keynote slide. */
.cap { position: absolute; left: 0; right: 0; top: var(--capY); padding-inline: var(--gutter); text-align: center; opacity: 0; visibility: hidden; will-change: transform, opacity; pointer-events: none; }
.cap h2 { margin: 0 auto; font-weight: 600; font-size: var(--word); line-height: 1.02; letter-spacing: -0.045em; text-wrap: balance; max-width: 13em; }
.cap h2 em { font-family: var(--font-ed); font-style: italic; font-weight: 400; letter-spacing: -0.02em; }
.cap p { margin: 14px auto 0; font-size: clamp(15.5px, calc(var(--vw, 1vw) * 1.6), 19px); line-height: 1.5; color: var(--ink-soft); max-width: 30em; text-wrap: balance; }
.cap.small h2 { font-size: var(--word2); }
/* Over the drawing the captions turn light; --sceneK (0..1) is how far the scene is in. */
.cap h2, .cap p { color: color-mix(in srgb, #F4F1EA calc(var(--sceneK, 0) * 100%), var(--cap-c, var(--ink))); }
.cap p { --cap-c: var(--ink-soft); }
/* Browsers without color-mix (Safari before 16.2): switch at once instead of blending. */
@supports not (color: color-mix(in srgb, red, blue)) {
  .cap h2 { color: var(--ink); } .cap p { color: var(--ink-soft); }
  .stage.onscene .cap h2 { color: #F4F1EA; } .stage.onscene .cap p { color: rgba(244, 241, 234, .85); }
}

/* Japanese (/ja/): no slanted or squeezed type, and room between the lines for its characters. */
:lang(ja) .cap h2, :lang(ja) .intro h1 { letter-spacing: 0; line-height: 1.25; }
/* Every Japanese character is a full square, so the same size reads bigger and heavier. */
:lang(ja) .cap h2 { font-size: calc(var(--word) * .8); }
:lang(ja) .cap.small h2 { font-size: calc(var(--word2) * .85); }
:lang(ja) .intro h1 { font-size: clamp(32px, calc(var(--vw, 1vw) * 5.8), 76px); }
:lang(ja) .stage.wide .intro h1 { font-size: clamp(36px, calc(var(--vw, 1vw) * 4.2), 62px); }
:lang(ja) .cap h2 em, :lang(ja) .intro h1 em, :lang(ja) .notes { font-style: normal; letter-spacing: 0; }

/* The first view. */
.intro { position: absolute; left: 0; right: 0; top: var(--introY); padding-inline: var(--gutter); text-align: center; display: flex; flex-direction: column; align-items: center; will-change: transform, opacity; }
.intro h1 { margin: 0; font-weight: 600; font-size: clamp(40px, calc(var(--vw, 1vw) * 7.2), 96px); line-height: 1; letter-spacing: -0.045em; text-wrap: balance; max-width: 11em; }
.intro h1 em { font-family: var(--font-ed); font-style: italic; font-weight: 400; letter-spacing: -0.02em; }
.intro p { margin: 18px 0 24px; font-size: clamp(16px, calc(var(--vw, 1vw) * 1.7), 19px); line-height: 1.5; color: var(--ink-soft); max-width: 30em; }
.intro .badges { justify-content: center; }
/* Get the app, on a computer (#872, after the "Get the app (smart)" pattern the owner picked): you
   can't install an app on a computer, so the store badges give way to two buttons: Get the app (opens
   a QR dialog to scan with the phone) and Log in (the web app). On a phone or tablet the badges stay: there
   they install directly. Decided by the pointer, so a touch screen keeps the badges. */
.desk-cta { display: none; gap: 12px; }
.desk-cta .btn { width: auto; min-height: 48px; padding: 12px 24px; }
@media (hover: hover) and (pointer: fine) {
  .intro .badges, .endcta .badges { display: none; }
  .desk-cta { display: flex; }
}
.getapp { width: min(600px, calc(100vw - 32px)); box-sizing: border-box; padding: 0; border: 1px solid var(--line); border-radius: 22px; overflow: hidden;
  background: var(--surface); color: var(--ink); box-shadow: 0 40px 80px -24px rgba(20, 26, 22, .45); }
.ga-in { position: relative; }
.getapp::backdrop { background: rgba(20, 26, 22, .38); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
.getapp[open] { animation: gaIn .28s cubic-bezier(.2, .8, .2, 1); }
@keyframes gaIn { from { opacity: 0; transform: translateY(12px) scale(.98); } to { opacity: 1; transform: none; } }
/* The owner's drawing of Maligne Lake across the top: its sky and snowy peaks (the light part, not the
   trees), a little brighter, fading into the card. */
.ga-hero { position: relative; height: 128px; overflow: hidden; }
.ga-hero img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 44%; filter: brightness(1.08) saturate(.92); }
.ga-hero::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(255, 255, 255, .12), rgba(255, 255, 255, 0) 40%, var(--surface) 100%); }
.ga-close { position: absolute; top: 12px; right: 12px; width: 34px; height: 34px; display: grid; place-items: center; border: 0; border-radius: 50%;
  background: rgba(255, 255, 255, .78); color: #1E2420; cursor: pointer; box-shadow: 0 2px 8px rgba(20, 26, 22, .18); }
.ga-close:hover { background: #fff; }
.ga-close svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 2.2; stroke-linecap: round; }
.ga-main { display: flex; gap: 28px; align-items: center; padding: 4px 32px 32px; margin-top: -40px; position: relative; }
/* The code on a white tile (codes need dark on light), the spotops pin in its middle. */
.ga-qr { position: relative; flex: none; width: 168px; padding: 12px; border-radius: 18px; background: #fff; border: 1px solid var(--line); box-shadow: 0 16px 32px -18px rgba(20, 26, 22, .5); }
.ga-qr img { display: block; width: 100%; height: auto; }
.ga-mark { position: absolute; left: 50%; top: 50%; width: 38px; height: 38px; margin: -19px 0 0 -19px; border-radius: 10px; background: #fff; display: grid; place-items: center; }
.ga-mark svg { width: 19px; height: 27px; color: #1E2420; }
.ga-text { min-width: 0; padding-top: 36px; }
.getapp h2 { margin: 0 0 8px; font-size: 24px; font-weight: 600; letter-spacing: -.5px; line-height: 1.15; }
.ga-body { margin: 0 0 18px; font-size: 14.5px; line-height: 1.5; color: var(--ink-soft); }
.ga-stores { display: flex; flex-wrap: wrap; gap: 8px; }
.ga-stores a { display: inline-flex; border-radius: 9px; }
.ga-stores a:hover { opacity: .9; }
.ga-stores img { display: block; height: 40px; width: auto; }
@media (prefers-reduced-motion: reduce) { .getapp[open] { animation: none; } }
.fine, .intro .fine { font-size: 13px; line-height: 1.4; color: var(--ink-soft); margin: 12px 0 0; }
.stage.wide .intro { left: var(--introX); right: auto; width: var(--introW); padding: 0; text-align: left; align-items: flex-start; }
.stage.wide .intro h1 { font-size: clamp(44px, calc(var(--vw, 1vw) * 5.2), 84px); max-width: none; }
.stage.wide .intro .badges { justify-content: flex-start; }
.stage.wide .rowcap { left: var(--introX); right: auto; text-align: left; }
/* On a computer "See how" is the scroll-on cue: its words, in grey, over a round outlined arrow, centred
   at the foot of the screen (home.js places it). A phone keeps the pill, which sits over the phone's map. */
.stage.wide .seehow {
  flex-direction: column; gap: 12px; padding: 0; background: none; border: 0; box-shadow: none;
  font-size: 15px; font-weight: 500; color: var(--ink-soft);
}
.stage.wide .seehow svg {
  width: 42px; height: 42px; padding: 11px; box-sizing: border-box; border-radius: 50%;
  border: 1.5px solid var(--line-strong); color: var(--ink);
}
.stage.wide .seehow:hover { color: var(--ink); }
.stage.wide .seehow:hover svg { border-color: var(--ink); }
.rowcap { position: absolute; left: 0; right: 0; text-align: center; font-size: 13px; font-weight: 500; letter-spacing: .2px; color: var(--ink-soft); }
.seehow {
  position: absolute; z-index: 3; left: 50%; transform: translateX(-50%); display: inline-flex; align-items: center; gap: 8px;
  font: inherit; font-size: 14px; font-weight: 600; color: var(--ink); background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: 999px; padding: 10px 16px 10px 18px; cursor: pointer; box-shadow: 0 10px 24px -16px rgba(30, 36, 32, .5); white-space: nowrap;
}
.seehow svg { animation: bounce 1.8s ease-in-out infinite; }
@keyframes bounce { 0%, 100% { transform: translateY(-1px); } 50% { transform: translateY(3px); } }

/* The six tools (the onboarding's own glyphs). */
.tile { width: var(--tile); height: var(--tile); margin: calc(var(--tile) / -2) 0 0 calc(var(--tile) / -2); border-radius: 26%; background: var(--surface); border: 1px solid var(--line-strong); display: grid; place-items: center; box-shadow: 0 18px 36px -24px rgba(30, 36, 32, .45); }
.tile svg { width: 46%; height: 46%; stroke: var(--ink); fill: none; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.tile b { position: absolute; top: calc(100% + 10px); left: 50%; transform: translateX(-50%); white-space: nowrap; font-size: 12.5px; font-weight: 500; color: var(--ink-soft); }
.spokes { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
/* At rest on the first view, the six drift a little, each out of step. */
#tiles.resting .tile svg { animation: bob 3.2s ease-in-out infinite alternate; }
#tiles.resting .tile:nth-child(2n) svg { animation-delay: -1.1s; }
#tiles.resting .tile:nth-child(3n) svg { animation-delay: -2.2s; }
@keyframes bob { from { transform: translateY(-2px); } to { transform: translateY(2px); } }
/* On a computer, pointing at one of the six lifts it a little and names it. (`translate` adds to the
   transform home.js sets, and the name's !important outranks the opacity home.js writes.) */
@media (hover: hover) {
  #tiles.resting .tile { transition: translate .25s cubic-bezier(.2, .8, .2, 1), box-shadow .25s ease; }
  #tiles.resting .tile:hover { translate: 0 -6px; box-shadow: 0 26px 40px -22px rgba(30, 36, 32, .5); }
  #tiles.resting .tile b { transition: opacity .2s ease; }
  #tiles.resting .tile:hover b { opacity: 1 !important; }
}

/* The pin and wordmark lockup, sized as on the app's sign-in screen (pin 78 high : wordmark 168 wide). */
.mark { width: var(--mark); margin-left: calc(var(--mark) / -2); transform-origin: 50% 100%; color: var(--ink); }
.mark svg, .word svg { display: block; width: 100%; height: auto; }
.word { width: calc(var(--mark) * 1.4 * 168 / 78); margin-left: calc(var(--mark) * 1.4 * -84 / 78); color: var(--ink); }

/* The map: full-bleed, fading into the page at its edges. */
.map { width: var(--mapS); height: var(--mapS); margin: calc(var(--mapS) / -2) 0 0 calc(var(--mapS) / -2);
  -webkit-mask-image: radial-gradient(closest-side, #000 55%, transparent 100%); mask-image: radial-gradient(closest-side, #000 55%, transparent 100%); }
.map svg { width: 100%; height: 100%; display: block; }
.tint { position: absolute; inset: 0; pointer-events: none; mix-blend-mode: multiply; }

/* The forecast scene: the place itself, played by the forecast clock. */
.scene { position: absolute; inset: 0; overflow: hidden; opacity: 0; visibility: hidden; pointer-events: none; }
.sbox { position: absolute; }
.sbox img { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.sl { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; }
.sky { opacity: 1; -webkit-mask: url(/assets/img/sky-mask.png) 0 0 / 100% 100%; mask: url(/assets/img/sky-mask.png) 0 0 / 100% 100%; }
.warm, .dawn, .night, .alpen { -webkit-mask: url(/assets/img/land-mask.png) 0 0 / 100% 100%; mask: url(/assets/img/land-mask.png) 0 0 / 100% 100%; }
.warm { background: linear-gradient(180deg, #FF8A4C 0%, #FFB27A 45%, rgba(255, 178, 122, .35) 100%); mix-blend-mode: soft-light; }
.alpen { background: linear-gradient(180deg, #FF8F8A 0%, #FFB09A 22%, rgba(255, 176, 154, 0) 42%); mix-blend-mode: screen; }
.dawn { background: linear-gradient(180deg, #E9A2B4 0%, #FFD2A8 45%, rgba(255, 210, 168, 0) 85%); mix-blend-mode: soft-light; }
.night { background: linear-gradient(180deg, #1A2A4E 0%, #0E1A34 55%, #0A1428 100%); mix-blend-mode: multiply; }
.nstars, .aur { -webkit-mask: url(/assets/img/sky-mask.png) 0 0 / 100% 100%; mask: url(/assets/img/sky-mask.png) 0 0 / 100% 100%; }
.aur { mix-blend-mode: screen; overflow: hidden; }
/* The curtains are a picture, blurred ahead of time (assets/img/aurora.webp, drawn by
   spotops-site-src/aurora.mjs): a blur drawn live stalled phones every time the aurora came on
   (Safari redraws it from scratch each time the hidden layer is shown). The sway moves the finished picture, a plain transform the graphics
   chip does without redrawing anything. The layer overhangs the sky (so the blur never shows an edge)
   and the picture's drawing overhangs by the same amount (aurora.mjs's viewBox), so the curtains sit
   exactly where they would at inset 0. Change one, change both. */
.aur-sway { position: absolute; inset: -4% -6%; will-change: transform; animation: sway 9s ease-in-out infinite alternate; transform-origin: 50% 0; }
.aur-sway img { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
@keyframes sway { from { transform: translateX(-1.5%) skewX(-2deg); } to { transform: translateX(1.5%) skewX(2deg); } }
.glow { top: var(--water, 81%); height: auto; background: linear-gradient(180deg, rgba(90, 240, 170, .55), rgba(90, 240, 170, 0) 70%); mix-blend-mode: screen; }
.ripple { top: var(--water, 81%); height: auto; -webkit-backdrop-filter: blur(2.6px); backdrop-filter: blur(2.6px); }
.ripple svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.scrim { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(8, 12, 10, .5) 0%, rgba(8, 12, 10, 0) 38%); }

/* The spot card. */
.spotcard { width: var(--cardW); border-radius: 24px; background: var(--surface); border: 1px solid var(--line); box-shadow: 0 30px 60px -30px rgba(30, 36, 32, .5); overflow: hidden; }
.panes { position: relative; height: var(--cardH); }
.pane { position: absolute; inset: 0; padding: 14px 16px 16px; display: flex; flex-direction: column; gap: 9px; }
.photo { height: 38%; margin: -14px -16px 2px; overflow: hidden; }
.photo img, .sthumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.over { font-size: 10.5px; font-weight: 600; letter-spacing: 1.5px; text-transform: uppercase; color: var(--ink-soft); display: flex; align-items: center; gap: 6px; }
.over i { width: 7px; height: 7px; border-radius: 50%; background: var(--cat-water); }
.nm { font-family: var(--font-ed); font-weight: 500; font-size: 22px; letter-spacing: -.4px; line-height: 1.1; }
.meta { font-size: 12px; color: var(--ink-soft); font-variant-numeric: tabular-nums; display: flex; gap: 8px; }
.stars { letter-spacing: 2px; font-size: 13px; }
.stars .dim { color: var(--ink-dim); }
.notes { font-family: var(--font-ed); font-style: italic; font-size: 14.5px; line-height: 1.45; color: var(--ink-soft); }
.months { display: flex; gap: 3px; }
.months span { flex: 1; height: 22px; display: grid; place-items: center; border-radius: 6px; font-size: 10.5px; font-weight: 500; border: 1px solid var(--line-strong); color: var(--ink-soft); }
.months span.on { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
#recipe { gap: 10px; }
.set { border: 1px solid var(--line); border-radius: 16px; padding: 10px 12px 11px; display: grid; gap: 8px; background: var(--bg); }
.rhead { display: flex; align-items: center; gap: 10px; }
.rhead .rt { flex: 1; min-width: 0; }
.rhead b { font-size: 15px; font-weight: 600; letter-spacing: -.2px; display: block; line-height: 1.2; }
.rhead small { font-size: 11.5px; color: var(--ink-soft); }
.ti { width: 34px; height: 34px; border-radius: 50%; overflow: hidden; flex: none; display: grid; place-items: center; }
.ti svg { display: block; }
.ti.sm { width: 26px; height: 26px; }
.ring { width: 40px; height: 40px; flex: none; font-family: var(--font-ui); }
.rule { position: relative; display: grid; gap: 5px; }
.rule.req { padding-left: 10px; }
.rule.req::before { content: ""; position: absolute; left: 0; top: 1px; bottom: 1px; width: 3px; border-radius: 2px; background: var(--ink); }
.rule .nv { font-style: normal; color: var(--ink); font-weight: 500; font-variant-numeric: tabular-nums; margin-left: 6px; }
.rule .nv svg { vertical-align: -1px; margin-right: 2px; }
.rule .lab { display: flex; justify-content: space-between; gap: 8px; font-size: 12.5px; }
.rule .lab span:first-child { color: var(--ink-soft); }
.rule .lab b { font-weight: 500; font-variant-numeric: tabular-nums; }
.bar { position: relative; height: 6px; border-radius: 3px; background: var(--surface-alt); }
.bar i { position: absolute; top: 0; bottom: 0; border-radius: 3px; background: var(--accent); transform-origin: left; }
.bar u { position: absolute; top: -3px; width: 3px; height: 12px; margin-left: -1.5px; border-radius: 2px; background: var(--ink); text-decoration: none; }
/* Sharing: the card turns to the people it's shared with. */
.shead { display: flex; align-items: center; gap: 10px; }
.shead b { display: block; font-family: var(--font-ed); font-weight: 500; font-size: 18px; letter-spacing: -.3px; line-height: 1.15; }
.shead small { font-size: 11.5px; color: var(--ink-soft); }
.sthumb { width: 42px; height: 42px; border-radius: 10px; overflow: hidden; flex: none; }
.slink { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-radius: 12px; background: var(--surface-alt); font-size: 12.5px; color: var(--ink-soft); }
.slink span { flex: 1; min-width: 0; font-variant-numeric: tabular-nums; }
.slink em { font-style: normal; font-size: 11.5px; font-weight: 600; color: var(--accent); }
.people { display: grid; gap: 4px; }
.pp { display: flex; align-items: center; gap: 10px; padding: 7px 0; border-bottom: 1px solid var(--line); }
.pp:last-child { border-bottom: 0; }
.av { width: 32px; height: 32px; border-radius: 50%; flex: none; display: grid; place-items: center; color: #fff; font-size: 13px; font-weight: 600; }
.pt { flex: 1; min-width: 0; }
.pt b { display: block; font-size: 13.5px; font-weight: 600; line-height: 1.2; }
.pt small { display: block; font-size: 11px; color: var(--ink-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.own { display: flex; align-items: center; gap: 6px; flex: none; }
.own small { font-size: 11px; font-weight: 500; font-variant-numeric: tabular-nums; color: var(--ink); }

/* The forecast bar, as in the app: a glass capsule, the ruler, and the loop box in the middle. */
.tape { width: var(--tapeW); margin-left: calc(var(--tapeW) / -2); height: 58px; border-radius: 29px; background: var(--glass); border: 1px solid var(--line); -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px); overflow: hidden; }
.ruler { position: absolute; top: 0; bottom: 0; left: 50%; will-change: transform; }
.ruler i { position: absolute; bottom: 13px; width: 1.5px; border-radius: 1px; background: var(--ink-dim); }
.ruler b { position: absolute; top: 8px; font-size: 10px; font-weight: 600; letter-spacing: 1.3px; color: var(--ink-soft); transform: translateX(-50%); }
.nowbox { position: absolute; left: 50%; top: 5px; transform: translateX(-50%); width: 62px; height: 46px; border-radius: 999px; background: var(--surface); border: 1.5px solid var(--accent); display: grid; place-items: center; text-align: center; line-height: 1.1; box-shadow: 0 2px 8px rgba(0, 0, 0, .14); }
.nowbox small { display: block; font-size: 9.5px; font-weight: 600; letter-spacing: 1.3px; text-transform: uppercase; color: var(--accent); margin-bottom: 1px; }
.nowbox b { font-size: 13px; font-weight: 700; letter-spacing: .2px; font-variant-numeric: tabular-nums; color: var(--accent); }

.banner { z-index: 25; width: min(360px, calc(var(--vw, 1vw) * 100 - 32px)); margin-left: calc(min(360px, calc(var(--vw, 1vw) * 100 - 32px)) / -2); padding: 12px 14px; border-radius: 22px; display: grid; grid-template-columns: 38px 1fr auto; gap: 0 10px; align-items: center; background: var(--glass); border: 1px solid var(--line); -webkit-backdrop-filter: blur(22px) saturate(160%); backdrop-filter: blur(22px) saturate(160%); box-shadow: 0 20px 40px -20px rgba(0, 0, 0, .4); }
.banner .ico { grid-row: span 2; width: 38px; height: 38px; border-radius: 9px; background: #1E2420; color: #E8E4DC; display: grid; place-items: center; }
.banner .ico svg { width: 15px; height: 21px; display: block; }
.banner b { font-size: 15px; font-weight: 600; letter-spacing: -.2px; min-width: 0; }
.banner small { font-size: 12.5px; color: var(--ink-soft); justify-self: end; }
.banner > span:last-child { grid-column: 2 / span 2; font-size: 15px; }

.endcta { left: 0; right: 0; top: var(--endY); display: flex; flex-direction: column; align-items: center; gap: 12px; pointer-events: none; }
.endcta.live { pointer-events: auto; }
.endcta .fine { margin: 0; }

.foot { position: absolute; left: 0; right: 0; bottom: 0; z-index: 30; background: var(--surface); border-radius: 24px 24px 0 0; box-shadow: 0 -18px 40px -24px rgba(0, 0, 0, .35); border-top: 1px solid var(--line); }

/* spotops on a computer and a phone (#872): two screens floating in depth, no hardware and no angles
   (owner 2026-10-01: a drawn laptop read like a company selling computers; then the tilt went too, and
   with it the soft text a tilted layer gets). The web app in a browser window at the back, the app's
   map screen in front of it; the depth is the overlap, the shadows and a parallax (the nearer phone moves
   more). The pair is drawn at a fixed size (.hero, 740 x 600; 560 x 600 stacked on a narrow screen) and
   home.js places and scales it as one, and moves the window and the phone (the pointer, the drift as the
   story starts); without script it sits in the page at that size (bottom of this file). */
.hero { position: absolute; left: 0; top: 0; width: 740px; height: 600px; transform-origin: 0 0; will-change: transform, opacity; z-index: 2;
  --ls: .571429; --bshadow: 0 1px 2px rgba(30, 36, 32, .06), 0 12px 24px -8px rgba(30, 36, 32, .12), 0 40px 80px -24px rgba(30, 36, 32, .22), 0 80px 140px -40px rgba(30, 36, 32, .18);
  --pshadow: 0 2px 4px rgba(30, 36, 32, .08), 0 18px 36px -10px rgba(30, 36, 32, .2), 0 50px 90px -20px rgba(30, 36, 32, .32); }
@media (prefers-color-scheme: dark) {
  .hero { --bshadow: 0 1px 2px rgba(0, 0, 0, .3), 0 12px 24px -8px rgba(0, 0, 0, .35), 0 40px 80px -24px rgba(0, 0, 0, .5), 0 80px 140px -40px rgba(0, 0, 0, .45);
    --pshadow: 0 2px 4px rgba(0, 0, 0, .3), 0 18px 36px -10px rgba(0, 0, 0, .45), 0 50px 90px -20px rgba(0, 0, 0, .6); }
}
/* A soft light behind the pair, in the place's own colours (the map's water and the accent). */
.hero::before { content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(48% 42% at 42% 40%, var(--accent-wash), transparent 70%), radial-gradient(40% 36% at 70% 62%, color-mix(in srgb, var(--map-water) 45%, transparent), transparent 70%); }
.screens { position: absolute; inset: 0; }
/* .browser is placed (home.js moves it); .lscr is the window itself (and what rises in on arrival). */
.browser { position: absolute; left: 0; top: 24px; will-change: transform; width: calc(1120px * var(--ls)); height: calc(720px * var(--ls)); }
.lscr { position: absolute; inset: 0; overflow: hidden; border-radius: 12px; background: var(--surface); box-shadow: 0 0 0 1px var(--line-strong), var(--bshadow); }
/* A faint sheen across the glass of both screens. */
.lscr::after, .device .scr::after { content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 8;
  background: linear-gradient(125deg, rgba(255, 255, 255, .16) 0%, rgba(255, 255, 255, 0) 32%); }

/* The web app, drawn at 1120 x 720 (a 44 px browser bar, then the app) and scaled to the window (--ls). */
.linner { position: absolute; left: 0; top: 0; width: 1120px; height: 720px; transform-origin: 0 0; transform: scale(var(--ls));
  background: var(--bg); color: var(--ink); font-size: 14px; line-height: 1.3; }
.linner svg:not(.wm-svg):not(.ring):not(.wa-th) { fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; flex: none; }
.wb-bar { position: relative; height: 44px; display: flex; align-items: center; gap: 22px; padding: 0 18px; background: var(--surface-alt); border-bottom: 1px solid var(--line); }
.wb-dots { display: flex; gap: 8px; }
.wb-dots i { width: 12px; height: 12px; border-radius: 50%; background: #FF5F57; }
.wb-dots i:nth-child(2) { background: #FEBC2E; } .wb-dots i:nth-child(3) { background: #28C840; }
.wb-nav { display: flex; gap: 10px; color: var(--ink-soft); } .wb-nav .dim { opacity: .45; }
.wb-url { position: absolute; left: 50%; top: 8px; width: 380px; margin-left: -190px; height: 28px; border-radius: 9px; background: var(--bg);
  display: flex; align-items: center; justify-content: center; gap: 7px; font-size: 14px; color: var(--ink-soft); }
.wa { display: flex; height: 676px; }
.wa-list { width: 340px; flex: none; display: flex; flex-direction: column; gap: 12px; padding: 16px 12px 0; background: var(--surface); border-right: 1px solid var(--line); overflow: hidden; }
.wa-space { display: flex; align-items: center; gap: 10px; padding: 6px 14px 6px 6px; border-radius: 999px; background: var(--surface-alt); margin: 0 4px; }
.wa-av { width: 30px; height: 30px; border-radius: 50%; background: var(--accent); color: var(--accent-ink); display: grid; place-items: center; font-size: 13px; font-weight: 600; }
.wa-st { flex: 1; display: flex; flex-direction: column; line-height: 1.2; }
.wa-st small { font-size: 10px; font-weight: 600; letter-spacing: 1.2px; text-transform: uppercase; color: var(--ink-soft); }
.wa-st b { font-size: 13px; font-weight: 500; }
.wa-search { display: flex; align-items: center; gap: 10px; height: 44px; padding: 0 10px 0 12px; border-radius: 12px; background: var(--surface-alt); color: var(--ink-soft); margin: 0 4px; }
.wa-search span { flex: 1; } .wa-search kbd { font: inherit; font-size: 11px; border: 1px solid var(--line-strong); border-radius: 5px; padding: 1px 5px; }
.wa-tabs { display: flex; gap: 3px; padding: 3px; border-radius: 12px; background: var(--surface-alt); margin: 0 4px; }
.wa-tabs span { flex: 1; text-align: center; padding: 8px 0; border-radius: 9px; font-size: 13px; font-weight: 500; color: var(--ink-soft); }
.wa-tabs span.on { background: var(--surface); color: var(--ink); box-shadow: 0 1px 3px rgba(30, 36, 32, .14); }
.wa-rows { display: flex; flex-direction: column; padding-top: 4px; border-top: 1px solid var(--line); }
.wa-row { display: flex; align-items: center; gap: 12px; padding: 9px 8px; border-radius: 12px; }
.wa-row.on { background: var(--accent-wash); }
.wa-th { width: 52px; height: 52px; border-radius: 10px; flex: none; object-fit: cover; display: block; }
.wa-rt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.wa-over { display: flex; align-items: center; gap: 6px; font-size: 10px; font-weight: 600; letter-spacing: 1.4px; text-transform: uppercase; color: var(--ink-soft); }
.wa-over i { width: 7px; height: 7px; border-radius: 50%; }
.wa-nm { font-family: var(--font-ed); font-size: 17px; font-weight: 500; letter-spacing: -.2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.wa-sub { font-size: 12px; color: var(--ink-soft); white-space: nowrap; } .wa-sub .st { letter-spacing: 1px; color: var(--ink); } .wa-sub .dim { color: var(--ink-dim); }
.wa-pill { flex: none; font-size: 12px; font-weight: 600; padding: 3px 8px; border-radius: 999px; font-variant-numeric: tabular-nums; }
.wa-pill.good { background: var(--accent); color: var(--accent-ink); }
.wa-pill.mid { background: rgba(201, 149, 43, .2); color: var(--ink); }
.wa-pill.low { background: var(--surface-alt); color: var(--ink-soft); }
.wa-map { position: relative; flex: 1; overflow: hidden; }
.wm-svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.wa-tools { position: absolute; left: 14px; right: 14px; top: 14px; display: flex; justify-content: space-between; }
.wa-filter, .wa-new { display: inline-flex; align-items: center; gap: 7px; height: 36px; padding: 0 14px 0 12px; border-radius: 999px; font-size: 13px; font-weight: 600; box-shadow: 0 4px 14px rgba(30, 36, 32, .14); }
.wa-filter { background: var(--glass); border: 1px solid var(--line); }
.wa-new { background: var(--ink); color: var(--bg); }
.wa-zoom { position: absolute; right: 14px; bottom: 96px; display: flex; flex-direction: column; border-radius: 12px; overflow: hidden; background: var(--glass); box-shadow: 0 6px 16px rgba(30, 36, 32, .16); }
.wa-zoom span { width: 38px; height: 38px; display: grid; place-items: center; } .wa-zoom span + span { border-top: 1px solid var(--line); }
.wa-hover { position: absolute; left: 262px; top: 70px; width: 290px; display: flex; flex-direction: column; gap: 12px; padding: 14px 16px; border-radius: 16px; background: var(--surface); border: 1px solid var(--line); box-shadow: 0 20px 40px -12px rgba(30, 36, 32, .35); }
.wh-top { display: flex; align-items: center; gap: 12px; }
.wh-t { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.wh-nm { font-family: var(--font-ed); font-size: 19px; font-weight: 500; letter-spacing: -.3px; line-height: 1.15; }
.wh-line { font-size: 12px; color: var(--ink-soft); }
.wa-hover .ring { width: 48px; height: 48px; }
.wh-set { display: flex; flex-direction: column; gap: 5px; }
.wh-h { display: flex; justify-content: space-between; font-size: 13px; } .wh-h span { font-weight: 500; } .wh-h b { font-weight: 600; } .wh-h b.dim { color: var(--ink-soft); }
.wh-bar { height: 5px; border-radius: 999px; background: var(--line); } .wh-bar i { display: block; height: 100%; border-radius: inherit; background: var(--accent); }
.wh-bar.mid i { background: var(--partial); }
.wa-tape { position: absolute; left: 50%; bottom: 18px; width: 480px; margin-left: -240px; height: 58px; border-radius: 29px; background: var(--glass); border: 1px solid var(--line); box-shadow: 0 8px 20px rgba(30, 36, 32, .12); overflow: hidden; }
.wa-tape i { position: absolute; bottom: 14px; width: 1.5px; border-radius: 1px; background: var(--ink-dim); }
.wa-day { position: absolute; right: 96px; top: 9px; }
/* The pins, as the web app draws them (positioned by webmap.mjs): a dot and its score. */
.wm-pin { position: absolute; width: 0; height: 0; }
.wm-pin i { position: absolute; left: -9px; top: -9px; width: 18px; height: 18px; box-sizing: border-box; border-radius: 50%; background: var(--accent); border: 3px solid var(--pin-halo); box-shadow: 0 2px 6px rgba(0, 0, 0, .28); }
.wm-pin b { position: absolute; left: 13px; top: -11px; padding: 3px 7px; border-radius: 999px; background: var(--glass); font-size: 11px; font-weight: 600; white-space: nowrap; box-shadow: 0 1px 3px rgba(30, 36, 32, .25); }
.wm-sel i { left: -13px; top: -13px; width: 26px; height: 26px; border-width: 4px; background: var(--ink); box-shadow: 0 0 0 5px var(--accent-wash), 0 3px 8px rgba(0, 0, 0, .3); }
.wm-sel b { left: 18px; background: var(--accent); color: var(--accent-ink); }
.wm-drop i { background: var(--pin); }
.pulse, .ripple { position: absolute; border-radius: 50%; border: 3px solid var(--accent); opacity: 0; pointer-events: none; will-change: transform, opacity; }
.wm-pin .pulse, .wm-pin .ripple { left: -20px; top: -20px; width: 40px; height: 40px; }
/* On the phone's map: the selected pin's pulse around its tip, and the pin that drops in. */
.hp-pulse { width: 36px; height: 36px; margin: -18px 0 0 -18px; z-index: 1; }
.hp-drop { position: absolute; width: 30px; height: 38px; z-index: 1; }
.hp-drop .pinsvg { display: block; opacity: .9; }
.hp-drop .ripple { left: -5px; top: 16px; width: 40px; height: 40px; }

/* The phone: the app's map screen at 393 x 852, scaled to --pwn wide, no frame. It floats in front of
   the window's lower right. */
.herophone { position: absolute; left: 532px; top: 150px; --pwn: 204; width: calc(var(--pwn) * 1px); will-change: transform; }
/* Stacked on a narrow screen the emphasis swaps: the phone, larger, is the picture, and the browser
   window a smaller backdrop behind it. */
@media (max-width: 899px) {
  .hero { width: 560px; height: 600px; --ls: .4107; }
  .browser { top: 18px; }
  .herophone { left: 300px; top: 64px; --pwn: 250; }
  /* The phone covers the right of the map here, so the hover card opens up and left of the pin. */
  .wa-hover { left: 24px; top: 58px; }
}

/* It moves (not with reduce-motion): the window rises into place, then the phone in front of it; a new
   spot drops onto both maps at the same moment, and the selected spot breathes on both, in step. Every
   state at rest is the final one, so with no animation (reduce motion, an old browser) the pair simply
   stands there. The loop pauses once the pair has faded out (.hero.away, home.js). */
@media (prefers-reduced-motion: no-preference) {
  .lscr { animation: rise 1.2s cubic-bezier(.2, .8, .2, 1) .1s both; }
  .herophone .device { animation: risefar 1.3s cubic-bezier(.2, .8, .2, 1) .45s both; }
  .drop { animation: drop .75s cubic-bezier(.3, 1.45, .5, 1) 1.7s both; }
  .ripple { animation: ripple 1.3s ease-out 2.25s both; }
  .pulse { animation: pulse 2.8s ease-out 3.2s infinite; }
  .hero.away .pulse { animation-play-state: paused; }
}
@keyframes rise { from { transform: translateY(28px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes risefar { from { transform: translateY(70px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes drop { from { transform: translateY(-70px); opacity: 0; } 35% { opacity: 1; } to { transform: none; opacity: 1; } }
@keyframes ripple { from { transform: scale(.3); opacity: .8; } to { transform: scale(2.6); opacity: 0; } }
@keyframes pulse { from { transform: scale(.55); opacity: .6; } 75%, to { transform: scale(2.2); opacity: 0; } }
.device { position: relative; width: 100%; aspect-ratio: 393 / 852; }
.device .scr { position: absolute; inset: 0; overflow: hidden; background: var(--bg); border-radius: 14% / 6.5%; box-shadow: 0 0 0 1px var(--line-strong), var(--pshadow, var(--shadow-lg)); }
.device .inner {
  position: absolute; top: 0; left: 0; width: 393px; height: 852px; transform-origin: 0 0;
  transform: scale(calc(var(--pwn, 300) / 393));
  background: var(--bg); color: var(--ink); font-size: 15px; line-height: 1.35; overflow: hidden;
}
.hp-map { position: absolute; inset: 0; width: 393px; height: 852px; }
.ios-status { position: absolute; top: 0; left: 0; right: 0; height: 54px; display: flex; align-items: center; justify-content: space-between; padding: 6px 34px 0 50px; font-size: 17px; font-weight: 600; letter-spacing: -.2px; z-index: 6; }
.ios-icons { display: flex; gap: 6px; align-items: center; }
.ios-icons svg { height: 13px; width: auto; }
.ios-island { position: absolute; top: 11px; left: 50%; width: 126px; height: 37px; margin-left: -63px; border-radius: 20px; background: #000; z-index: 7; }
.ios-home { position: absolute; bottom: 8px; left: 50%; width: 139px; height: 5px; margin-left: -70px; border-radius: 3px; background: var(--ink); opacity: .85; z-index: 7; }
.overline { font-size: 10px; font-weight: 600; letter-spacing: 1.5px; text-transform: uppercase; color: var(--ink-soft); }
.gl { background: var(--glass); -webkit-backdrop-filter: blur(18px) saturate(150%); backdrop-filter: blur(18px) saturate(150%); border: 1px solid var(--line); }
.inner svg:not(.hp-map):not(.ring) { fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.inner .ios-icons svg { stroke: none; }
.hp-space, .hp-search { position: absolute; top: 63px; height: 46px; border-radius: 999px; display: flex; align-items: center; z-index: 5; white-space: nowrap; }
.hp-space { left: 13px; width: 136px; padding: 0 10px 0 13px; gap: 7px; font-size: 14.5px; font-weight: 500; }
.hp-space span { flex: 1; }
.hp-space .dim { color: var(--ink-soft); }
.hp-search { left: 155px; right: 12px; padding: 0 5px 0 14px; gap: 9px; font-size: 15px; color: var(--ink-soft); }
.hp-search > span:first-of-type { flex: 1; }
.hp-filter { width: 36px; height: 36px; border-radius: 50%; display: grid; place-items: center; border: 1px solid var(--line-strong); color: var(--ink); }
.hp-seg { position: absolute; left: 13px; right: 12px; top: 120px; height: 40px; padding: 3px; border-radius: 999px; display: flex; z-index: 5; }
.hp-seg span { flex: 1; display: flex; align-items: center; justify-content: center; gap: 7px; height: 34px; border-radius: 999px; font-size: 14.5px; font-weight: 500; color: var(--ink-soft); }
.hp-seg span.on { background: var(--surface); color: var(--ink); box-shadow: 0 2px 8px -3px rgba(0, 0, 0, .25); }
.hp-round { position: absolute; right: 13px; width: 45px; height: 45px; border-radius: 50%; display: grid; place-items: center; z-index: 5; }
.hp-card { position: absolute; left: 14px; right: 14px; bottom: 112px; padding: 12px; border-radius: 20px; background: var(--surface); border: 1px solid var(--line); box-shadow: 0 14px 30px -16px rgba(0, 0, 0, .45); display: flex; gap: 12px; align-items: center; z-index: 5; }
.hp-thumb { width: 52px; height: 52px; border-radius: 12px; overflow: hidden; flex: none; }
.hp-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.hp-text { flex: 1; min-width: 0; }
.hp-text .overline { display: flex; align-items: center; gap: 6px; }
.hp-text .overline i { width: 7px; height: 7px; border-radius: 50%; background: var(--cat-water); }
.hp-name { font-family: var(--font-ed); font-size: 19px; font-weight: 500; letter-spacing: -.2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hp-line { font-size: 12.5px; color: var(--ink-soft); }
.hp-score { flex: none; padding: 5px 10px; border-radius: 999px; background: var(--accent); color: var(--accent-ink); font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
.hp-tape { position: absolute; left: 10px; right: 10px; bottom: 40px; height: 58px; border-radius: 29px; overflow: hidden; z-index: 5; }
.hp-tape i { position: absolute; bottom: 14px; width: 1.5px; border-radius: 1px; background: var(--ink-dim); }
.hp-day { position: absolute; right: 40px; top: 9px; }
.hp-loop { position: absolute; left: 50%; top: 5px; transform: translateX(-50%); width: 62px; height: 46px; border-radius: 999px; background: var(--surface); border: 1.5px solid var(--accent); display: grid; place-items: center; text-align: center; line-height: 1.1; box-shadow: 0 2px 8px rgba(0, 0, 0, .14); color: var(--accent); }
.hp-loop small { font-size: 9.5px; font-weight: 600; letter-spacing: 1.3px; text-transform: uppercase; display: block; }
.hp-loop b { font-size: 13px; font-weight: 700; letter-spacing: .2px; font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
  .aur-sway, .seehow svg, #tiles.resting .tile svg { animation: none; }
  #tiles.resting .tile, #tiles.resting .tile b { transition: none; }
}

/* Without script (or on a phone held sideways, index.html): no story, just the page read top to bottom. ------------------------------ */
html:not(.js) .track { height: auto; }
html:not(.js) .stage { position: relative; height: auto; overflow: visible; }
html:not(.js) .stage > main { position: static; width: auto; height: auto; display: flex; flex-direction: column; }
html:not(.js) .intro { order: 1; } html:not(.js) .hero { order: 2; } html:not(.js) #caps { order: 3; } html:not(.js) .endcta { order: 4; }
html:not(.js) .top { position: relative; }
html:not(.js) .el:not(.endcta), html:not(.js) .scene, html:not(.js) .tint, html:not(.js) .spokes,
html:not(.js) #tiles, html:not(.js) .rowcap, html:not(.js) .seehow { display: none; }
html:not(.js) .intro, html:not(.js) .cap, html:not(.js) .endcta, html:not(.js) .hero { position: relative; top: auto; opacity: 1; visibility: visible; }
html:not(.js) .intro { padding-top: 48px; }
/* The computer and the phone at their drawn size, zoomed down to fit a narrower page (zoom, since a
   transform would leave their full size in the flow). */
html:not(.js) .hero { margin: 48px auto 24px; flex: none; }
@media (max-width: 899px) { html:not(.js) .hero { zoom: .8; } }
@media (max-width: 599px) { html:not(.js) .hero { zoom: .56; } }
@media (max-width: 400px) { html:not(.js) .hero { zoom: .5; } }
html:not(.js) .cap { margin: 64px 0; --word: clamp(36px, 7vw, 72px); --word2: clamp(28px, 5vw, 52px); }
html:not(.js) .endcta { margin: 0 0 80px; }
html:not(.js) .foot { position: relative; }
