/* =============================================================================
   Reference pages — page chrome
   =============================================================================

   Styles for the reference site itself: its header, navigation, specimen frames
   and code blocks.

   This file is NOT part of DDS and must not be shipped to a product. It exists
   so the reference pages can present the system without polluting it: a
   "component demo frame" is a documentation concern, not a design system
   component, and putting it in components.css would mean every product carried
   it forever.

   It uses `dds.` layers deliberately: `dds.utilities` is the last DDS layer, so
   an unlayered rule here already wins. Everything is prefixed `ref-` so nothing
   here can be mistaken for part of the system.
   ============================================================================= */

/* ------------------------------------------------------------------ shell */
.ref-page {
  display: flex;
  flex-direction: column;
  min-block-size: 100svh;
}

.ref-header {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--dds-z-raised);

  background-color: color-mix(in srgb, var(--dds-color-surface-default) 88%, transparent);
  /* A blur so content scrolling underneath stays legible without a solid bar. */
  backdrop-filter: blur(8px);
  border-block-end: var(--dds-border-thin) solid var(--dds-color-border-subtle);
}

.ref-header-inner {
  /* One height for the header's top row, and everything in it hangs off this.
     ------------------------------------------------------------------------
     `align-items: center` was centring the brand and the theme toggle against the
     TALLEST item in the row — which is the navigation panel, two rows tall on most
     pages. So the brand sat lower than the navigation it belongs beside, and any
     difference between the panel's real height and its reserved height moved both
     of them.

     Aligning to the start of the row instead, with one shared row height, means the
     panel can only grow downwards. Nothing else in the header can be moved by it. */
  --ref-row: 2.25rem;

  /* The containing block for the collapsed navigation overlay. */
  position: relative;

  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: var(--dds-space-md);
  padding-block: var(--dds-space-sm);
}

.ref-brand {
  display: flex;
  align-items: baseline;
  gap: var(--dds-space-xs);

  /* The shared row height, so the brand sits on the same line as the first row of
     navigation rather than being centred against the whole panel. */
  min-block-size: var(--ref-row);
  align-content: center;
  flex-wrap: wrap;

  font-family: var(--dds-font-display);
  font-size: var(--dds-font-size-lg);
  font-weight: var(--dds-font-weight-bold);
  color: var(--dds-color-text-default);
  text-decoration: none;
  letter-spacing: var(--dds-letter-spacing-tight);
}

.ref-brand:hover {
  color: var(--dds-color-text-default);
}

/* The brand logo — assets/brand/dessau-logo.svg.
   ----------------------------------------------------------------------------
   The header carries the whole logo, mark and wordmark, rather than the mark
   beside the word set in the display face. Two of the same word, in two
   different drawings, is a lockup nobody chose.

   A MASK rather than an `<img>`, and that is the point: the brand is always the
   colour of the text around it. An `<img>` cannot be — an SVG loaded as an image
   is its own document with nothing to inherit from, so `currentColor` there
   resolves to black, in both themes, silently. A mask takes only the shape and
   lets `background-color` supply the colour, so the logo follows the theme
   exactly, including a site theme that disagrees with the operating system.

   Sized in `em`, because `--dds-font-size-lg` is a `clamp()` and a logo in `rem`
   would drift away from the sub-line as the viewport changes the type size.
   0.8em of height — the scrolled size, see below — puts the wordmark's cap
   slightly above Space Grotesk's 0.70em cap, which is the right direction: Inter
   Black reads heavier than the bold it replaces, so it needs less size to carry
   the same weight. `aspect-ratio` carries the file's own proportion, so only one
   length is written down.

   No `align-self`: the row aligns on the baseline, and a flex item with no line
   boxes baselines on its bottom edge — which is where this logo's baseline is,
   give or take the 1.3% of overshoot below it. The wordmark therefore sits on
   the same line as the sub-line beside it, without a nudge. */
/* Large on arrival, its reading size once the reader has started.
   ----------------------------------------------------------------------------
   Nothing is competing for the space at the top of a page, and at 0.8em the
   brand was being modest where it had no reason to be. Once anything is scrolled
   it is in the way, and 0.8em is the size that sits level with the sub-line.

   Two constraints hold the whole thing together, and both come from the header
   being `position: sticky`:

   1. **The header's height must not change.** A sticky bar that changes height
      moves the content underneath it, which is the opposite of getting out of
      the way. `--ref-row` fixes the row's height and both logo sizes fit inside
      it, so only the logo moves.
   2. **The row must not wrap.** The logo is over six times as wide as it is
      tall (wider still since the "DS" tag), so growing it moves the sub-line
      sideways. At the sizes below it stays on one line at every width; below
      48rem the sub-line is hidden anyway.

   `block-size` rather than `scale`, even though `scale` is the cheaper property:
   a transform would leave the layout at one size, so the logo would either
   overlap the sub-line or leave a hole beside it. Reflowing one element inside a
   fixed-height row for 220ms is the honest version.

   The state comes from `data-ref-scrolled`, set in reference.js. Without
   JavaScript the attribute never appears and the logo stays large — which is the
   correct default, because scroll position cannot be known without it. */
.ref-header {
  --ref-brand-logo-size: 1.25em;
}

.ref-header[data-ref-scrolled] {
  --ref-brand-logo-size: 0.8em;
}

/* The "DS" tag widened the logo enough to matter at the narrowest viewport
   this row is asked to fit: at 320px — the standard floor for a mobile
   viewport, not a value picked to make a test pass — the unscrolled row
   needs 313px (144 brand + 12 gap + 101 Menu button + 12 gap + 44 theme
   toggle) against 308px available inside the padding, and the toggle wraps
   onto its own line at the far left, the exact failure `.ref-brand-sub`
   above was already written to avoid. The sub-line is gone by this width
   already, so only the logo itself is left to give back the difference.
   1.1em keeps real headroom (about 11px) rather than shaving it to the
   edge; the scrolled state's 0.8em is smaller still and wins on specificity
   regardless of viewport, so this only ever touches the "large on arrival"
   size. */
@media (max-width: 20rem) {
  .ref-header {
    --ref-brand-logo-size: 1.1em;
  }
}

/* The transition is switched on one frame AFTER the first state is applied, so a
   page that loads already scrolled — arriving on a `#fragment`, reloading
   halfway down — starts at the small size rather than animating down to it in
   front of a reader who has not scrolled anything. */
