/* ==========================================================================
   Deepinfo Docs — chrome, prose and shared components.
   Reference-page components live in reference.css (ref- prefix).
   ========================================================================== */

/* ---------- base ----------
   Signal (docs/DESIGN-SIGNAL.md §2, §5): Onest for everything that is not data, Spline Sans
   Mono for data and code; running text in fg-2, headings in fg; weights 400 to 600 only. */
*,
*::before,
*::after {
  box-sizing: border-box;
}
html {
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: calc(var(--header-h) + 16px);
  /* a control reached by Tab from below the fold stops 8px above the window's edge, so the
     bottom of its focus ring (2px, 3px out) shows */
  scroll-padding-bottom: 8px;
  background: var(--bg);
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--fg-2);
  font-family: var(--sans);
  font-size: var(--fs-base);
  font-weight: 400;
  line-height: 1.65;
  letter-spacing: -0.012em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-wrap: break-word;
}
/* zero specificity: every component's own rule wins */
:where(h1, h2, h3, h4, h5, h6) {
  color: var(--fg);
  font-weight: 600;
}
:where(b, strong, th) {
  font-weight: 600;
}
a {
  color: inherit;
  text-decoration: none;
}
button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}
code,
pre,
samp {
  font-family: var(--mono);
  letter-spacing: 0;
  font-variant-ligatures: none;
  font-feature-settings: 'liga' 0, 'calt' 0;
}
img,
svg {
  display: block;
  max-width: 100%;
}
svg {
  flex: none;
}
/* the focus ring is never removed: 2px of the depth's accent (moss, lime on the dark depths
   and in code panels, white on the closing card), 3px out */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
/* A code block that scrolls (docs.js markScrollers: tabindex="0", data-scroller) is flush with
   a panel that clips (.code-block, .ref-card, .home-qs: overflow hidden or auto), so a ring 3px
   out would be cut on every side: the ring is drawn inside it instead, in the panel's lime
   (docs/DESIGN-SIGNAL.md §12, focus rings; a reference card rings itself: "code blocks"). */
pre[data-scroller]:focus-visible {
  outline-offset: -2px;
}
/* Try It's response body (assets/js/tryit.js) is focusable from the start, so markScrollers
   leaves it alone; it sits flush in its own clipping .code-block like any scrolling code */
.ref-tryit-body > pre:focus-visible {
  outline-offset: -2px;
}
/* A reference card's scrolling parts that are not a <pre> (docs.js markScrollers): the request
   card's panel (taller than 42vh) and a response card that scrolls itself. Both are flush with
   the card, which clips: the ring is drawn inside (the card's own, below, where :has works). */
.tab-panel[data-scroller]:focus-visible {
  outline-offset: -2px;
}
.ref-card-res[data-scroller]:focus-visible {
  outline-offset: -2px;
}
[hidden] {
  display: none !important;
}
::selection {
  background: var(--selection);
}

.skip {
  position: absolute;
  left: 12px;
  top: -80px;
  z-index: 100;
  background: var(--solid-bg);
  color: var(--solid-fg);
  padding: 10px 14px;
  border-radius: var(--radius);
  box-shadow: var(--sheet-shadow);
  font-size: var(--fs-md);
  font-weight: 600;
  letter-spacing: -0.01em;
}
.skip:focus {
  top: 12px;
}
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
/* the inline lockup (build/brand.mjs lockup()): the mark and "Deepinfo" in --logo-fg (moss on
   light grounds, white on dark), "| Docs" in --logo-suffix */
svg.logo {
  color: var(--logo-fg);
}
svg.logo .logo-suffix {
  color: var(--logo-suffix);
}
/* icons (build/brand.mjs icon()): Signal's hairline set, 16px grid, 1.3px stroke in
   currentColor; the dot and the triangle are filled */
.ico {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.3;
}
.ico.i-dot,
.ico.i-triangle {
  fill: currentColor;
  stroke: none;
}

/* ---------- method + status pills ----------
   A method is a soft chip: bold text in the method's colour on a tint of it (tokens.css
   "HTTP method chips"; maintainer feedback, 2026-10-03, replacing Signal's outlined chip,
   docs/DESIGN-SIGNAL.md §13). GET teal, POST blue, PUT amber, PATCH violet, DELETE red; an
   unknown method (.method-other) neutral. Inside a code panel (dark on every depth) the dark
   set is used. An HTTP status always says its code and its word ("200 OK", "400 Bad
   Request"): a 2xx in `ok`, everything else neutral; the exposure colour is never a status. */
.method {
  --m: var(--m-other);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 20px;
  min-width: 38px;
  padding: 0 7px;
  border: 0;
  border-radius: var(--radius-tag);
  background: color-mix(in srgb, var(--m) 13%, transparent);
  color: var(--m);
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  line-height: 1;
  white-space: nowrap;
}
.method-get {
  --m: var(--m-get);
}
.method-post {
  --m: var(--m-post);
}
.method-put {
  --m: var(--m-put);
}
.method-patch {
  --m: var(--m-patch);
}
.method-delete {
  --m: var(--m-delete);
}
.method-lg {
  height: 24px;
  min-width: 46px;
  padding: 0 9px;
  font-size: 12px;
}
:is(.code-block, .code-panel, .ref-card, .ref-tryit, .home-qs) .method {
  --m: var(--m-other-d);
  background: color-mix(in srgb, var(--m) 18%, transparent);
}
:is(.code-block, .code-panel, .ref-card, .ref-tryit, .home-qs) .method-get {
  --m: var(--m-get-d);
}
:is(.code-block, .code-panel, .ref-card, .ref-tryit, .home-qs) .method-post {
  --m: var(--m-post-d);
}
:is(.code-block, .code-panel, .ref-card, .ref-tryit, .home-qs) .method-put {
  --m: var(--m-put-d);
}
:is(.code-block, .code-panel, .ref-card, .ref-tryit, .home-qs) .method-patch {
  --m: var(--m-patch-d);
}
:is(.code-block, .code-panel, .ref-card, .ref-tryit, .home-qs) .method-delete {
  --m: var(--m-delete-d);
}

.status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 22px;
  padding: 0 8px;
  border: 1px solid var(--rule-3);
  border-radius: var(--radius-tag);
  background: transparent;
  color: var(--fg-2);
  font-family: var(--sans);
  font-size: 11.5px;
  font-weight: 500;
  line-height: 1;
  white-space: nowrap;
}
.status b {
  font-weight: 500;
}
.status-ok {
  color: var(--ok);
  border-color: currentColor;
}
:is(.code-block, .code-panel, .ref-card, .ref-tryit, .home-qs) .status:not(.status-ok) {
  color: var(--code-tab);
  border-color: color-mix(in srgb, var(--code-fg) 40%, transparent);
}
/* a dot beside a status: a 2xx is a filled `ok` dot, anything else an empty `fg-3` ring, so
   the shape differs as well as the colour */
.dot {
  display: inline-block;
  flex: none;
  width: 7px;
  height: 7px;
  border: 1.5px solid var(--fg-3);
  border-radius: 50%;
  background: transparent;
}
.dot-ok {
  border-color: var(--ok);
  background: var(--ok);
}

/* ---------- header ---------- */
/* Signal Header on the chrome depth (build/layout.mjs: data-depth="surface", sage; the dark
   chrome in the dark theme): 64px on every width, a hairline under it, a plain ground (no
   glass: the chrome sits on its own depth, never over the content). */
.topbar {
  position: sticky;
  top: 0;
  z-index: 40;
  height: var(--header-h);
  display: flex;
  align-items: center;
  background: var(--bg);
  color: var(--fg);
  border-bottom: 1px solid var(--rule);
}
.brand {
  flex: none;
  width: var(--sidebar-w);
  height: 100%;
  display: flex;
  align-items: center;
  padding-left: 24px;
}
/* The link fills the header's height from the window's left edge, so a ring round the link
   would sit off-canvas at the top and left: the ring goes round the lockup instead, the same
   2px 3px out (the link keeps its large target). */
.brand:focus-visible {
  outline: none;
}
.brand:focus-visible .logo {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}
/* the lockup (build/brand.mjs lockup(); its colours: docs.css base) at 24px. On phones it
   narrows to 290/56, the mark and "Deepinfo" (Responsive, 560px) */
.brand .logo,
.footer-logo .logo,
.drawer-head .logo {
  display: block;
  flex: none;
  height: 24px;
  width: auto;
  max-width: none;
  aspect-ratio: 460 / 56;
}

/* the three tabs: text only (Signal), the current one in fg with a 2px hi line on the
   header's bottom edge */
.areas {
  display: flex;
  align-items: stretch;
  height: 100%;
  gap: var(--s-6);
  padding-left: var(--gutter);
}
.area {
  position: relative;
  display: flex;
  align-items: center;
  font-size: var(--fs-md);
  font-weight: 500;
  letter-spacing: -0.005em;
  white-space: nowrap;
  color: var(--fg-2);
  transition: color 0.2s var(--ease);
}
.area:hover,
.area[aria-current] {
  color: var(--fg);
}
.area[aria-current]::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: var(--hi);
}
/* A tab is as tall as the header and starts at the window's top edge, so a ring round the
   link would lose its top edge off-canvas: the ring goes round its label instead, the same
   2px, 3px out, as the lockup's (.brand); the link keeps its full-height target. */
.area:focus-visible {
  outline: none;
}
.area:focus-visible > span {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

.top-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--s-2);
  padding-right: 20px;
  min-width: 0;
}
/* the search field that opens the palette: a panel on the sage, "Search" in fg-3 and ⌘K */
.search-trigger {
  position: relative;
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--s-2);
  width: 240px;
  height: 36px;
  padding: 0 7px 0 11px;
  border: 1px solid var(--rule-2);
  border-radius: var(--radius);
  background: var(--panel);
  color: var(--fg-3);
  font-size: var(--fs-md);
  font-weight: 400;
  text-align: left;
  transition: border-color 0.2s var(--ease);
}
.search-trigger:hover {
  border-color: var(--rule-3);
}
.search-trigger .search-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* a key hint (⌘K, ↑ ↓ ↵ esc) is interface text: Onest, like every label outside code */
kbd {
  font-family: var(--sans);
  height: 20px;
  padding: 0 6px;
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--rule-2);
  border-radius: 5px;
  background: var(--panel);
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: 1;
  color: var(--fg-3);
}
.icon-btn {
  width: 36px;
  height: 36px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius);
  color: var(--fg-3);
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}
.icon-btn:hover {
  background: var(--panel);
  color: var(--fg);
}
.theme-btn .i-sun {
  display: none;
}
:root[data-theme='dark'] .theme-btn .i-sun {
  display: block;
}
:root[data-theme='dark'] .theme-btn .i-moon {
  display: none;
}
/* "Sign in": a small line button (.btn.btn--line.btn--sm, the "hero (home)" section) */
.top-actions > .btn-login {
  flex: none;
  margin-left: 4px;
  white-space: nowrap;
}
.menu-btn {
  display: none;
}

/* ---------- environment switch (the API Reference sidebar) ----------
   A radio group: Production (default) / Demo, at the top of the sidebar of the pages it
   changes (build/layout.mjs drawerChrome; maintainer feedback, 2026-10-03). Shown only when
   scripts run (theme.js adds html.js); the hosts in its panel are filled in by docs.js. The
   chosen option is a filled chip (a white panel on the sage) with a hi dot. Demo takes no
   status colour: it is not a state, the word says it (.env.is-alt stays for the script). The
   label and the info button share the first row; the two options fill the second; the host
   list opens in place under them, inside the sidebar. */
/* it stays in view while the sidebar scrolls (and when it opens scrolled to the current
   page), so every API page shows which environment its samples use; keyboard focus scrolls
   rows clear of it (scroll-padding-top) */
.sidebar-env {
  position: sticky;
  /* a sticky box in a scroller sticks inside its padding: lift it by the sidebar's top padding */
  top: calc(-1 * var(--s-5));
  z-index: 3;
  margin: calc(-1 * var(--s-5)) -14px var(--s-3) -16px;
  padding: var(--s-5) 14px var(--s-4) 16px;
  border-bottom: 1px solid var(--rule);
  background: var(--bg);
}
.sidebar:has(.sidebar-env) {
  scroll-padding-top: 128px;
}
html:not(.js) .sidebar-env {
  display: none;
}
.env {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 6px 4px;
}
html:not(.js) .env {
  display: none;
}
.env-label {
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-3);
  white-space: nowrap;
}
.env-label {
  grid-column: 1;
  grid-row: 1;
  padding-left: 2px;
}
.env-info {
  grid-column: 2;
  grid-row: 1;
}
.env-pop {
  grid-row: 3;
}
.env-seg {
  grid-column: 1 / -1;
  grid-row: 2;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: center;
  gap: 2px;
  height: 36px;
  padding: 3px;
  border: 1px solid var(--rule-2);
  border-radius: var(--radius);
}
.env-opt {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  height: 28px;
  padding: 0 10px;
  border: 1px solid transparent;
  border-radius: 7px;
  font-size: var(--fs-sm);
  font-weight: 500;
  letter-spacing: -0.005em;
  white-space: nowrap;
  color: var(--fg-2);
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.env-opt::before {
  content: '';
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  border: 1px solid var(--rule-3);
}
.env-opt:hover {
  color: var(--fg);
}
.env-opt[aria-checked='true'] {
  background: var(--panel);
  border-color: var(--panel-bd);
  box-shadow: var(--shadow-sm);
  color: var(--fg);
}
.env-opt[aria-checked='true']::before {
  border-color: var(--hi);
  background: var(--hi);
}
.env-short {
  display: none;
}
.env-info {
  width: 28px;
  height: 28px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 7px;
  color: var(--fg-3);
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}
.env-info:hover,
.env-info[aria-expanded='true'] {
  background: var(--panel);
  color: var(--fg);
}
/* the host list: a panel (data-depth="surface-2") that opens in place under the options,
   rows on hairlines */
.env-pop {
  grid-column: 1 / -1;
  margin-top: 6px;
  padding: 12px 12px 14px;
  border: 1px solid var(--panel-bd);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--fg-2);
}
.env-pop-title {
  margin: 0 0 10px;
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.env-hosts {
  margin: 0 0 12px;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--rule-2);
}
.env-hosts li {
  border-bottom: 1px solid var(--rule);
}
/* each environment is a button: choosing it selects that environment. The hover panel sits
   behind the row, so the hairlines stay straight. */
