/* ============================================================
   base_docs.css — documentation layout (brand-neutral).
   Uses base theme tokens (--bg-gradient, --container-bg, --card-bg,
   --border-color, --text-color, --muted-text, --heading-color,
   --primary-color, --primary-blue, --link) so each project's theme
   applies automatically. Auto-injected on `.docs-page`.
   ============================================================ */

/* Layout metrics live on :root, not on .docs-page: the top bar is rendered in the
   layout's navbar block, OUTSIDE <main class="docs-page">, so tokens scoped to the
   page were undefined there - which silently invalidated the bar's grid columns and
   its height. Lengths are safe on :root; the colour tokens below are not, because
   they resolve --primary-blue, which is only declared on body. */
:root {
  --docs-topbar-h: 56px;
  --docs-sidebar-w: 288px;
  --docs-toc-w: 252px;
  --docs-maxw: 1380px;
}

.docs-page {
  /* The docs accent follows the PROJECT brand. It used to be --primary-color,
     which is the framework's own teal in dark and coral in light, so a rebrand
     changed the whole site except its documentation. Every value here is mixed
     off --primary-blue; nothing in this file may use a colour literal. */
  --docs-accent: var(--primary-blue);
  --docs-accent-soft: color-mix(in oklch, var(--primary-blue) 14%, transparent);
  --docs-accent-line: color-mix(in oklch, var(--primary-blue) 34%, transparent);
  --docs-row-hover: color-mix(in oklch, var(--text-color) 6%, transparent);
  --docs-rail: color-mix(in oklch, var(--text-color) 12%, transparent);
  --docs-focus: color-mix(in oklch, var(--primary-blue) 55%, transparent);
  width: 100% !important;
  max-width: none !important;
  margin: 0 !important;
  padding: 0 !important;
  background: none !important;
  box-shadow: none !important;
  border-radius: 0 !important;
}

/* Reserve the scrollbar gutter so the centered shell never shifts
   horizontally between docs pages (some pages scroll, some don't). */
html:has(.docs-page) {
  scrollbar-gutter: stable;
}

