/**
 * @file style.css
 * @description The documentation, drawn on the site's plate.
 *
 * This file used to be a fork. It declared 108 colours of its own, none of them
 * the site's, in a single skin, under a type stack nothing else on the site
 * uses. A reader left a two skin site through a link marked DOCS and landed on a
 * page that shared none of it, which on a dark machine was a page that flashed
 * white at them.
 *
 * It is now a consumer. Every colour, every family and every size step comes
 * from `tokens.css` beside it, which `site/scripts/wiki-tokens.mjs` generates
 * from `site/styles/tokens.css` and the `:root` blocks of `site/styles/type.css`
 * and refuses to let drift. Nothing here writes a hex. If a value is missing,
 * add it to the site's token layer and regenerate; do not inline it.
 *
 * Three rules from `site/content/DESIGN-CONTRACT.md` hold on every line below.
 *
 *   1. Sans is the prose face, mono is the instrument face. Inter carries the
 *      paragraphs, JetBrains Mono carries every label, eyebrow, caption, table
 *      header, route, code block and readout, and Anybody is display only. Every
 *      mono surface names `var(--mono)` explicitly. None of them inherits it,
 *      and none of those declarations is redundant.
 *   2. Radius is zero. The only curves are the status dots and the hexagon
 *      clip-path on the buttons.
 *   3. Depth is drawn, not lit. No shadow on hover, no lift, no scale, no glow.
 *      Separation is a rule, a hatch, a tick or a registration mark.
 *
 * The furniture sections repeat the site's own nav and footer rules rather than
 * linking them, for the reason `tokens.css` gives: `styles/` is not deployed and
 * the built bundle's filename carries a content hash. Where a rule here has a
 * twin in `site/styles/kit.css` or `site/styles/site.css`, that file is the
 * original and this one follows it.
 *
 * @author Byte <bhumika@bytevion.com>
 */

/* ==========================================================================
   1. Reset
   ========================================================================== */

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

* {
  margin: 0;
}

html {
  /* Landscape on iOS inflates text in a way that breaks a fixed label scale. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  tab-size: 2;
}

img,
svg,
video {
  display: block;
  max-inline-size: 100%;
}

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

/* ==========================================================================
   2. Local layout variables

   Sizes only. Not one of these is a colour, and none of them belongs in the
   site's token layer, because nothing on the site has a documentation rail.
   ========================================================================== */

:root {
  /* Reserved for the fixed header, and the larger figure an anchored jump has
     to clear once the bar has detached into its card. Both are the site's own
     measured numbers; see the note beside them in styles/site.css. */
  --nav-h: 78px;
  --nav-clear: 97px;

  --rail-w: 248px;
  --rail-w-collapsed: 60px;
  --rail-w-current: var(--rail-w);
  --rail-gap: 32px;

  /* The reading measure, in characters, so it re-derives from the face rather
     than from a remembered pixel count. Wider than the site's 67, because a
     reference page is scanned as often as it is read and a narrow column makes
     a long table of contents longer. */
  --measure: 76ch;
}

@media (min-width: 768px) {
  :root {
    --nav-clear: 113px;
  }
}

@media (min-width: 1280px) {
  :root {
    --rail-gap: 48px;
  }
}

body.sidebar-collapsed {
  --rail-w-current: var(--rail-w-collapsed);
}

/* ==========================================================================
   3. Shell
   ========================================================================== */

body {
  font-family: var(--sans);
  font-size: var(--f-body);
  font-weight: 400;
  line-height: 1.55;
  letter-spacing: 0;
  color: var(--ink-2);
  /* The colour only, never the shorthand: the grain below is a background
     image on the same element and the shorthand would erase it. */
  background-color: var(--ground);
  min-block-size: 100svh;
  /* The 320px insurance policy. This page is full of things that are one word
     to a line breaking algorithm and much wider than a narrow column:
     `~/.claude/byte-agent-monitor/dashboard.db`, `general-purpose`,
     `MCP_DASHBOARD_ALLOW_DESTRUCTIVE`. */
  overflow-wrap: break-word;
  /* Room for the fixed header, which sits over the page rather than in flow. */
  padding-block-start: var(--nav-h);
}

/*
 * One 200x200 fractalNoise tile, so nothing on the page is a flat colour.
 * `stitchTiles="stitch"` is the whole trick: the filter is evaluated per tile,
 * and without it every repeat shows its seams as a grid of hard edges.
 */
body::before {
  content: "";
  position: fixed;
  z-index: -1;
  inset: 0;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200' viewBox='0 0 200 200'%3E%3Cfilter id='kn' x='0%25' y='0%25' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='5' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23kn)'/%3E%3C/svg%3E");
  background-size: 200px 200px;
  background-repeat: repeat;
  opacity: 0.35;
  mix-blend-mode: multiply;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) body::before {
    mix-blend-mode: screen;
    opacity: 0.14;
  }
}

:root[data-theme="dark"] body::before {
  mix-blend-mode: screen;
  opacity: 0.14;
}

/* Anything with an id is a jump target, from the skip link, from the rail, or
   from a fragment somebody pasted. Without this they all land under the fixed
   header, which reads as the link having gone to the wrong place. */
[id] {
  scroll-margin-block-start: var(--nav-clear);
}

.wrap {
  inline-size: min(var(--wrap), 100%);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.skip {
  position: fixed;
  inset-block-start: -120px;
  inset-inline-start: 16px;
  z-index: 999;
  padding: 12px 20px;
  background: var(--ink);
  color: var(--ground);
  font-family: var(--display);
  font-weight: 600;
  text-decoration: none;
  transition: inset-block-start var(--t-state) var(--e-state);
}

.skip:focus-visible {
  inset-block-start: 16px;
}

/*
 * The house focus ring. Two bands, so it survives over any ground: an ink
 * outline offset off the element, and a five pixel plate of the page's own
 * colour behind it. `.btn` opts out below and draws a hexagonal plate instead,
 * because a rectangular shadow round a chamfered button paints flat ground over
 * the grain at all four corners.
 */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px var(--ground);
}

.vh {
  position: absolute;
  inline-size: 1px;
  block-size: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border-inline-width: 0;
}

/*
 * Every drawing on this page has its reading written out in a `.vh` block. The
 * head script sets `html.js` before first paint, so if it never ran, or ran and
 * threw, the class is absent and those alternatives stop being hidden and
 * become the content.
 */
html:not(.js) .vh {
  position: static;
  inline-size: auto;
  block-size: auto;
  margin: 0;
  overflow: visible;
  clip-path: none;
  white-space: normal;
}

/* ==========================================================================
   4. Motion

   Copied in policy, not in wording, from site/styles/type.css. The gate is an
   attribute rather than a media query, because a media query answers to the
   operating system and nothing on the page can overrule it, and the header
   carries a three position motion control that has to be able to.

   `html:not([data-motion="full"])` is deliberately the negative form. It has to
   be true in three situations: the visitor or the OS asked for less; no script
   ran; the head script was blocked. The failure mode of this rule should be too
   still, never too much movement.
   ========================================================================== */

html[data-motion="full"] {
  scroll-behavior: smooth;
}

