/* Sanndir — semantic CSS, native nesting. Class names describe content and role.
 *
 * The source of truth for the visual design. handoff/ holds the static mockups this came from;
 * they are the reference, this file is the living stylesheet. Changes belong here.
 *
 * Fonts are self-hosted rather than loaded from a CDN — see public/fonts/README.md. Both faces
 * fall back to a system stack, so a missing file costs typography and nothing else.
 */

/* Uncomment both blocks once the two .woff2 files are in public/fonts/. Commented out rather than
 * left dangling: a missing font URL is served the SPA fallback, which the browser then tries to
 * parse as a font.
 *
@font-face {
  font-family: "Archivo";
  src: url("/fonts/archivo-variable.woff2") format("woff2-variations");
  font-weight: 400 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "IBM Plex Mono";
  src: url("/fonts/ibm-plex-mono-regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
*/

:root {
  color-scheme: dark light;

  --ink: #14120f;
  --slate: #232019;
  --bone: #f4efe5;
  --charcoal: #2b2b2b;
  --white: #ffffff;
  --ash: #c9bfae;
  --brass: #c79a4e;
  --verdigris: #5e8a7e;
  --clay: #a25630;

  --background: var(--ink);
  --surface: var(--slate);
  --text: var(--bone);

  /* Quiet text, and there is exactly one grade of it.
   *
   * `--ash` is a dark-theme colour: it reads as quiet only when fading into ink, and applied
   * directly at any alpha it composites to about 1.2:1 on bone. So a palette entry defines tokens
   * and is never applied to an element; `test/contrast.test.ts` keeps that true. */
  --muted: color-mix(in oklab, var(--ash) 65%, transparent);  /* 5.0:1 on ink */

  /* Two kinds of line, and only one of them is decoration. `--hairline` separates things that are
   * read (rows in a list, a rule above the age gate). `--edge` is the boundary of something you
   * operate (a field's underline, a checkbox, an unpressed segment), and it carries 3:1, because a
   * control whose edge cannot be seen is a control nobody knows is there. */
  --hairline: color-mix(in oklab, var(--ash) 14%, transparent);
  --edge: color-mix(in oklab, var(--ash) 48%, transparent);    /* 3.3:1 on ink */

  --accent: var(--brass);

  /* What is written *on* the accent fill: ink in both themes, because the fill is brass in both and
   * nothing about it changes with the page behind it. Hence no override in the light block below. */
  --accent-text: var(--ink);

  /* The accent as *text*, which is a different job: brass on bone is 2.2:1, so links, headings and
   * focus rings take this one and light mode darkens it. */
  --accent-strong: var(--brass);

  --evidence: color-mix(in oklab, var(--verdigris) 78%, var(--bone));
  --alert: var(--clay);

  --voice: "Archivo", system-ui, sans-serif;
  --numerals: "IBM Plex Mono", ui-monospace, monospace;

  --measure: 19rem;
  --gutter: 1.625rem;
  --radius: 0.5rem;

  /* Set from JS while a phone keyboard is open, and only where the browser does not shrink the
   * layout viewport itself. `.session` is the one rule that reads it. */
  --keyboard-inset: 0px;

  /* One type scale, six steps, each with a job. A screen picks from it rather than choosing a
   * number; a size outside it is a decision to argue for rather than a number to nudge. The
   * transcript, the composer and the persona sheet set their own on purpose. */
  --type-hint: 0.6875rem;    /* uppercase labels, the step counter, the disclosure line */
  --type-fine: 0.8125rem;    /* fine print: asides, agreed details, notes beside an action */
  --type-body: 0.9375rem;    /* anything read as prose */
  --type-action: 1rem;       /* the filled button, and the fields somebody types into */
  --type-heading: 1.125rem;  /* a heading over a list, or inside a sheet */
  --type-title: 1.375rem;    /* the heading of a screen */

  /* And one spacing scale. `--gutter` is the horizontal inset everywhere, so a button cannot end up
   * a quarter of a rem wider than the words above it. */
  --space-xs: 0.375rem;
  --space-sm: 0.625rem;
  --space-md: 0.875rem;
  --space-lg: 1.25rem;
}

/* Light mode, twice: the explicit choice and the system preference. **The two blocks must stay
 * identical** — a token added to one is a colour that is right in half of light mode, and nobody
 * finds that by looking. `test/contrast.test.ts` compares them.
 *
 * Solid colours rather than alpha: a percentage of a pale grey has a floor it cannot pass on a pale
 * page, so anything that has to convey something is a measured colour. */
