/* Flock marketing site.
 *
 * One green screen: the wordmark, the flock loop under it at the middle of the
 * page, a disabled "Coming Soon" pill below that, and a footer line. There is no
 * second section and nothing to scroll to — if you are adding one, this file is
 * the wrong shape for it.
 *
 * Colour tokens are lifted from the iOS design system
 * (Flock-iOS/Packages/FlockDesign/Sources/FlockDesign/ThemePalette.swift) so the
 * site and the app agree. `--green` is the launch screen's background — the
 * flock loop over it reproduces the app's launch animation exactly, which is the
 * point of using it.
 */

:root {
  --green: #3A7D5C;                        /* launchBackground light */
  --on-green: #FFFFFF;
  /* DISABLED CONTROLS ONLY — not for text. Over `--green` in light mode this
     composites to #C8DBD1, which is 3.4:1: below WCAG AA's 4.5:1 for body copy.
     Raising the alpha does not rescue it, because the light green is the
     constraint rather than the alpha — even pure white on #3A7D5C is only
     4.92:1, and 0.9 alpha is 4.33:1. So anything that has to be *read* uses
     `--on-green`, and this token is reserved for the "Coming Soon" pill, which
     WCAG 1.4.3 exempts as an inactive component. (Dark mode is comfortable
     either way: 5.67:1 at this alpha.) Keeping the split this way means the
     contrast rule stays "dimmed is only ever a disabled control" as the page
     grows, rather than needing a per-element audit. */
  --on-green-dim: rgba(255, 255, 255, 0.72);
  --on-green-rule: rgba(255, 255, 255, 0.38);
  --on-green-fill: rgba(255, 255, 255, 0.10);

  /* The app's display face is SF Rounded — `Design.UI.roundedTitleFont` builds it
     from `fontDescriptor.withDesign(.rounded)`. `ui-rounded` is how CSS asks for
     that same face, so the web wordmark and the one on the phone are the same
     typeface rather than a lookalike.
     NOTE: Helvetica Rounded is listed but will never be hit on an Apple device —
     neither macOS nor iOS ships it. It (and Arial Rounded MT Bold, which they do
     ship) are here for non-Apple platforms, where `ui-rounded` resolves to
     nothing rounded at all and the stack degrades to plain system-ui. */
  --font-rounded: ui-rounded, "SF Pro Rounded", "Helvetica Rounded",
                  "Arial Rounded MT Bold", system-ui, -apple-system, sans-serif;

  /* The flock's width, FIXED — it deliberately does not grow with the viewport.
     0.5 × screen width is `LaunchFlockView.bandWidthFraction` on iOS, so on a
     phone this is the same size band as the splash screen.

     `min()` takes the SMALLER operand, so the 220px is what wins on viewports
     WIDER than 440px — it is a ceiling, not a floor, and the vw branch is the
     one that applies on phones. 220 is chosen as exactly 50vw of the widest
     iPhone in portrait (440pt, the 16 Pro Max), so every current phone takes
     the vw branch and the iOS parity is exact; landscape and desktop are held
     flat. At 200px the cap instead bit from 402pt upward, leaving the 16 Pro
     Max 9% narrow — the same class of silent mismatch as measuring the band
     against `.hero`'s padded box. A phone wider than 440pt would start being
     capped, which is the number to revisit.

     `vw`, NOT `%`. A percentage resolves against this element's containing
     block — `.hero`'s *content* box, i.e. viewport minus its 1.5rem side
     padding and minus any safe-area inset — so it came out ~12% narrower than
     the app (172.5px vs 196.5pt on a 393pt iPhone). `bandWidthFraction` is a
     fraction of the whole screen, and `vw` is the unit that means that. Keep it
     independent of `.hero`'s padding or the invariant quietly stops holding.

     The loop's 20:9 is also the band's 160:72 aspect, so height follows from
     width and needs no rule. */
  --flock-width: min(220px, 50vw);
  --wordmark-size: 3rem;
}

@media (prefers-color-scheme: dark) {
  :root {
    --green: #24503B;                      /* launchBackground dark */
  }
}

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

/* The green goes on <html> as well as <body> so it also paints the rubber-band
   overscroll area in mobile Safari — a background only on <body> stops at the
   document box and the bounce exposes the browser's own backdrop. Together with
   `viewport-fit=cover` and the `theme-color` metas (both in index.html) that is
   the full set: overscroll, safe-area insets, and toolbar tint respectively. */
html {
  background: var(--green);
  -webkit-text-size-adjust: 100%;

  /* No rubber-band bounce. This kills the overscroll *glow/bounce past the
     edges* without disabling scrolling itself, so the page still scrolls
     normally in the one case that needs it — a viewport too short for the
     content, e.g. a phone in landscape. That is why this is the right lever and
     `overflow: hidden` / `position: fixed` on <body> is not: those would also
     strand a landscape visitor on content they cannot reach.
     Note it disables pull-to-refresh too, which on a static page costs nothing.
     Unsupported before iOS 16, where the bounce simply remains — and lands on
     green either way, because <html> is painted above. */
  overscroll-behavior: none;
}

