/*
 * The design tokens of Steinmann Real Estate.
 *
 * Every value in this file comes from `content/design-tokens.md`, where each
 * contrast pair was calculated rather than estimated. Nothing else in this
 * project declares a colour, a radius, a duration or a spacing value
 * literally — a hex value outside this file is a finding, and
 * `tests/test_design_system.py` reports it.
 *
 * Three groups, in this order:
 *   1. the raw scales, which carry no meaning on their own
 *   2. the roles, which are what the rest of the CSS refers to
 *   3. the Bootstrap variables, mapped onto those roles rather than laid
 *      beside them
 *
 * The light set stands on bare `:root`. The dark set is repeated twice on
 * purpose: once under `prefers-color-scheme` for the visitor who has chosen
 * nothing, guarded so an explicit "light" wins over the system, and once
 * under `[data-theme="dark"]` so the toggle wins in the other direction too.
 *
 * Rewritten on 2026-09-05 to the design language of the company's own site,
 * https://www.steinmann-realestate.ch, surveyed in
 * `docs/referenzen/steinmann-website.md`. What came before was a cool slate
 * product with one saturated blue, built from a survey of SalesSuite; it was
 * carefully made and it was not the house this brand lives in. What replaces
 * it is the site's own palette — black, gold and paper white, with the Swiss
 * red as the one signal — in the proportions the site uses them.
 *
 * The one place this file departs from the site is measured rather than
 * chosen. Gold `#bfa15a` reaches 2.26:1 on the paper ground, and the site
 * sets small text in it anyway: the eyebrow, the card's location line, the
 * table head. This application carries a published accessibility statement,
 * so on a light ground gold as *text* is `--gold-ink`, the same hue and the
 * same chroma at the lightness where 4.5:1 is first met, and gold as an
 * *edge* is `--gold-edge` at 3:1. As a fill, a hairline, a seal and on every
 * dark ground it is the site's own `#bfa15a`, untouched. Section 6 of
 * `PROJECT-SPEC.md` records the decision.
 */

/* ------------------------------------------------------------------ *
 * Typefaces — served from this server, never from a foreign one.
 * A font fetched from a third party transmits the visitor's address
 * before they could consent to it, which is a data protection question
 * rather than a matter of taste.
 *
 * Two families, as the site has: Cormorant Garamond sets what is read as
 * language — headings, prices, the lead paragraph — and Jost sets what is
 * read as interface. Both are SIL Open Font License, so serving them is a
 * licence question already answered.
 *
 * The site declares a third, Cinzel, and never uses it. It is not carried
 * over: an unused face is 100 KB the visitor pays for and nobody sees.
 *
 * Weights are 300, 400 and 500 and there is no 600 or 700. That is the
 * handwriting rather than an omission — the site's heaviest weight is 500,
 * and emphasis is carried by the jump from 300 to 500, by size and by
 * letter-spacing. `--font-weight-bold` therefore resolves to 500 as well.
 *
 * Each upright file is one variable font holding every weight, and it is
 * declared once with its whole range (2026-10-16). Until then the same
 * file stood three times as a face of 300, 400 and 500: Chromium set the
 * weight axis anyway, Safari drew all three alike, and "Fett" in the text
 * editor and the 300 to 500 contrast of the whole interface were invisible
 * on an iPhone or a Mac.
 * ------------------------------------------------------------------ */

@font-face {
  font-family: "Jost";
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("../fonts/Jost-400.41a72a3a0ae3.woff2") format("woff2");
}

@font-face {
  font-family: "Jost";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/Jost-400i.4049ddafeddb.woff2") format("woff2");
}

@font-face {
  font-family: "Cormorant Garamond";
  font-style: normal;
  font-weight: 300 700;
  font-display: swap;
  src: url("../fonts/CormorantGaramond-400.ec4225ec161b.woff2") format("woff2");
}

@font-face {
  font-family: "Cormorant Garamond";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/CormorantGaramond-400i.95f875e7d230.woff2") format("woff2");
}

/* ------------------------------------------------------------------ *
 * 1. The scales
 * ------------------------------------------------------------------ */

