/* Docs theme chrome (SpeQA-inspired nav + footer). */
:root {
  --docs-nav-h: 64px;
  --docs-bg1: #ffffff;
  --docs-bg2: #f7f8fa;
  --docs-fg1: #0d1117;
  --docs-fg2: #4a5568;
  --docs-pri: #3b82f6;
  --docs-pri-hover: #2563eb;
  --docs-acc: #8b5cf6;
  --docs-brd: #e2e8f0;
  --docs-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
}
[data-theme="dark"] {
  --docs-bg1: #0d1117;
  --docs-bg2: #161b22;
  --docs-fg1: #f0f6fc;
  --docs-fg2: #8b949e;
  --docs-pri: #58a6ff;
  --docs-pri-hover: #79c0ff;
  --docs-acc: #a78bfa;
  --docs-brd: #30363d;
  --docs-shadow: 0 4px 20px rgba(0, 0, 0, 0.35);
}
body.docs-theme {
  padding-top: var(--docs-nav-h);
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 100;
  background: var(--docs-bg1);
  border-bottom: 1px solid transparent;
  transition: border-color 0.2s ease, box-shadow 0.25s ease;
}
.nav.scrolled {
  border-color: var(--docs-brd);
  box-shadow: var(--docs-shadow);
}
.nav-inner {
  max-width: 1200px; margin: 0 auto;
  padding: 0 36px;
  height: var(--docs-nav-h);
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px;
}
@media (min-width: 1200px) { .nav-inner { max-width: 1400px; } }
.nav-left { display: flex; align-items: center; gap: var(--sp-3); min-width: 0; }
.nav-brand {
  display: flex; align-items: center; gap: 8px;
  font-weight: 800; font-size: 1.25rem;
  color: var(--docs-fg1); letter-spacing: -0.01em;
  text-decoration: none; white-space: nowrap;
  min-width: 0; overflow: hidden;
}
.nav-brand:hover { color: var(--docs-pri); text-decoration: none; }
.nav-brand .brand-logo { height: 1.75rem; width: auto; flex-shrink: 0; }
.nav-brand-name { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nav-links {
  display: flex; align-items: center; gap: 32px;
  margin-left: auto; margin-right: var(--sp-3);
}
/* With no header nav (empty `header:`), `.nav-links` is absent, so `.nav-inner`'s
   space-between would center the remaining items. Push the leftmost right-cluster
   member (actions if present, else search) to the right so search always sits next
   to the theme toggle, as it does when `.nav-links` supplies the margin-left:auto. */
.nav-inner:not(:has(.nav-links)) .nav-actions { margin-left: auto; }
.nav-inner:not(:has(.nav-links)):not(:has(.nav-actions)) .site-search { margin-left: auto; }
.nav-links a {
  font-size: 0.875rem; font-weight: 500;
  color: var(--docs-fg2); text-decoration: none;
  transition: color 0.2s ease; white-space: nowrap;
}
.nav-links a:hover { color: var(--docs-pri); text-decoration: none; }
.nav-links a[aria-current="page"] { color: var(--docs-fg1); font-weight: 600; }
/* Collapsible header search: magnifier stays put on the right; the input expands
   leftward as an absolute OVERLAY so it never reflows the other header elements. */
.site-search { position: relative; display: flex; align-items: center; flex-shrink: 0; }
.site-search-input {
  position: absolute; right: calc(100% + 6px); top: 50%; transform: translateY(-50%);
  appearance: none; -webkit-appearance: none;
  width: 0; min-width: 0; height: 34px; padding: 0; margin: 0;
  border: 1px solid var(--docs-brd); border-radius: 6px;
  background: var(--docs-bg1); color: var(--docs-fg1);
  font: inherit; font-size: 0.875rem;
  opacity: 0; pointer-events: none; z-index: 20;
  transition: width 0.22s ease, opacity 0.18s ease, padding 0.22s ease;
}
.site-search-input::-webkit-search-cancel-button { -webkit-appearance: none; }
.site-search.open .site-search-input {
  /* Single resolved width (not 240px capped by max-width): on close, removing `.open` would
     un-cap the still-240px width for a frame, jerking the field to 240px before it collapses. */
  width: min(240px, 42vw); padding: 0 10px;
  opacity: 1; pointer-events: auto; box-shadow: var(--docs-shadow);
}
.site-search-input:focus-visible { outline: none; border-color: var(--docs-pri); }
.search-toggle {
  flex-shrink: 0; width: 38px; height: 34px;
  background: transparent; border: 1px solid var(--docs-brd); border-radius: 6px;
  cursor: pointer; color: var(--docs-fg2);
  display: inline-flex; align-items: center; justify-content: center;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.search-toggle:hover { border-color: var(--docs-pri); color: var(--docs-pri); }
.search-toggle svg { width: 18px; height: 18px; }
.docs-theme .theme-toggle {
  position: relative; flex-shrink: 0;
  width: 38px; height: 34px;
  background: transparent;
  border: 1px solid var(--docs-brd);
  border-radius: 6px;
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--docs-fg2);
  transition: border-color 0.2s ease, color 0.2s ease;
}
.docs-theme .theme-toggle:hover {
  border-color: var(--docs-pri);
  color: var(--docs-pri);
}
.docs-theme .theme-toggle svg {
  position: absolute; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 18px; height: 18px;
}
.docs-theme .theme-toggle .dark-icon { display: none; }
[data-theme="light"] .docs-theme .theme-toggle .light-icon { display: none; }
[data-theme="light"] .docs-theme .theme-toggle .dark-icon { display: block; }
html:not([data-theme]) .docs-theme .theme-toggle .light-icon { display: none; }
html:not([data-theme]) .docs-theme .theme-toggle .dark-icon { display: block; }
.footer-wrap {
  padding: 48px 0;
  background: var(--docs-bg2);
  border-top: 1px solid var(--docs-brd);
  font-size: 0.9rem;
  line-height: 1.6;
}
.footer-grid-layout {
  max-width: 1200px; margin: 0 auto;
  display: flex; justify-content: space-between;
  gap: 48px; padding: 0 36px;
  align-items: flex-start;
}
@media (min-width: 1200px) { .footer-grid-layout { max-width: 1400px; } }
.ftr-brand-box h4 {
  margin: 0 0 6px;
  font-size: 1.1rem; font-weight: 700;
  color: var(--docs-fg1);
}
.ftr-brand-box h4 a { color: inherit; text-decoration: none; }
.ftr-brand-box h4 a:hover { color: var(--docs-pri); }
.ftr-brand-box p {
  margin: 0;
  font-size: 0.85rem;
  color: var(--docs-fg2);
  line-height: 1.5;
}
.ftr-brand-box .site-description { margin-top: 4px; }
.ftr-copyright {
  margin-top: 12px !important;
  font-size: 0.8rem !important;
  color: var(--docs-fg2);
  opacity: 0.7;
}
.ftr-copyright a { color: inherit; text-decoration: underline; }
.ftr-lk-wrap {
  display: flex; flex-direction: column; gap: 8px;
}
.ftr-lk-wrap a {
  font-size: 0.85rem;
  color: var(--docs-fg2);
  text-decoration: none;
  transition: color 0.2s ease;
}
.ftr-lk-wrap a:hover { color: var(--docs-pri); }
.ftr-lk-wrap a[aria-current="page"] { color: var(--docs-fg1); font-weight: 600; }
@media (max-width: 960px) {
  .nav-inner { padding: 0 16px; }
  /* Pages take priority over the CTA when the bar gets tight: the page links
     keep their right-aligned place (base margin-left:auto is preserved - they are
     NOT shoved to the left) and stay visible, shrinking and scrolling horizontally
     if they overflow, instead of vanishing (was display:none). The blue CTA
     collapses (below) so the links keep the room. .nav-inner prefix outranks the
     later-in-file base rules. */
  .nav-inner .nav-links {
    min-width: 0; flex-shrink: 1;
    overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none;
  }
  .nav-inner .nav-links::-webkit-scrollbar { display: none; }
  .footer-grid-layout {
    flex-direction: column;
    gap: 24px;
    padding: 0 20px;
  }
  .footer-wrap { padding: 32px 0; }
  body.docs-theme {
    padding-top: var(--docs-nav-h);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
  }
  .docs-theme .page-toc { top: 0; }
  /* Drawer opens BELOW the fixed header (header stays visible/clickable above it):
     full remaining height, first nav item never hidden under the bar. Height is
     explicit because the base rule's align-self:start makes this fixed grid child
     shrink to content instead of stretching between its top/bottom insets. */
  .docs-theme .sidebar {
    top: var(--docs-nav-h);
    height: calc(100vh - var(--docs-nav-h));
    height: calc(100dvh - var(--docs-nav-h));
  }
  /* The blue CTA yields space BEFORE the page links do: its group shrinks first
     (high flex-shrink) and the label ellipsizes ("Get Started" -> "Get St..."),
     so the links stay full until the CTA is fully squeezed. The label is only
     DROPPED to icon-only when even a ~3-char ellipsized label no longer fits -
     that final step is done by the fitCTAButtons() script in shell.html adding
     .nav-btn--icon (pure CSS cannot measure "3 chars fit"). .nav-inner prefix
     outranks the later-in-file .nav-actions/.nav-btn base rules. */
  .nav-inner { gap: 12px; }
  /* Pages get the space first: the actions group yields far more readily than the
     links (flex-shrink 1000 vs the links' 1), so as the bar narrows the CTA label
     ellipsizes/collapses BEFORE the page links give up any room. It shrinks down to
     an explicit collapsed floor (~icon button + one social) and stops there - below
     the floor it would over-shrink and its social icon would overflow onto the
     search box. Only past that floor do the links themselves yield (they scroll). */
  .nav-inner .nav-actions { gap: 10px; flex-shrink: 1000; min-width: 4rem; }
  .nav-inner .nav-social { flex-shrink: 0; }
  .nav-inner .nav-btn { flex-shrink: 1; min-width: 0; overflow: hidden; }
  .nav-inner .nav-btn span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .nav-inner .nav-btn.nav-btn--icon { flex-shrink: 0; padding: 8px; }
  .nav-inner .nav-btn.nav-btn--icon span { display: none; }
  .nav-inner:not(:has(.nav-actions)) .site-search { margin-left: auto; }
  .nav-social span { display: none; }
  /* Scroll-affordance fade on the page links: fitNavLinksFade() in shell.html
     toggles .fade-start/.fade-end for whichever edge has more content to scroll
     to, and the mask fades that edge so it reads as "there is more, swipe". */
  .nav-inner .nav-links.fade-end {
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 28px), transparent);
  }
  .nav-inner .nav-links.fade-start {
    -webkit-mask-image: linear-gradient(to left, #000 calc(100% - 28px), transparent);
    mask-image: linear-gradient(to left, #000 calc(100% - 28px), transparent);
  }
  .nav-inner .nav-links.fade-start.fade-end {
    -webkit-mask-image: linear-gradient(to right, transparent, #000 28px, #000 calc(100% - 28px), transparent);
    mask-image: linear-gradient(to right, transparent, #000 28px, #000 calc(100% - 28px), transparent);
  }
}
@media (max-width: 640px) {
  /* Phone: brand is logo-only (clean, instead of an ellipsized name). The page
     links (flexible + horizontally scrollable, set at the 960px breakpoint) keep
     taking the middle; brand and the fixed right cluster (social/search/theme)
     never shrink. */
  .nav-brand-name { display: none; }
  .nav-left { flex-shrink: 0; }
  .nav-brand { flex-shrink: 0; }
  .nav-inner { gap: 10px; padding: 0 12px; }
}
@media (min-width: 961px) {
  .docs-theme .sidebar,
  .docs-theme .page-toc {
    top: calc(var(--docs-nav-h) + var(--sp-4));
  }
}
/* Design tokens (single source of truth for the docs template). */
:root {
  color-scheme: light;
  --fs-0: 0.8125rem; --fs-1: 0.9375rem; --fs-2: 1rem;
  --fs-3: 1.125rem; --fs-4: 1.25rem; --fs-5: 1.5rem;
  --fs-6: 1.875rem; --fs-7: 2.25rem;
  --lh-tight: 1.2; --lh-snug: 1.35; --lh-body: 1.65; --lh-relaxed: 1.75;
  --sp-1: 0.25rem; --sp-2: 0.5rem; --sp-3: 0.75rem; --sp-4: 1rem;
  --sp-5: 1.5rem; --sp-6: 2rem; --sp-7: 3rem;
  --r-sm: 4px; --r-md: 6px; --r-lg: 10px;
  --content-max: 760px; --sidebar-w: 260px; --rail-w: 220px;
  --ff-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Arial, sans-serif;
  --ff-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  --c-bg: #ffffff;
  --c-bg-soft: #f7f8fa;
  --c-bg-sunken: #eef0f3;
  --c-text: #1a1d21;
  --c-text-muted: #5b6573;
  --c-text-subtle: #8a93a0;
  --c-border: #e3e6eb;
  --c-border-strong: #cdd2d9;
  --c-accent: #2257d1;
  --c-accent-hover: #1a47b3;
  --c-link: var(--c-accent);
  --c-link-hover: var(--c-accent-hover);
  --c-code-bg: #f3f4f6;
  --c-code-text: #1a1d21;
  --c-syntax-keyword: #cf222e;
  --c-syntax-string: #0a3069;
  --c-syntax-comment: #6e7781;
  --c-syntax-number: #0550ae;
  --c-syntax-name: #8250df;
  --c-syntax-attr: #116329;
  --c-quote-border: #cdd2d9;
  --c-quote-text: #4b5360;
  --c-chip-bg: #eef0f3;
  --c-chip-text: #4b5360;
  --c-active-bg: rgba(34, 87, 209, 0.10);
  --c-active-text: var(--c-accent);
  --c-shadow: 0 1px 2px rgba(15, 23, 42, 0.06), 0 4px 12px rgba(15, 23, 42, 0.04);
  --c-focus: #2257d1;
}
[data-theme="dark"] {
  color-scheme: dark;
  --c-bg: #0f1115;
  --c-bg-soft: #161a21;
  --c-bg-sunken: #1c2128;
  --c-text: #e6e8ec;
  --c-text-muted: #9aa3b2;
  --c-text-subtle: #6c7585;
  --c-border: #262c36;
  --c-border-strong: #364050;
  --c-accent: #6ea8ff;
  --c-accent-hover: #8fbeff;
  --c-link: var(--c-accent);
  --c-link-hover: var(--c-accent-hover);
  --c-code-bg: #161a21;
  --c-code-text: #e6e8ec;
  --c-syntax-keyword: #ff7b72;
  --c-syntax-string: #a5d6ff;
  --c-syntax-comment: #8b949e;
  --c-syntax-number: #79c0ff;
  --c-syntax-name: #d2a8ff;
  --c-syntax-attr: #7ee787;
  --c-quote-border: #364050;
  --c-quote-text: #9aa3b2;
  --c-chip-bg: #1c2128;
  --c-chip-text: #c2c9d4;
  --c-active-bg: rgba(110, 168, 255, 0.14);
  --c-active-text: var(--c-accent);
  --c-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 12px rgba(0, 0, 0, 0.25);
  --c-focus: #6ea8ff;
}
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; background: var(--c-bg); color: var(--c-text); }
html, body { scrollbar-color: var(--c-border-strong) var(--c-bg); }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: var(--c-bg); }
::-webkit-scrollbar-thumb { background: var(--c-border-strong); border-radius: 999px; }
::-webkit-scrollbar-thumb:hover { background: var(--c-text-subtle); }
[data-theme="dark"] ::-webkit-scrollbar-thumb { background: #3a4352; }
[data-theme="dark"] ::-webkit-scrollbar-thumb:hover { background: #536070; }
body {
  margin: 0;
  font-family: var(--ff-sans);
  font-size: var(--fs-2);
  line-height: var(--lh-body);
  color: var(--c-text);
  background: var(--c-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}
/* Underline is a CONSTANT property of in-content links (article body), never a hover
   effect: chrome/navigation links signal hover by color only. */
a { color: var(--c-link); text-decoration: none; }
a:hover { color: var(--c-link-hover); }
:focus-visible { outline: 2px solid var(--c-focus); outline-offset: 2px; border-radius: var(--r-sm); }
.skip-link {
  position: absolute; left: var(--sp-2); top: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  background: var(--c-bg); color: var(--c-text);
  border: 1px solid var(--c-border-strong); border-radius: var(--r-md);
  transform: translateY(-200%); transition: transform 120ms ease;
  z-index: 100;
}
.skip-link:focus { transform: translateY(0); }
.topbar {
  position: sticky; top: 0; z-index: 20;
  padding: var(--sp-3) 0 0;
  background: color-mix(in srgb, var(--c-bg) 88%, transparent);
  backdrop-filter: saturate(180%) blur(8px);
  -webkit-backdrop-filter: saturate(180%) blur(8px);
}
/* Constrain topbar content to the same column box .layout uses so the
   brand sits flush with the sidebar's left edge and the theme toggle
   sits flush with the right rail's (or, below 1200px, the content's)
   right edge. The topbar element itself still spans full width for
   the sticky background band, but the divider lives on .topbar-inner
   so its left/right ends sit flush with the column box instead of
   extending past the brand and toggle. */
.topbar-inner {
  position: relative;
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--sp-3);
  max-width: 1200px; margin: 0 auto;
  padding: 0 var(--sp-5) var(--sp-3);
}
/* Divider rendered as a pseudo-element so its ends can fade to
   transparent — a flat border-bottom would stop abruptly at the
   column box's left/right edges, leaving two hard line-ends. The
   12%/88% stops give a soft taper a sixth of the way in from each
   side, scaling automatically with the column width. */
.topbar-inner::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: linear-gradient(
    to right,
    transparent,
    var(--c-border) 12%,
    var(--c-border) 88%,
    transparent
  );
}
@media (min-width: 1200px) { .topbar-inner { max-width: 1400px; } }
.brand { font-weight: 600; font-size: var(--fs-3); color: var(--c-text); letter-spacing: -0.01em; display: flex; align-items: center; gap: 0.375rem; }
.brand:hover { text-decoration: none; color: var(--c-text); }
.brand-logo { height: 1.5rem; width: auto; flex-shrink: 0; }
.brand-name { white-space: nowrap; }
.topbar-left { display: flex; align-items: center; gap: var(--sp-3); }
.topbar-right { display: flex; align-items: center; gap: var(--sp-4); }
.topbar-nav, .footer-nav {
  list-style: none; margin: 0; padding: 0;
  display: flex; align-items: center; gap: var(--sp-4);
}
.topbar-nav a, .footer-nav a {
  color: var(--c-text-muted);
  font-size: var(--fs-1);
  text-decoration: none;
  transition: color 120ms ease;
}
.topbar-nav a:hover, .footer-nav a:hover { color: var(--c-text); }
.topbar-nav a[aria-current="page"],
.footer-nav a[aria-current="page"] { color: var(--c-text); }
.footer-nav { justify-content: center; margin-bottom: var(--sp-3); }
.layout {
  flex: 1 0 auto;
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  gap: var(--sp-6);
  max-width: 1200px; margin: 0 auto;
  padding: var(--sp-5) var(--sp-5) var(--sp-7);
  width: 100%;
}
/* Three-column layout once the viewport has room for the right rail.
   1200px floor matches the existing max-width plus two columns of
   gutter; the .layout max-width below scales up so the rail doesn't
   cause horizontal scrolling. */
@media (min-width: 1200px) {
  .layout {
    grid-template-columns: var(--sidebar-w) minmax(0, 1fr) var(--rail-w);
    max-width: 1400px;
  }
}
.sidebar {
  position: sticky; top: calc(var(--sp-3) * 2 + 1.5rem + 1px);
  align-self: start; max-height: calc(100vh - 5rem);
  overflow-y: auto; padding-right: var(--sp-3);
}
main { min-width: 0; }
main:focus { outline: none; }
/* Right-rail "On this page" outline. Hidden below 1200px viewport
   (the breakpoint at which .layout drops to two columns) so the
   article stays comfortable on narrower screens. */
.page-toc {
  display: none;
  position: sticky; top: calc(var(--sp-3) * 2 + 1.5rem + 1px);
  align-self: start; max-height: calc(100vh - 5rem);
  overflow-y: auto;
  font-size: var(--fs-0);
  line-height: var(--lh-snug);
}
@media (min-width: 1200px) {
  .page-toc { display: block; }
}
.page-toc__title {
  margin: 0 0 var(--sp-2);
  padding: 0 var(--sp-3);
  font-size: var(--fs-0); font-weight: 600;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--c-text-subtle);
}
.page-toc__list { list-style: none; margin: 0; padding: 0; }
.page-toc__item a {
  display: block;
  padding: var(--sp-1) var(--sp-3);
  color: var(--c-text-muted);
  border-left: 2px solid transparent;
  text-decoration: none;
  transition: color 120ms, border-color 120ms;
}
.page-toc__item a:hover { color: var(--c-text); text-decoration: none; }
.page-toc__item--h3 a { padding-left: calc(var(--sp-3) + var(--sp-3)); }
.page-toc__item.is-active a {
  color: var(--c-accent);
  border-left-color: var(--c-accent);
}
.nav-list { list-style: none; margin: 0; padding: 0; }
.nav-section {
  display: block;
  margin: var(--sp-4) 0 var(--sp-2);
  padding: 0 var(--sp-3);
  font-size: var(--fs-0); font-weight: 600;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--c-text-subtle);
}
.nav-list .nav-section:first-child { margin-top: 0; }
.nav-list a {
  display: block;
  padding: var(--sp-2) var(--sp-3);
  margin: 1px 0;
  border-radius: var(--r-md);
  color: var(--c-text-muted);
  font-size: var(--fs-1);
  line-height: var(--lh-snug);
}
.nav-list a:hover { background: var(--c-bg-soft); color: var(--c-text); text-decoration: none; }
.nav-list a[aria-current="page"] {
  background: var(--c-active-bg);
  color: var(--c-active-text);
  font-weight: 500;
}
/* Section children nest under their label (slightly indented); the label and
   top-level items stay flush at the left edge. */
