/* Generated by build.py from themes/mono.toml. Do not edit. */

:root {
  color-scheme: light dark;

  --ds-font-mono: 'Berkeley Mono', ui-monospace, 'SF Mono', Menlo, monospace;
  --ds-font-sans: 'Berkeley Mono', ui-monospace, 'SF Mono', Menlo, monospace;
  --ds-font-display: 'Berkeley Mono', ui-monospace, 'SF Mono', Menlo, monospace;
  --ds-weight-text: 400;
  --ds-weight-label: 500;
  --ds-weight-strong: 600;

  --ds-size-micro: 0.6299rem;
  --ds-size-small: 0.7937rem;
  --ds-size-base: 1rem;
  --ds-size-medium: 1.26rem;
  --ds-size-large: 1.588rem;
  --ds-size-huge: 2rem;
  --ds-size-display: 2.52rem;
  --ds-size-mega: 3.176rem;
  --ds-size-wall: clamp(3.176rem, 9vw, 5.042rem);

  --ds-leading: 1.5;
  --ds-measure: 72ch;
  --ds-label-size: 0.66rem;
  --ds-label-track: 0.08em;
  --ds-display-track: -0.02em;
  --ds-display-leading: 0.92;

  --ds-space-1: 0.35rem;
  --ds-space-2: 0.7rem;
  --ds-space-3: 1.05rem;
  --ds-space-4: 1.4rem;
  --ds-space-6: 2.1rem;
  --ds-space-8: 2.8rem;

  --ds-gutter: clamp(0.9rem, 2.4vw, 1.6rem);
  --ds-sheet-max: 76rem;
  --ds-radius: 0;
  --ds-hairline: 1px;
  --ds-dot: 2px;
  --ds-dot-pitch: 6px;

  --ds-keyword-weight: 700;
  --ds-comment-style: italic;
  --ds-string-style: normal;

  --ds-bg: #f2f0ec;
  --ds-surface: #e8e5df;
  --ds-surface-hover: #dfdbd3;
  --ds-raised: #dedad2;
  --ds-line: #c2beb3;
  --ds-line-soft: #dbd7cf;
  --ds-text: #16181c;
  --ds-muted: #55555d;
  --ds-faint: #83807a;
  --ds-accent: #16181c;
  --ds-accent-ink: #f2f0ec;
  --ds-band: #16181c;
  --ds-band-ink: #eae7df;
  --ds-ok: #2f6b3f;
  --ds-warn: #6d5010;
  --ds-danger: #8f2d2d;
  --ds-syntax-keyword: #16181c;
  --ds-syntax-name: #16181c;
  --ds-syntax-string: #2f6b3f;
  --ds-syntax-number: #6d5010;
  --ds-syntax-comment: #6f6c66;
  --ds-syntax-punct: #55555d;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-ds-scheme="light"]) {
    color-scheme: dark;
    --ds-bg: #0e1013;
    --ds-surface: #16181b;
    --ds-surface-hover: #1f2126;
    --ds-raised: #1e2025;
    --ds-line: #343740;
    --ds-line-soft: #23252a;
    --ds-text: #e6e3db;
    --ds-muted: #a3a099;
    --ds-faint: #6d6a65;
    --ds-accent: #e6e3db;
    --ds-accent-ink: #0e1013;
    --ds-band: #24262b;
    --ds-band-ink: #e6e3db;
    --ds-ok: #8fbf98;
    --ds-warn: #d2ad57;
    --ds-danger: #e59797;
    --ds-syntax-keyword: #e6e3db;
    --ds-syntax-name: #e6e3db;
    --ds-syntax-string: #8fbf98;
    --ds-syntax-number: #d2ad57;
    --ds-syntax-comment: #8b8880;
    --ds-syntax-punct: #a3a099;
  }
}