:root {
  /* The brand values, verbatim from the site's own stylesheet. These eleven
   * are not derived, not adjusted and not up for discussion: they are what
   * the company looks like. */
  --black: #0b0b0c;
  --ink: #141416;
  --coal: #1c1c1f;
  --paper: #f7f4ee;
  --white: #ffffff;
  --ivory: #f5f1e8;
  --gold: #bfa15a;
  --gold-soft: #d6c08d;
  --red: #b5181c;
  --text-warm: #2e2d2b;
  --text-warm-soft: #6d6a63;
  --text-cool: #ede9e0;
  --text-cool-soft: #a39f95;

  /* Gold, derived twice for the light set. Same hue, same chroma, lower
   * lightness — `#bfa15a` is OKLCH 0.721 0.097 87.0, `--gold-ink` is
   * 0.539 0.097 86.5 and `--gold-edge` 0.639 0.097 87.2. The hue moves by
   * half a degree, which is below the threshold at which anybody sees a
   * different colour, and the chroma does not move at all.
   *
   * `--gold-ink` is gold that has to be read: 4.53:1 on ivory, 4.65 on
   * paper, 5.11 on white.
   * `--gold-edge` is gold that has to be seen but not read — a focus ring, a
   * control border, a chart series: 3.01 / 3.09 / 3.39 against the same
   * three. WCAG 2.2 1.4.11 asks 3:1 of both. */
  --gold-ink: #876a20;
  --gold-edge: #a58841;

  /* The gold hairline of the site, which is gold at 45 per cent and is
   * decoration rather than information — 1.4.11 does not reach it. */
  --gold-line: rgba(191, 161, 90, 0.45);
  --gold-line-soft: rgba(191, 161, 90, 0.22);
  --gold-wash: rgba(191, 161, 90, 0.06);

  /* Red is the Swiss signal, and it needs no correction on a light ground:
   * 5.99:1 on ivory. On a dark one it does — `#b5181c` reaches 2.92:1 on
   * black — so `--red-lifted` is the same hue and chroma raised to 4.51:1
   * against the lightest dark ground. */
  --red-lifted: #e64f47;

  /* Success. The site has no colour for it, so this one is designed rather
   * than observed: a moss green at gold's own chroma, 0.095, so that it sits
   * beside the brand colour instead of shouting past it. 142 degrees is far
   * enough from gold's 87 and red's 27 to be read as a third thing. */
  --moss: #50804b;
  --moss-ink: #4a7945;
  --moss-lifted: #5f8f59;

  /* The warm greys. Not a neutral scale from a library: the hue of the
   * site's own body text, `#6d6a63`, at the lightnesses this design needs.
   * A cool grey beside this palette reads as a different product. */
  --grey-line-light: #e1dfdb;
  --grey-divider-light: #ceccc7;
  --grey-control-light: #8e8b85;
  --grey-line-dark: #2c2b29;
  --grey-divider-dark: #3e3d3a;
  --grey-control-dark: #6a675f;

  /* The surfaces between paper and white, so that a subdued panel is not the
   * page and not a card. Both are lighter than `--ivory`, which keeps ivory
   * the worst light ground every text colour was measured against. */
  --paper-lifted: #faf8f4;

  /* The dark grounds are the site's own three, and they carry the same
   * order: the page is the darkest, a card sits above it, a raised thing
   * above that. */
  --dark-page: #0b0b0c;
  --dark-surface: #141416;
  --dark-raised: #1c1c1f;
  --dark-sunken: #101012;

  /* The tone set — seven tinted grounds with their matching text, and this
   * is how every state in this application is drawn: a badge, a phase count,
   * a table state cell. Never a saturated fill.
   *
   * Each hue is held at the palette's chroma rather than at full
   * saturation; a tone louder than the brand colour pulls the eye off it.
   * Where the palette already holds a value for a hue, that value is used
   * and nothing is derived — the red of a badge is the red of the brand.
   *
   * The two sets solve the same problem from opposite ends. In the light set
   * the *ground* gives way until the canonical text reaches 4.5:1 on it. In
   * the dark set the *text* gives way instead, because a tinted ground that
   * kept receding would end up the colour of the card it sits on: this
   * project has had exactly that defect, a badge at 1.002:1 against its own
   * card, and it is not being reintroduced. Every dark tone here stands at
   * least 1.05:1 off `--dark-surface`. */
  --tone-gold-light: #fdf0d2;
  --tone-green-light: #e2f8df;
  --tone-red-light: #ffe7e2;
  /* Grey is the palette's own warm grey, not a cool blue-grey: beside paper,
   * gold and black a cool badge read as coming from another product. */
  --tone-grey-light: #eeebe5;
  --tone-blue-light: #ddf4ff;
  --tone-violet-light: #faedff;
  --tone-teal-light: #d2f9f8;

  --on-tone-gold-light: #876a20;
  --on-tone-green-light: #4a7945;
  --on-tone-red-light: #b5181c;
  --on-tone-grey-light: #6a665e;
  --on-tone-blue-light: #56708d;
  --on-tone-violet-light: #7a6691;
  --on-tone-teal-light: #327879;

  --tone-gold-dark: #352a0e;
  --tone-green-dark: #1e311c;
  --tone-red-dark: #3f221f;
  --tone-grey-dark: #2c2a26;
  --tone-blue-dark: #192d41;
  --tone-violet-dark: #30253d;
  --tone-teal-dark: #073232;

  --on-tone-gold-dark: #bfa15a;
  --on-tone-green-dark: #6e9f68;
  --on-tone-red-dark: #f55d53;
  --on-tone-grey-dark: #98928a;
  --on-tone-blue-dark: #7895b3;
  --on-tone-violet-dark: #9c88b5;
  --on-tone-teal-dark: #599e9d;

  /* The four chart series. Hue alone does not separate them for a reader who
   * cannot tell hues apart, so they are staggered in lightness as well:
   * gold, moss, red, graphite, each a step darker than the last in the light
   * set and a step lighter in the dark one. Every one clears 3:1 against its
   * ground, which is what 1.4.11 asks of a graphical object. */
  --series-1-light: #a58841;
  --series-2-light: #50804b;
  --series-3-light: #b5181c;
  --series-4-light: #373b3f;
  --series-1-dark: #c8aa63;
  --series-2-dark: #6d9e68;
  --series-3-dark: #c8312d;
  --series-4-dark: #cdd1d6;

  /* The shadow tints.
   *
   * The site has one shadow and uses it everywhere a card sits on the page:
   * wide, soft and lifted from below, `0 18px 50px -22px` at 35 per cent of
   * the near-black. It is what makes a white card read as an object on the
   * paper ground rather than as a hole in it. Everything stronger belongs to
   * something that genuinely floats — a dropdown, a modal, a lightbox. */
  --shadow-tint-card: rgba(11, 11, 12, 0.35);
  --shadow-tint-raised: rgba(11, 11, 12, 0.45);
  --shadow-tint-overlay: rgba(11, 11, 12, 0.35);
  --shadow-tint-overlay-near: rgba(11, 11, 12, 0.18);
  --ring-tint: rgba(191, 161, 90, 0.35);

  /* An overlay is a wash of the site's own near-black. The lightbox uses it
   * at 96 per cent, a modal scrim at 78, which is the figure the site's
   * `.cta-band` uses over a photograph. */
  --scrim: rgba(8, 8, 10, 0.78);
  --scrim-deep: rgba(6, 6, 8, 0.96);

  /* The gradients, as tokens rather than as literals in `public.css`.
   *
   * They are here for the same reason every colour is: no stylesheet but this
   * one may declare a colour, and a gradient is three colours with positions.
   * All four are the site's own, read off its stylesheet.
   *
   * The veil over a hero photograph is the one that carries a legal weight
   * rather than only a visual one. A heading over an unknown photograph is
   * legible or it is not, and 4.5:1 cannot be measured against an image; the
   * three stops are what make the answer not depend on the picture. Dark at
   * the top so the header's own text holds, lighter through the middle where
   * the subject usually is, darkest at the foot where the heading sits. */
  --veil-hero: linear-gradient(
    to bottom,
    rgba(8, 8, 10, 0.6) 0%,
    rgba(8, 8, 10, 0.44) 45%,
    rgba(8, 8, 10, 0.8) 100%
  );
  /* The subpage veil carries a second layer from the left, where the eyebrow,
   * the heading and the facts stand. Through the light middle band alone the
   * small gold eyebrow and the grey facts vanished into a bright window. */
  --veil-page: linear-gradient(
      to right,
      rgba(8, 8, 10, 0.5) 0%,
      rgba(8, 8, 10, 0) 70%
    ),
    linear-gradient(
      to bottom,
      rgba(8, 8, 10, 0.5) 0%,
      rgba(8, 8, 10, 0.32) 45%,
      rgba(8, 8, 10, 0.85) 100%
    );
  /* The header before the page is scrolled: it floats on the photograph and
   * carries just enough of a gradient to keep its own entries readable. */
  --veil-header: linear-gradient(
    to bottom,
    rgba(8, 8, 9, 0.55),
    rgba(8, 8, 9, 0)
  );
  /* The wash inside a bordered panel — gold at five per cent, running off at
   * 55 per cent of the diagonal. Without it a gold-bordered box on a dark
   * ground reads as an empty frame. */
  --wash-panel: linear-gradient(
    160deg,
    rgba(191, 161, 90, 0.05),
    rgba(191, 161, 90, 0) 55%
  );
  /* The rule under the scroll hint, and the only gradient that is a line. */
  --wash-rule: linear-gradient(to bottom, var(--gold), rgba(191, 161, 90, 0));

  /* --------------------------------------------------------------- *
   * 2. The roles — light mode
   * --------------------------------------------------------------- */

  --color-ground: var(--paper);
  /* The dark bands of the public site: the accent section, the closing band.
   * Black on paper, and one step above the page in the dark theme, where
   * black on black left two bands' padding as one empty field. */
  --color-band: var(--black);
  --color-surface: var(--white);
  --color-surface-subdued: var(--paper-lifted);
  --color-surface-tinted: var(--ivory);
  --color-hairline: var(--grey-line-light);
  --color-divider: var(--grey-divider-light);
  --color-border-control: var(--grey-control-light);
  --color-border-disabled: var(--grey-divider-light);

  --color-heading: var(--black);
  --color-text: var(--text-warm);
  /* Muted text is the site's own `#6d6a63`, which reaches 4.79:1 on ivory —
   * the worst light ground — and 5.40 on white. */
  --color-muted: var(--text-warm-soft);
  --color-on-tint: var(--text-warm-soft);
  --color-disabled: var(--text-warm-soft);

  /* A link in running text is gold, but the readable gold: 4.65:1 on the
   * paper ground. The site's own link is black with a gold rule under it,
   * which `.textlink` still is; this role is for the links inside an
   * article, where a rule under every one would be noise. */
  --color-link: var(--gold-ink);
  --color-link-hover: var(--black);
  /* The focus ring. `--gold-edge` rather than `--gold`, because a ring has
   * to clear 3:1 against whatever it sits on and the brand gold does not do
   * that on paper. */
  --color-focus: var(--gold-edge);

  /* The quiet button of the site: black fill, ivory label, and on hover it
   * empties out to black on transparent. The hover token names the fill it
   * ends on so that anything reading the role rather than the class still
   * gets a legible pair. */
  --color-primary-fill: var(--black);
  --color-primary-fill-hover: var(--ink);
  --color-on-primary: var(--ivory);
  --color-primary-soft: var(--tone-gold-light);
  --color-primary-softer: var(--paper-lifted);
  --color-on-primary-soft: var(--on-tone-gold-light);

  /* The one main action per screen, and here it is the gold fill with the
   * black label — 7.93:1, and it is the single loudest thing on the page,
   * which is what a main action should be. On hover it lightens to
   * `--gold-soft` at 11.04:1 rather than darkening: a gold that darkens
   * reads as switched off, a gold that lightens reads as lit. */
  --color-action-fill: var(--gold);
  --color-action-fill-hover: var(--gold-soft);
  --color-on-action: var(--black);

  --color-success: var(--moss-ink);
  --color-success-fill: var(--moss-ink);
  --color-success-fill-hover: var(--moss);
  --color-on-success: var(--white);
  --color-danger: var(--red);
  --color-danger-fill: var(--red);
  --color-danger-fill-hover: var(--red);
  --color-on-danger: var(--white);

  --color-ground-problem: var(--tone-red-light);
  --color-on-ground-problem: var(--on-tone-red-light);
  --color-ground-solution: var(--tone-gold-light);
  --color-on-ground-solution: var(--on-tone-gold-light);
  --color-ground-positive: var(--tone-green-light);
  --color-on-ground-positive: var(--on-tone-green-light);

  --color-tone-blue-soft: var(--tone-blue-light);
  --color-on-tone-blue: var(--on-tone-blue-light);
  --color-tone-green-soft: var(--tone-green-light);
  --color-on-tone-green: var(--on-tone-green-light);
  --color-tone-red-soft: var(--tone-red-light);
  --color-on-tone-red: var(--on-tone-red-light);
  --color-tone-amber-soft: var(--tone-gold-light);
  --color-on-tone-amber: var(--on-tone-gold-light);
  --color-tone-violet-soft: var(--tone-violet-light);
  --color-on-tone-violet: var(--on-tone-violet-light);
  --color-tone-teal-soft: var(--tone-teal-light);
  --color-on-tone-teal: var(--on-tone-teal-light);
  --color-tone-grey-soft: var(--tone-grey-light);
  --color-on-tone-grey: var(--on-tone-grey-light);

  /* The switch track when it is off, and the knob that rides on it. The
   * track is a control edge and needs 3:1 like any other. */
  --color-switch-off: var(--grey-control-light);
  --color-switch-knob: var(--white);

  /* The black band the site wears at the top of every page, and the one
   * surface that is the same in both modes. The gold word mark reaches
   * 7.93:1 on it. */
  --color-accent-surface: var(--black);
  --color-on-accent: var(--ivory);
  --color-on-accent-muted: var(--text-cool-soft);
  /* The edge of a ticked box. Its fill is the accent surface in both sets,
   * which on the dark card is the card's own step: the edge carries it. */
  --color-check-edge: var(--black);
  /* Which of two cuts of one picture shows: the word mark for paper and the
   * one for the dark ground stand side by side where a page follows the
   * theme, and these two decide. */
  --show-in-light: block;
  --show-in-dark: none;

  /* Gold as itself: a fill, a hairline, a seal. Where it has to be read on a
   * light ground, `--color-brand-ink` is the value to use. */
  --color-brand: var(--gold);
  --color-brand-ink: var(--gold-ink);
  --color-brand-edge: var(--gold-edge);
  --color-brand-soft: var(--gold-soft);
  --color-brand-line: var(--gold-line);
  --color-brand-line-soft: var(--gold-line-soft);
  --color-brand-wash: var(--gold-wash);
  --color-on-brand: var(--black);

  --color-selection: var(--gold);
  --color-on-selection: var(--black);
  --color-scrim: var(--scrim);
  --color-scrim-deep: var(--scrim-deep);
  --color-ring: var(--ring-tint);

  --chart-1: var(--series-1-light);
  --chart-2: var(--series-2-light);
  --chart-3: var(--series-3-light);
  --chart-4: var(--series-4-light);
  --chart-average: var(--grey-control-light);
  --chart-grid: var(--grey-line-light);

  /* --------------------------------------------------------------- *
   * Typography. Every size in `rem` and none in `px`: N-10 asks for an
   * adjustable font size, the setting raises the root size, and a single
   * `px` here would break that silently for the users who need it.
   * --------------------------------------------------------------- */

  --font-family-base: "Jost", "Helvetica Neue", system-ui, -apple-system,
    "Segoe UI", Roboto, sans-serif;
  --font-family-display: "Cormorant Garamond", Georgia, "Times New Roman",
    serif;
  --font-weight-light: 300;
  --font-weight-regular: 400;
  --font-weight-medium: 500;
  /* There is no 600 and no 700 in this design. Both resolve to 500, which is
   * the heaviest weight the site owns; emphasis is carried by the jump from
   * 300, by size and by letter-spacing. */
  --font-weight-semibold: 500;
  --font-weight-bold: 500;

  --root-font-size: 100%;

  --text-2xs: 0.6875rem;
  --text-2xs-line: 1rem;
  --text-xs: 0.75rem;
  --text-xs-line: 1.125rem;
  --text-sm: 0.8125rem;
  --text-sm-line: 1.25rem;
  /* The application body size is 15 px rather than 16. A screen of lists,
   * filters and tables is read in glances rather than in sentences, and one
   * pixel less puts noticeably more of a record in view without costing
   * legibility. `text-md` is the public part, which is read in sentences —
   * and it is the site's own 1.0375 rem. */
  --text-base: 0.9375rem;
  --text-base-line: 1.5rem;
  --text-md: 1.0375rem;
  --text-md-line: 1.8125rem;
  --text-lg: 1.125rem;
  --text-lg-line: 1.6rem;
  --text-xl: 1.25rem;
  --text-xl-line: 1.6rem;
  --text-2xl: 1.5rem;
  --text-2xl-line: 1.875rem;
  --text-3xl: 1.875rem;
  --text-3xl-line: 2.125rem;
  --text-4xl: 2.25rem;
  --text-4xl-line: 2.5rem;
  --text-5xl: 3rem;
  --text-5xl-line: 3.125rem;

  /* The display sizes, which are the site's own clamps. A heading here is
   * set in Cormorant at 300 or 400 and leads at 1.12 — tight, because a
   * serif at forty pixels with interface leading looks like a mistake. */
  --display-line: 1.12;
  /* A lead paragraph is set in the serif at a display size, so its leading is
   * a ratio rather than one of the `--text-*-line` lengths: the size is a
   * clamp and a fixed leading would break at one end of it. */
  --display-line-lead: 1.5;
  --display-sm: clamp(1.35rem, 2vw, 1.7rem);
  --display-md: clamp(2rem, 3.6vw, 3.1rem);
  --display-lg: clamp(2.6rem, 6vw, 4.6rem);
  --display-hero: clamp(2.7rem, 6.6vw, 5rem);

  /* Letter-spacing. This is the loudest single signal of the design: the
   * site sets every small label in Jost 500, upper case, at between 0.18 and
   * 0.55 em. Nothing else about the typography says "this brand" as
   * immediately, so the values are tokens rather than literals. */
  /* The size of a button's label. It is neither `--text-xs` nor `--text-sm`
   * but the value the survey measured, and it is a token because four
   * stylesheets set a button. */
  --text-button: 0.78rem;

  --tracking-eyebrow: 0.42em;
  --tracking-eyebrow-wide: 0.55em;
  --tracking-label: 0.32em;
  --tracking-button: 0.22em;
  --tracking-nav: 0.24em;
  --tracking-pill: 0.3em;
  --tracking-wordmark: 0.18em;
  /* Cormorant needs no negative tracking; it is drawn for text sizes and
   * sets correctly at display sizes on its own. The five names below are
   * kept because stylesheets refer to them, and they resolve to nothing. */
  --tracking-lg: 0;
  --tracking-xl: 0;
  --tracking-2xl: 0.01em;
  --tracking-3xl: 0.01em;
  --tracking-4xl: 0.01em;
  --tracking-5xl: 0.01em;

  /* --------------------------------------------------------------- *
   * Spacing — multiples of 4 px, in `rem` so they scale with the font.
   * --------------------------------------------------------------- */

  --space-1: 0.25rem;
  --space-1-5: 0.375rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.25rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-10: 2.5rem;
  --space-12: 3rem;
  --space-16: 4rem;
  --space-20: 5rem;
  --space-24: 6rem;

  /* The public part breathes on a different scale from the working area, and
   * the site's own section padding is a clamp rather than a step. */
  --space-section: clamp(4.5rem, 9vw, 8rem);
  --space-section-sm: clamp(2.5rem, 5vw, 4.5rem);
  --space-gutter: clamp(1.25rem, 4vw, 3rem);
  --space-grid: clamp(1.4rem, 2.5vw, 2.4rem);

  /* --------------------------------------------------------------- *
   * Radii, borders, shadows, motion
   *
   * The site has exactly one rounded thing in fourteen hundred lines of CSS:
   * the circular arrow on an image slider. Everything else is square, and
   * that is most of why it reads as considered rather than as generated. So
   * every radius here is zero, and the five names are kept only so that the
   * stylesheets and Bootstrap's own variables have something to point at.
   * A radius reintroduced in one component is a finding.
   * --------------------------------------------------------------- */

  --radius-card: 0;
  --radius-control: 0;
  --radius-track: 0;
  --radius-modal: 0;
  --radius-sm: 0;
  /* The one exception, and it has a job: a round handle reads as a handle. */
  --radius-pill: 9999px;

  --border-hairline: 1px;
  --border-control: 1px;
  --border-focus: 2px;
  --border-focus-offset: 2px;

  --shadow-flat: none;
  --shadow-card: 0 18px 50px -22px var(--shadow-tint-card);
  --shadow-raised: 0 30px 60px -24px var(--shadow-tint-raised);
  --shadow-overlay: 0 4px 12px -4px var(--shadow-tint-overlay-near),
    0 24px 60px -18px var(--shadow-tint-overlay);
  --shadow-ring: 0 0 0 3px var(--color-ring);

  /* The site's own easing, and it is not a stock curve: it starts fast and
   * settles long, which is what makes a card lift feel weighted rather than
   * springy. Every transition in this project uses it. */
  --motion-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  /* The underline that grows from the left under a navigation entry. 350 ms
   * is the site's own figure and it sits between `base` and `slow` for a
   * reason worth keeping: the movement is a hairline crossing a short
   * distance, and at 300 ms it reads as a flicker rather than as a stroke. */
  --motion-nav: 350ms;
  --motion-fast: 180ms;
  --motion-base: 300ms;
  --motion-slow: 450ms;
  --motion-image: 800ms;

  /* --------------------------------------------------------------- *
   * Layout constants
   * --------------------------------------------------------------- */

  --sidebar-width: 15.5rem;
  --topbar-height: 3.5rem;
  /* The public header is 92 px on the site and stays that height here. */
  --header-height: 5.75rem;
  --content-max: 84rem;
  /* The site's own measure. Everything public is laid out inside it. */
  --page-max: 80rem;
  /* The measure of a column of running text where it stands on its own.
   * Where a rail stands beside it the column takes what is left instead and
   * the measure is held by the type size -- see `.article .prose`. */
  --prose-max: 42rem;
  --form-max: 34rem;
  /* The rail beside a long text or a form: contents, author, the next step.
   * Wide enough for a card with a heading and three lines, narrow enough to
   * leave the text column the larger half at every width it appears at. */
  --aside-width: 20rem;
  /* The narrow column of a field grid. Two of these plus a gap is what a
   * form panel needs before it puts two fields on a line. */
  --field-min: 21rem;
  --focus-scroll-margin: 7rem;
  --target-min: 24px;
  --target-primary: 44px;

  --control-height: 2.375rem;
  --control-height-sm: 2rem;
  --control-height-lg: 2.75rem;
  --row-height: 2.5rem;
  --nav-row-height: 2.25rem;

  --icon-size: 1rem;
  --icon-size-sm: 0.875rem;
  --icon-size-lg: 1.125rem;
  --icon-stroke: 1.5;
  --avatar-size: 2rem;
  --avatar-size-sm: 1.5rem;
  --avatar-size-lg: 2.5rem;
}

