/* everylane — marketing site (everylane.gg)
   Static, no build step. Brand tokens mirror web/public/static/styles.css; keep
   them in sync by hand — this page is deliberately not coupled to the app bundle. */

/* Space Grotesk, self-hosted (session 104). The page used to pull it from
   fonts.googleapis.com: a render-blocking stylesheet on one third-party origin
   that then fetched the files from a second, so the hero text waited on two DNS
   lookups and two TLS handshakes. These are the same OFL files the app serves,
   lifted from web/public/static/styles.css: one variable file (wght 300-700)
   per subset, latin and latin-ext, declared with a weight range. A file per
   weight was byte-identical four times over and fetched four times. A new
   weight needs no new file; a new subset does. */
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('assets/fonts/space-grotesk-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url('assets/fonts/space-grotesk-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

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

:root {
  --bg: #0c0d14;
  --surface-1: rgba(255, 255, 255, 0.04);
  --border: rgba(255, 255, 255, 0.07);
  --border-strong: rgba(255, 255, 255, 0.14);
  --mint: #39d98a;
  --mint-soft: rgba(57, 217, 138, 0.14);
  --mint-glow: rgba(57, 217, 138, 0.45);
  --text-hi: #f0f4ff;
  --text-med: #b0bcd0;
  --text-dim: #7c8c9c;

  /* Uncovered road. Must read as "road that exists but isn't done" — visible
     enough that the island's shape is legible before any mint lands, faint
     enough that the coverage sweep is unmistakable against it. The parishes
     left uncovered at the end have to stay legible; that IS the message. */
  --road-off: rgba(158, 178, 208, 0.34);

  /* The page's one side margin and one content width. Every band, hero
     included, starts its text at the same left edge because they all read
     these two. */
  --gutter: clamp(1.5rem, 6vw, 3rem);
  --content: 68rem;
}

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

body {
  min-height: 100%;
  font-family: "Space Grotesk", system-ui, -apple-system, sans-serif;
  background: var(--bg);
  color: var(--text-hi);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* ── Hero ─────────────────────────────────────────────────────────────────
   Echoes the app's login screen (copy left, island right) so a visitor who
   clicks through lands on the same composition rather than a different page. */

.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  overflow: hidden;
}

/* The island is the subject here, not wallpaper — so it gets a box and
   `xMidYMid meet` letterboxes the whole island inside it at any viewport.
   (The login screen deliberately crops its copy of this map; this must not.) */
.hero-map {
  position: absolute;
  top: 50%;
  right: 0;
  width: 62%;
  height: 88%;
  transform: translateY(-50%);
  pointer-events: none;
}
.hero-map .reveal-svg { width: 100%; height: 100%; display: block; }

/* Keeps the copy legible over the network without dimming the island itself —
   the reveal is the subject here, not wallpaper like it is on the login screen. */
.hero-scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    90deg,
    var(--bg) 28%,
    color-mix(in srgb, var(--bg) 55%, transparent) 44%,
    color-mix(in srgb, var(--bg) 0%, transparent) 62%
  );
}

/* The sections pad the band and cap the text inside it; this caps the band
   and pads inside it, so its cap includes both gutters. Capped at the bare
   content width it started 48px right of every section on a wide screen. The
   inner cap keeps the copy clear of the island. */
.hero-copy {
  position: relative;
  width: 100%;
  max-width: calc(var(--content) + 2 * var(--gutter));
  margin: 0 auto;
  padding: 0 var(--gutter);
}
.hero-copy > * { max-width: 34rem; }

.wordmark {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font-size: clamp(1.5rem, 3vw, 1.9rem);
  font-weight: 700;
  letter-spacing: -0.035em;
  margin-bottom: 1.5rem;
}
.wordmark img {
  width: clamp(38px, 5vw, 46px);
  height: auto;
  display: block;
}
.wordmark b { color: var(--mint); font-weight: 700; }

