/* DO NOT EDIT — generated by tools/render-html.py@0.5.0
 *
 * Structure only: layout, flow and overflow. No palette, no type scale, no
 * motifs. Those are S4's `identity.css` and `marks.css`, which are AUTHORED and
 * which this file must never contain, because a generated stylesheet carrying a
 * look would be overwritten on the next build.
 */
:root { color-scheme: light dark; }
* { box-sizing: border-box; }
body {
  margin: 0;
  font-family: var(--ds-font-body, system-ui, sans-serif);
  line-height: var(--ds-line-body, 1.55);
  color: var(--content-default, CanvasText);
  background: var(--ds-ground, Canvas);
}
/* ⚠️ `min(…, 100%)`, AND `min-width: 0` ALONE WAS NOT ENOUGH -- measured, after
 * the contact sheets made a latent shell bug visible on 69 pages.
 *
 * `margin: 0 auto` on a grid item suppresses the stretch, so `main` is sized as
 * fit-content, and fit-content is `min(max-content, max(min-content, available))`
 * -- the `max()` means a child with a large MIN-content contribution wins outright,
 * and no `min-width` on the item changes that. An 834px Figma sheet in a 510px
 * window therefore made `main` 876px and scrolled the whole page sideways, tables,
 * prose and nav included. `max-width: min(70rem, 100%)` caps the fit-content
 * result against the track and keeps the centring.
 *
 * The `min-width: 0` below stays; it is a different guard and still needed. Its
 * old comment claimed it covered wide tables, and that was true only by accident:
 * a table lives in `.scroll`, whose `overflow-x: auto` makes its min-content
 * contribution zero, so the bug could never fire there. The first element on this
 * site with a big min-content and no scroll container found it immediately. */
main {
  max-width: min(var(--ds-measure, 70rem), 100%);
  margin: 0 auto;
  min-width: 0;               /* removes the grid item's automatic minimum size */
  padding: var(--ds-space-page, 2rem 1.25rem 6rem);
}
main:focus { outline: none; } /* focused only by the skip link, never by a click */
/* Margins only. Leading is part of a type step and every heading takes it
 * from its [data-role] rule in identity.css; 1.2 here was a fifth value
 * competing with the four the scale names. */
h1, h2, h3 { margin: 2em 0 0.6em; }
h1 { margin-top: 0; }
p, ul, ol { margin: 0 0 1em; }
li { margin: 0 0 0.35em; }
code { font-family: var(--ds-font-mono, ui-monospace, monospace); font-size: 0.92em; }
pre { overflow-x: auto; padding: 1em; }
blockquote { margin: 1.5em 0; padding-left: 1em; border-left: 3px solid currentColor; }
hr { border: 0; border-top: 1px solid currentColor; opacity: 0.25; margin: 2.5em 0; }

/* Wide content scrolls in its own box. The body must never scroll sideways:
 * the token tables are five columns wide and one of them is a resolution chain. */
.scroll { overflow-x: auto; margin: 0 0 1.5em; }

/* An authored picture. Containment only -- the look is identity.css.
 *
 * ⚠️ THIS ONE SMUSHES, AND `.lp-frame img` DELIBERATELY DOES NOT. The two are
 * the opposite decision on purpose. A Figma contact sheet is a fixed grid of 66
 * variants that is legible to nobody at 380px, so it keeps its natural size and
 * its frame scrolls. An authored picture is placed BY A PERSON next to the
 * sentence it illustrates, at whatever size suits it -- the Map legend's
 * swatches are 116-198px wide -- and the cap only ever engages on a picture
 * wider than the reader's column, where fitting it is better than handing them a
 * second scrollbar inside a paragraph. `learnings/auto-margins-defeat-min-width-
 * on-a-grid-item.md` tested `img { max-width: 100% }` as the control for the
 * sideways-scroll bisect and it worked; `main { max-width: min(70rem, 100%) }`
 * won on other grounds and both are in force.
 *
 * `height: auto` is not optional beside a capped width: the tag carries explicit
 * `width` and `height` so the lazy image reserves its box, and without this a
 * capped picture keeps its declared height and stretches.
 *
 * The scrolling-frame variant for full-page product screenshots is NOT built --
 * plans/screenshots-on-the-docs-site.md parks it until a picture needs it, and
 * inventing the authoring syntax before then would be a surface with no
 * consumer. */