.ref-header[data-ref-scroll-ready] .ref-brand-logo {
  transition: block-size var(--dds-duration-base) var(--dds-ease-standard);
}

@supports (mask-image: url("brand/dessau-logo.svg")) {
  .ref-brand-logo {
    display: inline-block;
    flex-shrink: 0;

    block-size: var(--ref-brand-logo-size);
    aspect-ratio: 629.98 / 101.34;

    background-color: currentColor;
    mask-image: url("brand/dessau-logo.svg");
    mask-size: contain;
    mask-repeat: no-repeat;
    mask-position: center;
  }

  /* The word is in the logo now, so the text is hidden — but only here, inside
     the same `@supports` that drew the logo. Without mask support there is no
     logo, and the word has to stay visible; that is why this is not simply
     `class="dds-sr-only"` in the markup, which would hide it unconditionally and
     leave the header blank. The element stays in the DOM either way, so the
     link's accessible name is "Dessau Foundations for digital products" in both
     cases. Same recipe as the `dds-sr-only` utility. */
  .ref-brand-name {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
}

.ref-brand-sub {
  font-family: var(--dds-font-body);
  font-size: var(--dds-font-size-xs);
  font-weight: var(--dds-font-weight-regular);
  color: var(--dds-color-text-muted);
  letter-spacing: var(--dds-letter-spacing-normal);
}

/* Below the tablet breakpoint the sub-line is not drawn, and that is a layout
   fix rather than a matter of taste.
   ----------------------------------------------------------------------------
   `.ref-header-inner` wraps. Its in-flow children below the shell threshold are
   the brand, the Menu button and the theme toggle, and at 480px the first two
   very nearly fill the 448px content box on their own — around 290px of brand,
   most of it this sub-line, plus around 110px of button. The toggle then had
   nowhere to go but the next line, where it sat at the far LEFT: a utility
   control is looked for at the end, and it was the first thing on a row of its
   own.

   `margin-inline-start: auto` on the Menu button does not rescue it. An auto
   margin is resolved per line, after wrapping has already happened.

   Nor does making the brand shrinkable. A wrapping flex container breaks lines
   using each item's HYPOTHETICAL main size and only shrinks what is left on a
   line that still overflows — so by the time shrinking could apply, the toggle
   is already on the next line. The brand has to be genuinely narrower, not
   merely willing to be.

   So the sub-line goes, and it goes with the sr-only recipe rather than
   `display: none`: it is part of the link's accessible name — "Dessau
   Foundations for digital products" — and that name should not change with the
   viewport. Same reasoning as `.ref-brand-name` above.

   47.999rem is the named tablet breakpoint from the far side. At 768px the row
   needs about 476px of its 736px, so there is real headroom above the threshold
   rather than a value tuned until one test went green. */
@media (max-width: 47.999rem) {
  .ref-brand-sub {
    position: absolute;
    inline-size: 1px;
    block-size: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }

  /* The 320px floor (WCAG 2.2 1.4.10) is where brand + Menu button + theme
     toggle have to share one row without the toggle wrapping to a line of its
     own at the far left, where nobody looks for a utility control (#16).

     `--dds-space-sm` here (#120) left the margin at ~4px on a platform with an
     overlay scrollbar and negative once a classic one — `scrollbar-gutter:
     stable`, see base.css — takes its ~15px off the row width. A few px of
     per-engine text metrics then decided it, and the theme toggle wrapped
     (#153).

     `--dds-space-xs` for both the gutter and the gap frees another ~16px — two
     4px gutter edges and two 4px gaps — which turns the ~4px deficit into ~12px
     of real margin. At 320px nobody misses 4px of edge padding, and the header
     was already the one place tightened past the default `space-md`. */
  .ref-header-inner {
    --dds-container-gutter: var(--dds-space-xs);
    gap: var(--dds-space-xs);
  }
}

/* --------------------------------------------------------------- navigation */
/* Two levels, and a disclosure below the shell's threshold.
   ----------------------------------------------------------------------------
   A media query rather than a container query, and that is correct here: this is
   the page shell, so the viewport IS what it depends on. Inside a component the
   opposite is true — see agent/responsive.md.

   The panel is NOT `hidden` in the markup. It is hidden by CSS only at the widths
   where the toggle is actually displayed, which means the failure direction is
   right: with no JavaScript, or before enhancement runs, the navigation is
   present rather than behind a button that does nothing. */
/* Narrow: an overlay BELOW the header, not a row inside it.
   ----------------------------------------------------------------------------
   Out of flow on purpose. As a flex row it took the full width, which pushed
   everything after it in the DOM — the theme toggle — onto a third row while
   appearing above it. Moving the toggle before the navigation fixed the focus
   order and put it in an odd place instead.

   Out of flow, neither problem exists: the header row keeps its height, the
   toggle stays at the end where it belongs, and DOM order still matches visual
   order because an overlay is not in the row at all. */
.ref-nav-panel {
  position: absolute;
  inset-inline: 0;
  inset-block-start: 100%;
  z-index: var(--dds-z-dropdown);

  display: flex;
  flex-direction: column;
  gap: var(--dds-space-2xs);

  padding: var(--dds-space-sm) var(--dds-space-md);
  background-color: var(--dds-color-surface-raised);
  border-block-end: var(--dds-border-thin) solid var(--dds-color-border-default);
  box-shadow: var(--dds-elevation-md);
}

/* The menu button is pushed to the end of the row; the theme toggle follows it,
   which is where a utility control is looked for. Both share the row height, so
   neither can be moved by the panel growing. */
.ref-nav-toggle {
  margin-inline-start: auto;
}

.ref-header-inner > .dds-theme-toggle {
  min-block-size: var(--ref-row);
  display: inline-flex;
  align-items: center;
}

/* The shell's three thresholds, and what each one decides.
   ----------------------------------------------------------------------------
   These are the reference site's own, not DDS's — a page shell is the one place a
   viewport media query is right, because the shell IS the window. Written down
   together because they were three numbers in three files with three local
   reasons, and the question they answer as a set — what does a tablet in portrait
   get? — had no answer anywhere.

     47.999rem  the brand's sub-line goes. Below it the header row cannot hold
                brand, sub-line, disclosure and theme toggle without wrapping the
                toggle onto a line of its own, at the left, where nobody looks for
                it (#16).

     63.999rem  the navigation panel may be collapsed. This is the mirror of the
                rule below and exists only so the panel can be reopened where the
                toggle that reopens it exists.

     64rem      two columns: the contents list becomes a sticky side column and
                the navigation goes inline. The same number for both so the header
                and the content change shape at the same moment rather than one at
                a time.

   **A tablet in portrait (834px) therefore gets the phone shell**, and that is a
   decision rather than an oversight: at 834px a 15rem contents column leaves the
   text about 590px, which is wider than the comfortable measure only by enough to
   make the sticky column feel like it is taking room from the reading. The
   two-column layout starts where a sidebar plus a full measure genuinely fits.

   What a tablet does NOT get is a phone's content: nothing is hidden, the
   navigation is one disclosure away, and the contents list is above the text
   instead of beside it. */

/* Only where the toggle exists to reopen it. */
@media (max-width: 63.999rem) {
  .ref-nav-panel[hidden] {
    display: none;
  }
}

.ref-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--dds-space-2xs);
}