:root[data-ds-scheme="light"] {
  color-scheme: light;
  --ds-bg: #f2f0ec;
  --ds-surface: #e8e5df;
  --ds-surface-hover: #dfdbd3;
  --ds-raised: #dedad2;
  --ds-line: #c2beb3;
  --ds-line-soft: #dbd7cf;
  --ds-text: #16181c;
  --ds-muted: #55555d;
  --ds-faint: #83807a;
  --ds-accent: #16181c;
  --ds-accent-ink: #f2f0ec;
  --ds-band: #16181c;
  --ds-band-ink: #eae7df;
  --ds-ok: #2f6b3f;
  --ds-warn: #6d5010;
  --ds-danger: #8f2d2d;
  --ds-syntax-keyword: #16181c;
  --ds-syntax-name: #16181c;
  --ds-syntax-string: #2f6b3f;
  --ds-syntax-number: #6d5010;
  --ds-syntax-comment: #6f6c66;
  --ds-syntax-punct: #55555d;
}

:root[data-ds-scheme="dark"] {
  color-scheme: dark;
  --ds-bg: #0e1013;
  --ds-surface: #16181b;
  --ds-surface-hover: #1f2126;
  --ds-raised: #1e2025;
  --ds-line: #343740;
  --ds-line-soft: #23252a;
  --ds-text: #e6e3db;
  --ds-muted: #a3a099;
  --ds-faint: #6d6a65;
  --ds-accent: #e6e3db;
  --ds-accent-ink: #0e1013;
  --ds-band: #24262b;
  --ds-band-ink: #e6e3db;
  --ds-ok: #8fbf98;
  --ds-warn: #d2ad57;
  --ds-danger: #e59797;
  --ds-syntax-keyword: #e6e3db;
  --ds-syntax-name: #e6e3db;
  --ds-syntax-string: #8fbf98;
  --ds-syntax-number: #d2ad57;
  --ds-syntax-comment: #8b8880;
  --ds-syntax-punct: #a3a099;
}

:root[data-ds-scheme="white"] {
  color-scheme: light;
  --ds-bg: #ffffff;
  --ds-surface: #f2f2f2;
  --ds-surface-hover: #e6e6e6;
  --ds-raised: #ebebeb;
  --ds-line: #b8b8b8;
  --ds-line-soft: #dedede;
  --ds-text: #000000;
  --ds-muted: #4d4d4d;
  --ds-faint: #808080;
  --ds-accent: #000000;
  --ds-accent-ink: #ffffff;
  --ds-band: #000000;
  --ds-band-ink: #ffffff;
  --ds-ok: #2f6b3f;
  --ds-warn: #6d5010;
  --ds-danger: #8f2d2d;
  --ds-syntax-keyword: #000000;
  --ds-syntax-name: #000000;
  --ds-syntax-string: #2f6b3f;
  --ds-syntax-number: #6d5010;
  --ds-syntax-comment: #6b6b6b;
  --ds-syntax-punct: #4d4d4d;
}

:root[data-ds-scheme="black"] {
  color-scheme: dark;
  --ds-bg: #000000;
  --ds-surface: #0f0f0f;
  --ds-surface-hover: #1c1c1c;
  --ds-raised: #171717;
  --ds-line: #404040;
  --ds-line-soft: #262626;
  --ds-text: #ffffff;
  --ds-muted: #b3b3b3;
  --ds-faint: #737373;
  --ds-accent: #ffffff;
  --ds-accent-ink: #000000;
  --ds-band: #1f1f1f;
  --ds-band-ink: #ffffff;
  --ds-ok: #8fbf98;
  --ds-warn: #d2ad57;
  --ds-danger: #e59797;
  --ds-syntax-keyword: #ffffff;
  --ds-syntax-name: #ffffff;
  --ds-syntax-string: #8fbf98;
  --ds-syntax-number: #d2ad57;
  --ds-syntax-comment: #8c8c8c;
  --ds-syntax-punct: #b3b3b3;
}

/* The little of a reset that is still worth having. Not a normalise: the
   browser's defaults are mostly right now, and the ones that are not are
   the ones that fight a grid. */
*,
*::before,
*::after {
  box-sizing: border-box;
}

body,
h1,
h2,
h3,
h4,
p,
figure,
blockquote,
dl,
dd,
ul,
ol {
  margin: 0;
}

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

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

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

/* The hand means "this acts", on every control and on nothing else. The
   browser gives it to a link but not to a button, a select or a summary, so
   left alone the same page points at some controls and not at others. */
