/*
 * The site, in the app's design system (`AttunoIosAppDesign`, `ds/foundations`).
 *
 * Every size and gap below is a **named role from that system**, not a number
 * picked by eye. The first version of this file invented its own — 34px titles,
 * 44px gaps — which is exactly what the system was built to stop: "a screen
 * picks a role rather than inventing a number".
 *
 *   Type (`type.html`)     screenTitle 30/1.2/−0.4 · cardTitle 17/1.35 ·
 *                          note 17/1.45 · body 16/1.55 · row 15/1.4 ·
 *                          caption 13/1.5 · eyebrow mono 11/1.5 caps
 *   Spacing (`spacing.html`)  tight 6 · snug 10 · base 16 · loose 22 ·
 *                          section 32 · screen 24
 *   Radius                 control 6 · pill 999, and never on layout
 *
 * Structure is rules and space, never cards: no shadows, no rounded panels.
 *
 * **Light only, on purpose.** The system carries two themes; this takes the
 * light one. A privacy policy and a confirmation page are read once, often out
 * of a mail client, and get printed and screenshotted. `color-scheme: light` is
 * declared rather than left to the device.
 *
 * **No webfonts.** The system pairs IBM Plex Sans and Mono, loaded from Google
 * on its own pages; this site may not — `/verify` carries a confirmation code in
 * its URL and loads nothing third-party (CLAUDE.md), and the CSP allows only
 * this origin. The titles therefore run in the system face at the system's
 * sizes; self-hosting the two families later costs two binaries and a
 * `font-src 'self'` entry.
 */

:root {
  color-scheme: light;

  --bg: #ffffff;
  --surface: #ecf1f2;
  --rule: #ccd3d4;
  --hair: #e0e5e5;
  --text: #0b0b0b;
  --muted: #5d5d5d;
  --accent: #009cb5;
  /* `fragmented` is the system's warning hue: the staging banner and the draft
     notice, both of which say "this is not the real thing yet". Its two siblings,
     `stable` and `drifting`, are deliberately absent — they mean an attention
     state the server computes, and nothing on this site has one. They live in
     `AttunoIosAppDesign` if a page ever genuinely needs them. */
  --fragmented: #9f6300;

  /* The six steps. Nothing here may use a seventh. */
  --tight: 6px;
  --snug: 10px;
  --base: 16px;
  --loose: 22px;
  --section: 32px;
  --screen: 24px;

  /* The stacks carry named faces only; the generic family is written at each
     use site (`var(--sans), sans-serif`). It reads the same to a browser and
     better to everything else: a checker cannot see through `var()`, so a
     generic hidden inside the token looks like a missing one — and if this line
     is ever edited down to a single face, the fallback still stands where the
     property is. */
  --sans: -apple-system, BlinkMacSystemFont, 'SF Pro Text', system-ui;
  --mono: ui-monospace, 'SF Mono', Menlo;
}

* {
  box-sizing: border-box;
}

/* The column holds the footer against the bottom of a short page — `/verify` is
   two lines, and a footer floating mid-screen reads as unfinished. */
body {
  margin: 0;
  padding: 0 var(--screen);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans), sans-serif;
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

/* `dvh` is what the height above actually wants: mobile Safari's toolbars make
   `vh` taller than the visible page, so a footer pinned to `100vh` sits just
   below the fold. Written as a feature query rather than two `min-height` lines
   in a row — same result, but it says "an upgrade where supported" instead of
   looking like one declaration accidentally overwriting another. */
@supports (min-height: 100dvh) {
  body {
    min-height: 100dvh;
  }
}

/* ─ Masthead and footer ─────────────────────────────────────────────────── */

/* `width: 100%` is not decoration. As flex children of the body column, these
   three shrink to their content when both margins are `auto` — the masthead
   collapsed to 239px and the footer to 177px inside a 704px page — so the width
   has to be stated before `max-width` can centre it. */
.masthead,
.colophon,
main {
  width: 100%;
  max-width: 44rem;
  margin-left: auto;
  margin-right: auto;
}

.masthead,
.colophon {
  display: flex;
  flex-wrap: wrap;
  gap: var(--snug) var(--loose);
  align-items: center;
  justify-content: space-between;
}