/*
 * An allowlist, not a duration clamp. What is left transitions as designed;
 * what is gone snaps, which for a page written finished state first means it is
 * simply there. Delay is not reset: the reveal stagger is choreography, and
 * content arriving in an order is not motion.
 */
html:not([data-motion="full"]),
html:not([data-motion="full"]) *,
html:not([data-motion="full"]) *::before,
html:not([data-motion="full"]) *::after {
  transition-property:
    opacity, color, background-color, border-color, outline-color, box-shadow, fill, stroke,
    text-decoration-color, caret-color, accent-color !important;
  scroll-behavior: auto !important;
}

/* 1ms, not `none` and not `0ms`. A zero length animation never fires
   `animationend`, and anything waiting on that event to hand over hangs half
   built. One millisecond runs, completes, and dispatches. */
html:not([data-motion="full"]) *,
html:not([data-motion="full"]) *::before,
html:not([data-motion="full"]) *::after {
  animation-duration: 1ms !important;
  animation-delay: 0ms !important;
  animation-iteration-count: 1 !important;
}

/*
 * The reveal, in two tiers.
 *
 * The finished state is the CSS default. The pre-animation state exists only
 * under `html.js`, which script.js is what writes, so a page whose script never
 * arrives is a complete page rather than a blank one. Tier 1 is opacity, and it
 * applies under both motion settings, because arriving in an order at your own
 * pace is not motion. Tier 2 adds the travel and is gated on the resolved
 * attribute.
 *
 * Under reduce the fade starts from `--reveal-floor` rather than from zero, so
 * a visitor whose script half loads reads a slightly flat page rather than an
 * empty one.
 */
html.js .reveal-on-scroll {
  opacity: var(--reveal-floor, 0.6);
  transition: opacity var(--t-enter) var(--e-enter) var(--reveal-delay, 0ms);
}

html.js .reveal-on-scroll.is-visible {
  opacity: 1;
}

html.js[data-motion="full"] {
  --reveal-floor: 0;
}

html.js[data-motion="full"] .reveal-on-scroll {
  translate: 0 24px;
  transition:
    opacity var(--t-enter) var(--e-enter) var(--reveal-delay, 0ms),
    translate var(--t-enter) var(--e-travel) var(--reveal-delay, 0ms);
}

html.js[data-motion="full"] .reveal-on-scroll.is-visible {
  translate: 0 0;
}

/*
 * The jump target's acknowledgement. A rule struck down the left edge of the
 * section you landed on, dissolving. Not a glow and not a background flash:
 * the page is a plate, and the way a plate points at something is with a mark
 * in the margin.
 */
.nav-target-highlight {
  position: relative;
}

.nav-target-highlight::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: calc(-1 * clamp(10px, 1.4vw, 20px));
  inline-size: 3px;
  background: var(--signal);
  animation: doc-target 2.2s var(--e-state) forwards;
}

