/* Design tokens — the normative SET from docs/design-system.md §3 (AC-M0-W8-02).
 *
 * ARCHITECT owns that document; FRONTEND implements it. Every name here appears there and
 * every name there appears here, per scheme — asserted by
 * backend/apps/core/tests/../test_design_tokens.py, which also measures contrast rather than
 * trusting the numbers in these comments.
 *
 * NAMED BY ROLE, NEVER BY HUE (D-036). No token name mentions a colour and no rule below
 * reads a hue. `--color-accent` stays the right name if the palette moves again, and it has
 * moved twice already: a screenshot sample, then the declared CSS legend, then the wordmark
 * artwork, which is the mark printed on the instruments and therefore the decision rather
 * than a picture of one.
 *
 * THE DARK SCHEME IS NORMATIVE TOO (RC-031). Until 2026-09-05 §3 declared one unlabelled
 * legend which was in fact the light palette, so a dark block was answerable to nothing.
 * Both schemes carry identical obligations and the contrast assertion covers twelve pairs,
 * not six.
 */

/* --- Self-hosted subset faces (D-053, AC-M1-W7b-06) --------------------------------------
 *
 * SIX FILES, ZERO EXTERNAL REQUESTS. Every `src` below is a relative path into
 * backend/static/fonts/. Nothing here may ever become an absolute URL to a font CDN: that is
 * a third-party request, a third-party request risks a cookie, and a cookie means a consent
 * banner, which D-013 forbids. A gate asserts the SET of external hosts is empty.
 *
 * `unicode-range` IS NOT DECORATIVE AND THE OBVIOUS RANGE IS WRONG (D-053). U+0100-017F alone
 * loses `ó` and `Ó` — they are U+00F3 and U+00D3, in Latin-1 Supplement, and `ó` is among the
 * commonest Polish letters. Dropping U+0000-00FF fails SILENTLY: valid CSS, files that load,
 * perfect English, and a fallback glyph in every second Polish sentence. Verified against the
 * built files by codepoint: all 18 Polish letters draw contours in all six.
 *
 * `font-display: swap` is deliberate — text is readable in the fallback while the subset
 * arrives, and the fallback stacks below are chosen to match each face's proportions.
 */

