/*
  The app's own tokens, on a web page. Every value here is copied from
  app/src/theme/index.js rather than eyeballed — the site is the app's second
  surface, not a marketing skin over it, and the whole design argument (six
  colours, no cards, hierarchy from weight and spacing, a list is rules on the
  ground) survives the trip intact.

  Two departures, both deliberate:

  · The site FOLLOWS the browser's appearance, where the app declares its own.
    The app can declare because it owns its whole screen and Profile hands the
    declaration back to the user; a web page has no such settings row, and a
    white flash on a phone held in the dark is a worse failure than a page that
    isn't drawn dark-first. Both halves are the palette's real pairs, so it is
    the same app either way.

  · Points become px 1:1 and the column is capped in rem. The app's 24pt gutter
    is a phone constant; here the same figure has to hold on a 27" monitor, so
    the type sizes are absolute (the app's rule — never scaled by device width)
    and the MEASURE is what's bounded.
*/

:root {
  /* PAIRS, dark half — theme/index.js */
  --ground: #000000;
  --ink:    #F5F5F7;
  --dim:    #8E8E93;
  --faint:  #48484A;
  --rule:   #2A2A2C;
  --accent: #2997FF;
}

@media (prefers-color-scheme: light) {
  :root {
    /* PAIRS, light half. Apple's counterparts, chosen to match the CONTRAST
       rather than the position in the grey ramp — see the theme header. dim is
       the one value with no counterpart, and it stays #8E8E93 by founder ruling. */
    --ground: #FFFFFF;
    --ink:    #1D1D1F;
    --dim:    #8E8E93;
    --faint:  #AEAEB2;
    --rule:   #D1D1D6;
    --accent: #007AFF;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  /* One family: SF. Same ruling as the app — there is no bundled face and no
     mono. -apple-system gets SF on Apple platforms and the local UI font
     everywhere else, which is the right answer for a page whose entire audience
     arrives from an App Store listing. */
  font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, "Segoe UI", Roboto, sans-serif;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* GUTTER = 24. The max-width is the one value with no counterpart in the app:
   a phone column is 327pt wide and a desktop window is not, so the measure is
   bounded here instead of the gutter growing. */
.wrap {
  max-width: 36rem;
  margin: 0 auto;
  padding: 0 24px 96px;
}

/* ── Type, by role ────────────────────────────────────────────────────────── */

/* TEXT.label — the tracked caps that set context at the top of a screen. */
.eyebrow {
  margin: 48px 0 0;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--dim);
}
.eyebrow a { color: var(--dim); text-decoration: none; }
.eyebrow a:hover { color: var(--ink); }

/* TEXT.masthead, and the app's two-line shape: the name in ink, then what it is
   in dim under it. The <span> is the second line, not a subtitle element — same
   object, one step back. */
h1 {
  margin: 24px 0 0;
  font-size: 40px;
  line-height: 42px;
  font-weight: 700;
  letter-spacing: -0.040em;
}
h1 span {
  display: block;
  color: var(--dim);
}

/* TEXT.meta — the timestamp voice. */
.updated {
  margin: 20px 0 0;
  font-size: 13px;
  line-height: 18px;
  letter-spacing: -0.010em;
  color: var(--dim);
}

/* TEXT.row — the app's one convention for prose: ONE opening sentence a step up
   at 19, every paragraph under it at body/23. A reader meeting it on five
   screens knows the 19px line is the sentence to read if they read nothing
   else. */
.lead {
  margin: 32px 0 0;
  font-size: 19px;
  line-height: 26px;
  letter-spacing: -0.024em;
  color: var(--ink);
}

/* TEXT.micro over a rule. The rule belongs UNDER the heading, not over it:
   over it, a line closes the section above and orphans the heading below. Same
   shape LegalScreen and ScoringScreen use. */
h2 {
  margin: 40px 0 0;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--rule);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.100em;
  text-transform: uppercase;
  color: var(--dim);
}

/* TEXT.body at the row role's line-height ratio — body has none of its own in
   the app because it was drawn for a single line. Ink, not dim: on a page that
   is prose from the masthead down there is nothing to be subordinate TO, and
   dim body text makes the whole screen read as a footnote (ScoringScreen learnt
   this on 2026-08-08). */
p {
  margin: 14px 0 0;
  font-size: 17px;
  line-height: 23px;
  letter-spacing: -0.022em;
  color: var(--ink);
}

/* ⚠ There are no `ul` rules and that is the decision, not an omission. This
   selector carried `li` and a faint ::marker until 2026-08-10, for index.html's
   Pages list — the site's only bulleted list, and the only place it was written
   in the browser's grammar instead of the app's. The app has no bullet
   anywhere: a list is rows and rules (see `.rows` below). Reaching for `<ul>`
   here means the same thing wants drawing again, and it should be drawn the
   way the app draws it. */

a { color: var(--accent); }