/* ------------------------------------------------------------------ *
 * 3. Bootstrap, mapped onto the roles above.
 *
 * Repeated inside each theme block rather than declared once, because
 * Bootstrap's own `[data-bs-theme="dark"]` block would otherwise win over a
 * mapping that stands on bare `:root`.
 * ------------------------------------------------------------------ */

:root,
:root[data-theme="light"] {
  /* What the browser paints on its own account follows the theme too.
   * Without this line the page is light as far as the engine is concerned,
   * whatever `body` says: the panel of a `select`, the scrollbars, the
   * caret's default and the styling of any native control the project adds
   * later. It is declared in all three theme blocks below for the same
   * reason the roles are: a value set in only one of them wins in one
   * direction and loses in the other. */
  color-scheme: light;

  --bs-body-font-family: var(--font-family-base);
  --bs-body-font-size: var(--text-base);
  --bs-body-line-height: var(--text-base-line);
  --bs-body-color: var(--color-text);
  --bs-body-bg: var(--color-ground);
  --bs-emphasis-color: var(--color-heading);
  --bs-secondary-color: var(--color-muted);
  --bs-secondary-bg: var(--color-surface-tinted);
  --bs-tertiary-bg: var(--color-surface-subdued);
  --bs-tertiary-color: var(--color-muted);
  --bs-border-color: var(--color-hairline);
  --bs-border-color-translucent: var(--color-hairline);
  --bs-border-radius: var(--radius-control);
  --bs-border-radius-sm: var(--radius-sm);
  --bs-border-radius-lg: var(--radius-card);
  --bs-border-radius-xl: var(--radius-card);
  --bs-border-radius-xxl: var(--radius-modal);
  --bs-border-radius-pill: var(--radius-pill);
  --bs-primary: var(--color-primary-fill);
  --bs-link-color: var(--color-link);
  --bs-link-hover-color: var(--color-link-hover);
  --bs-code-color: var(--color-heading);
  --bs-heading-color: var(--color-heading);
  --bs-focus-ring-color: var(--color-focus);
  --bs-focus-ring-width: var(--border-focus);
  --bs-focus-ring-opacity: 1;
  --bs-highlight-bg: var(--color-primary-soft);
  --bs-highlight-color: var(--color-heading);
  --bs-box-shadow: var(--shadow-card);
  --bs-box-shadow-sm: var(--shadow-flat);
  --bs-box-shadow-lg: var(--shadow-overlay);
  --bs-card-bg: var(--color-surface);
  --bs-card-color: var(--color-text);
  --bs-card-border-color: var(--color-hairline);
  --bs-card-cap-bg: var(--color-surface-subdued);
}