a[href],
button:not(:disabled),
select:not(:disabled),
summary,
label[for],
[role="button"] {
  cursor: pointer;
}

/* A hairline is the system's only border, so it is never a rounded one, and
   it is never two pixels because a panel happened to sit beside another. */
hr {
  border: 0;
  border-top: var(--ds-hairline) solid var(--ds-line);
  margin: 0;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* The vocabulary. Every rule here reads tokens and declares no value of its
   own, which is what makes a theme a theme: change themes/*.toml, rebuild,
   and nothing in this file needs touching.
   A consuming project composes these classes and adds layout. It does not
   restate a colour, a size or a space - lint.py fails the build if it does. */

body {
  background: var(--ds-bg);
  color: var(--ds-text);
  font-family: var(--ds-font-mono);
  font-size: var(--ds-size-base);
  font-weight: var(--ds-weight-text);
  line-height: var(--ds-leading);
  -webkit-font-smoothing: antialiased;
}

/* --- the page ---------------------------------------------------------- */

/* One column, one left edge down the whole page. Every band, strip and grid
   starts on the gutter, which is the single thing holding the sheet together
   once the content stops being regular. */
.ds-sheet {
  max-width: var(--ds-sheet-max);
  margin-inline: auto;
  padding-inline: var(--ds-gutter);
}

/* Escapes the sheet to the full viewport, for the colour blocks that have to
   touch both edges to read as blocks. The negative margin is what makes it
   work from inside a max-width column: `width: 100%` only ever fills the
   parent, which is the thing being escaped. */
.ds-bleed {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  padding-inline: var(--ds-gutter);
}

/* The inverted strip. It holds its own pair of colours so it stays a dark
   band in both schemes instead of flipping to a white slab at dusk. */
.ds-band {
  background: var(--ds-band);
  color: var(--ds-band-ink);
  padding-block: var(--ds-space-2);
}

.ds-rule {
  border-top: var(--ds-hairline) solid var(--ds-line);
}

/* Solid divides; dotted relates. The distinction is the whole grammar of the
   diagrammatic identities this style comes from - a solid line is an edge
   between two things, a dotted one is a link between them, or a thing that is
   not settled yet. Never use it because it looks lighter.

   The dots are drawn rather than bordered. CSS ties a dotted border's dot
   diameter to the border width, so at a hairline it renders as a grey smear
   and at anything thicker as a row of squares; and switching border-style on
   a side that has no width falls back to the browser's 3px `medium`, which is
   how one dotted box ends up with two dot sizes on it. Drawing from two
   tokens means the dot is a theme value and the pitch is a decision. */
.ds-rule--dotted {
  border-top: 0;
  height: var(--ds-dot);
  background-image: radial-gradient(circle closest-side, var(--ds-line) 98%, transparent);
  background-size: var(--ds-dot-pitch) var(--ds-dot);
  background-repeat: repeat-x;
}

/* Provisional: pending, inferred, draft, proposed. One dotted frame around
   the whole thing, never a dotted border per row - a container whose every
   child restates the mark stops reading as a mark. The frame is an overlay
   inset by a step, so it never lands on the solid rule its container already
   draws and read as a doubled edge. */
.ds-provisional {
  position: relative;
}

.ds-provisional::after {
  content: "";
  position: absolute;
  inset: var(--ds-space-1);
  pointer-events: none;
  background-image: radial-gradient(circle closest-side, var(--ds-line) 98%, transparent), radial-gradient(circle closest-side, var(--ds-line) 98%, transparent), radial-gradient(circle closest-side, var(--ds-line) 98%, transparent), radial-gradient(circle closest-side, var(--ds-line) 98%, transparent);
  background-size:
    var(--ds-dot-pitch) var(--ds-dot),
    var(--ds-dot-pitch) var(--ds-dot),
    var(--ds-dot) var(--ds-dot-pitch),
    var(--ds-dot) var(--ds-dot-pitch);
  background-repeat: repeat-x, repeat-x, repeat-y, repeat-y;
  background-position: left top, left bottom, left top, right top;
}

/* A leader: two things on one line, joined rather than divided. The line is
   its own element because a diagram's connector is a thing, not a decoration
   on the thing beside it. */
.ds-connector {
  display: flex;
  align-items: baseline;
  gap: var(--ds-space-2);
}

.ds-connector__line {
  flex: 1;
  height: var(--ds-dot);
  background-image: radial-gradient(circle closest-side, var(--ds-line) 98%, transparent);
  background-size: var(--ds-dot-pitch) var(--ds-dot);
  background-repeat: repeat-x;
  transform: translateY(-0.3em);
}

/* --- panels ------------------------------------------------------------ */

/* A row of full-bleed blocks divided by hairlines rather than by gaps: the
   sheet stays continuous and the division is drawn, not spaced. One of them
   is usually filled, and that fill is the page's only large colour. */
/* No radius, in any theme. A radius is for an object that floats clear of
   what surrounds it; these do not float - they are one continuous surface cut
   by hairlines, and rounding the cut pulls the fill away from the rule and
   leaves the row looking assembled out of loose tiles. */
.ds-panels {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  border-block: var(--ds-hairline) solid var(--ds-line);
  overflow: hidden;
}

/* A card is an object on the sheet, not a run of prose: the I-beam the
   browser puts over its text says "select me" about a thing the reader means
   to point at. A panel is a card. A link or a button inside either still takes
   the hand from the reset, whose element selector outranks a class; an action
   panel takes it from its modifier, which comes after this rule. */
.ds-panel,
.ds-card {
  cursor: default;
}

/* The cut is drawn on two sides of every panel and clipped by the container,
   which is what makes it hold at any arrangement. A border on one side only
   is a rule about where the panels sit, and the row rearranges: at one column
   a left-hand border divides nothing and the panels run together; at two it
   draws a stray line down the outside of the second row. Drawn as a shadow at
   the top and the left of each panel, the lines that land outside the
   container are clipped away and every seam between two panels keeps one, in
   a column, in a row, or in a row that wraps. */
.ds-panel {
  display: flex;
  min-width: 0;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--ds-space-6);
  min-height: 11rem;
  padding: var(--ds-space-3) var(--ds-space-3) var(--ds-space-4);
  background: var(--ds-bg);
  box-shadow:
    calc(-1 * var(--ds-hairline)) 0 0 var(--ds-line),
    0 calc(-1 * var(--ds-hairline)) 0 var(--ds-line);
}