.nav-sublist { list-style: none; margin: 0; padding: 0; }
.nav-sublist a { padding-left: calc(var(--sp-3) + 14px); }
.nav-list > li.nav-group:first-child .nav-section { margin-top: 0; }
/* Clickable heading anchors: "#" appears on hover, links to the section. */
.body h1, .body h2, .body h3, .body h4 { scroll-margin-top: calc(var(--docs-nav-h) + 12px); }
.heading-anchor {
  margin-left: 0.35em; font-weight: 400; text-decoration: none;
  color: var(--docs-fg2); opacity: 0; transition: opacity 0.15s ease;
}
.body h1:hover .heading-anchor, .body h2:hover .heading-anchor,
.body h3:hover .heading-anchor, .body h4:hover .heading-anchor { opacity: 0.55; }
.heading-anchor:hover, .heading-anchor:focus-visible { opacity: 1; color: var(--docs-pri); text-decoration: none; }
.theme-toggle, .menu-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  width: 36px; height: 36px; padding: 0;
  background: transparent;
  border: 1px solid var(--c-border);
  border-radius: var(--r-md);
  color: var(--c-text-muted);
  cursor: pointer;
  transition: background 120ms ease, color 120ms ease, border-color 120ms ease;
}
.theme-toggle:hover, .menu-toggle:hover { background: var(--c-bg-soft); color: var(--c-text); border-color: var(--c-border-strong); }
.theme-toggle svg, .menu-toggle svg { width: 18px; height: 18px; display: block; }
.theme-toggle [data-icon] { display: none; }
/* Icon visibility is fully CSS-driven so morphdom patches that strip
   inline style attributes leave the toggle in a consistent state.
   The html:not([data-theme]) fallback shows the sun briefly while
   the bootstrap inline script has not yet written data-theme onto
   the root - without it the toggle would render iconless on first paint. */