/* ------------------------------------------------------------------ *
 * Dark mode.
 *
 * The site has none, so this half is designed rather than observed — but it
 * is designed out of the site's own material, because half of that site is
 * already dark: the header, the footer, every `section--dark`, the hero
 * under its gradient. What the dark mode does is take that half and make it
 * the whole, which is why the brand gold needs no correction here at all.
 * It reaches 6.85:1 on the lightest of the three dark grounds.
 * ------------------------------------------------------------------ */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --color-ground: var(--dark-page);
    --color-band: var(--dark-surface);
    --color-surface: var(--dark-surface);
    --color-surface-subdued: var(--dark-sunken);
    --color-surface-tinted: var(--dark-raised);
    --color-hairline: var(--grey-line-dark);
    --color-divider: var(--grey-divider-dark);
    --color-border-control: var(--grey-control-dark);
    --color-border-disabled: var(--grey-divider-dark);

    --color-heading: var(--text-cool);
    --color-text: var(--text-cool);
    --color-muted: var(--text-cool-soft);
    --color-on-tint: var(--text-cool-soft);
    --color-disabled: var(--text-cool-soft);

    --color-link: var(--gold-soft);
    --color-link-hover: var(--text-cool);
    --color-focus: var(--gold);

    --color-primary-fill: var(--ivory);
    --color-primary-fill-hover: var(--white);
    --color-on-primary: var(--black);
    --color-primary-soft: var(--tone-gold-dark);
    --color-primary-softer: var(--dark-raised);
    --color-on-primary-soft: var(--on-tone-gold-dark);

    --color-action-fill: var(--gold);
    --color-action-fill-hover: var(--gold-soft);
    --color-on-action: var(--black);

    --color-success: var(--moss-lifted);
    --color-success-fill: var(--moss-ink);
    --color-success-fill-hover: var(--moss);
    --color-on-success: var(--white);
    --color-danger: var(--red-lifted);
    --color-danger-fill: var(--red);
    --color-danger-fill-hover: var(--red);
    --color-on-danger: var(--white);

    --color-ground-problem: var(--tone-red-dark);
    --color-on-ground-problem: var(--on-tone-red-dark);
    --color-ground-solution: var(--tone-gold-dark);
    --color-on-ground-solution: var(--on-tone-gold-dark);
    --color-ground-positive: var(--tone-green-dark);
    --color-on-ground-positive: var(--on-tone-green-dark);

    --color-tone-blue-soft: var(--tone-blue-dark);
    --color-on-tone-blue: var(--on-tone-blue-dark);
    --color-tone-green-soft: var(--tone-green-dark);
    --color-on-tone-green: var(--on-tone-green-dark);
    --color-tone-red-soft: var(--tone-red-dark);
    --color-on-tone-red: var(--on-tone-red-dark);
    --color-tone-amber-soft: var(--tone-gold-dark);
    --color-on-tone-amber: var(--on-tone-gold-dark);
    --color-tone-violet-soft: var(--tone-violet-dark);
    --color-on-tone-violet: var(--on-tone-violet-dark);
    --color-tone-teal-soft: var(--tone-teal-dark);
    --color-on-tone-teal: var(--on-tone-teal-dark);
    --color-tone-grey-soft: var(--tone-grey-dark);
    --color-on-tone-grey: var(--on-tone-grey-dark);

    /* The knob is the near-black here, not the ivory. In the dark set the
     * track of a switch that is on is `--color-primary-fill`, which is the
     * ivory itself: an ivory knob on it would be the same byte, and a switch
     * whose knob cannot be seen states nothing. Black reaches 17.45:1 on the
     * track that is on and 3.48:1 on the one that is off. */
    --color-switch-off: var(--grey-control-dark);
    --color-switch-knob: var(--black);

    /* In the dark set the accent surface has to stand *above* the page
     * rather than below it, so it is the raised ground rather than the
     * black one. */
    --color-accent-surface: var(--dark-raised);
    --color-on-accent: var(--ivory);
    --color-on-accent-muted: var(--text-cool-soft);
    --color-check-edge: var(--gold);
    --show-in-light: none;
    --show-in-dark: block;

    /* Gold needs no correction here. `--color-brand-ink` and
     * `--color-brand-edge` exist so a stylesheet can name the readable gold
     * without asking which mode it is in; in this one all three are the
     * brand value. */
    --color-brand: var(--gold);
    --color-brand-ink: var(--gold);
    --color-brand-edge: var(--gold);
    --color-brand-soft: var(--gold-soft);
    --color-brand-line: var(--gold-line);
    --color-brand-line-soft: var(--gold-line-soft);
    --color-brand-wash: var(--gold-wash);
    --color-on-brand: var(--black);

    --color-selection: var(--gold);
    --color-on-selection: var(--black);

    --chart-1: var(--series-1-dark);
    --chart-2: var(--series-2-dark);
    --chart-3: var(--series-3-dark);
    --chart-4: var(--series-4-dark);
    --chart-average: var(--grey-control-dark);
    --chart-grid: var(--grey-line-dark);

    /* A shadow does nothing on a near-black ground; depth there is carried
     * by the hairline and by the step between the three grounds. */
    --shadow-card: none;
    --shadow-raised: 0 24px 48px -24px rgba(0, 0, 0, 0.75);
    --shadow-overlay: 0 24px 60px -18px rgba(0, 0, 0, 0.8);

    --bs-body-color: var(--color-text);
    --bs-body-bg: var(--color-ground);
    --bs-emphasis-color: var(--color-heading);
    --bs-secondary-color: var(--color-muted);
    --bs-secondary-bg: var(--color-surface-tinted);
    --bs-tertiary-bg: var(--color-surface-subdued);
    --bs-tertiary-color: var(--color-muted);
    --bs-border-color: var(--color-hairline);
    --bs-border-color-translucent: var(--color-hairline);
    --bs-primary: var(--color-primary-fill);
    --bs-link-color: var(--color-link);
    --bs-link-hover-color: var(--color-link-hover);
    --bs-code-color: var(--color-heading);
    --bs-heading-color: var(--color-heading);
    --bs-focus-ring-color: var(--color-focus);
    --bs-highlight-bg: var(--color-primary-soft);
    --bs-highlight-color: var(--color-heading);
    --bs-box-shadow: var(--shadow-card);
    --bs-box-shadow-lg: var(--shadow-overlay);
    --bs-card-bg: var(--color-surface);
    --bs-card-color: var(--color-text);
    --bs-card-border-color: var(--color-hairline);
    --bs-card-cap-bg: var(--color-surface-subdued);
  }
}