img.shot { display: block; max-width: 100%; height: auto; margin: 1.5em 0; }
/* In a cell the picture IS the cell's content, so the prose margin would be
 * padding measured twice. The legend on /patterns/map.md is the case: ten rows
 * whose first column is one swatch each. */
td img.shot, th img.shot { margin: 0; }

/* An authored card. Containment only -- the look is identity.css.
 *
 * A card list is a RUN of adjacent `.card` divs with no wrapper, so the gap
 * between two cards is the bottom margin of the first. `margin-bottom` is
 * therefore the whole layout: 0.75em between siblings is tighter than the 1.5em
 * that separates a card from the prose or heading around it, which is what makes
 * a run read as one list instead of four unrelated boxes.
 *
 * ⚠️ NO GRID AND NO COLUMNS, and this is the non-goal the plan states outright.
 * Joseph, 2026-09-14, on side-by-side cards: *"that's madness."* A card is a
 * full-measure item in one column. Jieun's prototype already honours it -- its
 * `.grid` is a column-direction flex despite the `two` and `three` class names --
 * so a block-level div in normal flow IS the design, and there is nothing here
 * for a narrow pane to stack because nothing was ever placed beside anything.
 * That is why check 9 costs `check-narrow-viewport.py` nothing new.
 *
 * The first and last child margins collapse into the padding rather than adding
 * to it, which is the same reason `td img.shot` above zeroes its margin. */
.card { margin: 1.5em 0; }
.card + .card { margin-top: 0.75em; }
.card > :first-child { margin-top: 0; }
.card > :last-child { margin-bottom: 0; }

/* live-preview's two figures. Containment only -- the look is blocks.css.
 *
 * ⚠️ BOTH BOUNDS ARE IN `dvh`, AND THAT IS THE REQUIREMENT, not a preference.
 * human-site-structure.md designs against a ~490px-wide, sometimes ~450px-TALL
 * side pane; a figure bounded in pixels takes the whole window there. `dvh` also
 * beats `vh` on mobile Safari, where `vh` is the LARGEST viewport height and puts
 * the caption permanently under the browser chrome.
 *
 * ⚠️ `max-width: none` on the sheet is deliberate and is the opposite of the usual
 * rule. A Figma contact sheet is a fixed grid -- Badge is 66 variants across 834px
 * -- so shrinking it to fit a 380px pane produces a legible-to-nobody thumbnail.
 * It keeps its natural size and the frame scrolls, exactly as `.scroll` handles a
 * five-column table. The two cases are the same case. */
[data-preview] { margin: 1.5em 0; }
.lp-frame { overflow: auto; max-height: 60dvh; }
.lp-frame img { display: block; max-width: none; height: auto; }
/* ⚠️ THE STORY FRAME'S DEFAULT IS IN `rem` AND ITS CEILING IS IN `dvh`, which
 * reads like a violation of the dvh rule and is the rule's actual point. The
 * requirement is that a figure must never take the whole window; sizing the
 * DEFAULT in dvh does not achieve that, it only guarantees the figure is always
 * a fixed fraction of whatever window it is in. Measured 2026-09-10: at 40dvh
 * the `ui-badge--default` frame is 560px of white around a 20px badge, because
 * most of these constructs are small — badge, checkbox, radio, toggle. So the
 * default is a size that suits the content, `max-height` in dvh is the promise
 * that it cannot swallow a short viewport, and `resize` hands the reader the
 * rest. A big component is one drag away; 560px of white was on every page. */
[data-preview="storybook"] iframe {
  display: block; width: 100%; height: 13rem;
  max-height: 70dvh; border: 0; resize: vertical;
}
/* Terminal above, browser below: the short case, which is as common as
 * side-by-side and is the one a single min-width query never reaches. */
@media (max-height: 34rem) {
  .lp-frame { max-height: 46dvh; }
  [data-preview="storybook"] iframe { height: 10rem; max-height: 55dvh; }
}
/* No font-size: identity.css sets the table to Body, and 0.94em here was
 * a second opinion that only lost on load order. */
table { border-collapse: collapse; width: 100%; }
th, td { text-align: left; padding: 0.45em 0.7em; vertical-align: top;
         border-bottom: 1px solid currentColor; }
th { white-space: nowrap; }
thead th { border-bottom-width: 2px; }

/* Blocks are addressable, and deliberately unstyled. `[data-block]` is the whole
 * interface S4 and S5 key off -- 15 names, fixed, checked. */