[data-theme="light"] .theme-toggle [data-icon="sun"] { display: block; }
[data-theme="dark"] .theme-toggle [data-icon="moon"] { display: block; }
html:not([data-theme]) .theme-toggle [data-icon="sun"] { display: block; }
.menu-toggle { display: none; }
article { max-width: var(--content-max); padding: 0 var(--sp-5) var(--sp-7); }
article .article-meta {
  margin: 0 0 var(--sp-6);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--c-border);
}
article .article-meta-row,
article .article-taxonomy-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-3);
  min-height: 1.75rem;
}
article .article-taxonomy-row {
  margin-top: 0;
}
article .article-meta-row + .article-taxonomy-row {
  margin-top: var(--sp-2);
}
article .article-meta .post-date {
  flex: 0 0 auto;
  margin: 0;
  font-size: var(--fs-0);
  line-height: var(--lh-snug);
  font-weight: 400;
  color: var(--c-text-muted);
}
article .article-meta .categories,
article .article-meta .tags {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  min-width: 0;
}
article .article-meta .tags {
  flex: 0 1 auto;
  margin: 0 0 0 auto;
  justify-content: flex-end;
}
article .article-meta .categories {
  flex: 0 1 auto;
}
article .article-meta-row .tags:only-child,
article .article-taxonomy-row .tags:only-child {
  margin-left: 0;
}
article .article-meta .categories li,
article .article-meta .tags li {
  display: inline-flex;
  align-items: center;
  margin: 0;
  padding: 2px var(--sp-2);
  font-size: var(--fs-0);
  line-height: var(--lh-snug);
  font-weight: 500;
  background: var(--c-chip-bg);
  color: var(--c-chip-text);
  border: 1px solid var(--c-border);
  border-radius: 999px;
}
article .article-meta .categories li {
  background: var(--c-active-bg);
  color: var(--c-active-text);
  border-color: color-mix(in srgb, var(--c-accent) 22%, transparent);
  font-weight: 600;
}
article .article-meta .category-icon {
  display: inline-flex;
  width: 0.9em;
  height: 0.9em;
  margin-right: var(--sp-1);
}
article .article-meta .category-icon svg { width: 100%; height: 100%; }
article .article-meta .tag-hash {
  margin-right: var(--sp-1);
  color: var(--c-text-subtle);
}
article .body h1,
article .body h2,
article .body h3,
article .body h4,
article .body h5,
article .body h6 {
  color: var(--c-text);
  line-height: var(--lh-tight);
  margin: var(--sp-6) 0 var(--sp-3);
  letter-spacing: -0.01em;
}
article .body h1:first-child,
article .body h2:first-child,
article .body h3:first-child { margin-top: 0; }
article .body h1 { font-size: var(--fs-7); font-weight: 700; }
article .body h2 { font-size: var(--fs-5); font-weight: 600; padding-bottom: var(--sp-2); border-bottom: 1px solid var(--c-border); }
article .body h3 { font-size: var(--fs-4); font-weight: 600; }
article .body h4 { font-size: var(--fs-3); font-weight: 600; }
article .body h5 { font-size: var(--fs-2); font-weight: 600; }
article .body h6 { font-size: var(--fs-1); font-weight: 600; color: var(--c-text-muted); }
article .body p,
article .body ul,
article .body ol { margin: 0 0 var(--sp-4); line-height: var(--lh-relaxed); }
article .body li > p { margin-bottom: var(--sp-2); }
article .body ul,
article .body ol { padding-left: var(--sp-5); }
article .body li { margin: var(--sp-2) 0; }
article .body blockquote {
  margin: var(--sp-5) 0;
  padding: var(--sp-2) var(--sp-5);
  border-left: 3px solid var(--c-quote-border);
  color: var(--c-quote-text);
  font-style: italic;
}
article .body blockquote p:last-child { margin-bottom: 0; }
article .body code {
  font-family: var(--ff-mono);
  font-size: 0.9em;
  background: var(--c-code-bg);
  color: var(--c-code-text);
  padding: 0.15em 0.35em;
  border-radius: var(--r-sm);
}
article .body pre {
  background: var(--c-code-bg);
  color: var(--c-code-text);
  margin: 0 0 var(--sp-4);
  padding: var(--sp-4) var(--sp-7) var(--sp-4) var(--sp-4);
  overflow-x: auto;
  border-radius: var(--r-md);
  border: 1px solid var(--c-border);
  font-size: var(--fs-1);
  line-height: var(--lh-snug);
}
article .body .code-block {
  position: relative;
  margin: 0 0 var(--sp-4);
}
article .body .code-block pre {
  margin: 0;
}
article .body pre code {
  background: transparent; padding: 0; border-radius: 0; font-size: inherit;
}
.code-copy-button {
  position: absolute;
  top: var(--sp-2);
  right: var(--sp-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  padding: 0;
  background: color-mix(in srgb, var(--c-code-bg) 84%, var(--c-bg));
  border: 1px solid var(--c-border);
  border-radius: var(--r-sm);
  color: var(--c-text-muted);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  z-index: 1;
  transition: opacity 120ms ease, color 120ms ease, border-color 120ms ease, background 120ms ease;
}
article .body .code-block:hover .code-copy-button,
.code-copy-button:focus-visible,
.code-copy-button[data-copied="true"] {
  opacity: 1;
  pointer-events: auto;
}
.code-copy-button:hover {
  background: var(--c-bg);
  border-color: var(--c-border-strong);
  color: var(--c-text);
}
.code-copy-button svg {
  display: block;
  width: 0.95rem;
  height: 0.95rem;
}
.code-copy-tooltip {
  position: absolute;
  right: 0;
  bottom: calc(100% + var(--sp-1));
  top: auto;
  padding: 2px var(--sp-2);
  border: 1px solid var(--c-border-strong);
  border-radius: var(--r-sm);
  background: var(--c-bg);
  color: var(--c-text);
  font-family: var(--ff-sans);
  font-size: var(--fs-0);
  line-height: var(--lh-snug);
  white-space: nowrap;
  box-shadow: var(--c-shadow);
  opacity: 0;
  pointer-events: none;
}
.code-copy-button:hover .code-copy-tooltip,
.code-copy-button:focus-visible .code-copy-tooltip {
  opacity: 1;
}
/* Syntax highlight classes emitted by rehype-highlight (lowlight).
   Five token buckets covers ~95% of hljs class names; remaining
   classes inherit the surrounding pre/code colour. */
article .body .hljs-keyword,
article .body .hljs-built_in,
article .body .hljs-literal,
article .body .hljs-tag,
article .body .hljs-selector-tag { color: var(--c-syntax-keyword); }
article .body .hljs-string,
article .body .hljs-regexp,
article .body .hljs-doctag { color: var(--c-syntax-string); }
article .body .hljs-comment,
article .body .hljs-quote { color: var(--c-syntax-comment); font-style: italic; }
article .body .hljs-number,
article .body .hljs-symbol,
article .body .hljs-meta { color: var(--c-syntax-number); }
article .body .hljs-title,
article .body .hljs-name,
article .body .hljs-section,
article .body .hljs-type,
article .body .hljs-class .hljs-title,
article .body .hljs-function .hljs-title { color: var(--c-syntax-name); }
article .body .hljs-attr,
article .body .hljs-attribute,
article .body .hljs-variable,
article .body .hljs-template-variable,
article .body .hljs-property { color: var(--c-syntax-attr); }
article .body .hljs-emphasis { font-style: italic; }
article .body .hljs-strong { font-weight: 600; }
article .body table {
  width: 100%;
  border-collapse: collapse;
  margin: var(--sp-5) 0;
  font-size: var(--fs-1);
}
article .body th,
article .body td {
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--c-border);
  text-align: left;
}
article .body th { font-weight: 600; color: var(--c-text); background: var(--c-bg-soft); }
article .body tr:hover td { background: var(--c-bg-soft); }
article .body img { max-width: 100%; height: auto; border-radius: var(--r-md); }
article .body hr { border: 0; border-top: 1px solid var(--c-border); margin: var(--sp-6) 0; }
article .body a { text-decoration: underline; text-underline-offset: 2px; text-decoration-thickness: 1px; }
footer {
  padding: var(--sp-6) 0 0;
  font-size: var(--fs-1); color: var(--c-text-muted);
}
/* Mirror .topbar-inner / .layout: footer text aligns with the brand
   on the left and the right rail (or content, when no rail) on the
   right. The divider lives on .footer-inner (not on the full-width
   <footer>) so its left/right ends sit flush with the column box
   instead of extending past the brand on the left and the toggle on
   the right. */
