/**
 * JobFront Docs — brand theme.
 *
 * Layered on top of vendored Bootstrap 5.3: Bootstrap supplies the grid,
 * utilities and the offcanvas/collapse behaviours; everything visual below is
 * ours. Bootstrap's own look is re-pointed at the brand through its `--bs-*`
 * custom properties rather than by overriding its rules, so a Bootstrap
 * upgrade doesn't fight this file.
 *
 * Cream + navy, Satoshi, LIGHT ONLY. There is no dark mode and no toggle: the
 * brand is a cream page with navy ink, and a dark variant would be a different
 * product.
 *
 * Token values are lifted verbatim from the approved prototype
 * (jobfront/docs/prototype/jobfront-docs-hub-brand.html), which encodes
 * jobfront-app/docs/DESIGN_SYSTEM.md.
 *
 * Component classes are `jf-` prefixed so they can never collide with a
 * Bootstrap class of the same name (.card, .badge, .table all exist there).
 */

/* ── Satoshi ─────────────────────────────────────────────────────────────
 * Served from /static/fonts. The prototype inlines these as data URIs only
 * because the Artifact CSP blocks font requests; on our own origin, files
 * cache properly and don't bloat every HTML response.
 */
@font-face {
  font-family: 'Satoshi';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/static/fonts/Satoshi-Regular.otf') format('opentype');
}
@font-face {
  font-family: 'Satoshi';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/static/fonts/Satoshi-Medium.otf') format('opentype');
}
@font-face {
  font-family: 'Satoshi';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/static/fonts/Satoshi-Bold.otf') format('opentype');
}
@font-face {
  font-family: 'Satoshi';
  font-style: normal;
  font-weight: 900;
  font-display: swap;
  src: url('/static/fonts/Satoshi-Black.otf') format('opentype');
}

:root {
  /* ── ground + surfaces ── */
  --paper: #faf6e8;
  --surface: #fffdf7;
  --surface-2: #f3ecd6;

  /* ── ink (brand navy) ── */
  --ink: #1a284f;
  --muted: #586183;
  --faint: #8c93a6;
  --line: rgba(26, 40, 79, 0.13);
  --line-2: rgba(26, 40, 79, 0.22);

  /* ── interactive accent ── */
  --accent: #2f4c9e;
  --accent-ink: #233b7d;
  --accent-soft: rgba(47, 76, 158, 0.1);

  /* ── semantic ── */
  --live: #12a150;
  --live-soft: rgba(18, 161, 80, 0.13);
  --warn: #b9791a;
  --crit: #d33f57;
  --crit-soft: rgba(211, 63, 87, 0.1);

  /* Gold hairline — the marketing cream+gold+navy detail. */
  --gold: #e6d580;

  /* Code rails stay dark navy inside this light theme. */
  --code-bg: #0d1320;
  --code-2: #141c2c;
  --code-ink: #e6ecf7;
  --code-mut: #8994ab;
  --code-line: rgba(150, 170, 210, 0.14);

  --shadow: 0 1px 2px rgba(26, 40, 79, 0.05), 0 10px 30px -16px rgba(26, 40, 79, 0.2);
  --shadow-sm: 0 1px 2px rgba(26, 40, 79, 0.06);
  --sel: rgba(47, 76, 158, 0.18);

  --radius: 11px;
  --radius-sm: 8px;
  --radius-xs: 6px;

  --sans: 'Satoshi', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --mono: ui-monospace, 'SF Mono', 'JetBrains Mono', Menlo, Consolas, monospace;

  --topbar-h: 58px;
  --sidebar-w: 262px;
  --rail-w: 400px;
  --maxw: 1320px;

  /* ── re-point Bootstrap at the brand ── */
  --bs-body-bg: var(--paper);
  --bs-body-color: var(--ink);
  --bs-body-font-family: var(--sans);
  --bs-body-font-size: 16px;
  --bs-body-line-height: 1.65;
  --bs-emphasis-color: var(--ink);
  --bs-secondary-color: var(--muted);
  --bs-tertiary-color: var(--faint);
  --bs-border-color: var(--line);
  --bs-border-radius: var(--radius-sm);
  --bs-link-color: var(--accent);
  --bs-link-hover-color: var(--accent-ink);
  --bs-link-color-rgb: 47, 76, 158;
  --bs-font-monospace: var(--mono);
  --bs-primary: var(--accent);
  --bs-focus-ring-color: rgba(47, 76, 158, 0.3);
  /* Bootstrap ships a magenta `code` colour that has nothing to do with this
   * palette. Without this it leaks into any inline code outside .prose — the
   * page lede, the API reference header — and reads as an error state. */
  --bs-code-color: var(--accent-ink);
}

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

html {
  scroll-behavior: smooth;
  /* Anchor targets must clear the sticky top bar. */
  scroll-padding-top: calc(var(--topbar-h) + 16px);
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

::selection {
  background: var(--sel);
}

a {
  color: var(--accent);
  text-decoration: none;
}
a:hover {
  text-decoration: underline;
}

h1,
h2,
h3,
h4 {
  margin: 0;
  line-height: 1.18;
  letter-spacing: -0.035em;
  text-wrap: balance;
  font-weight: 800;
  color: var(--ink);
}
h1 {
  font-size: clamp(30px, 4vw, 44px);
}
h2 {
  font-size: 26px;
  margin-top: 2.2rem;
  margin-bottom: 0.6rem;
  scroll-margin-top: calc(var(--topbar-h) + 16px);
}
h3 {
  font-size: 19px;
  margin-top: 1.6rem;
  margin-bottom: 0.4rem;
  scroll-margin-top: calc(var(--topbar-h) + 16px);
}
h4 {
  font-size: 16px;
  margin-top: 1.3rem;
  margin-bottom: 0.3rem;
}

code,
kbd,
.mono {
  font-family: var(--mono);
}

button {
  font-family: inherit;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

/* Numbers are the product — always tabular so columns line up. */
.tnum,
.mono,
table td {
  font-variant-numeric: tabular-nums;
}

.jf-eyebrow {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--faint);
  font-weight: 600;
  display: block;
}
.jf-muted {
  color: var(--muted);
}
.jf-lede {
  font-size: 18px;
  color: var(--muted);
  max-width: 66ch;
  /* Bottom margin matters: the lede is the page summary and the body starts
   * immediately after it, so without a gap the two read as one paragraph. */
  margin: 14px 0 26px;
}
/* Inline code anywhere, not just inside .prose — the lede and the API
 * reference header both carry it. */
:not(pre) > code {
  font-size: 88%;
  border: 1px solid var(--line);
  color: var(--accent-ink);
  background: var(--accent-soft);
  border-radius: var(--radius-xs);
  padding: 0.12em 0.36em;
}

/* ── homepage hero ───────────────────────────────────────────────────── */

.jf-hero {
  padding: 6px 0 2px;
}
.jf-hero h1 {
  font-size: clamp(32px, 4.6vw, 52px);
  font-weight: 900;
  margin-top: 18px;
}
.jf-hero h1 .grad {
  background: linear-gradient(100deg, var(--ink), var(--accent));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.jf-hero .jf-lede {
  font-size: 19px;
  margin-top: 18px;
}
.jf-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--line);
  padding: 5px 12px;
  border-radius: 30px;
}
.jf-pill .jf-dot {
  color: var(--live);
}
.jf-herocta {
  display: flex;
  gap: 12px;
  margin-top: 26px;
  flex-wrap: wrap;
}
.jf-herocta .jf-btn {
  height: 40px;
  padding: 0 18px;
  font-size: 14px;
}

/* ── skip link ───────────────────────────────────────────────────────── */
/* Visually gone until it has keyboard focus, then it drops in over the
 * topbar. Never display:none — that would remove it from the tab order,
 * which is the one place it must exist. */

.skiplink {
  position: fixed;
  top: -48px;
  left: 12px;
  z-index: 200;
  padding: 9px 16px;
  border-radius: var(--radius-sm);
  background: var(--ink);
  color: #fff;
  font-weight: 700;
  font-size: 13.5px;
  text-decoration: none;
  transition: top 0.15s ease;
}
.skiplink:focus {
  top: 10px;
  color: #fff;
}

/* ── top bar ─────────────────────────────────────────────────────────── */

.topbar {
  position: sticky;
  top: 0;
  z-index: 1040;
  height: var(--topbar-h);
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 0 20px;
  background: color-mix(in srgb, var(--surface) 86%, transparent);
  backdrop-filter: saturate(1.4) blur(10px);
  border-bottom: 1px solid var(--line);
}
.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  letter-spacing: -0.02em;
  font-size: 16px;
  color: var(--ink);
}
.brand:hover {
  text-decoration: none;
  color: var(--ink);
}
/* The JF monogram, matching the mark on jobfront.com: a hard-cornered navy
   square with the letters centred in mono. Square on purpose — the corner
   radius and the gradient this replaced were this site's own invention, and
   the docs should not ship a second version of the company's logo. */
.logomark {
  width: 24px;
  height: 24px;
  flex: 0 0 auto;
  background: var(--ink);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.02em;
}
@keyframes jf-pulse {
  0% {
    box-shadow: 0 0 0 0 var(--live-soft);
  }
  70% {
    box-shadow: 0 0 0 7px transparent;
  }
  100% {
    box-shadow: 0 0 0 0 transparent;
  }
}

.topnav {
  display: flex;
  gap: 2px;
  margin-left: 6px;
}
.topnav a {
  padding: 6px 11px;
  border-radius: 8px;
  color: var(--muted);
  font-weight: 550;
  font-size: 14px;
}
.topnav a:hover {
  background: var(--accent-soft);
  color: var(--ink);
  text-decoration: none;
}
.topnav a.on {
  color: var(--ink);
  background: var(--accent-soft);
}