/* ---------- Top bar (logo left · search centered · actions right) ---------- */
.docs-logo {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  justify-self: start;
  color: var(--heading-color);
  font-weight: 700;
  font-size: 17px;
  letter-spacing: -0.02em;
  text-decoration: none;
  border: 0;
}
.docs-logo:hover {
  color: var(--heading-color);
}
.docs-logo__mark {
  width: 26px;
  height: 26px;
  flex: none;
}
.docs-nav-toggle {
  display: none;
  width: 38px;
  height: 38px;
  border: 1px solid var(--docs-rail);
  border-radius: 9px;
  background: var(--card-bg);
  color: var(--text-color);
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
.docs-nav-toggle svg {
  width: 18px;
  height: 18px;
}

/* ---------- 3-column shell ---------- */
/* Full viewport width. The docs are an application surface, not an article on the
   marketing site, so the shell is not centred inside --docs-maxw; the reading
   measure is set on the article itself instead. */
.docs-shell {
  display: grid;
  grid-template-columns: var(--docs-sidebar-w) minmax(0, 1fr) var(--docs-toc-w);
  gap: 0;
  width: 100%;
  max-width: none;
  margin: 0;
}

/* The two nav columns scroll independently; their scrollbars should not draw
   attention away from the article. */
.docs-sidebar,
.docs-toc {
  scrollbar-width: thin;
  scrollbar-color: color-mix(in oklch, var(--text-color) 18%, transparent)
    transparent;
}

.docs-sidebar::-webkit-scrollbar,
.docs-toc::-webkit-scrollbar {
  width: 8px;
}

.docs-sidebar::-webkit-scrollbar-thumb,
.docs-toc::-webkit-scrollbar-thumb {
  border-radius: 8px;
  background: color-mix(in oklch, var(--text-color) 16%, transparent);
}

.docs-sidebar::-webkit-scrollbar-track,
.docs-toc::-webkit-scrollbar-track {
  background: transparent;
}

/* ---------- Top bar ---------- */
.docs-topbar {
  position: sticky;
  top: 0;
  z-index: 60;
  display: grid;
  grid-template-columns: var(--docs-sidebar-w) minmax(0, 1fr) auto;
  align-items: center;
  height: var(--docs-topbar-h);
  padding-right: 20px;
  background: color-mix(
    in srgb,
    var(--bg-gradient, var(--bg-dark)) 82%,
    transparent
  );
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-bottom: 1px solid
    color-mix(in oklch, var(--text-color) 12%, transparent);
}

.docs-logo {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-left: 20px;
  color: var(--text-color);
  text-decoration: none;
  border-bottom: 0;
}

.docs-logo__name {
  font-family: inherit;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -0.2px;
}

/* Centred over the article column, like the reference layout. */
.docs-topbar__search {
  display: flex;
  justify-content: center;
  padding: 0 24px;
}

.docs-topbar__search .search-field {
  width: 100%;
  max-width: 420px;
  cursor: pointer;
}

/* The input is readonly and only there for the placeholder, so it must not show a
   text caret or swallow the pointer. */
.docs-topbar__search .search-field__input,
.docs-topbar__search .search-field__icon {
  cursor: pointer;
}

.docs-search-kbd {
  position: absolute;
  top: 50%;
  right: 10px;
  transform: translateY(-50%);
  padding: 2px 6px;
  border-radius: 6px;
  border: 1px solid var(--docs-rail);
  background: color-mix(in oklch, var(--text-color) 6%, transparent);
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 11px;
  line-height: 1.5;
  color: var(--muted-text);
  pointer-events: none;
}

/* Room for the hint so a long placeholder never runs under it. */
.docs-topbar__search .search-field__input {
  padding-right: 52px;
}

.docs-topbar__actions {
  display: flex;
  align-items: center;
  gap: 10px;
  justify-self: end;
}

/* ---------- Left category nav ---------- */
.docs-sidebar {
  position: sticky;
  top: var(--docs-topbar-h);
  align-self: start;
  height: calc(100vh - var(--docs-topbar-h));
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 20px 14px 48px;
  border-right: 1px solid var(--docs-rail);
}
/* The identity row at the top of the sidebar, where the top bar used to be. */
.docs-page .base-sidebar--docs .base-sidebar__header {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 0;
  padding: 0 0 14px;
  border-bottom: 1px solid var(--docs-rail);
  margin-bottom: 14px;
}

.docs-side-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
}

.docs-page .base-sidebar--docs .base-sidebar__search {
  width: 100%;
  padding: 0;
}

.docs-page .base-sidebar--docs .search-field {
  width: 100%;
}

/* The component ships a collapse-to-rail control; a docs nav has nothing to
   collapse into, and data-collapse-toggle="false" stops it being injected. */
.docs-page .base-sidebar--docs .base-sidebar__collapse-toggle-row {
  display: none;
}

/* ---------- Sidebar: the shared component, skinned for docs ----------
   docs_nav.jinja2 emits `base-sidebar` markup so base_sidebar.js drives collapse,
   active state and the mobile drawer. base_sidebar.css styles it as a floating
   dashboard panel; this scope flattens it into the docs column, exactly the way
   base_sidebar_userpanel.css skins the same component for the user panel. */

.docs-page .base-sidebar--docs {
  position: static;
  width: 100%;
  height: auto;
  max-height: none;
  min-height: 0;
  margin: 0;
  padding: 0;
  background: none;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  backdrop-filter: none;
  transform: none;
  visibility: visible;
  pointer-events: auto;
  opacity: 1;
}

.docs-page .base-sidebar--docs .base-sidebar__content {
  padding: 0;
  overflow: visible;
}

.docs-page .base-sidebar--docs .base-sidebar__menu {
  gap: 1px;
  padding: 0;
  margin: 0;
}

/* Rows: quieter and denser than the dashboard default 44px pill. */
.docs-page .base-sidebar--docs .base-sidebar__item-link,
.docs-page .base-sidebar--docs .base-sidebar__item-toggle {
  min-height: 0 !important;
  padding: 7px 10px !important;
  border-radius: 8px !important;
  border: 1px solid transparent !important;
  background: none !important;
  box-shadow: none !important;
  transform: none !important;
  font-family: inherit !important;
  font-size: 14px !important;
  font-weight: 500 !important;
  color: var(--muted-text) !important;
}