/* The same set again, under the attribute the toggle writes, so that a
 * visitor on a light system who chooses dark gets it. */
:root[data-theme="dark"] {
  color-scheme: dark;

  --color-ground: var(--dark-page);
  --color-band: var(--dark-surface);
  --color-surface: var(--dark-surface);
  --color-surface-subdued: var(--dark-sunken);
  --color-surface-tinted: var(--dark-raised);
  --color-hairline: var(--grey-line-dark);
  --color-divider: var(--grey-divider-dark);
  --color-border-control: var(--grey-control-dark);
  --color-border-disabled: var(--grey-divider-dark);

  --color-heading: var(--text-cool);
  --color-text: var(--text-cool);
  --color-muted: var(--text-cool-soft);
  --color-on-tint: var(--text-cool-soft);
  --color-disabled: var(--text-cool-soft);

  --color-link: var(--gold-soft);
  --color-link-hover: var(--text-cool);
  --color-focus: var(--gold);

  --color-primary-fill: var(--ivory);
  --color-primary-fill-hover: var(--white);
  --color-on-primary: var(--black);
  --color-primary-soft: var(--tone-gold-dark);
  --color-primary-softer: var(--dark-raised);
  --color-on-primary-soft: var(--on-tone-gold-dark);

  --color-action-fill: var(--gold);
  --color-action-fill-hover: var(--gold-soft);
  --color-on-action: var(--black);

  --color-success: var(--moss-lifted);
  --color-success-fill: var(--moss-ink);
  --color-success-fill-hover: var(--moss);
  --color-on-success: var(--white);
  --color-danger: var(--red-lifted);
  --color-danger-fill: var(--red);
  --color-danger-fill-hover: var(--red);
  --color-on-danger: var(--white);

  --color-ground-problem: var(--tone-red-dark);
  --color-on-ground-problem: var(--on-tone-red-dark);
  --color-ground-solution: var(--tone-gold-dark);
  --color-on-ground-solution: var(--on-tone-gold-dark);
  --color-ground-positive: var(--tone-green-dark);
  --color-on-ground-positive: var(--on-tone-green-dark);

  --color-tone-blue-soft: var(--tone-blue-dark);
  --color-on-tone-blue: var(--on-tone-blue-dark);
  --color-tone-green-soft: var(--tone-green-dark);
  --color-on-tone-green: var(--on-tone-green-dark);
  --color-tone-red-soft: var(--tone-red-dark);
  --color-on-tone-red: var(--on-tone-red-dark);
  --color-tone-amber-soft: var(--tone-gold-dark);
  --color-on-tone-amber: var(--on-tone-gold-dark);
  --color-tone-violet-soft: var(--tone-violet-dark);
  --color-on-tone-violet: var(--on-tone-violet-dark);
  --color-tone-teal-soft: var(--tone-teal-dark);
  --color-on-tone-teal: var(--on-tone-teal-dark);
  --color-tone-grey-soft: var(--tone-grey-dark);
  --color-on-tone-grey: var(--on-tone-grey-dark);

  --color-switch-off: var(--grey-control-dark);
  --color-switch-knob: var(--black);

  --color-accent-surface: var(--dark-raised);
  --color-on-accent: var(--ivory);
  --color-on-accent-muted: var(--text-cool-soft);
  --color-check-edge: var(--gold);
  --show-in-light: none;
  --show-in-dark: block;

  --color-brand: var(--gold);
  --color-brand-ink: var(--gold);
  --color-brand-edge: var(--gold);
  --color-brand-soft: var(--gold-soft);
  --color-brand-line: var(--gold-line);
  --color-brand-line-soft: var(--gold-line-soft);
  --color-brand-wash: var(--gold-wash);
  --color-on-brand: var(--black);

  --color-selection: var(--gold);
  --color-on-selection: var(--black);

  --chart-1: var(--series-1-dark);
  --chart-2: var(--series-2-dark);
  --chart-3: var(--series-3-dark);
  --chart-4: var(--series-4-dark);
  --chart-average: var(--grey-control-dark);
  --chart-grid: var(--grey-line-dark);

  --shadow-card: none;
  --shadow-raised: 0 24px 48px -24px rgba(0, 0, 0, 0.75);
  --shadow-overlay: 0 24px 60px -18px rgba(0, 0, 0, 0.8);

  --bs-body-color: var(--color-text);
  --bs-body-bg: var(--color-ground);
  --bs-emphasis-color: var(--color-heading);
  --bs-secondary-color: var(--color-muted);
  --bs-secondary-bg: var(--color-surface-tinted);
  --bs-tertiary-bg: var(--color-surface-subdued);
  --bs-tertiary-color: var(--color-muted);
  --bs-border-color: var(--color-hairline);
  --bs-border-color-translucent: var(--color-hairline);
  --bs-primary: var(--color-primary-fill);
  --bs-link-color: var(--color-link);
  --bs-link-hover-color: var(--color-link-hover);
  --bs-code-color: var(--color-heading);
  --bs-heading-color: var(--color-heading);
  --bs-focus-ring-color: var(--color-focus);
  --bs-highlight-bg: var(--color-primary-soft);
  --bs-highlight-color: var(--color-heading);
  --bs-box-shadow: var(--shadow-card);
  --bs-box-shadow-lg: var(--shadow-overlay);
  --bs-card-bg: var(--color-surface);
  --bs-card-color: var(--color-text);
  --bs-card-border-color: var(--color-hairline);
  --bs-card-cap-bg: var(--color-surface-subdued);
}
