/* =========================================================
   TAGZ — "A day on the map"
   Scroll = time of day. One shader canvas carries the story;
   everything else stays quiet, precise, paper-and-ink.
   ========================================================= */

@property --progress {
  syntax: '<number>';
  inherits: true;
  initial-value: 0;
}

@property --gradient-angle {
  syntax: '<angle>';
  inherits: false;
  initial-value: 135deg;
}

:root {
  color-scheme: light dark;

  /* ---- brand ramp (from the icon's watercolor gradient) ---- */
  --orange-1: oklch(80% 0.15 55);   /* #FF9A3C territory */
  --orange-2: oklch(65% 0.19 40);   /* #F2600C territory */
  --orange-3: oklch(52% 0.19 25);   /* #D8341F territory */
  --teal: oklch(62% 0.09 200);      /* Donau accent */
  --teal-deep: oklch(38% 0.06 210);

  /* ---- paper / ink ---- */
  --paper: oklch(96% 0.025 75);
  --paper-soft: oklch(93% 0.03 70);
  --ink: oklch(20% 0.03 40);
  /* Secondary text was 38% L at 82% alpha — over glass cards or the
     darkening dusk paper the backdrop bled through and it read as grey-
     on-grey. Darker and near-opaque keeps it clearly legible everywhere. */
  --ink-soft: oklch(26% 0.035 45);
  --ink-faint: oklch(30% 0.03 45 / 0.85);

  --night-bg: oklch(19% 0.035 40);
  --night-ink: oklch(95% 0.02 70);
  --night-ink-soft: oklch(93% 0.025 65);

  --line: oklch(38% 0.03 45 / 0.16);
  --line-strong: oklch(38% 0.03 45 / 0.3);

  /* More opaque glass: at 0.72 the darkening shader bled through the
     cards and turned them muddy grey behind dark text. */
  --surface-ui: light-dark(oklch(98% 0.012 80 / 0.88), oklch(22% 0.03 40 / 0.72));
  --surface-ui-border: light-dark(oklch(40% 0.03 45 / 0.14), oklch(90% 0.02 70 / 0.14));

  --shadow-1: 0 1px 2px oklch(20% 0.03 40 / 0.06), 0 8px 24px oklch(20% 0.03 40 / 0.08);
  --shadow-2: 0 2px 6px oklch(20% 0.03 40 / 0.1), 0 20px 48px oklch(20% 0.03 40 / 0.14);

  /* ---- type ---- */
  --font-display: "Bricolage Grotesque", ui-sans-serif, system-ui, sans-serif;
  --font-body: "Plus Jakarta Sans", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "Space Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;

  --radius-s: 10px;
  --radius-m: 18px;
  --radius-l: 30px;

  --wrap: min(1180px, 100% - 48px);

  /* ---- scroll-reactive text tokens ----
     Content that sits directly on the shader canvas (no card behind
     it) needs to track the day→night ramp or it loses contrast once
     the map darkens. --progress is a registered <number> (0-100),
     updated every frame from JS.

     The shader's day→night geometry (see main.js FRAG_SRC): paper holds
     flat, bright day until t=0.53, then resolves to full night by t=0.615 (in the gap between features 3 and 4)
     — a fast transit, not a long crossfade. Features 1-3 sit entirely in
     the flat-day range and read as plain dark ink on clean paper; there
     is no more muddy mid-scroll resting state to compensate for, so the
     text ramp below is a single fast flip timed to land just behind the
     shader's own transition (dark ink until ~55, fully light by ~61.5). */
  --night-mix: clamp(0%, (var(--progress) - 55) * 15.4%, 100%);

  --scroll-ink: color-mix(in oklch, var(--ink) calc(100% - var(--night-mix)), var(--night-ink) var(--night-mix));
  --scroll-ink-soft: color-mix(in oklch, var(--ink-soft) calc(100% - var(--night-mix)), var(--night-ink-soft) var(--night-mix));
  --scroll-eyebrow: color-mix(in oklch, var(--orange-3) calc(100% - var(--night-mix)), var(--orange-1) var(--night-mix));
  --scroll-teal: color-mix(in oklch, var(--teal-deep) calc(100% - var(--night-mix)), var(--teal) var(--night-mix));
  --scroll-line: color-mix(in oklch, var(--line-strong) calc(100% - var(--night-mix)), oklch(90% 0.02 70 / 0.28) var(--night-mix));

  /* Soft halo so headings/copy stay legible wherever the river or a pin
     glow happens to pass behind them — light halo by day, dark by night. */
  --scroll-text-shadow:
    0 1px 3px color-mix(in oklch, oklch(100% 0 0 / 0.7) calc(100% - var(--night-mix)), oklch(0% 0 0 / 0.6) var(--night-mix)),
    0 2px 26px color-mix(in oklch, oklch(100% 0 0 / 0.8) calc(100% - var(--night-mix)), oklch(0% 0 0 / 0.65) var(--night-mix));

  /* Adaptive text panel: copy that floats directly on the shader canvas
     sits on this translucent surface (paper by day, warm ink by night) so
     legibility never depends on what the map happens to render behind it.
     On the clean day paper a full-strength card reads as a beige sticker,
     so day opacity is now barely-there (18%) — night keeps the original
     82%, where the panels are doing real, needed work against the busier
     night map. */
  --panel-surface: color-mix(in oklch, color-mix(in oklch, var(--paper) calc(100% - var(--night-mix)), oklch(17% 0.03 40) var(--night-mix)) calc(18% + var(--night-mix) * 0.64), transparent);
  --panel-border: color-mix(in oklch, var(--scroll-line) 60%, transparent);

  /* ---- header chrome: same fast-flip window as --night-mix, so the pill
     nav finishes darkening right as the background does, rather than
     lagging into #principles cream. */
  --header-mix: clamp(0%, (var(--progress) - 55) * 15.4%, 100%);
  --header-bg: color-mix(in oklch, oklch(98% 0.012 80 / 0.72) calc(100% - var(--header-mix)), oklch(19% 0.035 40 / 0.82) var(--header-mix));
  --header-border: color-mix(in oklch, oklch(40% 0.03 45 / 0.14) calc(100% - var(--header-mix)), oklch(90% 0.02 70 / 0.16) var(--header-mix));
  --header-solid-bg: color-mix(in oklch, var(--paper) calc(100% - var(--header-mix)), var(--night-bg) var(--header-mix));
  --header-ink: color-mix(in oklch, var(--ink) calc(100% - var(--header-mix)), var(--night-ink) var(--header-mix));
  --header-ink-soft: color-mix(in oklch, var(--ink-soft) calc(100% - var(--header-mix)), var(--night-ink-soft) var(--header-mix));
}

