/* docs-theme-extras component baseline.
   Always loaded. Brand-specific colors / fonts live in brand-oss.css and
   brand-enterprise.css and are layered on top via head-end.html based on
   Site.Params.themeExtras.brand. Per-repo overrides go in the consumer's
   own assets/css/custom.css (which Hextra concats into its main bundle). */

/* ── Theme color vars ────────────────────────────────────────────────── */
/* Defaults are Tailwind blue-500/600/400 — generic brand-neutral primary.
   Brand layers (brand-enterprise.css, brand-oss.css) override these to
   the consumer's actual palette. Component rules below reference
   var(--theme-primary*) so swapping the brand layer swaps the color. */
:root {
  --theme-primary:       #3b82f6;
  --theme-primary-hover: #2563eb;
  --theme-primary-tint:  rgba(59, 130, 246, 0.1);
}
.dark {
  --theme-primary:       #60a5fa;
  --theme-primary-tint:  rgba(96, 165, 250, 0.1);
}

/* ── Light/dark image toggle ─────────────────────────────────────────── */
/* reuse-image uses .toggle-dark (light-mode image), reuse-image-dark uses
   .toggle-light (dark-mode image). Match old theme behavior. */
.toggle-dark  { display: block; }
.toggle-light { display: none;  }
.dark .toggle-light { display: block; }
.dark .toggle-dark  { display: none;  }

/* ── Cards-shortcode grid wrapper handling ──────────────────────────────
   Both the auto-card partial and the {{< cards >}} shortcode emit a
   `.section-cards` container; the grid styling lives further down with
   the rest of the .section-card* rules.

   When a card is wrapped by Goldmark's <p> (e.g., a card inside a
   percent-form shortcode like `{{%% version %%}}{{< card >}}{{%% /version %%}}`),
   the <p> becomes the direct grid child. CSS grid stretches the <p>
   to row height, but the <a> card inside doesn't fill the <p>. Force
   any single-card-only <p> wrapper to flex so the card fills it. */
.section-cards > p:has(> .section-card:only-child) {
  display: flex;
  margin: 0;
}
.section-cards > p:has(> .section-card:only-child) > .section-card {
  flex: 1;
}

/* ── Version banner ──────────────────────────────────────────────────── */
/* Matches old alert-info banner styling */
.version-banner {
  background: hsl(204, 45.5%, 97.8%);
  border: 1px solid #dee2e6;
  border-radius: 4px;
  color: var(--tw-prose-body, #374151);
  font-size: 0.9rem;
  padding: 0.75rem 1rem;
  margin: 0.75rem 0;
  line-height: 1.5;
}

.version-banner p {
  margin: 0 !important;
}

.dark .version-banner {
  background: hsla(210, 100%, 50%, 0.1);
  border-color: #1e3a5f;
  color: #d1d5db;
}

/* ── Alerts and callouts ─────────────────────────────────────────────── */
/* Matches old docs-theme-lotus alert styling with Material Icons */
.solo-alert {
  display: flex;
  gap: 0.5rem;
  border: 1px solid #dee2e6;
  border-radius: 4px;
  padding: 0.75rem 1rem;
  margin: 1rem 0;
  font-size: 0.9rem;
  line-height: 1.6;
  color: inherit;
}

.solo-alert-icon {
  flex-shrink: 0;
}

.solo-alert-icon .material-icons {
  font-size: 20px;
  vertical-align: middle;
}

.solo-alert-body {
  flex: 1;
  min-width: 0;
}

/* Render alert body text at one size whether the markdown produced a
   <p>/<li> block or a bare inline text node. The global `.content p` and
   `#content > .content li` rules size block children to 1rem, but bare text
   would otherwise fall back to the `.solo-alert` 0.9rem, so the same alert
   looked like a different size depending on how its body was authored
   (markdown bullets vs literal <ul>/<li> HTML, or a single inline sentence). */
.solo-alert-body,
.solo-alert-body :where(p, ul, ol, li) {
  font-size: 1rem;
  line-height: 1.7;
}

.solo-alert-body p {
  margin: 0 !important;
}

/* Alert color variants — light mode */
.alert-info    { background: hsl(204, 45.5%, 97.8%); }
.alert-warning { background: hsl(48, 100%, 96%); }
.alert-success { background: hsl(140, 50%, 96%); }
.alert-danger  { background: hsl(0, 70%, 97%); }
.alert-default { background: hsl(226, 68%, 95.1%); }

.alert-info .solo-alert-icon    { color: var(--theme-primary); }
.alert-warning .solo-alert-icon { color: #d97706; }
.alert-success .solo-alert-icon { color: #059669; }
.alert-danger .solo-alert-icon  { color: #dc2626; }
.alert-default .solo-alert-icon { color: #6b7280; }

/* Alert color variants — dark mode */
.dark .solo-alert { border-color: #374151; color: #d1d5db; }
.dark .alert-info    { background: hsla(210, 100%, 50%, 0.1); }
.dark .alert-warning { background: hsla(48, 100%, 50%, 0.1); }
.dark .alert-success { background: hsla(160, 100%, 40%, 0.1); }
.dark .alert-danger  { background: hsla(0, 100%, 50%, 0.1); }
.dark .alert-default { background: hsla(226, 68%, 50%, 0.05); }
.dark .alert-info .solo-alert-icon    { color: #60a5fa; }
.dark .alert-warning .solo-alert-icon { color: #fbbf24; }
.dark .alert-success .solo-alert-icon { color: #34d399; }
.dark .alert-danger .solo-alert-icon  { color: #f87171; }
.dark .alert-default .solo-alert-icon { color: #9ca3af; }

/* ── Copy as Markdown button ─────────────────────────────────────────── */
.copy-md-wrapper {
  display: inline-flex;
}

.copy-md-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  font-size: 0.75rem;
  font-weight: 500;
  color: #6b7280;
  background: transparent;
  border: 1px solid #d1d5db;
  border-radius: 6px;
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.2s, border-color 0.2s;
}

.copy-md-btn:hover {
  color: var(--theme-primary);
  border-color: var(--theme-primary);
}

.copy-md-btn.copied {
  color: #059669;
  border-color: #059669;
}

.copy-md-icon {
  font-size: 14px !important;
  width: 14px !important;
  height: 14px !important;
}

.copy-md-source {
  display: none !important;
}

.dark .copy-md-btn {
  color: #9ca3af;
  border-color: #4b5563;
}
.dark .copy-md-btn:hover {
  color: var(--theme-primary);
  border-color: var(--theme-primary);
}
.dark .copy-md-btn.copied {
  color: #34d399;
  border-color: #34d399;
}

/* ── Full-width layout ───────────────────────────────────────────────── */
/* Wide layout — large enough to feel flush but bounded so TOC stays visible */
:root {
  --hextra-max-page-width: 100%;
  --hextra-max-navbar-width: 100%;
}

/* Show TOC at smaller viewport widths (default is xl/1280px) */
.hextra-toc {
  display: none;
}
@media (min-width: 1024px) {
  .hextra-toc {
    display: block !important;
  }
}

/* ── Typography ──────────────────────────────────────────────────────── */
/* Heading weight is component-shaped (lighter than hextra default). Heading
   *colors* are brand-specific and live in brand-{oss,enterprise}.css. */
.content h1, .content h2, .content h3, .content h4, .content h5, .content h6 {
  font-weight: 600 !important;
}

.content h1 {
  padding-top: 1.75rem;
}

/* Ensure spacing after headings even when followed by non-paragraph text (e.g. reuse snippets) */
.content h2, .content h3, .content h4, .content h5, .content h6 {
  margin-bottom: 1rem;
}

/* Anchor-jump offset. When a TOC entry or heading anchor is clicked, the
   browser aligns the heading to the top of the viewport — which would land it
   *under* Hextra's sticky nav container. `scroll-margin-top` reserves that
   space so the heading clears the navbar (+ banner). Reuses --solo-rail-top
   (navbar + banner height) plus a small breathing gap. Applies to native
   anchor scrolling regardless of smooth vs instant. */
.content h1, .content h2, .content h3, .content h4, .content h5, .content h6 {
  scroll-margin-top: calc(var(--solo-rail-top, 4rem) + 0.5rem);
}

/* Smooth in-page scrolling for TOC / anchor-link clicks (agentgateway/website
   #664). Gated on `no-preference` so it's opt-out for users who set reduced
   motion; Hextra's own `prefers-reduced-motion` reset also forces
   `scroll-behavior: auto`, so this stays motion-safe either way. Load-time
   hash landing stays instant — see head-end.html, which passes explicit
   `behavior: 'instant'` so this rule can't animate it. */
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

/* Body text size matching old theme — scoped to main content, not sidebar */
#content > .content p, #content > .content li {
  font-size: 1rem;
  line-height: 1.7;
}

/* ── Links ───────────────────────────────────────────────────────────── */
/* Link weight is component-shaped (consistent across brands). Link colors
   live in brand-{oss,enterprise}.css. */
.content a {
  font-weight: 500;
}

/* ── Code block highlighted lines ────────────────────────────────────── */
/* Expand code to the widest line. With .hl using width:max-content below,
   code's intrinsic max-content is unambiguously the widest line's text width
   (no circular dependency). .hl's min-width:100% then references this
   expanded code width, giving all highlights uniform width. */
.chroma pre > code {
  display: block;
  min-width: max-content;
}

.chroma .line.hl {
  display: block;
  width: max-content;
  min-width: 100%;
  background-color: var(--theme-primary-tint);
}

/* Line-number highlight: put the background on the .hl wrapper that contains
   .lnt (structure is <span class="hl"><span class="lnt">N</span></span>), so it
   spans the full line-number cell — not just the digit text. */
.chroma .lntable .hl:not(.line) {
  display: block;
  background-color: var(--theme-primary-tint);
}

/* Strip horizontal padding from <pre>s inside lntable so the line-number and
   code highlights meet flush and span the cell width uniformly. Hextra's own
   padding on .lnt / .hl provides breathing room within the highlight area. */
.content .chroma .lntable pre {
  padding-left: 0 !important;
  padding-right: 0 !important;
}

/* Remove gap between line number and code columns */
.lntable {
  border-spacing: 0 !important;
  border-collapse: collapse !important;
}

.lntd {
  vertical-align: top !important;
  padding: 0 !important;
  border: 0 !important;
}

/* Remove right padding/margin on line number column */
.lntd:first-child {
  padding-right: 0 !important;
}

/* Remove left padding/margin on code column */
.lntd:last-child {
  padding-left: 0 !important;
}

/* ── Ordered lists (numbered steps) ──────────────────────────────────── */
/* Matches old docs-theme-lotus: grey background square with number */
#content > .content ol {
  list-style: none;
  padding-left: 0;
}

/* Flush top-level steps to the content edge. Hextra's prose adds
   margin-left: 1.5rem on every ol; we keep that for nested ols (which
   should stay indented under their parent step) but zero it for the
   first level. `ol:not(li ol)` matches ols that aren't inside any li. */
#content > .content ol:not(li ol) {
  margin-left: 0;
}

#content > .content ol > li {
  position: relative;
  padding-left: 27px;
  margin-top: 1rem;
  margin-left: 0;
}

#content > .content ol > li::before {
  content: counter(list-item);
  background: #ebf4f9;
  color: #343a40;
  font-size: 12px;
  font-weight: 500;
  line-height: 10px;
  text-align: center;
  padding: 5px 0;
  width: 20px;
  height: 20px;
  border-radius: 5px;
  position: absolute;
  left: 0;
  top: 3px;
}

.dark #content > .content ol > li::before {
  background: #374151;
  color: #d1d5db;
}

/* Nested ordered lists: lowercase letters.
   `:not([start])` so that an explicit `<ol start="N">` continues the
   counter from the prior sibling nested ol — needed when a list-item's
   content includes a block (HTML pre, etc.) that Goldmark renders
   outside the parent <li>, splitting one logical list into two
   sibling <ol>s. Without this, item 9 after the split would render
   as "a" instead of "i". */
#content > .content ol ol:not([start]) {
  counter-reset: sublistitem;
}

#content > .content ol ol > li {
  counter-increment: sublistitem list-item 0;
}

#content > .content ol ol > li::before {
  content: counter(sublistitem, lower-alpha);
}

/* Doubly-nested ordered lists: lowercase roman numerals */
#content > .content ol ol ol:not([start]) {
  counter-reset: subsublistitem;
}