@keyframes doc-target {
  0% {
    opacity: 1;
  }
  60% {
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

/* ==========================================================================
   5. The hexagon button

   The site's signature component. The chamfer scales with the size; it is not a
   fixed bevel. You cannot border a clip-path, so the outline variant is a
   filled hexagon with a ground coloured face punched back through it.

   The polygon is written out in the rule rather than parked in a custom
   property because a var() inside a custom property is substituted where that
   property is declared, not where it is used.
   ========================================================================== */

.btn {
  --hex: 10px;
  --hex-py: 10px;
  --rim: 0px;
  --ring-w: 3px;
  --edge: var(--ink);
  --face: var(--ink);
  --btn-ground: var(--ground);

  position: relative;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: var(--hex-py) calc(var(--hex) + 16px);
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--ground);
  font-family: var(--display);
  font-size: var(--f-label);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.15;
  white-space: nowrap;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  appearance: none;
  transition:
    transform var(--t-state) var(--e-state),
    color var(--t-state) var(--e-state);
}

.btn::before,
.btn::after {
  content: "";
  position: absolute;
  z-index: -1;
  clip-path: polygon(
    var(--h) 0,
    calc(100% - var(--h)) 0,
    100% 50%,
    calc(100% - var(--h)) 100%,
    var(--h) 100%,
    0 50%
  );
  transition:
    background-color var(--t-state) var(--e-state),
    inset var(--t-state) var(--e-state);
}

.btn::before {
  --h: var(--hex);
  inset: 0;
  background: var(--edge);
}

/* The face sits inside the edge by --rim. Its chamfer shrinks with the inset so
   the keyline stays roughly even round the corner. */
.btn::after {
  --h: calc(var(--hex) - var(--rim));
  inset: var(--rim);
  background: var(--face);
}

.btn--sm {
  --hex: 8px;
  --hex-py: 6px;
  font-size: var(--f-label-sm);
}

/* Hover draws a keyline rather than lighting the surface: the face pulls back
   2px and the edge underneath shows through as a struck rule. Active pushes it
   to 3px, so a press reads as something stamped into the paper. */
.btn--signal {
  --edge: var(--signal);
  --face: var(--signal);
  color: var(--signal-on);
}

.btn--signal:hover {
  --rim: 2px;
  --edge: var(--ink);
}

.btn--signal:active {
  --rim: 3px;
  --edge: var(--ink);
}

/* The house ring's second band is a rectangle, and it paints flat ground over
   the page grain at the four chamfers. The hexagonal plate below replaces both
   bands, so the rectangle has to go. */
.btn:focus-visible {
  --rim: 0px;
  outline: none;
  box-shadow: none;
  z-index: 3;
}

.btn:focus-visible::before {
  --h: calc(var(--hex) + 2px);
  inset: calc(-1 * var(--ring-w));
  background: var(--ring-c, var(--ink));
}

/* ==========================================================================
   6. Links

   The block flood. Hover is not a colour shift on the glyphs, it is a solid
   block of signal that bleeds 6px past the text on both sides, so the link
   reads as struck through with a marker. The padding and the negative margin
   are equal, which keeps the flood out of the layout entirely.
   ========================================================================== */

.link-flood {
  display: inline-block;
  padding: 0 6px;
  margin: 0 -6px;
  color: inherit;
  text-decoration: none;
  transition:
    background-color var(--t-state) var(--e-state),
    color var(--t-state) var(--e-state);
}

.link-flood:hover,
.link-flood[aria-current="page"]:hover {
  background: var(--signal);
  color: var(--signal-on);
}

.link-flood[aria-current="page"] {
  color: var(--ink);
  box-shadow: inset 0 -1px 0 0 var(--signal);
}

/* ==========================================================================
   7. The site header

   Adapted from site/styles/kit.css and site/styles/site.css. The bar is fixed
   and full bleed; its row carries the page's own column rather than the
   window's, so the brand lands on the same margin the documentation below it
   does. Past 1600 an uncapped row walks away from the document, which only
   shows on a wide monitor.
   ========================================================================== */

.nav {
  --nav-inset: 16px;
  position: fixed;
  z-index: 50;
  inset-block-start: 0;
  inset-inline: 0;
}

@media (min-width: 768px) {
  .nav {
    --nav-inset: 32px;
  }
}

.nav__bar {
  --bar-px: var(--gutter);
  /* The disclosure panel hangs from this box, so it has to be the containing
     block. */
  position: relative;
  padding: 12px var(--bar-px) 0;
  border: 1px dashed transparent;
  border-block-end-color: var(--hair);
  background: var(--ground);
  transition:
    margin 300ms var(--e-state),
    padding 300ms var(--e-state),
    border-color 300ms var(--e-state),
    background-color 300ms var(--e-state);
}

.nav[data-scrolled]:not([data-scrolled="false"]) .nav__bar {
  --bar-px: 16px;
  margin: var(--nav-inset);
  border-color: var(--hair-3);
  background: var(--surface);
}

/* Written as two subtractions rather than `2 * var(--gutter)` out of caution: a
   calc() multiplying a custom property is silently dropped whenever that
   property holds a min() with a percentage in it. */
.nav__row {
  inline-size: min(calc(var(--wrap) - var(--gutter) - var(--gutter)), 100%);
  margin-inline: auto;
  display: flex;
  align-items: center;
  gap: 24px;
}

.nav__brand {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-inline-end: auto;
  color: var(--ink);
  text-decoration: none;
}

.nav__panel {
  display: contents;
}

.nav__links {
  display: flex;
  align-items: center;
  gap: 22px;
}

.nav__links .nav-link {
  padding: 0 6px;
  margin: 0 -6px;
  color: var(--ink-2);
  font-family: var(--mono);
  font-size: var(--f-label-sm);
  font-weight: 500;
  letter-spacing: 0.025em;
  text-transform: uppercase;
  text-decoration: none;
}

/* The document rule. It ships empty and keeps its height either way, so the
   page with no script gets a plain strip rather than a broken instrument. */
.nav__rail {
  block-size: 22px;
  margin-inline: calc(-1 * var(--bar-px));
  padding-inline: max(
    var(--bar-px),
    calc(50% - (var(--wrap) - var(--gutter) - var(--gutter)) / 2 + var(--bar-px))
  );
  border-block-start: 1px solid var(--hair);
}

.nav__toggle {
  display: none;
  align-items: center;
  justify-content: center;
  inline-size: 34px;
  block-size: 34px;
  padding: 0;
  border: 1px solid var(--hair);
  border-radius: 0;
  background: none;
  cursor: pointer;
}

.nav__bars {
  display: grid;
  gap: 5px;
}

.nav__bars i {
  display: block;
  inline-size: 15px;
  block-size: 1.5px;
  background: var(--ink);
  transition: transform var(--t-state) var(--e-state);
}

[aria-expanded="true"] .nav__bars i:first-child {
  transform: translateY(3.25px) rotate(45deg);
}

[aria-expanded="true"] .nav__bars i:last-child {
  transform: translateY(-3.25px) rotate(-45deg);
}

/* ---------------------------------------------- the preference controls -- */

/*
 * Two controls, one construction: colour scheme and motion. The inputs stay
 * real, so keyboard and assistive technology get a labelled radiogroup for
 * free and the segmented chip is only paint.
 *
 * The knob is one travelling third of the track rather than a fill that appears
 * under whichever label is checked, which is what shows the reader that the
 * three positions are one switch instead of three buttons. It reads the checked
 * label's ordinal, not its value, so a control can be spelled with any three
 * values it likes.
 */
.nav__seg {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  min-inline-size: 0;
  padding: 2px;
  border: 1px solid var(--hair);
  background: var(--well);
}

.nav__seg label {
  position: relative;
  display: block;
  /* Above the knob, so the checked label's text reads out of the fill. */
  z-index: 1;
}

.nav__seg input {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.nav__seg span {
  display: block;
  padding: 4px 8px;
  font-family: var(--mono);
  font-size: var(--f-micro);
  letter-spacing: 0.1em;
  text-align: center;
  text-transform: uppercase;
  color: var(--ink-3);
  transition:
    color var(--t-state) var(--e-state),
    background-color var(--t-state) var(--e-state);
}

.nav__seg input:checked + span {
  background: var(--ink);
  color: var(--ground);
}

@supports selector(:has(*)) {
  .nav__seg {
    position: relative;
  }

  .nav__seg::after {
    content: "";
    position: absolute;
    z-index: 0;
    inset-block: 2px;
    inset-inline-start: 2px;
    inline-size: calc((100% - 4px) / 3);
    background: var(--ink);
    transform: translateX(var(--knob-x, 0));
    transition: transform var(--t-state) var(--e-state);
    pointer-events: none;
  }

  .nav__seg:has(> label:nth-of-type(1) input:checked) {
    --knob-x: 0%;
  }

  .nav__seg:has(> label:nth-of-type(2) input:checked) {
    --knob-x: 100%;
  }

  .nav__seg:has(> label:nth-of-type(3) input:checked) {
    --knob-x: 200%;
  }

  /* The knob is the fill now, so the label must not paint a second one under
     it: the two disagree by a pixel while the knob is in flight. */
  .nav__seg input:checked + span {
    background: none;
  }
}

.nav__seg input:hover:not(:checked) + span {
  color: var(--ink);
}

/* The ring goes on the paint, because the input itself is a transparent overlay
   and an outline on it would be invisible. */
.nav__seg input:focus-visible + span {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/*
 * Both controls need a script to do anything: the radios are real, but nothing
 * listens to them until script.js runs. Shown without one they are switches
 * that do not switch, and they drag their own legends into view with them,
 * because a scriptless page un-hides every `.vh`. Hiding them costs the visitor
 * nothing: with no script the page follows the operating system for colour
 * through the media query, and shows no motion at all, which is what the two
 * third positions would have selected anyway.
 */
html:not(.js) .nav__seg {
  display: none;
}

/*
 * With no script the header stops being fixed and sits at the top of the
 * document. Everything the fixed position buys is script driven, and what is
 * left of it without one is a box reserving a height that no longer matches it.
 */
html:not(.js) .nav {
  position: static;
}

html:not(.js) body {
  padding-block-start: 0;
}

/* 1199, not 1023: measured, the row needs about 1139px once it carries two
   preference controls, and it has 974 at 1024. */
@media (max-width: 1199px) {
  html.js .nav__toggle {
    display: flex;
  }

  html:not(.js) .nav__row {
    flex-wrap: wrap;
    gap: 12px 18px;
  }

  html:not(.js) .nav__links {
    flex-wrap: wrap;
    gap: 10px 18px;
  }

  html.js .nav__panel {
    display: none;
    opacity: 0;
    translate: 0 -6px;
    transition:
      opacity var(--t-state) var(--e-state),
      translate var(--t-state) var(--e-state),
      display var(--t-state) allow-discrete;
  }

  html.js .nav__panel.is-open {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 18px;
    position: absolute;
    inset-inline: 0;
    inset-block-start: 100%;
    z-index: 1;
    padding: 16px var(--bar-px) 22px;
    border: 1px dashed var(--hair-3);
    border-block-start: none;
    background: var(--surface);
    opacity: 1;
    translate: 0 0;
  }

  @starting-style {
    html.js .nav__panel.is-open {
      opacity: 0;
      translate: 0 -6px;
    }
  }

  html.js .nav__panel.is-open .nav__links {
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
    inline-size: 100%;
  }

  html.js .nav__panel.is-open .nav__seg {
    inline-size: 100%;
  }
}

@media (max-width: 620px) {
  .nav__cta {
    display: none;
  }
}

/* ---------------------------------------------------------- brand lockup -- */

/* The icon and the wordmark are inlined from brand/ by the site's furniture
   script, so the geometry here is the pinned geometry. The icon keeps its own
   colours in both skins, exactly as the app tile ships; the wordmark is
   currentColor and takes the ink, so one inline copy serves both. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--ink);
}

.brand__icon {
  inline-size: 26px;
  block-size: 26px;
  flex: none;
}

.brand__stage {
  display: inline-flex;
  flex: none;
}

/* Sized by height, never by width, which is how site.css sizes it and is the
   reason these three rules are written out rather than eyeballed.

   The wordmark's viewBox is `13 -1 25 10`, so its aspect is 2.5 and the two
   axes are not interchangeable. Setting `inline-size: 66px` here against the
   site's `block-size: 15px` asked for 26.4px of height where the site asks for
   15, and the docs wore a wordmark 76 per cent taller than the one on the
   marketing pages, beside an icon that was the same 26px on both. The mark is
   the one thing on a site that may not be approximately right. */
.brand__word {
  block-size: 15px;
  inline-size: auto;
  flex: none;
}

.brand--footer .brand__icon {
  inline-size: 32px;
  block-size: 32px;
}

.brand--footer .brand__word {
  block-size: 18px;
}

/* ------------------------------------------------------- the pinned strip -- */

/* A replay, and it says so on its own face. It never animates and it carries
   its own label, because a strip that counted up from zero on load would be
   claiming something untrue about where the numbers come from. */
.strip {
  border-block-end: 1px solid var(--hair);
  background: var(--surface);
}

.strip__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px clamp(14px, 2.4vw, 30px);
  padding-block: 9px;
}

.strip__tag {
  font-family: var(--mono);
  font-size: var(--f-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--signal-text);
}

.strip__set {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px clamp(12px, 2vw, 26px);
}

.strip__set > div {
  display: flex;
  align-items: baseline;
  gap: 6px;
}

.strip__set dt {
  font-family: var(--mono);
  font-size: var(--f-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.strip__set dd {
  font-family: var(--mono);
  font-size: var(--f-label-sm);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}

.strip__zero dd {
  color: var(--signal-text);
}

.tnum {
  font-variant-numeric: tabular-nums;
}

/* ==========================================================================
   8. The site footer
   ========================================================================== */

.footer {
  border-block-start: 1px solid var(--hair);
  padding: var(--sect-lg) var(--gutter);
}

/* Capped at the column CONTENT width, not at --wrap. --wrap is a section's
   outer width and .wrap spends --gutter of it on padding, so the column a
   reader sees is --wrap less two gutters. Capping here at --wrap put the
   footer 64px further out on each side once the viewport passed 1728, on
   every page, without ever overflowing anything. Kept identical to
   site/styles/kit.css, which is where the same two rules live for the six
   marketing pages. */
.footer__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 32px 0;
  max-inline-size: calc(var(--wrap) - var(--gutter) - var(--gutter));
  margin-inline: auto;
}

@media (min-width: 768px) {
  .footer__grid {
    grid-template-columns: repeat(5, minmax(0, 1fr));
  }
}

/* border-style: double is the double solid rule, exactly: one pixel, one pixel
   of gap, one pixel. No image, no pseudo element. */
.footer__col {
  padding: 0 20px;
}

.footer__col + .footer__col {
  border-inline-start: 3px double var(--hair);
}

.footer__col:first-child {
  padding-inline-start: 0;
}

.footer__col--brand {
  max-inline-size: 34ch;
}

.footer__head {
  margin-block-end: 14px;
  color: var(--ink-4);
  font-family: var(--mono);
  font-size: var(--f-micro);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.footer__list {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 9px;
  padding: 0;
  list-style: none;
}

.footer__link {
  color: var(--ink-2);
  font-family: var(--mono);
  font-size: var(--f-label-sm);
  font-weight: 500;
  letter-spacing: 0.025em;
  /* A bare email address is one unbreakable word, and at 320 it is wider than
     the column. `anywhere` rather than `break-word` because this must break
     mid token, and it is scoped to footer links so it can never chop a word in
     a sentence. */
  overflow-wrap: anywhere;
}

.footer__blurb {
  margin-block-start: 10px;
  /* Prose, so sans is correct, but 12px is under the floor for Inter. */
  font-size: var(--f-label);
  color: var(--ink-2);
}

.footer__by {
  margin-block-start: 10px;
  font-family: var(--mono);
  font-size: var(--f-micro);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.footer__note {
  max-inline-size: calc(var(--wrap) - var(--gutter) - var(--gutter));
  margin: 40px auto 0;
  color: var(--ink-4);
  font-family: var(--mono);
  font-size: var(--f-micro);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

@media (max-width: 419px) {
  .footer__grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ==========================================================================
   9. The documentation layout

   Two columns past 1024: a plate index on the left, the document on the right.
   The index is sticky rather than fixed, so it can never sit under the header
   and it needs no measurement to stay clear of it.

   Below 1024 there is one column and the index becomes a band of contents above
   the document. That is deliberately not an off canvas drawer: a drawer needs a
   script to open, and this page has to be complete without one.
   ========================================================================== */

.wiki-layout {
  inline-size: min(var(--wrap), 100%);
  margin-inline: auto;
  padding-inline: var(--gutter);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sect-md) var(--rail-gap);
}

@media (min-width: 1024px) {
  .wiki-layout {
    grid-template-columns: var(--rail-w-current) minmax(0, 1fr);
    align-items: start;
  }
}

.main-content {
  min-inline-size: 0;
  padding-block: var(--sect-md) var(--sect-xl);
}

@media (min-width: 1024px) {
  .main-content {
    /* The index draws the column's own edge, so the document needs the gap
       twice: once for the rule and once to stand off it. */
    padding-inline-start: var(--rail-gap);
    border-inline-start: 1px solid var(--hair);
    margin-inline-start: calc(-1 * var(--rail-gap));
  }
}

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

.sidebar {
  min-inline-size: 0;
  padding-block: var(--sect-md) 0;
  transition: none;
}

@media (min-width: 1024px) {
  .sidebar {
    position: sticky;
    inset-block-start: calc(var(--nav-clear) + 8px);
    max-block-size: calc(100svh - var(--nav-clear) - 24px);
    overflow-y: auto;
    overflow-x: hidden;
    /* Scrollbar gutter rather than a hidden overflow, so a long index that has
       to scroll does not resize the column when it starts. */
    scrollbar-width: thin;
    scrollbar-color: var(--hair-3) transparent;
  }
}

.sidebar-header {
  margin-block-end: 18px;
}

.sidebar-topbar {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}

.sidebar-logo {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--ink);
  text-decoration: none;
}

/* The masthead mark.

   This slot used to hold a 14 by 16 hexagon filled with `--signal`, beside the
   word "Byte" set in the display face at weight 800. Neither is a logo. The
   hexagon is the shape the buttons wear, so putting it where a mark goes says
   "button" in the one place on the page that has to say who this is; and the
   product has a real wordmark, `brand/byte-wordmark.svg`, drawn on the same
   pixel grid as the Zyte wordmark in the bar above and rendered by nothing
   until now. It was the only file in brand/ that nothing used.

   `scripts/furniture.mjs` inlines it between the WIKIBRAND markers from that
   file, so it cannot drift from the asset the brand tests pin, and `--check`
   fails the build if this page and brand/ disagree.

   20px against the nav's 15, because a masthead outranks a bar. */
.brand--wiki {
  gap: 9px;
}

.brand--wiki .brand__word {
  block-size: 20px;
}

.logo-sub {
  font-family: var(--mono);
  font-size: var(--f-micro);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.sidebar-toggle {
  display: none;
  flex: none;
  inline-size: 26px;
  block-size: 26px;
  place-items: center;
  padding: 0;
  border: 1px solid var(--hair);
  border-radius: 0;
  background: none;
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  transition:
    color var(--t-state) var(--e-state),
    border-color var(--t-state) var(--e-state);
}

/* The collapse is a wide screen affordance and it needs a script, so it is
   gated on both. Below 1024 the index is a band above the document and there is
   nothing to collapse it into. */
@media (min-width: 1024px) {
  html.js .sidebar-toggle {
    display: grid;
  }
}

.sidebar-toggle:hover {
  color: var(--ink);
  border-color: var(--hair-3);
}

.search-wrap {
  margin-block-end: 18px;
}

.search-input {
  inline-size: 100%;
  min-inline-size: 0;
  padding: 8px 10px;
  border: 1px solid var(--hair);
  border-radius: 0;
  background: var(--well);
  color: var(--ink);
  font-family: var(--mono);
  font-size: var(--f-label-sm);
  letter-spacing: 0.025em;
}

.search-input::placeholder {
  color: var(--ink-4);
  text-transform: uppercase;
  font-size: var(--f-micro);
  letter-spacing: 0.1em;
}

.search-input:focus-visible {
  border-color: var(--ink);
}

/* With no script the field filters nothing, so it is a box that does not work.
   Same argument as the preference controls. */
html:not(.js) .search-wrap {
  display: none;
}

.sidebar-nav {
  display: flex;
  flex-direction: column;
  align-items: stretch;
}

.nav-section {
  padding-block: 14px 6px;
  font-family: var(--mono);
  font-size: var(--f-micro);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.nav-section:first-child {
  padding-block-start: 0;
}

.sidebar-nav .nav-link {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 7px 10px 7px 0;
  border-block-end: 1px solid var(--hair-2);
  color: var(--ink-2);
  font-family: var(--sans);
  font-size: var(--f-label);
  text-decoration: none;
  transition:
    color var(--t-state) var(--e-state),
    background-color var(--t-state) var(--e-state);
}

.sidebar-nav .nav-link:hover {
  color: var(--ink);
  background: var(--surface-2);
}

.sidebar-nav .nav-link.active {
  color: var(--ink);
  box-shadow: inset 2px 0 0 0 var(--signal);
  padding-inline-start: 10px;
}

/* The plate number. Mono, because it is a readout and not prose, and it is what
   makes the collapsed rail legible: nine identical glyphs told the reader
   nothing, and nine numbers are an index. */
.nav-icon {
  flex: none;
  min-inline-size: 2ch;
  font-family: var(--mono);
  font-size: var(--f-label-sm);
  font-variant-numeric: tabular-nums;
  color: var(--ink-4);
}

.sidebar-nav .nav-link.active .nav-icon,
.sidebar-nav .nav-link:hover .nav-icon {
  color: var(--signal-text);
}

.nav-empty {
  display: none;
  padding-block: 10px;
  font-family: var(--mono);
  font-size: var(--f-label-sm);
  color: var(--ink-4);
}

.sidebar-footer {
  padding-block: 20px 0;
  margin-block-start: 18px;
  border-block-start: 1px solid var(--hair);
}

.sidebar-links {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
}

.sidebar-links a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: var(--f-label-sm);
  letter-spacing: 0.025em;
  text-decoration: none;
  overflow-wrap: anywhere;
  transition: color var(--t-state) var(--e-state);
}

.sidebar-links a:hover {
  color: var(--signal-text);
}

.sidebar-links svg {
  flex: none;
}

/* ------------------------------------------------------- the collapsed rail -- */

body.sidebar-collapsed .sidebar .logo-sub,
body.sidebar-collapsed .sidebar .search-wrap,
body.sidebar-collapsed .sidebar .nav-section,
body.sidebar-collapsed .sidebar .sidebar-footer,
body.sidebar-collapsed .sidebar .nav-link > :not(.nav-icon) {
  display: none;
}

/* The mark stays on the rail, at a size that fits it. 60px of rail less its
   padding holds a 35px wordmark and not a 50px one, and the "WIKI" beside it
   hides above rather than being shrunk into an unreadable one. Losing the mark
   entirely would leave a collapsed rail that does not say whose it is.

   This rule used to name `.logo-text`, which stopped existing when the masthead
   became the real wordmark; a selector matching nothing is a rule that has
   quietly stopped doing its job, which is why it is rewritten here rather than
   deleted. */
body.sidebar-collapsed .sidebar .brand--wiki .brand__word {
  block-size: 14px;
}

body.sidebar-collapsed .sidebar .nav-link {
  justify-content: center;
  padding-inline: 0;
  font-size: 0;
}

body.sidebar-collapsed .sidebar .nav-link.active {
  box-shadow: inset 0 -2px 0 0 var(--signal);
}

body.sidebar-collapsed .sidebar-topbar {
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

/* The floating tooltip script.js mounts on <body> so the rail's own overflow
   cannot clip it. */
.byte-side-tip {
  position: fixed;
  z-index: 60;
  padding: 5px 9px;
  border: 1px solid var(--hair-3);
  background: var(--surface);
  color: var(--ink);
  font-family: var(--mono);
  font-size: var(--f-label-sm);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--t-state) var(--e-state);
}

.byte-side-tip.visible {
  opacity: 1;
}

/* ---------------------------------------------- the index below 1024 -- */

/*
 * One row of contents rather than a column, so a phone does not open the docs
 * on four hundred pixels of table of contents. The links wrap; the group
 * headings sit inline with them and read as the labels they are.
 */
@media (max-width: 1023px) {
  /*
   * One column, so the grid's row gap is now vertical rhythm rather than a
   * column gutter, and 40px of it lands on top of the index's own bottom
   * padding and the document column's own top padding. Three paddings in a row
   * put 145px of nothing between the contents and the masthead, measured.
   */
  .wiki-layout {
    row-gap: var(--sect-sm);
  }

  .sidebar {
    padding-block-end: var(--sect-sm);
    border-block-end: 1px solid var(--hair);
  }

  /* A full width field over a nine entry list reads as a search box for the
     document rather than for the index it is standing in. */
  .search-input {
    max-inline-size: 22rem;
  }

  .sidebar-nav {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 6px 8px;
  }

  .nav-section {
    padding: 0;
    inline-size: 100%;
    margin-block-start: 8px;
  }

  .nav-section:first-child {
    margin-block-start: 0;
  }

  .sidebar-nav .nav-link {
    padding: 5px 9px;
    border: 1px solid var(--hair);
    border-block-end: 1px solid var(--hair);
    font-size: var(--f-label-sm);
  }

  .sidebar-nav .nav-link.active {
    padding-inline-start: 9px;
    box-shadow: inset 0 -2px 0 0 var(--signal);
  }

  .sidebar-footer {
    padding-block-start: 16px;
  }

  .sidebar-links {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 8px 20px;
  }

  /* Nothing to collapse into, so the state cannot apply here. */
  body.sidebar-collapsed .sidebar .logo-sub,
  body.sidebar-collapsed .sidebar .search-wrap,
  body.sidebar-collapsed .sidebar .nav-section,
  body.sidebar-collapsed .sidebar .sidebar-footer,
  body.sidebar-collapsed .sidebar .nav-link > :not(.nav-icon) {
    display: revert;
  }

  body.sidebar-collapsed .sidebar .brand--wiki .brand__word {
    block-size: 20px;
  }

  body.sidebar-collapsed .sidebar .nav-section {
    display: block;
  }

  body.sidebar-collapsed .sidebar .search-wrap,
  body.sidebar-collapsed .sidebar .sidebar-footer {
    display: block;
  }

  body.sidebar-collapsed .sidebar .nav-link {
    font-size: var(--f-label-sm);
    padding: 5px 9px;
  }

  body.sidebar-collapsed .sidebar-topbar {
    flex-direction: row;
    align-items: flex-start;
  }
}

/* ==========================================================================
   10. Document typography

   Anybody for the headings, Inter for the paragraphs, JetBrains Mono for
   everything the machine said. There is no bold in prose: headings separate by
   size, by face and by negative tracking.

   Every base rule below scopes itself with `:where(.main-content)`, which
   matches exactly as it reads but contributes nothing to specificity. So each
   one weighs what its element alone would weigh, and any component further
   down, which is always a single class, overrides it without a fight. Written
   as a plain descendant selector these would sit at 0,1,1 and quietly beat the
   eyebrow, the masthead lead and every card in section 15, which is how a base
   layer and a component layer end up in an escalating war of prefixes.
   ========================================================================== */

:where(.main-content) h1 {
  font-family: var(--display);
  font-size: var(--f-display);
  font-weight: 800;
  font-stretch: 100%;
  letter-spacing: -0.045em;
  line-height: 0.98;
  color: var(--ink);
}

:where(.main-content) h2 {
  margin-block: 6px 18px;
  font-family: var(--display);
  font-size: var(--f-h2);
  font-weight: 600;
  font-stretch: 100%;
  letter-spacing: -0.03em;
  line-height: 1.08;
  color: var(--ink);
}

:where(.main-content) h3 {
  margin-block: 34px 12px;
  font-family: var(--display);
  font-size: var(--f-h3);
  font-weight: 600;
  font-stretch: 100%;
  letter-spacing: -0.02em;
  line-height: 1.2;
  color: var(--ink);
}

:where(.main-content section) > p,
:where(.main-content section) > ul,
:where(.main-content section) > ol {
  max-inline-size: var(--measure);
}

:where(.main-content) p {
  margin-block: 0 14px;
  font-size: var(--f-prose);
  letter-spacing: -0.011em;
  color: var(--ink-2);
}

:where(.main-content) p:last-child {
  margin-block-end: 0;
}

:where(.main-content) ul,
:where(.main-content) ol {
  padding-inline-start: 0;
  margin-block: 0 16px;
  list-style: none;
}

:where(.main-content) li {
  position: relative;
  padding-inline-start: 20px;
  padding-block: 5px;
  color: var(--ink-2);
}

:where(.main-content) li + li {
  border-block-start: 1px solid var(--hair-2);
}

/* A registration tick, not a bullet. Square, because radius is zero. */
:where(.main-content) li::before {
  content: "";
  position: absolute;
  inset-block-start: 0.72em;
  inset-inline-start: 0;
  inline-size: 6px;
  block-size: 1px;
  background: var(--signal);
}

:where(.main-content) strong {
  font-weight: 600;
  color: var(--ink);
}

:where(.main-content) em {
  font-style: italic;
}

:where(.main-content) a {
  color: var(--signal-text);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  text-decoration-color: var(--hair-3);
  overflow-wrap: anywhere;
  transition: text-decoration-color var(--t-state) var(--e-state);
}

:where(.main-content) a:hover {
  text-decoration-color: var(--signal);
}

/*
 * Inline code, and it is deliberately not a box.
 *
 * A well with a hairline round it is the usual docs idiom and it was the first
 * thing tried here. It does not survive this document: these paragraphs carry
 * hundreds of snippets, several of them in comma separated runs, and a box with
 * horizontal padding pushes the comma after it a visible gap away, so a line
 * reading `status`, `q`, `limit` renders as three chips adrift from their own
 * punctuation. It also turns a page of prose into a page of chips.
 *
 * So the site's own rule instead: the instrument face at the size of the text
 * it is sitting in, one step darker than the prose around it. Inter and
 * JetBrains Mono are different enough that the face alone is the distinction,
 * which is the whole reason the contract splits them.
 *
 * `letter-spacing: normal` because the prose carries an optical negative value
 * tuned for a proportional face, and negative tracking on a monospaced one is
 * not a refinement but a collision: the glyphs are drawn to fill a fixed
 * advance, so pulling them together closes the sidebearing entirely.
 */
:where(.main-content) code {
  font-family: var(--mono);
  font-size: 1em;
  letter-spacing: normal;
  color: var(--ink);
  /* `break-word`, inherited from the body, and deliberately not `anywhere`.
     `anywhere` breaks at the first opportunity that helps the line rather than
     only when the token genuinely cannot fit, so it chopped
     `DASHBOARD_ALLOWED_HOSTS` in half on a phone, in a document whose whole job
     is to print that name exactly. The weaker value still prevents overflow,
     because the only thing it declines to do is break a word that fits. */
  overflow-wrap: break-word;
}

:where(.main-content) h3 code {
  color: var(--signal-text);
}

/* ==========================================================================
   11. Section furniture
   ========================================================================== */

.main-content section {
  padding-block: var(--sect-lg) 0;
  scroll-margin-block-start: var(--nav-clear);
}

/* [ 01 · Start here ] over a highlighter sweep. The brackets are typed in the
   markup, not generated: a pseudo element can hold the sweep or one bracket,
   never both. */
.eyebrow {
  position: relative;
  display: inline-block;
  padding: 2px 4px;
  margin: 0 -4px 10px;
  color: var(--ink-2);
  font-family: var(--mono);
  font-size: var(--f-label-sm);
  font-weight: 500;
  letter-spacing: 0.025em;
  text-transform: uppercase;
}

.eyebrow::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0;
  background: var(--sweep, var(--wash-3));
}

.eyebrow--1 {
  --sweep: var(--wash-1);
}

.eyebrow--2 {
  --sweep: var(--wash-2);
}

.eyebrow--3 {
  --sweep: var(--wash-3);
}

.eyebrow--4 {
  --sweep: var(--wash-4);
}

/* ==========================================================================
   12. The masthead
   ========================================================================== */

/* No top padding of its own. `.main-content` already opens the column, and the
   two together stacked 80px of nothing above the masthead. */
.hero {
  padding-block: 0;
}

.hero .hero-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 10px;
  margin-block-end: 18px;
  border: 1px solid var(--hair);
  font-family: var(--mono);
  font-size: var(--f-micro);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* A status dot, which is one of the three curves the contract permits. */
.hero .hero-badge .dot {
  inline-size: 6px;
  block-size: 6px;
  flex: none;
  border-radius: 999px;
  background: var(--ok);
}

.hero .hero-desc {
  max-inline-size: 64ch;
  margin-block: 16px 0;
  font-size: var(--f-lead);
  letter-spacing: -0.011em;
  color: var(--ink-2);
}

/* -------------------------------------------------------------- the ticker -- */

/*
 * Two identical groups, the second hidden from the accessibility tree, moved by
 * half the track plus half a gap so the second lands exactly where the first
 * started and the loop has no seam.
 *
 * The default state is the scrollable list, not the frozen one. A marquee with
 * its animation removed hides half its content behind an edge, so with no
 * script, and under reduced motion, this is a strip you can scroll rather than
 * one you cannot read, and the duplicate group is dropped so nothing is said
 * twice.
 */
.marquee-wrapper {
  --gap: 40px;
  position: relative;
  margin-block-start: 28px;
  padding-block: 10px;
  overflow-x: auto;
  overflow-y: hidden;
  border-block: 1px solid var(--hair);
  scrollbar-width: none;
}

.marquee-wrapper::-webkit-scrollbar {
  inline-size: 0;
  block-size: 0;
}

/* No padding on the track, ever. The travel distance is derived from the
   track's own width, so a pad of any size on either end throws the loop out by
   exactly that much and the seam shows once a cycle. */
.marquee-track {
  display: flex;
  gap: var(--gap);
  inline-size: max-content;
}

.marquee-content {
  display: flex;
  flex: none;
  gap: var(--gap);
}

.marquee-content[aria-hidden="true"] {
  display: none;
}

html[data-motion="full"] .marquee-wrapper {
  overflow: hidden;
}

html[data-motion="full"] .marquee-content[aria-hidden="true"] {
  display: flex;
}

html[data-motion="full"] .marquee-track {
  animation: doc-ticker 52s linear infinite;
}

html[data-motion="full"] .marquee-wrapper:hover .marquee-track,
html[data-motion="full"] .marquee-wrapper:focus-within .marquee-track {
  animation-play-state: paused;
}

@keyframes doc-ticker {
  to {
    transform: translateX(calc(-50% - var(--gap) / 2));
  }
}

.tech-badge {
  display: flex;
  flex: none;
  align-items: center;
  gap: 9px;
  white-space: nowrap;
  font-family: var(--mono);
  font-size: var(--f-label-sm);
  font-weight: 500;
  letter-spacing: 0.025em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* A diamond, which is a lozenge and not a dot: the ticker is a list of parts
   and the parts are not statuses. */
.tech-badge::before {
  content: "";
  flex: none;
  inline-size: 5px;
  block-size: 5px;
  background: currentColor;
  clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
}

.tech-badge--signal {
  color: var(--signal-text);
}

/* ==========================================================================
   13. Figures

   Two drawings, both authored inline. Every colour in them resolves through a
   class here rather than through a presentation attribute, so the plate follows
   the reader's skin and there is not one hex in the markup.
   ========================================================================== */

.diagram-wrap {
  margin-block: 22px 26px;
  padding: clamp(14px, 2vw, 26px);
  border: 1px solid var(--hair);
  background: var(--surface);
}

.diagram-wrap svg {
  inline-size: 100%;
  block-size: auto;
}

.diagram-wrap svg text {
  font-family: var(--mono);
}

.diagram-label {
  margin-block-start: 14px;
  padding-block-start: 10px;
  border-block-start: 1px dashed var(--hair);
  font-family: var(--mono);
  font-size: var(--f-label-sm);
  letter-spacing: 0.025em;
  color: var(--ink-3);
}

.d-box {
  fill: var(--well);
  stroke: var(--hair-3);
}

.d-title {
  fill: var(--ink);
}

.d-sub {
  fill: var(--ink-3);
}

.d-note {
  fill: var(--ink-4);
}

.d-code {
  fill: var(--signal-text);
}

.d-flow {
  stroke: var(--signal-text);
  fill: none;
}

.d-arrow {
  fill: var(--signal-text);
}

.d-arrow-mute {
  fill: var(--ink-4);
}

.d-lead {
  stroke: var(--ink-4);
  fill: none;
}

.d-mark {
  stroke: var(--signal);
}

.d-strand {
  stroke: var(--ink-3);
  fill: none;
}

.d-notch {
  stroke: var(--warn);
}

.d-bar {
  stroke: var(--urgent);
}

/* ==========================================================================
   14. Notes and cautions
   ========================================================================== */

.callout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 10px;
  margin-block: 22px;
  padding: clamp(14px, 2vw, 20px);
  border: 1px solid var(--hair-3);
  background: var(--surface-2);
}

@media (min-width: 600px) {
  .callout {
    grid-template-columns: 84px minmax(0, 1fr);
    gap: 20px;
  }
}

.callout-icon {
  font-family: var(--mono);
  font-size: var(--f-micro);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.callout-info .callout-icon {
  color: var(--info);
}

.callout-warning .callout-icon {
  color: var(--warn);
}

.callout-warning {
  border-inline-start: 3px solid var(--warn);
}

.callout-info {
  border-inline-start: 3px solid var(--info);
}

/*
 * The direct child, and the combinator is load bearing. Written as a descendant
 * selector this matched every emphasised phrase inside the note's paragraphs
 * too, so `the server <strong>refuses to start</strong> and names the three
 * ways to fix it` broke into three blocks with the middle one set as a
 * subheading in Anybody. A callout's title is its first child and nothing else.
 */
.callout-body > strong {
  display: block;
  margin-block-end: 6px;
  font-family: var(--display);
  font-size: var(--f-sub);
  font-weight: 500;
  font-stretch: 100%;
  letter-spacing: -0.02em;
  color: var(--ink);
}

.callout-body p {
  max-inline-size: var(--measure);
}

/* ==========================================================================
   15. The screen plates
   ========================================================================== */

.feature-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1px;
  margin-block: 24px;
  border: 1px solid var(--hair);
  background: var(--hair);
}

@media (min-width: 700px) {
  .feature-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1400px) {
  .feature-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* One hairline between every cell, drawn by the grid's own gap over its
   background rather than by a border on each card, so no two rules ever
   double up and no cell has to know where it sits. */
.feature-card {
  padding: clamp(16px, 1.8vw, 24px);
  background: var(--surface);
}

.feature-card__route {
  display: inline-block;
  padding: 2px 7px;
  border: 1px solid var(--hair);
  background: var(--well);
  font-family: var(--mono);
  font-size: var(--f-label-sm);
  letter-spacing: 0.025em;
  color: var(--ink-3);
}

.feature-card__route code {
  font-size: inherit;
  color: inherit;
}

.feature-card h3 {
  margin-block: 4px 10px;
  font-size: var(--f-sub);
}

.feature-card p {
  max-inline-size: 56ch;
  font-size: var(--f-label);
  color: var(--ink-2);
}

/* ==========================================================================
   16. The four steps
   ========================================================================== */

.quick-start-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1px;
  margin-block: 24px;
  border: 1px solid var(--hair);
  background: var(--hair);
}

@media (min-width: 560px) {
  .quick-start-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 1100px) {
  .quick-start-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.qs-card {
  padding: clamp(16px, 1.8vw, 22px);
  background: var(--surface);
}

.qs-step {
  font-family: var(--mono);
  font-size: var(--f-micro);
  font-weight: 500;
  letter-spacing: 0.1em;
  font-variant-numeric: tabular-nums;
  color: var(--signal-text);
}

.qs-card h3 {
  margin-block: 4px 8px;
  font-size: var(--f-sub);
}

.qs-card p {
  max-inline-size: none;
  font-size: var(--f-label);
}

/* ==========================================================================
   17. Tables

   Mono, uppercase headers; sans in the cells, because most of them are
   sentences. A wrapper scrolls on its own so a wide table can never widen the
   page, and it is focusable so the scroll is reachable from the keyboard.
   ========================================================================== */

.table-wrap {
  margin-block: 20px 26px;
  overflow-x: auto;
  border: 1px solid var(--hair);
  background: var(--surface);
}

/*
 * 40rem, and the number is a measurement rather than a round one.
 *
 * A table that shrinks to a phone column is a table whose last column is forty
 * pixels wide, and every row in it then stands eight lines tall against a name
 * on one line. At 32rem the configuration table drew 130px rows of mostly white
 * space. 640px is the width at which the widest variable name, the default and
 * a readable description all have a column, so the wrapper scrolls a little
 * further sideways and the reader gets rows they can take in at a glance.
 */
.table-wrap table {
  inline-size: 100%;
  min-inline-size: 40rem;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}

.table-wrap th {
  padding: 10px 14px;
  border-block-end: 1px solid var(--hair-3);
  background: var(--well);
  font-family: var(--mono);
  font-size: var(--f-micro);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-align: start;
  color: var(--ink-3);
  white-space: nowrap;
}

.table-wrap td {
  padding: 12px 14px;
  border-block-start: 1px solid var(--hair-2);
  vertical-align: top;
  font-size: var(--f-label);
  color: var(--ink-2);
}

.table-wrap tbody tr:nth-child(even) {
  background: var(--surface-2);
}

.table-wrap td:first-child {
  color: var(--ink);
}

/* Inside a table nothing breaks mid token at all. The wrapper already scrolls,
   so the cost of an unbreakable name is a wider table, and the cost of a broken
   one is a variable nobody can read off the page. `normal` still breaks at a
   slash, which is what `$CLAUDE_HOME/byte-agent-monitor` needs. */
.table-wrap code {
  overflow-wrap: normal;
}

/* ==========================================================================
   18. Code

   A titled well. The header carries the language and the copy button, so the
   button is a control on the frame rather than a thing floating over the
   listing it is meant to copy.
   ========================================================================== */

.code-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-block-start: 22px;
  padding: 7px 14px;
  border: 1px solid var(--hair-3);
  border-block-end: none;
  background: var(--surface-2);
}

.code-lang {
  font-family: var(--mono);
  font-size: var(--f-micro);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-4);
}

:where(.main-content) pre {
  margin-block: 22px;
  padding: 14px;
  border: 1px solid var(--hair-3);
  background: var(--well);
  overflow-x: auto;
}

.code-header + pre {
  margin-block-start: 0;
}

:where(.main-content) pre code {
  display: block;
  padding: 0;
  border: 0;
  background: none;
  font-family: var(--mono);
  font-size: var(--f-code);
  line-height: 1.65;
  color: var(--ink-2);
  overflow-wrap: normal;
  white-space: pre;
}

.code-copy-btn {
  flex: none;
  padding: 3px 9px;
  border: 1px solid var(--hair-3);
  border-radius: 0;
  background: none;
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: var(--f-micro);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  transition:
    color var(--t-state) var(--e-state),
    border-color var(--t-state) var(--e-state);
}

.code-copy-btn:hover {
  color: var(--ink);
  border-color: var(--ink);
}

.code-copy-btn--floating {
  position: absolute;
  inset-block-start: 8px;
  inset-inline-end: 8px;
  background: var(--surface);
  opacity: 0;
  transition: opacity var(--t-state) var(--e-state);
}

/* A control that only appears on hover is a control a keyboard cannot find. */
.code-copy-btn--floating:focus-visible {
  opacity: 1;
}

/* ==========================================================================
   19. Status chips and routes
   ========================================================================== */

.status-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 8px;
  border: 1px solid var(--hair-3);
  font-family: var(--mono);
  font-size: var(--f-micro);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--ink-2);
}

.chip-dot {
  inline-size: 6px;
  block-size: 6px;
  flex: none;
  border-radius: 999px;
  background: currentColor;
}

.chip-waiting {
  color: var(--warn);
}

.chip-active {
  color: var(--ok);
}

.route-list {
  display: grid;
  gap: 1px;
  margin-block: 20px 26px;
  border: 1px solid var(--hair);
  background: var(--hair);
}

.route-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 4px 14px;
  padding: 12px 14px;
  background: var(--surface);
}

@media (min-width: 900px) {
  .route-item {
    grid-template-columns: 56px minmax(0, 15rem) minmax(0, 1fr);
    align-items: baseline;
    gap: 14px;
  }
}

.method {
  justify-self: start;
  padding: 1px 6px;
  border: 1px solid currentColor;
  font-family: var(--mono);
  font-size: var(--f-micro);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-align: center;
  color: var(--ink-3);
}

/* Two values, drawn rather than lit: GET is the outline and POST is the fill,
   so the difference survives a monochrome print and does not depend on hue. */
.method-get {
  color: var(--ink-3);
}

.method-post {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--ground);
}

.route-path {
  font-family: var(--mono);
  font-size: var(--f-label-sm);
  font-weight: 500;
  color: var(--ink);
  overflow-wrap: break-word;
}

.route-desc {
  font-size: var(--f-label);
  color: var(--ink-2);
}

/* ==========================================================================
   20. The colophon
   ========================================================================== */

.wiki-footer {
  margin-block-start: var(--sect-xl);
  padding-block-start: 20px;
  border-block-start: 1px solid var(--hair);
}

.wiki-footer p {
  max-inline-size: var(--measure);
  font-family: var(--mono);
  font-size: var(--f-label-sm);
  letter-spacing: 0.025em;
  color: var(--ink-4);
}

.wiki-footer a {
  color: var(--ink-3);
}