.status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  background: var(--mint-soft);
  border: 1px solid rgba(57, 217, 138, 0.20);
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--mint);
  margin-bottom: 1.75rem;
}
.status .pip {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--mint);
  animation: blink 2s ease-in-out infinite;
}
@keyframes blink { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }

.hero h1 {
  font-size: clamp(2.1rem, 5.4vw, 3.4rem);
  line-height: 1.06;
  font-weight: 700;
  letter-spacing: -0.035em;
  margin-bottom: 1.25rem;
}
.hero h1 em { font-style: normal; color: var(--mint); }

.hero-sub {
  font-size: clamp(1rem, 2vw, 1.15rem);
  line-height: 1.6;
  color: var(--text-med);
  max-width: 30rem;
}

/* Strava's button, unmodified: 48px tall, its own 6px corner for the focus
   ring. Its guidelines forbid altering or animating the mark, so no hover. */
.strava-connect {
  display: inline-block;
  line-height: 0;
  border-radius: 6px;
  margin-top: 1.75rem;
}
.strava-connect:focus-visible { outline: 2px solid var(--mint); outline-offset: 3px; }
.strava-connect img { display: block; height: 48px; width: auto; }

.hero-limit,
.join-note {
  margin-top: 0.9rem;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text-dim);
}
.join-note { margin-top: 1.4rem; font-size: 0.95rem; }
/* Two short lines, not one long one running out over the island. */
.hero-copy > .hero-limit { max-width: 25rem; }

/* For someone who already has an account: top right, out of the pitch's way. */
.signin {
  position: absolute;
  z-index: 1;
  top: clamp(1.25rem, 3vw, 2rem);
  right: var(--gutter);
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-hi);
  text-decoration: none;
  padding: 0.5rem 0.95rem;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: color-mix(in srgb, var(--bg) 70%, transparent);
  transition: color 0.15s, border-color 0.15s;
}
.signin:hover { color: var(--mint); border-color: var(--mint); }

/* ── The reveal ───────────────────────────────────────────────────────────
   Act 1: the network draws itself in faint. Act 2: mint inks over it, parish
   by parish. Settles partial — the trailing parishes are never drawn mint. */

.reveal-coast {
  fill: rgba(57, 217, 138, 0.05);
  stroke: rgba(255, 255, 255, 0.18);
  stroke-width: 2.5;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: draw 1200ms ease-out forwards;
}

.reveal-road,
.reveal-ink {
  fill: none;
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: draw 900ms ease-out forwards;
}
.reveal-road { stroke: var(--road-off); }
/* No drop-shadow here: the ink pass is ~340 separately-animated paths, and a
   per-path filter is the most expensive thing you can repaint on every frame of
   the first thing a visitor sees. The mint reads vividly enough without it. */
.reveal-ink { stroke: var(--mint); }

@keyframes draw { to { stroke-dashoffset: 0; } }

/* Parish name ticker — one cycling line, not ten labels on the map. Without it
   the sweep looks random; with it you read the island being worked through. */
.hero-ticker {
  position: relative;
  height: 1.5rem;
  margin-top: 1.75rem;
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mint);
}
.reveal-tick,
.reveal-caption {
  position: absolute;
  inset: 0;
  opacity: 0;
}
.reveal-tick { animation: tick 480ms ease-out both; }
@keyframes tick {
  0% { opacity: 0; transform: translateY(4px); }
  20% { opacity: 1; transform: translateY(0); }
  65% { opacity: 1; }
  100% { opacity: 0; }
}

/* What the sweep was. Quieter than the parish ticks it replaces — this is a
   footnote to the map, not part of the headline. */
.reveal-caption {
  color: var(--text-dim);
  font-weight: 500;
  letter-spacing: 0.02em;
  text-transform: none;
  animation: caption-in 600ms ease-out both;
}
@keyframes caption-in {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}

/* ── Portrait ─────────────────────────────────────────────────────────────
   Island to the top, copy on solid dark beneath it — same rule the login
   screen uses, so the copy never sits over faint roads. */