#content > .content ol ol ol > li {
  counter-increment: subsublistitem list-item 0;
}

#content > .content ol ol ol > li::before {
  content: counter(subsublistitem, lower-roman);
}

/* ── Sidebar ─────────────────────────────────────────────────────────── */
/* Tighten sidebar font to match old theme */
.hextra-sidebar-container {
  font-size: 0.875rem;
}

/* Hide the sidebar's scrollable content briefly on first paint to avoid the
   visible "scrolled to top → jump to active item" flash. Hextra's
   sidebar.js sets scrollTop on DOMContentLoaded; head-end.html adds the
   .sidebar-loading class during <head> parse and removes it via rAF
   after DCL, so the sidebar reveals at the correct scroll position.
   The second selector covers our centralized sidebar, whose scroll region is
   .sidebar-nav-wrapper (not a .hextra-scrollbar child); head-end.html
   restores its saved scrollTop in the same DCL window before the rAF reveal. */
html.sidebar-loading .hextra-sidebar-container .hextra-scrollbar,
html.sidebar-loading .sidebar-nav-wrapper {
  visibility: hidden;
}

/* Product logo in sidebar */
.sidebar-product-logo {
  padding: 0.75rem 0;
}

/* The logo's `<a>` wrapper defaults to `display: inline`, so its line box
   (line-height ~21px) rendered the anchor ~40px taller than the image and
   left a band of phantom whitespace below the logo — the logo hugged the top
   of its block and the hairline dropped well below it. `display: block` makes
   the anchor wrap the (block) image tightly with no line box, so the logo
   height equals the image height; the symmetric vertical padding on
   `.sidebar-product-logo` above then leaves equal space over and under the
   logo (and the hairline's matching `0.75rem` top margin keeps it balanced),
   centering the logo in its band. Flexing the anchor instead would re-trigger
   the replaced-element `min-width: auto` quirk and let the image overflow the
   column. */
.sidebar-product-logo a {
  display: block;
}

/* Short, centered hairline beneath the logo. A full-width border-bottom
   read as an unfinished frame edge (no matching rule on the right or
   bottom to terminate it), so this inset rule reads as decoration
   between sections instead. */
.sidebar-product-logo::after {
  content: "";
  display: block;
  width: 85%;
  height: 1px;
  margin: 0.75rem auto 0;
  background: #e5e7eb;
}

/* Size product logos so each wordmark fills the sidebar column and reads as a
   substantial header, while never exceeding the column. The "Solo Enterprise
   for <product>" lockups all share the same glyph height but differ in width
   by name length, so their aspect ratios range from ~5.7:1 (agentgateway, the
   longest name) down to ~3.2:1 (gloo-mesh, the shortest). With width:auto +
   max-width:100%, the widest logo binds on max-width and fills the column
   exactly (~45px tall); the shorter-named ones bind on max-height instead.
   The earlier 2.5rem cap held every logo to the same glyph height, but that
   left the shorter names filling only ~50% of the column so they read as
   tiny next to agentgateway — raising the cap to 3.5rem lets the shorter
   logos grow to fill 70–95% of the column. The trade-off: short-named
   products now render at a slightly larger glyph size than the widest one,
   which is the intended prominence boost. Sizing by width directly (the
   original `width: 108%` overscan) instead bled agentgateway past the column
   into the content gutter, so keep width:auto and tune the cap. `margin-inline:
   auto` centers the narrower logos in the column (the widest fills it exactly,
   so the margins collapse to zero) — matching the centered hairline below.
   Do NOT set `display` here: a `.sidebar-product-logo img` rule (specificity
   0,1,1) outranks the `.sidebar-logo-dark { display: none }` toggle (0,1,0)
   and would force BOTH the light and dark variants visible — the dark logo is
   light-on-light so it reads as invisible but still occupies a row, stacking
   an empty logo's worth of height below the visible one. The light/dark
   toggle rules below own `display`; `margin-inline: auto` still centers the
   one visible (block) variant. */