.env-host {
  position: relative;
  isolation: isolate;
  display: grid;
  gap: 3px;
  width: 100%;
  padding: 10px 10px 10px 12px;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.env-host::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset: 3px 0;
  border-radius: 8px;
  background: var(--panel-2);
  opacity: 0;
  transition: opacity 0.2s var(--ease);
}
.env-host:hover::before {
  opacity: 1;
}
.env-host.is-current {
  box-shadow: inset 2px 0 0 var(--hi);
  cursor: default;
}
.env-host-name {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--fg);
}
/* "Selected": a filled chip (aria-pressed already says it) */
.env-host.is-current .env-host-name::after {
  content: 'Selected';
  content: 'Selected' / '';
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding: 0 7px;
  border-radius: var(--radius-tag);
  background: var(--hi);
  color: var(--accent-fg);
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.env-host code {
  padding: 0;
  background: none;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--fg-2);
  overflow-wrap: anywhere;
}
.env-pop-note {
  margin: 0 0 10px;
  font-size: var(--fs-sm);
  line-height: 1.45;
  color: var(--fg-3);
}
.env-pop .env-pop-more {
  font-size: var(--fs-md);
}

/* ---------- layout ---------- */
/* The chrome (header, sidebar, footer) is on the surface depth; the columns between them are
   the reading content, on the root depth (white; deep in the dark theme). */
.layout {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  min-height: calc(100vh - var(--header-h));
}
.layout-nosidebar {
  grid-template-columns: minmax(0, 1fr);
}
/* the content column: page body on top, footer pinned underneath it */
.page-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
/* content pages: prose + right-hand TOC */
.page-body {
  flex: 1 1 auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--toc-w);
  align-items: start;
  min-width: 0;
}
.page-body-wide {
  grid-template-columns: minmax(0, 1fr);
}
/* reference pages bring their own two-pane layout (reference.css): the
   container gets out of the way completely so that grid can size itself. */
.page-body-ref {
  display: block;
  min-width: 0;
}
/* The one-column reference bodies (/reference/ and the module pages) have no code column to
   fill the right-hand side. When they have enough headings they get the same "On This Page"
   rail as a content page … */
.page-body-ref-toc {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--toc-w);
  align-items: start;
}
/* … and when they do not, the column is centred instead of being pinned to the
   left of a few hundred pixels of empty space. */
.page-body-ref-wide:not(.page-body-ref-toc) .ref-main {
  margin-inline: auto;
  /* an auto-margined grid item shrinks to fit its content and would grow past a phone with a
     wide table (QA: the WHOIS index at 439 px in a 375 px viewport); max-width still centres it */
  width: 100%;
}

/* ---------- sidebar ---------- */
/* The chrome depth (data-depth="surface": sage; the dark chrome in the dark theme). Hover and
   the current page put a panel behind the row (white on the sage), the current page adds a
   2px hi bar; no gradient, no counts (Signal: no numbers on a rail). */
.sidebar {
  position: sticky;
  top: var(--header-h);
  height: calc(100vh - var(--header-h));
  overflow-y: auto;
  overscroll-behavior: contain;
  border-right: 1px solid var(--rule);
  padding: var(--s-5) 14px 56px 16px;
  scrollbar-width: thin;
  scrollbar-color: var(--rule-2) transparent;
  background: var(--bg);
  color: var(--fg-2);
}
.drawer-head,
.drawer-areas,
.drawer-foot {
  display: none;
}
.nav-group + .nav-group {
  margin-top: 14px;
}
.nav-group-btn {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  min-height: 32px;
  padding: 4px 8px;
  border-radius: 8px;
  font-size: var(--fs-md);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--fg);
  text-align: left;
  transition: background-color 0.2s var(--ease);
}
.nav-group-btn:hover {
  background: var(--panel);
}
/* the chevron: a CSS mask (build/brand.mjs maskUrl('chevron')), so no SVG is repeated per
   group (build/layout.mjs); a quarter turn when the group is open */
.nav-group-btn::after {
  content: '';
  flex: none;
  width: 16px;
  height: 16px;
  background: var(--fg-3);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M6 3.5 10.5 8 6 12.5' fill='none' stroke='%23000' stroke-width='1.3'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M6 3.5 10.5 8 6 12.5' fill='none' stroke='%23000' stroke-width='1.3'/%3E%3C/svg%3E") center / contain no-repeat;
}
.nav-group-btn[aria-expanded='true']::after {
  transform: rotate(90deg);
}
@media screen and (prefers-reduced-motion: no-preference) {
  .nav-group-btn::after {
    transition: transform 0.2s var(--ease-out);
  }
}
.nav-group.is-collapsed + .nav-group.is-collapsed {
  margin-top: 2px;
}
/* Category icons (build/module-groups.mjs CATEGORY_ICONS): 24×24 line drawings, stroked
   here. In the sidebar every top-level entry carries one (an API module, Getting Started,
   API Overview, a Platform Guide section; maintainer feedback, 2026-10-03), in fg-3, hi when
   the entry holds the current page. */