body {
  margin: 0;
  background: var(--green);
  color: var(--on-green);
  font: 400 17px/1.6 var(--font-rounded);
  -webkit-font-smoothing: antialiased;

  /* `svh` is the *small* viewport height — the page is sized as if Safari's
     toolbars are showing, so it never grows or jumps as they collapse on scroll.
     `vh` first as the fallback for anything without svh support. */
  min-height: 100vh;
  min-height: 100svh;

  /* Horizontal safe-area padding matters in landscape on a notched phone, where
     the inset is on the side rather than the top. */
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);

  /* Equal `1fr` above and below the hero centres it at exactly 50% of the page
     whatever the wordmark and video measure — that is the whole reason for the
     empty first row. Row 3 (`.below`) takes the rest and places the pill and the
     footer inside it. The `fr` rows collapse before the `auto` ones are squeezed,
     so a short viewport degrades to a normal stacked page instead of overlapping. */
  display: grid;
  grid-template-rows: 1fr auto 1fr;
}

/* ── Hero: wordmark over the flock, dead centre of the page ─────────────── */

.hero {
  grid-row: 2;
  display: grid;
  justify-items: center;
  padding: 0 1.5rem;
  /* Also painted green (identical to the page) purely so the video below has a
     guaranteed opaque box to blend against — see `mix-blend-mode` on .hero__flock. */
  background: var(--green);
}

.wordmark {
  margin: 0 0 0.5rem;
  font-family: var(--font-rounded);
  /* Fixed, not `clamp()`d against the viewport: the wordmark is sized to sit
     over a fixed-width flock, so scaling one without the other breaks the pair. */
  font-size: var(--wordmark-size);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.01em;
  color: var(--on-green);
}

.hero__flock,
.hero__still {
  display: block;
  width: var(--flock-width);
  height: auto;
  /* Black backing, and it is NOT decorative: `screen` treats black as a no-op
     (result = 1-(1-a)(1-b)), so a black layer contributes exactly nothing to the
     page. What it buys is the failure mode — any instant this element paints
     itself rather than a frame (a `load()` that empties it, a layer allocated
     before the poster decodes) it composites as black-under-screen, i.e.
     invisibly, instead of as WHITE, which under `screen` is opaque white over
     everything behind it. The pixels are identical in the normal case; only the
     transient differs. */
  background: #000;
  /* The encode is opaque white-on-black. `screen` keeps the white and drops the
     black to fully transparent against any backdrop: result = 1-(1-a)(1-b), so
     black contributes nothing. Do NOT swap this for an alpha video — one opaque
     H.264 decodes everywhere, and this way the bird colour is a CSS variable. */
  mix-blend-mode: screen;
}

/* The still is the DEFAULT; the video is revealed only once script has opted into
   motion. Reduced motion is handled by never setting the video's `src` (see
   index.html), not here: `display: none` does not cancel a media load, so a
   CSS-only rule would download the whole 2.4 MiB and then hide it — the opposite
   of the intent.

   The swap happens as soon as script opts in, NOT once the video reports
   `playing`. Waiting for `playing` would deadlock on iOS Safari: WebKit won't
   start a video that isn't in the render tree, so a `display: none` element
   waiting to become visible never fires the event that would reveal it. The
   video's own `poster` covers the gap until the first frame decodes, and also
   covers a refused autoplay — so there's no bare-background state to guard. */
.hero__flock { display: none; }
.hero__still { display: block; }

.motion .hero__flock { display: block; }
.motion .hero__still { display: none; }

/* ── Below the flock: the pill, then the footer ─────────────────────────── */

/* Equal `1fr` above and below the pill again — here that centres it between the
   bottom of the flock and the top of the footer, i.e. halfway down the lower
   half of the page. The footer is the last row, so it sits on the bottom edge. */
.below {
  grid-row: 3;
  display: grid;
  grid-template-rows: 1fr auto 1fr auto;
  justify-items: center;
}

.cta {
  grid-row: 2;
  margin: 0;
}

.cta__button {
  /* Disabled in the markup, so this only has to look the part: the pill never
     lights up, never moves, and takes no pointer. */
  margin: 0;
  padding: 0.7rem 1.5rem;
  border: 1px solid var(--on-green-rule);
  border-radius: 999px;
  background: var(--on-green-fill);
  color: var(--on-green-dim);
  font-family: inherit;
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: default;
  /* Safari dims a disabled button to ~50% on its own, which on this background
     reads as a rendering fault rather than a deliberate state — the colours above
     already carry the "not yet" meaning. */
  opacity: 1;
  -webkit-appearance: none;
  appearance: none;
}

.foot {
  grid-row: 4;
  /* Full white, not the dim token — this is body copy at 0.8rem, too small for
     the large-text allowance, and the dim token is 3.4:1 here. See the token. */
  color: var(--on-green);
  font-size: 0.8rem;
  text-align: center;
  /* The inset keeps the line clear of the home indicator; the 1.25rem is the
     floor for devices that have no inset to report. */
  padding: 1.25rem 1.5rem calc(1.25rem + env(safe-area-inset-bottom));
}

.foot p { margin: 0; }

/* ── 404 ────────────────────────────────────────────────────────────────── */

/* Same green field as the landing page (`404.html` loads this same stylesheet —
   there is no second one). Its own layout lives in that file. */
.notfound a {
  color: var(--on-green);
  text-underline-offset: 0.2em;
}