.sidebar-product-logo img {
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 3.5rem;
  margin-inline: auto;
}

.sidebar-logo-light { display: block; }
.sidebar-logo-dark { display: none; }
.dark .sidebar-logo-light { display: none; }
.dark .sidebar-logo-dark { display: block; }
.dark .sidebar-product-logo::after { background: #374151; }

/* In the mobile slide-in panel the sidebar is a fixed 280px. Give the logo
   symmetric horizontal padding so it sits with breathing room from the panel
   edges. Sizing is handled by the base rule above (max-width:100% +
   max-height), so no width override is needed here. */
@media (max-width: 1279px) {
  .sidebar-product-logo {
    padding-left: 1rem;
    padding-right: 1rem;
  }
}

/* Darken sidebar link text */
.hextra-sidebar-container .hextra-sidebar-item a {
  color: #1f2937 !important;
}
.dark .hextra-sidebar-container .hextra-sidebar-item a {
  color: #d1d5db !important;
}

/* Nested sidebar children: indent + left border so the parent/child
   hierarchy reads visually. Matches the agw-oss sidebar design (0.75rem
   indent on both margin and padding, hairline left border). Applied to
   every <ul> inside another <ul> within .sidebar-container so the rule
   covers kgateway's recursive sidebar template AND any consumer using
   hextra's default sidebar — neither template needs to ship inline
   margins for nested levels. */
.sidebar-container ul ul {
  margin-left: 0.75rem;
  margin-top: 0.25rem;
  padding-left: 0.75rem;
  border-left: 1px solid #e5e7eb;
}
.dark .sidebar-container ul ul {
  border-left-color: #374151;
}

/* Sidebar active item — matches old theme's grey instead of hextra's blue tint */
.hextra-sidebar-container .hextra-sidebar-active-item {
  background-color: #e8eaed !important;
  color: #1f2937 !important;
  border-radius: 6px !important;
}
.dark .hextra-sidebar-container .hextra-sidebar-active-item {
  background-color: #363c47 !important;
  color: #d1d5db !important;
}
/* Sidebar hover — matches old theme */
.hextra-sidebar-container .hextra-sidebar-item a:hover {
  background-color: #eff1f4 !important;
}
.dark .hextra-sidebar-container .hextra-sidebar-item a:hover {
  background-color: #2b303b !important;
}

/* ── Figure images in dark mode ──────────────────────────────────────────
   No automatic white-card wrapper. Authors that need a dark-mode variant
   of a screenshot use `reuse-image-dark` (wraps the dark image in
   `<div class="toggle-light">`, shown only on dark pages). Images without
   a dark variant render as-is on dark pages. Mermaid diagrams use
   Mermaid's built-in dark theme; see layouts/_partials/scripts/mermaid.html. */

/* ── Mermaid: hide the raw graph source until it is rendered ──────────────
   Mermaid replaces a <pre class="mermaid"> source block with an <svg> and
   marks it data-processed. Until then the literal graph code (`graph LR …`)
   is visible. The loader deliberately defers the first render until the tab
   is painted (so the diagram isn't measured with a zero bounding box and
   collapsed), which widens that window into a visible flash of code. Hiding
   the unprocessed source removes the flash; the element keeps its box, so
   the SVG simply replaces an empty space. Mermaid here requires JS, so a
   never-processed block staying hidden is acceptable. */
pre.mermaid:not([data-processed]) {
  visibility: hidden;
}

/* ── Solo footer ─────────────────────────────────────────────────────── */
.solo-footer {
  border-top: 1px solid #e5e7eb;
  padding: 1rem 1.5rem 1.25rem;
  background: #fff;
  font-size: 0.875rem;
  line-height: 1.6;
  color: #6b7280;
}
.solo-footer-inner {
  max-width: var(--hextra-max-page-width, 100%);
  margin: 0 auto;
  text-align: center;
}
.solo-footer p {
  margin: 0;
}
.dark .solo-footer {
  background: transparent;
  border-top-color: rgba(255, 255, 255, 0.1);
  color: #9ca3af;
}

#solo-back-to-top {
  position: fixed;
  right: 1.5rem;
  bottom: 1.5rem;
  width: 40px;
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--theme-primary);
  color: #fff;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
  box-shadow: 0 2px 8px rgba(0,0,0,0.15);
  z-index: 30;
  transition: background-color 0.15s ease, transform 0.15s ease;
}
#solo-back-to-top:hover {
  background: var(--theme-primary-hover);
  transform: translateY(-1px);
}
#solo-back-to-top[hidden] {
  display: none;
}
.dark #solo-back-to-top {
  background: #2b3340;
  color: #d1d5db;
  box-shadow: 0 2px 8px rgba(0,0,0,0.4);
}
.dark #solo-back-to-top:hover {
  background: #3a4350;
}

/* When a product mounts the AI chat launcher, both it and the back-to-top
   arrow pin to the bottom-right at right:1.5rem and overlap. Rather than move
   the arrow, the arrow keeps the corner (always flush right) and the chat
   launcher is shifted left so the two sit side by side. The arrow is 40px wide
   (2.5rem) at right:1.5rem, so shifting the launcher to right:4.75rem (1.5rem
   corner + 2.5rem arrow + 0.75rem gap) clears it. !important overrides the
   launcher's inline `right`. Sites without a chat widget are unaffected.
   Contract: a product's AI chat must wrap itself in #chatbot-widget with the
   launcher carrying class .chatbot-trigger for this to apply. */
#chatbot-widget .chatbot-trigger {
  right: 4.75rem !important;
}

/* Sticky offset for the side rails (left sidebar + right TOC). It must equal
   the height of Hextra's sticky `.hextra-nav-container`, which is the navbar
   PLUS any announcement banner (`--navbar-height` + `--hextra-banner-height`,
   e.g. 4rem + 2rem = 6rem on the docs hub). Hardcoding `4rem` (navbar only)
   left both rails 1 banner-height too high, so they drifted up — and slid
   under the navbar — as the page scrolled, instead of staying pinned. The
   `0rem` fallback keeps it at the navbar height on any consumer that doesn't
   define the banner variable. */
:root {
  --solo-rail-top: calc(var(--navbar-height, 4rem) + var(--hextra-banner-height, 0rem));
}

/* ── TOC (right-hand "On this page" nav) ────────────────────────────────
   Rendered by layouts/_partials/toc.html. Class hooks are .solo-toc-*
   (plus the outer hextra-toc wrapper that hextra owns). Centralized
   from kgateway + agentgateway-oss inline styles so the right rail
   matches across both sites. */

.solo-toc-inner {
  position: sticky;
  top: var(--solo-rail-top);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  padding-right: 1rem;
  padding-top: 0.5rem;
  font-size: 0.875rem;
  hyphens: auto;
  max-height: calc(100vh - var(--solo-rail-top) - env(safe-area-inset-bottom));
  margin-right: -1rem;
}
.solo-toc-heading {
  margin-top: 0.1875rem;
  margin-bottom: 1rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  flex-shrink: 0;
}
/* The top-level heading list is the only scroll region; the "On this page"
   heading and the back-to-top footer stay pinned as fixed flex rows. This
   keeps TOC links from ever scrolling behind the footer (the prior
   sticky-footer layout let long lists bleed through its transparent
   background). min-height:0 lets the flex child actually scroll. It inherits
   the thin scrollbar from hextra's `.hextra-scrollbar *` rule. */