.cat-ico {
  flex: none;
  width: 24px;
  height: 24px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.nav-cat-ico {
  width: 18px;
  height: 18px;
  color: var(--fg-3);
  transition: color 0.2s var(--ease);
}
.nav-group-btn.has-ico,
.nav-top .nav-list a.has-ico {
  justify-content: flex-start;
  gap: 10px;
}
.nav-group-btn.has-ico > span {
  flex: 1;
  min-width: 0;
}
.nav-group-btn.has-ico:hover .nav-cat-ico,
.nav-group.is-active > .nav-group-btn .nav-cat-ico,
.nav-top a[aria-current] .nav-cat-ico {
  color: var(--hi);
}
/* the top-level pages of a sidebar (API Overview): set like the group headers beside them,
   without the guide line */
.nav-top > .nav-list {
  margin-left: 0;
  border-left: 0;
}
.nav-top > .nav-list > li::before,
.nav-top > .nav-list > li::after {
  display: none;
}
.nav-top > .nav-list a {
  padding-left: 8px;
  margin-left: 0;
  border-left: 0;
  border-radius: 8px;
  font-weight: 600;
  color: var(--fg);
}
.nav-top > .nav-list a[aria-current='page'],
.nav-top > .nav-list a[aria-current='true'] {
  border-left: 0;
  padding-left: 8px;
}
/* a closed module on a worked example page is one link to its Overview (build/layout.mjs
   renderTreeGroup `prune`): it looks like the group button it stands for */
.nav-group-link {
  text-decoration: none;
}
/* a section label between groups (API Reference: "DSI · Deep Search & Insights", "Platform
   APIs"): Signal's label, uppercase by CSS only */
.nav-section {
  margin: var(--s-5) 0 6px;
  padding: 0 8px;
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.nav-empty {
  margin: 0;
  padding: 4px 8px;
  font-size: var(--fs-md);
  color: var(--fg-3);
}
/* Without JavaScript the headers cannot toggle, so the whole tree is shown open
   (theme.js marks a scripted page with html.js). */
html:not(.js) .sidebar .nav-list[hidden] {
  display: block !important;
}
html:not(.js) .nav-group-btn {
  cursor: default;
}
html:not(.js) .nav-group-btn::after {
  display: none;
}
/* A group inside a module (EASM › Assets): a quieter header, indented like a link */
.nav-list .nav-group-btn {
  min-height: 30px;
  padding: 4px 8px 4px 14px;
  font-weight: 500;
  color: var(--fg-2);
  border-radius: 0 8px 8px 0;
}
.nav-list .nav-group-btn:hover {
  color: var(--fg);
}
.nav-list > .nav-group + li,
.nav-list > li + .nav-group {
  margin-top: 2px;
}
/* the module that holds the current page: its chevron takes hi */
.nav-group.is-active > .nav-group-btn::after {
  background: var(--hi);
}
/* Branch lines (the "branched menu", maintainer feedback 2026-10-03): a trunk down a group's
   list and a rounded elbow from it to each row, drawn per row so wrapped labels and nested
   groups keep their place. The path to the current page (the trunk above it and its elbow,
   through every nested group) is drawn in hi, growing once from the top when the page opens.
   Without :has() the path stays in the line colour; the current row is still marked. */
.nav-list {
  list-style: none;
  margin: 4px 0 0 8px;
  padding: 0;
}
.nav-list > li {
  position: relative;
}
/* the elbow: down the trunk to the row's first line (8px straight, a 7px quarter turn), then
   into the row */
.nav-list > li::before {
  content: '';
  position: absolute;
  z-index: 2; /* over the rows' panels (the current row's, the glide panel's) */
  left: 0;
  top: 0;
  width: 9px;
  height: 15px;
  border-left: 1px solid var(--rule-2);
  border-bottom: 1px solid var(--rule-2);
  border-bottom-left-radius: 7px;
  pointer-events: none;
}
/* the trunk on to the next row; on a row it runs past, the trunk owns the line's column and
   the elbow keeps only its turn, so no stretch is drawn twice */
.nav-list > li:not(:last-child)::after {
  content: '';
  position: absolute;
  z-index: 2;
  left: 0;
  top: 0;
  bottom: 0;
  border-left: 1px solid var(--rule-2);
  pointer-events: none;
}
.nav-list > li:not(:last-child)::before {
  clip-path: inset(0 0 0 1px);
}
/* a group row and its neighbours are 2px apart: the trunk bridges the gap */
.nav-list > li:has(+ .nav-group)::after,
.nav-list > li.nav-group:has(+ li)::after {
  bottom: -2px;
}
/* an endpoint whose Examples leaf ends the list: the trunk stops at its turn */
.nav-list > li:has(+ li.nav-sub:last-child)::after {
  bottom: auto;
  height: 8px;
}
/* an endpoint's "Examples" leaf hangs from its endpoint's row, a step further in */
.nav-list > li.nav-sub::before {
  left: 12px;
  height: 13px;
  clip-path: none; /* off the trunk: nothing to share */
}
/* the trunk runs on past it unbroken: its elbow is not on the trunk */
.nav-list > li.nav-sub:not(:last-child)::after {
  top: 0;
}
/* the path to the current page: the trunk above it and its elbow, through nested groups */
.nav-list > li:has(~ li [aria-current])::after {
  border-left-color: var(--hi);
}
.nav-list > li:has([aria-current])::before {
  border-color: var(--hi);
  clip-path: none;
}
/* the current row's own trunk goes on below its turn, in the line colour */
.nav-list > li:has([aria-current]):not(:last-child)::after {
  top: 8px;
}
/* on an example page the path turns into the endpoint's row, then down to its Examples leaf */
.nav-list > li:has(+ li.nav-sub [aria-current])::before {
  border-color: var(--hi);
  clip-path: none;
}
.nav-list > li:has(+ li.nav-sub [aria-current])::after {
  top: 8px;
  border-left-color: var(--rule-2);
}
@media screen and (prefers-reduced-motion: no-preference) {
  .nav-list > li:has(~ li [aria-current])::after {
    animation: nav-trunk 0.4s cubic-bezier(0.23, 1, 0.32, 1) both;
  }
  /* a fold's neighbours move with it */
  .nav-group {
    transition: margin-top 0.3s cubic-bezier(0.23, 1, 0.32, 1);
  }
  .nav-list > li:has([aria-current])::before {
    animation: nav-elbow 0.3s cubic-bezier(0.23, 1, 0.32, 1) 0.25s both;
  }
  /* a fold: the list's height, 300ms (assets/js/docs.js navGroups) */
  .nav-list.is-folding {
    overflow: hidden;
    transition: height 0.3s cubic-bezier(0.23, 1, 0.32, 1);
  }
}
/* the path takes its colour once, as the page opens: the line is never broken */
@keyframes nav-trunk {
  from {
    border-left-color: var(--rule-2);
  }
}
@keyframes nav-elbow {
  from {
    clip-path: inset(0 100% 0 0);
  }
  to {
    clip-path: inset(0 0 0 0);
  }
}
/* the glide panel (assets/js/docs.js navGlide): one hover panel that moves to the row under
   the pointer; the rows' own hover panels step aside while it is there */
.nav-glide {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 0;
  width: 0;
  height: 0;
  border-radius: 8px;
  background: var(--panel);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.15s ease;
}
.nav-glide.is-on {
  opacity: 1;
}
@media screen and (prefers-reduced-motion: no-preference) {
  .nav-glide {
    transition:
      transform 0.22s cubic-bezier(0.23, 1, 0.32, 1),
      width 0.22s cubic-bezier(0.23, 1, 0.32, 1),
      height 0.22s cubic-bezier(0.23, 1, 0.32, 1),
      opacity 0.15s ease;
  }
  .nav-glide.is-jump {
    transition: opacity 0.15s ease;
  }
}
.sidebar.has-glide .nav-list a,
.sidebar.has-glide .nav-group-btn {
  position: relative;
  z-index: 1;
}
.sidebar.has-glide .nav-list a:hover:not([aria-current]),
.sidebar.has-glide .nav-group-btn:hover {
  background: transparent;
}
.nav-list a {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  min-height: 30px;
  padding: 4px 8px 4px 14px;
  margin-left: -1px;
  border-left: 1px solid transparent;
  border-radius: 0 8px 8px 0;
  font-size: var(--fs-md);
  font-weight: 400;
  line-height: 1.35;
  color: var(--fg-2);
  transition: color 0.2s var(--ease), background-color 0.2s var(--ease);
}
.nav-list a:hover {
  color: var(--fg);
  background: var(--panel);
}
.nav-list a[aria-current='page'],
.nav-list a[aria-current='true'] {
  color: var(--fg);
  font-weight: 600;
  background: var(--panel);
}
/* An endpoint's "Examples" leaf (build/reference.mjs withExamplesLeaf): indented under the
   endpoint. aria-current="true" marks it on the example pages it stands for (they are not in
   the sidebar themselves). */
.nav-list > li.nav-sub > a {
  min-height: 26px;
  padding-left: 26px;
  font-size: var(--fs-sm);
}
.nav-list > li.nav-sub > a[aria-current] {
  padding-left: 26px;
}
.nav-list .nav-methods {
  display: inline-flex;
  gap: 4px;
  flex: none;
}
/* method chips on the rail: 18px (the chip itself: "method + status pills") */
.nav-list .method {
  height: 18px;
  min-width: 32px;
  padding: 0 5px;
  font-size: 10px;
}
.nav-list .nav-list {
  margin-left: 8px;
}
/* Deprecated / Beta on a sidebar leaf (build/layout.mjs leafItem, NavNode.badges): a neutral
   tag with the word, on its own line under the label (never colour alone), so the label keeps
   the width it has without it (the method chip stays on the first line). */
.nav-list a.has-badges {
  flex-wrap: wrap;
  row-gap: 3px;
}
.nav-list a.has-badges > .nav-badges {
  order: 2;
  flex-basis: 100%;
  display: flex;
  gap: 4px;
}
.nav-badge {
  display: inline-flex;
  align-items: center;
  height: 18px;
  padding: 0 6px;
  border: 1px solid var(--rule-2);
  border-radius: var(--radius-tag);
  background: var(--panel);
  color: var(--fg-2);
  font: 600 10px/1 var(--sans);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}
/* Sidebar labels wrap in full, however many lines they take: a clamp hid the end of a long
   label once a reader raised text spacing (WCAG 1.4.12), and the title that carried the full
   name reaches neither keyboard nor touch. build/layout.mjs gives a shortened label (its nav
   title) the full name as its title. */
.nav-list a > span:first-child,
.nav-group-btn > span {
  min-width: 0;
  overflow-wrap: break-word;
}

/* ---------- main column ---------- */
.main {
  min-width: 0;
  padding: 40px var(--gutter) 96px;
}
.prose-inner {
  max-width: var(--measure-wide);
}
/* Breadcrumbs (Signal; build/layout.mjs renderBreadcrumbs): the page's ancestors only, never
   the page itself, no aria-current. Mono 11px uppercase (CSS only), each link fg-3 with a 1px
   rule-3 underline 5px below; "›" between two ancestors, in the sans, fg-4, hidden from
   screen readers. The separator ends the item before it, so a trail that wraps never starts
   its second line with one. */
.crumbs {
  margin: 0 0 var(--s-4);
}
.crumbs ol {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: 1.6;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.crumbs li {
  display: flex;
  align-items: center;
  gap: 10px;
}
.crumbs li:not(:last-child)::after {
  content: '›';
  content: '›' / '';
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 400;
  line-height: 1;
  letter-spacing: 0;
  color: var(--fg-4);
}
.crumbs a {
  color: var(--fg-3);
  text-decoration: underline;
  text-decoration-color: var(--rule-3);
  text-decoration-thickness: 1px;
  text-underline-offset: 5px;
  transition: color 0.2s var(--ease), text-decoration-color 0.2s var(--ease);
}
.crumbs a:hover {
  color: var(--fg);
  text-decoration-color: currentColor;
}
/* inside .prose the list and link rules must not reach the breadcrumbs */
.prose .crumbs ol {
  margin: 0;
  padding: 0;
  color: var(--fg-3);
}
.prose .crumbs li {
  margin: 0;
  padding: 0;
}
.prose .crumbs li::before {
  content: none;
}
/* (0,3,1): above the prose link rule */
.prose .crumbs a[href] {
  color: var(--fg-3);
  font-weight: inherit;
  text-decoration-line: underline;
  text-decoration-color: var(--rule-3);
  text-decoration-thickness: 1px;
  text-underline-offset: 5px;
}
.prose .crumbs a[href]:hover {
  color: var(--fg);
  text-decoration-color: currentColor;
}
/* breadcrumbs → h1: 16px (the trail's own margin) */
.prose .crumbs + h1,
.prose .crumbs + .draft-banner {
  margin-top: 0;
}

/* ---------- prose ----------
   Signal's type, scaled to a documentation column (docs/DESIGN-SIGNAL.md §2): Onest 600
   headlines in `fg`, running text 16/1.65 in `fg-2`, list marks in `hi`, inline code as a
   `code-bg` chip. Headings keep Title Case (the titlecase gate); nothing here sets case. */
.prose h1 {
  margin: 0 0 var(--s-4);
  font-size: var(--fs-h1);
  line-height: 1.05;
  font-weight: 600;
  letter-spacing: -0.04em;
  word-spacing: -0.02em;
  text-wrap: balance;
  color: var(--fg);
}
.prose h2 {
  margin: var(--s-7) 0 var(--s-3);
  padding: 0;
  border: 0;
  font-size: var(--fs-h2);
  line-height: 1.15;
  font-weight: 600;
  letter-spacing: -0.03em;
  word-spacing: -0.02em;
  text-wrap: balance;
  color: var(--fg);
}
.prose h3 {
  margin: var(--s-6) 0 var(--s-2);
  font-size: var(--fs-h3);
  line-height: 1.3;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--fg);
}
.prose h4 {
  margin: var(--s-5) 0 var(--s-2);
  font-size: 1rem;
  line-height: 1.4;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--fg);
}
.prose > :first-child {
  margin-top: 0;
}
.heading-anchor {
  display: inline-flex;
  align-items: baseline;
  gap: var(--s-2);
  color: inherit;
}
.heading-anchor::after {
  content: '#';
  font-weight: 400;
  color: var(--fg-3);
  opacity: 0;
  transition: opacity 0.2s var(--ease);
}
.heading-anchor:hover::after,
.heading-anchor:focus-visible::after {
  opacity: 1;
}
.prose p,
.prose ul,
.prose ol {
  margin: 0 0 var(--s-4);
  color: var(--fg-2);
}
.prose ul,
.prose ol {
  padding-left: 1.4em;
}
.prose li {
  margin-bottom: var(--s-2);
}
.prose li::marker {
  color: var(--hi);
}
.prose ol > li::marker {
  font-weight: 600;
}
.prose li > ul,
.prose li > ol {
  margin: var(--s-2) 0 0;
}
.prose strong {
  font-weight: 600;
  color: var(--fg);
}
/* the lede under a page title: Signal's `lead`, one step smaller, at most a lede's measure */
.prose .lede {
  max-width: var(--measure);
  margin: 0 0 var(--s-6);
  font-size: var(--fs-lede);
  line-height: 1.55;
  letter-spacing: -0.02em;
  color: var(--fg-2);
}
.prose h1 + .lede {
  margin-top: 0;
}
.prose hr {
  margin: var(--s-7) 0;
  border: 0;
  border-top: 1px solid var(--rule);
}

/* inline code: a chip that keeps its shape when the line breaks */
.prose :not(pre) > code {
  padding: 0.1em 0.38em;
  border: 0;
  border-radius: 5px;
  background: var(--code-bg);
  font-size: 0.875em;
  font-weight: 400;
  color: var(--fg);
  overflow-wrap: anywhere;
  -webkit-box-decoration-break: clone;
  box-decoration-break: clone;
}

/* blockquote: a quotation, set off by a `hi` rule (callouts are .callout, below) */
.prose blockquote {
  margin: 0 0 var(--s-4);
  padding: 2px 0 2px var(--s-4);
  border-left: 2px solid var(--hi);
  color: var(--fg-2);
}
.prose blockquote > :last-child {
  margin-bottom: 0;
}

@media (max-width: 899px) {
  .prose h2 {
    margin-top: var(--s-6);
  }
  .prose .lede {
    margin-bottom: var(--s-5);
  }
}
/* Phones: the page title steps down from 32px to 26–30px (Signal's weight and tracking kept),
   so a long reference title ("Compromised Employee Credential Mark False Positive", "WHOIS for
   .vermögensberatung (…)") takes two or three lines at 375px instead of three or four, and the
   endpoint line and lede stay on the first screen. The token, so .prose h1 and reference.css
   .ref-head h1 both follow. */
@media (max-width: 560px) {
  :root {
    --fs-h1: clamp(1.625rem, 1.05rem + 2.4vw, 2rem);
  }
}

/* ---------- links ----------
   Signal's in-text link (docs/DESIGN-SIGNAL.md §4.1), for the whole site (reference.css uses
   the same values): the `link` colour at the text's own weight, a 1px underline at 40% of
   that colour, 0.2em below, always on, so colour is never the only cue. Hover and focus: the
   underline goes full colour and 2px; the colour stays. Visited links keep the same colour.
   Components that are links (.go, .btn, ledger rows, heading anchors, pager, breadcrumbs,
   reference components) carry a class and are left alone: only class-less links match.
   A link to another site ends in Signal's `external` mark (a CSS mask: nothing for a screen
   reader to announce). */
.prose a:not([class]),
.prose a.ref-unresolved {
  color: var(--link);
  font-weight: inherit;
  text-decoration-line: underline;
  text-decoration-thickness: 1px;
  text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);
  text-underline-offset: 0.2em;
  text-decoration-skip-ink: auto;
  transition: text-decoration-color 0.2s var(--ease), text-decoration-thickness 0.2s var(--ease);
}
.prose a:not([class]):hover,
.prose a:not([class]):focus-visible {
  text-decoration-color: currentColor;
  text-decoration-thickness: 2px;
}
.prose a:not([class])[href^='http']:not([href^='https://docs.deepinfo.com'])::after {
  content: '';
  display: inline-block;
  width: 0.7em;
  height: 0.7em;
  margin-left: 0.22em;
  vertical-align: 0.02em;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M5 3h8v8M13 3 3.5 12.5' fill='none' stroke='%23000' stroke-width='1.3'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M5 3h8v8M13 3 3.5 12.5' fill='none' stroke='%23000' stroke-width='1.3'/%3E%3C/svg%3E") center / contain no-repeat;
}
/* code inside a link is part of the link: the code chip, the text in the link colour */
.prose a:not([class]) code {
  background: var(--code-bg);
  color: inherit;
}

/* Screenshots (the Platform Guide): a panel frame, so a light screenshot does not bleed into
   the page and a dark page does not show a bare white block (§4.17). No caption line: the alt
   text says what it shows. The build writes each image's width/height (PNG header), so nothing
   shifts while it loads; a narrow crop keeps its natural size instead of being stretched. */
.prose img {
  display: block;
  max-width: 100%;
  height: auto;
  margin: var(--s-5) 0;
  border: 1px solid var(--panel-bd);
  border-radius: var(--radius-code);
  background: var(--bg-2);
  box-shadow: var(--panel-shadow);
}
:root[data-theme='dark'] .prose img {
  filter: brightness(0.92);
}

/* ---------- callouts ----------
   A callout is a panel (docs/DESIGN-SIGNAL.md §4.16): `panel` fill, a 1px `panel-bd` border,
   no tinted ground and no coloured border. A 2px bar on the left says the kind (`hi` for
   note, tip and important; `fg` for warning and caution), and the title row always writes the
   kind as a word, after a Signal mark: a dot (note, tip, important) or a triangle (warning,
   caution). Nothing rides on colour alone, and `exposure` is never used here. */
.callout {
  margin: 0 0 var(--s-4);
  padding: 16px 18px;
  border: 1px solid var(--panel-bd);
  border-left: 2px solid var(--hi);
  border-radius: var(--radius-code);
  background: var(--panel);
  box-shadow: var(--panel-shadow);
  color: var(--fg-2);
}
.callout > :last-child {
  margin-bottom: 0;
}
.prose .callout p {
  color: var(--fg-2);
}
.prose .callout .callout-title,
.callout-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 var(--s-2);
  font-family: var(--sans);
  font-size: 11px;
  line-height: 1.3;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.callout-title .ico {
  flex: none;
  width: 12px;
  height: 12px;
  fill: currentColor;
  stroke: none;
  color: var(--hi);
}
.prose .callout-important .callout-title {
  color: var(--hi);
}
.callout-warning,
.callout-caution {
  border-left-color: var(--fg);
}
.prose .callout-warning .callout-title,
.prose .callout-caution .callout-title,
.callout-warning .callout-title .ico,
.callout-caution .callout-title .ico {
  color: var(--fg);
}
.callout-warning .callout-title .ico,
.callout-caution .callout-title .ico {
  width: 13px;
  height: 13px;
}