@font-face {
  font-family: 'Display';
  src: url('../fonts/display-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0100-017F, U+2000-206F;
}
@font-face {
  font-family: 'Display';
  src: url('../fonts/display-600.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0100-017F, U+2000-206F;
}
@font-face {
  font-family: 'Body';
  src: url('../fonts/body-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0100-017F, U+2000-206F;
}
@font-face {
  font-family: 'Body';
  src: url('../fonts/body-400-italic.woff2') format('woff2');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0100-017F, U+2000-206F;
}
@font-face {
  font-family: 'Body';
  src: url('../fonts/body-600.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0100-017F, U+2000-206F;
}
@font-face {
  font-family: 'Mono';
  src: url('../fonts/mono-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0100-017F, U+2000-206F;
}

:root {
  /* --- 3.1 Colour — LIGHT. Values from the wordmark artwork, 2026-09-05. --- */
  --color-ink: #1f1a16;
  --color-ink-muted: #6e6154;
  --color-ink-inverse: #f7eedc;

  --color-surface: #f7efe0;
  --color-surface-raised: #fffbf3;
  --color-surface-sunken: #3a2e24;

  /* THREE NAMES, THREE DUTIES (OQ-012 option A). --color-rule is decorative and carries no
   * contrast requirement precisely because it may never convey a control boundary; the two
   * border tokens are the WCAG 1.4.11 floor and a real step above it.
   *
   * A-021 — THESE ARE MARGIN-FREE BY CONSTRUCTION. --color-border clears 3:1 against
   * --color-surface by 0.01 and falls under it after ONE least-significant-bit darkening of
   * that surface. IF YOU MOVE --color-surface, THE BORDER VALUES MOVE WITH IT. The contrast
   * assertion is what turns this comment into a red run instead of a note someone reads past.
   */
  --color-rule: #e4d7c0;
  --color-border: #9f866e;
  --color-border-strong: #736a5c;

  /* The accent ramp is a SET OF THREE and is valid only as one (RC-026): hover lighter than
   * base, active darker. Patching one value into a superseded ramp reintroduces the defect
   * OQ-008 existed to remove. */
  --color-accent: #a8412b;
  --color-accent-hover: #c0533c;
  --color-accent-active: #8f3421;
  --color-accent-muted: #c9a18a;

  --color-accent-secondary: #b07a22;
  --color-accent-secondary-hover: #d89b3c;
  --color-accent-secondary-muted: #e6c88e;

  --color-focus: #1e40af;
  --color-danger: #ef4444;
  --color-success: #166534;
  /* #E6E000 is the SAME value in both schemes. It replaced two values that each failed the
   * distinguishability test against their own scheme's ochre, at 5.1° and 5.7°. */
  --color-warning: #e6e000;

  /* --- 3.2 Typography --- */
  /* OQ-005 CLOSED by D-053: three SIL OFL 1.1 faces, self-hosted and subset. The interim
   * system stack that stood here made zero external requests, and so does this — the files are
   * in backend/static/fonts/ and nothing is fetched from a CDN, which is what D-013 requires.
   *
   * THE FAMILY NAMES ARE DELIBERATELY GENERIC AND MUST NOT BE CHANGED BACK (D-053 obligation
   * 3). Subsetting is modification under OFL, and OFL forbids distributing a modified font
   * under a Reserved Font Name. Read from each download's own OFL.txt rather than assumed, and
   * the three do NOT agree:
   *     Josefin Sans   RFN "Josefin Sans"   -> rename REQUIRED
   *     Source Serif 4 no RFN declared      -> rename not required, done for consistency
   *     IBM Plex Mono  RFN "Plex"           -> the TOKEN, not the family name
   * So `Display`, `Body` and `Mono` are compliant for all three, for different reasons each.
   * backend/static/fonts/README.md carries the provenance and the rebuild method. */
  --font-display: "Display", Futura, "Century Gothic", sans-serif;
  --font-body: "Body", Georgia, "Times New Roman", serif;
  --font-mono: "Mono", ui-monospace, "SFMono-Regular", monospace;

  /* One fluid scale between the container breakpoints, per §3.2 — not per-breakpoint
   * overrides.
   *
   * D-080: THE BOUNDS ARE rem, AND THAT IS AN ACCESSIBILITY PROPERTY RATHER THAN A
   * STYLE ONE. A px `max` caps the scale against the reader's own browser font-size
   * setting: measured in Chrome at root=24px, `--text-base` gained 0% (17px -> 17px)
   * and the whole scale gained 0-5%, against the 50% the reader asked for. Worse as
   * an interaction: `--measure` is 34rem and DID scale, so the reading column grew
   * 544px -> 816px while the type inside it did not move at all.
   *
   * EVERY VALUE IS UNCHANGED AT THE 16px DEFAULT — the conversion is exact, no
   * rounding anywhere, and the page D-073 approved renders the same computed pixels.
   * Only the reader-intervention case differs. D-073 locked the package's VALUES as
   * the design; a unit is an accident of export, which is what D-073's own sentence
   * says the values are not.
   *
   * `--target-min` STAYS px on purpose: WCAG 2.5.8 specifies a physical target size,
   * not a font-relative one. Not everything here should be rem. */
  --text-xs: clamp(0.6875rem, 0.72rem, 0.75rem);
  --text-sm: clamp(0.8125rem, 0.86rem, 0.875rem);
  --text-base: clamp(1rem, 1rem + 0.1vw, 1.0625rem);
  --text-lg: clamp(1.125rem, 1.05rem + 0.25vw, 1.3125rem);
  --text-xl: clamp(1.375rem, 1.2rem + 0.6vw, 1.75rem);
  --text-2xl: clamp(1.75rem, 1.5rem + 1.2vw, 2.5rem);
  /* NOTHING USES THIS SINCE `AC-M6-W12-06`, AND THAT IS RECORDED RATHER THAN RESOLVED.
     It had exactly one consumer — the generic `h1` in `main.css` — and the ruling moved that to
     `--text-2xl` because `--text-3xl` is the only step the visual reference never renders: the
     home page's sole `h1` is visually hidden (`AC-M5-W6-04`, `R-054`), so no amount of looking
     at the reference could validate this value.
     It is neither deleted nor quietly kept. A token nothing uses is an invitation to use it, so
     the next session that reaches for the biggest step in the scale should read this first: the
     ruling is that THE BIGGEST THING ON ANY PAGE IS `--text-2xl`. Removing the declaration is a
     change to the SET `docs/design-system.md` normatively declares, which is ARCHITECT-owned. */
  --text-3xl: clamp(2.25rem, 1.9rem + 2.4vw, 3.75rem);

  --leading-tight: 1.12;
  --leading-normal: 1.55;
  --leading-loose: 1.75;

  --tracking-tight: 0.01em;
  --tracking-normal: 0;
  --tracking-wide: 0.14em;

  --weight-regular: 400;
  --weight-medium: 600;
  --weight-bold: 700;

  /* --- 3.3 Space — a single scale. Component-specific values are not permitted; if a value
   * is needed that is not here, the scale is wrong and the DOCUMENT is amended. --- */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-8: 3rem;
  --space-10: 4rem;
  --space-12: 6rem;
  --space-16: 9rem;

  /* --- 3.4 Layout --- */
  --measure: 34rem;
  --container-narrow: 44rem;
  /* NOTHING READS THIS SINCE `D-108` AND IT IS NOT DEAD. Every page renders at
     `--container-wide` now, so `.l-page` no longer names this token — but it is design-system
     vocabulary shared with the delivery, and package 18 genuinely caps its inner pages here.
     Removing it would diverge the TOKEN FILE as well as the stylesheet, for nothing, and would
     make the next parity reader wonder which of the two trees was wrong. */
  --container-default: 68rem;
  --container-wide: 84rem;
  --gutter: clamp(20px, 4vw, 56px);

  /* --- 3.5 Surface treatment --- */
  --radius-sm: 3px;
  --radius-md: 6px;
  --radius-lg: 10px;
  /* A SHAPE, not a step on the sm/md/lg scale — chips, the locale switch and status tags are
   * fully rounded whatever size step they sit at. The only genuinely new name of 2026-09-05. */
  --radius-pill: 999px;

  /* Two shadows only. Shadow indicates elevation, never decoration (§3.5). */
  --shadow-sm: 0 1px 2px rgba(31, 26, 22, 0.07);
  --shadow-md: 0 10px 28px rgba(31, 26, 22, 0.12);
  --border-hairline: 1px;

  /* --- 3.4 Layout: the accessibility floor ---
   * A WCAG 2.5.8 constant, not a design choice, which is why §3.3's spacing rule never
   * governed it — but a constant written as a bare 44px is indistinguishable from an
   * off-scale value, and the next reader cannot tell which it is. */
  --target-min: 44px;

  /* --- 3.6 Motion --- */
  --duration-fast: 140ms;
  --duration-normal: 280ms;
  /* The third step, added with the M5 package (D-073, design-system §3.6). It is a RECORD
     of the value the approved design cross-fades at, not a new choice: the package ships
     `var(--duration-slow, 600ms)` so its CSS stands alone, and what we lacked was the name. */
  --duration-slow: 600ms;
  --ease-standard: cubic-bezier(0.2, 0, 0.2, 1);
}

/* --- 3.1 Colour — DARK. Normative since 2026-09-05 (RC-031).
 *
 * ONLY the colour tokens are redeclared. The type scale, space, layout, surface and motion
 * tokens are scheme-independent and redeclaring them here would create two places to change
 * one value.
 *
 * RC-030 — --color-border was #6B6154 at 2.99:1 / 2.72:1 and did NOT implement option A in
 * this scheme while the light block did. #72685A is the derived floor on the same hue.
 * Every light value was measured, disputed and re-derived across four exchanges; the dark
 * block was written once and read once. That asymmetry is the reason the assertion covers
 * both schemes.
 */
@media (prefers-color-scheme: dark) {
  :root {
    --color-ink: #f2e9d9;
    --color-ink-muted: #b3a695;
    --color-ink-inverse: #241a10;

    --color-surface: #1a1511;
    --color-surface-raised: #241e18;
    /* Rule 1 does NOT invert: the surface family is not monotonic in lightness, and `sunken`
     * is the LIGHT member here. It still takes --color-ink-inverse (13.77:1); the tempting
     * --color-ink pairing gives 1.03:1. The rule survives because it names a ROLE rather
     * than a lightness — D-036's naming principle protecting rules as well as names. */
    --color-surface-sunken: #efe6d4;

    --color-rule: #3a3129;
    --color-border: #72685a;
    --color-border-strong: #8a8073;

    --color-accent: #e79a82;
    --color-accent-hover: #f3b29b;
    --color-accent-active: #d98a72;
    --color-accent-muted: #6e4b3a;

    --color-accent-secondary: #dfae5c;
    --color-accent-secondary-hover: #ecc378;
    --color-accent-secondary-muted: #5e4623;

    --color-focus: #93b4ff;
    --color-danger: #f87171;
    --color-success: #4ade80;
    --color-warning: #e6e000;
  }
}

/* --- 3.6 Motion: the reduced-motion floor (D-073, AC-M5-W1-01) ---------------------------
   FROM THE PACKAGE, AND IT IS THE ONLY BLOCK OF ITS OWN THE PACKAGE ADDED.

   Collapsing the duration tokens rather than disabling animation per component is what makes
   this reachable from anything that already reads `--duration-*`: a transition still runs, in
   1ms, so no component needs a second code path and nothing can forget to honour the setting.

   `carousel.js` ALSO stops advancing under the same query (AC-M5-W1-05). The two are not
   redundant — this one governs CSS transitions, that one governs whether the slide index
   moves at all, and a 1ms transition on an auto-advancing carousel is still an auto-advancing
   carousel. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --duration-fast: 1ms;
    --duration-normal: 1ms;
    --duration-slow: 1ms;
  }
}