/* A top-level row is a category, so it reads as a heading. */
.docs-page
  .base-sidebar--docs
  > .base-sidebar__content
  > .base-sidebar__menu
  > .base-sidebar__item
  > .base-sidebar__item-toggle {
  font-weight: 700 !important;
  color: var(--text-color) !important;
}

.docs-page .base-sidebar--docs .base-sidebar__item-link:not(.active):hover,
.docs-page .base-sidebar--docs .base-sidebar__item-toggle:not(.active):hover {
  background: var(--docs-row-hover) !important;
  border-color: transparent !important;
  color: var(--text-color) !important;
}

/* Rest and hover are declared TOGETHER. Declaring them apart is what broke this
   twice: base_sidebar.css hovers every row with !important on background, border
   AND colour, so any property the active rule leaves out gets repainted and the
   row appears to lose its state under the cursor. */
/* Only the PAGE gets the active treatment. A category that merely contains the
   current page is not itself a destination, and giving it the same filled frame
   made two rows compete for "you are here". Its open state is the chevron. */
.docs-page .base-sidebar--docs .base-sidebar__item-link.active,
.docs-page .base-sidebar--docs .base-sidebar__item-link.active:hover {
  background: var(--docs-accent-soft) !important;
  border-color: var(--docs-accent-line) !important;
  color: var(--text-color) !important;
  font-weight: 600 !important;
  box-shadow: none !important;
  transform: none !important;
}

/* The open category keeps the plain category look, and hovers like any other. */
.docs-page .base-sidebar--docs .base-sidebar__item-toggle.active {
  background: none !important;
  border-color: transparent !important;
  box-shadow: none !important;
  transform: none !important;
}

.docs-page .base-sidebar--docs .base-sidebar__item-toggle.active:hover {
  background: var(--docs-row-hover) !important;
  border-color: transparent !important;
  color: var(--text-color) !important;
  box-shadow: none !important;
  transform: none !important;
}

/* No rail and no glow ring: the base component's ::before is switched off on
   both rows. The active page is marked by its tinted frame alone - a rail on
   top of the frame is the same fact said twice, and the heavier of the two. */
.docs-page .base-sidebar--docs .base-sidebar__item-toggle.active::before,
.docs-page .base-sidebar--docs .base-sidebar__item-link.active::before {
  display: none !important;
}

/* The base component sets outline:none on its rows and never restores a ring. */
.docs-page .base-sidebar--docs .base-sidebar__item-link:focus-visible,
.docs-page .base-sidebar--docs .base-sidebar__item-toggle:focus-visible {
  outline: 2px solid var(--docs-focus) !important;
  outline-offset: 2px;
}

/* Indent guide on nested levels. */
.docs-page .base-sidebar--docs .base-sidebar__submenu {
  margin-left: 14px;
  padding-left: 8px;
  border-left: 1px solid var(--docs-rail);
}

.docs-page
  .base-sidebar--docs
  .base-sidebar__item-link:hover
  .base-sidebar__item-icon,
.docs-page
  .base-sidebar--docs
  .base-sidebar__item-toggle:hover
  .base-sidebar__item-icon {
  color: inherit !important;
}

.docs-page .base-sidebar--docs .base-sidebar__item-chevron {
  margin-left: auto;
  font-size: 10px;
  opacity: 0.7;
}