/* ── A list is rules on the ground ────────────────────────────────────────── */
/*
  index.html's Pages list, ported from the app rather than styled here: a list
  in this design has no bullets, no card and no fill — it is rows separated by
  1pt rules, and a row is a name with a dim line under it. ⚠ The rule is a
  BORDER here and a <View> in the app, and that difference is not a drift: the
  app's rule is a View because a DynamicColorIOS border flattens to whichever
  appearance was current when it was set (see the theme header). CSS custom
  properties re-resolve on the media query, so a border is safe on the web and
  is the simpler thing.

  Three roles, all the app's own values. The name is TEXT.row/19 in ink; the
  line under it is TEXT.meta/13 in faint at marginTop 5 — ConfirmScreen's
  candidate rows exactly, where a dish name carries its ingredients underneath
  so two lookalikes can be told apart. The 14px a side is ROW_PAD, the one row
  padding the whole app uses.

  The → is Profile's ruling, not decoration: an arrow in a list of rows means
  the row is a PAGE, and it is faint rather than ink because it has to lose to
  the name it belongs to. It is also what tells a mouse this is a link, since
  the name stays ink — the web's blue would put the loudest colour on the page
  on four rows that are simply the site's contents.

  ⚠ The arrow belongs to the ROW, not to the name, so it hangs off the anchor
  and the anchor is the flex container. It was inside `.rowname` first and sat
  on the name's baseline with the dim line hanging below it, which reads as an
  arrow pointing at the title rather than at the row — Profile's rows are one
  line, so nothing there had settled where it goes on two. Centred against both
  lines: what a press opens is the whole row.
*/
.rows { margin-top: 0; }
.rows a {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 0;
  border-bottom: 1px solid var(--rule);
  color: var(--ink);
  text-decoration: none;
}
.rows a::after {
  content: '→';
  flex: none;
  /* The name's own size, so the two read as one row — the same relation
     Profile's larrow keeps (19 against a 19pt name). */
  font-size: 19px;
  line-height: 26px;
  color: var(--faint);
}
.rowtext { flex: 1; min-width: 0; }
.rowname {
  display: block;
  font-size: 19px;
  line-height: 26px;
  letter-spacing: -0.024em;
}
.rowmeta {
  display: block;
  margin-top: 5px;
  font-size: 13px;
  line-height: 18px;
  letter-spacing: -0.010em;
  color: var(--faint);
}
.rows a:hover .rowname { color: var(--accent); }

/* ── Footer ───────────────────────────────────────────────────────────────── */

footer {
  margin-top: 64px;
  padding-top: 20px;
  border-top: 1px solid var(--rule);
}
footer p {
  margin: 0;
  font-size: 13px;
  line-height: 18px;
  letter-spacing: -0.010em;
  color: var(--dim);
}
footer a { color: var(--dim); text-decoration: none; }
footer a:hover { color: var(--ink); }
.colophon { margin-top: 8px; color: var(--faint); }
/* index.html has no link row — its four links are the page itself — so the
   copyright is the whole footer and the 8 above it was air between two lines
   that no longer both exist. */
footer .colophon:only-child { margin-top: 0; }

/* A footer with nothing in it but the copyright takes no rule (`class="bare"`,
   index.html, 2026-08-10). The rule under a footer's link row is what separates
   the page from the way out of it; with the links gone it was separating the
   page from a single dim line, and index's list already ends in a rule of its
   own four rows up — two closing rules on one short page, the second closing
   nothing. The 64 above it stays: that space is what makes the line a footer
   now, where the rule used to. ⚠ A class rather than :has(), which is not
   universal — a footer that silently keeps its rule in an older Safari is the
   fix half-failing where nobody would look. */
footer.bare {
  padding-top: 0;
  border-top: 0;
}

/* ── The support form ─────────────────────────────────────────────────────── */
/*
  The one place this site has a filled field, which the APP deliberately has
  none of ("no cards, no filled fields, no segmented controls"). A page that
  posts a message has to show where the words go, and a bare underline on a
  black ground reads as a broken layout in a browser the way it never does on a
  phone. Kept as quiet as it can be: the app's own rule colour for the border,
  the ground itself for the fill.

  ⚠ These rules were deleted on 2026-08-08 with the form and restored the same
  day with it — the argument above is the one that justified them the first
  time and it did not change. What changed is the reason the form exists: not
  "a page that takes a message" as a nicety, but that removing it left the
  privacy policy's Contact section pointing at the App Store's support link,
  which resolves to this site, which offered no way to reach anyone. See
  support.html.
*/
label {
  display: block;
  margin: 24px 0 8px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.100em;
  text-transform: uppercase;
  color: var(--dim);
}
textarea, input[type="email"] {
  width: 100%;
  padding: 12px;
  background: var(--ground);
  color: var(--ink);
  border: 1px solid var(--rule);
  border-radius: 8px;
  font-family: inherit;
  font-size: 17px;
  line-height: 23px;
  letter-spacing: -0.022em;
}
textarea { min-height: 9rem; resize: vertical; }
textarea:focus, input[type="email"]:focus {
  outline: none;
  border-color: var(--accent);
}
button {
  margin-top: 20px;
  padding: 14px 24px;
  background: var(--accent);
  color: #FFFFFF;
  border: 0;
  border-radius: 8px;
  font-family: inherit;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.022em;
  cursor: pointer;
}
button:hover { opacity: 0.9; }

/* What the script writes under the button. TEXT.meta, the timestamp voice —
   the same size and colour the "Last updated" line uses, because this is the
   same kind of sentence: the page reporting on itself rather than addressing
   the reader. ⚠ No green and no red. The palette has six colours and neither
   is among them, and the app's whole argument is that hierarchy comes from
   weight and spacing — so success is the message stepping up to ink while the
   Send button leaves, and failure is the button still sitting there under it.
   The state is the layout, not a hue. */
.formstatus {
  margin: 16px 0 0;
  font-size: 13px;
  line-height: 18px;
  letter-spacing: -0.010em;
  color: var(--dim);
}
.formstatus:empty { display: none; }
.formstatus.sent { color: var(--ink); }