.ref-nav a {
  padding: var(--dds-space-2xs) var(--dds-space-sm);
  min-block-size: var(--ref-row);
  display: inline-flex;
  align-items: center;

  font-size: var(--dds-font-size-sm);
  font-weight: var(--dds-font-weight-medium);
  color: var(--dds-color-text-subtle);
  text-decoration: none;
  border-radius: var(--dds-radius-sm);
}

.ref-nav a:hover {
  background-color: var(--dds-color-surface-hover);
  color: var(--dds-color-text-default);
  text-decoration: none;
}

/* --- the second level ---------------------------------------------------- */
/* The pages of the current group. Set apart from the first level by size and by a
   leading rule, not by indentation — indentation disappears the moment the row
   wraps, which on a narrow screen is immediately. */
.ref-nav-secondary {
  display: flex;
  flex-wrap: wrap;
  gap: var(--dds-space-3xs);

  padding-inline-start: var(--dds-space-sm);
  border-inline-start: var(--dds-border-thick) solid var(--dds-color-border-subtle);
}

.ref-nav-secondary a {
  padding: var(--dds-space-3xs) var(--dds-space-xs);
  min-block-size: 2rem;
  display: inline-flex;
  align-items: center;

  font-size: var(--dds-font-size-xs);
  color: var(--dds-color-text-muted);
  text-decoration: none;
  border-radius: var(--dds-radius-sm);
}

.ref-nav-secondary a:hover {
  background-color: var(--dds-color-surface-hover);
  color: var(--dds-color-text-default);
  text-decoration: none;
}