@media (max-width: 560px) {
  :root { --wrap: min(1180px, 100% - 32px); }
}

/* ---------------------------------------------------------
   Reset
   --------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { min-width: 0; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  min-height: 100svh;
  font-family: var(--font-body);
  color: var(--ink);
  background: var(--paper);
  font-size: 16px;
  line-height: 1.5;
}

img { max-width: 100%; display: block; }

h1, h2, h3 { font-family: var(--font-display); margin: 0; text-wrap: balance; }
p { margin: 0; text-wrap: pretty; hanging-punctuation: first last; }

a { color: inherit; }

button {
  font: inherit;
  color: inherit;
  background: none;
  border: none;
  cursor: pointer;
}

ul, ol { margin: 0; padding: 0; list-style: none; }

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.wrap { width: var(--wrap); margin-inline: auto; }

.eyebrow {
  display: block;
  font-size: 12.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--scroll-eyebrow);
  text-shadow: var(--scroll-text-shadow);
  margin-bottom: 14px;
}

.mono { font-family: var(--font-mono); }

.skip-link {
  position: fixed;
  top: -60px;
  left: 12px;
  z-index: 999;
  padding: 12px 18px;
  background: var(--ink);
  color: var(--paper);
  border-radius: var(--radius-s);
  transition: top 0.2s ease;
}
.skip-link:focus-visible { top: 12px; }

:focus-visible {
  outline: 2.5px solid var(--orange-2);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ---------------------------------------------------------
   Background canvas + fallback
   --------------------------------------------------------- */
#map-canvas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -2;
  display: none;
}
html.js-webgl-ready #map-canvas { display: block; }