[data-block] { display: block; }
[data-block] + [data-block] { margin-top: 1.5em; }
/* value-specimen. LAYOUT ONLY -- every colour a specimen draws comes from the
 * token's own resolved value, inline, because that value IS the data. The
 * chrome around it (borders, labels, the alpha checkerboard) is identity's. */
/* IN THE CELL is the default, and the list below is the exception. A chip that
 * draws at a fixed size belongs beside the number it depicts -- the two were a
 * grid of chips above a table of values until 2026-09-11, which is the same
 * rows twice and made the reader do the join by eye.
 * The chip is SMALLER here than in the list (1.1rem against 1.6rem) because it
 * shares a line with body text rather than owning a row, and `flex: none` is
 * what stops a wide cell stretching it. */
/* ⚠️ INLINE, not flex. A cell's value can be a 94-character shadow, and an
 * inline-flex wrapper makes the text one flex item that will not break where
 * the reader's pane needs it -- which is how a chip 17px wide pushes a table
 * past a 490px viewport. An inline-block chip followed by a text node wraps
 * exactly as the text did before the chip was there. */
.sp-cell .sp { display: inline-block; width: 1.1rem; height: 1.1rem;
               vertical-align: -0.2em; margin-right: 0.45em; }

/* ONE ROW PER TOKEN, and one line of text on it. This was a multi-column grid
 * of two-line cells, and it failed twice at once (Joseph, 2026-09-10):
 *
 *   - Nothing lined up. Name over value, four columns across, so neither the
 *     names nor the values shared an edge and the eye had to zigzag 192 times
 *     to compare two hexes.
 *   - Big type STEPPED ON ITS NEIGHBOURS. The font-size page draws each sample
 *     at its own value, and two of them are `8rem` and `6rem` -- 128px and 96px
 *     of glyph inside a 13rem cell, overflowing into the labels beside them.
 *
 * A single list fixes both, and it fixes the second one structurally rather
 * than by clamping: with one item per row there is nothing to the side to
 * collide with. The art column is FIXED so that the text columns align down the
 * page, and `--sp-art` is set per dimension below, because a swatch needs 2rem
 * and a 128px `Ag` needs nine. */
.specimens { list-style: none; margin: 0 0 1.5em; padding: 0;
             display: grid; gap: 0; --sp-art: 2.5rem; }
.specimens li { margin: 0; display: grid; min-width: 0; align-items: center;
                gap: 0 1em; padding: 0.25em 0;
                grid-template-columns:
                  var(--sp-art) minmax(0, 24ch) minmax(0, 1fr); }
.specimens code, .sp-val { min-width: 0; overflow-wrap: anywhere; }
/* Colour is the high-count case -- 192 rows on one page -- so its swatch is
 * sized for a list rather than for a card. */
.specimens[data-dim^="color"], .specimens[data-dim="chart-color"] { --sp-art: 2rem; }
.specimens[data-dim="font-size"] { --sp-art: 10.5rem; }
.specimens[data-dim="line-height"], .specimens[data-dim="font-family"],
.specimens[data-dim="font-weight"] { --sp-art: 6rem; }
/* A length or a rule is drawn at its own value up to the clamp, so it wants a
 * column wide enough for the comparison to mean something. */
.specimens[data-dim="spacing"],
.specimens[data-dim="border-width"], .specimens[data-dim="radius"] { --sp-art: 8rem; }
/* `overflow: hidden` is the backstop, not the fix: every specimen above is
 * sized against its own column now, and this is what makes a NEW one that is
 * not fail visibly in its own cell instead of drawing across the labels. */
.sp-art { display: flex; gap: 0.5em; align-items: center;
          min-width: 0; overflow: hidden; }
.sp-pair { display: inline-flex; align-items: center; gap: 0.3em;
           min-width: 0; max-width: 100%; }
/* A light/dark row draws TWO specimens and two side labels where a single row
 * draws one chip, so the column is sized for the pair. Missing this is what put
 * 107px of swatch across the names on the two semantic colour pages. */
.specimens[data-pairs] { --sp-art: 10rem; }
.sp { display: block; width: 1.6rem; height: 1.6rem; flex: none; }
/* A length is the one specimen whose size IS the value, so it is clamped rather
 * than scaled: the largest tokens all hit the cap, and the cap is visible. */