.ref-nav-secondary a[aria-current="page"] {
  color: var(--dds-color-text-link);
  font-weight: var(--dds-font-weight-semibold);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* --- the group containing the current page -------------------------------- */
/* `data-current-section`, not `aria-current`: the group is not a page, and the
   second row already carries the real state. This is a visual aid that is
   deliberately redundant, so nothing depends on it alone.

   It reads as a TAB that owns the row beneath it, rather than as a highlighted
   link. The first version was a colour step plus a weight step — subtle to
   default, medium to semibold — and it was too quiet to find at a glance, which is
   the one job it has. Four cues now: fill, weight, full-contrast text and a bar
   along the edge it shares with the row it introduces. */
.ref-nav a[data-current-section] {
  color: var(--dds-color-text-default);
  font-weight: var(--dds-font-weight-semibold);
  background-color: var(--dds-color-surface-selected);
}

/* The connecting bar, only when there is actually a second row to connect to. A bar
   pointing at nothing would be decoration claiming to be structure. */
.ref-nav-panel:has(.ref-nav-secondary) .ref-nav a[data-current-section] {
  box-shadow: inset 0 -2px 0 0 var(--dds-color-action-primary);
  /* Square along the shared edge, so the bar reads as a join rather than as a
     detached underline. */
  border-end-start-radius: 0;
  border-end-end-radius: 0;
}

/* The current page. Colour plus weight plus an underline — three cues, so
   "where am I" does not rely on perceiving a tint. */
.ref-nav a[aria-current="page"] {
  color: var(--dds-color-text-link);
  font-weight: var(--dds-font-weight-semibold);
  background-color: var(--dds-color-surface-selected);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.ref-main {
  flex-grow: 1;
  padding-block: var(--dds-space-2xl);
}

/* The footer carries more than one line on some pages — the reference landing page
   states the licence and what is not offered — so it needs the rhythm of a block of
   text rather than the padding of a single line.

   `padding-block-end` is larger than the start on purpose: the border above already
   separates the footer from the content, while below it there is nothing but the
   end of the document, and a page that stops immediately under its last line reads
   as cut off rather than finished. */
.ref-footer {
  border-block-start: var(--dds-border-thin) solid var(--dds-color-border-subtle);
  padding-block-start: var(--dds-space-xl);
  padding-block-end: var(--dds-space-2xl);
  color: var(--dds-color-text-muted);
  font-size: var(--dds-font-size-sm);
}

.ref-footer p + p {
  margin-block-start: var(--dds-space-sm);
}

.ref-footer p {
  max-inline-size: var(--dds-measure-wide);
}

/* ------------------------------------------------------------------ sections */
.ref-section {
  padding-block-end: var(--dds-space-2xl);
  /* No `content-visibility: auto` here, and the reason is worth keeping.

     It was here, on every section of every reference page, to skip the rendering
     work for the ones off-screen. It also broke the pages on WebKit in two ways
     that took a browser to see:

       - a click on a control far down the page landed on nothing. Sections above
         it take their real height only as they are approached, so the page grows
         while the pointer is being aimed. Three unrelated demos — the wizard, a
         theme toggle, a password field — all failed the same way (#9).
       - `getComputedStyle(el).getPropertyValue('--dds-color-…')` returned an
         empty string for anything inside a skipped section, so the foundations
         page reported thirty of its own tokens as undeclared.

     Both are consequences of the containment, not bugs in the components. The
     saving was never measured and the reference pages are not long enough to
     need it, so the trade is one-sided.

     `.dds-defer-render` still offers this to a product that has measured a
     reason — opt-in, and with the cost written down in agent/responsive.md. */
}

.ref-section-head {
  padding-block-end: var(--dds-space-md);
  margin-block-end: var(--dds-space-lg);
  border-block-end: var(--dds-border-thin) solid var(--dds-color-border-subtle);
}

/* ------------------------------------------------------------------ specimen */
/* A frame around a rendered example. The dashed edge says "this is a specimen,
   not part of the page". */
.ref-specimen {
  padding: var(--dds-space-lg);
  background-color: var(--dds-color-surface-default);
  border: var(--dds-border-thin) solid var(--dds-color-border-subtle);
  border-radius: var(--dds-radius-lg);
}

/* A specimen shown on the page background instead, for anything whose own
   surface colour is the point. */
.ref-specimen-plain {
  background-color: var(--dds-color-surface-page);
}

.ref-specimen-label {
  font-size: var(--dds-font-size-xs);
  font-weight: var(--dds-font-weight-medium);
  color: var(--dds-color-text-muted);
  margin-block-end: var(--dds-space-xs);
}

/* The "Using it" section reads as prose with two code samples in it, not a
   page of code — .ref-code's own full-width default is correct for a
   genuine code sample elsewhere on the site (a long line legitimately
   needs the room) but wrong for a section this short. Capped on the
   section's own OUTER wrapper, not on the fetched-prompt specimen alone:
   capping one specimen fixes it and leaves every neighbour (the HTML
   integration example, the notice boxes) full-width beside it, which reads
   as more inconsistent than capping nothing at all. One shared width on
   the wrapper means everything inside inherits it by construction. */
[data-ref-using-it] {
  max-inline-size: var(--dds-measure-wide);
}

/* 1.5rem is 24px, the WCAG 2.2 2.5.8 minimum — dds-text-sm's line height
   alone measures 22px at 320px. Same shape and same fix as .dds-breadcrumb
   a in components-navigation.css: not exempt as an inline target, since it
   sits beside a button rather than inside a sentence. */
.ref-prompt-file-link {
  display: inline-flex;
  align-items: center;
  min-block-size: 1.5rem;
}

/* A grid of state variations. */
.ref-matrix {
  display: grid;
  gap: var(--dds-space-md);
  grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
}

/* ------------------------------------------------------------------- swatches */
.ref-swatches {
  display: grid;
  gap: var(--dds-space-sm);
  grid-template-columns: repeat(auto-fill, minmax(min(11rem, 100%), 1fr));
}

.ref-swatch {
  border: var(--dds-border-thin) solid var(--dds-color-border-subtle);
  border-radius: var(--dds-radius-md);
  overflow: hidden;
}

.ref-swatch-chip {
  --ref-swatch-color: transparent;

  block-size: 3.5rem;

  /* A chequerboard BEHIND the swatch colour, so a token that is unexpectedly
     transparent or translucent shows as such instead of looking like the page
     background.

     The colour is the FIRST background layer and the chequerboard the rest,
     because background layers stack front to back — the first one listed is on
     top. Setting the colour with `background-color` instead does not work: the
     colour layer would then sit underneath every `background-image`, and the
     chequerboard would be drawn over the swatch, making every single one look
     chequered. */
  background-image:
    linear-gradient(var(--ref-swatch-color), var(--ref-swatch-color)),
    linear-gradient(45deg, var(--dds-color-surface-sunken) 25%, transparent 25%),
    linear-gradient(-45deg, var(--dds-color-surface-sunken) 25%, transparent 25%),
    linear-gradient(45deg, transparent 75%, var(--dds-color-surface-sunken) 75%),
    linear-gradient(-45deg, transparent 75%, var(--dds-color-surface-sunken) 75%);
  background-size: auto, 12px 12px, 12px 12px, 12px 12px, 12px 12px;
  background-position: 0 0, 0 0, 0 6px, 6px -6px, -6px 0;

  /* The chequerboard needs something to sit on, or the transparent squares show
     the card behind and the effect is invisible on a matching surface. */
  background-color: var(--dds-color-surface-default);
}

.ref-swatch-body {
  padding: var(--dds-space-xs);
  background-color: var(--dds-color-surface-default);
  border-block-start: var(--dds-border-thin) solid var(--dds-color-border-subtle);
}

.ref-swatch-name {
  display: block;
  font-family: var(--dds-font-mono);
  font-size: var(--dds-font-size-2xs);
  color: var(--dds-color-text-default);
  overflow-wrap: anywhere;
}

.ref-swatch-note {
  display: block;
  font-size: var(--dds-font-size-2xs);
  color: var(--dds-color-text-muted);
  margin-block-start: var(--dds-space-3xs);
}

/* A specimen whose token does not resolve. Bordered in the error colour so it cannot
   be mistaken for a value that happens to be transparent or zero. */
.ref-swatch-missing,
.ref-ruler-missing {
  border: var(--dds-border-thin) solid var(--dds-color-border-error);
  border-radius: var(--dds-radius-sm);
  padding: var(--dds-space-xs);
}

/* ------------------------------------------------------------------- rulers */
/* A spacing ruler drawn at true size, so the scale can be judged rather than
   read as a number. */
.ref-ruler {
  display: flex;
  align-items: center;
  gap: var(--dds-space-sm);
}

.ref-ruler-bar {
  block-size: var(--dds-space-md);
  background-color: var(--dds-color-accent);
  border-radius: var(--dds-radius-sm);

  /* The JS gives this an exact width, in px once scaled — never re-compressed
     by this row's own flex layout, or a bar with a larger share of `widest`
     can still render narrower than one with a smaller share, whenever its
     own row happens to have marginally less room (a real, measured bug: see
     fitRulers() in reference.js). */
  flex-shrink: 0;
}

.ref-ruler-name {
  font-family: var(--dds-font-mono);
  font-size: var(--dds-font-size-2xs);
  color: var(--dds-color-text-muted);
  min-inline-size: 11rem;
  white-space: nowrap;
}

/* The readout never wraps, and the bar gives up the width instead.
   Left to wrap, it made the taller rows twice the height of the shorter ones,
   and the stack's single gap then read as a scale of gaps growing down the
   list — the ramp looked uneven, in a specimen whose whole job is to show an
   even ramp. The bar is the specimen and the readout is the caption, so when
   the row runs out of room it is the bar that shrinks. */
.ref-ruler-readout {
  white-space: nowrap;
  flex-shrink: 0;
}

/* On a phone the name and the readout together leave the bar almost nothing to
   draw with, now that neither of them wraps. So below the tablet breakpoint the
   name takes a line of its own and the bar gets the full width underneath it.
   Every row is two lines instead of one — still the same height as its
   neighbours, which is the point. */
@media (max-width: 47.999rem) {
  .ref-ruler {
    flex-wrap: wrap;
  }

  .ref-ruler-name {
    min-inline-size: 100%;
  }
}

/* ------------------------------------------------------------------- motion */
/* A duration or an easing curve read as a number does not say how it feels.
   One table, not two: the token list and its live demo used to be separate
   blocks stating the same seven values twice — this folds the animated rail
   and its own Play control into the Demo column of the token table itself,
   so a token's name, value, use and feel are all read in one row rather than
   assembled across two places.

   The dot plays the real token — actual `transition-duration` /
   `transition-timing-function`, not a hand-tuned approximation — so what is
   seen is what a component actually does, never an artist's impression of it.

   Static at rest and only moves when played: modern-web-guidance's own
   accessibility guidance is to default auto-animating content to a static
   view and let motion be opted into, and nothing here needed a manual
   `prefers-reduced-motion` check on top of that — the transitions this uses
   are ordinary `transition-duration`/`transition-timing-function`, already
   collapsed to ~0 for anyone with reduced motion set, by the same global rule
   in base.css every real component relies on. */
.ref-motion-demo-cell {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--dds-space-sm);
}

/* `surface-active` rather than `surface-sunken`: sunken is defined equal to
   the page background in dark mode (semantic.css), which made the track this
   dot travels along nearly disappear against the card behind it — exactly
   the range the demo exists to show. `-active` is a clearly distinct step
   from `-default` (the card's own surface) in both themes, and the border
   gives the pill a crisp edge even against a background close to its own. */
.ref-motion-rail {
  position: relative;
  inline-size: 8rem;
  block-size: 1.75rem;
  background-color: var(--dds-color-surface-active);
  border: var(--dds-border-thin) solid var(--dds-color-border-subtle);
  border-radius: var(--dds-radius-pill);
  flex-shrink: 0;
}

/* The dot's own transition reads the SAME two custom properties every row
   sets — `--ref-motion-duration` and `--ref-motion-ease` — pointed at
   whichever `--dds-duration-*`/`--dds-ease-*` token that row demonstrates.
   reference.js derives both from the row's own `data-ref-motion-token`;
   nothing here or there hard-codes a millisecond figure or a curve, so if a
   token's value ever changes, this changes with it — the same guarantee
   every other live specimen on this page already makes. */
/* The end (played) position is set directly as an inline style by
   reference.js, computed from live geometry rather than a second copy of
   these numbers — not toggled through an attribute selector. CI's Linux
   WebKit was found, by direct diagnostic evidence, to sometimes leave
   getComputedStyle() reporting the pre-attribute value even after
   `data-ref-motion-run` was confirmably present on the element: the
   attribute existed, the custom properties it drove resolved correctly,
   and the position simply never picked up the `[data-ref-motion-run]`
   rule — a missed style invalidation specific to that engine, not
   anything wrong upstream of it. An inline style write doesn't route
   through attribute-selector invalidation at all, so it isn't exposed to
   that bug. */
.ref-motion-dot {
  position: absolute;
  inset-block: 0.1875rem;
  inset-inline-start: 0.1875rem;
  inline-size: 1.375rem;
  border-radius: var(--dds-radius-circle);
  background-color: var(--dds-color-accent);

  transition-property: inset-inline-start;
  transition-duration: var(--ref-motion-duration, var(--dds-duration-base));
  transition-timing-function: var(--ref-motion-ease, var(--dds-ease-standard));
}

/* -------------------------------------------------------------------- layers */
/* The cascade-layer stack, weakest at the top. Each step is inset a little further
   so the order reads as a progression rather than as a plain list. */
.ref-layer {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--dds-space-xs);

  padding: var(--dds-space-2xs) var(--dds-space-sm);
  border-inline-start: var(--dds-border-thick) solid var(--dds-color-border-subtle);
  background-color: var(--dds-color-surface-sunken);
  border-radius: var(--dds-radius-sm);
}