/* Content sits at the bottom of the block, so a row of panels with two words
   in one and twenty in the next still lands on one baseline. */
.ds-panel > :last-child {
  margin-block-start: auto;
}

.ds-panel--accent {
  background: var(--ds-accent);
  color: var(--ds-accent-ink);
}

.ds-panel--surface {
  background: var(--ds-surface);
}

/* A panel that does something. The hover is a ground shift rather than a
   colour change, which is the only kind a monotone theme can make - and the
   kind that still works when the accent is already spent on a neighbour. */
.ds-panel--action {
  cursor: pointer;
  text-decoration: none;
  color: inherit;
  transition: background 90ms linear;
}

.ds-panel--action:hover,
.ds-panel--action:focus-visible {
  background: var(--ds-surface-hover);
}

.ds-panel--accent.ds-panel--action:hover,
.ds-panel--accent.ds-panel--action:focus-visible {
  background: var(--ds-text);
  color: var(--ds-bg);
}

/* --- the index --------------------------------------------------------- */

/* Label column beside content column: the month against its days, the field
   against its value, the section against its notes. The label column is
   fixed so every row in a long list agrees on where the content starts. */
.ds-index {
  display: grid;
  grid-template-columns: minmax(6rem, 10rem) 1fr;
  gap: var(--ds-space-2) var(--ds-space-4);
  align-items: baseline;
  padding-block: var(--ds-space-3);
  border-top: var(--ds-hairline) solid var(--ds-line-soft);
}

/* A grid item's automatic minimum size is the min-content width of what is
   inside it, and a scroll container is no exception: one long line in a code
   well stretched its cell, its track and the page with it, at which point the
   whole document scrolled sideways on a phone instead of the code well
   scrolling inside its own box. Every cell the system draws says min-width: 0
   so the overflow stays where it belongs. */
.ds-index > * {
  min-width: 0;
}

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