.map-fallback {
  position: fixed;
  inset: 0;
  z-index: -3;
  background:
    radial-gradient(ellipse 60% 40% at 70% 20%, oklch(85% 0.09 55 / 0.5), transparent 60%),
    radial-gradient(ellipse 50% 40% at 20% 70%, oklch(75% 0.08 195 / 0.35), transparent 60%),
    linear-gradient(180deg, var(--paper) 0%, var(--paper-soft) 20%, oklch(55% 0.09 50) 65%, var(--night-bg) 100%);
  /* No WebGL2 → no shader loop, but this still tracks page scroll via the
     same --progress token (kept live by a plain scroll listener), so the
     one-image fallback still reads as day up top, night at the bottom,
     instead of going dark within the first viewport. */
  background-size: 100% 420%;
  background-position: 0% calc(var(--progress) * 1%);
}
html.js-webgl-ready .map-fallback { display: none; }

/* ---------------------------------------------------------
   Scroll progress — CSS scroll-timeline where supported
   --------------------------------------------------------- */
.scroll-progress {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  z-index: 60;
  background: color-mix(in oklch, var(--ink) 6%, transparent);
}

.scroll-progress__bar {
  height: 100%;
  width: calc(var(--progress, 0) * 1%);
  background: linear-gradient(90deg, var(--orange-1), var(--orange-3) 55%, var(--teal));
  transform-origin: left;
}

@supports (animation-timeline: scroll()) {
  @keyframes progress-scrub {
    from { width: 0%; }
    to { width: 100%; }
  }
  .scroll-progress__bar {
    width: 0%;
    animation: progress-scrub linear both;
    animation-timeline: scroll(root);
  }
}

/* ---------------------------------------------------------
   Header
   --------------------------------------------------------- */
.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 50;
  padding-top: 3px;
}

.site-header__inner {
  width: var(--wrap);
  margin-inline: auto;
  margin-top: 14px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 14px;
  border-radius: var(--radius-m);
  background: var(--header-bg);
  border: 1px solid var(--header-border);
  color: var(--header-ink);
  backdrop-filter: blur(18px) saturate(1.3);
  -webkit-backdrop-filter: blur(18px) saturate(1.3);
  box-shadow: var(--shadow-1);
  transition: background 0.15s linear, border-color 0.15s linear;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  text-decoration: none;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 18px;
  letter-spacing: 0.01em;
}

.brand__icon { border-radius: 8px; }

.site-nav {
  display: flex;
  align-items: center;
  gap: 4px;
}

.site-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding: 0 14px;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  color: var(--header-ink-soft);
  transition: background 0.18s ease, color 0.18s ease;
}
.site-nav a:hover { background: color-mix(in oklch, var(--orange-2) 10%, transparent); color: var(--header-ink); }

.site-nav__cta {
  background: linear-gradient(135deg, var(--orange-1), var(--orange-2));
  color: oklch(99% 0.01 80) !important;
  font-weight: 700 !important;
}
.site-nav__cta:hover { filter: brightness(1.05); }

.site-header__tools { display: flex; align-items: center; gap: 6px; }

.icon-btn {
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  color: var(--header-ink-soft);
  transition: background 0.18s ease, color 0.18s ease;
}
.icon-btn:hover { background: color-mix(in oklch, var(--orange-2) 10%, transparent); color: var(--header-ink); }

.nav-toggle { display: none; }

@media (max-width: 860px) {
  .site-nav { display: none; }
  .nav-toggle { display: grid; }
}

/* ---- Legend popover (anchor positioning + popover API) ---- */
.legend-trigger { anchor-name: --legend-anchor; }

.legend-popover {
  position: fixed;
  margin: 0;
  padding: 16px 18px;
  border: 1px solid var(--surface-ui-border);
  border-radius: var(--radius-m);
  background: var(--surface-ui);
  backdrop-filter: blur(20px) saturate(1.3);
  -webkit-backdrop-filter: blur(20px) saturate(1.3);
  box-shadow: var(--shadow-2);
  color: var(--ink);
  width: min(280px, 86vw);
  inset: auto;
  top: 76px;
  right: max(16px, calc((100% - var(--wrap)) / 2));

  opacity: 0;
  transform: translateY(-8px) scale(0.98);
  transition: opacity 0.2s ease, transform 0.2s ease, overlay 0.2s allow-discrete, display 0.2s allow-discrete;
}