.ref-layer code {
  font-family: var(--dds-font-mono);
  font-size: var(--dds-font-size-xs);
  color: var(--dds-color-text-default);
}

/* The product's own layer. Marked with weight and a border as well as colour, so
   "this is the one that wins" survives greyscale. */
.ref-layer-yours {
  border-inline-start-color: var(--dds-color-action-primary);
  background-color: var(--dds-color-surface-selected);
}

/* --------------------------------------------------------------------- icons */
/* One cell per symbol in the sprite, each with its role name. The name matters as
   much as the glyph: the role is what markup refers to, and which Ionicon backs it
   is an implementation detail that may change. */
.ref-icons {
  display: grid;
  gap: var(--dds-space-sm);
  grid-template-columns: repeat(auto-fill, minmax(min(9rem, 100%), 1fr));
}

.ref-icon {
  display: flex;
  align-items: center;
  gap: var(--dds-space-xs);

  padding: var(--dds-space-xs) var(--dds-space-sm);
  background-color: var(--dds-color-surface-sunken);
  border-radius: var(--dds-radius-sm);

  /* The glyph is drawn larger than body text so the shape can be judged. */
  font-size: var(--dds-font-size-lg);
  color: var(--dds-color-text-default);
}

.ref-icon-name {
  font-family: var(--dds-font-mono);
  font-size: var(--dds-font-size-2xs);
  color: var(--dds-color-text-subtle);
  /* A long role name must not push the glyph out of the cell. */
  min-inline-size: 0;
  overflow-wrap: anywhere;
}

/* -------------------------------------------------------------- breakpoints */
/* Live: which named breakpoint the current window width has reached. Resizing the
   window is the demonstration, so the state has to be visible at a glance. */
.ref-breakpoint-readout {
  padding: var(--dds-space-xs) var(--dds-space-sm);
  margin-block-end: var(--dds-space-sm);

  font-family: var(--dds-font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--dds-color-text-default);

  background-color: var(--dds-color-surface-sunken);
  border-radius: var(--dds-radius-sm);
}