@media (max-width: 760px) {
  .hero { align-items: flex-end; padding-bottom: 3rem; }
  /* Whole island, not a crop — the uncovered south-west is the message, and a
     portrait crop of the northern half throws exactly that away. */
  .hero-map {
    top: 2%;
    right: auto;
    left: 0;
    width: 100%;
    height: 46%;
    transform: none;
  }
  .hero-scrim {
    background: linear-gradient(180deg, transparent 20%, var(--bg) 54%);
  }
  .hero-copy { max-width: none; }
  /* A phone has no room for the wordmark and the status pill between the
     island and the headline once the button is there: both sat on top of the
     south-west. The wordmark becomes a header row opposite Sign in, and the
     pill goes, since the line under the button says the same thing. The copy
     block drops out of positioning so the wordmark can anchor to the hero;
     its children stay positioned so they still paint above the scrim. */
  .hero-copy { position: static; }
  .hero-copy > * { position: relative; }
  .wordmark {
    position: absolute;
    top: 1.25rem;
    left: var(--gutter);
    margin: 0;
    height: 36px;
  }
  .status { display: none; }
  .hero-map { top: 9%; height: 42%; }
  /* The caption can wrap to two lines at this width; the ticks never do. */
  .hero-ticker { min-height: 2.6rem; }
}

/* ── Sections ─────────────────────────────────────────────────────────────
   Everything below the hero is ordinary stacked content: island and product
   first, the build as a closer. No second animation competes with the hero. */

.section {
  border-top: 1px solid var(--border);
  padding: clamp(3rem, 9vw, 7rem) var(--gutter);
}

/* One container width for every band on the page, hero included, so the whole
   thing shares a single left edge. Text is constrained by the ch-based caps on
   h2/.lead rather than by narrowing the container — narrowing it would pull
   those sections' left edge inward and make the page read as ragged. */
.wrap { max-width: var(--content); margin: 0 auto; }

.tag {
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 1.1rem;
}

.section h2 {
  font-size: clamp(1.7rem, 4vw, 2.6rem);
  line-height: 1.12;
  font-weight: 700;
  letter-spacing: -0.03em;
  margin-bottom: 1.5rem;
  max-width: 26ch;
  text-wrap: balance;
}
/* Section headings carry no mint accent: the hero h1 is the page's single
   accented headline. Five accented headings in a row read as a formula. */

.lead {
  font-size: clamp(1rem, 1.7vw, 1.12rem);
  line-height: 1.65;
  color: var(--text-med);
  max-width: 54ch;
  text-wrap: pretty;
}
.lead + .lead { margin-top: 1.1rem; }

/* Real screenshots of the running app (scripts/build_site_shots.py). Few and
   large, not a gallery: each one sits in the section it proves. */
.shot { margin: clamp(2rem, 4vw, 2.5rem) 0; }
.shot img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface-1);
}
.shot figcaption {
  margin-top: 0.75rem;
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--text-dim);
}

/* A phone-sized shot at a phone's size: shrunk to the column's width it
   would be a poster, and the point is that this is what it looks like in
   your hand. */
.shot.phone { width: min(100%, 15rem); margin-inline: auto; }
.shot.phone img { border-color: var(--border-strong); border-radius: 28px; }
.shot.phone figcaption { text-align: center; }
/* The board read as a spreadsheet at the page's full width. */
.shot.board { max-width: 52rem; }

/* Text beside its picture on a wide screen, above it on a phone. */
@media (min-width: 761px) {
  .split {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    gap: clamp(2rem, 6vw, 5rem);
    align-items: start;
  }
  .split .shot { margin: 0; }
  .shot.phone { width: 17rem; }
  /* A landscape picture needs the wider column. */
  .split.wide-shot { grid-template-columns: minmax(0, 5fr) minmax(0, 6fr); }
}

/* The privacy page's mint-dot list (.doc ul below), at the page's lead size. */
.facts { max-width: 54ch; }
.facts li { font-size: clamp(1rem, 1.7vw, 1.12rem); line-height: 1.6; color: var(--text-med); }

