/* ===========================================================================
   Crest — base layer: reset, typography, primitives
   =========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

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

/* The wave engine owns scroll position. If the OS asks for less motion we stop
   hijacking scroll entirely. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  margin: 0;
  background: var(--deep-blue);
  color: var(--ink-2);
  font-family: var(--font);
  font-size: var(--t-md);
  line-height: var(--leading-body);
  letter-spacing: var(--track-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}

h1, h2, h3, h4, p, figure, blockquote, ul, ol { margin: 0; }
ul, ol { padding: 0; list-style: none; }
img, svg, canvas { display: block; max-width: 100%; }
img { height: auto; }
button { font: inherit; color: inherit; }

a {
  color: var(--teal);
  text-decoration-color: color-mix(in oklab, var(--teal) 40%, transparent);
  text-underline-offset: 0.22em;
  transition: color var(--dur-fast) var(--ease-out-soft);
}
a:hover { color: var(--foam); }

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

::selection {
  background: color-mix(in oklab, var(--teal) 42%, transparent);
  color: var(--ink-0);
}

/* --- Type primitives ------------------------------------------------------ */

.display {
  font-size: var(--t-hero);
  line-height: var(--leading-hero);
  letter-spacing: var(--track-hero);
  font-weight: 700;
  color: var(--ink-0);
  max-width: var(--measure);
  text-wrap: balance;
}

.h2 {
  font-size: var(--t-xxl);
  line-height: var(--leading-tight);
  letter-spacing: var(--track-xxl);
  font-weight: 700;
  color: var(--ink-0);
  max-width: var(--measure);
  text-wrap: balance;
}

.h3 {
  font-size: var(--t-xl);
  line-height: var(--leading-snug);
  letter-spacing: var(--track-xl);
  font-weight: 650;
  color: var(--ink-0);
  text-wrap: balance;
}

.lede {
  font-size: var(--t-lg);
  line-height: 1.45;
  letter-spacing: var(--track-lg);
  color: var(--ink-2);
  max-width: 46ch;
  font-weight: 400;
  text-wrap: pretty;
}

/* The domain doesn't carry the product name, so the first sentence has to. */
.lede strong { color: var(--ink-0); font-weight: 600; }

.body { max-width: var(--measure-body); text-wrap: pretty; }

.eyebrow {
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: var(--track-eyebrow);
  text-transform: uppercase;
  color: var(--phase-accent, var(--accent-label));
  display: flex;
  align-items: center;
  gap: var(--s-3);
  transition: color var(--dur-slow) var(--ease-out-soft);
}
.eyebrow::before {
  content: "";
  width: 22px;
  height: 1px;
  background: currentColor;
  opacity: 0.55;
  flex: none;
}

.muted { color: var(--ink-3); }
.tnum { font-variant-numeric: tabular-nums; font-feature-settings: "tnum" 1; }

/* --- Layout --------------------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: var(--max-w);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: var(--section-y); position: relative; }

.stack > * + * { margin-top: var(--flow, var(--s-5)); }

/* minmax(0,…) throughout — a grid track's implicit minimum is min-content, which
   lets a wide child (a nowrap button, a long unbroken string) push the track
   past the viewport instead of shrinking. */
.split {
  display: grid;
  gap: clamp(var(--s-7), 5vw, var(--s-9));
  align-items: center;
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 900px) {
  .split { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .split--wide-text { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); }
  .split--reverse > :first-child { order: 2; }
}

/* --- Buttons -------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-3);
  padding: 1.05rem 2rem;
  min-height: 56px;
  border: 0;
  border-radius: var(--r-full);
  font-size: var(--t-md);
  font-weight: 600;
  letter-spacing: -0.01em;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  transition:
    transform var(--dur-fast) var(--ease-out-soft),
    box-shadow var(--dur-fast) var(--ease-out-soft),
    background var(--dur-fast) var(--ease-out-soft);
}

/* At 320px (iPhone SE 1st gen) "Download on the App Store" plus 2rem of padding
   either side is 8px wider than the content box, and nowrap means it pushes the
   document instead of wrapping. Tighten rather than let the label break. */
@media (max-width: 380px) {
  .btn {
    padding-inline: 1.25rem;
    font-size: var(--t-sm);
    gap: var(--s-2);
  }
}

