/* LAYER: page — the docs' own shell and prose, the most specific sheet a
   docs page loads. Beats `component` (sidenav.css, topbar.css) and `site`
   (footer.css), which is what lets the footer rules below simply say what
   they mean. */
@layer page {

/* Drift Documentation — docs-only styles.
 *
 * Shared concerns (the --brand-1/2/3, --ink, --bg, --max-width, and
 * --padding custom properties, the html/body reset, the .btn family)
 * come from styles/global.css, loaded
 * right alongside this file in every docs page's <head> — the same file
 * the homepage loads, not a second copy of the same values. Nothing
 * below touches .navbar, .brand, .btn, or :root — if the navbar ever
 * needs to look different in docs, that's a shared/components/navbar.html
 * slot (see scripts/sync-navbar.py), not a rule here.
 *
 * Page structure (all present in the static HTML — nothing is created
 * and appended by JS anymore):
 *
 *   .docs-layout                       (single column; offset past the sidebar)
 *     div.docs-center                  (inner grid: main | toc)
 *       div.docs-main                  (everything in the middle column)
 *         main.docs-content            (the page's own reading content)
 *         nav.docs-footer-nav          (prev/next)
 *       nav.docs-toc                   (auto-built from this page's headings)
 */

html {
  /* The renderer fills the footer nav; docs.js still builds the
   * TOC after first paint. If that
   * growth crosses the "needs a scrollbar" threshold, the scrollbar
   * appearing shrinks the viewport width out from under any
   * 100vw-sized fixed element, producing a brief horizontal shift.
   * Reserving the scrollbar's space up front means its presence never
   * toggles, so there's nothing to shift. */
  overflow-y: scroll;
}

/* ── The chrome is carried across a navigation ───────────────────────────────
 *
 * Every docs page is its own document, so a click tears the whole page down and
 * paints a new one — measured at 76–84ms from click to first contentful paint.
 * The ARTICLE should change in that window. The column should not: it is
 * identical either side of the click, down to the pixel (same groups, same open
 * branch, same scroll position — only the highlighted row differs). Blinking it
 * out and back is what reads as the navigation flickering, and it is worst where
 * an expanded branch has put twenty-five rows of ink on screen.
 *
 * Naming an element makes the browser treat the old and new instances as ONE
 * object and carry it across rather than draw a new one. The names must be
 * unique within a document, which is why the two bands are named separately
 * instead of sharing one.
 *
 * Both documents have to opt in for this to engage, which every docs page does
 * by loading this file. A browser without cross-document view transitions
 * ignores the at-rule and navigates exactly as before — there is no fallback to
 * write, and nothing degrades. */
} /* @layer page — reopened below.

     @view-transition is valid only at the TOP LEVEL of a stylesheet, never
     inside a grouping rule, so the layer has to be interrupted around it rather
     than wrapping the file whole. Two @layer blocks of the same name merge, so
     this costs nothing but the braces. */

@view-transition { navigation: auto; }

@layer page {

.docs-sidenav { view-transition-name: docs-sidebar; }
.topbar { view-transition-name: docs-topbar; }

/* A blink, not a production. The chrome does not move, so the only thing
   animating is the article replacing itself; a longer cross-fade would turn
   every page change into an event and add its own duration to a navigation that
   already completes in under 100ms. */
::view-transition-old(root),
::view-transition-new(root) { animation-duration: 90ms; }

/* Motion IS the mechanism here, so this turns it off rather than shortening it:
   with `navigation: none` the browser does a plain navigation, which is the
   behaviour someone asking for reduced motion is asking for. */
} /* @layer page — interrupted again for the same reason */

@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }
}

@layer page {

/* ── Page grid ───────────────────────────────────────────────────── */

/* Two nested grids remain, though the outer one now has a single column:
 * .docs-layout clears the pinned header bands and spans full width, while
 * .docs-center caps and centres the content + TOC. The rationale that used to
 * be here was entirely about keeping a left sidebar flush to the true screen
 * edge, and that sidebar is gone. */

/* ---- Where the chrome sits -------------------------------------------------
 * The two components are the page's whole chrome: `sidenav` down the left,
 * `topbar` across the rest of the top. NEITHER OWNS ITS OWN PLACE ON THE PAGE —
 * a component that dictated where it sat could not be used twice, and HQ wears
 * the same column against a different layout. So the pinning is here, in the
 * page's own sheet, which is the only file that knows there are two of them. */
.docs-sidenav {
  position: fixed;
  inset: 0 auto 0 0;
  /* Above the bar's 997. They do not overlap, but the column is the more
     important surface if a future width ever makes them. */
  z-index: 998;
  /* The column's own padding stops at the last row; this is the air under it, so
     the final entry is not flush against the bottom of the viewport. */
  padding-bottom: 40px;
}

/* How far from the left edge the bar starts: the width of what sits beside it.
   The bar reads this and knows nothing else about the column. */
.topbar { --topbar-left: var(--sidenav-w); }

/* No announcement strip and no navbar on the docs. The marketing site's strip
 * carries a broadcast to a stranger arriving on a landing page, and a reader
 * three levels into the CLI reference has already arrived; the column holds the
 * wordmark, the way back to the site and every page, so a second bar across the
 * top would repeat what it already says.
 *
 * ZEROED rather than deleted, all three. Every offset on this page — the
 * layout's top padding, the TOC's resting and sticky position, every heading's
 * scroll-margin — is written as calc(--header-h + --subnav-h), so retiring the
 * bands here retires them in all four places at once and nothing derived has to
 * be found and rewritten.
 *
 * --header-h is the TOP BAR's height on these pages, because the top bar is the
 * only thing pinned above the content. One mapping line, so the derived offsets
 * below keep reading the name they always did. */
:root {
  --announce-h: 0px;
  --nav-h: 0px;
  --subnav-h: 0px;
  --header-h: var(--topbar-h);
}

/* Everything in flow clears the top bar. One rule on the layout rather than on
   the content, so the TOC column clears it too. */
.docs-layout { padding-top: calc(var(--header-h) + var(--subnav-h)); }

/* Nothing is pinned above the content here, so this is the whole of the page's
   top air rather than a gap under a band. It is --docs-top-gap, not a number of
   its own: the TOC beside it derives its offset from the same token, and the two
   columns have to start on the same line. */
.docs-main { padding-top: calc(var(--docs-top-gap) * 1.5); }

/* ONE column. This was "220px 1fr" — a sidebar track beside the content — until
 * the sub-navbar became the docs' navigation and the sidebar was deleted for
 * answering the same question twice. .docs-center still does the capping and
 * centring; .docs-layout is now just what clears the pinned bands.
 *
 * The max-width cap went with the sidebar: it existed so margin:auto would not
 * pull the sidebar off the true left edge. With one centred column there is
 * nothing to hold flush, and .docs-center caps itself. */
.docs-layout {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-areas: "center";
  min-height: 100vh;
  /* THIS element owns the content column, and it is the only one that does.
   * Deriving the same edge in two places is two chances to disagree, and this
   * page has paid for that repeatedly — a missing box-sizing, then a centred
   * grid, then a parent that became a flex container.
   *
   * Capped at --docs-region rather than the site-wide --max-width: the docs hold
   * a wider measure and a wider outline than 1500px has room for once the left
   * gutter is paid. The gutters themselves are the site's, unchanged, so this
   * column starts on the same left edge every other page does. */
  box-sizing: border-box;
  max-width: var(--docs-region);
  margin: 0 auto;
  padding-left: calc(var(--padding) * 1.5);
  padding-right: var(--padding);
  /* Room for the fixed sidebar. It is out of flow, so nothing reserves this
     space on its own and the prose would start underneath it. margin-left
     rather than padding because the cap above measures the content column, and
     padding would eat --padding out of it at every width.
     Stated after the shorthand: `margin: 0 auto` sets all four, and only the
     left one is ours to override. --sidenav-w is the column's own width, stated
     once in shared/components/sidenav/sidenav.css. */
  margin-left: var(--sidenav-w);
}

/* The footer needs the same offset for the same reason: the sidebar is fixed,
   so it reserves no space, and a full-bleed footer runs underneath it and comes
   out from behind on the left.

   width has to move with the margin: 100vw plus a 284px margin is 284px of
   horizontal scroll on every docs page. */
.site-footer {
  margin-left: var(--sidenav-w);
  width: auto;
}

/* The footer's inner column, on the prose's left edge instead of its own.
   footer.css sizes .wrap from --max-width and --padding, which on a docs page
   starts it some hundred pixels right of the text above it — two columns on one
   page, neither wrong on its own. */
.site-footer .wrap {
  max-width: var(--docs-region);
  margin: 0;
  padding-left: calc(var(--padding) * 1.5);
  padding-right: var(--padding);
}

/* ── The docs footer ─────────────────────────────────────────────
 * Two rows: the brand and the status badge share the first, the rule that opens
 * .footer-bottom separates them from the copyright line.
 *
 * The badge is injected between the two by status-badge.js, so this cannot be a
 * two-column grid with named areas — the middle child does not exist until the
 * script runs, and on a failed fetch it never does. A wrapping flex row places
 * whatever is present and lets .footer-bottom claim a line of its own. */
.docs-site-footer .wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1.5rem;
}
/* Full width, so it always lands on its own row under the two above it. */
.docs-site-footer .footer-bottom { flex: 0 0 100%; margin-top: 0; }
.docs-site-footer .footer-brand p { margin: 0.35rem 0 0; }
/* Level with the wordmark rather than the slogan beneath it: the badge is a
   peer of the mark, and aligning it to the block's top edge reads as a stray
   line of text hanging off the right. */
.docs-site-footer .footer-status { margin-top: 0.5rem; }

@media (max-width: 700px) {
  /* Side by side, the badge and the mark end up a few characters each. Stacked
     they keep their own line and the row order still reads top to bottom. */
  .docs-site-footer .wrap { flex-direction: column; gap: 1rem; }
}