/* The rule that splits the documentation sections from the two entries that
   are not documentation. Wider margins than the 2px between siblings, so the
   break is read as a grouping rather than as a stray pixel. */
.topnav .navsep {
  width: 1px;
  height: 20px;
  margin: 0 12px;
  background: var(--line-2);
  flex: 0 0 auto;
  align-self: center;
}

/* Data coverage is a live view over the production index, not a page of prose,
   and it is the entry we most want found — so it carries more weight than its
   neighbours and a dot in the same green the live tiles and chips use.
   Deliberately NOT the animated .jf-dot: a pulse is fine on a dashboard you
   chose to open, and wearing on a bar that is on screen the whole time. */
.topnav a.navlive {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--ink);
  font-weight: 650;
}
.topnav a.navlive::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--live);
  flex: 0 0 auto;
}

.searchbtn {
  display: flex;
  align-items: center;
  gap: 9px;
  height: 34px;
  padding: 0 10px 0 12px;
  min-width: 210px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 9px;
  color: var(--faint);
  font-size: 13.5px;
  cursor: pointer;
}
.searchbtn:hover {
  border-color: var(--line-2);
}
.searchbtn kbd {
  margin-left: auto;
  font-size: 11px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: 5px;
  padding: 1px 5px;
  color: var(--muted);
}

.iconbtn {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--muted);
  cursor: pointer;
}
.iconbtn:hover {
  color: var(--ink);
  border-color: var(--line-2);
}

.jf-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  height: 34px;
  padding: 0 14px;
  border-radius: 9px;
  font-weight: 600;
  font-size: 13.5px;
  cursor: pointer;
  border: 1px solid transparent;
  white-space: nowrap;
}
.jf-btn.primary {
  background: var(--accent);
  color: #fff;
  box-shadow: 0 2px 10px -3px var(--accent);
}
.jf-btn.primary:hover {
  background: var(--accent-ink);
  color: #fff;
  text-decoration: none;
}
.jf-btn.ghost {
  background: transparent;
  border-color: var(--line-2);
  color: var(--ink);
}
.jf-btn.ghost:hover {
  background: var(--surface-2);
  text-decoration: none;
  color: var(--ink);
}

/* Platform status — quiet by default, because a link that shouts implies
   something is wrong. */
.statuslink {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  height: 34px;
  padding: 0 10px;
  border-radius: 9px;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  text-decoration: none;
  white-space: nowrap;
}

.statuslink span {
  font-size: 10px;
  opacity: 0.7;
}

.statuslink:hover {
  color: var(--ink);
  background: var(--surface-2);
}

/* ── shell ───────────────────────────────────────────────────────────── */

.shell {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  max-width: var(--maxw);
  margin: 0 auto;
  min-height: calc(100vh - var(--topbar-h));
}
.shell.with-toc {
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr) 210px;
}
.shell.full {
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
}

/* A page that IS the thing the reader came for — the coverage explorer — drops
   the left navigation entirely and takes its 262px for content. There is no
   toggle: the page should look like an ordinary page that happens to be wide,
   not like one wearing a control no other page has. The way out is the topbar,
   which carries a Data coverage entry precisely so this page is reachable
   without a sidebar, plus ⌘K search and the field-reference links on the page.

   Scoped above the drawer breakpoint. Below it the sidebar is a fixed
   off-canvas drawer and IS the whole of a phone's navigation, since `.topnav`
   is hidden there — so on a small screen this page keeps its sidebar like
   every other. */
@media (min-width: 861px) {
  .shell.nav-hidden {
    grid-template-columns: minmax(0, 1fr);
  }
  .shell.nav-hidden.with-toc {
    grid-template-columns: minmax(0, 1fr) 210px;
  }
  .shell.nav-hidden > .sidebar {
    display: none;
  }
}

/* The other direction, for the one page whose sidebar carries a list: the API
   reference. 356px is the narrowest width that keeps every path in the spec on
   one line, and at 262px twelve of the twenty-four wrapped to two.

   Spent on this page and nowhere else, for two reasons. Every other page would
   give up 94px of content column for nav labels that already fit, and the
   column is not that far from where it starts costing something — `.jf-tiles`
   drops a column around 744px, see the note on it. And this is the one page
   with no contents rail, so it is the one page with 94px to give: 964px of
   content at the full shell, against the 848px a `with-toc` page gets.

   Above 1280px only. What the 94px comes out of is the prose column beside
   the reference's 400px code rail, and that column is the floor here, not the
   content column: 426px at the full shell, 388px at this breakpoint. A lower
   one is where it goes wrong — the same override at 1180px leaves that column
   296px. Below the breakpoint the page cannot spare the width and the paths
   wrap instead, which is what they do in the drawer below 861px too — a fixed
   280px that does not read this. */
@media (min-width: 1280px) {
  .shell.api-nav {
    --sidebar-w: 356px;
  }
}

.sidebar {
  border-right: 1px solid var(--line);
  padding: 18px 10px 60px;
  position: sticky;
  top: var(--topbar-h);
  align-self: start;
  height: calc(100vh - var(--topbar-h));
  overflow: auto;
}

/* Each section of the nav is its own container, so a long sidebar reads as
   five short lists rather than one thirty-item one. Separation comes from the
   border and the gap between groups, not from colour — every group is the
   same flat white as the rest of the page's cards, which keeps the sidebar
   calm instead of banding it into a four-step ladder that implied a meaning
   the sections don't carry. */
.navgroup {
  margin-bottom: 10px;
  padding: 10px 7px 8px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

.navgroup > .lbl {
  padding: 0 9px 7px;
  display: block;
  color: var(--faint);
}
.navgroup a {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 6px 9px;
  border-radius: 8px;
  color: var(--muted);
  font-size: 13.5px;
  font-weight: 500;
}
/* Translucent rather than a flat colour: the hover has to be visible on all
   four group backgrounds, and a fixed fill disappears against one of them. */
.navgroup a:hover {
  background: color-mix(in srgb, var(--ink) 8%, transparent);
  color: var(--ink);
  text-decoration: none;
}
.navgroup a.on {
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-weight: 650;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 22%, transparent);
}
.navgroup a .tag {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #fff;
  background: var(--live);
  padding: 1px 5px;
  border-radius: 20px;
  font-weight: 700;
}

/* A nav row that opens in place, for a page whose own contents are a list —
   the API reference and its endpoints. The list sits under the row it belongs
   to, indented against a rule so it reads as part of that row rather than as a
   sixth section of the sidebar. */
.navexp .exprow {
  display: flex;
  align-items: center;
  gap: 2px;
}
.navexp .exprow > a {
  flex: 1;
  min-width: 0;
}
.expbtn {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--faint);
  cursor: pointer;
}
.expbtn:hover {
  background: color-mix(in srgb, var(--ink) 8%, transparent);
  color: var(--ink);
}
.expbtn svg {
  transition: transform 0.18s;
}
.navexp.open .expbtn svg {
  transform: rotate(90deg);
}
@media (prefers-reduced-motion: reduce) {
  .expbtn svg {
    transition: none;
  }
}
/* Shut unless the row says otherwise. The server renders the class, so the
   list on the page it belongs to is never painted closed and then opened. */
.navexp > .endpointnav {
  display: none;
  margin: 2px 0 4px;
  padding-left: 6px;
  border-left: 1px solid var(--line);
}
.navexp.open > .endpointnav {
  display: block;
}

.content {
  padding: 34px clamp(20px, 4vw, 52px) 90px;
  min-width: 0;
}

.crumbs {
  display: flex;
  gap: 8px;
  align-items: center;
  font-size: 12.5px;
  color: var(--faint);
  margin-bottom: 14px;
}

/* Right-hand contents rail. */
.toc {
  position: sticky;
  top: calc(var(--topbar-h) + 24px);
  align-self: start;
  padding: 34px 16px 40px 0;
  font-size: 12.5px;
  max-height: calc(100vh - var(--topbar-h));
  overflow: auto;
}
.toc .lbl {
  margin-bottom: 10px;
}
.toc a {
  display: block;
  color: var(--muted);
  padding: 4px 0 4px 10px;
  border-left: 2px solid var(--line);
  line-height: 1.4;
}
.toc a:hover {
  color: var(--ink);
  text-decoration: none;
}
.toc a.on {
  color: var(--accent-ink);
  border-left-color: var(--accent);
  font-weight: 650;
}
.toc a.lvl-3 {
  padding-left: 20px;
  font-size: 12px;
}

/* ── prose ───────────────────────────────────────────────────────────── */

.prose p,
.prose li {
  max-width: 68ch;
}
.prose p {
  margin: 0 0 1rem;
}
.prose ul,
.prose ol {
  padding-left: 1.2rem;
  margin-bottom: 1rem;
}
.prose li {
  margin-bottom: 0.35rem;
}
.prose hr {
  border: 0;
  border-top: 1px solid var(--line);
  margin: 2rem 0;
}
.prose blockquote {
  margin: 1rem 0;
  padding: 2px 0 2px 16px;
  border-left: 3px solid var(--accent);
  color: var(--muted);
}
.prose img {
  max-width: 100%;
  height: auto;
}

/* ── code blocks ─────────────────────────────────────────────────────── */