.footer-inner {
  position: relative;
  max-width: 1200px; margin: 0 auto;
  padding: var(--sp-5) var(--sp-5) var(--sp-6);
  text-align: center;
}
/* Mirror of .topbar-inner::after — fade the divider ends so the
   line never sits flush against the column edge. */
.footer-inner::before {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  height: 1px;
  background: linear-gradient(
    to right,
    transparent,
    var(--c-border) 12%,
    var(--c-border) 88%,
    transparent
  );
}
@media (min-width: 1200px) { .footer-inner { max-width: 1400px; } }
footer a { color: var(--c-text-muted); text-decoration: none; }
footer a:hover { color: var(--c-text); }
@media (max-width: 960px) {
  .layout { grid-template-columns: minmax(0, 1fr); padding: var(--sp-4); }
  .topbar-inner { padding: 0 var(--sp-4) var(--sp-3); }
  .footer-inner { padding: var(--sp-5) var(--sp-4) var(--sp-6); }
  .menu-toggle { display: inline-flex; }
  .sidebar {
    position: fixed; top: 0; left: 0; bottom: 0;
    width: min(86vw, 320px); max-height: 100vh;
    background: var(--c-bg);
    border-right: 1px solid var(--c-border);
    padding: var(--sp-5);
    transform: translateX(-100%);
    transition: transform 180ms ease;
    /* Shadow only while open: a closed (translated-off) drawer's shadow would
       bleed into the viewport as a stripe along the left edge. */
    z-index: 30;
  }
  .sidebar.open { transform: translateX(0); box-shadow: var(--c-shadow); }
  .sidebar-backdrop {
    position: fixed; inset: 0; background: rgba(0,0,0,0.4);
    opacity: 0; pointer-events: none;
    transition: opacity 180ms ease; z-index: 25;
  }
  .sidebar-backdrop.open { opacity: 1; pointer-events: auto; }
}
@media (min-width: 961px) { .sidebar-backdrop { display: none; } }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
  }
}
/* Posts listing & cards.
   The listing is a container-query root so cards adapt to the
   article column width (not viewport). That lets them stay
   horizontal in the IDE preview pane AND in a full-width browser
   deploy, collapsing to vertical only when the column itself is
   too narrow. */