/* ---------- tables ----------
   Signal's spec table (docs/DESIGN-SIGNAL.md §3, §4.5): hairline rows, no box, no radius, no
   fill. A `rule-2` line on top, a `rule` line under every row; column heads are labels (mono
   11px uppercase in `fg-3`); cells are padded 14px 16px 14px 0, so the first column lines up
   with the text above the table. A table wider than the column scrolls sideways inside
   .table-scroll. The reference's own tables (reference.css .ref-params) follow the same rule. */
/* 6px of room on each side, given back by the margins (the table stays where it was): the box
   scrolls, so without it the focus ring (2px, 3px out) of a link in the first or last column
   lost its outer edge */
.table-scroll {
  margin: 0 -6px var(--s-5);
  padding: 0 6px;
  overflow-x: auto;
  scrollbar-width: thin;
}
.prose table,
.table-scroll > table,
.params {
  width: 100%;
  border-collapse: collapse;
  border-spacing: 0;
  border-top: 1px solid var(--rule-2);
  font-size: var(--fs-md);
  line-height: 1.55;
  text-align: left;
}
.prose th,
.table-scroll > table th,
.params th {
  padding: 12px 16px 12px 0;
  border-bottom: 1px solid var(--rule);
  background: none;
  text-align: left;
  vertical-align: bottom;
  font-family: var(--sans);
  font-size: var(--fs-xs);
  line-height: 1.3;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-3);
  white-space: nowrap;
}
/* a row header (the first cell of a row) is a value, not a label */
.prose tbody th,
.table-scroll > table tbody th,
.params tbody th {
  padding: 14px 16px 14px 0;
  vertical-align: top;
  font-family: var(--font-sans);
  font-size: var(--fs-md);
  line-height: 1.55;
  font-weight: 600;
  letter-spacing: normal;
  text-transform: none;
  color: var(--fg);
  white-space: normal;
}
.prose td,
.table-scroll > table td,
.params td {
  padding: 14px 16px 14px 0;
  border-bottom: 1px solid var(--rule);
  vertical-align: top;
  color: var(--fg-2);
  line-height: 1.55;
}
.prose :is(th, td):last-child,
.table-scroll > table :is(th, td):last-child,
.params :is(th, td):last-child {
  padding-right: 0;
}
.params .c-name {
  width: 30%;
}
.params .c-type {
  width: 15%;
}
.p-name {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--fg);
  overflow-wrap: anywhere;
}
.params td .p-name,
.params td code.p-name {
  padding: 0;
  border: 0;
  background: none;
  font-size: var(--fs-sm);
}
/* Required in `hi`, spelled out (never a colour or a star alone); Optional in `fg-3` */
.req {
  display: inline-block;
  margin-top: 4px;
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--hi);
}
.p-type {
  font-family: var(--sans);
  font-size: 12px;
  color: var(--fg-3);
}
.p-ex {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: var(--s-2);
  font-size: var(--fs-sm);
  color: var(--fg-3);
}
.p-ex > span {
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
/* a phone: every row of a parameter table is one block, the name and Required on one line
   and the description under them; the head stays in the accessibility tree */
@media (max-width: 700px) {
  .params thead {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
  .params,
  .params tbody,
  .params tr,
  .params td,
  .params tbody th {
    display: block;
    width: auto !important;
  }
  .params tr {
    padding: 14px 0;
    border-bottom: 1px solid var(--rule);
  }
  .params td,
  .params tbody th {
    padding: 0;
    border: 0;
  }
  .params td.c-name,
  .params td.c-type {
    display: inline;
  }
  .params td.c-name .p-name {
    display: inline;
  }
  .params td.c-name .req {
    margin: 0 0 0 8px;
  }
  .params td.c-type {
    margin-left: 8px;
  }
  .params td.c-desc {
    margin-top: 8px;
  }
}

/* ---------- status / response rows ----------
   A list of responses: hairline rows (a `rule-2` line on top, `rule` between), the status
   chip, then what the response means. */
.resp-list {
  list-style: none;
  margin: 0 0 var(--s-4);
  padding: 0;
  border-top: 1px solid var(--rule-2);
}
.resp-list li {
  display: grid;
  grid-template-columns: 96px minmax(0, 1fr);
  align-items: center;
  gap: var(--s-3);
  min-height: 46px;
  padding: 10px 0;
  border-bottom: 1px solid var(--rule);
  font-size: var(--fs-md);
  color: var(--fg-2);
}
.resp-list .status {
  justify-self: start;
}
@media (max-width: 560px) {
  .resp-list li {
    grid-template-columns: minmax(0, 1fr);
    gap: 6px;
  }
}

/* ---------- tabs (markup contract) ----------
   .tabs > .tabs-list[role=tablist] > .tab[role=tab][aria-selected], then .tab-panel(s).
   Signal's tabs: mono 11.5px, padding 6px 11px, radius 7px; the selected one carries
   aria-selected and is a filled chip. On a light page (a tab group above a code block) the
   row sits on a `rule` hairline and the chip is `code-bg`; in a code panel's bar the tabs
   are `code-tab` and the selected one `code-fg` on `code-tab-on`. In forced colours the
   selected tab keeps a Highlight underline (backgrounds are flattened there). */
.tabs {
  margin: 0 0 var(--s-4);
}
.tabs-list {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  margin: 0;
  padding: 0 0 6px;
  border-bottom: 1px solid var(--rule);
}
.tab {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 28px;
  padding: 0 11px;
  border-radius: 7px;
  background: none;
  color: var(--fg-3);
  font-family: var(--sans);
  font-size: 11.5px;
  font-weight: 400;
  letter-spacing: 0.02em;
  line-height: 1;
  white-space: nowrap;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}
.tab:hover {
  color: var(--fg);
}
.tab[aria-selected='true'] {
  background: var(--code-bg);
  color: var(--fg);
}
:is(.code-block, .code-panel, .ref-card, .home-qs) .tab {
  color: var(--code-tab);
}
:is(.code-block, .code-panel, .ref-card, .home-qs) .tab:hover,
:is(.code-block, .code-panel, .ref-card, .home-qs) .tab[aria-selected='true'] {
  color: var(--code-fg);
}
:is(.code-block, .code-panel, .ref-card, .home-qs) .tab[aria-selected='true'] {
  background: var(--code-tab-on);
}
/* The fill alone is too faint to find the selected language (white 8% on the panel, 1.3:1;
   WCAG 1.4.11): a 2px line under the label marks it too, hi on a light page and lime in a
   code panel (docs/DESIGN-SIGNAL.md §4.8). Not the example rows (.ref-ex-tab, .ref-ex-item):
   they carry their own bar. */
.tabs-list > .tab[aria-selected='true']:not(.ref-ex-tab, .ref-ex-item) {
  text-decoration-line: underline;
  text-decoration-thickness: 2px;
  text-decoration-color: var(--hi);
  text-underline-offset: 5px;
}
:is(.code-block, .code-panel, .ref-card, .home-qs) .tabs-list > .tab[aria-selected='true']:not(.ref-ex-tab, .ref-ex-item) {
  text-decoration-color: var(--code-ring);
}
.tabs .tab-panel {
  margin-top: var(--s-2);
}
.tabs .tab-panel > .code-block:last-child {
  margin-bottom: 0;
}
@media (forced-colors: active) {
  .tab[aria-selected='true'] {
    border-bottom: 2px solid Highlight;
  }
}

/* ---------- code blocks (markup contract) ----------
   Signal's code panel (docs/DESIGN-SIGNAL.md §1.4, §4.8): near-black green on every depth
   (`depth-code`: #0D1810 on light grounds, #112812 on bedrock, #081009 on deep), a 14px
   radius, a 1px `depth-code-bd` border and, on light grounds, the panel shadow. The bar on
   top holds one title (or, in a tab group, the tabs) and Copy, with a `code-rule` hairline
   under it. Code is Spline Sans Mono 12.8px / 1.7, indentation kept, scrolling sideways.
   tokens.css gives every panel its own scope (.code-block, .code-panel, .ref-card,
   .ref-tryit, .home-qs): a lime focus ring and a teal 2xx inside, whatever the band. */
.code-block {
  position: relative;
  margin: 0 0 var(--s-5);
  border: 1px solid var(--depth-code-bd);
  border-radius: var(--radius-code);
  background: var(--depth-code);
  color: var(--code-fg);
  overflow: hidden;
  box-shadow: var(--panel-shadow);
}
/* 42px high and 6px from the right edge: the Copy button (30px) keeps room for its whole
   focus ring (2px, 3px out) inside the panel, which clips (overflow: hidden) */
.code-head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-height: 42px;
  padding: 0 6px 0 16px;
  border-bottom: 1px solid var(--code-rule);
  background: transparent;
}
.code-title {
  min-width: 0;
  font-family: var(--sans);
  font-size: 11.5px;
  font-weight: 400;
  line-height: 1.35;
  letter-spacing: 0.02em;
  color: var(--code-tab);
  overflow-wrap: anywhere;
}
.code-head .copy {
  margin-left: auto;
}
/* A reference card scrolls on its own (reference.css .ref-card-res, and the request's
   .tab-panel): a response taller than the card would keep the bottom edge of its code's inset
   ring far below the card's fold. While the code in a card has focus, the ring is the card's:
   inside its edge, 2px of the panel's lime, always wholly in view. */
@supports selector(:has(a)) {
  .ref-card:has(pre[data-scroller]:focus-visible) {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
  }
  .ref-card pre[data-scroller]:focus-visible {
    outline: none;
  }
  /* the request card's panel scrolls when its snippet is taller than 42vh (reference.css) */
  .ref-card:has(> .tabs > .tab-panel[data-scroller]:focus-visible) {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
  }
  .ref-card .tab-panel[data-scroller]:focus-visible {
    outline: none;
  }
}
.code-block pre {
  margin: 0;
  padding: 16px 0;
  overflow-x: auto;
  background: transparent;
  font-size: var(--fs-code);
  line-height: 1.7;
  color: var(--code-fg);
  tab-size: 4;
  -moz-tab-size: 4;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--code-fg) 28%, transparent) transparent;
}
.code-block pre code {
  display: inline-block;
  min-width: 100%;
  padding: 0 18px;
  border: 0;
  border-radius: 0;
  background: none;
  vertical-align: top;
  color: inherit;
  font-size: inherit;
}
.code-block pre::-webkit-scrollbar {
  width: 10px;
  height: 10px;
}
.code-block pre::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--code-fg) 22%, transparent);
  border-radius: 10px;
  border: 3px solid var(--depth-code);
}
@media (max-width: 560px) {
  .code-head {
    padding-left: 12px;
  }
}
/* the narrowest phones: the title keeps its room beside Copy (it wraps, it is never hidden) */
@media (max-width: 380px) {
  .code-head {
    gap: 6px;
  }
  .code-head .copy {
    padding: 0 6px;
  }
}

/* copy button: the Signal copy icon and a visible "Copy" (build/reference.mjs copyButton):
   <button class="copy" type="button" data-copy [aria-label="Copy …"]>
     <svg class="ico i-copy" …/><span class="copy-label">Copy</span></button>
   docs.js sets .copy-label to "Copied" for 1.6s (.is-copied: the icon turns into a check), or
   to "Press ⌘C" / "Copy failed" when the clipboard refused (.is-failed). Mono 11px; in a code
   panel `code-tab`, and `code-fg` on hover. */
.copy {
  position: relative;
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-width: 30px;
  height: 30px;
  padding: 0 8px;
  border-radius: 7px;
  background: transparent;
  color: var(--fg-3);
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.04em;
  line-height: 1;
  white-space: nowrap;
  transition: color 0.2s var(--ease), background-color 0.2s var(--ease);
}
.copy:hover {
  color: var(--fg);
}
:is(.code-block, .code-panel, .ref-card, .ref-tryit, .home-qs) .copy {
  color: var(--code-tab);
}
:is(.code-block, .code-panel, .ref-card, .ref-tryit, .home-qs) .copy:hover {
  color: var(--code-fg);
}
.copy .ico {
  width: 14px;
  height: 14px;
}
.copy.is-copied .i-copy,
.copy.is-failed .i-copy {
  display: none;
}
/* "Copied": the copy icon becomes Signal's check (the same 14px box, drawn as a mask) */
.copy.is-copied::before {
  content: '';
  flex: none;
  width: 14px;
  height: 14px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='m3 8.5 3.2 3L13 4.5' fill='none' stroke='%23000' stroke-width='1.4'/%3E%3C/svg%3E") center / 14px 14px no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='m3 8.5 3.2 3L13 4.5' fill='none' stroke='%23000' stroke-width='1.4'/%3E%3C/svg%3E") center / 14px 14px no-repeat;
}
@media (forced-colors: active) {
  .copy.is-copied::before {
    background: ButtonText;
  }
}

/* syntax token colours (build/highlight.mjs; tokens.css binds --t-* to Signal's code colours:
   keys coral, strings sand, numbers peach, keywords, commands and flags lime, comments white
   at 55% and upright, the rest `code-fg`) */