.btn--primary {
  background: linear-gradient(180deg,
    color-mix(in oklab, var(--coral) 92%, white 8%),
    var(--coral));
  color: #2a1206;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.22) inset,
    0 10px 30px color-mix(in oklab, var(--coral) 34%, transparent);
}
.btn--primary:hover {
  transform: translateY(-2px);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.28) inset,
    0 16px 42px color-mix(in oklab, var(--coral) 44%, transparent);
  color: #2a1206;
}
.btn--primary:active { transform: translateY(0); }

.btn--ghost {
  background: var(--surface-2);
  color: var(--ink-1);
  border: 1px solid var(--hairline);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
.btn--ghost:hover {
  background: var(--surface-1);
  border-color: var(--hairline-strong);
  color: var(--ink-0);
  transform: translateY(-2px);
}

/* --- Card ----------------------------------------------------------------- */

.card {
  background: var(--surface-1);
  border: 1px solid var(--hairline);
  border-radius: var(--r-lg);
  padding: clamp(var(--s-5), 3vw, var(--s-7));
  backdrop-filter: blur(20px) saturate(120%);
  -webkit-backdrop-filter: blur(20px) saturate(120%);
}

.card--tinted {
  background:
    linear-gradient(180deg,
      color-mix(in oklab, var(--teal) 13%, transparent),
      color-mix(in oklab, var(--teal) 5%, transparent));
  border-color: color-mix(in oklab, var(--teal) 26%, transparent);
}

/* --- Device frame ---------------------------------------------------------
   A real iPhone silhouette in CSS rather than a baked-in bezel PNG: it stays
   sharp at every DPR, recolours with the page, and costs nothing to ship.
   Proportions follow iPhone 15/17 Pro — 19.5:9 with a 44px-equivalent radius. */

/* 320px was the desktop value applied everywhere. On a 390px phone that is a
   692px-tall block, and with six of them the mockups alone were ~40% of the
   page's total height — the page ran to twelve screens. 272px on small screens
   is still comfortably legible (the live surf scales with it, being sized in
   cqw) and takes roughly a screen and a half out of the scroll. */
.device {
  position: relative;
  width: min(100%, 272px);
  margin-inline: auto;
  aspect-ratio: 1284 / 2778;
  border-radius: var(--r-device);
  padding: 5px;
  background:
    linear-gradient(150deg, #454f5e 0%, #171d28 26%, #0d121b 55%, #39424f 100%);
  box-shadow: var(--shadow-device);
  isolation: isolate;
}

.device::after {
  /* Glass sheen. Sits above the screenshot, ignores pointer events. */
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(148deg,
    rgba(255, 255, 255, 0.14) 0%,
    rgba(255, 255, 255, 0.04) 18%,
    transparent 42%,
    transparent 100%);
  pointer-events: none;
  z-index: 2;
}

.device__screen {
  width: 100%;
  height: 100%;
  border-radius: calc(var(--r-device) - 5px);
  overflow: hidden;
  background: var(--deep-blue);
  position: relative;
  z-index: 1;
}

.device__screen img { width: 100%; height: 100%; object-fit: cover; }

@media (min-width: 620px) {
  .device { width: min(100%, 320px); }
}

.device--sm { width: min(100%, 240px); }
@media (min-width: 620px) {
  .device--sm { width: min(100%, 258px); }
}

/* --- Scroll reveal --------------------------------------------------------
   Opacity + a short rise. Deliberately restrained: the wave is the motion on
   this page, and competing animations would cheapen it. */

.reveal {
  opacity: 0;
  transform: translate3d(0, 22px, 0);
  transition:
    opacity var(--dur-slow) var(--ease-out-soft),
    transform var(--dur-slow) var(--ease-out-soft);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}
.reveal.is-in {
  opacity: 1;
  transform: none;
  will-change: auto;
}

@media (prefers-reduced-motion: reduce) {
  .reveal, .reveal.is-in {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .btn:hover, .btn:active { transform: none; }
}

/* --- Accessibility -------------------------------------------------------- */

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  top: var(--s-4);
  left: var(--s-4);
  z-index: 100;
  padding: var(--s-3) var(--s-5);
  background: var(--ink-0);
  color: var(--deep-blue);
  border-radius: var(--r-full);
  font-weight: 600;
  text-decoration: none;
  transform: translateY(-200%);
  transition: transform var(--dur-fast) var(--ease-out-soft);
}
.skip-link:focus-visible { transform: none; color: var(--deep-blue); }