/* Prev/next page navigation over the published TOC sequence (docs-only). */
.page-nav { display: flex; justify-content: space-between; gap: 16px; margin: 40px 0 8px; }
.page-nav-prev, .page-nav-next {
  display: flex; flex-direction: column; gap: 2px; max-width: 48%;
  padding: 12px 16px; border: 1px solid var(--docs-brd); border-radius: 8px;
  text-decoration: none; color: var(--docs-fg1); overflow: hidden;
}
.page-nav-next { text-align: right; margin-left: auto; }
.page-nav-spacer { flex: 0 0 auto; }
.page-nav-prev:hover, .page-nav-next:hover { border-color: var(--docs-pri); color: var(--docs-pri); }
.page-nav-dir { font-size: 0.75rem; color: var(--docs-fg2); }
.page-nav-prev .page-nav-dir::before { content: "\2190  "; }   /* left arrow */
.page-nav-next .page-nav-dir::after { content: "  \2192"; }    /* right arrow */
.page-nav-title { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Header/footer actions: CTA buttons (and social icon links) from tree.yml entries. */
.nav-actions { display: flex; align-items: center; gap: 12px; flex-shrink: 0; }
.nav-btn {
  display: inline-flex; align-items: center;
  padding: 8px 16px; border-radius: 6px;
  background: var(--nav-btn-bg, var(--docs-pri));
  color: #ffffff; font-size: 0.875rem; font-weight: 600;
  text-decoration: none; white-space: nowrap;
  transition: opacity 0.2s ease;
}
.nav-btn:hover { opacity: 0.88; color: #ffffff; text-decoration: none; }
.nav-btn { gap: 6px; }
.nav-btn svg { width: 14px; height: 14px; flex-shrink: 0; }
/* External-link cue for icon-less text links: a small NE arrow after the label.
   Icon-carrying elements (.nav-social, buttons with inline svg) are exempt by construction. */
article .body a[href^="http"]:not(:has(img))::after,
.nav-links a[href^="http"]::after,
.ftr-lk-wrap a[href^="http"]::after {
  content: "\2197"; display: inline-block;
  font-size: 0.75em; margin-left: 3px;
}
.nav-social {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 0.875rem; font-weight: 500;
  color: var(--docs-fg2); text-decoration: none; white-space: nowrap;
  transition: color 0.2s ease;
}
/* Header social/external links render at full strength: unlike internal page
   links (muted fg2, so the active page can stand out as fg1), an external link
   can never be the active/selected page, so muting it just makes it look
   permanently inactive. */
.nav .nav-social { color: var(--docs-fg1); }
.nav-social:hover { color: var(--docs-pri); text-decoration: none; }
.nav-social svg { width: 18px; height: 18px; }

/* ---- Landing sections (frontmatter `sections:`) ---- */
.landing { display: flex; flex-direction: column; }
.landing section { padding: 64px 24px; }
.landing-label {
  display: inline-block; font-size: 0.7rem; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--docs-pri); background: rgba(59, 130, 246, 0.08);
  border-radius: 99px; padding: 4px 10px; margin-bottom: 8px;
}
[data-theme="dark"] .landing-label { background: rgba(88, 166, 255, 0.1); }
.landing-hero { text-align: center; background: linear-gradient(180deg, var(--docs-bg2) 0%, var(--docs-bg1) 100%); }
.landing-hero-inner { max-width: 860px; margin: 0 auto; }
.landing-badge {
  display: inline-block; padding: 4px 12px; border: 1px solid var(--docs-brd);
  border-radius: 999px; font-size: 0.8125rem; color: var(--docs-fg2); margin-bottom: 20px;
}
.landing-hero h1 { font-size: clamp(1.75rem, 6vw, 2.75rem); line-height: 1.15; letter-spacing: -0.02em; color: var(--docs-fg1); margin: 0 0 16px; overflow-wrap: break-word; text-wrap: balance; }
.landing-subtitle { font-size: 1.125rem; color: var(--docs-fg2); margin: 0 auto 28px; max-width: 640px; }
.landing-btn-row { display: flex; justify-content: center; gap: 12px; flex-wrap: wrap; }
.landing-btn-primary, .landing-btn-outline {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 12px 22px; border-radius: 8px;
  font-size: 0.9375rem; font-weight: 600; text-decoration: none; white-space: nowrap;
}
.landing-btn-primary { background: var(--docs-pri); color: #ffffff; }
.landing-btn-primary:hover { background: var(--docs-pri-hover); color: #ffffff; text-decoration: none; }
.landing-btn-outline { border: 1px solid var(--docs-brd); color: var(--docs-fg1); }
.landing-btn-outline:hover { border-color: var(--docs-pri); color: var(--docs-pri); text-decoration: none; }
.landing-btn-primary svg, .landing-btn-outline svg { width: 14px; height: 14px; flex-shrink: 0; }
.landing-steps, .landing-features, .landing-code, .landing-cta { text-align: center; }
.landing h2 { font-size: 1.875rem; letter-spacing: -0.01em; color: var(--docs-fg1); margin: 0 0 32px; }
.landing-card-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(230px, 100%), 1fr));
  gap: 20px; max-width: 1100px; margin: 0 auto; text-align: left;
}
/* Steps read as full-width horizontal rows (old landing's steps-layout), not columns:
   a leading marker block (auto number, or the item's icon) sits inline with the title,
   the text hangs indented under the title. */