.codewrap {
  background: var(--code-bg);
  border: 1px solid var(--code-line);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  margin: 1rem 0;
}
.codewrap .bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--code-line);
  background: var(--code-2);
}
.codewrap .bar .fn {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--code-mut);
}
.codewrap .cp {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--code-mut);
  background: transparent;
  border: 1px solid var(--code-line);
  border-radius: 7px;
  padding: 3px 9px;
  cursor: pointer;
}
.codewrap .cp:hover {
  color: var(--code-ink);
}
.codewrap pre,
.codehilite pre {
  margin: 0;
  padding: 14px 16px;
  overflow: auto;
  font-family: var(--mono);
  font-size: 12.6px;
  line-height: 1.65;
  color: var(--code-ink);
  background: transparent;
}
.codehilite {
  background: var(--code-bg);
  border-radius: var(--radius);
  overflow: hidden;
}
.codewrap .codehilite {
  border-radius: 0;
}
.codewrap pre::selection,
.codewrap pre ::selection {
  background: rgba(120, 150, 255, 0.28);
}

/* Pygments token colours, tuned to the prototype's navy code rail. Only the
 * token classes that actually appear in JSON / bash / python / JS samples are
 * themed; anything else inherits --code-ink and stays legible. */
.codehilite .k,
.codehilite .kd,
.codehilite .kn,
.codehilite .kc,
.codehilite .kr,
.codehilite .kt,
.codehilite .ow {
  color: #7ea2ff;
}
.codehilite .s,
.codehilite .s1,
.codehilite .s2,
.codehilite .sb,
.codehilite .sd,
.codehilite .se,
.codehilite .sh,
.codehilite .si,
.codehilite .sx,
.codehilite .sr,
.codehilite .ss {
  color: #8fd39a;
}
.codehilite .m,
.codehilite .mi,
.codehilite .mf,
.codehilite .mh,
.codehilite .mo,
.codehilite .il {
  color: #f2c078;
}
.codehilite .c,
.codehilite .c1,
.codehilite .cm,
.codehilite .cp,
.codehilite .cs {
  color: #6b7794;
  font-style: italic;
}
.codehilite .nt,
.codehilite .na {
  color: #7ea2ff;
}
.codehilite .nf,
.codehilite .nx,
.codehilite .nb {
  color: #c4cee0;
}
.codehilite .p,
.codehilite .o {
  color: #c4cee0;
}
.codehilite .err {
  color: var(--code-ink);
  background: transparent;
}

/* Content tabs — multi-language examples on a prose page. The header row is
 * built by docs.js from each pane's `data-label`, so the Markdown source only
 * carries the panes. */
.jf-tabs {
  margin: 1rem 0;
}
.jf-tabhead {
  display: flex;
  gap: 3px;
  border-bottom: 1px solid var(--line);
  margin-bottom: -1px;
}
.jf-tabhead button {
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  padding: 7px 12px;
  cursor: pointer;
}
.jf-tabhead button:hover {
  color: var(--ink);
}
.jf-tabhead button.on {
  color: var(--accent-ink);
  border-bottom-color: var(--accent);
}
.jf-tabs [data-tab][hidden] {
  display: none;
}

.langtabs {
  display: flex;
  gap: 3px;
  padding: 7px 10px 0;
  background: var(--code-2);
}
.langtabs button {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--code-mut);
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  padding: 5px 9px;
  cursor: pointer;
}
.langtabs button.on {
  color: var(--code-ink);
  border-color: var(--accent);
}

/* ── tables ──────────────────────────────────────────────────────────── */

.jf-tablewrap,
.prose table {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: auto;
  box-shadow: var(--shadow-sm);
  background: var(--surface);
  margin: 1rem 0;
  display: block;
  max-width: 100%;
}
.jf-tablewrap table {
  margin: 0;
  border: 0;
  box-shadow: none;
  display: table;
  width: 100%;
}
table {
  border-collapse: collapse;
  width: 100%;
  font-size: 13.5px;
}
thead th {
  background: var(--surface-2);
  text-align: left;
  padding: 11px 14px;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--faint);
  font-weight: 650;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
tbody td {
  padding: 11px 14px;
  border-bottom: 1px solid var(--line);
  vertical-align: top;
}
tbody tr:last-child td {
  border-bottom: 0;
}
tbody tr:hover {
  background: var(--surface-2);
}

/* ── admonitions (Python-Markdown `admonition` extension) ────────────── */

.admonition {
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  background: var(--surface-2);
  border-radius: var(--radius-sm);
  padding: 13px 16px;
  font-size: 13.5px;
  color: var(--muted);
  margin: 1.2rem 0;
}
.admonition p:last-child {
  margin-bottom: 0;
}
.admonition-title {
  font-weight: 700;
  color: var(--ink);
  margin: 0 0 0.4rem;
  font-size: 13.5px;
}
.admonition.tip,
.admonition.note,
.admonition.live {
  border-left-color: var(--live);
}
.admonition.warning {
  border-left-color: var(--warn);
}
.admonition.danger {
  border-left-color: var(--crit);
}
.admonition b,
.admonition strong {
  color: var(--ink);
}

/* ── component vocabulary ────────────────────────────────────────────── */

.jf-grid2,
.jf-grid3,
.jf-grid4,
.jf-gridauto {
  display: grid;
  gap: 16px;
  margin: 16px 0;
  align-items: start;
}
.jf-grid2 {
  grid-template-columns: 1fr 1fr;
}
.jf-grid3 {
  grid-template-columns: repeat(3, 1fr);
}
.jf-grid4 {
  grid-template-columns: repeat(4, 1fr);
}
/* For a set whose size does not divide into a fixed track count — five audience
   cards, say. The column count follows the width rather than being pinned at
   three, so the cards reflow continuously (3+2, then 2+2+1, then one per row)
   and never get squeezed below a readable 232px. This class is deliberately
   absent from the breakpoint overrides below: the minmax already does what they
   do, and a fixed `repeat(n, 1fr)` there would undo it. */
.jf-gridauto {
  grid-template-columns: repeat(auto-fit, minmax(232px, 1fr));
}
/* Cards read as one comparison row rather than four separate notes. Opt-in,
   because the dashboard grids deliberately keep their natural heights. */
.jf-grid2.even,
.jf-grid3.even,
.jf-grid4.even,
.jf-gridauto.even {
  align-items: stretch;
}

.jf-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 20px;
  box-shadow: var(--shadow-sm);
}
.jf-card h3 {
  font-size: 16.5px;
  margin: 0 0 6px;
  display: flex;
  align-items: center;
  gap: 9px;
}
.jf-card p {
  font-size: 14px;
  color: var(--muted);
  margin: 0;
  max-width: none;
}
a.jf-card {
  display: block;
  color: inherit;
  transition: transform 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease;
}
a.jf-card:hover {
  transform: translateY(-2px);
  border-color: var(--line-2);
  box-shadow: var(--shadow);
  text-decoration: none;
}

/* ── error catalog ─────────────────────────────────────────────────────
   The left rule carries the only thing a reader needs at a glance: green =
   nothing wrong, amber = back off and try again, red = your request is
   wrong and will stay wrong. */

.jf-errorgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(258px, 1fr));
  gap: 14px;
  margin: 22px 0 26px;
}

.jf-errcard {
  display: grid;
  gap: 3px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--line-2);
  border-radius: var(--radius);
  padding: 15px 17px;
  color: inherit;
  box-shadow: var(--shadow-sm);
  transition: transform 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease;
}

.jf-errcard:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow);
  text-decoration: none;
}

.jf-errcard .c {
  font-family: var(--mono);
  font-size: 21px;
  font-weight: 680;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.jf-errcard b {
  font-size: 14.5px;
}

.jf-errcard .d {
  font-size: 13px;
  color: var(--muted);
}

.jf-errcard .d code {
  font-size: 12px;
}

.jf-errcard .r {
  margin-top: 8px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--faint);
}

.jf-errcard.ok {
  border-left-color: var(--live);
}
.jf-errcard.ok .c,
.jf-errcard.ok .r {
  color: var(--live);
}

.jf-errcard.soft {
  border-left-color: var(--warn);
}
.jf-errcard.soft .c,
.jf-errcard.soft .r {
  color: var(--warn);
}

.jf-errcard.hard {
  border-left-color: var(--crit);
}
.jf-errcard.hard .c,
.jf-errcard.hard .r {
  color: var(--crit);
}