.tok-key {
  color: var(--t-key);
}
.tok-str {
  color: var(--t-str);
}
.tok-num {
  color: var(--t-num);
}
.tok-bool {
  color: var(--t-bool);
}
.tok-null {
  color: var(--t-null);
}
.tok-kw {
  color: var(--t-kw);
}
.tok-com {
  color: var(--t-com);
  font-style: normal;
}
.tok-punc {
  color: var(--t-punc);
}
.tok-fn {
  color: var(--t-fn);
}
.tok-var {
  color: var(--t-var);
}
.tok-op {
  color: var(--t-op);
}

/* ---------- endpoint chip (shared with reference pages) ----------
   Signal's endpoint line (docs/DESIGN-SIGNAL.md §4.9): no box, a `rule-2` line above and
   below; the method chip, then the URL in mono with the host in `fg-3` and the path in 600.
   The reference's own line is .ref-endpoint (reference.css), with the same values. */
.endpoint {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-3) 14px;
  min-height: 52px;
  padding: 14px 0;
  border-top: 1px solid var(--rule-2);
  border-bottom: 1px solid var(--rule-2);
}
.endpoint-url {
  flex: 1;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-md);
  line-height: 1.5;
  overflow-wrap: break-word;
  color: var(--fg);
}
.endpoint-url .host {
  color: var(--fg-3);
  font-size: 0.9em;
}
.endpoint-url .path {
  font-weight: 600;
}

/* ---------- cards (home + index pages) ----------
   Lists of pages are ledger rows now (.ledger, "hero (home)" below). A .card is kept for the
   one place that is a real panel: Signal's panel (white on sage, sage on white, a faint wash
   on dark), a 1px `panel-bd` border, no lift on hover. */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(248px, 1fr));
  gap: var(--s-3);
  margin: 0 0 var(--s-4);
}
.card {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 18px 20px;
  border: 1px solid var(--panel-bd);
  border-radius: var(--radius-lg);
  background: var(--panel);
  box-shadow: var(--panel-shadow);
  transition: border-color 0.2s var(--ease), background 0.2s var(--ease);
}
a.card:hover {
  border-color: var(--rule-3);
  background: var(--panel-2);
}
.card-name {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  font-size: var(--fs-h3);
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--fg);
}
.card-desc {
  margin: 0;
  font-size: var(--fs-md);
  line-height: 1.55;
  color: var(--fg-2);
}
.prose a.card {
  text-decoration: none;
}
@media (max-width: 560px) {
  .card-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ---------- draft pages (only in --drafts preview builds) ----------
   A neutral note, not a status colour: a dashed `rule-3` border and the word "Draft". */
.draft-banner {
  margin: 0 0 var(--s-4);
  padding: 10px 14px;
  border: 1px dashed var(--rule-3);
  border-radius: var(--radius);
  background: var(--panel);
  color: var(--fg-2);
  font-size: var(--fs-md);
}
.draft-banner strong {
  color: var(--fg);
}

/* ---------- hero (home) ----------
   Signal's shared components, used on every page (docs/DESIGN-SIGNAL.md §4.1–4.3, §4.18):
     .btn           .btn--solid (one per view) / .btn--line; sizes .btn--sm 36px, default
                    46px, .btn--lg 54px, .btn--block; label first, then an arrow
                    (icon('arrow', 'ico i-arrow')). The old .btn-primary is solid, a bare
                    .btn is a line button, .btn-login a small line button.
     .go            a text link: Onest 15px 600 in `fg`, then an arrow in `hi` (another
                    site: the external mark); hover draws a 1px underline from the left.
     .label         mono 11px 500 uppercase 0.1em in `fg-3` (uppercase is CSS only).
     .tag, .tags    a mono uppercase chip that classifies; never a link or a button.
     .chip-on       the selected state as a filled chip ("Selected").
     .ledger        hairline rows instead of card grids: `rule-2` on top, `rule` between,
                    a `panel-2` hover panel behind the row, an arrow in `hi`; the title link
                    stretches over the row, so the whole row is one target.
   Every colour is a depth token, so each component works on every depth. Exposure is never a
   button, a tag or a decoration. */

/* ---- buttons ---- */
.btn,
:where(.btn-login) {
  --btn-bg: var(--panel);
  --btn-fg: var(--fg);
  --btn-bd: var(--rule-2);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 46px;
  padding: 0 20px;
  border: 1px solid var(--btn-bd);
  border-radius: var(--radius);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.01em;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: transform 0.25s var(--ease-out), background-color 0.2s var(--ease), border-color 0.2s var(--ease),
    color 0.2s var(--ease);
}
.btn:hover,
.btn--line:hover,
:where(.btn-login):hover {
  --btn-bg: var(--panel-2);
  --btn-bd: var(--rule-3);
  color: var(--btn-fg);
}
.btn--solid,
.btn-primary {
  --btn-bg: var(--solid-bg);
  --btn-fg: var(--solid-fg);
  --btn-bd: var(--solid-bg);
}
.btn--solid:hover,
.btn-primary:hover {
  --btn-bg: var(--solid-hover);
  --btn-bd: var(--solid-hover);
}
.btn--line {
  --btn-bg: var(--panel);
  --btn-fg: var(--fg);
  --btn-bd: var(--rule-2);
}
.btn--sm,
:where(.btn-login) {
  min-height: 36px;
  padding: 0 14px;
  gap: 8px;
  font-size: 14px;
}
.btn--lg {
  min-height: 54px;
  padding: 0 26px;
  font-size: 16px;
}
.btn--block {
  width: 100%;
}
.btn .ico {
  flex: none;
  width: 16px;
  height: 16px;
}
.btn kbd {
  margin-left: 4px;
}
button.btn:disabled,
.btn[aria-disabled='true'] {
  opacity: 0.55;
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
}
/* the old names, where a page still writes them (the class, not the look, is kept) */
.prose a.btn,
.prose a.btn-primary {
  color: var(--btn-fg);
  text-decoration: none;
}

/* ---- the text link with an arrow ---- */
.go {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding-block: 4px;
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.01em;
  text-decoration: none;
  background: linear-gradient(currentColor, currentColor) 0 100% / 0 1px no-repeat;
  transition: background-size 0.4s var(--ease-out), color 0.2s var(--ease);
}
.go:hover,
.go:focus-visible {
  background-size: 100% 1px;
}
.go .ico {
  flex: none;
  width: 16px;
  height: 16px;
  color: var(--hi);
}
.prose a.go {
  color: var(--fg);
  text-decoration: none;
}
.go-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 24px;
}

/* the arrow nudge: 3px, only for readers who have not asked for less motion */
@media screen and (prefers-reduced-motion: no-preference) {
  .btn .i-arrow,
  .go .i-arrow,
  .ledger-go {
    transition: transform 0.25s var(--ease-out);
  }
  .btn:hover .i-arrow,
  .go:hover .i-arrow,
  .ledger-row:hover .ledger-go {
    transform: translateX(3px);
  }
  .btn--solid:hover,
  .btn-primary:hover {
    transform: translateY(-1px);
  }
}

/* ---- label ---- */
.label,
.prose .label {
  font-family: var(--sans);
  font-size: 11px;
  line-height: 1.3;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-3);
}

/* ---- tags ---- */
.tag {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 24px;
  padding: 0 9px;
  border: 1px solid var(--rule-2);
  border-radius: var(--radius-tag);
  background: var(--panel);
  color: var(--fg-2);
  font-family: var(--sans);
  font-size: 11px;
  line-height: 1;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}
.tag--dashed {
  border-style: dashed;
  border-color: var(--rule-3);
}
ul.tags,
ol.tags,
.tags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.tags > li {
  margin: 0;
}
/* the selected state as a filled chip ("Selected"): `hi` fill, `accent-fg` text */
.chip-on {
  display: inline-flex;
  align-items: center;
  height: 22px;
  padding: 0 8px;
  border-radius: var(--radius-tag);
  background: var(--hi);
  color: var(--accent-fg);
  font-family: var(--sans);
  font-size: 11px;
  line-height: 1;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* ---- ledger rows ----
   <ul class="ledger">
     <li class="ledger-row">
       <p class="ledger-meta">…</p>                        optional: a date, tags
       <h3 class="ledger-title"><a class="ledger-link" href="…">Title</a></h3>
       <p class="ledger-text">One or two sentences.</p>    optional
       <ul class="tags ledger-tags">…</ul>                 optional
       <svg class="ico i-arrow ledger-go" …></svg>
     </li>
   </ul>
   The row may be an <article> inside a plain <li> (the changelog, whose markup check.mjs
   reads). .ledger--split puts the title beside the text from 900px (the home page's module
   lists). The ul/li/h3/p type selectors keep these rules above the .prose list and heading
   rules. */
ul.ledger,
ol.ledger {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--rule-2);
}
ul.ledger > li,
ol.ledger > li {
  margin: 0;
}
:is(li, article, div).ledger-row {
  position: relative;
  isolation: isolate;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: 'meta go' 'title go' 'text go' 'tags go';
  column-gap: 24px;
  margin: 0;
  padding: 20px 0;
  border-bottom: 1px solid var(--rule);
}
:is(li, article, div).ledger-row::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset: 6px -14px;
  border-radius: 12px;
  background: var(--panel-2);
  opacity: 0;
  transition: opacity 0.25s var(--ease);
}
:is(li, article, div).ledger-row:hover::before {
  opacity: 1;
}
.ledger-row > .ledger-meta,
.prose .ledger-row > .ledger-meta {
  grid-area: meta;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 12px;
  margin: 0 0 8px;
  color: var(--fg-3);
  font-family: var(--sans);
  font-size: 13px;
  line-height: 1.5;
}
h2.ledger-title,
h3.ledger-title {
  grid-area: title;
  margin: 0;
  padding: 0;
  border: 0;
  font-family: var(--font-sans);
  font-size: var(--fs-h3);
  line-height: 1.3;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--fg);
}
.ledger-link,
.prose a.ledger-link {
  color: inherit;
  text-decoration: none;
  /* tabbing to a row never leaves it under the sticky header */
  scroll-margin-block: calc(var(--header-h) + 48px) 24px;
}
/* the title link covers the whole row: one target, one name */
.ledger-link::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 12px;
}
.ledger-link:focus-visible {
  outline: none;
}
.ledger-link:focus-visible::after {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
p.ledger-text,
.ledger-text {
  grid-area: text;
  max-width: 44rem;
  margin: 4px 0 0;
  color: var(--fg-2);
  font-size: 15px;
  line-height: 1.6;
}
.ledger-text code {
  font-size: 0.875em;
}
.ledger-tags,
ul.ledger-tags {
  grid-area: tags;
  margin: 12px 0 0;
}
.ledger .tag {
  height: 22px;
  padding: 0 8px;
  font-size: 10.5px;
  letter-spacing: 0.08em;
}
.ledger-go {
  grid-area: go;
  align-self: center;
  width: 16px;
  height: 16px;
  color: var(--hi);
}
/* a second line under a title (a module's full name): Onest 14px in `fg-3` */
.ledger-sub {
  display: block;
  margin-top: 2px;
  color: var(--fg-3);
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.45;
  font-weight: 400;
  letter-spacing: -0.006em;
}
/* Split: the meta and the title on the left, the text and the tags on the right. The text
   spans a flexible third row, so a long summary grows that row and the title stays at the top
   of the row beside the text's first line (an `auto` row would share the height out and push
   the title down). */
@media (min-width: 900px) {
  .ledger--split > li.ledger-row {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr) auto;
    grid-template-areas: 'meta text go' 'title text go' '. text go' '. tags go';
    grid-template-rows: auto auto 1fr auto;
    column-gap: 32px;
    padding-block: 24px;
  }
  .ledger--split > li.ledger-row > .ledger-text {
    margin-top: 0;
  }
  .ledger--split > li.ledger-row > .ledger-tags {
    margin-top: 12px;
  }
}
@media (forced-colors: active) {
  :is(li, article, div).ledger-row:hover::before {
    border: 1px solid CanvasText;
  }
  .chip-on {
    border: 1px solid CanvasText;
  }
}

/* ---- a page hero (the class is kept for any page that writes it) ---- */
.hero {
  padding-bottom: var(--s-2);
}
.hero h1 {
  margin: 0 0 var(--s-3);
  font-size: var(--fs-h1);
  line-height: 1.05;
  font-weight: 600;
  letter-spacing: -0.04em;
  word-spacing: -0.02em;
  text-wrap: balance;
}
.hero .lede {
  max-width: var(--measure);
  margin: 0 0 var(--s-5);
  font-size: var(--fs-lede);
  line-height: 1.55;
  letter-spacing: -0.02em;
  color: var(--fg-2);
}
.hero-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 24px;
  margin-bottom: var(--s-5);
}

/* ---------- 404 (build/seo.mjs notFoundPage) ----------
   A centred block on the reading ground (docs/DESIGN-SIGNAL.md §4.22): the "404" label in
   `hi`, the h1, a lede, the similar pages (docs.js), a line button that opens the search
   palette, the four places to go as ledger rows, and the help line. */
