/* ───────────────────────────────────────────────────────────────────────────
   Air Post — the design system, taken out of the app rather than described.

   Every value here has a counterpart in lib/design/. Where the two could
   drift, the app is right and this is wrong: tokens.dart is the source of
   truth for the chrome, accent.dart for the colour, typography.dart for the
   scale. A number invented here is a number that will disagree with the
   product it is advertising.
   ─────────────────────────────────────────────────────────────────────────── */

:root {
  /* ── Colour — lib/design/tokens.dart ───────────────────────────────────
     The page is deliberately pure white, so the scalloped edge of a card
     reads as a cut-out rather than a border. */
  --page: #ffffff;
  --paper: #f3eed7;          /* warm cream card stock */
  --stage: #f0e6e3;          /* the ground a card is viewed against */
  --ink: #000000;
  --ink-muted: rgba(0, 0, 0, 0.54);
  --ink-faint: rgba(0, 0, 0, 0.20);
  --hairline: rgba(0, 0, 0, 0.10);
  --seal: #74222a;           /* the maroon of the house wax */
  --olive: #6f7a63;          /* what the app rings a chosen thing in */

  /* The meadow accent. The front door's green: its own family, not a second
     orange — the app uses orange to mean "act on this", and a welcome screen
     is a different register. The word is not the fill: the green is too light
     to set type in and has a deeper relative for exactly that. */
  --mark: #92d044;
  --rings: #b9e087;
  --word: #6d9a35;

  /* ── Radii — Radii in tokens.dart ─────────────────────────────────── */
  --r-card: 18px;
  --r-pill: 30px;
  --r-sheet: 28px;

  /* ── Perforation — Perf in tokens.dart ─────────────────────────────────
     The Figma card is 381.8pt wide with scallop centres 49.4pt apart and a
     19.0pt radius: a radius/pitch ratio of 0.385. */
  --perf-pitch: 44px;
  --perf-radius: 16.9px;     /* 44 × 0.385 */

  /* ── Motion — Motion in tokens.dart ───────────────────────────────── */
  --fast: 180ms;
  --medium: 320ms;
  --slow: 620ms;
  --ease: cubic-bezier(0.2, 0.8, 0.2, 1);

  /* ── Measure ─────────────────────────────────────────────────────── */
  --gutter: clamp(20px, 5vw, 40px);
  --max: 1120px;
  --max-prose: 34rem;
}

/* ── Type ────────────────────────────────────────────────────────────────
   Instrument Serif keeps every display style — headings, the wordmark, the
   postcard headlines. Mint Grotesk sets everything read as interface.

   Rubik sits behind Mint Grotesk on purpose and is load bearing, not belt and
   braces: the bundled cut is the **trial**, which is 66 glyphs — A-Z, a-z,
   0-9, comma, full stop, space. No apostrophe, no hyphen, no accent. CSS
   falls back per glyph, so "Amelia's trip" keeps its apostrophe instead of
   dropping it. See assets/fonts/LICENCE.md before this goes anywhere public.
   ────────────────────────────────────────────────────────────────────── */