.ref-breakpoint-list {
  display: flex;
  flex-direction: column;
  gap: var(--dds-space-3xs);
}

.ref-breakpoint {
  display: flex;
  align-items: baseline;
  gap: var(--dds-space-sm);
  flex-wrap: wrap;

  padding: var(--dds-space-2xs) var(--dds-space-xs);
  border-inline-start: var(--dds-border-thick) solid var(--dds-color-border-subtle);
  border-radius: var(--dds-radius-sm);
}

/* The active one gains a border weight as well as a colour — the state is not
   carried by hue alone. */
.ref-breakpoint[data-active] {
  border-inline-start-color: var(--dds-color-action-primary);
  background-color: var(--dds-color-surface-selected);
}

.ref-breakpoint-name {
  font-family: var(--dds-font-mono);
  font-size: var(--dds-font-size-2xs);
  color: var(--dds-color-text-default);
  /* 14rem is 224px of a 320px screen, before the value and the state have had
     any. `min()` lets the name take a line of its own instead — the row already
     wraps, so the rest follows underneath. Same treatment as `.ref-ruler-name`
     one specimen above. */
  min-inline-size: min(14rem, 100%);
}

.ref-breakpoint-value {
  color: var(--dds-color-text-subtle);
  font-size: var(--dds-font-size-xs);
}

.ref-breakpoint-state {
  margin-inline-start: auto;
  color: var(--dds-color-text-muted);
}

.ref-breakpoint[data-active] .ref-breakpoint-state {
  color: var(--dds-color-text-link);
  font-weight: var(--dds-font-weight-semibold);
}

/* --------------------------------------------------------------------- code */
.ref-code {
  margin: 0;
  padding: var(--dds-space-md);
  overflow-x: auto;

  font-family: var(--dds-font-mono);
  font-size: var(--dds-font-size-sm);
  line-height: var(--dds-line-height-normal);
  tab-size: 2;

  background-color: var(--dds-color-surface-sunken);
  border: var(--dds-border-thin) solid var(--dds-color-border-subtle);
  border-radius: var(--dds-radius-md);
  color: var(--dds-color-text-subtle);
}

.ref-code:focus-visible {
  outline: var(--dds-focus-ring-width) solid var(--dds-color-focus-ring);
  outline-offset: calc(var(--dds-focus-ring-offset) * -1);
}

/* --------------------------------------------------------------- guidance */
/* Paired do / don't guidance. The heading carries the word, never only the
   colour of the border. */
.ref-guidance {
  display: grid;
  gap: var(--dds-space-md);
  grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
}

.ref-do,
.ref-dont {
  padding: var(--dds-space-md);
  border-radius: var(--dds-radius-md);
  border: var(--dds-border-thin) solid var(--dds-color-border-default);
  border-inline-start-width: var(--dds-space-2xs);
}

.ref-do {
  border-color: var(--dds-color-border-success);
  background-color: var(--dds-color-surface-success);
}

.ref-dont {
  border-color: var(--dds-color-border-error);
  background-color: var(--dds-color-surface-error);
}

.ref-do h3,
.ref-dont h3 {
  font-size: var(--dds-font-size-md);
  font-family: var(--dds-font-body);
  margin-block-end: var(--dds-space-2xs);
}

.ref-do h3 { color: var(--dds-color-text-success); }
.ref-dont h3 { color: var(--dds-color-text-error); }

/* ----------------------------------------------------------- theme preview */
/* Forces a theme on a subtree, so both themes can be seen side by side without
   toggling the page. The tokens are scoped to `[data-theme]`, so nesting one
   inside the other simply works. */
.ref-theme-pair {
  display: grid;
  gap: var(--dds-space-md);
  grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
}

.ref-theme-panel {
  padding: var(--dds-space-md);
  background-color: var(--dds-color-surface-page);
  border: var(--dds-border-thin) solid var(--dds-color-border-default);
  border-radius: var(--dds-radius-md);
  color: var(--dds-color-text-default);
}

/* ------------------------------------------------------------------- tokens */
.ref-token-table {
  font-size: var(--dds-font-size-sm);
}

.ref-token-table code {
  font-size: var(--dds-font-size-xs);
  overflow-wrap: anywhere;
}

/* =============================================================================
   Variant switch
   =============================================================================

   One component, several variants that differ in content or behaviour, shown one
   at a time behind a segmented control.

   `.ref-matrix` above is the other answer, and the two are not interchangeable.
   A matrix is right for small state variations — five button sizes, four badge
   tones — where seeing them together is the comparison. A switch is right when a
   variant is a whole layout, because three of those stacked in a column put the
   difference between them outside the viewport, and the difference is the entire
   reason the reader scrolled here.

   The control itself is `.dds-segmented`, unmodified: the reference is the first
   place that ought to take its own prescription for "two to five mutually
   exclusive options, all visible at once".
   ============================================================================= */

/* Block, not grid, and the reason is the panels rather than the switch.
   `hidden="until-found"` leaves an element in the layout with its contents
   skipped — a zero-height box. Zero-height boxes cost nothing in block flow and
   cost a full `gap` each in a grid, so two inactive variants would open a hole
   under the switch. */
[data-ref-variants] {
  margin-block: var(--dds-space-md);
}

/* Never wider than the specimen. `.dds-segmented` wraps its own options
   (components-forms.css), which is what lets this cap be honoured instead of
   overflowed — three options of ordinary length measured 366px in a 238px slot
   at 320px when it could do neither (#87). */
.ref-variants-switch {
  max-inline-size: 100%;
  margin-block-end: var(--dds-space-md);
}

/* Before the switch exists, every variant is on show — nothing is hidden until
   there is a control able to bring it back. Each therefore needs the caption the
   segmented control would otherwise be giving it, and the attribute that names
   it for the enhanced case is already on the element. */
[data-ref-variants]:not([data-ref-variants-enhanced]) > [data-ref-variant]::before {
  content: attr(data-ref-variant);
  display: block;

  margin-block-end: var(--dds-space-xs);
  font-size: var(--dds-font-size-xs);
  font-weight: var(--dds-font-weight-medium);
  color: var(--dds-color-text-muted);
}

