/* bfc — the global stylesheet: reset, design tokens, typography.
 *
 * ┌─────────────────────────────────────────────────────────────────────────┐
 * │ RECONSTRUCTED. The rules below are exactly what this file contained —   │
 * │ recovered from the minified output — but the original comments were     │
 * │ lost when a `build-assets` step minified this file in place. These      │
 * │ comments were rewritten from `docs/src/design.md` and from the code     │
 * │ that reads these tokens. They describe the file correctly; they are not │
 * │ word for word what was here before.                                     │
 * │                                                                          │
 * │ `build-assets` no longer touches this file: it is a hand-written source │
 * │ and only the generated `components.css` is minified.                    │
 * └─────────────────────────────────────────────────────────────────────────┘
 *
 * Two levels, and only two. This file owns what is global by nature — the
 * reset, the token set, typography, and document-wide preferences — and it is
 * the only place that styles bare elements. Everything a component looks like
 * lives in a `*.module.css` beside that component and is bundled by `stylance`
 * into `/assets/components.css`.
 *
 * If a rule here names anything other than an element, a token or a
 * document-wide preference, it belongs in a module. That line is what stops the
 * global file becoming the place all styling ends up.
 */

/* The layer order, declared once and before anything uses it.
 *
 * A module's `@layer components` block needs this declaration to have been seen
 * already, which is why `Shell` links this stylesheet **before**
 * `components.css`. Order here is the cascade order, not the file order. */
@layer reset, tokens, base, layout, components;

/* The brand face, self-hosted. One variable file rather than one per weight:
 * the design uses 400 and 500, and two static instances cost more than the
 * variable font that covers the whole range — which the `font-weight` range
 * below declares, so shipping instances would make this rule lie.
 *
 * `swap`, so text is readable in the fallback face while the font arrives.
 * `Shell` preloads this URL; the two must agree, which is why the Rust side
 * names it once as `FONT_URL`. */
@font-face {
  font-family: Inter;
  src: url("/assets/fonts/InterVariable.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

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

  /* Margins come from the layout, never from the element. */
  body,
  h1,
  h2,
  h3,
  p,
  ul,
  ol,
  figure {
    margin: 0;
  }

  ul,
  ol {
    padding: 0;
    list-style: none;
  }

  /* Form controls do not inherit typography by default, and the poster design
   * has no rounded corners anywhere. */
  button,
  input {
    font: inherit;
    color: inherit;
    border-radius: 0;
  }

  img,
  svg {
    max-width: 100%;
    display: block;
  }

  /* `clip`, not `hidden`: `overflow-x: hidden` on the root turns off
   * `position: sticky` in the same axis. The poster compositions push shapes
   * past the viewport edge and this is what stops them widening the page. */
  html,
  body {
    overflow-x: clip;
  }
}

@layer tokens {
  :root {
    /* The site is light only. Saying so stops a browser rendering form
     * controls in a dark palette the rest of the page does not follow. */
    color-scheme: light;

    /* The four brand colours, from the chosen design direction
     * (`.dev-flow/design/09-bauhaus-poster.css`). Nothing outside this block
     * may invent a fifth: every module composes from these. */
    --teal: #023332;
    --orange: #f79722;
    --bone: #f2f2f2;
    --sage: #bed3d2;

    /* The one derived tint, for secondary copy. 6.11:1 on bone — comfortably
     * past 4.5:1, and mixed in oklab so the result stays on the same hue
     * rather than drifting through sRGB. `prefers-contrast: more` collapses it
     * back to full teal below. */
    --teal-soft: color-mix(in oklab, var(--teal) 74%, var(--bone));

    --font: "Inter", system-ui, "Liberation Sans", Arial, sans-serif;
    --w-body: 400;
    --w-display: 500;

    /* The page margin, and the rule thickness the poster language is built on.
     * Both are tokens because several modules have to agree on them. */
    --gutter: clamp(1rem, 5vw, 4rem);
    --rule: 6px;
  }
}

@layer base {
  body {
    background: var(--bone);
    color: var(--teal);
    font-family: var(--font);
    font-size: 0.9375rem;
    font-weight: var(--w-body);
    line-height: 1.55;
  }

  h1,
  h2,
  h3 {
    font-weight: var(--w-display);
    text-wrap: balance;
    line-height: 1.05;
  }

  /* The poster headline. Uppercase in CSS rather than in the catalogue, so the
   * DOM keeps the words as they were written — which is what a screen reader
   * reads, and what a search matches. */
  h1 {
    letter-spacing: 0.02em;
    text-transform: uppercase;
    font-size: max(1.75rem, min(4vw, 2.5rem));
  }

  p {
    text-wrap: pretty;
  }

  a {
    color: var(--teal);
    text-underline-offset: 3px;
  }

  /* `:focus-visible`, never `:focus`: a mouse click on a button should not
   * paint a focus ring, and a keyboard traversal must. `check_a11y.py` walks
   * every route asserting this is visible at every stop. */
  :focus-visible {
    outline: 3px solid var(--teal);
    outline-offset: 3px;
  }

  /* Somebody who asked for less motion gets none. Not "less" — the site has no
   * motion that carries meaning, so there is nothing to degrade gracefully. */
  @media (prefers-reduced-motion: reduce) {
    *,
    ::before,
    ::after {
      scroll-behavior: auto !important;
      transition-duration: 0.01ms !important;
      animation-duration: 0.01ms !important;
      animation-iteration-count: 1 !important;
    }
  }

  /* More contrast asked for: the derived tint collapses to full teal, the focus
   * ring thickens, and links are underlined rather than distinguished by
   * colour. */
  @media (prefers-contrast: more) {
    :root {
      --teal-soft: var(--teal);
    }

    :focus-visible {
      outline-width: 4px;
    }

    a {
      text-decoration: underline;
      text-decoration-thickness: 2px;
    }
  }

  /* Forced colours replace the palette entirely, so anything the design carried
   * with a background has to be re-stated as a border or an outline — those are
   * the properties the mode keeps. The current-page marker and the focus ring
   * are the two that would otherwise disappear. */
  @media (forced-colors: active) {
    [aria-current] {
      outline: 3px solid;
      outline-offset: 2px;
    }

    :focus-visible {
      outline: 3px solid;
      outline-offset: 3px;
    }
  }
}

@layer layout {
  /* `main` is not a block element in every browser this supports. */
  main {
    display: block;
  }
}