/* ⚠️ `max-width: 100%`, not a rem figure. These two had a hard 8rem cap, which
 * fitted the old 13rem card and overflowed the moment the art column became
 * 2.5rem -- the bars drew straight through the token names beside them. A cap
 * expressed against the CONTAINER cannot come apart from the container again;
 * one expressed in rem has to be kept in sync with `--sp-art` by hand, and was
 * not. The clamp is still visible, which is the property that matters: the
 * largest lengths all hit it. */
.sp-length { height: 0.5rem; max-width: 100%; min-width: 1px; }
.sp-rule { height: 0; width: 100%; max-width: 100%; border-top-style: solid; }
.sp-type, .sp-leading { width: auto; height: auto; min-width: 0;
                        text-align: left; font-style: normal; line-height: 1; }
.sp-leading { display: block; }
/* .sp-side is sized in blocks.css, with the rest of its treatment. It was
 * 0.7em here -- 11.2px, under the 13px Caption floor -- while its family,
 * case and tracking were set in another file. One label, two sheets, and
 * the half that broke the scale was the half no check could see. */

/* ---- the shell ---------------------------------------------------------- *
 * The nav is chrome and belongs OUTSIDE main, so a reader can skip it and a
 * stylesheet can move it wholesale. Layout only: no colour, no rules, nothing
 * an identity would have to undo.
 *
 * TWO STATES, and the NARROW ONE IS THE DEFAULT -- deliberately, because the
 * cramped case is the one that gets forgotten when it is written as the
 * exception. This site is read in a pane beside an editor and an agent console
 * at least as often as in a maximised window: half a 13-inch laptop is ~735px
 * and a third is ~490px (plans/done/human-site-structure.md §0).
 */
body { display: grid; grid-template-columns: minmax(0, 1fr); }

/* Absolutely positioned, so it is NOT a grid item -- an in-flow skip link would
 * claim a cell of the shell grid and push the rail down a row. */
.skip { position: absolute; left: -9999px; }
.skip:focus { position: fixed; z-index: 10; left: 0.5rem; top: 0.5rem;
              padding: 0.5em 0.9em; background: var(--ds-paper, Canvas);
              outline: 2px solid currentColor; }

/* ⚠️ `nav { font-size: 0.9em }` WAS HERE AND IS DELETED. 0.9 of Body is 14.4px,
 * which is not one of the six sizes -- it is the "body, but a bit quieter"
 * affordance the type scale says was removed rather than aliased, surviving in
 * the layout file where the scale's own comment could not see it. It also cost
 * the rail its hierarchy: the group label is Caption at 13px, so the label and
 * the links it heads were 1.4px apart and only case and typeface separated
 * them. Links are Body now, the label is Caption, and the gap is a full rung. */
nav ul { list-style: none; margin: 0; padding: 0; }
nav li { margin: 0; }

/* ---- the third level ----------------------------------------------------- *
 * A `<details>` per container, server-rendered `open` when the reader is inside
 * it. One built-in element, no script, no state to manage, and it works the same
 * in both rail states -- which is the whole reason it is a `<details>` and not a
 * bespoke disclosure. The predecessor accumulated twenty bespoke components; a
 * built-in element is not one of them.
 *
 * ⚠️ SUMMARIES ARE NOT HIDDEN IN THE NARROW STRIP, and that is the point. The
 * strip hides group headings because there is no room for them and their links
 * survive underneath. A container's label is not decoration: hide it and the
 * pages inside become UNREACHABLE at 490px. Flattening instead is not available
 * either -- five entries plus twenty children is six wrapped lines of sticky
 * chrome on every page. So the strip keeps the expanders as expanders: nine
 * items, about what it carried before, and opening one wraps its children
 * below it. */
nav summary { cursor: pointer; }
/* Both halves are needed to retire the native triangle: `list-style` covers
 * Firefox and current WebKit, the pseudo-element covers older Safari. The
 * marker below replaces it because the native one cannot be positioned
 * consistently across the two engines. */
nav summary { list-style: none; }
nav summary::-webkit-details-marker { display: none; }
nav summary::before {
  content: "\203A";              /* U+203A, a single angle quote, not an image.
                                    ⚠️ DOUBLE the backslash: this literal is a
                                    Python string, and `\203` alone is an OCTAL
                                    escape that silently emits U+0083 + "A" --
                                    which renders as tofu, not a marker. */
  display: inline-block;
  width: 0.85em;
  transform-origin: 0.3em 50%;
  transition: transform 0.12s ease-out;
}
nav details[open] > summary::before { transform: rotate(90deg); }
/* The indent is the only thing saying a child belongs to the summary above it,
 * so it is a real step rather than a hint -- and it lines the children up under
 * the label's first letter, past the marker. */