.masthead {
  padding: var(--base) 0;
  border-bottom: 1px solid var(--rule);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--snug);
  /* cardTitle: the one place a title sits inline with a mark. */
  font-size: 17px;
  font-weight: 500;
  line-height: 1.35;
  color: var(--text);
  text-decoration: none;
}

.brand img {
  display: block;
}

.masthead nav,
.colophon nav {
  display: flex;
  gap: var(--loose);
  font-size: 15px; /* row */
}

.colophon {
  margin-top: var(--section);
  padding: var(--base) 0 var(--section);
  border-top: 1px solid var(--rule);
  color: var(--muted);
  font-size: 13px; /* caption */
}

.colophon nav {
  font-size: 13px;
}

a {
  color: var(--accent);
  text-underline-offset: 2px;
}

a:hover {
  color: var(--text);
}

/* ─ Page body ───────────────────────────────────────────────────────────── */

/* `flex: 1` is what pushes the footer down: main takes the leftover height on a
   short page and nothing on a long one. `min-width: 0` keeps a long unbroken
   string (an address in the policy, say) from stretching the column. */
main {
  flex: 1;
  min-width: 0;
  padding-top: var(--section);
}

/* A measure, not a container: ~68 characters is where a line stops being
   comfortable, and the legal pages are the longest text we will ever publish. */
main p,
main li {
  max-width: 68ch;
}

/* screenTitle */
h1 {
  margin: 0 0 var(--snug);
  font-size: 30px;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.4px;
}

/* cardTitle, with the hairline doing the work a bigger size would otherwise do.
   That is the system's own trade: structure from rules, not from scale. */
h2 {
  margin: var(--section) 0 var(--snug);
  padding-top: var(--base);
  border-top: 1px solid var(--hair);
  font-size: 17px;
  font-weight: 500;
  line-height: 1.35;
}

/* row */
h3 {
  margin: var(--loose) 0 var(--tight);
  font-size: 15px;
  font-weight: 500;
  line-height: 1.4;
}

p {
  margin: 0 0 var(--base);
}

ul {
  margin: 0 0 var(--base);
  padding-left: var(--loose);
}

li {
  margin-bottom: var(--tight);
}

/* The eyebrow is the one place the mono face earns itself: a label that must
   not read as a heading. `tight` under it, because it labels the title. */
.eyebrow {
  margin: 0 0 var(--tight);
  font-family: var(--mono), monospace;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--muted);
}

/* note */
.lede {
  font-size: 17px;
  line-height: 1.45;
}

/* caption */
.muted {
  color: var(--muted);
  font-size: 13px;
}

/* A raised block for a pulled-out claim — never a card with a border. */
.note {
  margin: 0 0 var(--base);
  padding: var(--loose);
  background: var(--surface);
}

.note > :last-child {
  margin-bottom: 0;
}

.updated {
  font-family: var(--mono), monospace;
  font-size: 13px;
  color: var(--muted);
}

/* ─ Environment banner (staging builds only) ────────────────────────────── */

.env-banner {
  margin: 0 calc(var(--screen) * -1);
  padding: var(--tight) var(--screen);
  background: var(--fragmented);
  color: #fff;
  font-family: var(--mono), monospace;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  text-align: center;
}

/* ─ Draft legal pages (remove with the notice when the text is final) ───── */

.draft-note {
  margin: 0 0 var(--section);
  padding: var(--base) var(--loose);
  background: var(--surface);
  color: var(--fragmented);
  font-size: 15px;
  font-weight: 500;
}

/* ─ /verify ─────────────────────────────────────────────────────────────── */

/*
 * No state colour on this page, by decision (2026-09-18). The outcome was shown
 * first by colouring the title, then by a rule, then by a dot — three placements
 * of the same doubtful idea. It had to go for two reasons: the page is one
 * sentence and that sentence already says what happened, in the reader's
 * language, so a mark beside it only asks to be decoded; and the three state
 * hues mean an attention state in the app, computed by the server, which a page
 * outcome is not. `verify.js` still sets `data-outcome` on <body> — it costs
 * nothing, and a future state that genuinely needs showing has it ready.
 */

/* note: the confirmation page is one sentence, and it is the sentence. */
.verify p {
  font-size: 17px;
  line-height: 1.45;
}