.jf-statstrip {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--gold);
  border-radius: var(--radius);
  overflow: hidden;
  margin: 26px 0;
}
.jf-statstrip .cell {
  background: var(--surface);
  padding: 16px 18px;
}
.jf-statstrip .k {
  font-family: var(--mono);
  font-size: 26px;
  font-weight: 680;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.jf-statstrip .l {
  font-size: 12px;
  color: var(--muted);
  margin-top: 2px;
  display: flex;
  align-items: center;
  gap: 6px;
}

.jf-tiles {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
  margin: 16px 0;
}
/* Five headline numbers do not fit across one content column, and pinning the
 * row to `repeat(5, 1fr)` did not make them: `1fr` is `minmax(auto, 1fr)`,
 * whose floor is the item's min-content width, and a tile's value is 30px
 * tabular mono with `white-space: nowrap`. Five of those need ~1031px against
 * the 744px the column actually offers, so the row overflowed to the right and
 * painted straight across the `.toc` rail.
 *
 * `auto-fit` sizes the row to the COLUMN, which is the part no media query in
 * this file can do — the overlap showed up at a 1535px viewport, above every
 * breakpoint here, because the window is wide while the column is not (the
 * sidebar and the contents rail take 472px of the 1320px shell).
 *
 * The floor is one tile at its natural width — a ten-digit tabular value plus
 * the tile's 36px of padding — so the count only drops when a full-size number
 * genuinely stops fitting. Shrinking the value to keep five across was the
 * other option and is worse: it lands at 19px, and the labels start wrapping
 * to two lines, which is what `.tl`'s reserved height exists to prevent.
 *
 * `.four` is the same fix for the live-dashboard widget's tile row: same
 * nowrap tabular values, same blowout, just one column narrower — it only
 * showed up in the ~1200-1310px band where the contents rail is still shown
 * but the column beside it has gotten tight. Hand-authored four-tile rows
 * (`/delivery/conventions`, say) are unaffected and don't carry this class:
 * their content is already known and, where it's wide, marked `.text`
 * instead — see below. */
/* `.three` opts a three-tile row into the same auto-fit sizing. The default
   `repeat(4, 1fr)` would lay three tiles across three of four tracks and leave
   the fourth empty, which reads as a tile that failed to load. */
.jf-tiles.five,
.jf-tiles.four,
.jf-tiles.three {
  grid-template-columns: repeat(auto-fit, minmax(214px, 1fr));
}
/* The same overflow reached the hand-written tile rows from the other end. A
 * `1fr` track is free to grow to its item's min-content width, which is what
 * lets `/data/live` give its 9-digit tile a wider track than its neighbours —
 * useful, until the value is a string rather than a numeral. `api.jobfront.com`
 * at the 30px display size is 315px of unbreakable text, and four tiles led by
 * that one no longer fit the column, so the row ran under the contents rail.
 *
 * `.text` marks a row whose values are strings — a hostname, a range, a field
 * name. They are not display numerals and do not want a numeral's size. */
.jf-tiles.text .tv {
  font-size: 20px;
  letter-spacing: -0.01em;
}
.jf-tile {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px 18px;
  box-shadow: var(--shadow-sm);
}
.jf-tile .tl {
  font-size: 12px;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 6px;
  /* Reserve two lines so a label that wraps doesn't push its value out of
     line with the tiles beside it. */
  min-height: 2.6em;
  align-items: flex-start;
}
.jf-tile .tv {
  font-family: var(--mono);
  font-size: 30px;
  font-weight: 680;
  letter-spacing: -0.02em;
  margin-top: 7px;
  font-variant-numeric: tabular-nums;
}
.jf-tile .td {
  font-size: 11.5px;
  color: var(--faint);
  margin-top: 3px;
}

.jf-panel {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 18px;
  box-shadow: var(--shadow-sm);
}
.jf-panel h3 {
  font-size: 14.5px;
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  letter-spacing: -0.01em;
}
.jf-panel h3 .sub {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--faint);
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
}
.jf-dashgrid {
  display: grid;
  grid-template-columns: 1.5fr 1fr;
  gap: 14px;
  margin-top: 14px;
  /* Panels size to their own content — stretching a short panel to match a
     tall neighbour leaves a large empty area that reads as missing data. */
  align-items: start;
}
.jf-dashgrid.even {
  grid-template-columns: 1fr 1fr;
}

/* Breakdown bars.
 * `.bf` MUST be block-level. The prototype rendered the fill as an inline
 * <span>, which ignores width/height and silently collapsed every bar to
 * 0x0 — the bug called out in §2.4 of the build spec. */
.jf-barrow {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-top: 13px;
  font-size: 13px;
}
.jf-barrow .bl {
  width: 132px;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 7px;
  flex: 0 0 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.jf-barrow .bl.wide {
  width: 214px;
  color: var(--ink);
}
.jf-barrow .bt {
  flex: 1;
  height: 9px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 20px;
  overflow: hidden;
  min-width: 40px;
}
.jf-barrow .bf {
  display: block;
  height: 100%;
  background: var(--accent);
  width: 0;
  border-radius: 20px;
  transition: width 1.1s cubic-bezier(0.2, 0.7, 0.2, 1);
}
.jf-barrow .bv {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
  width: 68px;
  text-align: right;
  flex: 0 0 auto;
  font-variant-numeric: tabular-nums;
}

.jf-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 20px;
  white-space: nowrap;
}
.jf-badge.src {
  background: var(--surface-2);
  color: var(--muted);
  border: 1px solid var(--line);
}
.jf-badge.null {
  color: var(--warn);
  background: color-mix(in srgb, var(--warn) 12%, transparent);
}
.jf-badge.req {
  color: var(--live);
  background: var(--live-soft);
}
.jf-badge.crit {
  color: var(--crit);
  background: var(--crit-soft);
}
/* A status badge that links to its catalog page. Underlined on hover only, so
   the responses table stays a table rather than becoming a wall of links. */
a.jf-badge {
  text-decoration: none;
  cursor: pointer;
}
a.jf-badge:hover {
  text-decoration: underline;
  filter: brightness(0.94);
}

.jf-type {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--accent-ink);
  background: var(--accent-soft);
  padding: 2px 7px;
  border-radius: var(--radius-xs);
  white-space: nowrap;
}
.jf-fname {
  font-family: var(--mono);
  font-size: 12.6px;
  color: var(--ink);
  font-weight: 600;
}

/* Provenance tags — colour-coded by pipeline stage, so a reader can see at a
 * glance whether a field was read off the posting or inferred. */
.jf-prov {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 5px;
  white-space: nowrap;
}
.jf-prov.scrape {
  color: #3b82f6;
  background: rgba(59, 130, 246, 0.12);
}
.jf-prov.augment {
  color: var(--live);
  background: var(--live-soft);
}
.jf-prov.discover {
  color: #a855f7;
  background: rgba(168, 85, 247, 0.14);
}
.jf-prov.metrics {
  color: var(--warn);
  background: color-mix(in srgb, var(--warn) 13%, transparent);
}

.jf-chip {
  font-size: 12.5px;
  font-weight: 550;
  color: var(--muted);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 5px 12px;
  cursor: pointer;
}
.jf-chip:hover {
  border-color: var(--line-2);
  color: var(--ink);
  text-decoration: none;
}
.jf-chip.on {
  background: var(--accent-soft);
  color: var(--accent-ink);
  border-color: transparent;
}
.jf-chiprow {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin: 16px 0;
}

.jf-livechip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--live);
  background: var(--live-soft);
  border: 1px solid color-mix(in srgb, var(--live) 26%, transparent);
  padding: 5px 11px;
  border-radius: 20px;
  font-weight: 600;
}
.jf-livechip.stale {
  color: var(--warn);
  background: color-mix(in srgb, var(--warn) 12%, transparent);
  border-color: color-mix(in srgb, var(--warn) 26%, transparent);
}
.jf-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  animation: jf-pulse 2.6s infinite;
  flex: 0 0 auto;
  display: inline-block;
}

.jf-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 0;
  border-top: 1px solid var(--line);
  font-size: 13.5px;
}
.jf-row:first-of-type {
  border-top: 0;
}
.jf-row .code {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--faint);
  background: var(--surface-2);
  padding: 1px 6px;
  border-radius: 5px;
  margin-right: 8px;
}

.jf-spark {
  width: 100%;
  height: 120px;
  margin-top: 8px;
  display: block;
}
@keyframes jf-spark-draw {
  to {
    stroke-dashoffset: 0;
  }
}

.jf-kinds {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  margin: 16px 0;
}
.jf-kind {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px;
  background: var(--surface);
}
.jf-kind .kt {
  font-family: var(--mono);
  font-size: 12.5px;
  font-weight: 700;
}
.jf-kind.add .kt {
  color: var(--live);
}
.jf-kind.chg .kt {
  color: var(--accent);
}
.jf-kind.rem .kt {
  color: var(--crit);
}
.jf-kind.all .kt {
  color: var(--muted);
}
.jf-kind p {
  font-size: 12.5px;
  color: var(--muted);
  margin: 6px 0 0;
  max-width: none;
}

.jf-evt {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 15px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  margin-top: 10px;
  box-shadow: var(--shadow-sm);
}
.jf-evt .en {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 650;
  min-width: 150px;
}
.jf-evt .ed {
  font-size: 13px;
  color: var(--muted);
  flex: 1;
}
.jf-evt .mark {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: 0 0 auto;
}

.jf-stage {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 8px 0;
  font-size: 14px;
  color: var(--muted);
}
.jf-stage .sd {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 2px solid var(--line-2);
  flex: 0 0 auto;
}
.jf-stage.done {
  color: var(--ink);
}
.jf-stage.done .sd {
  background: var(--live);
  border-color: var(--live);
}
.jf-stage.run {
  color: var(--ink);
  font-weight: 600;
}
.jf-stage.run .sd {
  border-color: var(--accent);
  border-top-color: transparent;
  animation: jf-spin 0.8s linear infinite;
}
@keyframes jf-spin {
  to {
    transform: rotate(360deg);
  }
}

/* A numbered pipeline: one row per stage, joined by a rail, with the agent that
 * runs the stage as a pill on the heading. Deliberately NOT .jf-stage — a
 * checklist of filled green dots reads as "a run that has completed", which is
 * the wrong idea for an architecture that never stops running. */
.jf-pipe {
  margin: 18px 0 22px;
}
.jf-pipe .step {
  position: relative;
  display: grid;
  grid-template-columns: 28px 1fr;
  gap: 14px;
  padding-bottom: 16px;
}
.jf-pipe .step:last-child {
  padding-bottom: 0;
}
/* The rail spans marker-to-marker, so the last step terminates the line rather
 * than trailing off into whitespace. */
.jf-pipe .step:not(:last-child)::before {
  content: "";
  position: absolute;
  left: 14px;
  top: 30px;
  bottom: 0;
  width: 1px;
  background: var(--line-2);
}
.jf-pipe .n {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1px solid var(--line-2);
  background: var(--surface);
  color: var(--muted);
  font-family: var(--mono);
  font-size: 12.5px;
  font-weight: 600;
  display: flex;
  align-items: center;
  justify-content: center;
}
.jf-pipe .sh {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  min-height: 28px;
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
}
.jf-pipe .ag {
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--muted);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 2px 8px;
}
.jf-pipe p {
  margin: 4px 0 0;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--muted);
}