.legend-popover:popover-open {
  opacity: 1;
  transform: translateY(0) scale(1);
}

@starting-style {
  .legend-popover:popover-open {
    opacity: 0;
    transform: translateY(-8px) scale(0.98);
  }
}

@supports (anchor-name: --a) {
  .legend-popover {
    position-anchor: --legend-anchor;
    position: absolute;
    top: anchor(bottom);
    right: anchor(right);
    margin-top: 10px;
  }
}

.legend-popover .eyebrow { margin-bottom: 10px; }
.legend-popover ul { display: grid; gap: 10px; }
.legend-popover li {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 13.5px;
  color: var(--ink-soft);
}

.legend-swatch { width: 16px; height: 16px; border-radius: 50%; flex: none; }
.legend-swatch--pin { background: radial-gradient(circle, var(--orange-1), var(--orange-3)); box-shadow: 0 0 10px 1px color-mix(in oklch, var(--orange-2) 60%, transparent); }
.legend-swatch--line { border-radius: 2px; height: 3px; background: var(--ink); }
.legend-swatch--river { border-radius: 2px; height: 6px; background: var(--teal); }

/* ---- Mobile nav (popover) ---- */
.mobile-nav {
  position: fixed;
  inset: 0;
  margin: 0;
  border: none;
  width: 100%;
  height: 100%;
  max-width: none;
  max-height: none;
  padding: 100px 32px 40px;
  /* Match whichever day/night state the header is in when this opens,
     rather than always being hardcoded to night. */
  background: var(--header-solid-bg);
  color: var(--header-ink);

  opacity: 0;
  transition: opacity 0.28s ease, overlay 0.28s allow-discrete, display 0.28s allow-discrete;
}
.mobile-nav:popover-open { opacity: 1; }
@starting-style { .mobile-nav:popover-open { opacity: 0; } }

.mobile-nav__close {
  position: absolute;
  top: 20px;
  right: 20px;
  color: var(--header-ink);
}

.mobile-nav nav {
  display: grid;
  gap: 4px;
}
.mobile-nav a {
  display: block;
  padding: 16px 4px;
  font-family: var(--font-display);
  font-size: 30px;
  font-weight: 600;
  text-decoration: none;
  color: var(--header-ink);
  border-bottom: 1px solid var(--header-border);
}

/* ---------------------------------------------------------
   Sections — shared rhythm
   --------------------------------------------------------- */
.section {
  position: relative;
  z-index: 1;
  padding: clamp(88px, 14vw, 160px) 0;
  /* Anchor jumps land below the fixed pill header instead of swallowing
     the section eyebrow ("THE ROUTE", "ON THE MAP", "SIGNALS, NOT NOISE"). */
  scroll-margin-top: 108px;
}

.hero { padding-top: clamp(140px, 20vw, 210px); padding-bottom: clamp(60px, 8vw, 90px); }

.section h2 {
  font-size: clamp(32px, 4.4vw, 52px);
  font-weight: 650;
  line-height: 1.05;
  max-width: 16ch;
  color: var(--scroll-ink);
  text-shadow: var(--scroll-text-shadow);
}

/* ---- Scroll reveals: view() timeline, IO fallback ---- */
.reveal {
  opacity: 1;
  transform: none;
}

@supports (animation-timeline: view()) {
  .reveal {
    opacity: 0;
    transform: translateY(28px);
    animation: reveal-in linear both;
    animation-timeline: view();
    /* Shortened from cover 30%: a heading only needs to be modestly into
       the viewport to read as "arrived." A wider range left headings
       resting at low opacity ("ghost" text) whenever a section landed
       near the top of the viewport, e.g. right after an anchor jump. */
    animation-range: entry 0% cover 15%;
  }
  @keyframes reveal-in {
    to { opacity: 1; transform: translateY(0); }
  }
}

html:not(.supports-view-timeline) .reveal.io-ready {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.7s cubic-bezier(.2,.7,.2,1), transform 0.7s cubic-bezier(.2,.7,.2,1);
}
html:not(.supports-view-timeline) .reveal.io-visible {
  opacity: 1;
  transform: translateY(0);
}