.solo-toc-inner > .solo-toc-sublist {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
.solo-toc-sublist {
  margin-left: 1rem;
  margin-top: 0.25rem;
}
.solo-toc-item {
  margin: 0.5rem 0;
  scroll-margin-top: 1.5rem;
  scroll-padding-top: 1.5rem;
}
.solo-toc-link {
  display: inline-block;
  width: 100%;
  word-break: break-word;
  color: #6b7280;
  text-decoration: none;
  font-size: 0.875rem;
  font-weight: 400 !important;
  padding: 2px 8px;
  transition: none !important;
}
.dark .solo-toc-link {
  color: #9ca3af;
}
.solo-toc-link:hover {
  color: inherit !important;
  background-color: #f5f6f8;
  border-radius: 6px;
}
.dark .solo-toc-link:hover {
  background-color: #2b303b;
}
.solo-toc-link.toc-active {
  color: #111827 !important;
  background-color: #e8eaed;
  border-radius: 6px;
}
.dark .solo-toc-link.toc-active {
  color: #f9fafb !important;
  background-color: #363c47;
}

/* Footer of the TOC (back-to-top + future links). Pinned as a fixed flex
   row at the bottom of .solo-toc-inner rather than sticky-overlaid, so the
   heading list scrolls above it instead of behind it. Background stays
   transparent (no brand hex to hardcode) because nothing scrolls behind it
   anymore. */
.solo-toc-bottom {
  margin-top: 2rem;
  border-top: 1px solid #e5e7eb;
  padding-top: 2rem;
  padding-bottom: 2rem;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
  background: transparent;
}
.dark .solo-toc-bottom {
  border-top-color: #374151;
}
.solo-toc-back-to-top {
  font-size: 0.75rem;
  font-weight: 500;
  color: #6b7280;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  display: inline-flex;
  align-items: center;
  gap: 0.25rem;
  /* opacity transitions the hx:opacity-0 reveal/hide toggled by Hextra's
     main.js on scroll; color handles hover. */
  transition: color 0.15s, opacity 0.15s;
}
.solo-toc-back-to-top:hover {
  color: #111827;
}
.dark .solo-toc-back-to-top {
  color: #9ca3af;
}
.dark .solo-toc-back-to-top:hover {
  color: #e5e7eb;
}
.solo-toc-back-to-top svg {
  display: inline;
  height: 0.875rem;
  width: 0.875rem;
  border: 1px solid #9ca3af;
  border-radius: 9999px;
  margin-left: 0.25rem;
}
.dark .solo-toc-back-to-top svg {
  border-color: #6b7280;
}

/* ── Page description (subtitle under <h1>) ──────────────────────────── */
/* Auto-rendered from front matter `description` by docs/single.html and
   docs/list.html. Matches the lead-paragraph styling from docs-theme-lotus. */
.page-description {
  font-size: 1.125rem;
  line-height: 1.6;
  color: #6b7280;
  margin-top: -0.5rem;
  margin-bottom: 1.5rem;
}
.dark .page-description {
  color: #9ca3af;
}

/* ── Copy-as-Markdown only blocks ────────────────────────────────────── */
/* Content emitted purely for transform.HTMLToMarkdown to capture (e.g. an
   OpenAPI summary inside the openapi shortcode). Hidden from readers but
   visible to the "Copy as Markdown" extraction. */
.copy-md-only {
  display: none !important;
}

/* ── Code blocks ─────────────────────────────────────────────────────── */
/* Match old theme: white background in light mode, dark grey in dark mode */
.content pre {
  border-radius: 6px;
  padding: 1rem;
  background-color: #fff !important;
  border: 1px solid #e5e7eb;
}

.content .highlight pre,
.content .chroma {
  background-color: #fff !important;
}

/* Syntax-highlighted blocks with line numbering: put the border/radius
   on the outer .chroma wrapper so lntable's two-cell layout renders as
   a single box, not one border per <pre>. Inner <pre>s keep their
   padding for code spacing.

   Scoped to `div.chroma` because Hugo emits `<pre class="chroma">` for
   plain blocks and `<div class="chroma">` for line-numbered ones. The
   non-`div` form is the <pre> itself; applying overflow:hidden there
   killed horizontal scroll on every plain code block. */
.content div.chroma {
  border-radius: 6px;
  border: 1px solid #e5e7eb;
  overflow: hidden;
}
.content div.chroma pre {
  border: 0 !important;
  border-radius: 0 !important;
}

.dark .content pre {
  background-color: #1a1a2e !important;
  border-color: #374151;
}

.dark .content .highlight pre,
.dark .content .chroma {
  background-color: #1a1a2e !important;
}

.dark .content div.chroma {
  border-color: #374151;
}

/* Chroma error tokens get a light background in the default theme.
   Clear it in dark mode so code blocks don't show light patches
   (common when non-JSON content is fenced as ```json). */
.dark .chroma .err {
  background-color: transparent !important;
}

/* ── Footnotes ───────────────────────────────────────────────────────── */
/* Goldmark emits `<hr class="footnotes-sep">` immediately before a
   footnotes section. The horizontal line clashes with our typography
   (tables already have a bottom border, headings have spacing) and reads
   as a visual artifact rather than a structural separator. Hide it; the
   `<section class="footnotes">` heading already separates the block. */
.footnotes-sep,
hr.footnotes-sep,
.footnotes > hr:first-child {
  display: none;
}

/* ── Tables ──────────────────────────────────────────────────────────── */
/* Match old table styling */
.content .table-wrapper {
  margin-top: 1rem;
}
.content table {
  font-size: 0.9375rem;
}
.content table th {
  font-weight: 600;
}
/* Tailwind preflight sets img{display:block} and the Hextra typography layer
   adds margin:1rem auto to all content images — override both for inline
   badge images (e.g. shields.io) used inside table cells. */
.content table td img {
  display: inline;
  vertical-align: middle;
  margin: 0 2px;
}

/* Responsive table wrapper styling (the wrapper itself comes from
   _markup/render-table.html, which inlines `overflow-x` for safety). These
   rules add the cell padding/border treatment that the inline style alone
   doesn't cover. */
.table-wrapper {
  margin: 1.5rem 0;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.table-wrapper table {
  width: 100%;
  table-layout: auto;
  border-collapse: collapse;
}
.table-wrapper th,
.table-wrapper td {
  padding: 0.5rem 0.75rem;
  border: 1px solid #e5e7eb;
  white-space: normal;
  word-wrap: break-word;
}
.dark .table-wrapper th,
.dark .table-wrapper td {
  border-color: #374151;
}

/* ── Section cards (auto-generated on list pages) ────────────────────── */
/* Replicates the docs-theme-lotus card grid on parent sections */
.section-cards {
  display: grid;
  grid-template-columns: 1fr;
  grid-auto-rows: auto;
  gap: 1rem;
  margin-top: 1.5rem;
}

@media (min-width: 640px) {
  .section-cards {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1024px) {
  .section-cards {
    /* --section-cards-cols is set inline by the {{< cards >}} shortcode
       when an author passes a `cols=N` attribute. Auto-card grids leave
       it unset and fall back to 3. */
    grid-template-columns: repeat(var(--section-cards-cols, 3), 1fr);
    grid-auto-rows: 1fr;
  }
}

.section-card {
  display: flex;
  flex-direction: column;
  padding: 1.25rem;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.2s, box-shadow 0.2s;
  height: 100%;
  /* Prevent the grid cell from expanding to the image's intrinsic width.
     Without this, a wide-aspect SVG with no explicit dimensions (only a
     viewBox) can force all 1fr columns wider than the available space in
     Firefox and WebKit. */
  min-width: 0;
}

.section-card:hover {
  border-color: var(--theme-primary);
  box-shadow: 0 2px 8px var(--theme-primary-tint);
}

/* Icons. Auto-cards emit <i class="material-icons section-card-icon">
   (font icon, sized via font-size); the {{< card >}} shortcode emits an
   inline <svg class="section-card-icon"> via utils/icon.html. Cover both. */
.section-card-icon {
  font-size: 28px;
  color: var(--theme-primary);
  flex-shrink: 0;
  margin-top: 2px;
}
svg.section-card-icon {
  width: 28px;
  height: 28px;
  margin-bottom: 0.25rem;
}

/* Optional leading image for manual cards ({{< card image="..." >}}). */
.section-card-image {
  max-height: 4rem;
  max-width: 100%;
  width: auto;
  object-fit: contain;
  margin-bottom: 1rem;
  align-self: flex-start;
}

/* The body wrapper is a <div> in auto-cards (block by default) and a
   <span class="section-card-body"> in shortcode-rendered cards (to stay
   valid HTML inside a Goldmark-added <p>). Force flex column on both. */
.section-card-body {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
}

/* Title + desc are <p> in auto-cards and <span> in shortcode cards.
   display: block makes the span behave like a block so the margins
   below apply. */
.section-card-title {
  display: block;
  font-size: 1rem !important;
  font-weight: 600 !important;
  margin: 16px 0 4px !important;
  color: #111827;
}

.section-card-desc {
  display: block;
  font-size: 0.75rem !important;
  color: #374151;
  margin: 0 !important;
  line-height: 1.5;
}
/* When the shortcode passes the subtitle through markdownify, Goldmark
   may wrap the rendered prose in a <p> inside the .section-card-desc
   <span>. That nested <p> picks up the default browser margins and
   spaces the description awkwardly. Zero them. */
.section-card-desc > p {
  margin: 0 !important;
}

.section-card-badge {
  display: inline-block;
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 2px 6px;
  border-radius: 4px;
  background: #e5e7eb;
  color: #374151;
  vertical-align: middle;
  margin-left: 4px;
}

.section-card-badge.badge-tag {
  background: #dbeafe;
  color: #1e40af;
}

.section-card-badge.badge-oss {
  background: #d1fae5;
  color: #065f46;
}

/* Section cards dark mode */
.dark .section-card {
  border-color: #374151;
}

.dark .section-card:hover {
  border-color: var(--theme-primary);
  box-shadow: 0 2px 8px var(--theme-primary-tint);
}

.dark .section-card-title {
  color: #f3f4f6;
}

.dark .section-card-desc {
  color: #9ca3af;
}

.dark .section-card-badge {
  background: #374151;
  color: #d1d5db;
}

.dark .section-card-badge.badge-tag {
  background: #1e3a5f;
  color: #93c5fd;
}

.dark .section-card-badge.badge-oss {
  background: #064e3b;
  color: #6ee7b7;
}

/* ── Page title badges (Enterprise / Alpha / Beta / etc.) ────────────── */
.page-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 6px;
}

.page-badges .section-card-badge {
  margin-left: 0;
}

/* ── Sidebar nav badges (Enterprise / Open Source) ───────────────────── */
.sidebar-badge {
  display: inline-block;
  font-size: 0.4375rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  padding: 1px 3px;
  border-radius: 3px;
  vertical-align: middle;
  margin-left: 2px;
  flex-shrink: 0;
  white-space: nowrap;
  line-height: 1.4;
}

.sidebar-badge-enterprise {
  background: #1f2937;
  color: #f9fafb;
}

.sidebar-badge-oss {
  background: #d1fae5;
  color: #065f46;
}

.dark .sidebar-badge-enterprise {
  background: #4b5563;
  color: #f9fafb;
}

.dark .sidebar-badge-oss {
  background: #064e3b;
  color: #6ee7b7;
}

/* ── Sidebar icons ───────────────────────────────────────────────────── */
/* Material Symbols in sidebar — matches old docs-theme-lotus */
.material-icons {
  font-family: 'Material Symbols Outlined';
  font-weight: normal;
  font-style: normal;
  display: inline-block;
  line-height: 1;
  text-transform: none;
  letter-spacing: normal;
  word-wrap: normal;
  white-space: nowrap;
  direction: ltr;
}

.sidebar-icon {
  font-size: 20px;
  width: 24px;
  height: 24px;
  margin-right: 6px;
  opacity: 0.7;
  flex-shrink: 0;
}

.sidebar-icon-svg {
  transform: scale(0.833333);
}

/* Keep icon + text left-aligned */
.hextra-sidebar-item a:has(.sidebar-icon) {
  justify-content: flex-start !important;
}

/* ── Version dropdown ────────────────────────────────────────────────── */
/* Replicates the docs-theme-lotus version switcher styling */

.version-dropdown {
  position: relative;
}

/* Below xl (1280px) the mobile slide-out sidebar renders its own version
   selector (.sidebar-mobile-version-row), so hide the navbar version dropdown
   there to avoid showing it in two places on mobile. Scoped to pages that
   actually have a slide-out panel, so landing / non-docs pages keep the navbar
   dropdown as their only selector. The 1279px bound matches the
   .sidebar-mobile-panel breakpoint. The dropdown stays on desktop (>= 1280px). */
@media (max-width: 1279px) {
  body:has(.sidebar-mobile-panel) .version-dropdown {
    display: none !important;
  }
}

.version-product-name {
  display: none;
}

@media (min-width: 768px) {
  .version-product-name {
    display: inline;
  }
}

.version-dropdown-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.3px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 6px;
  cursor: pointer;
  color: inherit;
  white-space: nowrap;
  transition: color 0.2s, border-color 0.2s;
}

.version-dropdown-btn:hover {
  color: var(--theme-primary);
}

.version-dropdown-btn svg {
  transition: transform 0.2s;
}

.version-dropdown.open .version-dropdown-btn svg {
  transform: rotate(180deg);
}

/* Menu — hidden by default, shown when .open is on parent */
.version-dropdown-menu {
  display: none !important;
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 4px;
  min-width: 180px;
  max-height: 300px;
  overflow-y: auto;
  background: #fff;
  border: 1px solid #e5e7eb;
  border-top: none;
  border-radius: 0 0 6px 6px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  padding: 4px 0;
  z-index: 50;
  list-style: none;
}

.version-dropdown.open .version-dropdown-menu {
  display: block !important;
}

.version-dropdown-item {
  display: block;
  padding: 8px 16px;
  font-size: 0.875rem;
  color: #374151;
  text-decoration: none;
  transition: color 0.15s;
}

.version-dropdown-item:hover {
  color: var(--theme-primary);
  background: #f9fafb;
}

/* ── Version dropdown dark mode ──────────────────────────────────────── */
.dark .version-dropdown-btn {
  color: #d1d5db;
}

.dark .version-dropdown-btn:hover {
  color: var(--theme-primary);
}

.dark .version-dropdown-menu {
  background: #1a1a1a;
  border-color: #333;
}

.dark .version-dropdown-item {
  color: #d1d5db;
}

.dark .version-dropdown-item:hover {
  color: var(--theme-primary);
  background: #262626;
}

.version-dropdown-divider {
  height: 0;
  margin: 4px 0;
  border-top: 1px solid #e5e7eb;
}

.dark .version-dropdown-divider {
  border-color: #444;
}

.version-dropdown-header {
  padding: 6px 16px 2px;
  font-size: 0.75rem;
  font-weight: 600;
  color: #6b7280;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.dark .version-dropdown-header {
  color: #9ca3af;
}

.version-dropdown-hidden {
  padding: 2px 16px;
  font-size: 0;
  line-height: 0;
}

/* Search: "Other versions" collapsible section */
.hextra-search-other-versions {
  border-top: 1px solid #e5e7eb;
  margin-top: 4px;
}
.dark .hextra-search-other-versions {
  border-top-color: #374151;
}
.hextra-search-other-versions > summary {
  padding: 6px 12px;
  font-size: 0.75rem;
  font-weight: 600;
  color: #6b7280;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  user-select: none;
}
.hextra-search-other-versions > summary::-webkit-details-marker {
  display: none;
}
.hextra-search-other-versions > summary::before {
  content: '▶ ';
  font-size: 0.6rem;
  vertical-align: middle;
  margin-right: 2px;
}
details[open].hextra-search-other-versions > summary::before {
  content: '▼ ';
}
.dark .hextra-search-other-versions > summary {
  color: #9ca3af;
}
.hextra-search-other-versions > ul {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* ── Hextra v0.12 missing compiled variants ──────────────────────────── */
/* hextra's compiled main.css includes hx:dark:block but not its responsive
   variants. These are used in navbar-title.html for the dark-mode logos. */
@media (min-width: 48rem) {
  .hx\:md\:dark\:block:where(.dark, .dark *) { display: block; }
}
@media not all and (min-width: 48rem) {
  .hx\:max-md\:dark\:block:where(.dark, .dark *) { display: block; }
}

/* ── Print styles ─────────────────────────────────────────────────────── */
@media print {
  @page { margin: 1.5cm 2cm; }

  /* Hide UI chrome — sidebar/TOC already have hx:print:hidden from hextra */
  .copy-md-wrapper,
  .nav-container,
  .hextra-nav-container,
  footer,
  .hextra-component-issue,
  [class*="pager"],
  [class*="page-feedback"],
  [class*="last-updated"],
  [class*="comments"],
  #chatbot-container { display: none !important; }

  /* Let article fill the printable area */
  body, html { overflow: visible !important; }
  article {
    display: block !important;
    width: 100% !important;
    max-width: 100% !important;
    padding-right: 0 !important;
    min-height: 0 !important;
  }
  article > main {
    max-width: 100% !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
  }

  /* Fix the main cause: code blocks clip at the paper edge on screen overflow */
  pre, code {
    white-space: pre-wrap !important;
    overflow: visible !important;
    word-break: break-word !important;
    max-width: 100% !important;
  }

  /* Chroma lntable: the general pre/code rules above collapse the line-number
     column at page breaks, causing two-digit numbers to split across lines.
     Undo word-break and max-width constraints for that column only. */
  .lntable { width: 100%; }
  .lntable .lntd:first-child pre,
  .lntable .lntd:first-child code {
    white-space: pre !important;
    word-break: normal !important;
    overflow-wrap: normal !important;
    max-width: none !important;
    min-width: 2.5em;
  }

  /* Avoid breaking inside short blocks; don't force headings to next page */
  blockquote, figure, img { break-inside: avoid; }
}

/* ──────────────────────────────────────────────────────────────────────
 * Tailwind 4 hx: utility fallbacks.
 *
 * Hextra v0.12.3 ships a precompiled main.css generated from its own
 * template scan. Utilities Hextra doesn't use internally aren't in the
 * bundle — so any class extras' or a consumer's templates emit that
 * Hextra doesn't happen to use silently no-ops.
 *
 * These rules fill the specific gaps extras' own templates introduce
 * (currently the taller navbar height). They use Hextra's --hx-spacing
 * token so they track the same scale.
 * ────────────────────────────────────────────────────────────────────── */

.hx\:h-20 { height: calc(var(--hx-spacing) * 20) }
.hx\:h-24 { height: calc(var(--hx-spacing) * 24) }

/* Navbar bottom border. Hextra's navbar template emits an arbitrary-value
   shadow class — `hx:shadow-[0_2px_4px_rgba(0,0,0,.02),0_1px_0_rgba(0,0,0,.06)]`
   — to paint a subtle bottom hairline + soft drop shadow. Hextra's
   precompiled bundle does NOT include this class (the comma + bracket
   form gets skipped by their template scanner), so the navbar renders
   without any separation from content. The matching `dark:` and
   `contrast-more:` variants are also missing. Rebuild them as direct
   rules on .nav-container-blur. */
.nav-container-blur {
  box-shadow: 0 2px 4px rgba(0,0,0,.02), 0 1px 0 rgba(0,0,0,.06);
}
:where(.dark, .dark *) .nav-container-blur {
  box-shadow: 0 -1px 0 rgba(255,255,255,.1) inset;
}
@media (prefers-contrast: more) {
  .nav-container-blur { box-shadow: 0 0 0 1px #000; }
  :where(.dark, .dark *) .nav-container-blur { box-shadow: 0 0 0 1px #fff; }
}

/* ── Hextra tab buttons ─────────────────────────────────────────────────
   Hextra v0.12.3's native tabs style their <button> toggles entirely with
   `hx:` utilities that land in @layer utilities. A consumer whose local
   Tailwind build emits its own (unlayered) Preflight — `button{padding:0;
   margin:0}` and `*{border-width:0}` — overrides those layered utilities,
   because unlayered declarations beat layered ones in the cascade. The
   result: the tab bar collapses to plain run-together text with no padding,
   spacing, or underline.

   Re-assert the toggle styling here as plain, unlayered class rules so it
   survives any consumer Preflight. The selected/hover accent uses
   var(--theme-primary*) so it tracks the active brand layer. The panels
   themselves are <div>s (not hit by the button reset) so Hextra's own
   show/hide utilities still work — only the buttons need rescuing. */
.hextra-tabs-toggle {
  cursor: pointer;
  padding: 0.5rem;
  margin-right: 0.5rem;
  font-weight: 500;
  border-bottom: 2px solid transparent;
  border-top: none;
  border-left: none;
  border-right: none;
  background: none;
  color: #4b5563;
  transition: color 0.15s, border-color 0.15s;
}
.hextra-tabs-toggle:hover {
  color: #000;
  border-bottom-color: #d1d5db;
}
.hextra-tabs-toggle[data-state="selected"] {
  color: var(--theme-primary);
  border-bottom-color: var(--theme-primary);
}
.dark .hextra-tabs-toggle {
  color: #d1d5db;
}
.dark .hextra-tabs-toggle:hover {
  color: #fff;
  border-bottom-color: #4b5563;
}
.dark .hextra-tabs-toggle[data-state="selected"] {
  color: var(--theme-primary);
  border-bottom-color: var(--theme-primary);
}

/* ── Breadcrumb ─────────────────────────────────────────────────────────
   Rendered by layouts/_partials/breadcrumb.html. The partial emits plain
   class hooks (no Tailwind utilities) so styling doesn't depend on
   Hextra's precompiled bundle picking up the right variants. */
.solo-breadcrumb {
  margin-top: 0.1875rem;
  margin-bottom: 1rem;
  display: flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.875rem;
  color: #6b7280;
  flex-wrap: wrap;
}
.solo-breadcrumb-home,
.solo-breadcrumb-link {
  color: #6b7280;
  text-decoration: none;
}
.solo-breadcrumb-home {
  display: flex;
  align-items: center;
}
.solo-breadcrumb-link:hover,
.solo-breadcrumb-home:hover {
  color: #374151;
}
.solo-breadcrumb-sep {
  color: #d1d5db;
}
.dark .solo-breadcrumb,
.dark .solo-breadcrumb-home,
.dark .solo-breadcrumb-link {
  color: #9ca3af;
}
.dark .solo-breadcrumb-sep {
  color: #4b5563;
}
.dark .solo-breadcrumb-link:hover,
.dark .solo-breadcrumb-home:hover {
  color: #e5e7eb;
}

/* ── Navbar dropdowns ────────────────────────────────────────────────────
   Hover-based dropdowns in the top navbar (e.g. version switcher, "Docs"
   sub-menu). Each `<div class="dropdown">` wraps a trigger element plus a
   `<div|ul class="dropdown-content navbar-dropdown-content">` popover.
   Hover on the parent shows the popover.

   This used to live in kgateway's _partials/navbar.html and a near-
   identical copy in agentgateway-oss-website's partials/nav.html. Moved
   here so a single rule applies to both consumers (and any future ones).
   Note: agw's local copy can be deleted on the next docs-theme-extras
   release bump.

   `font` is explicitly inherited on the trigger to defeat the user-agent
   stylesheet's button defaults — without this, Safari ships a slightly
   heavier weight on `<button>` triggers than on sibling `<a>` triggers,
   making the version dropdown visually taller and bolder than the Docs
   dropdown trigger right next to it. */
.dropdown {
  position: relative;
  display: inline-block;
}
.dropdown-content {
  display: none;
  min-width: 160px;
}
.dropdown:hover .dropdown-content {
  display: block;
}
/* Invisible hover bridge between the trigger and the popover so moving
   the cursor across the 0.25rem gap doesn't close the menu. */
.dropdown::before {
  content: '';
  position: absolute;
  top: 100%;
  right: 0;
  left: 0;
  height: 0.5rem;
  z-index: 49;
}

.navbar-dropdown-content {
  position: absolute;
  top: calc(100% + 0.25rem);
  right: 0;
  background-color: white;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 0.5rem;
  box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
  z-index: 50;
  padding-top: 0.25rem;
}
:where(.dark, .dark *) .navbar-dropdown-content {
  background-color: rgb(17, 24, 39); /* gray-900 */
  border-color: rgba(255, 255, 255, 0.1);
}

/* Normalize trigger typography across <button> and <a> triggers. Tailwind
   4's preflight already does `button { font: inherit }` but Safari is
   inconsistent about applying the inherited weight; lock it in. */
.nav-container .dropdown > button,
.nav-container .dropdown > a {
  font-family: inherit;
  font-size: 0.875rem; /* text-sm — match other nav links */
  font-weight: 400;
  line-height: 1.25rem;
  letter-spacing: inherit;
}

/* Popover items. Single source for color + sizing so the Docs dropdown
   items and the version dropdown items render identically. */
.navbar-dropdown-content a {
  display: block;
  padding: 0.75rem 1rem;
  font-size: 0.875rem;
  font-weight: 400;
  color: rgb(55, 65, 81); /* gray-700 */
  white-space: nowrap;
  text-decoration: none;
}
:where(.dark, .dark *) .navbar-dropdown-content a {
  color: rgb(209, 213, 219); /* gray-300 */
}
.navbar-dropdown-content a:hover {
  background-color: rgb(243, 244, 246); /* gray-100 */
  color: rgb(17, 24, 39); /* gray-900 */
}
:where(.dark, .dark *) .navbar-dropdown-content a:hover {
  background-color: rgb(31, 41, 55); /* gray-800 */
  color: rgb(255, 255, 255);
}


/* ── Sidebar ─────────────────────────────────────────────────────────── */
/* Centralized sidebar styling. The template lives in _partials/sidebar.html;
   the chevron-toggle / mobile-panel JS lives in themeExtras/head-end.html.
   These rules cover:
     - Mobile slide-in panel + overlay (< xl)
     - Mobile-only section/version chip rows
     - Expand/collapse chevron button styling
     - Sidebar link colors (light + dark)
     - Tree indentation with left rule
   Site-specific palettes (e.g. active link color, active background) can
   still be overridden in the consumer's custom.css. */

/* Mobile slide-in panel (< xl). Hidden on desktop; rendered in same DOM
   as the desktop aside, just promoted to position:fixed on mobile.

   Bound uses 1279px (integer), not 1279.99px: Chromium rounds fractional
   max-width comparisons in ways that can spuriously match at exactly
   1280px viewport, which left the panel position:fixed + translateX(-100%)
   on desktop and broke `await expect(sidebar).toBeVisible()` in Playwright. */
@media (max-width: 1279px) {
  .sidebar-mobile-panel {
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    bottom: 0 !important;
    width: 280px !important;
    z-index: 90 !important;
    transform: translateX(-100%);
    transition: transform 300ms ease-in-out;
    background: white;
    padding-top: 64px;
    visibility: hidden;
    overflow-y: auto;
    display: flex !important;
    flex-direction: column !important;
  }
  .dark .sidebar-mobile-panel {
    background: rgb(17, 24, 39);
  }
  .sidebar-mobile-panel.mobile-sidebar-open {
    transform: translateX(0);
    visibility: visible;
  }
}
.sidebar-mobile-overlay {
  display: none;
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  z-index: 89;
}
.sidebar-mobile-overlay.active {
  display: block;
}

/* Hide mobile-only chrome on desktop. */
@media (min-width: 1280px) {
  .sidebar-mobile-only {
    display: none !important;
  }
}

/* Mobile section + version chip rows. */
.sidebar-mobile-header {
  border-bottom: 1px solid #e5e7eb;
}
.dark .sidebar-mobile-header {
  border-bottom-color: #374151;
}
.sidebar-mobile-section-row {
  display: flex;
  gap: 0.5rem;
  padding: 0.75rem;
}
.sidebar-mobile-section-link {
  flex: 1;
  text-align: center;
  padding: 0.5rem;
  border-radius: 0.375rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: rgb(75, 85, 99);
  text-decoration: none;
}
.sidebar-mobile-section-link:hover {
  background: rgb(243, 244, 246);
}
.dark .sidebar-mobile-section-link {
  color: rgb(156, 163, 175);
}
.dark .sidebar-mobile-section-link:hover {
  background: rgb(31, 41, 55);
}
.sidebar-mobile-section-active {
  background: rgb(219, 234, 254);
  color: rgb(30, 64, 175);
}
.dark .sidebar-mobile-section-active {
  background: rgba(96, 165, 250, 0.1);
  color: rgb(96, 165, 250);
}
.sidebar-mobile-version-row {
  padding: 0 0.75rem 0.75rem;
  display: flex;
  gap: 0.25rem;
  flex-wrap: wrap;
}
.sidebar-mobile-version-group {
  flex-basis: 100%;
  margin-top: 0.5rem;
  font-size: 0.6875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: rgb(107, 114, 128);
}
.sidebar-mobile-version-group:first-child {
  margin-top: 0;
}
.dark .sidebar-mobile-version-group {
  color: rgb(156, 163, 175);
}
.sidebar-mobile-version-link {
  padding: 0.375rem 0.75rem;
  border-radius: 0.375rem;
  font-size: 0.75rem;
  font-weight: 500;
  color: rgb(107, 114, 128);
  text-decoration: none;
}
.sidebar-mobile-version-link:hover {
  background: rgb(243, 244, 246);
}
.dark .sidebar-mobile-version-link {
  color: rgb(156, 163, 175);
}
.dark .sidebar-mobile-version-link:hover {
  background: rgb(31, 41, 55);
}
.sidebar-mobile-version-active {
  background: rgb(229, 231, 235);
  color: rgb(17, 24, 39);
}
.dark .sidebar-mobile-version-active {
  background: rgb(55, 65, 81);
  color: rgb(255, 255, 255);
}

/* Sidebar nav wrapper. On desktop the nav tree is the scroll region (see the
   min-width:1280px block below); on mobile the slide-in panel scrolls the
   whole aside, so flex-grow lets the wrapper fill the panel. */
.sidebar-nav-wrapper {
  padding: 0 1rem 1rem;
  flex-grow: 1;
}
.sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  font-size: 0.875rem;
}

/* Desktop: pin the sidebar in the viewport with its own scroll region,
   mirroring the right-hand TOC. The product logo stays pinned as a fixed
   flex row while the nav tree scrolls inside .sidebar-nav-wrapper, so the
   sidebar no longer scrolls with the article. Loaded after Hextra's CSS, so
   `display: flex` here wins over the aside's `hx:xl:block` at equal
   specificity. Below xl the mobile slide-in panel rules above own the
   layout. */
@media (min-width: 1280px) {
  .sidebar-container {
    position: sticky;
    top: var(--solo-rail-top);
    max-height: calc(100vh - var(--solo-rail-top) - env(safe-area-inset-bottom));
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }
  .sidebar-product-logo {
    flex-shrink: 0;
  }
  .sidebar-nav-wrapper {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    /* Match the right TOC's thin scrollbar (Hextra's .hextra-scrollbar). */
    scrollbar-width: thin;
    scrollbar-color: oklch(55.55% 0 0 / 0.4) transparent;
    scrollbar-gutter: stable;
  }
}

/* Tree lists. Depth 0 sits at the section root; deeper levels indent under
   a thin left rule that mirrors the docs-theme-lotus pattern. */
.sidebar-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.sidebar-list-depth-0 {
  margin-top: 0;
}
.sidebar-list:not(.sidebar-list-depth-0) {
  margin-left: 0.75rem;
  margin-top: 0.25rem;
  padding-left: 0.75rem;
  border-left: 1px solid #e5e7eb;
}
.dark .sidebar-list:not(.sidebar-list-depth-0) {
  border-left-color: #374151;
}
.sidebar-list > li + li {
  margin-top: 0.25rem;
}

/* Link row: link + chevron toggle button live in a flex wrapper so clicking
   the chevron doesn't fire the link's navigation. */
.sidebar-link-wrapper {
  display: flex;
  align-items: stretch;
  gap: 0;
}
.sidebar-link-wrapper .sidebar-link {
  flex: 1;
  min-width: 0;
}
.sidebar-link {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  border-radius: 0.375rem;
  padding: 0.5rem 0.75rem;
  font-size: 0.875rem;
  transition: color 0.15s;
  text-decoration: none;
  color: rgb(75, 85, 99);
}
/* Let long, unbreakable nav labels (e.g. CRD names like
   EnterpriseKgatewayTrafficPolicy) wrap instead of being clipped at the
   sidebar's right edge. `anywhere` (not `break-word`) is required here: only
   `anywhere` reduces the flex item's min-content size, so the word actually
   wraps rather than overflowing the fixed-width sidebar. min-width:0 lets the
   flex span shrink below its content width. */
.sidebar-link > span {
  min-width: 0;
  overflow-wrap: anywhere;
}
/* Hextra's prev/next pager links carry the `[word-break:break-word]` utility,
   which (like `break-word` anywhere) does NOT reduce the flex item's
   min-content size. A long, unbreakable title (e.g. a CRD name like
   EnterpriseKgatewayTrafficPolicy) therefore fails to wrap and shoves the
   pager's arrow icon past the viewport's right edge, producing a horizontal
   scrollbar on mobile. `overflow-wrap:anywhere` + `min-width:0` lets the word
   actually break, the same fix applied to `.sidebar-link > span` above. The
   `[word-break:break-word]` class is Hextra's marker for these pager links, so
   the attribute selector targets exactly them without needing the Tailwind
   `:`/`[]` escaping. */
a[class*="word-break:break-word"] {
  min-width: 0;
  overflow-wrap: anywhere;
}
.sidebar-link:hover {
  color: rgb(17, 24, 39);
  background: rgb(243, 244, 246);
}
.sidebar-link.sidebar-active-item {
  color: rgb(30, 64, 175);
  background: rgb(219, 234, 254);
  font-weight: 600;
}
.dark .sidebar-link {
  color: rgb(156, 163, 175);
}
.dark .sidebar-link:hover {
  color: rgb(229, 231, 235);
  background: rgba(255, 255, 255, 0.05);
}
.dark .sidebar-link.sidebar-active-item {
  color: rgb(199, 210, 254);
  background: rgba(99, 102, 241, 0.1);
}

/* Chevron toggle button — flips 0deg → 90deg on data-expanded="true". */
.sidebar-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 0.5rem;
  background: transparent;
  border: 0;
  border-radius: 0.25rem;
  color: inherit;
  cursor: pointer;
  flex-shrink: 0;
}
.sidebar-toggle:hover {
  background: rgba(0, 0, 0, 0.05);
}
.dark .sidebar-toggle:hover {
  background: rgba(255, 255, 255, 0.06);
}
.sidebar-toggle svg {
  transition: transform 0.15s ease;
  width: 1rem;
  height: 1rem;
}
.sidebar-toggle[aria-expanded="true"] svg {
  transform: rotate(90deg);
}

/* Sidebar mobile trigger — opens the docs sidebar slide-in panel.
   Pure-text/icon style matching agw production: no border, no background,
   just the colored hamburger icon with padding. The boxed look is reserved
   for the global nav drawer trigger (which is a heavier UI element). */
.solo-sidebar-mobile-trigger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.5rem;
  margin-left: -0.5rem;
  margin-right: 0.25rem;
  background: transparent;
  border: 0;
  color: rgb(55, 65, 81);
  cursor: pointer;
}
.solo-sidebar-mobile-trigger:hover {
  color: rgb(17, 24, 39);
}
.dark .solo-sidebar-mobile-trigger {
  color: rgb(209, 213, 219);
}
.dark .solo-sidebar-mobile-trigger:hover {
  color: rgb(243, 244, 246);
}
@media (min-width: 1280px) {
  .solo-sidebar-mobile-trigger {
    display: none !important;
  }
}
/* `hidden` attribute must win over the base `display: inline-flex` above (a
   class selector otherwise beats the UA [hidden] rule). The theme navbar
   renders its trigger with `hidden` and themeExtras/head-end.html removes it
   only when a `.sidebar-mobile-panel` exists, so landing / non-docs pages
   never show a dead button. Consumer navbars (kgw/agw) render the trigger
   without `hidden`, so this rule does not affect them. */
.solo-sidebar-mobile-trigger[hidden] {
  display: none !important;
}
/* Tablet-band scope for the theme-navbar trigger only: below md the wired
   `.hextra-hamburger-menu` already toggles the sidebar, so suppress the
   second trigger there to avoid two hamburgers on mobile. (Combined with the
   >= 1280 rule above, the trigger shows only across 768–1279px.) Consumer
   triggers omit this class and stay visible across the full < 1280 range. */
@media (max-width: 767px) {
  .solo-sidebar-trigger-tabletonly {
    display: none !important;
  }
}

/* ── Mobile drawer "closed" state: visibility instead of display ─────────
   Hextra v0.12.3's `en.search.js` defines:
     function getActiveSearchElement() {
       const inputs = Array.from(document.querySelectorAll('.hextra-search-wrapper'))
         .filter(el => el.clientHeight > 0);
       if (inputs.length === 1) { return {...}; }
       // implicit undefined when 0 or 2+ visible
     }
   Its mousedown/keydown handlers destructure the result without a null
   guard, so every event throws when no `.hextra-search-wrapper` has
   `clientHeight > 0`. Crucially, that includes every keystroke INSIDE
   the drawer's search input — typing crashes the search.

   The drawer toggles `hx:hidden` (display: none) for its closed state.
   `display: none` collapses descendants' clientHeight to 0, so when the
   drawer holds the only search wrapper on mobile, "closed" means the
   wrapper has clientHeight 0 → filter returns []. Worse, typing in the
   open drawer still triggers keydown on the document, and Hextra's
   handler queries again — if anything else collapses height between
   keystrokes the same throw fires.

   Fix: override `display: none` from `hx:hidden` with `visibility:
   hidden` for `#mobile-icons-menu` specifically. visibility-hidden
   elements stay in layout (descendants keep non-zero clientHeight) so
   Hextra's filter still finds the wrapper. Pointer-events: none keeps
   invisible content from blocking clicks. `position: absolute` is
   already set on the drawer so it doesn't take normal-flow space.

   ID selector (specificity 100) wins over `.hx\:hidden`'s class
   selector (specificity 10) without needing !important. */
#mobile-icons-menu.hx\:hidden {
  display: block;
  visibility: hidden;
  pointer-events: none;
}

/* ── Mobile drawer search ─────────────────────────────────────────────────
   Hextra hides the navbar search below md via `nav .hextra-search-wrapper {
   display: none }` (re-shown only at >= 48rem), because stock Hextra relocates
   search into its own mobile menu. Our `#mobile-icons-menu` lives inside <nav>,
   so the search we render there inherits that hide. Re-show it: the ID selector
   (specificity 100) beats Hextra's `nav .hextra-search-wrapper` (11) without
   !important, and at >= 768px the drawer's parent is `hx:md:hidden`
   (display: none), so this never produces a second visible search wrapper on
   desktop — keeping exactly one for Hextra's getActiveSearchElement(). */
#mobile-icons-menu .hextra-search-wrapper {
  display: block;
  width: 100%;
}
.solo-mobile-drawer-search {
  width: 16rem;
  max-width: 80vw;
  padding: 0.25rem 0.25rem 0.5rem;
}