/* Wall-sized. Negative tracking and leading under one: at this size the
   default spacing of a face designed for paragraphs reads as a gap, and the
   heading stops being one object. */
.ds-wall {
  font-family: var(--ds-font-display);
  font-size: var(--ds-size-wall);
  font-weight: var(--ds-weight-label);
  line-height: var(--ds-display-leading);
  letter-spacing: var(--ds-display-track);
  text-transform: uppercase;
}

.ds-title {
  font-family: var(--ds-font-display);
  font-size: var(--ds-size-large);
  font-weight: var(--ds-weight-strong);
  line-height: 1.15;
  letter-spacing: var(--ds-display-track);
}

/* Every small uppercase run on the site is this one class - masthead, panel
   heading, index key, tag, caption. They read as one element because they
   are one rule. */
.ds-label {
  font-size: var(--ds-label-size);
  font-weight: var(--ds-weight-label);
  letter-spacing: var(--ds-label-track);
  line-height: 1.3;
  text-transform: uppercase;
  color: var(--ds-muted);
}

.ds-label--loud {
  color: inherit;
}

.ds-muted {
  color: var(--ds-muted);
}

.ds-faint {
  color: var(--ds-faint);
}

.ds-prose {
  max-width: var(--ds-measure);
}

.ds-prose > * + * {
  margin-block-start: var(--ds-space-3);
}

.ds-prose strong {
  font-weight: var(--ds-weight-strong);
}

/* --- spec sheet -------------------------------------------------------- */

/* The technical-documentation register: a field, a hairline, a value. It is
   the same shape as the index and deliberately so - one is prose in the
   right column, the other is a measurement. */
.ds-spec {
  display: grid;
  grid-template-columns: minmax(8rem, 14rem) 1fr;
  gap: 0 var(--ds-space-4);
}

.ds-spec > dt,
.ds-spec > dd {
  min-width: 0;
  padding-block: var(--ds-space-1);
  border-top: var(--ds-hairline) solid var(--ds-line-soft);
}

.ds-spec > dt {
  font-size: var(--ds-label-size);
  font-weight: var(--ds-weight-label);
  letter-spacing: var(--ds-label-track);
  text-transform: uppercase;
  color: var(--ds-muted);
}

/* Below this width the label column costs more than it buys: holding 14rem of
   a 24rem screen for one uppercase word leaves the value column too narrow to
   set anything in, and a spec sheet whose values wrap after two glyphs is not
   a spec sheet. Both shapes stack instead, and they stack together because
   they are the same shape - which is also why this sits at the foot of the
   second one rather than beside the first: it has to come after both, or the
   two-column rule below it wins on source order. */
@media (max-width: 34rem) {
  .ds-index,
  .ds-spec {
    grid-template-columns: 1fr;
  }

  /* Stacked, a field and its value are one row read downwards, so the rule
     that opens the row belongs to the field alone - kept on both, it draws a
     divider through the middle of every entry. */
  .ds-spec > dd {
    padding-block-start: 0;
    border-top: 0;
  }
}

/* --- marks ------------------------------------------------------------- */

/* State is a bordered word, never a filled pill: the system has one fill and
   it belongs to the accent. In the monotone theme these three are the only
   hue on the page, which is exactly how much attention they deserve. */
.ds-tag {
  --tag-ink: var(--ds-muted);
  display: inline-block;
  padding: 0 var(--ds-space-1);
  border: var(--ds-hairline) solid var(--tag-ink);
  border-radius: var(--ds-radius);
  font-size: var(--ds-label-size);
  font-weight: var(--ds-weight-label);
  letter-spacing: var(--ds-label-track);
  text-transform: uppercase;
  color: var(--tag-ink);
}

.ds-tag--ok {
  --tag-ink: var(--ds-ok);
}

.ds-tag--warn {
  --tag-ink: var(--ds-warn);
}

.ds-tag--danger {
  --tag-ink: var(--ds-danger);
}

