/*
 * The site's whole stylesheet. Values come from design/tokens.json, not from
 * taste - the page has to sit next to the app without arguing with it.
 *
 * Deliberately zero third-party requests: the face, the texture and the type
 * are all served from this origin. A privacy page that phones a CDN home to
 * render itself is a page that contradicts its own text.
 */

@font-face {
  font-family: 'Courier Prime';
  src: url('fonts/CourierPrime-Regular.ttf') format('truetype');
  font-weight: 400;
  font-display: swap;
}

@font-face {
  font-family: 'Courier Prime';
  src: url('fonts/CourierPrime-Bold.ttf') format('truetype');
  font-weight: 700;
  font-display: swap;
}

:root {
  --paper: #e9e1d1;
  --surface: #f1ebdd;
  --ink: #1e1b16;
  --ink-muted: #8a8275;
  --divider: #d8cebc;
  --accent: #b58e7a;
  --accent-text: #8a5240;

  --measure: 34rem;
}

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

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

body {
  margin: 0;
  padding: 0;
  color: var(--ink);
  /* No background here: the textured canvas above shows through. */
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  font-size: 17px;
  line-height: 1.6;
}

/*
 * Two procedural noise layers over the flat fill, the same pair the app
 * composites: grain for the fibre, mottle for the staining. Both are inline
 * SVG so they stay sharp at any density, and both are fixed so a long page
 * does not visibly slide its own paper as it scrolls.
 *
 * Tile, frequency, octaves and seed are paper.grain and paper.mottle in
 * design/tokens.json. The amplitudes are lower than the app's: the app shows
 * the texture behind three shapes, this shows it behind a thousand words, and
 * the app's 0.32 of grain under 17px body text reads as a dirty screen.
 *
 * Layers on the canvas background, NOT a blended pseudo-element. The obvious
 * version - a fixed body::before at z-index -1 with mix-blend-mode: multiply -
 * renders as nothing at all: body creates no stacking context, so a negative
 * z-index child paints behind the canvas background rather than on top of it,
 * and the whole texture disappears under the flat fill. It survives review
 * because the page still looks correct; only measuring the pixels catches it
 * (the crop came back one single value, 0 variance). Do not "tidy" this back
 * into a pseudo-element.
 */
html {
  background-color: var(--paper);
  background-image:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='620' height='620'%3E%3Cfilter id='m'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.038' numOctaves='3' seed='21'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='620' height='620' filter='url(%23m)' opacity='0.09'/%3E%3C/svg%3E"),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' seed='7'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23g)' opacity='0.2'/%3E%3C/svg%3E");
  background-size: 620px 620px, 220px 220px;
  background-attachment: fixed, fixed;
}

/* --- shell ------------------------------------------------------------- */

.page {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 4rem 1.5rem 5rem;
}

/* The mark, at the size it reads as a face rather than as a favicon. */
.mark {
  display: block;
  width: 56px;
  height: 56px;
  border-radius: 23%;
  margin-bottom: 2.5rem;
}

/* --- type -------------------------------------------------------------- */

h1,
h2,
.wordmark {
  font-family: 'Courier Prime', ui-monospace, 'Courier New', monospace;
  font-weight: 400;
  letter-spacing: -0.01em;
}

h1 {
  font-size: 2rem;
  line-height: 1.2;
  margin: 0 0 0.5rem;
}

/* One line under the title: what this is, and when it started saying so. */
.stamp {
  color: var(--ink-muted);
  font-size: 0.9375rem;
  margin: 0 0 3rem;
}

h2 {
  font-size: 1.1875rem;
  margin: 3rem 0 0.75rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--divider);
}

/* The first rule under the stamp would double the stamp's own gap. */
h2:first-of-type {
  margin-top: 0;
}

p {
  margin: 0 0 1rem;
}

ul {
  margin: 0 0 1rem;
  padding-left: 1.25rem;
}

li {
  margin-bottom: 0.375rem;
}

/* The lead paragraph carries the summary, so it gets the weight the
   headings do not. */
.lead {
  font-size: 1.125rem;
}

strong {
  font-weight: 600;
}

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

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

/* --- blocks ------------------------------------------------------------ */

/*
 * A key: the tile the app uses for anything sitting ON the paper rather than
 * IN it. Same surface colour, same continuous-corner feel.
 */
.key {
  background: var(--surface);
  border: 1px solid var(--divider);
  border-radius: 14px;
  padding: 1.25rem 1.375rem;
  margin: 0 0 1rem;
}

.key p:last-child,
.key ul:last-child {
  margin-bottom: 0;
}

/* Things the app does not do. A list of absences, set quieter than a list of
   facts, because that is what it is. */
.none li {
  color: var(--ink-muted);
}

footer {
  margin-top: 4rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--divider);
  color: var(--ink-muted);
  font-size: 0.9375rem;
}

/* Flex with a gap rather than a margin on each link: a trailing margin on the
   last one pulls the centred footer of the holding page off centre. */
footer nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.25rem;
}

.holding footer nav {
  justify-content: center;
}

/* --- landing ----------------------------------------------------------- */

/*
 * index.html only. The apex has to serve something - a bare 404 at the root
 * of a domain whose /privacy App Review is reading looks abandoned - but it
 * is a holding page, not a launch. It says the true thing and stops.
 */
.holding {
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: center;
  align-items: center;
}

.holding .mark {
  width: 88px;
  height: 88px;
  margin-bottom: 2rem;
}

.holding .wordmark {
  font-size: 1.75rem;
  margin: 0 0 0.75rem;
}

.holding p {
  color: var(--ink-muted);
  max-width: 22rem;
}

.holding footer {
  margin-top: 3rem;
  border-top: 0;
  padding-top: 0;
}

@media (max-width: 30rem) {
  .page {
    padding: 3rem 1.25rem 4rem;
  }

  h1 {
    font-size: 1.625rem;
  }
}

/* --- unfilled ---------------------------------------------------------- */

/*
 * A blank that only its owner can fill: a legal name, a postal address. Styled
 * to be impossible to miss rather than tastefully grey, because the failure
 * mode is deploying the page without noticing it is still empty.
 */
.todo {
  background: #ffe9a8;
  border: 1px dashed #b58e7a;
  border-radius: 4px;
  padding: 0.0625rem 0.375rem;
  font-family: 'Courier Prime', ui-monospace, monospace;
  font-size: 0.9375em;
  color: #6b4a12;
}