nav details > ul { padding-left: 0.85em; }

/* NARROW: a sticky one-line strip. Every link stays VISIBLE and one click away,
 * at one line of vertical cost, with no disclosure state to manage and no
 * script. The group headings and the one-line notes are the price, and they are
 * hidden here rather than dropped from the markup.
 *
 * The rejected alternative was collapsing the rail into the top of the DOCUMENT,
 * which is the phone-shaped answer: it makes a reader who is arriving briefly
 * and repeatedly scroll past ten links every time.
 *
 * ⚠️ IT WRAPS RATHER THAN SCROLLING SIDEWAYS, and that is a correction, not a
 * preference. The first version was one line with `overflow-x: auto`, which put
 * the current item OFF SCREEN on any page late in the nav order -- on
 * /coverage.html at 480px the reader saw six links and none of them was the one
 * marked `aria-current`. A position cue you have to scroll to find is not a
 * position cue. Wrapping costs a second line and buys: every link visible, the
 * cue always visible, and no hidden-content affordance to invent.
 *
 * The rejected fixes are worth naming. Reordering the current item to the front
 * with `order: -1` is pure CSS and destroys the one property a persistent nav
 * exists for -- the same links in the same place on every page. Scrolling it
 * into view is one line of script and would work; wrapping needs none, so the
 * script is not yet worth the first `<script>` tag on the site. */
/* The background is not decoration here: a sticky bar with a transparent
 * ground lets the page scroll UNDER it and shred both. A var() with a neutral
 * fallback is what this file is allowed to say about colour, and identity.css
 * can replace it -- it paints `body` with a gradient wash, so a flat strip over
 * it will band slightly until it does. */
nav { position: sticky; top: 0; z-index: 5;
      background: var(--ds-ground, Canvas);
      display: flex; flex-wrap: wrap; gap: 0.35rem 1rem; align-items: baseline;
      padding: 0.55rem 1rem; }
nav h2 { display: none; }
nav ul { display: flex; flex-wrap: wrap; gap: 0.35rem 1rem; }
nav a { white-space: nowrap; }
/* An expander is one item in the wrapping row until it is opened, and then it
   takes a full line and wraps its own children inside it -- so opening one
   never pushes a sibling off the row it was on. */
nav li:has(> details[open]) { flex: 1 0 100%; }
nav details > ul { margin-top: 0.35rem; }
/* ⚠️ AN OPEN EXPANDER IS CAPPED IN THE STRIP, because the strip is sticky and
 * `All components` holds 125 links. Unclamped, every component page opened
 * with the whole list wrapped across the top of the screen and pinned there --
 * at 600px wide that was the entire viewport. The cap is about five wrapped
 * rows, and rail.js scrolls the current link into the visible part of it, so
 * the position cue survives. Wide rail only lifts it: there the whole rail is
 * the scroll container instead. */
nav details > ul { max-height: 9.5em; overflow-y: auto; }

/* WIDE: the persistent rail. It gives up EARLY -- 16rem is 35% of a 735px
 * half-window, and the content is what the reader came for. */