.nf {
  max-width: 640px;
  margin: 0 auto;
  padding: var(--s-8) 0 var(--s-6);
}
.nf-top {
  text-align: center;
}
.prose .nf-code {
  margin: 0 0 var(--s-3);
  color: var(--hi);
}
.prose .nf h1 {
  margin: 0 0 var(--s-4);
}
.prose .nf .lede {
  margin: 0 auto var(--s-6);
}
.nf-search-row {
  display: flex;
  justify-content: center;
  margin: 0 0 var(--s-7);
}
.nf-search {
  min-width: min(100%, 320px);
}
.nf-search .ico {
  color: var(--fg-3);
}
.nf-search kbd {
  margin-left: auto;
  padding: 0 6px;
  min-width: 20px;
  height: 20px;
  border: 1px solid var(--rule-2);
  border-radius: 5px;
  background: var(--panel);
  color: var(--fg-3);
  font-size: 11px;
  font-weight: 500;
  line-height: 18px;
}
html:not(.js) .nf-search-row {
  display: none;
}
.prose .nf-places-h {
  margin: 0 0 var(--s-3);
}
.prose .nf-places {
  margin: 0 0 var(--s-6);
}
.prose .nf-help {
  margin: 0;
  font-size: var(--fs-md);
  text-align: center;
  color: var(--fg-3);
}
@media (pointer: coarse) {
  .nf-search kbd {
    display: none;
  }
}
@media (max-width: 560px) {
  .nf {
    padding-top: var(--s-6);
  }
}

/* ---------- 404: similar pages (docs.js nfSuggest) ----------
   The pages closest to the requested URL, as ledger rows: the title, then its place and path
   in mono `fg-3`. docs.js writes <li><a class="nf-suggest-link"> … </a></li>, so the row is
   the link itself. */
.nf-suggest {
  margin: 0 0 var(--s-6);
}
.prose .nf-suggest-h {
  margin: 0 0 var(--s-3);
  padding: 0;
  border: 0;
  font-family: var(--sans);
  font-size: 11px;
  line-height: 1.3;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.prose .nf-suggest-list {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--rule-2);
}
.prose .nf-suggest-list > li {
  margin: 0;
  border-bottom: 1px solid var(--rule);
}
.nf-suggest-link {
  position: relative;
  isolation: isolate;
  display: grid;
  gap: 2px;
  padding: 14px 0;
  color: var(--fg);
  text-decoration: none;
}
.nf-suggest-link::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset: 4px -14px;
  border-radius: 12px;
  background: var(--panel-2);
  opacity: 0;
  transition: opacity 0.25s var(--ease);
}
.nf-suggest-link:hover::before {
  opacity: 1;
}
.nf-suggest-title {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--fg);
}
.nf-suggest-path {
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.5;
  color: var(--fg-3);
  overflow-wrap: anywhere;
}

/* ---------- page actions (build/layout.mjs renderPageActions) ----------
   A split line button next to the h1 (36px, the look of .btn--line.btn--sm): "Copy page" and
   a chevron that opens the menu, a layer (data-depth="surface-2"). Hidden without
   JavaScript: the .md twin is still linked from <head>. */
/* The row wraps when the h1 would get less than 12rem beside the buttons (a phone with the
   changelog's "Atom feed" and the actions): the buttons move under the title instead of
   squeezing it until a word breaks in the middle. */
.page-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s-3) var(--s-4);
  /* the h1's own 16px below it (prose, .ref-head) moves to the row, so buttons that wrap
     under the title keep the same distance to the lede */
  margin-bottom: var(--s-4);
}
/* (0,2,1): above .prose h1 and reference.css .ref-head h1 */
.page-head > h1:first-child {
  flex: 1 1 12rem;
  min-width: 0;
  margin-bottom: 0;
}
/* two things beside the title (the changelog: "Atom feed" and the actions): they wrap as a
   pair, so the title keeps its own line on a phone rather than one button */
.page-head:has(> :nth-child(3)) > h1:first-child {
  flex-basis: 20rem;
}
.prose .crumbs + .page-head > h1 {
  margin-top: 0;
}
.page-actions {
  /* above the page's code blocks (positioned, z-index auto), below the sticky header (40) */
  position: relative;
  z-index: 30;
  /* baseline-aligned with the h1's first line, then nudged to its optical centre */
  top: -6px;
  flex: none;
  display: inline-flex;
  align-items: stretch;
}
html:not(.js) .page-actions {
  display: none;
}
/* beside the changelog's "Atom feed", which sits unnudged from 720px down (docs.css
   "changelog"): the pair stays level, on the title's line or wrapped under it */
@media (max-width: 720px) {
  .page-head > .cl-feed + .page-actions {
    top: 0;
  }
}
.pa-copy,
.pa-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 36px;
  border: 1px solid var(--rule-2);
  background: var(--panel);
  color: var(--fg);
  font-size: var(--fs-md);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1;
  white-space: nowrap;
  transition: border-color 0.2s var(--ease), background-color 0.2s var(--ease);
}
.pa-copy {
  gap: 8px;
  padding: 0 13px 0 12px;
  border-radius: var(--radius) 0 0 var(--radius);
}
.pa-toggle {
  width: 34px;
  margin-left: -1px;
  border-radius: 0 var(--radius) var(--radius) 0;
  color: var(--fg-3);
}
.pa-copy:hover,
.pa-toggle:hover,
.page-actions.is-open .pa-toggle {
  position: relative;
  border-color: var(--rule-3);
  background: var(--panel-2);
}
.pa-toggle:hover,
.page-actions.is-open .pa-toggle {
  color: var(--fg);
}
/* the two halves overlap by 1px: the focused one is drawn on top, so its whole ring shows
   (.page-actions is the stacking context) */
.pa-copy:focus-visible,
.pa-toggle:focus-visible {
  position: relative;
  z-index: 1;
}
.pa-copy .ico {
  color: var(--fg-3);
}
.page-actions.is-open .pa-toggle .ico {
  transform: rotate(180deg);
}
.pa-copy .pa-i-done {
  display: none;
  color: var(--ok);
}
.pa-copy.is-copied .pa-i-copy {
  display: none;
}
.pa-copy.is-copied .pa-i-done {
  display: block;
}
.pa-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 45;
  width: 300px;
  max-width: calc(100vw - 32px);
  margin: 0;
  padding: 6px;
  list-style: none;
  border: 1px solid var(--panel-bd);
  border-radius: var(--radius-code);
  background: var(--bg);
  color: var(--fg);
  box-shadow: var(--sheet-shadow);
}
.prose .pa-menu {
  margin: 0;
  padding: 6px;
}
.pa-menu li,
.prose .pa-menu li {
  margin: 0;
  padding: 0;
}
.prose .pa-menu li::before {
  content: none;
}
.pa-item {
  display: grid;
  grid-template-columns: 16px minmax(0, 1fr);
  align-items: start;
  column-gap: 10px;
  width: 100%;
  padding: 9px 10px;
  border-radius: var(--radius);
  font: inherit;
  text-align: left;
  text-decoration: none;
  color: var(--fg);
  cursor: pointer;
  transition: background-color 0.2s var(--ease);
}
.pa-item:hover,
.pa-item:focus {
  background: var(--panel-2);
}
.pa-item:focus:not(:focus-visible) {
  outline: none;
}
.pa-ico {
  margin-top: 2px;
  color: var(--fg-3);
}
.pa-item-text {
  display: grid;
  gap: 1px;
  min-width: 0;
}
.pa-item-title {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--fs-md);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.01em;
}
.pa-ext {
  width: 11px;
  height: 11px;
  color: var(--fg-3);
}
.pa-item-desc {
  font-size: var(--fs-sm);
  line-height: 1.45;
  color: var(--fg-3);
}

/* ---------- toast (docs.js) ---------- */
/* inverse colours (fg ground, bg text) of the page's depth; an error is the same toast with a
   triangle and its sentence (never the exposure colour) */
.toast {
  position: fixed;
  left: 50%;
  bottom: 24px;
  z-index: 90;
  display: flex;
  align-items: center;
  gap: 8px;
  /* left: 50% would leave it half the viewport to shrink into: size it to its text */
  width: max-content;
  max-width: calc(100vw - 32px);
  padding: 10px 16px;
  border-radius: var(--radius);
  background: var(--fg);
  color: var(--bg);
  font-size: var(--fs-md);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: -0.006em;
  box-shadow: var(--sheet-shadow);
  opacity: 0;
  transform: translate(-50%, 0);
}
.toast.is-shown {
  opacity: 1;
}
@media screen and (prefers-reduced-motion: no-preference) {
  .toast {
    transform: translate(-50%, 8px);
    transition: opacity 0.15s var(--ease), transform 0.15s var(--ease-out);
  }
  .toast.is-shown {
    transform: translate(-50%, 0);
  }
}
.toast.is-error::before {
  content: '';
  flex: none;
  width: 14px;
  height: 14px;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M5 1.2 9.2 8.8H.8Z' fill='%23000' transform='translate(3 3)'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M5 1.2 9.2 8.8H.8Z' fill='%23000' transform='translate(3 3)'/%3E%3C/svg%3E") center / contain no-repeat;
}
.toast-link {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}
.toast-link:focus-visible {
  outline-color: currentColor;
}

/* ---------- page meta: feedback + last updated (renderPageMeta) ---------- */
.page-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3) var(--s-6);
  margin-top: var(--s-8);
}
/* "Last updated September 23, 2026": xs in fg-3 (a meta line, not a heading) */
.page-meta .page-updated {
  margin: 0 0 0 auto;
  font-size: var(--fs-sm);
  line-height: 1.45;
  letter-spacing: 0;
  color: var(--fg-3);
}
.page-meta + .pager {
  margin-top: var(--s-5);
}

/* "Was this page helpful?": the votes are small line buttons (.btn.btn--line.btn--sm), the
   pressed one a filled chip; "Send feedback" the solid one */
.feedback {
  flex: 1 1 360px;
  min-width: 0;
}
.feedback-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2) var(--s-3);
}
.page-meta .feedback-q {
  margin: 0;
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--fg);
}
.feedback-votes {
  display: inline-flex;
  gap: 6px;
}
html:not(.js) .feedback {
  display: none;
}
.feedback-vote {
  gap: 6px;
}
.feedback-vote .feedback-down {
  transform: rotate(180deg);
}
.feedback-vote[aria-pressed='true'],
.feedback-vote[aria-pressed='true']:hover {
  border-color: var(--hi);
  background: var(--hi);
  color: var(--accent-fg);
}
.feedback-vote:disabled {
  cursor: default;
}
.feedback-form {
  display: grid;
  gap: 8px;
  max-width: 560px;
  margin-top: var(--s-3);
}
.feedback-label {
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--fg);
}
.feedback-optional {
  font-weight: 400;
  color: var(--fg-3);
}
/* a form field: its border clears 3:1 (--field-bd) */
.feedback-text {
  width: 100%;
  min-height: 84px;
  padding: 10px 12px;
  border: 1px solid var(--field-bd);
  border-radius: var(--radius);
  background: var(--bg);
  color: var(--fg);
  font: inherit;
  font-size: var(--fs-md);
  line-height: 1.5;
  resize: vertical;
}
.feedback-text::placeholder {
  color: var(--fg-3);
}
.feedback-form-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
}
.feedback-count {
  font-size: var(--fs-sm);
  color: var(--fg-3);
}
.page-meta .feedback-status {
  margin: 8px 0 0;
  font-size: var(--fs-md);
  color: var(--fg-2);
}
.page-meta .feedback-status:empty {
  display: none;
}
.page-meta .feedback-status.is-error {
  color: var(--fg);
}

/* ---------- Postman downloads (renderPostmanDownloads) ---------- */
/* a panel: "Download the collection" (solid, small) and "Download the environment" (line) */
.postman-dl {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3) var(--s-5);
  margin: var(--s-5) 0;
  padding: 16px 18px;
  border: 1px solid var(--panel-bd);
  border-radius: var(--radius-code);
  background: var(--panel);
  box-shadow: var(--panel-shadow);
}
.postman-dl-text {
  flex: 1 1 280px;
  min-width: 0;
}
.postman-dl .postman-dl-title {
  margin: 0 0 6px;
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.postman-dl .postman-dl-desc {
  margin: 0;
  font-size: var(--fs-md);
  line-height: 1.55;
  color: var(--fg-2);
}
.postman-dl-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-2);
}
/* the link to the Postman Collection page, after the two buttons */
.postman-dl-guide {
  margin-left: var(--s-2);
  font-size: var(--fs-md);
}