@media (max-width: 900px) {
  /* A 284px column is most of a phone, so the sidebar goes back into normal flow
     at the top of the document. The PINNING is dropped here because the pinning
     was this file's to begin with; the column's own sheet handles what it looks
     like once it is a wrapping row.
     It is the first thing in the document, so it clears the top bar itself —
     and the layout drops its own clearance, or the gap is counted twice. */
  .docs-sidenav {
    position: static;
    margin-top: var(--header-h);
    padding-bottom: 0;
  }
  .docs-layout { padding-top: 0; }

  /* The sidebar reserves its own space now, so an offset here would double it. */
  .docs-layout { margin-left: 0; }
  .site-footer { margin-left: 0; width: 100vw; }
}

/* ── Center column (main content + TOC, capped and centered) ────── */

.docs-center {
  grid-area: center;
  display: grid;
  /* TOC on the right. It was tried on the left, where the deleted sidebar used
     to sit, on the theory that the eye starts at the left edge — it read worse:
     the outline competed with the prose for the starting position instead of
     staying out of its way. The content keeps the left edge; the TOC is
     reference material and sits beside it. */
  grid-template-columns: minmax(0, var(--docs-measure)) var(--docs-toc-w);
  grid-template-areas: "main toc";
  /* START, not center. The content column has ONE left edge on this page — the
     one the sub-navbar's first card sits on, and the wordmark above it — and the
     prose has to begin there too. Centring the grid tracks inside the column
     floated the text some hundred pixels right of everything it is supposed to
     line up with. */
  justify-content: start;
  align-items: start;
  /* The TOC is reference material sitting beside the prose, and a narrow gap
     crowds the measure's right edge — close enough to read as a second column of
     the text rather than as an aside. */
  column-gap: var(--docs-col-gap);
  /* border-box, STATED. Without it max-width applies to the CONTENT box and the
     padding is added OUTSIDE it, making this column 1800px wide where a sibling
     sharing --max-width and --padding resolves to 1500px total — two elements
     nominally on the same measure, landing on different left edges. One of
     several places a width or height met a padding or border under a box model
     nobody declared. */
  /* No width, no centring, no side padding: .docs-layout already placed this
     inside the column. Anything here would be a second opinion about where the
     column starts. */
  padding-bottom: 80px;
}

/* No room for the TOC's column.
 *
 * 1500, not the 1240 a 190px outline could live with, and the number is measured
 * rather than chosen. Below this width a 280px outline costs the prose more than
 * the wider measure wins it: at 1440 the text would come out around 600px, which
 * is NARROWER than it was when the outline was 190. So this is the point where
 * the outline stops earning its column — and giving it up hands the prose the
 * whole 940-odd pixels instead.
 * The reader loses the outline on a 1440 laptop. That is the trade, stated
 * plainly: the prose is the page, and a cramped measure costs every reader while
 * a missing outline costs the ones who were going to jump. */
@media (max-width: 1500px) {
  .docs-center {
    grid-template-columns: minmax(0, var(--docs-measure));
    grid-template-areas: "main";
  }
  .docs-toc { display: none; }
}

@media (max-width: 768px) {
  /* One gutter for both, or the footer keeps the desktop 40px while the prose
     drops to 16 and the page shows two left edges on a phone. */
  .docs-layout,
  .site-footer .wrap {
    padding-left: 16px;
    padding-right: 16px;
  }
  .docs-content {
    padding: 24px 0;
  }
  .docs-card-grid {
    grid-template-columns: 1fr;
  }
}

/* More space BETWEEN sections than WITHIN one (below) — proximity does
 * the grouping work: tight spacing reads as "these belong together",
 * generous spacing reads as "new group starts here". */

/* ── Middle column (content + footer nav) ───────────────────────── */

.docs-main {
  grid-area: main;
  min-width: 0; /* let wide <pre> blocks scroll instead of stretching the column */
}

:root {
  /* The gap above the first thing on the page. BOTH columns need it: .docs-main
   * takes it as padding, .docs-toc as part of its own offset — so the outline
   * starts level with the h2 it belongs to. One token, consumed twice; when the
   * two were separate numbers they disagreed by a whole rem and the TOC sat
   * high. */
  /* ---- The reading column, ported from Scaleway's docs ---------------------
   * Read out of their shipped stylesheet rather than eyeballed:
   *   --container-width: 1280px      the region holding prose AND outline
   *   --container-padding: 2.5rem    40px each side of it, at desktop
   *   the outline: min-width 280px; max-width 280px — a hard track
   * so their prose is the 1000px the outline leaves of the 1280.
   *
   * The region grows to the RIGHT, and only to the right. The left gutter is
   * --padding * 1.5, unchanged, so the prose begins exactly where it always has;
   * widening the measure and pushing the outline outward is done by raising the
   * cap, never by moving the edge the reader's eye already knows.
   *
   * Which means the cap cannot be the site-wide --max-width. At 1500px there is
   * no room for a 225px gutter plus 1000 of prose plus 280 of outline, so the
   * prose track would silently shrink back to about what it already was —
   * minmax(0, …) is a ceiling, not a promise. It is summed from its parts
   * below instead. */
  --docs-measure: 1000px;
  --docs-toc-w: 280px;
  /* Ours, not theirs: their outline sits flush against the prose and separates
     itself with a left rail, while this one is reference material that must not
     read as a second column of the text. */
  --docs-col-gap: clamp(40px, 4vw, 88px);
  /* Left gutter + the three tracks + right gutter. Written as the sum so the cap
     cannot fall out of step with what it has to hold. */
  --docs-region: calc(var(--padding) * 1.5 + var(--docs-measure)
                      + var(--docs-col-gap) + var(--docs-toc-w) + var(--padding));

  --docs-top-gap: 3.5rem;
  /* One prev/next card's height. The footer nav is filled by a script after
   * first paint and needs the space reserved — see .docs-footer-nav. */
  --footer-link-h: 76px;
}

.docs-footer-nav {
  display: flex;
  gap: 16px;
  margin-top: 3rem;
  padding-top: 1.5rem;
  /* Shipped in the HTML by scripts/build-docs.py. The reservation stays:
   * 25px tall empty, 101px filled, so the document grew ~95px the
   * moment the script ran. Nothing visible sits below it, so this is not what
   * anyone SAW move — but a document that changes height after paint is what
   * makes a restored scroll position land somewhere other than where it was
   * left. Free to hold, so it is held. */
  min-height: var(--footer-link-h);
  box-sizing: content-box;
}