/* ---------- Main content ---------- */
.docs-content {
  min-width: 0;
  /* The trailing space is deliberate and generous: a short final section can then
     still be scrolled up to the top of the viewport, which is what lets it become
     the current entry in the TOC and what makes an anchor jump to the last heading
     actually land on it. */
  padding: 40px 56px min(40vh, 420px);
  max-width: 860px;
  margin: 0 auto;
}
.docs-content > :first-child {
  margin-top: 0;
}
.docs-content h1 {
  font-size: clamp(28px, 3.4vw, 38px);
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--heading-color);
  margin: 0 0 14px;
}
.docs-content h2 {
  font-size: 23px;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--heading-color);
  margin: 44px 0 14px;
  padding-top: 8px;
  scroll-margin-top: calc(var(--docs-topbar-h) + 16px);
}
.docs-content h3 {
  font-size: 18px;
  color: var(--heading-color);
  margin: 30px 0 10px;
  scroll-margin-top: calc(var(--docs-topbar-h) + 16px);
}
.docs-content p,
.docs-content li {
  font-size: 15.5px;
  line-height: 1.7;
  color: var(--text-color);
}
.docs-content p {
  margin: 0 0 16px;
}
.docs-content ul,
.docs-content ol {
  margin: 0 0 16px;
  padding-left: 22px;
}
.docs-content li {
  margin: 4px 0;
}
/* Tab sets in a docs page: the list rules above would indent the tab bar. */
.docs-content .tab-nav {
  margin: 0;
  padding: 0;
}
.docs-content .tab-nav li {
  margin: 0;
}
.docs-content a {
  color: var(--link, var(--docs-accent));
  text-decoration: underline;
  text-underline-offset: 2px;
  border: 0;
}
.docs-content a:hover {
  color: var(--docs-accent);
}
.docs-content code {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: 0.88em;
  background: color-mix(in srgb, var(--text-color) 8%, transparent);
  border: 1px solid var(--docs-rail);
  border-radius: 5px;
  padding: 1px 6px;
}
.docs-content pre code {
  background: none;
  border: 0;
  padding: 0;
}
.docs-content table {
  width: 100%;
  border-collapse: collapse;
  margin: 0 0 18px;
  font-size: 14.5px;
}
/* A wide table scrolls inside its own box rather than widening the whole page.
   The wrapper is added by base_docs.js, since markdown emits a bare <table>. */
.docs-table-wrap {
  overflow-x: auto;
  margin: 0 0 18px;
  -webkit-overflow-scrolling: touch;
}
.docs-table-wrap > table {
  margin: 0;
}
.docs-content th,
.docs-content td {
  text-align: left;
  padding: 9px 12px;
  border: 1px solid var(--docs-rail);
}
.docs-content th {
  background: color-mix(in srgb, var(--text-color) 5%, transparent);
  color: var(--heading-color);
}
.docs-content hr {
  border: 0;
  border-top: 1px solid var(--docs-rail);
  margin: 32px 0;
}

/* Images: screenshots are captured at full device width, so they must scale
   down to the column instead of overflowing it. Click opens the lightbox. */
.docs-content img {
  display: block;
  max-width: 100%;
  height: auto;
  margin: 0 0 18px;
  border: 1px solid var(--docs-rail);
  border-radius: 10px;
  cursor: zoom-in;
}
/* An image that is its own link keeps the link behaviour. */
.docs-content a > img {
  cursor: pointer;
}

/* Lightbox (element built by base_docs.js) */
.docs-lightbox {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(0, 0, 0, 0.82);
  cursor: zoom-out;
}
.docs-lightbox.is-open {
  display: flex;
}
.docs-lightbox__img {
  max-width: 96vw;
  max-height: 92vh;
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: 8px;
  background: var(--card-bg);
  box-shadow: 0 18px 60px rgba(0, 0, 0, 0.5);
}
.docs-lightbox__close {
  position: absolute;
  top: 16px;
  right: 20px;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 26px;
  line-height: 1;
  color: #fff;
  background: rgba(255, 255, 255, 0.14);
  border: 0;
  border-radius: 50%;
  cursor: pointer;
}
.docs-lightbox__close:hover {
  background: rgba(255, 255, 255, 0.26);
}
/* Stops the page behind the overlay from scrolling. */
body.docs-lightbox-open {
  overflow: hidden;
}
@media (max-width: 860px) {
  .docs-lightbox {
    padding: 12px;
  }
}

/* heading anchor link (added by JS) */
.docs-content .docs-anchor {
  opacity: 0;
  margin-left: 8px;
  color: var(--muted-text);
  text-decoration: none;
  font-weight: 400;
  border: 0;
}
.docs-content h2:hover .docs-anchor,
.docs-content h3:hover .docs-anchor {
  opacity: 1;
}