@media (max-width: 640px) {
  /* one row still: the copy button keeps its icon, the label is for screen readers */
  .pa-copy {
    padding: 0 10px;
  }
  .pa-copy-label {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .page-meta .page-updated {
    margin-left: 0;
  }
}

/* ---------- pages without a sidebar (changelog) ----------
   The column is centred in the viewport rather than pinned left: the changelog's wider
   column, and the 404's reading column (the 404 shares the home page's html class but not
   home.css, whose full-width column overrides this on "/"). */
.no-sidebar .prose-inner {
  margin-inline: auto;
}
.page-changelog .prose-inner {
  max-width: 920px;
  margin-inline: auto;
}
.page-changelog .footer-inner {
  max-width: calc(920px + 2 * var(--gutter));
  margin-inline: auto;
}

/* ---------- changelog (build/changelog.mjs) ----------
   The list is grouped by day (docs/DESIGN-SIGNAL.md §4.19): from 900px the date sits in a
   sticky mono column on the left and that day's entries are ledger rows on the right; below
   900px the date is set above its entries. A row: neutral tags, the title (the whole row is
   its link), the summary. No timeline, no dots, no colour per tag. The markup keeps the names
   `npm run check` reads (build/check.mjs changelogProblems): li.cl-day, h2.cl-when > time,
   li.cl-item > article … </article>, h3.cl-title > a[href], div.cl-meta > time. */
.cl-head {
  margin: 0 0 var(--s-7);
}
.cl-head .lede,
.cl-intro > :last-child {
  margin-bottom: 0;
}
/* in the title row (Page.headLinks), beside the page actions: same height, 8px apart
   (without JavaScript the actions are hidden and the button ends the row) */
.page-head > .cl-feed {
  position: relative;
  top: -4px;
  flex: none;
}
.page-head > .cl-feed + .page-actions {
  margin-left: calc(8px - var(--s-4));
}
.cl-feed .ico {
  color: var(--fg-3);
}
.prose a.cl-feed {
  text-decoration: none;
}
.prose .cl-list,
.cl-list {
  margin: 0;
  padding: 0;
  list-style: none;
}
.prose .cl-list > li.cl-day,
.cl-day {
  display: grid;
  grid-template-columns: 160px minmax(0, 1fr);
  column-gap: var(--s-6);
  margin: 0 0 var(--s-7);
}
.prose h2.cl-when,
.cl-when {
  position: sticky;
  top: calc(var(--header-h) + 16px);
  align-self: start;
  margin: 0;
  padding: 23px 0 0;
  border: 0;
  font-family: var(--sans);
  font-size: 13px;
  line-height: 1.5;
  font-weight: 400;
  letter-spacing: 0;
  color: var(--fg-3);
  white-space: nowrap;
}
/* the rows: Signal's ledger (the hover panel, the stretched title link and the arrow come
   from .ledger / .ledger-row, "hero (home)") */
.prose .cl-cards > li.cl-item {
  margin: 0;
}
.cl-card-meta {
  grid-area: meta;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin: 0 0 10px;
}
.prose h3.cl-title {
  grid-area: title;
  margin: 0;
  padding: 0;
  border: 0;
  font-size: var(--fs-h3);
  line-height: 1.3;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--fg);
}
.prose .cl-summary {
  grid-area: text;
  max-width: 44rem;
  margin: 4px 0 0;
  font-size: 15px;
  line-height: 1.6;
  color: var(--fg-2);
}
/* a draft entry (only in a --drafts preview): a dashed rule and the word "Draft" */
.cl-card[data-draft] {
  border-bottom-style: dashed;
  border-bottom-color: var(--rule-3);
}
.cl-empty {
  color: var(--fg-3);
}
/* an entry page: the date (data style) and the tags under the title */
.cl-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 14px;
  margin: calc(-1 * var(--s-2)) 0 var(--s-5);
  font-family: var(--sans);
  font-size: 13px;
  line-height: 1.5;
  color: var(--fg-3);
}
.prose .cl-entry-lede {
  margin: 0 0 var(--s-6);
}
/* An entry page shares the list's wider column (the page head, the pager); its running text
   keeps the article measure (46rem), as on every other page. */
.prose .cl-entry-lede ~ :is(p, ul, ol, blockquote, h2, h3, h4, .callout) {
  max-width: var(--measure-wide);
}
@media (max-width: 899px) {
  .prose .cl-list > li.cl-day,
  .cl-day {
    grid-template-columns: minmax(0, 1fr);
    margin-bottom: var(--s-6);
  }
  .prose h2.cl-when,
  .cl-when {
    position: static;
    padding: 0 0 var(--s-3);
  }
}
@media (max-width: 720px) {
  .page-head > .cl-feed {
    top: 0;
  }
}

/* ---------- right-hand TOC ---------- */
/* "On This Page" (Signal ContentsRail): the title a label, a rule-2 line down the rail, the
   links Onest 13px in fg-3; the section being read (docs.js: aria-current="true") in fg 600
   with a 2px hi bar on the line. No numbers, no counts. */
.toc {
  position: sticky;
  top: var(--header-h);
  align-self: start;
  max-height: calc(100vh - var(--header-h));
  overflow-y: auto;
  overscroll-behavior: contain;
  /* 6px on the left, given back by the margin: the rail is a scroller, so without it a
     link's focus ring (2px, 3px out) lost its left edge */
  padding: 40px 20px 56px 6px;
  margin-left: -6px;
  scrollbar-width: thin;
  scrollbar-color: var(--rule-2) transparent;
}
.toc-title {
  margin: 0 0 var(--s-3);
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.toc ul {
  list-style: none;
  margin: 0;
  padding: 0;
  border-left: 1px solid var(--rule-2);
}
.toc a {
  position: relative;
  display: block;
  padding: 5px 0 5px 14px;
  font-size: var(--fs-sm);
  line-height: 1.45;
  font-weight: 400;
  color: var(--fg-3);
  transition: color 0.2s var(--ease);
}
.toc a:hover {
  color: var(--fg);
}
.toc a[aria-current='true'] {
  color: var(--fg);
  font-weight: 600;
}
.toc a[aria-current='true']::before {
  content: '';
  position: absolute;
  left: -1px;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--hi);
}
.toc .toc-h3 a {
  padding-left: 26px;
}

/* ---------- prev / next ---------- */
/* two cells on a hairline, no box: the direction a label, the title Onest 16px 600 with an
   arrow in hi (pointing back for Previous); hover underlines the title and nudges the arrow */
.pager {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-3) var(--s-6);
  margin-top: var(--s-8);
  padding-top: var(--s-5);
  border-top: 1px solid var(--rule);
}
.pager a {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  min-width: 0;
  padding: 4px 0;
  text-decoration: none;
}
.pager .pager-dir {
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.pager .pager-title {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  font-size: var(--fs-base);
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--fg);
}
.pager .pager-name {
  min-width: 0;
  text-decoration: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
  transition: text-decoration-color 0.2s var(--ease);
}
.pager a:hover .pager-name {
  text-decoration-color: currentColor;
}
.pager .pager-arrow {
  color: var(--hi);
}
.pager-prev .pager-arrow {
  transform: scaleX(-1);
}
.pager-next {
  align-items: flex-end;
  text-align: right;
  grid-column: 2;
}
@media screen and (prefers-reduced-motion: no-preference) {
  .pager .pager-arrow {
    transition: transform 0.25s var(--ease-out);
  }
  .pager-next:hover .pager-arrow {
    transform: translateX(3px);
  }
  .pager-prev:hover .pager-arrow {
    transform: scaleX(-1) translateX(3px);
  }
}
.prose .pager a {
  text-decoration: none;
}

/* ---------- footer ---------- */
/* The chrome depth (data-depth="surface"), a hairline on top. */
.footer {
  flex: none;
  border-top: 1px solid var(--rule);
  background: var(--bg);
  color: var(--fg-3);
}
.footer-inner {
  padding: var(--s-5) var(--gutter) var(--s-6);
  font-size: var(--fs-sm);
  line-height: 1.45;
  color: var(--fg-3);
}
/* Every item draws a "·" in front of itself; the one at the start of each line
   falls outside .footer-clip and is clipped, so a wrapped footer never starts
   or ends a line with a separator. The 6px of padding keeps whole focus rings
   (2px, 3px out). */
.footer-clip {
  overflow: hidden;
  padding: 6px;
  margin: -6px;
}
.footer-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  row-gap: 6px;
  margin: 0 0 0 -24px;
  padding: 0;
  list-style: none;
}
.footer-links li {
  position: relative;
  margin-left: 24px;
}
.footer-links li::before {
  content: '·';
  position: absolute;
  left: -15px;
  color: var(--fg-4);
  pointer-events: none;
}
.footer-links a {
  color: var(--fg-3);
  transition: color 0.2s var(--ease);
}
.footer-links a:hover {
  color: var(--fg);
}
/* the one-line footer: © on the left, the links after it */
.footer:not(.footer-rich) .footer-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 28px;
}
.footer-copy {
  margin: 0;
  flex: none;
}
/* the full footer (home, 404, changelog): the lockup and a line about the site, then the
   link columns (their titles are labels), then © */