.landing-steps .landing-card-grid { grid-template-columns: 1fr; max-width: 960px; gap: 24px; }
.landing-steps .landing-card { padding: 28px 32px; }
.landing-card-head { display: flex; align-items: center; gap: 14px; margin-bottom: 12px; }
.landing-card-head h3 { margin: 0; }
.landing-step-marker {
  display: inline-flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 8px; flex-shrink: 0;
  background: rgba(59, 130, 246, 0.1); color: var(--docs-pri);
  font-weight: 800; font-size: 0.9rem;
}
[data-theme="dark"] .landing-step-marker { background: rgba(88, 166, 255, 0.12); }
.landing-step-marker img { width: 20px; height: 20px; display: block; }
/* Hang the text under the title only when a marker sets that indent (numbered: false
   cards without icons have no marker and stay flush left). */
.landing-steps .landing-card:has(.landing-step-marker) p { padding-left: 54px; }
.landing-card {
  padding: 22px; border: 1px solid var(--docs-brd); border-radius: 10px; background: var(--docs-bg1);
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
}
.landing-card:hover { border-color: var(--docs-pri); box-shadow: var(--docs-shadow); }
.landing-card h3 { margin: 0 0 8px; font-size: 1rem; color: var(--docs-fg1); }
.landing-card p { margin: 0; font-size: 0.9375rem; color: var(--docs-fg2); }
.landing-card-icon { display: block; width: 48px; height: 48px; margin-bottom: 16px; }
.landing-card-icon img { width: 48px; height: 48px; display: block; }
.landing-code .code-sample { max-width: 760px; margin: 0 auto; text-align: left; }
.landing-code .code-sample pre {
  background: var(--docs-bg2); border: 1px solid var(--docs-brd);
  border-radius: 10px; padding: 24px 28px;
  box-shadow: var(--docs-shadow); overflow: auto;
}
/* Distinct accent band so the closing CTA does not blend into the neighboring sections. */
.landing-cta { background: linear-gradient(135deg, var(--docs-pri) 0%, var(--docs-acc) 100%); }
.landing-cta h2 { color: #ffffff; }
.landing-cta .landing-subtitle { color: rgba(255, 255, 255, 0.85); }
.landing-cta .landing-btn-primary {
  background: #ffffff; color: var(--docs-pri);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.landing-cta .landing-btn-primary:hover {
  background: #ffffff; color: var(--docs-pri);
  transform: translateY(-2px); box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
}
.landing-content { text-align: initial; }
.landing-content article { max-width: 860px; margin: 0 auto; }
/* `layout: full` chrome: no sidebar, no local toc, hero starts under the fixed header. */
body.layout-full { padding-top: 0; }
.layout-full .sidebar, .layout-full .page-toc, .layout-full .menu-toggle { display: none; }
.layout-full .layout { display: block; max-width: none; padding: 0; margin: 0; }
.layout-full main { max-width: none; padding: 0; }
.layout-full .landing-hero { padding-top: calc(var(--docs-nav-h) + 72px); padding-bottom: 72px; }

/* Header search results (the dropdown search-runtime.js fills): a floating panel anchored
   under the search box's right edge. Without these rules the runtime's div is a plain flex
   child of .site-search and the inline result links flow as ONE line across the header.
   The collapsed-search guard matters because Escape/blur only remove .open - the runtime
   hides the panel on outside clicks, not on collapse. */
.site-search-results {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  width: min(440px, calc(100vw - 32px));
  max-height: min(60vh, 480px);
  overflow-y: auto;
  background: var(--docs-bg1);
  border: 1px solid var(--docs-brd);
  border-radius: 10px;
  box-shadow: var(--docs-shadow);
  padding: 6px;
  z-index: 30;
}
.site-search:not(.open) .site-search-results { display: none; }
.site-search-result { display: block; padding: 8px 10px; border-radius: 8px; text-decoration: none; }
.site-search-result:hover, .site-search-result:focus-visible { background: var(--docs-bg2); text-decoration: none; }
.site-search-title { display: block; color: var(--docs-fg1); font-weight: 600; font-size: 0.9rem; }
.site-search-excerpt {
  color: var(--docs-fg2); font-size: 0.8rem; line-height: 1.4; margin-top: 2px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.site-search-empty { padding: 10px; color: var(--docs-fg2); font-size: 0.85rem; }
/* Query-term highlight inside the dropdown: accent-colored text, no yellow mark background
   (the default <mark> yellow clashes with both themes). */
.site-search-results mark { background: transparent; color: var(--docs-pri); font-weight: 600; }