@media (min-width: 60rem) and (min-height: 36rem) {
  body { grid-template-columns: var(--ds-rail, 16rem) minmax(0, 1fr); }
  nav { display: block; align-self: start;
        position: sticky; top: 0; height: 100dvh;
        overflow-y: auto; overflow-x: hidden;
        padding: 1.5rem 1.25rem 2rem; }
  /* Layout only. The label's treatment is the `eyebrow` role in identity.css;
     this file used to set its size, case and tracking too, and the two fought.
     A border and its spacing are not typography, so check-heading-roles.py
     permits them here and the role keeps everything it forbids.

     The hairline is `--ds-rule-strong`, which the token block defines as the
     weight that separates one section from the next -- three nav groups is
     exactly that, and `--ds-rule` (between rows in a table) would be the same
     one-weight-below-its-job mistake the rail's own right edge already made
     once. All three groups get one, including the first: above it sits `Home`,
     a loose link outside every group, so the first rule separates something
     real rather than heading a list against nothing.

     The vertical space is deliberately generous, and it is load-bearing rather
     than taste. The group label gave up its brightness step on 2026-09-14 (see
     the `eyebrow` role), so whitespace and the rule are carrying what colour
     used to. Joseph, agreeing to the trade and naming its cost: *"we're
     patching that by significantly reducing information density to add
     whitespace."* If the rail ever has to get denser again, this is the first
     thing that goes and the colour step is what has to come back with it. */
  nav h2 { display: block; margin: 1.6em 0 0.75em; padding-top: 1.2em;
           border-top: 1px solid var(--ds-rule-strong); }
  /* ⚠️ THESE FOUR NUMBERS ARE A FIRST GUESS, 2026-09-14, and are meant to be
     tuned by eye rather than defended. Joseph asked for "bonus vertical space
     between elements" in the rail and for a guess to start from; the gap was
     0.3em (4.8px), which against a 24.8px line box made the rail about as dense
     as a table. It is doubled here.

     They are in `em` so they track the rail's own text rather than the page's
     root, and they move TOGETHER on purpose -- the label's bottom margin is a
     notch above the item gap so it reads as belonging to the list under it
     rather than floating between two, and the nested list keeps the same
     relationship one level down. Change one and the other two want changing.

     ⚠️ WIDE RAIL ONLY. The narrow strip sets its own `gap: 0.35rem 1rem` above
     and is a wrapping horizontal row, where vertical space is line spacing for
     a bar the reader scrolls past -- not the thing being asked for here. */
  nav ul { display: grid; gap: 0.6em; margin: 0 0 0.5em; }
  /* A nested list is inside a list item, not beside one: its own top
     margin would double the gap the grid already provides. */
  nav details > ul { margin: 0.45em 0 0.3em; max-height: none; overflow: visible; }
  /* The rail clips sideways, so a long code name such as
     NaturalLanguageDateRangeInput lost its tail at 16rem. It breaks instead. */
  nav a { white-space: normal; overflow-wrap: anywhere; }
}

/* `dvh`, not `vh`: on mobile Safari `vh` is the LARGEST viewport height, which
 * parks the last nav group permanently under the browser chrome.
 *
 * ⚠️ The `min-height` half of that query is the non-obvious one. A SHORT window
 * is its own case, not a narrow one -- terminal above, browser below is as
 * common as side by side -- and at 420px tall a full-height rail is almost
 * entirely scrollbar. The first version of this rule answered that by letting
 * the rail go `static`, which fixed the scrollbar and threw away persistence:
 * the rail simply scrolled off. Falling back to the STRIP instead keeps the
 * links on screen at one line, which is what a short window can actually
 * afford. Shortage of height and shortage of width want the same answer.
 *
 * 36rem (576px) is a judgement, not a measurement -- tune it against real
 * windows rather than trusting it. */

/* ---- the identity ---------------------------------------------------------
 * Layout only. The lockup carries its own two fills and takes the page's ink
 * for the word; if the word should ever be the mark's gold, that is one
 * `color` rule in identity.css, not a second file.
 *
 * The image is sized by HEIGHT with `width: auto`, and the intrinsic width in
 * the markup comes from the file's viewBox -- so a regenerated wordmark of a
 * different length stays correctly proportioned and still reserves the right
 * box before it loads. */
.identity-link { display: inline-flex; align-items: center; text-decoration: none; }
.identity { display: block; height: 1.25rem; width: auto; }

/* In the narrow strip the anchor is simply the first thing in the flex row. In
 * the rail it sits above the groups, and the space below it is what separates
 * an identity from a menu item. */
@media (min-width: 60rem) and (min-height: 36rem) {
  .identity-link { display: block; margin: 0 0 1.75rem; }
}