/* =============================================================================
   Breakpoint preview
   =============================================================================

   A width switcher around a specimen, so every breakpoint can be inspected
   without resizing the browser window.

   This is the single most useful documentation tool in the system, for one
   reason: without it, nobody looks at the narrow state. Not the person building
   the component, not the person reviewing it, and not a tool. The narrow layout
   is where responsive bugs live, and a switcher is what makes checking it a
   two-second act instead of a deliberate exercise.

   It only works on components that respond to their CONTAINER rather than the
   viewport. A component using `@media` reads the real window and ignores the
   stage entirely — the buttons would visibly do nothing. That is exactly why
   DDS requires container queries for anything with layout-shifting behaviour.
   ============================================================================= */

.ref-bp {
  border: var(--dds-border-thin) solid var(--dds-color-border-subtle);
  border-radius: var(--dds-radius-md);
  overflow: hidden;
}

.ref-bp-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--dds-space-2xs);

  padding: var(--dds-space-2xs);
  background-color: var(--dds-color-surface-sunken);
  border-block-end: var(--dds-border-thin) solid var(--dds-color-border-subtle);
}

.ref-bp-toolbar-label {
  font-size: var(--dds-font-size-2xs);
  color: var(--dds-color-text-muted);
  padding-inline: var(--dds-space-2xs);
}

/* The horizontal scroller: the stage may be wider than the page area when a
   large width is selected. */
.ref-bp-scroll {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  padding: var(--dds-space-md);
  background-color: var(--dds-color-surface-page);
}

.ref-bp-scroll:focus-visible {
  outline: var(--dds-focus-ring-width) solid var(--dds-color-focus-ring);
  outline-offset: calc(var(--dds-focus-ring-offset) * -1);
}

/* The stage. Its inline-size is what the container queries inside actually
   measure, which is the entire point. */
.ref-bp-stage {
  inline-size: 100%;
  margin-inline: auto;
  background-color: var(--dds-color-surface-default);
  border: var(--dds-border-thin) dashed var(--dds-color-border-default);
  border-radius: var(--dds-radius-sm);
  /* Establish a containing block so a sticky child behaves predictably. */
  position: relative;
  transition: inline-size var(--dds-duration-base) var(--dds-ease-standard);
}

.ref-bp-readout {
  margin-inline-start: auto;
  padding-inline: var(--dds-space-xs);
  font-family: var(--dds-font-mono);
  font-size: var(--dds-font-size-2xs);
  font-variant-numeric: tabular-nums;
  color: var(--dds-color-text-muted);
}

/* =============================================================================
   Code view
   =============================================================================

   The markup behind a specimen, in a collapsible block.

   Generated from the live DOM rather than maintained by hand. A hand-written
   code sample beside a live demo is two sources of truth, and the sample is
   always the one that goes stale — usually silently, and usually in the ARIA
   attributes, which is the part somebody is most likely to copy without
   checking.
   ============================================================================= */

.ref-codeview {
  margin-block-start: var(--dds-space-sm);
  border: var(--dds-border-thin) solid var(--dds-color-border-subtle);
  border-radius: var(--dds-radius-md);
  background-color: var(--dds-color-surface-default);
}

.ref-codeview > summary {
  display: flex;
  align-items: center;
  gap: var(--dds-space-xs);

  padding: var(--dds-space-xs) var(--dds-space-sm);
  min-block-size: 2.5rem;

  font-size: var(--dds-font-size-sm);
  font-weight: var(--dds-font-weight-medium);
  color: var(--dds-color-text-link);
  cursor: pointer;
  list-style: none;
  border-radius: var(--dds-radius-md);
}

.ref-codeview > summary::-webkit-details-marker {
  display: none;
}

.ref-codeview > summary:hover {
  background-color: var(--dds-color-surface-hover);
}

.ref-codeview-marker {
  transition: rotate var(--dds-duration-fast) var(--dds-ease-standard);
}

.ref-codeview[open] .ref-codeview-marker {
  rotate: 180deg;
}

.ref-codeview-body {
  padding: 0 var(--dds-space-sm) var(--dds-space-sm);
}

.ref-codeview pre {
  margin: 0;
  max-block-size: 28rem;
  overflow: auto;
  padding: var(--dds-space-sm);
  background-color: var(--dds-color-surface-sunken);
  border-radius: var(--dds-radius-sm);
  font-size: var(--dds-font-size-xs);
  tab-size: 2;
}

.ref-codeview-actions {
  display: flex;
  justify-content: flex-end;
  padding-block-start: var(--dds-space-2xs);
}

/* =============================================================================
   Mobile behaviour note
   =============================================================================

   A fixed place for the sentence describing what a component does at narrow
   widths.

   A fixed location, rather than "somewhere in the prose", because the source
   this was learned from had the note in maybe a third of its components,
   scattered between body text, do/don't blocks and nowhere. A consistent slot
   is what makes its absence visible.
   ============================================================================= */

/* A note is a BLOCK, and that is a bug fix rather than a preference.
   ----------------------------------------------------------------------------
   It used to be `display: flex` with a `gap`, to sit the icon beside the text.
   Flex makes every child a flex item — including each inline element and each run
   of text between them. A sentence containing four `<code>` spans became eleven
   flex items with a gap between all of them: four boxed numbers strewn across two
   ragged columns, with the sentence broken around them.

   It looked like a font or wrapping problem, which is why it survived a long time.
   The cause is that flex does not lay out text; it lays out boxes.

   So the note is block, text flows the way text does, and the icon is taken out of
   flow entirely — it cannot make items out of anything if it is not in the flow. */
.ref-note {
  display: block;
  position: relative;

  margin-block-start: var(--dds-space-sm);
  padding: var(--dds-space-xs) var(--dds-space-sm);

  font-size: var(--dds-font-size-sm);
  color: var(--dds-color-text-subtle);

  background-color: var(--dds-color-surface-sunken);
  border-inline-start: var(--dds-border-thick) solid var(--dds-color-border-default);
  border-radius: var(--dds-radius-sm);
}

/* Room for the icon, but only where there is one — most notes lead with a heading
   instead, and an empty indent on those reads as a mistake. */
.ref-note:has(> .dds-icon) {
  padding-inline-start: calc(var(--dds-space-sm) + 1.6em);
}

.ref-note > .dds-icon {
  position: absolute;
  inset-inline-start: var(--dds-space-sm);
  /* Optically aligned to the first line's cap height rather than its box. */
  inset-block-start: calc(var(--dds-space-xs) + 0.2em);
  color: var(--dds-color-text-muted);
}