.footer-rich .footer-inner {
  padding-block: 48px 28px;
}
.footer-top {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 2fr);
  gap: 32px 48px;
}
.footer-logo {
  display: inline-flex;
  align-items: center;
}
.footer-logo .logo {
  height: 22px;
}
.footer-about {
  max-width: 36ch;
  margin: 14px 0 0;
  font-size: var(--fs-md);
  line-height: 1.55;
  color: var(--fg-2);
}
.footer-cols {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
}
.footer-h {
  margin: 0 0 12px;
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--fg-3);
}
.footer-col ul {
  display: grid;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.footer-col a {
  font-size: var(--fs-md);
  line-height: 1.45;
  color: var(--fg-2);
  overflow-wrap: anywhere;
  transition: color 0.2s var(--ease);
}
.footer-col a:hover {
  color: var(--fg);
}
.footer-bottom {
  margin-top: 36px;
  padding-top: 18px;
  border-top: 1px solid var(--rule);
}
@media (max-width: 760px) {
  .footer-top {
    grid-template-columns: minmax(0, 1fr);
  }
}
@media (max-width: 480px) {
  .footer-cols {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
/* home and 404: the footer lines up with the centred content column */
.page-home .footer-inner {
  max-width: calc(var(--home-max, 1040px) + 2 * var(--gutter));
  margin-inline: auto;
}
/* /reference/ and module pages without a rail centre .ref-main (reference.css):
   the footer takes the same width and padding, so the two line up */
.page-col:has(> .page-body-ref-wide:not(.page-body-ref-toc)) .footer-inner {
  max-width: calc(var(--content-max) + 120px);
  margin-inline: auto;
  padding-inline: clamp(16px, 3.2vw, 46px);
}

/* ---------- search palette ---------- */
/* A layer (data-depth="surface-2") on the scrim: 18px radius, the sheet shadow, at most
   640px; full screen on phones (Responsive). */
.palette {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: flex;
  justify-content: center;
  /* the box sizes to its results (no stretch to 72vh for "No results") */
  align-items: flex-start;
  padding: 10vh 16px 16px;
  background: var(--scrim);
}
.palette[hidden] {
  display: none !important;
}
.palette-box {
  display: flex;
  flex-direction: column;
  width: min(640px, 100%);
  max-height: 72vh;
  border: 1px solid var(--panel-bd);
  border-radius: var(--radius-lg);
  background: var(--bg);
  color: var(--fg-2);
  box-shadow: var(--sheet-shadow);
  overflow: hidden;
}
@media screen and (prefers-reduced-motion: no-preference) {
  .palette:not([hidden]) {
    animation: layer-fade 0.15s var(--ease);
  }
  .palette:not([hidden]) .palette-box,
  .pa-menu:not([hidden]),
  .env-pop:not([hidden]) {
    animation: layer-rise 0.15s var(--ease-out);
  }
}
@keyframes layer-fade {
  from {
    opacity: 0;
  }
}
@keyframes layer-rise {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
}
.palette-head {
  position: relative;
  display: flex;
  align-items: center;
  flex: none;
  gap: 8px;
  height: 56px;
  padding: 0 12px 0 16px;
  border-bottom: 1px solid var(--rule);
}
/* the leading magnifier only: the close button's icon stays in its button */
.palette-head > .palette-ico {
  position: absolute;
  left: 18px;
  color: var(--fg-3);
  pointer-events: none;
}
/* The input keeps the ring every control has (2px accent, 3px out): 40px high in the 56px
   head and 8px from the close button, so the whole ring shows round it. */
.palette-head input {
  flex: 1;
  min-width: 0;
  height: 40px;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  padding: 0 8px 0 28px;
  font: 400 17px/1 var(--sans);
  letter-spacing: -0.01em;
  color: var(--fg);
}
.palette-head input::placeholder {
  color: var(--fg-3);
  opacity: 1;
}
.palette-head input::-webkit-search-cancel-button {
  display: none;
}
.palette-results {
  flex: 0 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 6px;
  scrollbar-width: thin;
  scrollbar-color: var(--rule-2) transparent;
}
/* a result: the title, then its path (mono) and context; the method chip on the right. The
   active one (aria-selected, arrow keys) and the hovered one get a panel behind the row, the
   active one a 2px hi bar. */
.palette-item {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: 'title badge' 'path badge';
  column-gap: var(--s-3);
  row-gap: 3px;
  align-items: center;
  width: 100%;
  padding: 10px 12px 10px 14px;
  border-radius: var(--radius);
  text-align: left;
  text-decoration: none;
}
.palette-item:hover,
.palette-item[aria-selected='true'] {
  background: var(--panel-2);
}
.palette-item[aria-selected='true']::before {
  content: '';
  position: absolute;
  left: 0;
  top: 8px;
  bottom: 8px;
  width: 2px;
  background: var(--hi);
}
.palette-title {
  grid-area: title;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--fg);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.palette-path {
  grid-area: path;
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.4;
  color: var(--fg-3);
}
.palette-path .palette-ctx {
  flex: none;
  font-family: var(--sans);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.palette-path .palette-ctx::after {
  content: '·';
  margin-left: 6px;
  letter-spacing: 0;
  color: var(--fg-4);
}
.palette-path span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.palette-item .method {
  grid-area: badge;
}
.palette-item mark {
  background: var(--selection);
  color: var(--fg);
  border-radius: 3px;
  padding: 0 1px;
}
.palette-empty {
  padding: 28px 16px;
  text-align: center;
  font-size: var(--fs-md);
  color: var(--fg-3);
}
.palette-foot {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 16px;
  padding: 10px 16px;
  border-top: 1px solid var(--rule);
  font-size: var(--fs-sm);
  color: var(--fg-3);
}
.palette-foot span {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}
/* keyboard hints mean nothing on a touch screen */
@media (pointer: coarse) {
  .palette-foot {
    display: none;
  }
}

/* ---------- drawer overlay ---------- */
.overlay {
  display: none;
}
/* Home and 404 have no sidebar: their drawer only carries the section links
   and "Sign in", for phones, where the header hides them. */
@media (min-width: 1200px) {
  .sidebar-min {
    display: none;
  }
}
.no-sidebar .menu-btn {
  display: none;
}

/* ==========================================================================
   Responsive
   The breakpoints: 1440 / 1360 / 1320 / 1280 / 1199 / 1099 / 899 / 560 (and 380, 350).
   --header-h is 64px on every width; --gutter is fluid (tokens.css).
   Each component's own responsive rules sit in its own section (tables, code blocks,
   prose, hero, cards); this block holds the chrome's.
   ========================================================================== */
@media (max-width: 1440px) {
  /* retune the token only: .page-body reads var(--toc-w), so re-declaring
     grid-template-columns here would override .page-body-wide/.page-body-ref */
  :root {
    --toc-w: 200px;
  }
}
/* The header holds the lockup, the tabs, search, the theme and "Go to Platform" on one line
   down to 900px. The Environment switch is in the API Reference sidebar. */
@media (max-width: 1360px) {
  .search-trigger {
    width: 200px;
  }
}
@media (max-width: 1280px) {
  .areas {
    gap: var(--s-5);
  }
}
@media (max-width: 1320px) {
  :root {
    --sidebar-w: 248px;
    --code-col-w: clamp(340px, 34vw, 460px);
  }
}
@media (max-width: 1199px) {
  .layout {
    grid-template-columns: minmax(0, 1fr);
  }
  .page-body {
    grid-template-columns: minmax(0, 1fr);
  }
  .toc {
    display: none;
  }
  /* the rail is hidden from here down, so every one-column reference page
     centres its content instead of leaving the right-hand side empty */
  .page-body-ref-wide .ref-main {
    margin-inline: auto;
    width: 100%; /* see .page-body-ref-wide:not(.page-body-ref-toc) .ref-main */
  }
  .page-col:has(> .page-body-ref-wide) .footer-inner {
    max-width: calc(var(--content-max) + 120px);
    margin-inline: auto;
    padding-inline: clamp(16px, 3.2vw, 46px);
  }
  .menu-btn {
    display: inline-flex;
    margin-left: 10px;
  }
  .no-sidebar .menu-btn {
    display: none;
  }
  .brand {
    width: auto;
    padding-left: 8px;
    padding-right: 8px;
  }
  .no-sidebar .brand {
    padding-left: 20px;
  }
  .brand .logo {
    height: 22px;
  }
  /* 900–1199px: the three tabs, the search and "Sign in" must fit on one line */
  .areas {
    padding-left: 16px;
    gap: 20px;
  }
  .search-trigger {
    width: 160px;
  }
  /* the sidebar becomes the drawer: the chrome depth, over a scrim. It arrives by opacity
     and 12px of travel (Signal: nothing moves further), in the motion block below. */
  .sidebar {
    position: fixed;
    z-index: 60;
    top: 0;
    left: 0;
    bottom: 0;
    height: auto;
    width: min(320px, 86vw);
    padding-top: 0;
    /* a link reached by Shift+Tab stops below the sticky drawer head, not under it */
    scroll-padding-top: calc(var(--header-h) + 8px);
    box-shadow: var(--sheet-shadow);
    opacity: 0;
    transform: translateX(-12px);
    visibility: hidden;
  }
  .nav-open .sidebar {
    opacity: 1;
    transform: none;
    visibility: visible;
  }
  .overlay {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 55;
    background: var(--scrim);
    opacity: 0;
    pointer-events: none;
  }
  .nav-open .overlay {
    opacity: 1;
    pointer-events: auto;
  }
  .nav-open body {
    overflow: hidden;
  }
  .drawer-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: var(--header-h);
    margin: 0 -14px 16px -16px;
    padding: 0 10px 0 20px;
    border-bottom: 1px solid var(--rule);
    position: sticky;
    top: 0;
    background: var(--bg);
    z-index: 4; /* above the rows (1, with the glide panel), the branch lines (2), the Environment switch (3) */
  }
  /* the Environment switch sticks under the drawer's head */
  .sidebar-env {
    top: var(--header-h);
    margin: 0 -14px var(--s-3) -16px;
    padding-top: var(--s-2);
  }
  .sidebar:has(.sidebar-env) {
    scroll-padding-top: calc(var(--header-h) + 128px);
  }
  .drawer-head .logo {
    height: 22px;
  }
}
@media screen and (max-width: 1199px) and (prefers-reduced-motion: no-preference) {
  .sidebar {
    transition: opacity 0.25s var(--ease-out), transform 0.25s var(--ease-out), visibility 0s linear 0.25s;
  }
  .nav-open .sidebar {
    transition: opacity 0.25s var(--ease-out), transform 0.25s var(--ease-out);
  }
  .overlay {
    transition: opacity 0.25s var(--ease);
  }
}
@media (max-width: 1099px) {
  .areas {
    gap: 18px;
  }
  .search-trigger {
    width: 36px;
    height: 36px;
    padding: 0;
    justify-content: center;
    border-color: transparent;
    background: transparent;
  }
  .search-trigger:hover {
    border-color: transparent;
    background: var(--panel);
    color: var(--fg);
  }
  .search-trigger .search-label,
  .search-trigger kbd {
    display: none;
  }
}
@media (max-width: 899px) {
  .topbar {
    gap: 4px;
  }
  .menu-btn,
  .no-sidebar .menu-btn {
    display: inline-flex;
    margin-left: 6px;
  }
  .brand,
  .no-sidebar .brand {
    padding-left: 2px;
    padding-right: 4px;
  }
  .brand .logo {
    height: 22px;
  }
  .areas {
    display: none;
  }
  .top-actions {
    padding-right: 10px;
    gap: 2px;
  }
  .top-actions > .btn-login {
    display: none;
  }
  /* the drawer's section links: rows, the current one on a panel with a hi bar */
  .drawer-areas {
    display: grid;
    gap: 2px;
    margin: 0 0 18px;
    padding: 0 0 16px;
    border-bottom: 1px solid var(--rule);
  }
  .drawer-areas a {
    display: flex;
    align-items: center;
    min-height: 40px;
    padding: 0 12px;
    border-radius: 0 8px 8px 0;
    font-size: 15px;
    font-weight: 500;
    letter-spacing: -0.01em;
    color: var(--fg-2);
    transition: color 0.2s var(--ease), background-color 0.2s var(--ease);
  }
  .drawer-areas a:hover {
    color: var(--fg);
    background: var(--panel);
  }
  .drawer-areas a[aria-current] {
    color: var(--fg);
    font-weight: 600;
    background: var(--panel);
    box-shadow: inset 2px 0 0 var(--hi);
  }
  .drawer-foot {
    display: block;
    margin-top: 24px;
    padding-top: 16px;
    border-top: 1px solid var(--rule);
  }
  .drawer-foot .btn-login {
    display: flex;
    width: 100%;
    justify-content: center;
    margin: 0;
  }
  /* the minimal drawer (home, 404, changelog): the section links, then "Sign in", one rule */
  .drawer-areas + .drawer-foot {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
  }
  .main {
    padding: 24px var(--gutter) 56px;
  }
  .toc {
    padding-top: 24px;
  }
  .footer-inner,
  .page-col:has(> .page-body-ref-wide) .footer-inner {
    padding: 20px var(--gutter) 64px;
  }
  .palette {
    padding: 0;
  }
  .palette-box {
    width: 100%;
    max-height: 100%;
    height: 100%;
    border: 0;
    border-radius: 0;
  }
}
@media (max-width: 560px) {
  /* phones: the header keeps the mark and "Deepinfo" (290 of the lockup's 460 units, which
     lockup() slices from the left) and drops "| Docs": the full lockup would push the header
     past a 375px screen */
  .brand .logo {
    aspect-ratio: 290 / 56;
  }
  .brand .logo .logo-suffix {
    display: none;
  }
  /* The title takes the column's whole width and "Copy page" (with the changelog's feed
     button) goes under it: beside the buttons a 32px title had 256px at 375 (four lines for
     "Compromised Employee Credential Mark False Positive") and "Compromised" alone did not
     fit at 320. */
  .page-head > h1:first-child,
  .page-head:has(> :nth-child(3)) > h1:first-child {
    flex-basis: 100%;
  }
  .page-actions,
  .page-head > .cl-feed {
    top: 0;
  }
  /* the pager stacks: Previous, then Next, both from the left */
  .pager {
    grid-template-columns: minmax(0, 1fr);
  }
  .pager > span:empty {
    display: none;
  }
  .pager-next {
    grid-column: auto;
    align-items: flex-start;
    text-align: left;
  }
}
@media (max-width: 380px) {
  .brand .logo {
    height: 20px;
  }
}
/* Motion (docs/DESIGN-SIGNAL.md §7) plays only under
   @media screen and (prefers-reduced-motion: no-preference); this block is the safety net for
   everything else: with reduced motion nothing moves, and every element shows its final state
   (no JavaScript and print show it too). */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    transition: none !important;
    animation: none !important;
    scroll-behavior: auto !important;
  }
}
/* Print: the page prints dark on white in either theme, code included (the --print-* tokens,
   every colour 4.5:1 or better on white). The tokens are set again for print on :root and on
   every depth, !important so the dark theme's blocks cannot win. */
@media print {
  /* method chips: ink on paper, whatever the theme or the panel */
  .method {
    --m: var(--print-fg) !important;
  }
  :root,
  [data-depth] {
    --bg: var(--print-bg) !important;
    --bg-2: var(--print-bg) !important;
    --bg-3: var(--print-bg) !important;
    --fg: var(--print-fg) !important;
    --fg-2: var(--print-fg) !important;
    --fg-3: var(--print-muted) !important;
    --fg-4: var(--print-muted) !important;
    --fg-dim: var(--print-fg) !important;
    --em: var(--print-kw) !important;
    --link: var(--print-fg) !important;
    --hi: var(--print-kw) !important;
    --accent: var(--print-kw) !important;
    --ok: var(--print-fg) !important;
    --warn: var(--print-fg) !important;
    --exposure: var(--print-fg) !important;
    --rule: var(--print-rule) !important;
    --rule-2: var(--print-rule) !important;
    --rule-3: var(--print-muted) !important;
    --panel: var(--print-bg) !important;
    --panel-2: var(--print-bg) !important;
    --panel-bd: var(--print-rule) !important;
    --panel-shadow: none !important;
    --shadow-sm: none !important;
    --sheet-shadow: none !important;
    --code-bg: var(--print-bg) !important;
    --depth-code: var(--print-bg) !important;
    --depth-code-bd: var(--print-rule) !important;
    --logo-fg: var(--print-kw) !important;
    --logo-suffix: var(--print-muted) !important;
    --code-fg: var(--print-fg) !important;
    --code-keyword: var(--print-kw) !important;
    --code-string: var(--print-str) !important;
    --code-number: var(--print-num) !important;
    --code-punct: var(--print-key) !important;
    --code-comment: var(--print-com) !important;
    --code-tab: var(--print-muted) !important;
    --code-tab-on: transparent !important;
    --code-rule: var(--print-rule) !important;
    --code-ok: var(--print-fg) !important;
    --code-ring: var(--print-kw) !important;
    color-scheme: light !important;
  }
  .topbar,
  .sidebar,
  .toc,
  .overlay,
  .palette,
  .pager,
  .skip,
  .copy,
  .tabs-list,
  .heading-anchor::after,
  .page-actions,
  .feedback,
  .toast,
  .postman-dl,
  .nf-suggest {
    display: none !important;
  }
  html,
  body {
    background: var(--print-bg);
    color: var(--print-fg);
  }
  .layout,
  .page-col,
  .page-body {
    display: block;
  }
  /* every tab panel prints, one after the other */
  .tab-panel[hidden] {
    display: block !important;
  }
  /* code prints dark on white, with the print syntax colours */
  .code-block {
    background: var(--print-bg) !important;
    color: var(--print-fg) !important;
    border: 1px solid var(--print-rule) !important;
    box-shadow: none !important;
    --t-key: var(--print-key);
    --t-str: var(--print-str);
    --t-num: var(--print-num);
    --t-bool: var(--print-kw);
    --t-null: var(--print-kw);
    --t-kw: var(--print-kw);
    --t-com: var(--print-com);
    --t-punc: var(--print-fg);
    --t-op: var(--print-fg);
    --t-fn: var(--print-fg);
    --t-var: var(--print-fg);
  }
  .code-head {
    background: var(--print-bg) !important;
    border-bottom-color: var(--print-rule) !important;
  }
  .code-title {
    color: var(--print-muted) !important;
  }
  .code-block pre {
    color: var(--print-fg) !important;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
  }
  .code-block,
  .callout,
  .card,
  tr {
    break-inside: avoid;
  }
  h2,
  h3 {
    break-after: avoid;
  }
}

/* ---------- small utilities ---------- */
.hero-note {
  margin-top: var(--sp-5);
}