/* ------------------------------------------------------------- the jump-to box
 * LAYOUT AND NAMED TOKENS ONLY, like everything else in this file. The look is
 * Jieun's (P6); this decides where it sits and that it can be driven from the
 * keyboard.
 *
 * `position: relative` on the wrapper and an absolute list is what keeps the
 * results OUT of the layout -- a list that pushed the groups down would move
 * every link in the rail on every keystroke.
 *
 * ⚠️ NO LITERAL font-size ANYWHERE HERE, and check-type-scale.py is why: the
 * scale has six named roles and a seventh size arrives by exactly this route.
 * The field inherits Body, which is the size the rail already uses, and the two
 * small things go through `--ds-caption`. With no identity.css the var is
 * undefined and they inherit Body too, which is plain rather than broken.
 *
 * ⚠️ AND NO INVENTED COLOUR, RADIUS OR OPACITY EITHER -- which took three
 * passes to get right, so it is worth naming what was wrong. Joseph,
 * 2026-09-21: *"our general border color is rgb(44, 51, 61) but the input box
 * uses rgb(30, 35, 43) ... let's be careful not to invent colors."*
 *
 *   * The borders used `--ds-rule` (#1e232b), which identity.css reserves for
 *     the line BETWEEN ROWS IN A TABLE and says in as many words never to use
 *     for the other rule's job. Chrome against content is `--ds-rule-strong`
 *     (#2c333d) -- the rgb(44,51,61) above -- and that is what every other
 *     border on the site is.
 *   * The selected row was `var(--ds-wash, ...)`, a token that does not exist,
 *     so readers got the OPERATING SYSTEM's selection blue on a near-black
 *     ground. Replacing it with a `color-mix` on currentColor was no better: a
 *     derived colour is still a colour this file decided. `--ds-fill-subtle` is
 *     the real token for a faint fill.
 *   * The radii were 0.25rem / 0.2rem / 0.15rem, three invented values where
 *     `--ds-radius-chip` already exists for exactly this scale of thing.
 *   * Dimmed text was `opacity`, which is a way of inventing a colour without
 *     naming one. The product ships a semantic content scale and identity.css
 *     carries it: `--content-secondary` and `--content-subtle`.
 *
 * Note `--content-muted` is named in identity.css's own comment and is NOT
 * defined anywhere -- check before reaching for one of those four. */
.jump { position: relative; flex: 1 0 100%; }
.jump input { width: 100%; box-sizing: border-box;
              font: inherit;
              padding: 0.4rem 1.9rem 0.4rem 0.55rem;
              color: inherit; background: var(--ds-paper, Canvas);
              border: 1px solid var(--ds-rule-strong, currentColor);
              border-radius: var(--ds-radius-chip, 3px); }
/* The keyboard hint sits INSIDE the field and is hidden once there is text in
 * it, because at that point it is describing a shortcut the reader has already
 * used. `aria-hidden` in the markup keeps it out of the accessible name. */
.jump-hint { position: absolute; right: 0.5rem; top: 50%; transform: translateY(-50%);
             font-size: var(--ds-caption); pointer-events: none;
             color: var(--content-subtle, inherit);
             border: 1px solid var(--ds-rule-strong, currentColor);
             border-radius: var(--ds-radius-chip, 3px);
             padding: 0 0.25rem; line-height: var(--ds-lh-caption); }
.jump input:not(:placeholder-shown) + .jump-hint { display: none; }

/* ⚠️ THE RESULT LIST IS GONE, 2026-10-08: the box filters the rail instead.
   What it needs here is three things.

   HIDING A RAIL ROW HAS TO BEAT THE RAIL'S OWN `display`. `nav h2` is
   `display: block` and `nav ul` is flex or grid, and ANY author `display`
   beats the UA stylesheet's `[hidden] { display: none }` whatever the
   specificity -- the same trap that once painted an empty result box on every
   page. So the hidden state is stated, at (0,1,2) against `nav h2`'s (0,0,2).

   THE ENTER TARGET IS A SURFACE, NOT A COLOUR: `--ds-fill-subtle`, so the link
   keeps whatever colour identity.css gives it, including the current-page
   cue.

   THE MATCHED NAME sits beside a label that does not contain it -- `c-pill`
   beside Badge -- smaller and quieter, because it explains the hit rather than
   being the thing chosen. */
nav h2[hidden], nav ul[hidden], nav li[hidden] { display: none; }
nav a[data-best] { background: var(--ds-fill-subtle, Highlight);
                   border-radius: var(--ds-radius-chip, 3px); }
.jump-why { margin-left: 0.4em; font-size: var(--ds-caption);
            color: var(--content-subtle, inherit); }
.jump-none { margin: 0.4rem 0 0; font-size: var(--ds-caption);
             color: var(--content-secondary, inherit); }

/* In the rail the box is the first thing under the identity, and the space
   below it is what separates a control from the menu it searches. */
@media (min-width: 60rem) and (min-height: 36rem) {
  .jump { flex: none; margin: 0 0 1.25rem; }
}

/* Orientation used to live here, as an aside above the facts on every page.
 * It is the class template's own prose now, at the foot of the page, so there
 * is nothing left to lay out -- see the note where load_copy() used to be. */