/* =============================================================================
   Page layout with a side navigation
   =============================================================================

   Every reference page carries an "On this page" navigation beside the content.
   It is generated by `scripts/sync-reference-toc.mjs` from the page's own
   sections, so it cannot drift from what is actually there.

   The aside comes FIRST in the DOM. On a narrow screen it therefore appears
   above the content, which is where a reader expects a contents list — and it
   means reading order matches visual order at both widths with no `order`
   juggling and no invisible tab stops.

   It is a plain, always-visible list rather than a collapsible one. A
   `<details>` would be tidier on a phone, but hiding a contents list behind a
   control that only exists at one width is exactly the kind of state that
   desynchronises on resize. Eight links are not worth that.
   ============================================================================= */

/* The track is constrained at EVERY width, not only where there are two of them.
   ----------------------------------------------------------------------------
   `display: grid` with no template gives one implicit `auto` track, and an `auto`
   track cannot be narrower than the min-content of what is in it. So a single
   descendant that refuses to become narrow — a table without its scroll region, a
   `max-content` column, a long unbroken identifier — made this track wider than
   the phone, and `.ref-content` was stretched to match.

   Everything inside then laid itself out against that inflated width. The colour
   swatch grids computed several columns and put the later ones off-screen, which
   read as a wrapping bug in a grid that was wrapping perfectly correctly: a
   measured page on a phone was about three times the width of the screen, and
   every section on it ended at the same right edge. One overflowing element, a
   page-wide symptom, and eight components that each looked individually broken.

   `minmax(0, 1fr)` on the track and `min-inline-size: 0` on the two items is the
   pair that stops it — both are needed, because a grid item's own automatic
   minimum is its content as well, so constraining only the track moves the
   inflation one level down instead of ending it.

   The consequence is deliberate: an element that is genuinely too wide now
   overflows ITSELF and is the only thing that scrolls. Whether it scrolls
   gracefully is that element's own responsibility — see the table's scroll
   region. */
.ref-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--dds-space-lg);
}

.ref-layout > * {
  min-inline-size: 0;
}

.ref-aside {
  /* Compact on narrow screens: the list sits above the content, so it should
     not consume the whole first screen. */
  padding: var(--dds-space-sm) var(--dds-space-md);
  background-color: var(--dds-color-surface-sunken);
  border: var(--dds-border-thin) solid var(--dds-color-border-subtle);
  border-radius: var(--dds-radius-md);
}

/* Two columns once there is genuinely room. A media query is correct here,
   unlike inside a component: this is the page shell, so the viewport IS what it
   depends on. */
/* Wide enough for the header to hold both rows without a disclosure. Chosen to match
   the shell's own two-column threshold, so the header and the content change shape at
   the same moment rather than one at a time. */
@media (min-width: 64rem) {
  .ref-nav-toggle {
    display: none;
  }

  /* Beats the `hidden` attribute, which the toggle sets and which is meaningless once
     the rows are inline. Without this, resizing a window while collapsed would leave
     the navigation unreachable — the trap the site header component documents. */
  /* Beats the `hidden` attribute, which the toggle sets and which is meaningless once
     the rows are inline. Without this, resizing a window while collapsed would leave
     the navigation unreachable — the trap the site header component documents. */
  .ref-nav-panel,
  .ref-nav-panel[hidden] {
    /* Back in flow, and no longer an overlay. */
    position: static;
    padding: 0;
    background: none;
    border-block-end: 0;
    box-shadow: none;

    display: flex;
    flex-basis: auto;
    /* Stacked, not side by side. Two levels in one row read as one long list again —
       which is the flattening this restructuring was meant to undo, and it left the
       active first-level item with nothing to be the parent OF. */
    flex-direction: column;
    align-items: flex-end;
    gap: 0;
    margin-inline-start: auto;

    /* Room for the second row whether or not this page has one.
       ----------------------------------------------------------------------
       Three of the pages are a group of one and get no second row. Without a
       reserved height the header changed size when moving between them — and it
       is sticky, so the whole page shifted under the pointer on every
       navigation.

       Reserving is better than the alternatives: giving those pages a second row
       containing only themselves is a choice that is not a choice, and
       restructuring the groups so none has a single child would distort the
       structure to serve a layout constraint. Calculated from the same values the
       rows are built from, so it tracks a change to either. */
    min-block-size: calc(
      var(--ref-row) + var(--dds-space-2xs) + var(--dds-space-2xs) +
      var(--dds-border-thin) + 2rem
    );
    /* Pinned to the top of the reserved box, not centred in it.
       ----------------------------------------------------------------------
       Centring kept the box the same height and moved its contents: on a page
       with a second row the pair was centred as a pair, on a page without it the
       single row was centred alone — so the first-level items sat at a different
       height depending on which page you were on, and moved as you navigated.

       Fixing the container's height without fixing the position of what is inside
       it solved half the problem and left the visible half. Top-aligned, the first
       row is at the same place on all eight pages and the reserved space below is
       either the second row or nothing. */
    justify-content: flex-start;
  }

  /* The second row sits directly under its parent, sharing an edge with it. */
  .ref-nav-secondary {
    padding-inline-start: 0;
    border-inline-start: 0;
    border-block-start: var(--dds-border-thin) solid var(--dds-color-border-subtle);
    padding-block-start: var(--dds-space-2xs);
    margin-block-start: var(--dds-space-2xs);
  }

  .ref-layout {
    grid-template-columns: 15rem minmax(0, 1fr);
    gap: var(--dds-space-2xl);
    align-items: start;
  }

  .ref-aside {
    position: sticky;
    /* Clear of the sticky page header. */
    inset-block-start: 4.5rem;
    max-block-size: calc(100svh - 6rem);
    overflow-y: auto;
    /* The shell's own copy of what `.dds-toc-sticky` carries: contain the
       scroll chain, and reserve the scrollbar so the entries do not shift. */
    overscroll-behavior: contain;
    scrollbar-gutter: stable;

    /* At this width the list is furniture, not a card. */
    padding: 0;
    background: none;
    border: 0;
  }
}

/* The generated list itself reuses the DDS table-of-contents component, so the
   active-section highlighting and its `aria-current="location"` semantics come
   from the system rather than from this page. */