/* A status is a report, so a plain tag does not react to the pointer - a
   thing that lights up under the cursor and then does nothing is a lie about
   what is clickable. A tag that is a link or a button is a filter, and that
   one inverts: the border colour becomes the fill, keeping the status legible
   while the element states it is a control. Selecting by element rather than
   by a modifier class means it cannot be got wrong - the markup already knows
   whether it acts. The role is held in a local property rather than
   currentColor because the fill and the ink change in the same rule. */
a.ds-tag,
button.ds-tag {
  cursor: pointer;
  text-decoration: none;
  transition: background 90ms linear, color 90ms linear;
}

a.ds-tag:hover,
a.ds-tag:focus-visible,
button.ds-tag:hover,
button.ds-tag:focus-visible {
  background: var(--tag-ink);
  color: var(--ds-bg);
}

/* Underlined, because in a monotone theme colour cannot be what marks a
   link, and a rule that only works in one theme is not a rule. */
.ds-link {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: var(--ds-hairline);
  text-underline-offset: 0.2em;
}

.ds-link:hover,
.ds-link:focus-visible {
  background: var(--ds-accent);
  color: var(--ds-accent-ink);
  text-decoration: none;
}

:focus-visible {
  outline: var(--ds-hairline) solid var(--ds-accent);
  outline-offset: 2px;
}

/* A native control keeps its own type and its own chrome, both of which look
   borrowed. This is the minimum that makes one belong: the system's face, the
   system's hairline, and colours inherited from whatever it sits on - which
   is how it survives being dropped into the inverted band. */
.ds-select {
  background: transparent;
  color: inherit;
  border: var(--ds-hairline) solid currentColor;
  border-radius: var(--ds-radius);
  padding: 0 var(--ds-space-1);
  font-size: var(--ds-label-size);
  font-weight: var(--ds-weight-label);
  letter-spacing: var(--ds-label-track);
  text-transform: uppercase;
}

.ds-select option {
  background: var(--ds-bg);
  color: var(--ds-text);
  text-transform: none;
}

/* Where the browser lets a page draw the open list, it becomes the system's
   own dropdown: an object floating off the sheet, so it takes the radius, one
   hairline, the page's ground whatever the control sits on, and the link's
   accent under the pointer. The element stays a select, so the keyboard, the
   form value and a phone's own picker all still work. A browser without
   base-select keeps the native list above, and nothing else changes. */
@supports (appearance: base-select) {
  .ds-select,
  .ds-select::picker(select) {
    appearance: base-select;
  }

  /* base-select brings a 24px touch-target floor; the control sits in label
     rows half that tall, and a floor there grows the row it sits in. */
  .ds-select {
    gap: var(--ds-space-1);
    min-block-size: 0;
  }

  .ds-select::picker(select) {
    margin-block-start: var(--ds-space-1);
    padding: 0;
    background: var(--ds-bg);
    color: var(--ds-text);
    border: var(--ds-hairline) solid var(--ds-line);
    border-radius: var(--ds-radius);
  }

  .ds-select option {
    gap: var(--ds-space-1);
    padding: var(--ds-space-1) var(--ds-space-2);
    text-transform: uppercase;
  }

  .ds-select option:hover,
  .ds-select option:focus-visible {
    background: var(--ds-accent);
    color: var(--ds-accent-ink);
    outline: none;
  }
}

.ds-code {
  background: var(--ds-raised);
  /* A path or an identifier is one long unbreakable word, and inline it has
     no scroll container to fall back on: on a phone it simply left the page.
     It breaks only when it does not fit, so prose is unaffected. */
  overflow-wrap: anywhere;
  border-radius: var(--ds-radius);
  padding: 0 var(--ds-space-1);
  font-family: var(--ds-font-mono);
  font-size: var(--ds-size-small);
}

pre.ds-code {
  padding: var(--ds-space-2) var(--ds-space-3);
  overflow-x: auto;
}

/* --- highlighting ------------------------------------------------------ */

/* Six roles, not sixteen. base16 spends eight hues on syntax and no reader
   separates eight; what a reader does separate is "a word the language
   owns", "a thing being named", "literal text", "a number", "not code at
   all" and "punctuation". Weight and slant carry as much of that as colour
   does, which is what lets the monotone theme highlight at all. */
.ds-hl--keyword {
  color: var(--ds-syntax-keyword);
  font-weight: var(--ds-keyword-weight);
}