[data-theme="light"], :root:has(.theme-light) {
  --background: var(--bone);
  --surface: var(--white);
  --text: var(--charcoal);
  --muted: #6b6259;          /* 5.2:1 on bone; the old 82 % mix of #6c6459 was 3.6:1 */
  --hairline: color-mix(in oklab, var(--charcoal) 14%, transparent);
  --edge: #898279;           /* 3.3:1 on bone */
  --accent-strong: #856016;  /* 5.0:1 on bone; brass itself is 2.2:1 */
  --evidence: #3f6b5f;       /* 5.2:1 on bone; verdigris itself is 3.4:1 */
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --background: var(--bone);
    --surface: var(--white);
    --text: var(--charcoal);
    --muted: #6b6259;          /* 5.2:1 on bone; the old 82 % mix of #6c6459 was 3.6:1 */
    --hairline: color-mix(in oklab, var(--charcoal) 14%, transparent);
    --edge: #898279;           /* 3.3:1 on bone */
    --accent-strong: #856016;  /* 5.0:1 on bone; brass itself is 2.2:1 */
    --evidence: #3f6b5f;       /* 5.2:1 on bone; verdigris itself is 3.4:1 */
  }
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--background);
  color: var(--text);
  font-family: var(--voice);
  font-size: 1rem;
  line-height: 1.55;
  text-wrap: pretty;
  -webkit-font-smoothing: antialiased;
}

a {
  color: var(--accent-strong);
  text-decoration: none;
  border-bottom: 1px solid color-mix(in oklab, var(--accent-strong) 45%, transparent);

  &:hover { border-bottom-color: var(--accent-strong); }
  &:focus-visible { outline: 2px solid var(--accent-strong); outline-offset: 3px; border-bottom-color: transparent; }
}

/* The legible accent rather than the fill one: a ring at 2.2:1 is not told apart from the page. */
:where(button, input, textarea, a):focus-visible {
  outline: 2px solid var(--accent-strong);
  outline-offset: 3px;
}

/* The articles. Appended to the foundation of app.css (tokens, light mode, body and links) when the
 * pages are generated, so everything here is layout and the reading column. */

body {
  padding-inline: var(--gutter);
}

.site-header,
main,
.site-footer {
  max-width: 38rem;
  margin-inline: auto;
}

.site-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  padding-block: 1.25rem 0.75rem;
  border-bottom: 1px solid var(--hairline);

  .brand {
    color: var(--text);
    font-weight: 600;
    border-bottom: none;
  }

  .to-the-articles { font-size: var(--type-fine); }
}

.written-piece {
  font-size: 1.0625rem;
  line-height: 1.65;

  h1 {
    font-size: 1.875rem;
    line-height: 1.2;
    font-weight: 600;
    margin-block: 0.5rem 1.25rem;
    text-wrap: balance;
  }

  h2 {
    font-size: 1.3125rem;
    line-height: 1.3;
    font-weight: 600;
    margin-block: 2.25rem 0.5rem;
  }

  h3 {
    font-size: var(--type-heading);
    font-weight: 600;
    margin-block: 1.5rem 0.25rem;
  }

  p, ul, ol { margin-block: 0 1rem; }

  li + li { margin-block-start: 0.375rem; }

  blockquote {
    margin: 1.25rem 0;
    padding-inline-start: 1rem;
    border-inline-start: 2px solid var(--accent-strong);
    color: var(--muted);

    p:last-child { margin-block-end: 0; }
  }

  strong { font-weight: 600; }
}

.belongs-to {
  margin-block: 2rem 0;
  font-size: var(--type-hint);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
}

.article-group {
  h2 {
    font-size: var(--type-heading);
    font-weight: 600;
    margin-block: 2rem 0.5rem;
  }
}

.article-list {
  list-style: none;
  padding: 0;
  margin: 0;

  li {
    padding-block: 0.75rem;
    border-bottom: 1px solid var(--hairline);
  }

  p {
    margin: 0.25rem 0 0;
    font-size: var(--type-fine);
    color: var(--muted);
  }
}

.invitation {
  margin-block: 3rem 2rem;
  padding: 1.25rem 1.5rem;
  background: var(--surface);
  border-radius: var(--radius);

  h2 {
    font-size: var(--type-heading);
    font-weight: 600;
    margin-block: 0 0.5rem;
  }

  p { margin-block: 0 0.875rem; font-size: var(--type-body); }

  .action {
    display: inline-block;
    padding: 0.625rem 1.25rem;
    border-radius: var(--radius);
    border-bottom: none;
    background: var(--accent);
    color: var(--accent-text);
    font-size: var(--type-action);
    font-weight: 600;
  }

  .disclosure {
    margin: 0;
    font-size: var(--type-fine);
    color: var(--muted);
  }
}

.site-footer {
  padding-block: 1.5rem 3rem;
  border-top: 1px solid var(--hairline);
  font-size: var(--type-fine);

  .all-articles {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
    gap: 0.5rem 2rem;
  }

  h2 {
    font-size: var(--type-hint);
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted);
    margin-block: 1rem 0.5rem;
  }

  ul {
    list-style: none;
    padding: 0;
    margin: 0;
  }

  li + li { margin-block-start: 0.375rem; }

  .about-sanndir {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.25rem;
    margin-block: 2rem 0;
  }
}