.docs-footer-link {
  display: flex;
  flex-direction: column;
  gap: 4px;
  text-decoration: none;
  padding: 12px 16px;
  border: 2px solid var(--ink);
  color: var(--ink);
  width: 250px;
  /* Stated, so the space the mount reserves above and the card that lands in it
     are the same number rather than two numbers that happen to agree today. */
  min-height: var(--footer-link-h);
  box-sizing: border-box;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.docs-footer-link:hover {
  color: white;
  background-color: var(--ink);
}

.docs-footer-next { margin-left: auto; text-align: right; }

.docs-footer-label {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}

.docs-footer-title { font-size: 0.95rem; font-weight: 600; }

/* ── TOC (right column, populated from this page's own headings) ─── */

.docs-toc {
  grid-area: toc;
  /* Clears the one thing standing between the top of the row and the page's own
     h2: the gap above the content. Derived from the same token that gap uses, so
     the two columns cannot drift apart the next time it changes. Only the
     resting position — once the column sticks it uses `top` below. */
  margin-top: var(--docs-top-gap);
  position: sticky;
  /* Sticks exactly where it STARTED — level with the page's h2 — rather than
     riding up the moment you scroll. Same sum as its resting position, written
     from the same tokens so it cannot drift away from the margin-top above.
     --header-h and --subnav-h are both zero on the docs and stay in the sum
     because they are what a host with chrome above the content would set. */
  top: calc(var(--header-h) + var(--subnav-h) + var(--docs-top-gap)
            - var(--header-shift, 0px));
  align-self: start;
  max-height: calc(100vh - var(--header-h) - var(--subnav-h) - var(--docs-top-gap)
                   - 24px + var(--header-shift, 0px));
  overflow-y: auto;
  /* No divider. The column gap already separates the two, and a hairline rule
     alongside a page whose every other border is 2px ink read as a stray. */
  padding-left: 20px;
}

/* Fewer than two headings: docs.js leaves this empty rather than
 * building a table of contents with one entry in it. The column's own
 * width is a fixed 190px (not content-sized), so this doesn't collapse
 * the grid track — it just stops the empty border from floating next
 * to nothing. */
.docs-toc:empty { display: none; }

.docs-toc-title {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  padding: 2px 0 8px;
}

/* A single-cell grid, not a block, so the label and its bold twin below can be
 * stacked in the same cell. See .docs-toc-label. */
.docs-toc-link {
  display: grid;
  padding: 4px 0 4px 12px;
  font-size: 13px;
  font-weight: 300;
  line-height: 1.4;
  color: var(--muted);
  text-decoration: none;
  border-left: 2px solid transparent;
  transition: color 0.1s ease, border-color 0.1s ease;
}

/* ---- The outline holds still while you read --------------------------------
 * Every link reserves the height its OWN BOLD FORM would need, at all times.
 *
 * The active entry goes from weight 300 to 600, and bold is wider. In a 190px
 * column that is enough to push a link that fitted on two lines onto three — it
 * gains a line, and every entry below it drops one. Scrolling /docs/sdk/ moved
 * ten of its twenty-six links by 18px each, and the movement tracks the reading
 * position, so the outline squirms exactly while you are looking at it.
 *
 * The twin is the fix: the same string, permanently at 600, permanently hidden,
 * in the same grid cell as the visible label. The cell is as tall as the taller
 * of the two, which is always the bold one — so becoming active changes weight
 * and nothing else. The height was already reserved.
 *
 * Hidden with `visibility`, not `opacity` or a clip: visibility:hidden still
 * takes part in layout (which is the entire point) and is removed from the
 * accessibility tree, so the outline is not read out twice.
 *
 * The cost is a few pixels of slack under the rare link whose bold form needs
 * the extra line — one of twenty-six on a dense page, none at all on most.
 * A little steady whitespace beats ten moving links.
 *
 * The other two active signals — ink colour and the brand-1 left edge — were
 * already free of this: the border is 2px transparent at rest and only changes
 * colour, so it reserves its own space by construction. Bold was the one
 * property that changed the box. Anything added to .active later has to clear
 * the same bar. */
.docs-toc-label { grid-area: 1 / 1; }

.docs-toc-link::before {
  content: attr(data-label);
  grid-area: 1 / 1;
  font-weight: 600;
  visibility: hidden;
}

.docs-toc-link:hover { color: var(--ink); }

.docs-toc-link.active {
  color: var(--ink);
  font-weight: 600;
  border-left-color: var(--brand-1);
}

.docs-toc-link.toc-h4 {
  padding-left: 24px;
  font-size: 12px;
}

/* ── Content typography ─────────────────────────────────────────── */

/* The headline face, same as the marketing page's. --display is defined in
   styles/global.css, and each docs page requests it across `wght@200..700` in
   its own <head> — the face is variable over that range, so every weight named
   below is a weight that actually renders. Ask for a single weight there and
   CSS font matching silently substitutes the nearest one it has, which reads as
   a rule that had no effect rather than as a missing file.
   700 is the default here; the rules below override it where the level wants a
   different weight, and each keeps its own size. */
.docs-content h1,
.docs-content h2,
.docs-content h3,
.docs-content h4 {
  font-family: var(--display);
  font-weight: 700;
}

/* The vertical rhythm is proportional to the hierarchy, and every heading sits
   FAR from what precedes it and CLOSE to what it introduces. That asymmetry is
   the whole of it: a heading equidistant between two paragraphs belongs to
   neither, and the page reads as one undifferentiated column.
   h2 carried no top margin at all, so a new section began against the last line
   of the previous one with only that paragraph's own gap between them. */
.docs-content h1 {
  font-size: 2rem;
  margin-bottom: 0.6rem;
  line-height: 1.2;
}

/* h2 and h3 share a weight, so the step between them is carried by size and by
   h2's rule alone. That is deliberate: at 2.2rem against 24px the size already
   separates them, and a weight change on top would make a section title shout
   twice. */
.docs-content h2 {
  font-size: 2.2rem;
  margin-top: 3.75rem;
  border-bottom: 2px solid var(--bg);
  font-weight: 500;
  /* Negative, because tracking drawn for reading sizes is loose at display
     sizes — the gaps scale with the type while the eye's tolerance does not, and
     the line drifts apart. Well past the marketing hero's -0.01em, because this
     sits at 500 where the hero sits at 700: thinner strokes leave more apparent
     air between letters at the same measured gap, so a heading set lighter needs
     pulling tighter, not looser. About 1.2px out of every gap at 2.2rem. */
  letter-spacing: -0.05em;
}

.docs-content h3 {
  font-size: 24px;
  margin-top: 4rem;
  margin-bottom: 0.75rem;
  font-weight: 500;
  letter-spacing: -0.075rem;;
}

.docs-content h4 {
  font-size: 1.02rem;
  margin-top: 1.9rem;
  margin-bottom: 0.45rem;
  color: var(--ink);
}

/* A page opening on a heading gets its air from .docs-main's padding, not from
   the heading as well — otherwise the first screen is mostly empty and every
   page starts lower than the sidebar beside it. */
.docs-content > :first-child { margin-top: 0; }

/* Anchor-jump offset so a TOC click lands the heading below the fixed navbar */
.docs-content h2,
.docs-content h3,
.docs-content h4 {
  /* An in-page anchor must land below the pinned bands, or the heading you
     jumped to is the one thing hidden behind them. */
  scroll-margin-top: calc(var(--header-h) + var(--subnav-h) + 20px);
}

.docs-content p {
  margin-bottom: 1.15rem;
}

/* Lists were left to the browser, so pages inlined their own margins to get a
   gap at all — the indent and the spacing ended up written per page, differently
   each time. Stated once here, they stop being every author's problem.
   Items get their own gap: a run of one-line bullets with none reads as a
   paragraph that happens to have dots. */
.docs-content ul,
.docs-content ol {
  margin: 0 0 1.25rem 1.25rem;
  padding-left: 0.75rem;
}
.docs-content li { margin-bottom: 0.45rem; }
.docs-content li:last-child { margin-bottom: 0; }
/* A nested list belongs to the item above it, not to the gap after it. */
.docs-content li > ul,
.docs-content li > ol { margin: 0.45rem 0 0 1rem; }

/* ── Code ────────────────────────────────────────────────────────── */

/* brand.css owns how inline code LOOKS — white fill, ink border, 14px, the
   system mono stack, `padding: 0 4px`. This rule adds the one thing the docs
   need on top of it and restates nothing.
   What used to be here was a second opinion, and every difference pushed the
   same way: weight 700, `padding: 2px 7px`, and Courier New. Bold monospace in
   a sentence stops being a token and becomes a shout, the fatter padding made
   every `--flag` a button, and Courier New is a different typeface from the one
   the rest of the page is set in. A token should be quiet enough to read a
   paragraph through. */
.docs-content code {
  /* INLINE code must be allowed to break. Docs prose is full of unbreakable
     tokens — `drift-slice-<user>-<slice>`, a fully-qualified path, an env var —
     and a run of characters with no space in it will not wrap on its own. One
     such token measured 465px inside a 390px viewport and pushed the DOCUMENT
     to 486px, so every page on the docs site scrolled sideways on a phone. The
     page moving is far worse than a token breaking mid-word.

     `pre code` is untouched and must stay that way: it sets white-space:pre and
     its parent already scrolls (overflow-x:auto above), which is the right
     behaviour for a block you are meant to copy verbatim — a wrapped shell
     command is a command that no longer works when pasted.

     Not in a media query on purpose: overflow-wrap only acts when the token
     would otherwise overflow, so this is inert at desktop widths and also fixes
     a narrow browser window. */
  overflow-wrap: anywhere;
}

/* No font-family: every block here is <pre><code>, so the inner element takes
   brand.css's mono stack and the blocks are set in the same face as the inline
   tokens. Naming a second one here is how they drifted apart. */
.docs-content pre {
  background: #1e1e1e;
  color: #dadada;
  border: 2px solid var(--ink);
  padding: 16px 20px;
  font-size: 13px;
  line-height: 1.4;
  overflow-x: auto;
  /* More than a paragraph's gap. A code block is a set piece the eye stops at,
     and at a paragraph's spacing it reads as another line of the prose rather
     than as the thing the prose was leading to. */
  margin: 1.75rem 0;
}

.docs-content pre code {
  background: none;
  border: none;
  padding: 0;
  font-size: inherit;
  font-weight: normal;
  white-space: pre;
  color: inherit;
}

/* ── A single command is a key you press ─────────────────────────────────────
 * A one-line shell command is the one code block a reader does not read — they
 * take it. So it stops being a window onto a terminal and becomes a control: a
 * white card on the grey desk, ink border, ink shadow, and a click that copies
 * it. The dark fill belongs to blocks you read; this is a thing you press, and
 * it wears the same palette as every other pressable object on the platform.
 *
 * Raised at rest, straight from HQ's epic latch: it starts UP, and pressing is
 * what puts it down. That is why there is NO hover raise — raised-at-rest has
 * exactly two positions, up and pressed, and lifting it further on hover
 * borrows the gesture belonging to flat-at-rest controls. Hover brightens the
 * hint instead, which says "this responds" without spending the position.
 *
 * docs.js decides which blocks qualify and builds the element; see the
 * predicate there for what counts as a command. */
.docs-content .docs-cmd {
  position: relative;
  display: block;
  box-sizing: border-box;
  text-align: left;
  /* The block's own margin, so swapping a <pre> for one of these does not move
     the paragraphs around it. */
  margin: 1.75rem 0;
  padding: 12px 76px 12px 16px;
  background: var(--panel);
  color: var(--ink);
  border: 2px solid var(--ink);
  border-radius: 0;
  font-size: 13px;
  line-height: 1.4;
  cursor: pointer;
  /* Already up, waiting to be pushed. */
  transform: translateY(-3px);
  box-shadow: 0 4px 0 var(--ink);
  /* Springy on release, at the latch's 160ms rather than the marketing site's
     320ms: this sits inside prose, and the full overshoot reads as sluggish
     next to text. */
  transition: transform .16s cubic-bezier(.34, 1.56, .64, 1),
              box-shadow .16s cubic-bezier(.34, 1.56, .64, 1);
}
.docs-content .docs-cmd:active {
  transform: translateY(0);
  box-shadow: 0 0 0 var(--ink);
}
.docs-content .docs-cmd:focus-visible {
  outline: 2px solid var(--brand-2);
  outline-offset: 2px;
}
/* brand.css paints every <code> as a chip. Inside the key that would be a grey
   box around the command, so the chip is cleared here exactly as it is inside a
   <pre>. */
.docs-content .docs-cmd code {
  background: none;
  border: none;
  padding: 0;
  font-size: inherit;
  font-weight: inherit;
  color: inherit;
  white-space: pre;
}
/* The affordance in words. The raise says "pressable"; this says what pressing
   does, because copy is not the only thing a button could mean. */
.docs-content .docs-cmd::after {
  content: "copy";
  position: absolute;
  top: 50%;
  right: 14px;
  transform: translateY(-50%);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  transition: color .1s ease;
}
.docs-content .docs-cmd:hover::after { color: var(--ink); }
.docs-content .docs-cmd[data-copied="yes"]::after { content: "copied"; color: var(--brand-3); }
.docs-content .docs-cmd[data-copied="no"]::after  { content: "failed"; color: var(--brand-1); }

/* Syntax highlighting (VS Code Dark+) */
.kw { color: #569CD6; }   /* keywords */
.str { color: #CE9178; }  /* strings */
.cmt { color: #6A9955; }  /* comments */
.fn { color: #DCDCAA; }   /* functions */
.num { color: #B5CEA8; }  /* numbers */
.ctrl { color: #C586C0; } /* control flow */

/* ── Cards ───────────────────────────────────────────────────────── */


.docs-card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  margin: 1rem 0;
}

/* One card per row on a phone. `repeat(3, 1fr)` is a fixed count, not a
   responsive one — 1fr floors at min-content, so three cards plus .btn-docs's
   own `margin-right: 1rem` pushed the DOCUMENT to 470px in a 390px viewport and
   /docs/ was the last page still scrolling sideways. The margin goes too: it is
   spacing between cards in a row, and there is no row any more. */
@media (max-width: 640px) {
  .docs-card-grid { grid-template-columns: 1fr; }
}

/* ── The list: contents of a box ─────────────────────────────────────────────
 *
 * The file tree's shape, applied to prose. A filled ink bar NAMES the set and
 * the items are its contents, indented beneath it as quiet cards — the same
 * argument a folder makes: containment carries the meaning, so nothing has to
 * be framed and no marker has to point.
 *
 * The bar is the page's own <h3>, styled, not a second element carrying the
 * same words. That matters twice over: the heading stays in the document
 * outline, and docs.js keeps building a table-of-contents entry from it. A bar
 * that replaced the heading would have silently cost this page its outline —
 * and with only one h3 left, docs.js drops the TOC entirely.
 *
 *   <h3 class="docs-list-title">What you get out of the box</h3>
 *   <ul class="docs-list">
 *     <li><strong>Term</strong><span>What it means.</span></li>
 *
 * The two elements are a pair: the title's bottom margin is zero because the
 * list sits directly under it, and the list carries the pair's bottom margin.
 *
 * Each row is a tree row's anatomy — a short label, then a note in the body
 * face — held in two columns so every description starts on one edge. A term
 * and its meaning are different KINDS of text, and a column says so more
 * quietly than a font change would. */
.docs-content h3.docs-list-title {
  margin: 2.5rem 0 0;
  padding: 9px 14px;
  background: var(--ink);
  color: #fff;
  font-size: 1.02rem;
  letter-spacing: 0.01em;
}
.docs-content .docs-list {
  list-style: none;
  /* Indented under the bar, the way a folder's contents are. No frame: the bar
     above and the indent are the container. */
  margin: 0 0 1.75rem;
  padding: 8px 0 0 22px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
/* A row is TWO objects with a gap between them: a detached square carrying the
   icon, then the card. Detached rather than a cell inside the card because a
   marker that shares the card's border is a column of it — this one is its own
   plate, the way the file tree's leaf sits beside its folder rather than in its
   frame. */
.docs-content .docs-list li {
  margin: 0;
  display: flex;
  /* STRETCH, so the mark is exactly as tall as the card beside it. A stated
     height here would be a copy of an answer three other declarations already
     hold — the card's line box, its padding and its borders — and the copy is
     what goes stale. Letting the mark stretch leaves nothing to keep in step. */
  align-items: stretch;
  gap: 8px;
}

/* The mark takes its HEIGHT from the row and its WIDTH from that height, so it
   is square without either dimension being written down. Rows are one line by
   the copy rule below, which is what keeps it reading as a square rather than as
   a tall tab. */
.docs-content .docs-list .dl-mark {
  flex: none;
  align-self: stretch;
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--panel);
  border: 2px solid var(--ink-subtle);
  /* The icon is drawn in currentColor, so its colour is set once here. Ink: the
     glyph already carries the meaning, and seven accent-coloured marks down a
     column would spend the docs' one highlight colour on decoration. */
  color: var(--ink);
}
.docs-content .docs-list .dl-mark svg {
  width: 18px;
  height: 18px;
  fill: currentColor;
}

/* The card, in the tree's leaf weight — --panel fill, 2px --ink-subtle
   hairline. Hairline rather than full ink because there are seven of them in a
   column, and at full ink the page becomes a grid of boxes. */
.docs-content .docs-list .dl-card {
  flex: 1;
  min-width: 0;
  display: grid;
  /* minmax(0, …) so a long term wraps inside its column instead of widening it
     and pushing every description out of line. 160px holds the longest term
     this component has and leaves the rest to the note. */
  grid-template-columns: minmax(0, 160px) 1fr;
  gap: 3px 18px;
  padding: 9px 14px;
  line-height: 1.5;
  background: var(--panel);
  border: 2px solid var(--ink-subtle);
}
.docs-content .docs-list .dl-card strong { color: var(--ink); }
/* The note, in the tree's own muted grey and a step down in size — the same
   anatomy a tree row has, where the name leads and the note explains.
   ONE LINE PER ROW IS A COPY RULE, NOT A CSS ONE. At this size the note column
   holds about 60 characters; write past that and the row wraps, which is what
   this component is not for. Nothing here truncates, because a docs list that
   hides the end of a sentence is worse than one that wraps. */
.docs-content .docs-list .dl-card span {
  color: var(--muted);
  font-size: 0.94rem;
}

@media (max-width: 640px) {
  /* One column: at this width the term's column is narrower than most terms,
     so the grid would hyphenate labels to protect an alignment nobody can see
     any more. */
  .docs-content .docs-list .dl-card { grid-template-columns: 1fr; }
  /* The card is two lines here, and a mark that stayed square would be a 70px
     block against a paragraph. It keeps the card's height and takes a fixed
     width instead — a tab rather than a square. */
  .docs-content .docs-list .dl-mark { aspect-ratio: auto; width: 40px; }
}

/* ── Breadcrumbs ─────────────────────────────────────────────────────────────
 *
 * Where this page sits, above its title. Built by scripts/build-docs.py out of the
 * sidebar, so no page carries a trail of its own to keep in step.
 *
 * Nav weight, from BRAND.html#navlinks: --muted at rest, --ink on hover. A
 * crumb is navigation rather than prose, so it takes none of the prose link's
 * underline; the separators are the hairline so the names carry the row. */
.docs-content .docs-crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 7px;
  margin-bottom: -3.5rem;
  font-size: 0.86rem;
  font-weight: 300;
  line-height: 1.4;
  color: var(--muted);
}
.docs-content .docs-crumbs a {
  color: var(--muted);
  text-decoration: none;
  transition: color 0.15s ease;
}
.docs-content .docs-crumbs a:hover { color: var(--ink); }
.docs-content .docs-crumbs .crumb-sep { color: var(--ink-subtle); }
/* The page you are on is the one crumb that is not a link, so it says so in
   weight rather than by being the last thing in the row. */
.docs-content .docs-crumbs .crumb-here { color: var(--ink); font-weight: 500; }

/* ── Inline links ────────────────────────────────────────────────────────────
 *
 * Ink text with an underline. The UNDERLINE is the signal, which is what lets a
 * link be identifiable without spending one of the three pillar colours on it —
 * orange, purple and green mean Atomic, Backbone and Canvas everywhere else on
 * the page, and a link is none of them.
 *
 * Stating :link and :visited alike is the point. A docs index is the one place
 * on the site guaranteed to be half-visited, and a colour that repaints the
 * pages you have already read sorts the list by your history rather than by
 * what it is.
 *
 * The hairline → ink swap on hover is the same weight change the cards make
 * when you reach them: --ink-subtle at rest, full --ink under the cursor.
 * text-underline-offset keeps the rule clear of the descenders. */
.docs-content a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-decoration-color: var(--ink-subtle);
  text-underline-offset: 3px;
  transition: text-decoration-color 0.15s ease;
}
.docs-content a:hover { text-decoration-color: var(--ink); }
.docs-content a:focus-visible {
  outline: 2px solid var(--brand-2);
  outline-offset: 2px;
  text-decoration-color: var(--ink);
}
/* A heading is already the loudest thing in its block; an underline under one
   reads as a mistake rather than as a link. */
.docs-content h2 a,
.docs-content h3 a,
.docs-content h4 a { text-decoration: none; }

/* ── The list, navigating ────────────────────────────────────────────────────
 *
 * The same object with a destination: an overview page listing the pages under
 * it. The row is wrapped in an <a> and is the card alone — NO .dl-mark. Every
 * row on such a page belongs to the same section, so a plate per row is the
 * same glyph repeated down a column, which is decoration rather than a label.
 * The plain .docs-list keeps its mark, where the rows are unlike each other.
 *
 * A LINK HERE IS NOT PROSE, SO IT TAKES NO PROSE STYLING. The whole row is the
 * target, and a blue underlined phrase inside a card that is already clickable
 * says the card is not. Both colours are stated rather than inherited, because
 * `:visited` will otherwise repaint the term on the pages a reader has been to
 * — the one column of a docs index guaranteed to be half-visited.
 *
 * The affordance is the CARD's, from BRAND.html#toy: 4px lift, `0 4px 0`
 * var(--ink), 200ms. It is earned — #cards: "Only cards that DO something get
 * the affordance", and this one goes somewhere. */
.docs-content .docs-list-nav li { display: block; }
.docs-content .docs-list-nav li > a {
  display: block;
  text-decoration: none;
  color: var(--ink);
}
.docs-content .docs-list-nav .dl-card {
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.docs-content .docs-list-nav li > a:hover .dl-card,
.docs-content .docs-list-nav li > a:focus-visible .dl-card {
  transform: translateY(-4px);
  box-shadow: 0 4px 0 var(--ink);
  /* Hairline at rest keeps a column of eleven from reading as a grid of boxes.
     The row being pressed is a single object, so it takes the full edge. */
  border-color: var(--ink);
}
.docs-content .docs-list-nav li > a:active .dl-card {
  transform: translateY(0);
  box-shadow: 0 0 0 var(--ink);
}
.docs-content .docs-list-nav li > a:focus-visible {
  outline: 2px solid var(--brand-2);
  outline-offset: 3px;
}
/* Stated, not inherited: see the :visited note above. */
.docs-content .docs-list-nav .dl-card strong { color: var(--ink); }
.docs-content .docs-list-nav .dl-card > span { color: var(--muted); }

/* ── The counter: a bullet, as an object ─────────────────────────────────────
 *
 * The desk is nothing and a white card is a thing. So the marker is a card at
 * its smallest possible size: 14px of --panel, a 2px ink edge, and the hard ink
 * shadow. The prose stays bare on the desk, which is what keeps this usable for
 * a three-item aside inside a paragraph run — where the titled list, with its
 * bar and its icon plates, would be a set piece.
 *
 * The variant's own stylesheet, unmodified except for the `.docs-content`
 * ancestor its author's production note asks for: `.docs-content ul` above is
 * (0,1,1) and a bare `.ctr-list` is (0,1,0), so an unqualified rule would lose
 * the base list's margin and indent to it. */
.docs-content .ctr-list {
  list-style: none;
  /* The block's own bottom gap, matching the docs' list rhythm. No left margin:
     the gutter below IS the indent, and two of them would double it. */
  margin: 0 0 1.25rem;
  padding: 0;
  font-weight: 300;
  line-height: 1.625;

  /* ONE gutter, stated as its two parts. The prose's left edge is derived from
     them, so changing the marker never leaves the text behind. */
  --ctr-mark: 14px;
  --ctr-gap: 14px;
}

.docs-content .ctr-list > li {
  position: relative;
  /* Items get their own gap: a run of one-line items with none reads as a
     paragraph that happens to have markers. */
  margin: 0 0 0.7rem;
  padding-left: calc(var(--ctr-mark) + var(--ctr-gap));
}
.docs-content .ctr-list > li:last-child { margin-bottom: 0; }

/* The counter itself. Generated, so no markup changes and an existing <li>
   upgrades by putting one class on its list. */
.docs-content .ctr-list > li::before {
  content: "";
  position: absolute;
  left: 0;
  /* (26px first line − 14px tile) / 2 = 6px. The tile centres on the LINE it
     marks, not on the paragraph it starts — an item three lines long would put
     a centred marker beside its middle. */
  top: 6px;
  box-sizing: border-box;
  width: var(--ctr-mark);
  height: var(--ctr-mark);
  background: var(--panel);
  border: 2px solid var(--ink);
  /* Hard, ink, directly below. Two pixels, not four: this is a 14px object and
     the lift has to be proportional to what is lifting. It never animates —
     nothing here is pressable, and this is thickness, not an affordance. */
  box-shadow: 0 2px 0 var(--ink);
}

/* ---- The ordered case -----------------------------------------------------
   A numbered step is a thing you are DOING, so the counter grows until it can
   carry its own number and becomes a numbered tile. Same object, one dimension
   different. */
.docs-content .ctr-list-num {
  /* --ctr-zero is the number BEFORE the first row: set it to 4 for a list that
     continues at 5. */
  counter-reset: ctr-step var(--ctr-zero, 0);
  --ctr-mark: 24px;
}
.docs-content .ctr-list-num > li { counter-increment: ctr-step; }
.docs-content .ctr-list-num > li::before {
  content: counter(ctr-step);
  /* (26px first line − 24px tile) / 2 = 1px. */
  top: 1px;
  width: auto;
  min-width: var(--ctr-mark);
  height: var(--ctr-mark);
  padding: 0 4px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink);
  /* 700 — the weight this system gives display numbers and badges. */
  font-weight: 700;
  font-size: 12px;
  line-height: 1;
  /* So 9 and 10 sit on the same left edge. */
  font-variant-numeric: tabular-nums;
}

/* ---- Nesting is containment -----------------------------------------------
   No rail, no tick, no corner. A nested item is INSIDE the item above it, so it
   sits lower: the tree's own weight rule, where a folder is full ink and its
   contents are the hairline. The tile keeps its edge and loses its shadow,
   because a thing inside a box does not stand proud of the desk. */
.docs-content .ctr-list .ctr-list {
  margin: 0.5rem 0 0;
  padding-left: 0;
}
.docs-content .ctr-list .ctr-list > li::before {
  border-color: var(--ink-subtle);
  box-shadow: none;
}

.docs-content .ctr-list strong { font-weight: 600; }

@media (max-width: 640px) {
  /* The gutter tightens; nothing stacks. A 28px marker column is the whole cost
     of this component, and at 320px giving four characters back to the measure
     is worth more than the four pixels of air. */
  .docs-content .ctr-list { --ctr-gap: 10px; }
  .docs-content .ctr-list-num { --ctr-mark: 22px; }
}

/* ── The file tree ───────────────────────────────────────────────────────────
 *
 * A project layout is a HIERARCHY, so it is a nested <ul> — not ASCII box
 * characters inside a <pre>. That is not pedantry: box-drawing art is one
 * opaque string to a screen reader, it cannot reflow on a phone, and the
 * indentation is spaces that break the moment a filename changes length.
 * Real nesting gives depth to assistive tech for free and lets CSS draw it.
 *
 * The Drift part is what the depth is drawn WITH. A folder is a filled label
 * bar and its contents are indented beneath it; a file is a quiet white card.
 * And — the point — a folder that feeds a pillar wears that pillar: Atomic's
 * bar in orange, Canvas's in green, the same icon files the sidebar includes.
 * The tree stops being a picture of some directories and starts teaching which
 * directory becomes which primitive.
 *
 *   <ul class="filetree">                    ← the outer plate
 *     <li><span class="ft-node is-dir">…</span>   ← its label bar
 *       <ul class="ft-kids">                 ← what is inside it
 *         <li class="ft-branch on-atomic">   ← a plate of its own
 *           <span class="ft-node is-dir">…</span>
 *           <ul class="ft-kids"> …
 *
 * Two rules hold it together. .ft-node is a SIBLING of the nested list, never
 * its parent — wrap the children inside the row and the row becomes as tall as
 * its whole subtree. And the pillar goes on the LI, not on the row: it is a
 * property of the directory, which is the box, not of the text naming it. */
.docs-content .filetree {
  margin: 1.75rem 0;
  padding: 0;
  list-style: none;
  font-size: 13px;
  /* How far inside its parent a box sits. The LEFT step is bigger than the
     other three on purpose: containment is read horizontally, and a box inset
     equally on all sides reads as padding rather than as depth. */
  --ft-pad: 9px;
  --ft-step: 22px;
}
.docs-content .filetree ul { list-style: none; margin: 0; padding: 0; }
.docs-content .filetree li { margin: 0; }

/* ---- Depth is CONTAINMENT, not lines ---------------------------------------
 * A directory is a box, and its children are inside it. That is the whole
 * mechanism: no rails, no ticks, no corners — nesting you can see because one
 * object is physically within another.
 *
 * Connector lines are a TERMINAL idiom. They exist because a text console can
 * only draw characters in a grid, so containment has to be implied with `├` and
 * `│`. Drift is not a console, and it can say the same thing with position and
 * fill. This is the argument the platform makes about itself — fewer, more
 * literal objects instead of a notation you have to decode. */
.docs-content .filetree .ft-kids {
  /* Left only, plus a little air under the label. There is no frame to clear on
     the other two sides, so padding there would be a margin pretending to be
     containment. */
  padding: var(--ft-pad) 0 0 var(--ft-step);
}

/* A FILE is a card too, just a quieter one: same object as the box above it,
   drawn in the hairline weight rather than the full ink edge. Without this a
   folder is a thing and its contents are loose text, which reads as the files
   sitting NEXT to the box rather than in it.
   Scoped to a leaf inside a contents area — the root row is the card's own
   label bar and must not become a card within itself. */
.docs-content .filetree .ft-kids > li:not(.ft-branch) > .ft-node {
  border: 2px solid var(--ink-subtle);
  background: var(--panel);
  margin: 5px 0;
}
.docs-content .filetree .ft-kids > li:not(.ft-branch):first-child > .ft-node { margin-top: 0; }
.docs-content .filetree .ft-kids > li:not(.ft-branch):last-child > .ft-node { margin-bottom: 0; }
/* A directory is its LABEL, and nothing else draws it.
 *
 * No frame around the children: a four-sided box around a subtree is a lot of
 * edge for one fact, and at three levels deep the page becomes borders with
 * text between them. The filled bar already says "this is a container" and the
 * indent already says what is inside it, so the frame was stating a third time
 * what two things had said.
 *
 * Folders need air around them; a run of plain files does not, and gets none —
 * which is what keeps a list of four filenames reading as one list. */
.docs-content .filetree .ft-branch { margin: 10px 0; }
.docs-content .filetree .ft-branch:first-child { margin-top: 0; }
.docs-content .filetree .ft-branch:last-child { margin-bottom: 0; }

/* The label bar names the box it opens, filled with that box's own colour. */
.docs-content .filetree .ft-branch > .ft-node,
.docs-content .filetree > li > .ft-node {
  background: var(--ft-hue, var(--ink));
  color: #fff;
}
.docs-content .filetree .ft-branch > .ft-node .ft-name,
.docs-content .filetree > li > .ft-node .ft-name { color: #fff; }
/* On ink the note takes the sidebar's own label grey; on a brand fill that
   blue-grey turns muddy, so a coloured bar dims with its own white instead. */
.docs-content .filetree > li > .ft-node .ft-note,
.docs-content .filetree .ft-branch > .ft-node .ft-note { color: #ffffffc4; }
.docs-content .filetree > li:not([class*="on-"]) > .ft-node .ft-note { color: #a8b4cc; }

.docs-content .filetree .ft-node {
  display: flex;
  align-items: center;
  gap: 9px;
  /* Wraps rather than overflowing: on a narrow column the note drops to its own
     line under the name instead of pushing the card sideways. */
  flex-wrap: wrap;
  padding: 6px 11px;
  /* Stated rather than inherited: the body's 1.75 makes every row a third
     taller than the text in it, and a tree is a list of short labels. */
  line-height: 1.4;
}
.docs-content .filetree .ft-name {
  font-family: var(--mono);
  color: var(--ink);
}
.docs-content .filetree .is-dir .ft-name { font-weight: 600; }
/* The note is prose about the row, so it is set in the body face, not the mono
   one, and pushed to the card's right edge — a single alignment for every note
   at every depth, which a per-level column could not give. */
.docs-content .filetree .ft-note {
  margin-left: auto;
  color: var(--muted);
  font-size: 12px;
}
/* A note may name a key or a flag. brand.css sizes the chip at an absolute
   14px, which is larger than the note carrying it — inherit instead, so the
   token sits inside the line rather than setting its height. */
.docs-content .filetree .ft-note code {
  font-size: inherit;
  padding: 0 3px;
}
.docs-content .filetree .ft-node svg {
  height: 15px;
  width: 15px;
  flex: none;
  fill: currentColor;
}

/* ---- The triad, as ONE property --------------------------------------------
 * A directory that becomes a primitive sets --ft-hue, and the box reads it for
 * its edge, its shadow and its label bar. Three declarations colour an entire
 * subtree instead of one rule per part, and adding a pillar later is one line.
 *
 * --ft-hue INHERITS on purpose: a box inside atomic/ stays orange unless it
 * names its own pillar, so a colour reads as territory rather than as a label
 * on a single row. Deed sets none — it takes no directory in a project, and a
 * fourth rule would imply a symmetry that does not exist. */
.docs-content .filetree .on-atomic   { --ft-hue: var(--brand-1); }
.docs-content .filetree .on-backbone { --ft-hue: var(--brand-2); }
.docs-content .filetree .on-canvas   { --ft-hue: var(--brand-3); }
/* On the outer element too, so a tree whose ROOT is a primitive — an element
   folder rather than a project containing one — colours its whole card. */
.docs-content .filetree.on-atomic   { --ft-hue: var(--brand-1); }
.docs-content .filetree.on-backbone { --ft-hue: var(--brand-2); }
.docs-content .filetree.on-canvas   { --ft-hue: var(--brand-3); }

@media (max-width: 560px) {
  /* The note has nowhere to be pushed to, so it stops being a right-hand column
     and becomes a second line. */
  .docs-content .filetree .ft-note { margin-left: 0; flex-basis: 100%; }
}

/* ── Badges ──────────────────────────────────────────────────────────────────
 *
 * ONE class, TWO jobs, and they want different objects.
 *
 * In a sentence the badge names a primitive while a reader is mid-line, and the
 * hard constraint is the line box: brand.css runs body at 16px/1.625, so a line
 * box is 26px, and anything that reaches the leading makes a paragraph carrying
 * four badges set on a different rhythm from one carrying none. At the top of a
 * Build page the badge IS the heading, carries the primitive's icon, and has no
 * line box to protect.
 *
 * So the treatments split on context rather than on a second class in the
 * markup: `.badge` in prose is a KEY, `.badge` inside an h2 is a MARK. The
 * colour modifiers already in the markup drive both.
 *
 * ---- In prose: the key ------------------------------------------------------
 * A moulded cap set into the line. 12px of text in a 16px content box inside a
 * 2px edge is 20px tall, and `vertical-align: middle` seats its centre half an
 * x-height above the baseline — 15.8px up, 4.2px down, inside a 26px line box
 * that it therefore cannot reach. */
.docs-content .badge {
  display: inline-flex;
  align-items: center;
  height: 20px;
  vertical-align: middle;
  padding: 0 8px;
  margin-right: 4px;
  background: var(--ink);
  color: #fff;
  border: 2px solid var(--ink);
  border-radius: 0;
  font-size: 12px;
  line-height: 1;
  font-weight: 700;
  letter-spacing: 0.01em;
  /* One object. A key broken across two lines is two half keys. */
  white-space: nowrap;
}

.docs-content .badge-orange { background: var(--brand-1); border-color: var(--brand-1); }
.docs-content .badge-purple { background: var(--brand-2); border-color: var(--brand-2); }
.docs-content .badge-green  { background: var(--brand-3); border-color: var(--brand-3); }
.docs-content .badge-ink    { background: var(--ink);     border-color: var(--ink); }

/* INK on orange and green, white on purple and ink. This is arithmetic, not
   taste: white measures 2.2:1 on --brand-1 and 2.6:1 on --brand-3, and this is
   12px at weight 700 — a label owes its reader 4.5:1. Ink reads 6.8:1 and 5.7:1
   on those two fills. It diverges from .btn, which is white platform-wide at a
   larger size; the divergence is the point, because the button is 14px and this
   is not. */
.docs-content .badge-orange,
.docs-content .badge-green { color: var(--ink); }

/* ---- At the top of a Build page: the mark ----------------------------------
 * The square mark at heading size. favicon.svg is an ink field with the triad
 * along its bottom edge and a white glyph; this is that object holding a word.
 *
 * The fill is INK for the same arithmetic as above, one size up: white cannot
 * carry three of the four pillars. So the hue LEAVES the text's ground and
 * becomes an edge — a mark rather than a highlight — and the badge states which
 * of the three by POSITION as well as by colour, so it never leans on hue
 * alone. Deed lights none: it is a peer of the triad, not a fourth member, the
 * same call the file tree makes. */
.docs-content h2 .badge {
  display: inline-flex;
  align-items: center;
  height: auto;
  /* em, so the gap tracks the badge's own size rather than being re-tuned if
     the heading scale ever moves. */
  gap: 0.5em;
  font-size: 0.8em;
  font-weight: 600;
  line-height: 1.15;
  padding: 6px 16px;
  margin-right: 8px;
  vertical-align: middle;
  position: relative;
  background: var(--ink);
  color: #fff;
  border: none;
  /* The unlit edge: the accent bar with none of it lit. */
  border-bottom: 3px solid var(--muted);
}
.docs-content h2 .badge-orange { --mark-seat: 0; --mark-hue: var(--brand-1); }
.docs-content h2 .badge-purple { --mark-seat: 1; --mark-hue: var(--brand-2); }
.docs-content h2 .badge-green  { --mark-seat: 2; --mark-hue: var(--brand-3); }
/* The lit third, positioned against the badge's padding box so it costs no
   layout — the box is identical with it and without it. */
.docs-content h2 .badge-orange::after,
.docs-content h2 .badge-purple::after,
.docs-content h2 .badge-green::after {
  content: "";
  position: absolute;
  left: calc(var(--mark-seat) * 33.3333%);
  bottom: -3px;
  width: 33.3334%;
  height: 3px;
  background: var(--mark-hue);
}
/* The same file the sidebar includes, drawn in currentColor, so one icon serves
   an ink sidebar row and this ink title block without naming a colour. */
.docs-content h2 .badge svg {
  height: 1em;
  width: 1em;
  flex: none;
  fill: currentColor;
}

@media (max-width: 640px) {
  /* A page title is the widest unbreakable run on a narrow screen and the only
     badge carrying a glyph. One step down keeps it clear of the gutter. The key
     does NOT shrink: 12px is the floor at which a 700-weight word still reads. */
  .docs-content h2 .badge { font-size: 0.68em; padding: 5px 12px; }
}

/* ── Callouts: the notice bar ────────────────────────────────────────────────
 *
 * An aside is a CLAIM plus the reason for it. The bar carries the claim and the
 * reason is its contents, indented beneath it — the list's anatomy spent on
 * prose, and the tree's argument that depth is containment rather than a frame.
 * A coloured left border is what every documentation site on earth draws here;
 * this is the same information with an object instead of a stripe.
 *
 * docs.js builds the structure, because the claim and the reason arrive as a
 * <strong> and the text after it inside one box, and no selector can move a
 * text node into a card. Where a callout has no <strong> lead there is no claim
 * to put on a bar, and it renders as the card alone — a deliberate second
 * state, not a broken first one.
 *
 * The bar is a <p>, NEVER a heading: buildToc() reads every h3 and h4 inside
 * .docs-content, and a claim marked up as a heading would put 92 asides into 35
 * page outlines. */
.docs-content .callout {
  /* The kind, as ONE inherited property — the tree's --ft-hue move. Panel is
     "no flavour": the key is still a key, it just names nothing. */
  --co-hue: var(--panel);
  --co-step: 22px;
  /* A code block's gap, not a paragraph's. An aside is a set piece the eye
     stops at; at a paragraph's spacing it reads as another line of prose. */
  margin: 1.75rem 0;
  font-size: 0.94rem;
  /* The old box is gone: the bar and the indent are the container now. */
  background: none;
  border: none;
  padding: 0;
}
/* The kind of aside, in the status three rather than the triad — an aside says
   what a thing IS, never which primitive it belongs to, and reusing a pillar's
   colour here would make Backbone's purple mean "note" on half the pages.
   `tip` keeps Canvas green because it is the palette's "done" and a tip is a
   thing that works; it is the one flavour that is genuinely good news. */
.docs-content .callout-info  { --co-hue: var(--info); }
.docs-content .callout-warn  { --co-hue: var(--warning); }
.docs-content .callout-error { --co-hue: var(--error); }
.docs-content .callout-tip   { --co-hue: var(--brand-3); }

.docs-content .callout .co-claim {
  display: flex;
  align-items: stretch;
  margin: 0;
  background: var(--ink);
  color: #fff;
  font-weight: 600;
  line-height: 1.45;
}
/* The hue rides a flush square on the bar's end rather than filling the bar. A
   sentence set on --brand-1 is 2.2:1 against white; the same sentence on ink is
   13:1. So the fill goes to a 34px key with an ink glyph — 6.8:1 on orange,
   5.8:1 on green — and the words stay on ink where they can be read. */
.docs-content .callout .co-chip {
  flex: none;
  width: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--co-hue);
  border-right: 2px solid var(--ink);
  /* INK, not white. Every one of the status three carries ink better than white
     at this size — red is the closest at 3.0 against white's 4.8, and warning
     is not close at all: 9.3 against 1.6. One rule for all four flavours beats
     a per-colour exception nobody will remember to add. */
  color: var(--ink);
}
.docs-content .callout .co-chip svg {
  width: 17px;
  height: 17px;
  fill: currentColor;
}
.docs-content .callout .co-text { min-width: 0; padding: 8px 14px; }

/* The contents of the box: indented, unframed, joined to the bar by position
   alone. A four-sided box around the reason is a lot of edge for one aside, and
   a connector line is a terminal idiom. */
.docs-content .callout .co-body { padding: 8px 0 0 var(--co-step); }
.docs-content .callout .co-card {
  background: var(--panel);
  /* Hairline, not full ink: there are 92 of these across 35 pages, and at a
     full ink edge the docs become a grid of boxes. The list makes the same call
     for the same reason. */
  border: 2px solid var(--ink-subtle);
  padding: 11px 15px;
  font-weight: 300;
  line-height: 1.6;
}
.docs-content .callout .co-card > :last-child { margin-bottom: 0; }
/* No claim, so no bar: the card carries the whole aside and keeps the indent,
   which is what stops it reading as a paragraph that grew a border. */
.docs-content .callout.co-bare .co-body { padding-left: 0; }

@media (max-width: 640px) {
  /* The indent halves rather than disappearing: containment is read
     horizontally, and at 0 the card stops being inside anything. */
  .docs-content .callout { --co-step: 10px; }
  .docs-content .callout .co-chip { width: 28px; }
  .docs-content .callout .co-text { padding: 7px 11px; }
  .docs-content .callout .co-card { padding: 9px 12px; }
}

/* ── Reference tables ────────────────────────────────────────────────────────
 *
 * Two shapes, two objects, and docs.js tells them apart by counting the columns
 * in the first row: 74 of the 99 tables are a two-column MAPPING, and 25 are a
 * matrix you compare across. A mapping and a matrix are read differently, so
 * they stopped sharing a treatment.
 *
 * ---- Two columns: the plaque -----------------------------------------------
 * The label bar turns the corner. The header's ink runs on down the key column
 * as a spine, so the table is one object: an ink Γ with the meanings held in
 * the white field it encloses, and the keys cut into the ink in white. Ink fill
 * is how this brand marks the object that does the work — the search bar's
 * mark, the list's title bar, the dark button — and the key column is the
 * handle a reader looks things up by. */
.docs-content .rt-scroll {
  /* The scroll lives on a wrapper, so the table keeps `display: table` and its
     role at every width. Focusable, because a scroll container a mouse can
     reach and a keyboard cannot is a control only half the readers have. */
  overflow-x: auto;
  margin: 1.75rem 0;
}
.docs-content .rt-scroll:focus-visible { outline: 2px solid var(--brand-2); outline-offset: 2px; }

.docs-content .reference-table {
  width: 100%;
  border-collapse: collapse;
  border: 2px solid var(--ink);
  background: var(--panel);
  margin: 0;
  font-size: 0.9em;
}
/* The top of the Γ. Its bottom edge is ink: invisible where the spine continues
   under it, and the bar's own edge where the white field begins. */
.docs-content .reference-table th {
  background: var(--ink);
  color: #fff;
  font-weight: 600;
  text-align: left;
  padding: 8px 14px;
  border-bottom: 2px solid var(--ink);
}
.docs-content .reference-table td {
  padding: 8px 14px;
  vertical-align: top;
  border-bottom: 2px solid var(--bg);
  line-height: 1.55;
}
/* The spine. A STATED share of the measure, and it WRAPS.
   Shrink-to-fit — `width: 1%` with `white-space: nowrap` — sizes the ink to the
   widest key, which is the better drawing when every key is a flag or a token.
   It is the wrong one here: a third of these tables carry keys that are whole
   clauses, the longest running 62 characters, and a clause that cannot wrap
   pushes the table past the 760px measure and hands the reader a sideways
   scroll. Worse, it made two tables on the same page look like two different
   components — one scrolling, one not — when only their contents differed.
   A stated share is the same drawing at every length. 32% of the measure is
   about thirty characters, which holds a key without starving the meaning
   beside it.
   Every table still in the page at this point is a two-column one: docs.js has
   already replaced the three- and four-column tables with the rack, so nothing
   here needs to exclude them. */
.docs-content .reference-table td:first-child {
  width: 32%;
  white-space: normal;
  overflow-wrap: break-word;
  background: var(--ink);
  color: #fff;
  border-right: 2px solid var(--ink);
  /* --bg is a light line and vanishes on ink. --muted is the palette's answer
     for a quiet edge drawn ON a dark fill — the copy button's own border. */
  border-bottom-color: var(--muted);
}
.docs-content .reference-table tr:last-child td { border-bottom: none; }
/* On the spine the token IS the fill: the desk-coloured chip would be a grey
   box floating on the ink, and its ink text unreadable there. */
.docs-content .reference-table td:first-child code {
  background: none;
  border: none;
  padding: 0;
  font-size: 13px;
  color: inherit;
  /* pre-WRAP, not pre: the spine wraps now, and `pre` would exempt exactly the
     cells most likely to be long from the thing that stops the table
     overflowing. It still never breaks mid-token — there is no space inside an
     identifier to break at — so a token stays whole and a key made of several
     wraps between them. */
  white-space: pre-wrap;
}
/* In the white field a token keeps its chip and never wraps — a token broken
   across lines is not a smaller token, it is a wrong one. */
.docs-content .reference-table td + td code { white-space: nowrap; overflow-wrap: normal; }

@media (max-width: 640px) {
  /* Nothing restructures: the plaque is one object and stays one. It no longer
     carries a 460px floor either — that existed to protect the meaning column
     from collapsing while the un-wrapping spine ate the width, and with a spine
     that wraps it only forces a phone to scroll a table that would have fit. */
  .docs-content .reference-table td:first-child { width: 34%; }
}

/* ---- Three and four columns: the rack --------------------------------------
 *
 * THE FILE TREE'S FOLDER, applied to a table row. The key becomes a filled label
 * bar; the row's other columns are its CONTENTS, indented beneath it as quiet
 * cards. One ink legend names those columns once, at the top, so nothing
 * repeats.
 *
 * For catalogue tables — Unit | Per month | Why · Keyword | Values | Meaning —
 * where the key names a THING and the row describes it. A <ul> of <dl>s rather
 * than a <table>: each item is one thing with named properties, not a grid of
 * independent facts. docs.js builds that structure from the table in the page,
 * so the markup an author writes is unchanged.
 *
 * This stylesheet is the variant's own, unmodified except for --rk-cols, which
 * the original hardcoded to 2 because its specimen had two value columns. */
.docs-content .tbl-rack {
  --rk-step: 22px; /* the tree's indent — containment is read horizontally */
  --rk-gap: 8px;
  --rk-cols: 2;
  margin: 1.75rem 0;
}

/* ONE template, used by the legend AND the rows below it, so a label can never
   come to sit over a column it does not name. The indent is padding rather than
   a track, so the legend's columns are the exact width of the rows' columns;
   background on the container means the ink runs unbroken behind the gap.
   14px of padding = the 2px card edge + the 12px card padding beneath it, so
   each label sits on its own column's first letter. */
.docs-content .tbl-rack .rk-head {
  display: grid;
  grid-template-columns: repeat(var(--rk-cols), minmax(0, 1fr));
  column-gap: var(--rk-gap);
  padding-left: var(--rk-step);
  background: var(--ink);
  color: #fff;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.docs-content .tbl-rack .rk-head span { padding: 7px 14px; }

.docs-content .tbl-rack .rk-list {
  list-style: none;
  margin: 0;
  padding: 8px 0 0;
  max-width: none;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.docs-content .tbl-rack .rk-item { margin: 0; }

/* The label bar names the box it opens, filled with that box's own colour.
   No frame around the contents: a four-sided box would be a lot of edge for
   one fact. */
.docs-content .tbl-rack .rk-bar {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
  padding: 6px 11px;
  background: var(--rk-hue, var(--ink));
  color: #fff;
  line-height: 1.4;
}
.docs-content .tbl-rack .rk-bar svg { width: 15px; height: 15px; flex: none; fill: currentColor; }
.docs-content .tbl-rack .rk-name { font-weight: 600; }
/* A key that is an identifier rather than a product name wears <code>; the chip
   chrome comes off, the same as inside the command key. */
.docs-content .tbl-rack .rk-name code {
  background: none;
  border: none;
  padding: 0;
  color: inherit;
  font-family: var(--mono);
  font-size: 13px;
  white-space: nowrap;
}
.docs-content .tbl-rack .rk-note { margin-left: auto; font-size: 12px; color: #ffffffc4; }

/* The triad, as ONE property, and it INHERITS — the file tree's own rule.
   Deed sets none: the fallback IS ink, and a fourth rule would imply a symmetry
   that does not exist. */
.docs-content .tbl-rack .on-atomic   { --rk-hue: var(--brand-1); }
.docs-content .tbl-rack .on-backbone { --rk-hue: var(--brand-2); }
.docs-content .tbl-rack .on-canvas   { --rk-hue: var(--brand-3); }

.docs-content .tbl-rack .rk-fields {
  display: grid;
  grid-template-columns: repeat(var(--rk-cols), minmax(0, 1fr));
  column-gap: var(--rk-gap);
  margin: 6px 0 0 var(--rk-step);
}
/* Drawn once by the legend above, kept here for a screen reader — so each cell
   is announced with its column's name. Clipped rather than display:none, which
   would take it out of the accessibility tree along with the picture. */
.docs-content .tbl-rack .rk-fields dt {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
/* Contents, in the hairline weight, so they read as being IN the box rather
   than beside it. */
.docs-content .tbl-rack .rk-fields dd {
  margin: 0;
  min-width: 0;
  padding: 9px 12px;
  background: var(--panel);
  border: 2px solid var(--ink-subtle);
  font-size: 0.94rem;
  line-height: 1.5;
}
.docs-content .tbl-rack .rk-fields code { white-space: nowrap; }

@media (max-width: 640px) {
  /* The legend goes with the columns it labelled: stacked, its two words would
     sit above a list they no longer head. The names come back onto the cells
     themselves — the same <dt>s, unhidden, as section labels. */
  .docs-content .tbl-rack .rk-head { display: none; }
  .docs-content .tbl-rack .rk-fields { grid-template-columns: minmax(0, 1fr); }
  .docs-content .tbl-rack .rk-fields dt {
    position: static;
    width: auto;
    height: auto;
    margin: 8px 0 3px;
    overflow: visible;
    clip-path: none;
    white-space: normal;
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
  }
  .docs-content .tbl-rack .rk-fields dt:first-of-type { margin-top: 4px; }
}


/* ── Ordinary lists: the nameplate ───────────────────────────────────────────
 *
 * Every term-led list in these docs is written `<strong>Term</strong> — text`.
 * The dash is there because a term and its meaning are different KINDS of text
 * and there was nothing else to say so. A fill and a hard edge say it instead,
 * and the gap of desk between the plate and the prose IS the dash.
 *
 * NO CARD: the item's body sits on the bare ground, which is what keeps a
 * four-item aside from becoming four boxes. The markup is unchanged — the plate
 * is the page's own <strong>, styled, not a second element carrying the same
 * words.
 *
 * COPY RULE, not a CSS one: the term holds about 18 characters at this width.
 * Nothing truncates, so a longer term wraps its plate. Terms are one to three
 * words. */
.docs-content ul:not([class]),
.docs-content ol:not([class]) {
  list-style: none;
  margin: 0 0 1.25rem;
  padding: 0;
  /* The gutter, as its two parts: the plate, then the desk showing between it
     and the prose. */
  --np-col: 148px;
  --np-gap: 12px;
}
.docs-content ul:not([class]) > li,
.docs-content ol:not([class]) > li {
  position: relative;
  margin: 0 0 0.85rem;
  /* Ink by default. The triad is opt-in, per item, as ONE property. */
  --np-hue: var(--ink);
}
.docs-content ul:not([class]) > li:last-child,
.docs-content ol:not([class]) > li:last-child { margin-bottom: 0; }
/* Only an item that HAS a plate reserves the gutter for one. A plate is ~1.9rem
   tall and out of flow, so a one-line item shorter than the object beside it
   would let the next plate start under this one. */
.docs-content ul:not([class]) > li:has(> strong:first-child),
.docs-content ol:not([class]) > li:has(> strong:first-child) {
  padding-left: calc(var(--np-col) + var(--np-gap));
  min-height: 1.9rem;
}
.docs-content ul:not([class]) > li.on-atomic   { --np-hue: var(--brand-1); }
.docs-content ul:not([class]) > li.on-backbone { --np-hue: var(--brand-2); }
.docs-content ul:not([class]) > li.on-canvas   { --np-hue: var(--brand-3); }

/* THE PLATE. Absolutely positioned rather than floated: the prose keeps a clean
   hanging column at every line, instead of the first two lines being notched
   around the plate and the rest starting under it. */
.docs-content ul:not([class]) > li > strong:first-child,
.docs-content ol:not([class]) > li > strong:first-child {
  position: absolute;
  left: 0;
  /* 3px, so the plate's cap height lands on the first line's rather than its
     box on the line box. */
  top: 3px;
  box-sizing: border-box;
  width: var(--np-col);
  padding: 3px 10px;
  background: var(--np-hue);
  color: #fff;
  font-weight: 600;
  font-size: 0.86rem;
  line-height: 1.45;
  overflow-wrap: anywhere;
}
/* A term can BE a token. Inline code is a chip everywhere else; on the plate
   that would be a grey box inside a black one, so it is cleared exactly as it
   is inside the command key. */
.docs-content ul:not([class]) > li > strong:first-child code,
.docs-content ol:not([class]) > li > strong:first-child code {
  background: none;
  border: none;
  padding: 0;
  color: inherit;
  font-size: 0.94em;
}

/* Inside an aside the measure is already indented once and the card pads it
   again, so a 148px plate column would leave the prose beside it too narrow to
   read. The gutter comes down with the measure. */
.docs-content .callout .co-card ul:not([class]),
.docs-content .callout .co-card ol:not([class]) { --np-col: 110px; }

@media (max-width: 640px) {
  /* 148px of plate against a 320px screen leaves no measure, so the plate comes
     back into the flow and sits ON its item rather than beside it — the same
     naming, read top to bottom. */
  .docs-content ul:not([class]) > li:has(> strong:first-child),
  .docs-content ol:not([class]) > li:has(> strong:first-child) {
    padding-left: 0;
    min-height: 0;
  }
  .docs-content ul:not([class]) > li > strong:first-child,
  .docs-content ol:not([class]) > li > strong:first-child {
    position: static;
    display: inline-block;
    width: auto;
    margin-bottom: 4px;
  }
}

/* ── Code blocks: the plaque ─────────────────────────────────────────────────
 *
 * The dark fill is the one place the desk is cut through, so it is the one
 * object on the page that cannot be labelled from the inside. The label goes on
 * a bar ON TOP of it, in the file tree's shape: a filled bar names the box and
 * its contents sit beneath it. Fourth use of that bar, after the folder, the
 * list title and the swap head.
 *
 * A <figure> with a real <figcaption>, because the caption names the figure —
 * which also puts the filename into a screen reader's announcement of the block
 * instead of leaving it in the sentence above. docs.js builds it; a block with
 * no data-name gets a bar carrying only its copy control, which is still a
 * drawer front. */
.docs-content .cb-plaque {
  /* The tree's --ft-hue, under this component's name. Unset means ink. */
  --cb-hue: var(--ink);
  margin: 1.75rem 0;
}
/* The FILE TREE'S OWN CLASSES, compounded rather than copied, so a block of
   atomic/sign.go and the atomic/ folder above it are the same orange for the
   same reason. */
.docs-content .cb-plaque.on-atomic   { --cb-hue: var(--brand-1); }
.docs-content .cb-plaque.on-backbone { --cb-hue: var(--brand-2); }
.docs-content .cb-plaque.on-canvas   { --cb-hue: var(--brand-3); }

/* The bar sits OUTSIDE the scroller on purpose: a block wider than the measure
   scrolls under a label that stays put. */
.docs-content .cb-bar {
  display: flex;
  align-items: center;
  gap: 9px;
  /* Less on the right than the left: that end holds a bordered control, and its
     own 2px edge is part of the gap the eye reads. */
  padding: 6px 8px 6px 12px;
  background: var(--cb-hue);
  border: 2px solid var(--ink);
  color: #fff;
  line-height: 1.4;
}
.docs-content .cb-bar svg { width: 15px; height: 15px; flex: none; fill: currentColor; }
/* Mono, because it is a path. The tree's .ft-name, unchanged. */
.docs-content .cb-name {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 600;
  min-width: 0;
  overflow-wrap: anywhere;
}
/* The tree's .ft-note on a filled bar. Nothing truncates: a route hidden behind
   an ellipsis is a route the reader has to go and look up. */
.docs-content .cb-note {
  margin-left: auto;
  font-size: 12px;
  color: #ffffffc4;
  white-space: nowrap;
}
/* brand.css's .copy-btn, at rest in the bar rather than absolutely positioned
   over the code. Ink fill with a --muted edge is the chrome the brand wrote for
   dark grounds, and the bar is one. Static: a raised white key on an ink bar
   would need a white shadow, which merges into the key and spends the
   affordance. */
.docs-content .cb-copy {
  flex: none;
  margin-left: auto;
  font-family: inherit;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: var(--ink);
  color: #fff;
  border: 2px solid var(--muted);
  border-radius: 0;
  padding: 3px 9px;
  cursor: pointer;
}
/* When a note is present it takes the free space and the button follows it. */
.docs-content .cb-note + .cb-copy { margin-left: 0; }
.docs-content .cb-copy:hover { background: var(--brand-2); border-color: var(--brand-2); }
.docs-content .cb-copy:focus-visible { outline: 2px solid var(--brand-2); outline-offset: 2px; }
.docs-content .cb-copy.done { background: var(--brand-3); border-color: var(--brand-3); }

/* The bar owns the top edge, so the body does not draw a second one. */
.docs-content .cb-body {
  background: #1e1e1e;
  border: 2px solid var(--ink);
  border-top: none;
}
.docs-content .cb-body pre {
  margin: 0;
  padding: 14px 20px;
  overflow-x: auto;
  color: #dadada;
  font-size: 13px;
  line-height: 1.4;
  border: none;
  background: none;
  /* A hard scrollbar in the palette. The usual answer to a block wider than its
     column is a fade at the right edge, and a fade is a gradient — so the
     overflow is STATED instead: a square ink-and-muted bar the reader can see
     and grab, rather than a soft edge implying one. */
  scrollbar-width: thin;
  scrollbar-color: var(--muted) #1e1e1e;
}
.docs-content .cb-body pre::-webkit-scrollbar { height: 10px; }
.docs-content .cb-body pre::-webkit-scrollbar-track {
  background: #1e1e1e;
  border-top: 2px solid var(--muted);
}
.docs-content .cb-body pre::-webkit-scrollbar-thumb { background: var(--muted); }

@media (max-width: 640px) {
  /* The bar wraps rather than truncating: name and control on the first line,
     the note under them. A filename reassembled from an ellipsis is worse than
     one on two lines. The code stays at 13px — the measure is what shrinks, not
     the type, because a block set smaller than the CLI it quotes stops being a
     picture of it. */
  .docs-content .cb-bar { flex-wrap: wrap; padding: 6px 8px 6px 10px; }
  .docs-content .cb-name { flex: 1 1 auto; }
  .docs-content .cb-note { order: 1; flex: 1 0 100%; margin-left: 0; white-space: normal; }
  .docs-content .cb-copy { margin-left: auto; }
  .docs-content .cb-body pre { padding: 12px 14px; }
}

} /* @layer page */