.ds-hl--name {
  color: var(--ds-syntax-name);
}

.ds-hl--string {
  color: var(--ds-syntax-string);
  font-style: var(--ds-string-style);
}

.ds-hl--number {
  color: var(--ds-syntax-number);
}

.ds-hl--comment {
  color: var(--ds-syntax-comment);
  font-style: var(--ds-comment-style);
}

.ds-hl--punct {
  color: var(--ds-syntax-punct);
}

/* The same six, addressed by the class names highlight.js and Prism emit, so
   a project that already runs one of those gets the theme without a mapping
   file and without touching its build. Anything either library emits that is
   not listed here inherits, which is the right default: an unstyled token
   reads as code, not as a bug. */
.hljs-keyword,
.hljs-built_in,
.hljs-literal,
.hljs-type,
.token.keyword,
.token.boolean,
.token.important,
.token.atrule {
  color: var(--ds-syntax-keyword);
  font-weight: var(--ds-keyword-weight);
}

.hljs-title,
.hljs-function,
.hljs-attr,
.hljs-selector-tag,
.token.function,
.token.class-name,
.token.tag,
.token.selector,
.token.attr-name {
  color: var(--ds-syntax-name);
}

.hljs-string,
.hljs-regexp,
.token.string,
.token.regex,
.token.attr-value,
.token.char {
  color: var(--ds-syntax-string);
  font-style: var(--ds-string-style);
}

.hljs-number,
.hljs-symbol,
.token.number,
.token.constant,
.token.symbol {
  color: var(--ds-syntax-number);
}

.hljs-comment,
.hljs-quote,
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
  color: var(--ds-syntax-comment);
  font-style: var(--ds-comment-style);
}

.hljs-punctuation,
.hljs-operator,
.token.punctuation,
.token.operator {
  color: var(--ds-syntax-punct);
}

/* --- the specimen page ------------------------------------------------- */

/* These exist for the reference page and nothing else. They live here rather
   than in the page so the page can be honest: everything it shows is drawn by
   the stylesheet it is demonstrating. */

/* The stack of specimens. Its sections are grid items and take the min-width
   rule the index takes, for the same reason: the code well in the last
   section otherwise sets the width of the column and every section above it
   inherits that width. */
.ds-specimens {
  display: grid;
  gap: var(--ds-space-8);
  padding-block: var(--ds-space-6);
}

.ds-specimens > * {
  min-width: 0;
}

.ds-swatches {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: var(--ds-space-2);
}

.ds-swatch {
  display: flex;
  min-width: 0;
  align-items: center;
  gap: var(--ds-space-2);
}

.ds-swatch__chip {
  width: var(--ds-space-8);
  height: var(--ds-space-6);
  border: var(--ds-hairline) solid var(--ds-line);
  border-radius: var(--ds-radius);
}

.ds-specimen {
  line-height: var(--ds-display-leading);
  letter-spacing: var(--ds-display-track);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Generated by scripts/fonts.mjs. Do not edit; do not commit. */

@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal;
  font-weight: 100 800;
  font-display: swap;
  src: url('/assets/fonts/jetbrains-mono-latin-wght-normal.18be4527.woff2') format('woff2');
}

@font-face {
  font-family: 'JetBrains Mono';
  font-style: italic;
  font-weight: 100 800;
  font-display: swap;
  src: url('/assets/fonts/jetbrains-mono-latin-wght-italic.a8afa085.woff2') format('woff2');
}

:root {
  --ds-font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --ds-font-sans: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --ds-font-display: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
}


/* A domain's public face: the boo banner's layout from home.css, alone on the
   band's colours. 10vw fits "cancelling..." with its tracking on a phone. */
.door {
  display: grid;
  align-content: center;
  justify-items: center;
  gap: var(--ds-space-3);
  min-height: 100dvh;
  margin: 0;
  padding: var(--ds-gutter);
}

.door__word {
  font-size: max(10vw, var(--ds-size-large));
  font-weight: var(--ds-weight-text);
  letter-spacing: var(--ds-label-track);
  text-indent: var(--ds-label-track);
  line-height: 1;
  text-align: center;
  text-wrap: balance;
}