@font-face {
  font-family: "Instrument Serif";
  src: url("../fonts/instrument-serif-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Instrument Serif";
  src: url("../fonts/instrument-serif-400-italic.woff2") format("woff2");
  font-weight: 400; font-style: italic; font-display: swap;
}
@font-face {
  font-family: "Mint Grotesk";
  src: url("../fonts/mint-grotesk-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Mint Grotesk";
  src: url("../fonts/mint-grotesk-500.woff2") format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Mint Grotesk";
  src: url("../fonts/mint-grotesk-700.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Rubik";
  src: url("../fonts/rubik-var.woff2") format("woff2");
  font-weight: 300 700; font-style: normal; font-display: swap;
}

:root {
  --font-ui: "Mint Grotesk", "Rubik", -apple-system, BlinkMacSystemFont,
    "Segoe UI", sans-serif;
  --font-display: "Instrument Serif", Georgia, "Times New Roman", serif;
}

/* ── Reset ───────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
/* `hidden` is a user-agent `display: none`, which any class that sets display
   outruns. `.pill` is `inline-flex`, so a hidden pill was showing. */
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

body {
  margin: 0;
  background: var(--page);
  color: var(--ink);
  font-family: var(--font-ui);
  /* The app sets body at 17/20. That leading is right on a 402pt phone and
     too tight for a column of web prose, so the size is kept and the leading
     is opened up. */
  font-size: 1.0625rem;
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

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

h1, h2, h3 {
  font-family: var(--font-display);
  /* The display serif ships one upright face and one italic and nothing
     heavier. Stating the weight stops a browser synthesising a bold, which at
     heading size reads as smeared rather than strong. */
  font-weight: 400;
  margin: 0;
  letter-spacing: -0.005em;
}

h1 { font-size: clamp(2.6rem, 6.4vw, 4.25rem); line-height: 1.07; }
h2 { font-size: clamp(2rem, 4.2vw, 3rem);      line-height: 1.14; }
h3 { font-size: clamp(1.35rem, 2.2vw, 1.7rem); line-height: 1.22; }

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }

/* The accented word: colour and italic alone, no rule under it. */
.accent { font-style: italic; color: var(--word); }

.lede {
  font-size: clamp(1.1rem, 1.6vw, 1.3rem);
  line-height: 1.5;
  color: var(--ink-muted);
  max-width: var(--max-prose);
}

/* Small all-caps, as on the stamps and the postmarks. */
.eyebrow {
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 0.9rem;
}

.muted { color: var(--ink-muted); }

/* ── Layout ──────────────────────────────────────────────────────────── */
.wrap {
  width: 100%;
  max-width: var(--max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

section { padding-block: clamp(4rem, 9vw, 7.5rem); }
.section-head { max-width: 46rem; margin-bottom: clamp(2rem, 4vw, 3.25rem); }
.section-head p { margin-top: 1rem; }

/* ── Paper ───────────────────────────────────────────────────────────────
   The app's paper texture is three layers at different scales — broad
   mottling, short fibres, a dot field — over a fine grain. Any one alone
   reads as digital noise, which is why there are three here too.

   It is tuned per tone in the app for a real reason: warm flecks that read as
   fibre on cream read as dirt on white. So the white surface gets a lighter
   hand than the cream one.
   ────────────────────────────────────────────────────────────────────── */
.paper { background-color: var(--paper); position: relative; isolation: isolate; }
.paper::before,
.stage::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    /* dot field */
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='a'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23a)' opacity='0.55'/%3E%3C/svg%3E"),
    /* short fibres */
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='320' height='320'%3E%3Cfilter id='b'%3E%3CfeTurbulence type='turbulence' baseFrequency='0.14 0.02' numOctaves='2'/%3E%3C/filter%3E%3Crect width='320' height='320' filter='url(%23b)' opacity='0.35'/%3E%3C/svg%3E"),
    /* broad mottling */
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='600' height='600'%3E%3Cfilter id='c'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.012' numOctaves='2'/%3E%3C/filter%3E%3Crect width='600' height='600' filter='url(%23c)' opacity='0.4'/%3E%3C/svg%3E");
  background-size: 120px 120px, 320px 320px, 600px 600px;
  mix-blend-mode: multiply;
  opacity: 0.055;
}
.stage { background-color: var(--stage); position: relative; isolation: isolate; }

/* The stamp edge. Bites of page colour taken out of the bottom of a paper
   band — the same scallop the app cuts into a PerforatedCard, at the same
   radius-to-pitch ratio. */
.perf {
  height: var(--perf-radius);
  background-color: var(--paper);
  background-image: radial-gradient(
    circle var(--perf-radius) at calc(var(--perf-pitch) / 2) 100%,
    var(--page) 99.4%, transparent 100%
  );
  background-size: var(--perf-pitch) 100%;
  background-repeat: repeat-x;
}
.perf.on-stage { background-color: var(--stage); }
.perf.flip {
  background-image: radial-gradient(
    circle var(--perf-radius) at calc(var(--perf-pitch) / 2) 0,
    var(--page) 99.4%, transparent 100%
  );
}

/* ── The pill ────────────────────────────────────────────────────────────
   Black pill, white label, rings showing through. It does not invert and it
   does not take the accent: the app's one primary action is ink-black on both
   stocks, because a control that turns into its own opposite between two
   settings is two controls.
   ────────────────────────────────────────────────────────────────────── */
.pill {
  --pill-fill: var(--ink);
  --pill-ink: var(--page);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  min-height: 56px;
  padding: 0 2rem;
  border: 0;
  border-radius: var(--r-pill);
  background-color: var(--pill-fill);
  /* The blob field behind a dark pill — AppColors.blobOnDark. */
  background-image:
    radial-gradient(circle at 14% 130%, rgba(255,255,255,0.16), transparent 42%),
    radial-gradient(circle at 78% -40%, rgba(255,255,255,0.13), transparent 46%),
    radial-gradient(circle at 52% 150%, rgba(255,255,255,0.10), transparent 38%);
  color: var(--pill-ink);
  font-family: var(--font-ui);
  font-size: 1.0625rem;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  transition: transform var(--fast) var(--ease), opacity var(--fast) var(--ease);
}
.pill:hover { transform: translateY(-1px); }
.pill:active { transform: translateY(0); opacity: 0.9; }

/* The welcome screen's primary action wears the accent — with the label in
   ink rather than reversed out of it. At that lightness white type on the
   fill is the one thing on the screen you cannot read. */
.pill.accent-fill {
  --pill-fill: var(--mark);
  --pill-ink: var(--ink);
  background-image:
    radial-gradient(circle at 14% 130%, rgba(255,255,255,0.28), transparent 42%),
    radial-gradient(circle at 78% -40%, rgba(255,255,255,0.22), transparent 46%);
  font-style: normal;
}

.pill.ghost {
  --pill-fill: transparent;
  --pill-ink: var(--ink);
  background-image: none;
  box-shadow: inset 0 0 0 1px var(--ink-faint);
}
.pill.small { min-height: 44px; padding: 0 1.35rem; font-size: 0.9375rem; }

:where(a, button, summary):focus-visible {
  outline: 2px solid var(--olive);
  outline-offset: 3px;
  border-radius: 4px;
}

/* ── Header ──────────────────────────────────────────────────────────── */
.masthead {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--page) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(14px);
  border-bottom: 1px solid var(--hairline);
}
.masthead .wrap {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 68px;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  margin-right: auto;
}
/* "airpost", beside the mark. Regular, not medium: the design sets the name
   lighter than everything under it. */
.wordmark {
  font-family: var(--font-ui);
  font-size: 1.375rem;
  font-weight: 400;
  letter-spacing: -0.01em;
}
.nav { display: flex; align-items: center; gap: 1.6rem; }
.nav a {
  font-size: 0.9375rem;
  font-weight: 500;
  text-decoration: none;
  color: var(--ink-muted);
  transition: color var(--fast) var(--ease);
}
.nav a:hover, .nav a[aria-current="page"] { color: var(--ink); }
/* A pill in the nav is a pill first. Without this the more specific `.nav a`
   colour wins and the label goes dark grey on a black fill — which is to say
   invisible. */
.nav a.pill { color: var(--pill-ink); }
.nav a.pill:hover { color: var(--pill-ink); }
@media (max-width: 760px) {
  .nav .hide-sm { display: none; }
}
/* On a phone the masthead is the mark and one action. Three words and a pill
   do not fit beside the wordmark at 390pt, and a nav that wraps under itself
   reads as a broken header — the footer carries every link anyway. */
@media (max-width: 620px) {
  .nav { gap: 0; }
  .nav a:not(.pill) { display: none; }
}

/* ── Footer ──────────────────────────────────────────────────────────── */
.footer { padding-block: 3.5rem 2.5rem; border-top: 1px solid var(--hairline); }
.footer-grid {
  display: grid;
  gap: 2.5rem;
  grid-template-columns: 1.4fr repeat(2, minmax(0, 1fr));
}
@media (max-width: 720px) { .footer-grid { grid-template-columns: 1fr 1fr; } }
.footer h4 {
  font-family: var(--font-ui);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin: 0 0 0.9rem;
}
.footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.footer a { text-decoration: none; font-size: 0.9375rem; }
.footer a:hover { text-decoration: underline; text-underline-offset: 3px; }
.colophon {
  margin-top: 3rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--hairline);
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 2rem;
  align-items: baseline;
  font-size: 0.8125rem;
  color: var(--ink-muted);
}

/* ── Prose pages: privacy, terms, support ────────────────────────────── */
/* A measure, not a centred column. Setting max-width on the .wrap itself
   makes the whole block narrow and `margin-inline: auto` then centres it, so
   the text starts halfway across the page while every other page starts at
   the masthead's gutter. Constrain the children instead. */
.wrap.prose { max-width: var(--max); }
.wrap.prose > * { max-width: 40rem; }
.prose h2 { font-size: clamp(1.5rem, 2.6vw, 1.9rem); margin: 2.75rem 0 0.9rem; }
.prose h3 {
  font-family: var(--font-ui);
  font-size: 1rem;
  font-weight: 500;
  margin: 1.75rem 0 0.5rem;
}
.prose ul { padding-left: 1.15rem; margin: 0 0 1.1em; }
.prose li { margin-bottom: 0.45rem; }
.prose a { text-underline-offset: 3px; }
.prose .updated {
  font-size: 0.8125rem;
  color: var(--ink-muted);
  margin-top: 0.75rem;
}