.jf-chatmsg {
  font-size: 13.5px;
  line-height: 1.5;
  padding: 9px 13px;
  border-radius: 12px;
  margin-bottom: 8px;
  max-width: 94%;
}
.jf-chatmsg.you {
  background: var(--accent-soft);
  color: var(--ink);
  margin-left: auto;
  border-bottom-right-radius: 3px;
}
.jf-chatmsg.bot {
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--ink);
  border-bottom-left-radius: 3px;
}

.jf-error {
  font-size: 13px;
  color: var(--muted);
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-left: 3px solid var(--warn);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  margin: 10px 0;
}

/* A block-level loading placeholder, for panels that fill with a whole
 * rendered document rather than a number. */
.jf-skel-block {
  height: 180px;
  border-radius: var(--radius-sm);
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface) 50%, var(--surface-2) 75%);
  background-size: 200% 100%;
  animation: jf-shimmer 1.4s infinite;
}

.jf-callout {
  font-size: 13.5px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-sm);
  padding: 12px 15px;
  margin: 12px 0;
}
.jf-callout.warn {
  border-left-color: var(--warn);
}
.jf-callout ul {
  margin: 8px 0 0;
  padding-left: 18px;
  color: var(--muted);
}
.jf-callout li + li {
  margin-top: 4px;
}

/* Skeleton shimmer while a live widget fetches. Deliberately low contrast —
 * a loading state shouldn't shout. */
.jf-skel {
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface) 50%, var(--surface-2) 75%);
  background-size: 200% 100%;
  animation: jf-shimmer 1.4s infinite;
  border-radius: var(--radius-xs);
  color: transparent;
  display: inline-block;
  min-width: 60px;
}
@keyframes jf-shimmer {
  to {
    background-position: -200% 0;
  }
}

/* ── API reference (three columns) ───────────────────────────────────── */

.ref {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--rail-w);
  gap: 34px;
  align-items: start;
}
.method {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--mono);
  font-size: 14px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 7px 12px;
  box-shadow: var(--shadow-sm);
}
.method .m {
  font-weight: 700;
  color: var(--live);
}
.method .m.post {
  color: var(--accent);
}
.method .m.delete {
  color: var(--crit);
}
.op {
  padding: 40px 0;
  border-top: 1px solid var(--line);
  scroll-margin-top: calc(var(--topbar-h) + 16px);
}
.op:first-of-type {
  border-top: 0;
  padding-top: 8px;
}
.param {
  border-top: 1px solid var(--line);
  padding: 14px 0;
}
.param:first-of-type {
  border-top: 0;
}
.param .row {
  display: flex;
  gap: 9px;
  align-items: baseline;
  flex-wrap: wrap;
}
.param .pn {
  font-family: var(--mono);
  font-size: 13px;
  font-weight: 650;
}
.param .pt {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--faint);
}
.param .rq {
  font-size: 10.5px;
  font-weight: 700;
  color: var(--crit);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.param .pd {
  font-size: 13.5px;
  color: var(--muted);
  margin-top: 4px;
  max-width: 62ch;
}
.param .enum {
  margin-top: 6px;
  display: flex;
  gap: 5px;
  flex-wrap: wrap;
}
.param .enum span {
  font-family: var(--mono);
  font-size: 11px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--muted);
  padding: 1px 6px;
  border-radius: 5px;
}

.rail {
  position: sticky;
  top: calc(var(--topbar-h) + 24px);
}
.rail .codewrap pre {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.tryrow {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 10px 12px;
  background: var(--code-2);
  border-bottom: 1px solid var(--code-line);
}
.tryrow .u {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--code-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tryrow .u b {
  color: var(--live);
}
.send {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--accent);
  color: #fff;
  border: 0;
  border-radius: 7px;
  padding: 5px 12px;
  font-size: 12.5px;
  font-weight: 650;
  cursor: pointer;
  white-space: nowrap;
}
.send:hover {
  background: var(--accent-ink);
}
.send:disabled {
  opacity: 0.55;
  cursor: default;
}
.respmeta {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--code-mut);
  border-bottom: 1px solid var(--code-line);
  background: var(--code-2);
}
.respmeta .ok {
  color: var(--live);
  font-weight: 700;
}
.respmeta .bad {
  color: var(--crit);
  font-weight: 700;
}
.spin {
  width: 13px;
  height: 13px;
  border: 2px solid var(--code-line);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: jf-spin 0.7s linear infinite;
}

/* The token field: a reader's credential lives in their browser only. */
.tokenbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  background: var(--code-2);
  border-bottom: 1px solid var(--code-line);
}
.tokenbar input {
  flex: 1;
  min-width: 0;
  background: var(--code-bg);
  border: 1px solid var(--code-line);
  border-radius: 7px;
  color: var(--code-ink);
  font-family: var(--mono);
  font-size: 12px;
  padding: 5px 9px;
  outline: none;
}
.tokenbar input::placeholder {
  color: var(--code-mut);
}
.tokenbar .lbl {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--code-mut);
}

/* The endpoint list itself. It lives inside a `.navgroup`, under the API
   reference row (see `.navexp` above), so these rules are overriding the
   sidebar's own link styling — same specificity, later in the file. */
.endpointnav a {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 5px 10px;
  border-radius: 8px;
  color: var(--muted);
  font-size: 13px;
  font-weight: 500;
}
.endpointnav a:hover {
  background: color-mix(in srgb, var(--ink) 8%, transparent);
  color: var(--ink);
  text-decoration: none;
}
/* No inset ring here, unlike a section row: the API reference row above is
   already carrying it, and two rings inside one group compete for "you are
   here" when only one of them is the page. */
.endpointnav a.on {
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-weight: 650;
  box-shadow: none;
}
/* Deliberately NOT given its own max-height + overflow. The sidebar already
   scrolls; a nested scroller inside it traps the wheel and makes the section
   groups below harder to reach, not easier. */

/* 34px is DELETE, the longest method the spec has. At 30px it overran its own
   column into the 8px gap and sat flush against the path. */
.endpointnav .mm {
  font-family: var(--mono);
  font-size: 9.5px;
  font-weight: 700;
  color: var(--live);
  width: 34px;
  flex: 0 0 auto;
}
.endpointnav .mm.post {
  color: var(--accent);
}
.endpointnav .mm.delete {
  color: var(--crit);
}
/* Wraps rather than truncates. The sidebar is wide enough for every path on
   the desktop reference (see `.shell.api-nav`), but the narrow window below
   that and the 280px drawer are not, and there an ellipsis cut three distinct
   rows — /v4/sources-id/{source_id}, its /jobs and its /related — down to the
   same `/v4/sources-id/{sou…`, which is worse than useless: the reader cannot
   tell which row is the one they want, and hovering told them nothing either.
   `<wbr>` before each segment (see `wrappable_path` in main.py) puts the break
   at a slash; `break-word` is the fallback for a segment too long even alone.
   `align-items: baseline` above keeps the method label on the first line. */
.endpointnav .pp {
  font-family: var(--mono);
  font-size: 12px;
  min-width: 0;
  overflow-wrap: break-word;
}

/* ── overlays ────────────────────────────────────────────────────────── */

.scrim {
  position: fixed;
  inset: 0;
  background: rgba(10, 14, 22, 0.5);
  backdrop-filter: blur(3px);
  z-index: 1060;
  display: none;
  align-items: flex-start;
  justify-content: center;
  padding-top: 12vh;
}
.scrim.on {
  display: flex;
}
.cmdk {
  width: min(600px, 92vw);
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: 14px;
  box-shadow: 0 30px 80px -20px rgba(0, 0, 0, 0.6);
  overflow: hidden;
}
.cmdk input {
  width: 100%;
  border: 0;
  background: transparent;
  color: var(--ink);
  font-size: 16px;
  padding: 16px 18px;
  outline: none;
  border-bottom: 1px solid var(--line);
}
.cmdk .res {
  padding: 8px;
  max-height: 52vh;
  overflow: auto;
}
.cmdk .r {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 10px 12px;
  border-radius: 9px;
  cursor: pointer;
  font-size: 14px;
  color: var(--ink);
}
.cmdk .r:hover,
.cmdk .r.on {
  background: var(--accent-soft);
  text-decoration: none;
}
.cmdk .r .rk {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--faint);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-left: auto;
}
.cmdk .r .sub {
  font-size: 12px;
  color: var(--faint);
}
.cmdk .foot {
  display: flex;
  gap: 14px;
  padding: 9px 14px;
  border-top: 1px solid var(--line);
  font-size: 11.5px;
  color: var(--faint);
}
.cmdk .empty {
  padding: 22px 16px;
  color: var(--muted);
  font-size: 13.5px;
}

/* ── page footer actions ─────────────────────────────────────────────── */

.pagenote {
  margin-top: 40px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
  font-size: 12.5px;
  color: var(--faint);
}
.llmact {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 5px 9px;
  white-space: nowrap;
  color: var(--muted);
  cursor: pointer;
  font-size: 12px;
}
.llmact:hover {
  border-color: var(--line-2);
  color: var(--ink);
  text-decoration: none;
}
.pager {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-top: 26px;
}
.pager a {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 16px;
  background: var(--surface);
  color: var(--ink);
}
.pager a:hover {
  border-color: var(--line-2);
  text-decoration: none;
}
.pager a .d {
  font-size: 11.5px;
  color: var(--faint);
  display: block;
}
.pager a.next {
  text-align: right;
  grid-column: 2;
}