/* Belt-and-suspenders for direct loads at /#features, /#how, etc: main.js
   force-adds this class to every .reveal inside the URL's hash target on
   boot, bypassing view-timeline math entirely so the section is always
   fully readable without requiring the user to scroll first. */
.reveal.reveal-instant {
  opacity: 1 !important;
  transform: none !important;
  animation: none !important;
}

@media (prefers-reduced-motion: reduce) {
  .reveal, html:not(.supports-view-timeline) .reveal.io-ready {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
    transition: none !important;
  }
}

/* ---------------------------------------------------------
   Hero
   --------------------------------------------------------- */
.hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.86fr);
  align-items: center;
  gap: clamp(24px, 5vw, 60px);
}

.hero__copy { max-width: 46ch; }

.hero h1 {
  font-size: clamp(40px, 6.6vw, 84px);
  line-height: 0.98;
  font-weight: 700;
  font-variation-settings: "opsz" 90, "wght" 700;
  letter-spacing: -0.01em;
  color: var(--ink);
}

.hero__lede {
  margin-top: 22px;
  font-size: clamp(17px, 1.6vw, 20px);
  line-height: 1.5;
  color: var(--ink-soft);
  max-width: 40ch;
}

.badges__label {
  margin-top: 34px;
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.store-badges {
  margin-top: 12px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.store-badge {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 9px 16px 9px 14px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-s);
  color: var(--ink-faint);
  cursor: not-allowed;
  user-select: none;
}

.store-badge__text {
  display: flex;
  flex-direction: column;
  font-size: 14.5px;
  font-weight: 700;
  line-height: 1.15;
  color: var(--ink-soft);
}
.store-badge__text small {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.store-badge--dark {
  border-color: oklch(90% 0.02 70 / 0.22);
  color: oklch(90% 0.02 70 / 0.7);
}
.store-badge--dark .store-badge__text { color: var(--night-ink); }
.store-badge--dark .store-badge__text small { color: var(--night-ink-soft); }

/* ---- Phone frame ---- */
.phone__frame {
  position: relative;
  aspect-ratio: 720 / 1565;
  border-radius: 46px;
  padding: 14px;
  background: linear-gradient(155deg, oklch(28% 0.02 60), oklch(14% 0.02 40));
  box-shadow: var(--shadow-2), inset 0 0 0 1.5px oklch(100% 0 0 / 0.06);
}

.phone__screen {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 32px;
  background: var(--paper-soft);
}

.phone__notch {
  position: absolute;
  top: 14px;
  left: 50%;
  translate: -50% 0;
  width: 34%;
  height: 22px;
  border-radius: 0 0 16px 16px;
  background: oklch(14% 0.02 40);
  z-index: 2;
}

.hero__phone { display: grid; justify-items: center; gap: 22px; }

.phone--hero { width: min(300px, 72vw); view-transition-name: hero-phone-frame; }

.hero-tabs {
  display: inline-flex;
  gap: 4px;
  padding: 5px;
  border-radius: 999px;
  background: var(--surface-ui);
  border: 1px solid var(--surface-ui-border);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  box-shadow: var(--shadow-1);
}

.hero-tabs button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 38px;
  padding: 0 13px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 700;
  color: var(--ink-faint);
  transition: background 0.2s ease, color 0.2s ease;
}
.hero-tabs button span { display: none; }
.hero-tabs button[aria-selected="true"] {
  background: linear-gradient(135deg, var(--orange-1), var(--orange-2));
  color: oklch(99% 0.01 80);
}

@media (min-width: 560px) {
  .hero-tabs button span { display: inline; }
}

#hero-screen { view-transition-name: hero-screen; }

::view-transition-old(hero-screen),
::view-transition-new(hero-screen) {
  animation-duration: 0.42s;
  animation-timing-function: cubic-bezier(.2,.7,.2,1);
}

.scroll-cue {
  position: absolute;
  left: 50%;
  bottom: 30px;
  translate: -50% 0;
  width: 26px;
  height: 42px;
  border: 1.5px solid var(--line-strong);
  border-radius: 20px;
  display: grid;
  place-items: start center;
  padding-top: 8px;
}
.scroll-cue span {
  width: 4px;
  height: 8px;
  border-radius: 3px;
  background: var(--orange-2);
  animation: scroll-cue-move 1.8s ease-in-out infinite;
}
@keyframes scroll-cue-move {
  0%, 100% { transform: translateY(0); opacity: 1; }
  60% { transform: translateY(10px); opacity: 0.3; }
}
@media (prefers-reduced-motion: reduce) {
  .scroll-cue span { animation: none; }
}

/* ---------------------------------------------------------
   How it works
   --------------------------------------------------------- */
.steps {
  margin-top: 44px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(20px, 3vw, 32px);
}

.step {
  container-type: inline-size;
  position: relative;
  padding: 28px 24px 26px;
  border-radius: var(--radius-m);
  background: var(--surface-ui);
  border: 1px solid var(--surface-ui-border);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: var(--shadow-1);
}

.step__num {
  display: block;
  font-size: 13px;
  color: var(--orange-3);
  font-weight: 700;
  margin-bottom: 18px;
}

.step__icon { color: var(--orange-2); margin-bottom: 14px; }

.step h3 {
  font-size: 21px;
  font-weight: 650;
  margin-bottom: 8px;
  color: var(--ink);
}

.step p { color: var(--ink-soft); font-size: 15px; line-height: 1.55; }

@media (max-width: 860px) {
  .steps { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------
   Features
   --------------------------------------------------------- */
/* The narrow-layout @container rule below queries the nearest ANCESTOR
   container, so the declaration must sit on the list, not on .feature
   itself (an element can't match a query against its own container). */
.section__lede {
  max-width: 54ch;
  margin-top: 16px;
  font-size: 17px;
  line-height: 1.6;
  color: var(--scroll-ink-soft);
  text-shadow: var(--scroll-text-shadow);
}

.feature-list {
  container-type: inline-size;
  margin-top: 60px;
  display: grid;
  gap: clamp(64px, 10vw, 110px);
}

.feature {
  display: grid;
  grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(28px, 6vw, 72px);
  width: var(--wrap);
  margin-inline: auto;
}

.feature--reverse { grid-template-columns: minmax(0, 1fr) minmax(0, 0.62fr); }
.feature--reverse .feature__media { order: 2; }
.feature--reverse .feature__copy { order: 1; }

.feature__media { display: flex; justify-content: center; }

/* min-height: 0 defeats the flex "automatic minimum size" default, which
   would otherwise size this item off the nested <img>'s intrinsic 1565px
   height instead of the aspect-ratio-driven ~500px, blowing the frame out
   past the viewport (clipped behind the header, cut off at the bottom). */
.phone--sm { width: min(300px, 100%); min-height: 0; }

/* Explicit safety cap: whatever the natural aspect-ratio height comes to,
   never let a feature device frame exceed 76% of the viewport, so the
   whole phone is always visible below the fixed header. Width isn't set
   on .phone__frame (it fills its 230px-wide parent), so it only kicks in
   on unusually short viewports; on normal desktop/mobile heights the
   natural ~500px frame is already well under this cap and nothing changes. */
.features .phone__frame { max-height: min(80vh, 660px); margin-inline: auto; }

.feature__copy {
  max-width: 46ch;
  padding: 26px 28px;
  border-radius: var(--radius-m);
  background: var(--panel-surface);
  border: 1px solid var(--panel-border);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}
.feature__copy h3 {
  font-size: clamp(24px, 2.6vw, 32px);
  font-weight: 650;
  color: var(--scroll-ink);
  margin-bottom: 12px;
}
.feature__copy p { color: var(--scroll-ink-soft); font-size: 16.5px; line-height: 1.6; }

@container (max-width: 620px) {
  .feature, .feature--reverse {
    grid-template-columns: 1fr;
    text-align: center;
  }
  .phone--sm { width: min(270px, 78cqw); }
  .feature--reverse .feature__media,
  .feature--reverse .feature__copy { order: initial; }
  .feature__copy { max-width: 40ch; margin-inline: auto; }
}

/* ---------------------------------------------------------
   Principles
   --------------------------------------------------------- */
.principles-grid {
  margin-top: 44px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(18px, 3vw, 28px);
}

.principle-card {
  container-type: inline-size;
  padding: 30px 26px;
  border-radius: var(--radius-m);
  border: 1px solid var(--panel-border);
  background: var(--panel-surface);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  color: var(--scroll-ink);
}

.principle-card svg { color: var(--scroll-teal); margin-bottom: 16px; }

.principle-card h3 {
  font-size: 19px;
  font-weight: 650;
  margin-bottom: 8px;
  color: var(--scroll-ink);
}

.principle-card p { color: var(--scroll-ink-soft); font-size: 15px; line-height: 1.55; }
.principle-card h3, .principle-card p { text-shadow: none; }

@media (max-width: 860px) {
  .principles-grid { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------
   CTA — night
   --------------------------------------------------------- */
.cta { color: var(--night-ink); text-align: center; }
.cta .eyebrow { color: var(--orange-1); }
.cta h2 { color: var(--night-ink); max-width: 20ch; margin-inline: auto; }

.cta__inner { display: flex; flex-direction: column; align-items: center; }

.cta__lede {
  margin-top: 18px;
  font-size: clamp(16px, 1.6vw, 19px);
  color: var(--night-ink-soft);
  max-width: 42ch;
}

.cta .badges__label { color: var(--night-ink-soft); }
.cta .store-badges { justify-content: center; }

.cta__mail {
  margin-top: 34px;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 14px 26px;
  border-radius: 999px;
  font-weight: 700;
  font-size: 15.5px;
  text-decoration: none;
  color: oklch(99% 0.01 80);
  background: linear-gradient(var(--gradient-angle), var(--orange-1), var(--orange-2) 55%, var(--orange-3));
  box-shadow: 0 12px 34px oklch(55% 0.19 40 / 0.35);
  transition: --gradient-angle 0.5s ease, transform 0.2s ease, box-shadow 0.2s ease;
}
.cta__mail:hover {
  --gradient-angle: 305deg;
  transform: translateY(-2px);
  box-shadow: 0 16px 40px oklch(55% 0.19 40 / 0.45);
}

@supports not (color: oklch(0% 0 0)) {
  .cta__mail { background: #F2600C; }
}

/* ---------------------------------------------------------
   Footer
   --------------------------------------------------------- */
.site-footer {
  position: relative;
  z-index: 1;
  padding: 44px 0 max(36px, env(safe-area-inset-bottom));
  color: var(--night-ink);
}

.site-footer__inner {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 20px 28px;
  padding-top: 28px;
  border-top: 1px solid oklch(90% 0.02 70 / 0.16);
}

.brand--footer { color: var(--night-ink); }

.site-footer__nav {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 20px;
  justify-content: center;
}
.site-footer__nav a {
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  color: var(--night-ink-soft);
}
.site-footer__nav a:hover { color: var(--night-ink); }

.site-footer__coords { margin: 0; color: var(--night-ink-soft); justify-self: end; }

.site-footer__copy {
  grid-column: 1 / -1;
  margin-top: 6px;
  font-size: 13px;
  color: var(--night-ink-soft);
}
.site-footer__copy a { text-decoration: underline; text-underline-offset: 3px; }

@media (max-width: 720px) {
  .site-footer__inner { grid-template-columns: 1fr; text-align: center; justify-items: center; }
  .site-footer__coords { justify-self: center; }
}

/* ---------------------------------------------------------
   Container-query-driven scroll-state restyle for header
   (stuck detection where supported)
   --------------------------------------------------------- */
@supports (animation-timeline: scroll-state(nearest-scroll-container stuck)) {
  .site-header { container-type: scroll-state; }
}

/* ---------------------------------------------------------
   Reduced motion — kill smooth scroll + shader loop signalling
   --------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    scroll-behavior: auto !important;
  }
}

/* ---------------------------------------------------------
   Responsive tuning
   --------------------------------------------------------- */
@media (max-width: 980px) {
  .hero__grid { grid-template-columns: 1fr; text-align: center; }
  .hero__copy { max-width: 56ch; margin-inline: auto; }
  .hero__lede { margin-inline: auto; }
  .store-badges { justify-content: center; }
  .hero__phone { margin-top: 12px; }
}

@media (max-width: 480px) {
  .site-header__inner { margin-top: 8px; padding: 8px 10px; }
  .hero { padding-top: clamp(120px, 26vw, 160px); }
  .phone--hero { width: min(260px, 78vw); }
}