.cards {
  margin-top: clamp(1.5rem, 4vw, 2.5rem);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: 1rem;
}
.card {
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1.4rem;
  background: var(--surface-1);
}
.card h3 {
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-bottom: 0.55rem;
  color: var(--mint);
}
.card p {
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--text-med);
}
/* On a phone the four stack, so their padding is most of their height. */
@media (max-width: 760px) {
  .cards { gap: 0.75rem; }
  .card { padding: 1rem 1.15rem; }
}

.stack {
  margin-top: 2.25rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--border);
  font-size: 0.82rem;
  letter-spacing: 0.05em;
  color: var(--text-dim);
}

/* ── Footer ── */
.footer {
  border-top: 1px solid var(--border);
  padding: clamp(3rem, 7vw, 5rem) var(--gutter);
}
.footer-brand {
  font-size: 1.3rem;
  font-weight: 700;
  letter-spacing: -0.035em;
  margin-bottom: 0.9rem;
}
.footer-brand b { color: var(--mint); font-weight: 700; }
.footer-note {
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--text-med);
  max-width: 40ch;
  margin-bottom: 1.1rem;
}
.footer-link {
  display: inline-block;
  color: var(--text-hi);
  text-decoration: none;
  border-bottom: 1px solid var(--border-strong);
  padding-bottom: 2px;
  transition: color 0.15s, border-color 0.15s;
}
.footer-link:hover { color: var(--mint); border-color: var(--mint); }
.footer-meta {
  margin-top: 2.5rem;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: var(--text-dim);
}
.footer-strava {
  margin-top: 1.1rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  color: var(--text-dim);
}
.footer-strava img { display: block; }

/* ── Document pages (privacy/) ──
   Reading-length prose on the site's ground: the same wordmark, container and
   gutter as the landing page, capped at a comfortable measure. */
.doc { padding: clamp(2.5rem, 7vw, 5rem) var(--gutter) clamp(3rem, 8vw, 6rem); }
.doc-wrap { max-width: 44rem; }
.doc-mark a { display: flex; align-items: center; gap: 0.7rem; color: inherit; text-decoration: none; }
.doc h1 {
  font-size: clamp(2rem, 5vw, 3rem);
  line-height: 1.1;
  font-weight: 700;
  letter-spacing: -0.035em;
  margin-top: 1rem;
}
.doc-meta { margin-top: 0.6rem; font-size: 0.85rem; color: var(--text-dim); }
.doc section { margin-top: 2.5rem; }
.doc h2 {
  font-size: 1.2rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  margin-bottom: 0.7rem;
}
.doc p, .doc li { font-size: 1rem; line-height: 1.65; color: var(--text-med); }
.doc ul, .facts { list-style: none; display: flex; flex-direction: column; gap: 0.8rem; }
.doc li, .facts li { padding-left: 1.1rem; position: relative; }
.doc li::before, .facts li::before { content: ""; position: absolute; left: 0; top: 0.72em; width: 5px; height: 5px; border-radius: 50%; background: var(--mint); }
.doc ul + p { margin-top: 1rem; }
.doc strong { color: var(--text-hi); font-weight: 600; }
.doc section a { color: var(--text-hi); text-decoration: none; border-bottom: 1px solid var(--border-strong); }
.doc section a:hover { color: var(--mint); border-color: var(--mint); }
.footer-meta-link { color: inherit; text-decoration: none; }
.footer-meta-link:hover { color: var(--mint); }

@media (prefers-reduced-motion: reduce) {
  .reveal-coast,
  .reveal-road,
  .reveal-ink { animation: none; stroke-dashoffset: 0; }
  .status .pip { animation: none; }
  /* The parish ticks narrate a sweep that isn't happening, but the caption is
     still owed — the map shows its settled illustrative state either way. */
  .reveal-tick { display: none; }
  .reveal-caption { animation: none; opacity: 1; }
}