.sitefooter {
  border-top: 1px solid var(--line);
  background: var(--surface);
  padding: 30px clamp(20px, 4vw, 52px);
  font-size: 13px;
  color: var(--muted);
}
.sitefooter .inner {
  max-width: var(--maxw);
  margin: 0 auto;
  display: flex;
  gap: 40px;
  flex-wrap: wrap;
}
.sitefooter h4 {
  font-size: 12px;
  color: var(--ink);
  margin-bottom: 8px;
}
.sitefooter a {
  color: var(--muted);
  display: block;
  padding: 2px 0;
}
.sitefooter a:hover {
  color: var(--ink);
}

/* ── responsive ──────────────────────────────────────────────────────── */

.menub {
  display: none;
}

@media (max-width: 1200px) {
  .shell.with-toc {
    grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  }
  .toc {
    display: none;
  }
}
@media (max-width: 1080px) {
  .ref {
    grid-template-columns: minmax(0, 1fr);
  }
  .rail {
    position: static;
  }
  .jf-dashgrid,
  .jf-dashgrid.even {
    grid-template-columns: 1fr;
  }
  .jf-tiles,
  .jf-tiles.five,
  .jf-grid3,
  .jf-grid4 {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 860px) {
  .shell,
  .shell.with-toc,
  .shell.full {
    grid-template-columns: minmax(0, 1fr);
  }
  .sidebar {
    position: fixed;
    z-index: 1050;
    top: var(--topbar-h);
    left: 0;
    width: 280px;
    /* Paper, not surface — the group cards need something to sit ON, and a
       surface-coloured drawer would swallow the lightest of them. */
    background: var(--paper);
    transform: translateX(-100%);
    transition: transform 0.25s;
    height: calc(100vh - var(--topbar-h));
  }
  .sidebar.open {
    transform: none;
    box-shadow: var(--shadow);
  }
  .topnav {
    display: none;
  }
  .searchbtn {
    min-width: 0;
    width: 40px;
    justify-content: center;
  }
  .searchbtn span,
  .searchbtn kbd {
    display: none;
  }
  .menub {
    display: grid;
  }
  .jf-statstrip,
  .jf-grid2,
  .jf-grid3,
  .jf-grid4,
  .jf-tiles,
  .jf-tiles.five,
  .jf-kinds {
    grid-template-columns: 1fr 1fr;
  }
  .hidesm {
    display: none;
  }
  .jf-barrow .bl,
  .jf-barrow .bl.wide {
    width: 96px;
  }
}
@media (max-width: 520px) {
  .jf-statstrip,
  .jf-tiles,
  .jf-tiles.five,
  .jf-kinds,
  .jf-grid2,
  .jf-grid3,
  .jf-grid4,
  .pager {
    grid-template-columns: 1fr;
  }
  .pager a.next {
    grid-column: 1;
  }
}

/* Motion is decoration here — every animated element is legible without it. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
}


/* ── data dictionary table ───────────────────────────────────────────────
 * Four columns. Left to itself the field description column expands and
 * pushes Produced-by off the right edge. Constrain the wide cells instead of
 * letting the table scroll.
 */
[data-field-table] {
  table-layout: fixed;
  width: 100%;
}
/* With `table-layout: fixed` the column widths come from the FIRST ROW — the
   header — so these must target `th`. Putting them on `td` silently does
   nothing and the browser falls back to equal columns, which clipped the
   right-hand columns. */
[data-field-table] th:nth-child(1) {
  width: 40%;
}
[data-field-table] th:nth-child(2) {
  width: 13%;
}
[data-field-table] th:nth-child(3) {
  width: 25%;
}
[data-field-table] th:nth-child(4) {
  width: 22%;
}
[data-field-table] td .jf-muted {
  max-width: none;
}
/* Field names are the one string in the row that must stay legible, so they
   never break mid-token; the column is sized to fit the longest of them. */
[data-field-table] .jf-fname {
  overflow-wrap: normal;
  word-break: keep-all;
}
[data-field-table] .jf-badge {
  white-space: normal;
}

/* Tile values must not wrap — "9.2 days" on two lines breaks the row's
 * baseline and makes one tile taller than its neighbours. */
.jf-tile .tv {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── coverage explorer (static/js/live.js) ────────────────────────────── */

/* Ported from the monolith's standalone /data-coverage page. That page brings
   its own palette, its own type scale and its own 1px-rule borders; none of
   that came across. What did is the shape of the thing — a search, the filters
   it produced, a breakdown you can drill into, and a sample of what you'd get.
   Everything below is built from this file's existing tokens and primitives so
   the explorer reads as part of the docs rather than as an embedded page. */

.jf-covctl {
  margin: 18px 0 14px;
}
/* The search box and its scope toggle share one bordered shell, so the toggle
   reads as a mode switch on the box rather than a control floating beside it.
   The border lives on the wrapper and the input carries none of its own —
   otherwise the two draw concentric rounded rectangles. */
.jf-covsearch {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 4px 4px 4px 0;
}
.jf-covsearch:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--bs-focus-ring-color);
}
.jf-covsearch input {
  flex: 1;
  min-width: 0;
  font-family: var(--sans);
  font-size: 14px;
  color: var(--ink);
  background: transparent;
  border: 0;
  padding: 8px 14px;
  outline: 0;
}
.jf-covsearch input::placeholder {
  color: var(--faint);
}
.jf-covscope {
  flex: 0 0 auto;
}

/* Company rows become buttons in lookup mode. .jf-row is a flex layout, so the
   button needs the width and text alignment a <div> got for free. */
.jf-row.jf-covsrc {
  width: 100%;
  text-align: left;
  font-family: inherit;
  font-size: inherit;
  color: inherit;
  background: transparent;
  border-left: 0;
  border-right: 0;
  border-bottom: 0;
  cursor: pointer;
}
.jf-row.jf-covsrc:hover {
  color: var(--accent-ink);
}

@media (max-width: 620px) {
  .jf-covsearch {
    flex-wrap: wrap;
    padding: 6px;
  }
  .jf-covsearch input {
    flex-basis: 100%;
    padding: 6px 8px;
  }
}

.jf-covchips {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
  margin-top: 11px;
  font-size: 12.5px;
}
.jf-covtotal {
  font-size: 13px;
  margin: 10px 0 0;
}
.jf-covtotal strong {
  font-family: var(--mono);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
/* Empty when nothing is filtered — collapse it rather than leave a gap that
   reads as a panel that failed to load. */
.jf-covtotal:empty {
  display: none;
}

.jf-covseg {
  margin-top: 14px;
}
.jf-covseg .jf-chiprow {
  margin: 12px 0 0;
}
.jf-covmeta {
  font-family: var(--mono);
  font-size: 11.5px;
  margin: 10px 0 4px;
  font-variant-numeric: tabular-nums;
}
.jf-covnote {
  font-size: 12px;
  margin: 12px 0 0;
}

/* A bucket row. Same anatomy as .jf-barrow, plus a share column and a hit
   target — the row is a <button> wherever the dimension can be filtered on,
   and a plain <div> where it can't, so the affordance never lies. */
.jf-covrow {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  margin-top: 9px;
  padding: 4px 6px;
  font-size: 13px;
  font-family: var(--sans);
  text-align: left;
  color: var(--ink);
  background: transparent;
  border: 1px solid transparent;
  border-radius: var(--radius-xs);
  cursor: pointer;
}
.jf-covrow.flat {
  cursor: default;
}
.jf-covrow:not(.flat):hover {
  background: var(--surface-2);
  border-color: var(--line);
}
.jf-covrow.on {
  background: var(--accent-soft);
  border-color: transparent;
}
.jf-covrow .bl {
  width: 200px;
  flex: 0 0 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.jf-covrow.on .bl {
  color: var(--accent-ink);
  font-weight: 600;
}
.jf-covrow .bt {
  flex: 1;
  height: 9px;
  min-width: 40px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 20px;
  overflow: hidden;
}
/* Block-level, for the reason .jf-barrow .bf documents — an inline element
   ignores width and the bar silently collapses to nothing. */
.jf-covrow .bt i {
  display: block;
  height: 100%;
  width: 0;
  background: var(--accent);
  border-radius: 20px;
  transition: width 1.1s cubic-bezier(0.2, 0.7, 0.2, 1);
}
.jf-covrow .bv,
.jf-covrow .bp {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
  text-align: right;
  flex: 0 0 auto;
  font-variant-numeric: tabular-nums;
}
.jf-covrow .bv {
  width: 68px;
}
.jf-covrow .bp {
  width: 46px;
  color: var(--faint);
}

/* Hierarchy header — cities and metros are ambiguous without their parent,
   so the server resolves one and the rows sit under it. */
.jf-covgroup {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin: 18px 0 2px;
  padding-bottom: 6px;
  border-bottom: 1px solid var(--line);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted);
}
.jf-covgroup .gc {
  font-family: var(--mono);
  font-weight: 600;
  letter-spacing: 0;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}
.jf-covmore {
  margin-top: 14px;
}

/* Job cards. The monolith shows a company logo from its public S3 bucket;
   this site's CSP is `img-src 'self' data:`, so the request would be blocked
   outright. A monogram identifies the company just as well from the data
   already in the response. */
.jf-covjobs {
  margin-top: 4px;
}
.jf-covjob {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr);
  gap: 12px;
  padding: 14px 0;
  border-top: 1px solid var(--line);
}
.jf-covjob:first-child {
  border-top: 0;
  padding-top: 6px;
}
.jf-covjob .jm {
  width: 34px;
  height: 34px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-xs);
  background: var(--surface-2);
  border: 1px solid var(--line);
  font-family: var(--mono);
  font-size: 11px;
  font-weight: 700;
  color: var(--muted);
}
.jf-covjob .jt {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 13.5px;
  font-weight: 650;
  line-height: 1.4;
}
.jf-covjob .jco {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 500;
  color: var(--faint);
}
.jf-covjob .jmeta {
  font-size: 12.5px;
  color: var(--muted);
  margin-top: 4px;
}
.jf-covjob .jmeta .sep {
  color: var(--line-2);
  margin: 0 7px;
}
.jf-covjob .jmeta .pay {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--live);
  font-weight: 600;
}
.jf-covjob .jd {
  font-size: 12.5px;
  color: var(--muted);
  margin: 7px 0 0;
  max-width: none;
  /* The endpoint already caps descriptions at 600 characters; two lines is
     enough to show the shape of one without turning the panel into a feed. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.jf-covjob .jtags {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 8px;
}
.jf-covjob .jfoot {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--faint);
  margin-top: 8px;
}

@media (max-width: 900px) {
  .jf-covrow {
    gap: 9px;
  }
  .jf-covrow .bl {
    width: 130px;
  }
  .jf-covrow .bv {
    width: 58px;
  }
  .jf-covrow .bp {
    display: none;
  }
}

/* ── interactive tools (static/js/tools.js) ───────────────────────────── */

/* A segmented control. Used for the sample viewer's level and format
   switches — small enough that tabs would be heavier than the choice. */
.jf-seg {
  display: inline-flex;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 2px;
  gap: 2px;
}
.jf-seg button {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--muted);
  background: transparent;
  border: 0;
  border-radius: 7px;
  padding: 5px 12px;
  cursor: pointer;
  white-space: nowrap;
}
.jf-seg button:hover {
  color: var(--ink);
}
.jf-seg button.on {
  background: var(--surface);
  color: var(--accent-ink);
  box-shadow: var(--shadow-sm);
}