/* callout / caution boxes */
.docs-callout,
.docs-caution {
  margin: 20px 0;
  padding: 14px 16px;
  border-radius: 12px;
  border: 1px solid var(--docs-rail);
  background: var(--card-bg);
  font-size: 14.5px;
}
.docs-callout {
  border-color: color-mix(in srgb, var(--docs-accent) 35%, var(--docs-rail));
  background: color-mix(in srgb, var(--docs-accent) 7%, transparent);
}
.docs-caution {
  border-color: color-mix(in srgb, #e0a035 45%, transparent);
  background: color-mix(in srgb, #e0a035 9%, transparent);
}
.docs-callout__title,
.docs-caution__title {
  display: block;
  font-weight: 700;
  color: var(--heading-color);
  margin-bottom: 4px;
}

/* ---------- Right "On this page" TOC ---------- */
.docs-toc {
  position: sticky;
  top: var(--docs-topbar-h);
  align-self: start;
  height: calc(100vh - var(--docs-topbar-h));
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 40px 24px 40px 4px;
}
.docs-toc__title {
  margin: 0 0 12px;
  /* Inherit, so the project's own font applies. This was monospace, uppercase and
     letter-spaced, which read as system chrome rather than as part of the site. */
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--text-color);
}
.docs-toc__list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
/* Plain links, no pill and no rail: the active section is marked by colour and
   weight alone, which keeps the column quiet beside the article. */
.docs-toc__link {
  display: block;
  padding: 5px 0;
  border: 0;
  font-family: inherit;
  font-size: 13px;
  line-height: 1.45;
  color: var(--muted-text);
  text-decoration: none;
  border-top: 0;
  border-right: 0;
  border-bottom: 0;
  transition:
    color 0.15s ease,
    border-color 0.15s ease;
}
.docs-toc__link--h3 {
  padding-left: 22px;
  font-size: 12.5px;
}
.docs-toc__link:hover {
  color: var(--text-color);
}
.docs-toc__link.is-active {
  color: var(--docs-accent);
  font-weight: 600;
}

/* ---------- Page notices (draft / untranslated banners) ---------- */
.docs-notice {
  margin: 0 0 20px;
  padding: 10px 14px;
  border-radius: 8px;
  border: 1px solid var(--docs-rail);
  background: var(--container-bg);
  color: var(--muted-text);
  font-size: 14px;
}
.docs-notice--draft {
  border-style: dashed;
}

/* ---------- Pjax (client-side doc swap) transition ---------- */
.docs-content {
  transition: opacity 0.12s ease;
}
.docs-loading .docs-content {
  opacity: 0.45;
}

/* ---------- Responsive ---------- */
@media (max-width: 1180px) {
  .docs-shell {
    grid-template-columns: var(--docs-sidebar-w) minmax(0, 1fr);
  }
  .docs-toc {
    display: none;
  }
}
@media (max-width: 860px) {
  .docs-topbar {
    display: flex;
    gap: 12px;
  }
  .docs-shell {
    grid-template-columns: 1fr;
  }
  .docs-nav-toggle {
    display: inline-flex;
    order: -1;
  }
  .docs-logo {
    width: auto;
  }
  .docs-topbar__search {
    flex: 1 1 auto;
    justify-self: auto;
    max-width: none;
  }
  .docs-search-kbd {
    position: absolute;
    top: 50%;
    right: 10px;
    transform: translateY(-50%);
    padding: 2px 6px;
    border-radius: 6px;
    border: 1px solid var(--docs-rail);
    background: color-mix(in oklch, var(--text-color) 6%, transparent);
    font-family: var(--font-mono, ui-monospace, monospace);
    font-size: 11px;
    line-height: 1.5;
    color: var(--muted-text);
    pointer-events: none;
  }

  /* Room for the hint so a long placeholder never runs under it. */
  .docs-topbar__search .search-field__input {
    padding-right: 52px;
  }

  .docs-topbar__actions {
    justify-self: auto;
  }
  .docs-search-kbd {
    display: none;
  }
  .docs-sidebar {
    position: fixed;
    top: var(--docs-topbar-h);
    left: 0;
    width: min(320px, 84vw);
    background: var(--container-bg);
    border-right: 1px solid var(--docs-rail);
    transform: translateX(-100%);
    transition: transform 0.22s ease;
    z-index: 90;
    box-shadow: var(--shadow-elev);
  }
  .docs-sidebar.is-open {
    transform: translateX(0);
  }
  .docs-content {
    padding: 28px 20px 80px;
  }
}