/* ── sample viewer ── */

.jf-sampler {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 16px;
  margin: 22px 0;
  box-shadow: var(--shadow-sm);
}
.jf-sampler .sh {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.jf-sampler .sh .mt {
  font-size: 12.5px;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}
.jf-sampler .sc {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
.jf-sampler .nt {
  font-size: 13px;
  color: var(--muted);
  margin: 12px 0;
  max-width: none;
}
/* The rendered sample is capped rather than left to run for hundreds of
   lines — `max` on a rich posting is longer than the rest of the page. */
.jf-sampler .sb .codehilite {
  max-height: 460px;
  overflow: auto;
  border-radius: var(--radius-sm);
}
.jf-sampler .sf {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 12px;
}

/* ── faceted query builder ── */

.jf-qb {
  margin: 22px 0;
}
.jf-qb .qbwrap {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
.jf-qb .qbtop {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
  padding: 14px 16px;
  border-bottom: 1px solid var(--line);
}
.jf-qb .qbsearch {
  flex: 1 1 260px;
}
.jf-qb .qbsearch input {
  width: 100%;
  height: 36px;
  font-family: inherit;
  font-size: 14px;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 0 12px;
}
.jf-qb .qbsearch input:focus {
  outline: 2px solid var(--accent-soft);
  border-color: var(--accent);
}
.jf-qb .jf-chip.toggle[aria-pressed='true'] {
  background: var(--accent-soft);
  color: var(--accent-ink);
  border-color: transparent;
}
.jf-qb .qbchips {
  display: flex;
  gap: 7px;
  flex-wrap: wrap;
  align-items: center;
  padding: 12px 16px;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
  background: var(--paper);
}
.jf-qb .qbmid {
  display: grid;
  grid-template-columns: 208px minmax(0, 1fr);
  border-bottom: 1px solid var(--line);
}
.jf-qb .qbfacets {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 14px 12px;
  border-right: 1px solid var(--line);
  background: var(--paper);
}
.jf-qb .qbfacets .jf-eyebrow {
  padding: 0 8px 6px;
}
.jf-qb .qbfacet {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  width: 100%;
  font-size: 13.5px;
  color: var(--muted);
  background: transparent;
  border: 0;
  border-radius: var(--radius-xs);
  padding: 6px 8px;
  cursor: pointer;
  text-align: left;
}
.jf-qb .qbfacet code {
  font-size: 10.5px;
  color: var(--faint);
  background: transparent;
  padding: 0;
}
.jf-qb .qbfacet:hover {
  background: var(--surface-2);
  color: var(--ink);
}
.jf-qb .qbfacet.on {
  background: var(--accent-soft);
  color: var(--accent-ink);
  font-weight: 600;
}
.jf-qb .qbvalues {
  padding: 14px 16px;
  min-height: 240px;
}
.jf-qb .qbvalues .vh {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 4px;
}
.jf-qb .qbvalues .vn {
  font-size: 12.5px;
  margin: 0 0 10px;
  max-width: none;
}
.jf-qb .qbvalues .vn code,
.jf-callout code,
.jf-sampler .nt code {
  font-size: 11.5px;
}
.jf-qb .vlist {
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.jf-qb .vrow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 90px 66px;
  align-items: center;
  gap: 10px;
  font-size: 13px;
  color: var(--ink);
  background: transparent;
  border: 0;
  border-radius: var(--radius-xs);
  padding: 5px 8px;
  cursor: pointer;
  text-align: left;
}
.jf-qb .vrow:hover {
  background: var(--surface-2);
}
.jf-qb .vrow.on {
  background: var(--accent-soft);
  font-weight: 600;
}
.jf-qb .vrow .vl {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.jf-qb .vrow .vb {
  height: 6px;
  border-radius: 4px;
  background: var(--surface-2);
  overflow: hidden;
}
.jf-qb .vrow .vb i {
  display: block;
  height: 100%;
  background: var(--accent);
  opacity: 0.55;
}
.jf-qb .vrow .vc {
  text-align: right;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.jf-qb .qbout {
  padding: 16px;
}
.jf-qb .qbtotal {
  display: flex;
  align-items: baseline;
  gap: 9px;
  margin-bottom: 12px;
}
.jf-qb .qbtotal .k {
  font-family: var(--mono);
  font-size: 28px;
  font-weight: 680;
  letter-spacing: -0.02em;
  font-variant-numeric: tabular-nums;
}
.jf-qb .qbtotal .l {
  font-size: 13px;
  color: var(--muted);
}
.jf-qb .qburl {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 9px 12px;
}
.jf-qb .qburl code {
  flex: 1 1 300px;
  font-size: 12.5px;
  overflow-wrap: anywhere;
  background: transparent;
  padding: 0;
}
.jf-qb .codewrap .bar {
  border-bottom: 0;
  border-top: 1px solid var(--code-line);
  flex-wrap: wrap;
}
/* Chips sitting on the dark code rail need the rail's palette, not the
   page's. */
.jf-qb .codewrap .bar .jf-chip {
  background: transparent;
  border-color: var(--code-line);
  color: var(--code-mut);
}
.jf-qb .codewrap .bar .jf-chip:hover {
  color: var(--code-ink);
}
.jf-qb .qbtip {
  font-size: 12.5px;
  margin: 12px 0 0;
  max-width: none;
}
.jf-qb .qbtip code {
  font-size: 11.5px;
  overflow-wrap: anywhere;
}

@media (max-width: 900px) {
  .jf-qb .qbmid {
    grid-template-columns: minmax(0, 1fr);
  }
  .jf-qb .qbfacets {
    flex-direction: row;
    flex-wrap: wrap;
    border-right: 0;
    border-bottom: 1px solid var(--line);
  }
  .jf-qb .qbfacets .jf-eyebrow {
    width: 100%;
  }
  .jf-qb .qbfacet {
    width: auto;
  }
}

/* ── Try-it: editable parameters + response shape ─────────────────────
   Both panels live on the dark code rail, so they take the rail's palette
   rather than the page's. */

.tryparams {
  border-bottom: 1px solid var(--code-line);
  background: var(--code-2);
}
.tryparams > summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  font-size: 11.5px;
  font-family: var(--mono);
  color: var(--code-mut);
  cursor: pointer;
  list-style: none;
}
.tryparams > summary::-webkit-details-marker {
  display: none;
}
.tryparams > summary::before {
  content: '▸';
  font-size: 9px;
}
.tryparams[open] > summary::before {
  content: '▾';
}
.tryparams > summary:hover {
  color: var(--code-ink);
}
.tryparams > summary .n {
  margin-left: auto;
  font-variant-numeric: tabular-nums;
}
.tryparams .pf {
  max-height: 340px;
  overflow: auto;
  /* Bottom padding so the last row's underscores aren't shaved off by the
     scroll container's edge — `is_remote` read as "is remote". */
  padding: 4px 12px 14px;
}
.tryparams .pfrow {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr);
  align-items: center;
  gap: 8px;
  padding: 3px 0;
}
.tryparams .pfrow label {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
  cursor: pointer;
}
.tryparams .pfn {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--code-ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tryparams input[type='checkbox'] {
  accent-color: var(--accent);
  flex: none;
}
.tryparams input[type='text'],
.tryparams select {
  width: 100%;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--code-ink);
  background: var(--code-bg);
  border: 1px solid var(--code-line);
  border-radius: 6px;
  padding: 4px 7px;
}
.tryparams input[type='text']::placeholder {
  color: var(--code-mut);
  opacity: 0.65;
}
.tryparams input[type='text']:focus,
.tryparams select:focus {
  outline: 0;
  border-color: var(--accent);
}
.tryparams .pfoot,
.trybody .pfoot {
  display: flex;
  gap: 8px;
  padding: 0 12px 10px;
}
.tryparams .pfoot button,
.trybody .pfoot button {
  font-size: 11.5px;
  color: var(--code-mut);
  background: transparent;
  border: 1px solid var(--code-line);
  border-radius: 7px;
  padding: 3px 9px;
  cursor: pointer;
}
.tryparams .pfoot button:hover,
.trybody .pfoot button:hover {
  color: var(--code-ink);
}

/* Request-body editor. Same chrome as the parameter form — it sits in the same
   rail and does the same job for the one operation that needs a body. */
.trybody {
  border-bottom: 1px solid var(--code-line);
  background: var(--code-2);
}
.trybody > summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  font-size: 11.5px;
  font-family: var(--mono);
  color: var(--code-mut);
  cursor: pointer;
  list-style: none;
}
.trybody > summary::-webkit-details-marker {
  display: none;
}
.trybody > summary::before {
  content: '▸';
  font-size: 9px;
}
.trybody[open] > summary::before {
  content: '▾';
}
.trybody > summary:hover {
  color: var(--code-ink);
}
.trybody > summary .n {
  margin-left: auto;
}
.trybody textarea {
  display: block;
  width: calc(100% - 24px);
  margin: 0 12px 8px;
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.55;
  color: var(--code-ink);
  background: var(--code-bg);
  border: 1px solid var(--code-line);
  border-radius: 7px;
  padding: 8px 10px;
  resize: vertical;
}
.trybody textarea:focus {
  outline: 0;
  border-color: var(--accent);
}

.schemabox > summary {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 12px;
  font-size: 12px;
  color: var(--code-ink);
  cursor: pointer;
  list-style: none;
}
.schemabox > summary::-webkit-details-marker {
  display: none;
}
.schemabox > summary .d {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--code-mut);
}
.schemabox > summary::before {
  content: '▸';
  font-size: 9px;
  color: var(--code-mut);
}
.schemabox[open] > summary::before {
  content: '▾';
}

.stree {
  list-style: none;
  margin: 0;
  padding: 0 12px 10px;
  max-height: 420px;
  overflow: auto;
}
.stree .stree {
  padding: 3px 0 3px 14px;
  border-left: 1px solid var(--code-line);
  margin-left: 3px;
  max-height: none;
  overflow: visible;
}
.stree li {
  padding: 3px 0;
}
.stree .sr {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
}
.stree .sn {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--code-ink);
}
.stree .st {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--accent);
  opacity: 0.85;
}
.stree .rq {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--warn);
}
.stree .sd {
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--code-mut);
  margin-top: 1px;
}
.stree .senum {
  display: flex;
  gap: 5px;
  flex-wrap: wrap;
  margin-top: 3px;
}
.stree .senum span {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--code-mut);
  border: 1px solid var(--code-line);
  border-radius: 5px;
  padding: 1px 5px;
}

.respmeta a {
  color: var(--code-mut);
  text-decoration: underline;
}
.respmeta a:hover {
  color: var(--code-ink);
}
.respmeta [data-copy-response] {
  margin-left: auto;
}

/* ── export-file panel ────────────────────────────────────────────────── */

.jf-exportfiles {
  margin: 22px 0;
}
.jf-exportfiles .sh {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.jf-exportfiles .sh .mt {
  font-size: 12.5px;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}
.jf-exportfiles .fx {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 14px;
  align-items: stretch;
}
.jf-exportfiles .fx .jf-card h3 code {
  font-size: 12.5px;
}

/* Example-response panel on the API reference. Same chrome as the schema
   explorer beside it. */
.examplebox > summary {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 12px;
  font-size: 12px;
  color: var(--code-ink);
  cursor: pointer;
  list-style: none;
}
.examplebox > summary::-webkit-details-marker {
  display: none;
}
.examplebox > summary::before {
  content: '▸';
  font-size: 9px;
  color: var(--code-mut);
}
.examplebox[open] > summary::before {
  content: '▾';
}
.examplebox > summary .d {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--code-mut);
}
/* Live values earn the green; illustrative ones stay grey, so the difference is
   visible without reading the label. */
.examplebox > summary .d.live {
  color: var(--live);
}
.examplebox pre {
  max-height: 420px;
}
.jf-exportfiles .xn {
  font-size: 12.5px;
  margin: 0 0 12px;
  max-width: none;
}

/* ── customer preview gate ─────────────────────────────────────────────
 *
 * The unlock screen at /preview-access, the locked nav badge, and the
 * request-access form. Styled as an ordinary page rather than a modal or an
 * interstitial: it IS the page at that URL, and dressing it up as an
 * interruption implies there is something underneath to dismiss.
 */

/* The nav badge. Grey, not the green `live` pill — that one means "this page
 * shows live data", and a second meaning on the same shape would make both
 * unreadable. */
.navgroup a .tag.tag-locked {
  background: var(--muted);
}

.gate {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr);
  gap: 20px;
  margin: 26px 0 34px;
  align-items: start;
}
/* The left column carries the unlock box AND the request form. The unlock box
   alone is about a third the height of the aside beside it, which left a
   screen-deep hole directly under it — exactly where a reader who has no code
   is looking for what to do next. */
.gatemain > h2 {
  margin-top: 30px;
}
.gatebox {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 20px;
}
.gateform label {
  display: block;
  font-size: 12.5px;
  font-weight: 650;
  color: var(--muted);
  margin-bottom: 7px;
}
.gaterow {
  display: flex;
  gap: 8px;
}
.gaterow input {
  flex: 1;
  min-width: 0;
  font-family: var(--mono);
  font-size: 14px;
  padding: 9px 11px;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
}
.gaterow input:focus,
.reqfield input:focus,
.reqfield textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--bs-focus-ring-color);
}
.gatebtn {
  border: 1px solid var(--accent);
  background: var(--accent);
  color: #fff;
  font-weight: 650;
  font-size: 14px;
  padding: 9px 16px;
  border-radius: var(--radius-sm);
  white-space: nowrap;
  cursor: pointer;
}
.gatebtn:hover {
  background: var(--accent-ink);
  border-color: var(--accent-ink);
}
.gatebtn:disabled {
  opacity: 0.55;
  cursor: default;
}
.gate-hint {
  margin: 10px 0 0;
  font-size: 12.5px;
  color: var(--faint);
}
.gate-hint.bad {
  color: var(--crit);
}
.gate-error {
  margin: 0 0 14px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  background: var(--crit-soft);
  color: var(--crit);
  font-size: 13.5px;
  border: 1px solid color-mix(in srgb, var(--crit) 26%, transparent);
}
.gate-error:focus {
  outline: none;
  box-shadow: 0 0 0 3px rgba(211, 63, 87, 0.24);
}
.gate-ok {
  margin: 18px 0;
  padding: 12px 14px;
  border-radius: var(--radius-sm);
  background: var(--live-soft);
  color: var(--live);
  font-size: 14px;
  font-weight: 650;
  border: 1px solid color-mix(in srgb, var(--live) 26%, transparent);
}

.gateaside {
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 18px;
}
.gatelist {
  list-style: none;
  margin: 10px 0 14px;
  padding: 0;
}
.gatelist li {
  padding: 8px 0;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
}
.gatelist li:last-child {
  border-bottom: 0;
}
.gatelist strong {
  display: block;
  color: var(--ink);
  font-weight: 650;
}
.gatelist span {
  color: var(--muted);
  font-size: 12.5px;
}

/* Request-access form */
.reqform {
  margin: 18px 0 10px;
}
.reqgrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 14px;
}
.reqfield {
  margin-bottom: 14px;
}
.reqfield label {
  display: block;
  font-size: 12.5px;
  font-weight: 650;
  color: var(--muted);
  margin-bottom: 6px;
}
.reqfield input,
.reqfield textarea {
  width: 100%;
  font-family: var(--sans);
  font-size: 14px;
  padding: 9px 11px;
  color: var(--ink);
  background: var(--surface);
  border: 1px solid var(--line-2);
  border-radius: var(--radius-sm);
}
.reqfield textarea {
  resize: vertical;
}
.reqactions {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
.reqactions .gate-hint {
  margin: 0;
}

/* The honeypot. Moved off-canvas rather than `display:none`, because the
 * cheapest bots skip anything display:none and fill everything else. A real
 * reader never reaches it: it is aria-hidden and tabindex=-1 in the markup. */
.reqtrap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* The footer sign-out, shown only to an unlocked reader. */
.gateout {
  margin-top: 12px;
  font-size: 12px;
  color: var(--faint);
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.gateout button {
  background: none;
  border: 0;
  padding: 0;
  font-size: 12px;
  color: var(--accent);
  text-decoration: underline;
  cursor: pointer;
}

/* The "this page is not published" chip that replaces the assistant hand-off
 * buttons on a gated page. Not a button — there is nothing to press. */
.llmact.locked {
  cursor: default;
  color: var(--faint);
  background: var(--surface-2);
}

@media (max-width: 900px) {
  .gate {
    grid-template-columns: 1fr;
  }
}

/* ── print ───────────────────────────────────────────────────────────── */
/* Docs get printed (and printed-to-PDF for review). Strip the chrome and let
 * the prose own the page; code blocks keep their dark ground because losing
 * the contrast loses the syntax colours with it. */

@media print {
  .topbar,
  .sidebar,
  .toc,
  .sitefooter,
  .scrim,
  .pagenote,
  .pager,
  .skiplink {
    display: none !important;
  }
  .shell {
    display: block;
    max-width: none;
    padding: 0;
  }
  .content {
    max-width: none;
    padding: 0;
  }
  body {
    background: #fff;
  }
  a {
    text-decoration: underline;
  }
}
