/* ==========================================================================
   Design Tokens
   ========================================================================== */

:root {
  /* Brand */
  --primary: oklch(0.5424 0.1883 258.91);
  --primary-hover: oklch(0.45 0.18 258.91);
  --ring-focus: oklch(0.5424 0.1883 258.91 / 0.35);   /* focus glow */

  /* Surfaces (hub-aligned: stone-tinted, low-contrast) */
  --bg: oklch(0.98 0 0);
  --bg-subtle: oklch(0.97 0.001 106.424);   /* hub --muted */
  --bg-hover: oklch(0.955 0.001 106.424);
  --card: oklch(1 0 0);                       /* hub --card */
  --nav-bg: oklch(0.98 0 0);
  --nav-text: oklch(0.147 0.004 49.25);

  /* Text */
  --text: oklch(0.147 0.004 49.25);           /* hub --foreground */
  --text-muted: oklch(0.553 0.013 58.071);    /* hub --muted-foreground */

  /* Borders (hub-aligned: subtle, no pure black) */
  --border: oklch(0.923 0.003 48.717);        /* hub --border */
  --border-strong: oklch(0.86 0.004 49);
  --ring: oklch(0.709 0.01 56.259);           /* hub --ring */

  /* Accents (kept dark for ::selection contrast) */
  --accent-bg: oklch(0.147 0.004 49.25);
  --accent-text: oklch(0.985 0 0);

  /* Callout tints (subtle primary-derived surfaces).
     Mix in oklab (not oklch) — mixing a chromatic hue with a near-neutral
     in oklch interpolates hue the wrong way round the wheel (blue → pink). */
  --surface-primary: color-mix(in oklab, var(--primary) 8%, var(--card));
  --surface-primary-border: color-mix(in oklab, var(--primary) 30%, var(--border));

  /* Inline code: higher-contrast surface + text than body muted grey */
  --code-bg: oklch(0.945 0.008 265);
  --code-text: oklch(0.40 0.14 265);          /* readable blue-slate on light */
  --code-border: oklch(0.89 0.01 265);

  /* Search / in-page match highlight (soft amber, not neon) */
  --highlight-bg: oklch(0.9 0.11 92);
  --highlight-text: oklch(0.32 0.06 79);

  /* Typography */
  --font-body:
    -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu",
    "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
  --font-heading:
    -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu",
    "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
  --font-mono:
    source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
  /* Topbar wordmark only (loaded in layout.html); falls back to the body stack */
  --font-brand: "DM Sans", var(--font-body);

  /* Layout */
  --content-padding: 30px;
  /* Max width for the content column on wide→very-wide screens; the column is
     capped at this and anchored left (see the min-width:1441px rule). Only set
     in the large-desktop / ultra-wide breakpoints — unused below 1441px. */
  --content-measure: 82rem;
  /* Matches the hub's `SIDEBAR_WIDTH = "16rem"` (sidebar.tsx). Fixed rather
     than scaled per breakpoint: the hub's sidebar is one width at every
     desktop size, and a nav column that grows to 360px on a wide screen reads
     as a different component from the app's. Extra viewport goes to content. */
  --sidebar-width: 16rem; /* 256px — hub SIDEBAR_WIDTH */
  /* Hub SIDEBAR_WIDTH_MOBILE = "18rem"; used by the drawer below. */
  --sidebar-width-mobile: 18rem; /* 288px */
  /* Reading measure is enforced on div.body via --content-measure, not here. */
  --content-max-width: 100%;
  /* Radius scale (hub --radius: 0.625rem) */
  --radius: 0.625rem;
  --radius-sm: calc(var(--radius) - 4px);   /* 6px */
  --radius-md: calc(var(--radius) - 2px);   /* 8px */
  --radius-lg: var(--radius);               /* 10px */

    /* Top bar */
    --topbar-height: 48px;
    --topbar-z: 100;
    --drawer-width: var(--sidebar-width-mobile);
    --drawer-z: 90;
    --backdrop-z: 80;
    /* Above the topbar: the image preview is a modal and must cover the whole
       chrome, including the theme and sidebar buttons. */
    --lightbox-z: 200;
}

.dark-mode,
html.dark-mode-pre {
  --primary: oklch(0.7 0.15 258.91);
  --primary-hover: oklch(0.8 0.12 258.91);
  --ring-focus: oklch(0.7 0.15 258.91 / 0.4);

  --bg: oklch(0.147 0.004 49.25);             /* hub dark --background */
  --bg-subtle: oklch(0.216 0.006 56.043);     /* hub dark --card */
  --bg-hover: oklch(0.25 0.006 56);
  --card: oklch(0.216 0.006 56.043);
  --nav-bg: oklch(0.147 0.004 49.25);
  --nav-text: oklch(0.985 0.001 106.423);

  --text: oklch(0.985 0.001 106.423);         /* hub dark --foreground */
  --text-muted: oklch(0.709 0.01 56.259);     /* hub dark --muted-foreground */

  --border: oklch(1 0 0 / 10%);               /* hub dark --border */
  --border-strong: oklch(1 0 0 / 22%);
  --ring: oklch(0.553 0.013 58.071);

  --accent-bg: oklch(0.985 0.001 106.423);
  --accent-text: oklch(0.147 0.004 49.25);

  --surface-primary: color-mix(in oklab, var(--primary) 14%, var(--card));
  --surface-primary-border: color-mix(in oklab, var(--primary) 40%, var(--border));

  /* Inline code: brighter text + slightly lifted surface for contrast */
  --code-bg: oklch(0.27 0.02 265);
  --code-text: oklch(0.86 0.11 255);          /* light blue on dark */
  --code-border: oklch(1 0 0 / 12%);

  /* Search / in-page match highlight (deeper amber for dark bg) */
  --highlight-bg: oklch(0.62 0.12 84);
  --highlight-text: oklch(0.16 0.02 79);
}

/* ==========================================================================
   Base & Typography
   ========================================================================== */

html {
  scroll-behavior: smooth;
  /* Clear the fixed topbar (--topbar-height) plus a little breathing room, so
     an anchored heading — e.g. a jump from the "On this page" panel — lands
     just below the bar instead of hidden behind it. At 20px the target sat
     under the 48px topbar, so second-level toc jumps looked like they did
     nothing. */
  scroll-padding-top: calc(var(--topbar-height) + 16px);
}

body {
  margin: 0;
  padding: 0;
  font-family: var(--font-body);
  font-size: clamp(15px, 0.5vw + 14px, 17px);
  line-height: 1.6;
  background-color: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

p {
  margin: 0 0 1em 0;
}

/* Alabaster sets `div.body p, div.body dd, div.body li { line-height: 1.4em }`,
   which out-specifies the 1.6 on <body> above. Line blocks (`| foo`) aren't in
   that selector list, so they kept inheriting 1.6 and sat a visible 3.4px per
   line looser than the surrounding prose. Restate the theme's own leading at
   matching specificity so every block of body copy agrees. */
div.body p,
div.body dd,
div.body li,
div.body .line-block .line {
  line-height: 1.6;
}

/* A line block is a paragraph-like run of hard-wrapped lines, so give it the
   same vertical rhythm as <p> rather than basic.css's symmetric 1em/1em. */
div.body .line-block {
  margin: 0 0 1em 0;
}

::selection {
  background-color: var(--accent-bg);
  color: var(--accent-text);
}

/* ==========================================================================
   Layout — Sidebar & Content Widths
   ========================================================================== */

/* Alabaster / classic Sphinx layout */
div.document {
  max-width: none;
  width: 100%;
  /* Alabaster puts a 30px top margin here, which lands between the fixed
     topbar and the first relbar as dead space. The body already reserves room
     for the fixed topbar, so only a small gap is wanted. */
  margin-top: 8px;
}

div.documentwrapper {
  float: left;
  width: 100%;
}

div.bodywrapper {
  margin: 0 0 0 var(--sidebar-width);
}

div.sphinxsidebar {
  width: var(--sidebar-width);
}

div.sphinxsidebarwrapper {
  width: var(--sidebar-width);
  padding: 20px;
  box-sizing: border-box;
}

div.body {
  max-width: var(--content-max-width);
}

/* Align the footer under the content column for every builder — alabaster
   centres its fixed-width footer, which ignores the sidebar. */
div.footer {
  width: auto;
  margin: 1.25rem 0 0 var(--sidebar-width);
  padding: 0 var(--content-padding) 1.5rem;
  text-align: left;
  color: var(--text-muted);
}

/* singlehtml drops the relbars, so add a divider + spacing in the footer. */
body.gs-singlehtml div.footer {
  margin-top: 3rem;
  padding: 1.5rem var(--content-padding) 1.5rem;
  border-top: 1px solid var(--border);
}

/* RTD theme layout (in case theme switches) */
.wy-nav-side {
  width: var(--sidebar-width);
}

.wy-side-scroll {
  width: calc(var(--sidebar-width) + 20px);
}

.wy-nav-content-wrap {
  margin-left: var(--sidebar-width);
}

.wy-nav-content {
  max-width: var(--content-max-width);
}

/* ==========================================================================
   Links
   ========================================================================== */

a {
  color: var(--primary);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
}

a:hover {
  color: var(--primary-hover);
  text-decoration-thickness: 2px;
}

/* In-content links: cleaner shadcn treatment — colored, underline on hover */
div.body a {
  text-decoration: none;
  text-decoration-color: color-mix(in oklch, var(--primary) 40%, transparent);
}

div.body a:hover {
  text-decoration: underline;
  text-decoration-thickness: 1px;
}

a:visited {
  color: var(--primary);
}

a:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* ==========================================================================
   Body Content
   ========================================================================== */

div.body {
  background-color: var(--bg);
  color: var(--text);
  padding-block: 0;
  padding-inline: var(--content-padding);
  /* On wide→very-wide screens the column is capped at --content-measure and kept
     anchored left (surplus becomes right-hand margin, not centred). See the
     min-width:1441px rule below. Below that it fills the available width. */
}

div.body img {
  max-width: 100%;
  height: auto;
}

/* Centre images that carry no explicit alignment — bare `.. image::` images
   and graphviz diagrams. Author-set :align: left/right/center get docutils'
   own alignment classes and are deliberately left untouched. */
div.body img:not(.align-left):not(.align-right):not(.align-center) {
  display: block;
  margin-inline: auto;
}

/* Un-sized images ballooned once the content area widened (the old narrow
   layout capped them implicitly by column width). Cap the height only when no
   dimensions were specified — no width/height attribute and no inline style.
   Readers can click to zoom via the image preview. Graphviz diagrams are
   excluded; they size to their own rendered content. */
div.body img:not([width]):not([height]):not([style]):not(.graphviz) {
  max-height: 480px;
  width: auto;
}

/* Tables: centre everything except author-set align-left/right. This must be
   stated here (not left to docutils' own `table.align-center { margin: auto }`)
   because geoscape.js wraps every table in `.gs-table-wrap`, and
   `.gs-table-wrap > table.docutils { margin: 0 }` out-specifies docutils' rule
   and would otherwise pin even align-center tables to the left.
   Centre the caption (the table's "header" title) to match the centred table. */
div.body table.docutils.align-default,
div.body table.docutils.align-center,
div.body table.docutils:not(.align-left):not(.align-right):not(.align-center) {
  margin-inline: auto;
}
div.body table.docutils.align-default > caption,
div.body table.docutils.align-center > caption {
  text-align: center;
}

/* Alabaster's mobile rule (max-width: 875px) zeroes `ul { margin-left }` for
   top-level lists, leaving content bullets flush against the edge with no
   indent. Restore a sensible indent for content lists at narrow widths.
   Scoped to div.body so sidebar/toctree lists are unaffected. */
@media (max-width: 875px) {
  div.body ul,
  div.body ol {
    margin-left: 1.5rem;
  }
}

/* Docutils wraps any indented block (including indented bullet/definition
   lists) in a <blockquote>, and the Geoscape docs use that indentation purely
   for structure — there are no prose "quotes". So render blockquotes as plain
   indented body text: no left rule, no muted colour, no italic. This keeps
   indented lists visually identical to normal lists and matches the previous
   (alabaster) indent-only behaviour. */
blockquote {
  margin: 1em 0;
  padding-left: 1.5em;
}

/* Table-of-contents / topic boxes (e.g. page contents directive):
   soft card instead of a hard black-bordered box. */
div.topic,
nav.contents,
div.contents {
  background-color: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 14px 18px;
  margin: 1.5em 0;
}

div.topic p.topic-title,
nav.contents p.topic-title,
div.contents p.topic-title {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 0 0 0.5rem 0;
}

/* ==========================================================================
   Headings
   ========================================================================== */

div.body h1,
div.body h2,
div.body h3,
div.body h4,
div.body h5,
div.body h6 {
  font-family: var(--font-heading);
  font-weight: 600;
  margin: 2em 0 0.5em 0;
  padding: 0;
  line-height: 1.25;
}

/* Heading scale is deliberately flatter than a typical docs theme. The hub's
   largest routine heading is `text-2xl` (24px) — `text-xl`/`text-2xl` appear 18
   times across its pages against 463 uses of `text-xs` — so a 220% h1 (46.8px
   at the 18px body size) towered over both the app and the 12–13px sidebar
   beside it. Sized in rem, not %, so the steps don't compound with the
   viewport-scaled body font. */
div.body h1 {
  margin-top: 0;
  padding-top: 0;
  font-size: 1.75rem; /* 28px */
  font-weight: 700;
  letter-spacing: -0.02em;
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.3em;
}

div.body h2 {
  font-size: 1.375rem; /* 22px */
  letter-spacing: -0.015em;
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.2em;
}

div.body h3 {
  font-size: 1.125rem; /* 18px */
}
div.body h4 {
  font-size: 1rem; /* 16px */
}
div.body h5 {
  font-size: 0.9375rem; /* 15px */
}
div.body h6 {
  font-size: 0.9375rem;
}

/* Heading text is wrapped in <a class="toc-backref"> (a link back to the
   page ToC). Don't paint it like a body link — it should read as a heading. */
div.body h1 .toc-backref,
div.body h2 .toc-backref,
div.body h3 .toc-backref,
div.body h4 .toc-backref,
div.body h5 .toc-backref,
div.body h6 .toc-backref {
  color: inherit;
  text-decoration: none;
}

/* The ¶ anchor permalink: hidden until the heading is hovered. Sized to match
   the heading text and never styled as a hyperlink (no underline, ever). */
a.headerlink {
  font-size: inherit;
  font-weight: inherit;
  color: var(--text-muted);
  opacity: 0;
  margin-left: 0.35em;
  text-decoration: none !important;
  transition: opacity 0.12s ease, color 0.12s ease;
}

h1:hover > a.headerlink,
h2:hover > a.headerlink,
h3:hover > a.headerlink,
h4:hover > a.headerlink,
h5:hover > a.headerlink,
h6:hover > a.headerlink,
/* Table captions get a "Link to this table" headerlink too (Sphinx emits one
   for every `.. csv-table:: NAME`). Without this it stayed at opacity 0 and
   the anchor was unreachable by mouse. */
caption:hover > a.headerlink,
a.headerlink:focus-visible {
  opacity: 0.5;
}

a.headerlink:hover {
  color: var(--primary);
  opacity: 1;
}

/* ==========================================================================
   Sidebar / Nav
   ========================================================================== */

div.sphinxsidebar {
  overflow-y: auto;
  max-height: 100vh;
  background-color: var(--nav-bg);
  color: var(--nav-text);
}

div.sphinxsidebar h3,
div.sphinxsidebar h4 {
  font-family: var(--font-heading);
  color: var(--nav-text);
  font-size: 24px;
  font-weight: 600;
  margin: 0 0 5px 0;
  padding: 0;
}

div.sphinxsidebar p,
div.sphinxsidebar ul,
div.sphinxsidebar li,
div.sphinxsidebar a {
  color: var(--nav-text);
}

div.sphinxsidebar a {
  text-decoration: none;
}

div.sphinxsidebar a:hover {
  color: var(--primary);
  text-decoration: underline;
}

div.sphinxsidebar input {
  border: 1px solid var(--border);
  background-color: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 1em;
  padding: 4px 6px;
  max-width: 100%;
  box-sizing: border-box;
}

div.sphinxsidebar a.current {
  font-weight: bold;
  color: var(--primary);
}

/* ==========================================================================
   Navigation tree (custom navigation.html)
   ========================================================================== */

/* Alabaster's site title. At its 28px a long product name ("G-NAF Data Product
   Description") wrapped to four lines in a 256px column and pushed the whole
   toctree below the fold. */
div.sphinxsidebar h1.logo,
div.sphinxsidebar h1.logo a {
  font-size: 1.125rem;
  line-height: 1.3;
  font-weight: 700;
}

/* Drop alabaster's `div.sphinxsidebar a { border-bottom: dotted }`, which draws
   a broken underline across the site title. (The nav links clear it separately
   below.) */
div.sphinxsidebar h1.logo a {
  border-bottom: 0;
}

.gs-nav {
  margin-top: 0.5rem;
}

/* Out-specify alabaster's `div.sphinxsidebar a { border-bottom: dotted }` */
div.sphinxsidebar .gs-nav__global a,
div.sphinxsidebar .gs-nav__local a,
div.sphinxsidebar .gs-nav__extra a {
  border-bottom: 0;
}

.gs-nav__heading {
  font-family: var(--font-heading);
  /* Hub SidebarGroupLabel is `text-xs`; the uppercase tracking below already
     makes it read small, so use the literal 0.75rem rather than under-size it. */
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 0 0 0.5rem 0;
  padding: 0;
}

/* First heading ("Documentation") sits directly under the site title */
.gs-nav > .gs-nav__heading:first-child {
  margin-top: 0;
}

/* Prefixed with div.sphinxsidebar to out-specify alabaster's
   `div.sphinxsidebar p { margin: 10px 0 }`, so this separator matches the
   external-links separator exactly (same margin-top + padding-top). */
div.sphinxsidebar .gs-nav__heading--local {
  margin-top: 1.75rem;
  padding-top: 1rem;
  border-top: 1px solid var(--border);
}

/* Suppress "On this page" unless the current doc has a THIRD heading level.
   The local toc nests as: outer <ul> (page title) > <ul> (1.1, 1.2 …) > <ul>
   (1.1.1 …). The first two levels just restate the sidebar nav, which already
   shows 1.1 under 1 — so the panel only earns its space once a 1.1.1 exists,
   i.e. once a `.gs-nav__local ul ul ul` is present.

   Anchored on the .gs-nav container so both the heading and the toc div are
   hidden by one condition. (A `:not(:has())` on the div itself is fine, but
   hiding the sibling heading the same way would need :has inside :not inside
   :has, which no browser accepts — so drive both from the ancestor.) */
.gs-nav:not(:has(.gs-nav__local ul ul ul)) .gs-nav__heading--local,
.gs-nav:not(:has(.gs-nav__local ul ul ul)) .gs-nav__local {
  display: none;
}

/* Reset Sphinx's default toctree list chrome.
   Alabaster sets list-style:square on nested ul AND li, so reset both. */
.gs-nav__global ul,
.gs-nav__local ul,
.gs-nav__global li,
.gs-nav__local li {
  list-style: none !important;
  margin: 0;
  padding: 0;
}

.gs-nav__global li,
.gs-nav__local li {
  display: block;
}

/* Links render as full-width rows with a hover/active pill.
   Alabaster adds a dotted border-bottom to sidebar links — remove it. */
.gs-nav__global a,
.gs-nav__local a {
  display: block;
  padding: 0.3rem 0.6rem;
  border-radius: var(--radius-md);
  text-decoration: none;
  color: var(--nav-text);
  line-height: 1.35;
  transition: background-color 0.12s ease, color 0.12s ease;
}

.gs-nav__global a:hover,
.gs-nav__local a:hover {
  background-color: var(--bg-hover);
  color: var(--text);
  text-decoration: none;
}

/* Sphinx injects a <p class="caption">Contents</p> that duplicates our
   own "Documentation" heading — hide it. */
.gs-nav__global .caption {
  display: none;
}

/* Top-level entries read as section groups: slightly larger, weightier,
   with breathing room above each group.
   Match direct-child <li> regardless of class — Sphinx drops the
   `toctree-l1` class from the current page's entry on some pages (e.g. the
   bibliography/References page), which otherwise leaves it undersized. */
/* Out-specify alabaster's `div.sphinxsidebar ul li.toctree-l1 > a {120%}`
   so ALL top-level links match — including the current page's entry, which
   Sphinx emits without the toctree-l1 class (e.g. References). */
/* The hub sets one size for every menu row (`text-xs`, 12px) and separates
   levels by weight and indent alone. A docs toctree is deeper than an app nav,
   though, so keep a small step down per level for scannability — but start
   from the hub's 0.8125rem (13px) rather than the old 1rem, which made the
   nav column read a full size larger than the app's. */
div.sphinxsidebar .gs-nav__global > div > ul > li > a,
div.sphinxsidebar .gs-nav__global > ul > li > a {
  font-weight: 600;
  font-size: 0.8125rem;
  margin-top: 0.35rem;
}

.gs-nav__global > div > ul > li + li,
.gs-nav__global > ul > li + li {
  margin-top: 0.15rem;
}

/* Nesting indentation per level */
/* Sized in rem, not em, and prefixed with div.sphinxsidebar: alabaster's
   `div.sphinxsidebar ul li.toctree-l2 > a { font-size: 110% }` out-specifies a
   bare `.gs-nav__global .toctree-l2 a`, so nested entries rendered *larger*
   than their l1 parent. 0.75rem is the hub's `text-xs`. */
div.sphinxsidebar .gs-nav__global .toctree-l2 a { padding-left: 1.4rem; font-size: 0.75rem; font-weight: 400; }
div.sphinxsidebar .gs-nav__global .toctree-l3 a { padding-left: 2.2rem; font-size: 0.75rem; }
div.sphinxsidebar .gs-nav__global .toctree-l4 a { padding-left: 3.0rem; font-size: 0.75rem; }

/* Nested groups sit tight under their parent, with a subtle guide line */
.gs-nav__global li.toctree-l1 > ul,
.gs-nav__global li.toctree-l2 > ul {
  margin-left: 0.7rem;
  border-left: 1px solid var(--border);
}

/* Active page: filled pill + left accent bar */
.gs-nav__global a.current,
.gs-nav__global li.current > a {
  color: var(--primary);
  font-weight: 600;
}

.gs-nav__global li.current.toctree-l1 > a,
.gs-nav__global a.current {
  background-color: color-mix(in oklch, var(--primary) 12%, transparent);
}

/* Current-branch section headers stay readable but not fully highlighted */
.gs-nav__global li.current > a {
  background-color: color-mix(in oklch, var(--primary) 6%, transparent);
}

/* Local "On this page" toc: lighter weight, thin marker */
.gs-nav__local {
  font-size: 0.75rem; /* hub text-xs */
}

.gs-nav__local a {
  color: var(--text-muted);
  border-left: 2px solid transparent;
  border-radius: 0;
  padding-left: 0.6rem;
}

.gs-nav__local a:hover {
  background-color: transparent;
  color: var(--text);
  border-left-color: var(--border-strong);
}

.gs-nav__local li.current > a,
.gs-nav__local a.current {
  color: var(--primary);
  border-left-color: var(--primary);
  background-color: transparent;
}

/* Multi-doc singlehtml: scopeLocalToc (geoscape.js) tags the in-view chapter
   `gs-toc-active`; show only it, dropping its title (repeats the on-screen
   heading) and surfacing its sections. no-JS builds keep the full list. */
.gs-nav__local.gs-local-scoped > ul > li { display: none; }
.gs-nav__local.gs-local-scoped > ul > li.gs-toc-active { display: block; }
.gs-nav__local.gs-local-scoped > ul > li.gs-toc-active > a { display: none; }
.gs-nav__local.gs-local-scoped > ul > li.gs-toc-active > ul {
  margin-left: 0;
  border-left: 0;
}

/* Section-less chapter: hide heading + panel rather than show a bare heading. */
.gs-nav.gs-local-empty .gs-nav__heading--local,
.gs-nav.gs-local-empty .gs-nav__local {
  display: none;
}

/* External links list. No "Links" heading — a top border + spacing
   separates it from the nav above, matching the "On this page" separator
   (1.75rem margin-top + 1rem padding-top). Out-specify alabaster's
   `div.sphinxsidebar ul { margin: 10px 0 }`. */
div.sphinxsidebar .gs-nav__extra {
  list-style: none;
  margin: 1.75rem 0 0 0;
  padding: 1rem 0 0 0;
  border-top: 1px solid var(--border);
}

.gs-nav__extra li {
  margin: 0;
}

.gs-nav__extra a {
  display: flex;
  align-items: center;
  gap: 0.55em;
  /* Same 0.8125rem as a top-level toctree entry — these are peer nav rows, and
     at the sidebar's inherited 14px they sat a step larger than the tree. */
  font-size: 0.8125rem;
  padding: 0.3rem 0.6rem;
  color: var(--nav-text);
  text-decoration: none;
  border-radius: var(--radius-md);
  transition: color 0.12s ease, background-color 0.12s ease;
}

.gs-nav__extra a:hover {
  background-color: var(--bg-hover);
  color: var(--primary);
}

/* Label stays on one line; the icon never shrinks or wraps under it */
.gs-nav__extra-label {
  white-space: nowrap;
}

/* Leading icon: muted by default, inherits link colour on hover */
.gs-nav__icon {
  flex: 0 0 auto;
  color: var(--text-muted);
  transition: color 0.12s ease;
}

.gs-nav__extra a:hover .gs-nav__icon {
  color: var(--primary);
}

/* ==========================================================================
   Quick Search
   ========================================================================== */

/* Own section, divided from the links above (matches other separators) */
div.sphinxsidebar .gs-search-section {
  display: block;
  margin-top: 0;
  margin-bottom: 1.25rem;
}

/* Docs-home landing page: about.html suppresses the sidebar title, so the search
   box becomes the FIRST sidebar element and alabaster's `#searchbox { margin:
   1em 0 }` leaves it floating well below the content's relbar header. Pull it up
   so its top lines up with that relbar. Both the sidebar (fixed, top:48px) and
   the relbar are anchored to the same topbar bottom; the relbar clears it by 8px
   while the search box otherwise clears it by ~30px (20px wrapper padding + a
   ~10px intrinsic offset), so a -22px top margin aligns the two. The
   `:first-child` guard confines this to the landing page (docs_geoscape) — every
   other page keeps the title above the search, so its search is never the first
   child. Specificity (1,1,1) intentionally beats alabaster's `#searchbox` rule. */
div.sphinxsidebar #searchbox:first-child {
  margin-top: -22px;
}

/* Sphinx injects `<p class="highlight-link"><a>Hide Search Matches</a></p>`
   INSIDE the search box after a search. It's left in normal flow so it can
   never overlap the "DOCUMENTATION" caption below — an earlier version pulled
   it out of flow into a fixed reserved margin, but any taller line or different
   font metrics (as on Read the Docs) tipped it onto the caption. The link only
   appears on a fresh page load after a search, so it re-flows the nav on load
   rather than causing a mid-view jump. */
div.sphinxsidebar .gs-search-section .highlight-link {
  margin: 0.5rem 0 0 0;
  padding: 0;
  font-size: 0.78rem;
  line-height: 1.2;
}

div.sphinxsidebar .gs-search-section .highlight-link a {
  color: var(--text-muted);
}

/* Input + button form one connected control (button attached flush right) */
.gs-search {
  display: flex;
  align-items: stretch;
  gap: 0;
}

/* Out-specify alabaster's `div.sphinxsidebar input { ... }` */
div.sphinxsidebar .gs-search input[type="text"] {
  flex: 1 1 auto;
  min-width: 0;
  box-sizing: border-box;
  padding: 0.5rem 0.65rem !important;
  font-family: var(--font-body);
  font-size: 0.9rem;
  color: var(--text);
  background-color: var(--card);
  border: 1px solid var(--border);
  border-right: 0;
  border-radius: var(--radius-md) 0 0 var(--radius-md);   /* left corners only */
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

/* Placeholder replaces the old "SEARCH" heading — muted so it reads as a hint,
   not entered text. Needs the sphinxsidebar prefix to beat alabaster's input
   colour, and the vendor selectors can't be combined (an unknown one voids the
   whole list). */
div.sphinxsidebar .gs-search input[type="text"]::placeholder {
  color: var(--text-muted);
  opacity: 1;   /* Firefox dims placeholders by default; undo it. */
}

div.sphinxsidebar .gs-search input[type="text"]:focus,
div.sphinxsidebar .gs-search input[type="text"]:focus-visible {
  outline: none !important;
  border-color: var(--primary) !important;
  z-index: 1;
  position: relative;
  box-shadow: 0 0 0 3px var(--ring-focus) !important;
}

/* Attached icon-only submit button (shadcn primary) */
div.sphinxsidebar .gs-search__submit {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  padding: 0;
  color: var(--text-muted);
  background-color: var(--bg-subtle);
  border: 1px solid var(--border);
  border-left: 0;
  border-radius: 0 var(--radius-md) var(--radius-md) 0;   /* right corners only */
  cursor: pointer;
  transition: background-color 0.12s ease, color 0.12s ease;
}

div.sphinxsidebar .gs-search__submit:hover {
  background-color: var(--bg-hover);
  color: var(--text);
}

div.sphinxsidebar .gs-search__submit:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 2px;
}

/* --- Search results page (search.html) ------------------------------------
   Style the built-in results-page form + result list to match the theme. */
div.body form[action=""] {
  display: flex;
  align-items: stretch;   /* input + button share the same height */
  gap: 0;
  flex-wrap: wrap;
  margin: 1rem 0 1.5rem 0;
}

div.body form[action=""] input[type="text"] {
  flex: 1 1 240px;
  max-width: 360px;
  box-sizing: border-box;
  padding: 0.55rem 0.7rem;
  font-family: var(--font-body);
  font-size: 0.95rem;
  color: var(--text);
  background-color: var(--card);
  border: 1px solid var(--border);
  border-right: 0;
  border-radius: var(--radius-md) 0 0 var(--radius-md);   /* left corners only */
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

div.body form[action=""] input[type="text"]:focus {
  outline: none;
  border-color: var(--primary);
  z-index: 1;
  position: relative;
  box-shadow: 0 0 0 3px var(--ring-focus);
}

/* Submit button attached flush to the input's right edge */
div.body form[action=""] input[type="submit"] {
  padding: 0.55rem 1.1rem;
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--text);
  background-color: var(--bg-subtle);
  border: 1px solid var(--border);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;   /* right corners only */
  cursor: pointer;
  transition: background-color 0.12s ease;
}

div.body form[action=""] input[type="submit"]:hover {
  background-color: var(--bg-hover);
}

/* Keep the "searching…" progress text off the attached button */
div.body form[action=""] #search-progress {
  margin-left: 0.6rem;
}

/* Result list: card-like rows */
ul.search {
  list-style: none;
  margin: 1rem 0 0 0;
  padding: 0;
}

ul.search li {
  margin: 0 0 0.5rem 0;
  padding: 0.85rem 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background-color: var(--card);
  /* basic/alabaster sets a file.png bullet-icon background on each result;
     remove it. */
  background-image: none;
}

ul.search li > a {
  font-weight: 600;
  font-size: 1.02em;
}

ul.search li p.context {
  margin: 0.35rem 0 0 0;
  color: var(--text-muted);
  font-size: 0.9em;
}

/* Search-term highlight (shared with in-page highlighting): soft amber */
.highlighted,
ul.search .highlighted {
  background-color: var(--highlight-bg);
  color: var(--highlight-text);
  border-radius: 3px;
  padding: 0 2px;
  font-weight: 600;
}

/* ==========================================================================
   Code
   ========================================================================== */

pre {
  font-family: var(--font-mono);
  font-size: 0.875em;
  line-height: 1.6;
  background-color: var(--bg-subtle);
  color: var(--text);
  border: 1px solid var(--border);
  padding: 14px 16px;
  overflow-x: auto;
  border-radius: var(--radius-lg);
}

/* .xref suffixes out-specify alabaster's `tt.xref, code.xref, a tt` rules */
code,
tt,
code.xref,
tt.xref,
a code,
a tt {
  font-family: var(--font-mono);
  font-size: 0.875em;
  background-color: var(--code-bg);
  color: var(--code-text);
  padding: 0.15em 0.4em;
  border: 1px solid var(--code-border);
  border-radius: var(--radius-sm);
}

/* Code inside the code block, or inside headings/links, inherits its
   surroundings rather than the inline-code chip styling. */
pre code {
  background: none;
  border: 0;
  padding: 0;
  color: inherit;
}

h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
  color: inherit;
}

/* ==========================================================================
   Tables
   ========================================================================== */

/* Scroll container injected by geoscape.js around every content table.
   Wide reference tables would otherwise overflow the content column and
   force the whole page to scroll sideways. */
/* The wrapper is a pure scroll container with no outline of its own: a
   <caption> is a child of <table> but renders outside the table's box, so a
   border here would enclose the title row too. The border goes on the table
   below, which puts it around the grid only — as in the PDF export. */
.gs-table-wrap {
  position: relative;
  width: 100%;
  max-width: 100%;
  overflow-x: auto;
  margin: 1.5em 0;
}

.gs-table-wrap:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

/* Hint that there is more table off to the side. Only on wrappers that
   actually scroll — see syncScrollability() in geoscape.js. */
.gs-table-wrap[data-scrollable] {
  box-shadow: inset -12px 0 12px -12px oklch(0 0 0 / 0.18);
}

table.docutils {
  border-collapse: separate;
  border-spacing: 0;
  margin: 1.5em 0;
  /* Shrink-to-fit rather than `width: 100%`. Now that the content column fills
     the window, stretching every table to it spread 2- and 3-column tables
     (e.g. abbreviation lists) into vast half-empty rows whose value and label
     sat a screen apart. Auto lets a narrow table stay narrow and a wide one
     still exceed the container — which is what triggers the wrapper's scroll. */
  width: auto;
  /* Outline the grid. Alabaster puts a 1px #888 border plus a
     `box-shadow: 2px 2px 4px #EEE` here; keep the border, drop the shadow. */
  border: 1px solid var(--border);
  box-shadow: none;
  /* Dense reference tables read better a step down from body copy — the hub's
     `<Table>` sets `text-xs` for the same reason. Set on the table so bare
     cell text scales too, not only cells docutils happens to wrap in a <p>
     (it only emits <p> for multi-paragraph cells). */
  font-size: 0.875rem;
}

/* Inside the scroll container the wrapper owns the vertical rhythm. No
   `min-width: 100%` here: that would stretch a 3-column table back to the full
   container and undo the `width: auto` above. */
.gs-table-wrap > table.docutils {
  margin: 0;
}

/* Table captions (`.. csv-table:: NAME`) render as a <caption> inside the
   table. Treated as the table's title row — centred, matching the PDF export,
   and carrying a visible "Link to this table" anchor on hover. */
table.docutils > caption {
  text-align: center;
  padding: 8px 12px;
  font-weight: 600;
  color: var(--text);
}

/* On a table wider than its scroll container the caption would be centred
   over the full table width — i.e. off to the side, or scrolled out of sight
   entirely. Stick it to the container's left edge; geoscape.js sets the width
   to the container's, which CSS can't express here (`width: 100%` on a
   <caption> resolves against the table, not the scroll container). */
.gs-table-wrap > table.docutils > caption {
  position: sticky;
  left: 0;
  box-sizing: border-box;
}

/* Alabaster draws a full 1px #888 grid on `table.docutils td, th`. Reset it
   once here, then re-add only the horizontal rules below — the hub's rows use
   `border-b` and no vertical rules at all. */
table.docutils th,
table.docutils td {
  border: 0;
}

/* Header: the dark inverted bar mirrors the PDF export's `\cellcolor{black}`
   header, so the HTML and PDF renditions of the same appendix stay
   recognisably the same document. */
table.docutils th {
  text-align: left;
  color: var(--accent-text);
  background-color: var(--accent-bg);
  padding: 8px 12px;
}

tr {
  text-align: left;
}

table.docutils td {
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  white-space: normal;
}

/* Row separators only, no vertical rules — the hub uses `border-b` per row
   and drops it on the last one so it doesn't double the container border. */
table.docutils tr:last-child td {
  border-bottom: 0;
}

table.docutils tbody tr:hover td {
  background-color: var(--bg-hover);
}

table.docutils td p,
table.docutils th p {
  font-size: inherit;
  margin: 0;
}

.wy-table-responsive table td,
.wy-table-responsive table th {
  white-space: inherit;
}

/* ==========================================================================
   Footnotes

   docutils 0.18+ emits `<aside class="footnote">` (older versions used a
   <dl>/<table>, which is what alabaster styles). basic.css bridges the gap by
   floating the `<span class="label">` left and indenting the sibling <p>, but
   the float escapes its own <aside> — the next footnote's text starts beside
   the previous label instead of at the margin. Lay each entry out as a flex
   row instead, which keeps the marker on the same line without a float.
   ========================================================================== */

aside.footnote-list {
  margin: 1.5em 0;
}

aside.footnote {
  display: flex;
  gap: 0.5em;
  margin: 0.4em 0;
  font-size: 0.9em;
  color: var(--text-muted);
}

aside.footnote > span.label {
  /* Out-specify basic.css's `aside.footnote > span { float: left }`. */
  float: none;
  flex: none;
  color: var(--text-muted);
}

/* basic.css indents these to clear the float we just removed. */
aside.footnote > p {
  margin-left: 0;
  margin-bottom: 0;
}

/* A footnote sitting directly beneath a centred image reads as that image's
   caption, so centre the entry to line up with the image. The entry is already
   a flex row, so justify-content does it. Scoped to footnotes that immediately
   follow a centred or un-aligned image (align-left/right images keep theirs
   flush), plus a footnote-list that itself carries align-center. */
div.body img.align-center + aside.footnote-list aside.footnote,
div.body img:not(.align-left):not(.align-right):not(.align-center) + aside.footnote-list aside.footnote,
div.body aside.footnote-list.align-center aside.footnote {
  justify-content: center;
}

aside.footnote:target {
  /* basic.css paints a #ffa block highlight; use the theme's own accent so it
     works in dark mode too. */
  background-color: transparent;
  outline: 2px solid var(--primary);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

/* ==========================================================================
   Admonitions
   ========================================================================== */

div.admonition {
  border: 1px solid var(--surface-primary-border);
  border-left: 3px solid var(--primary);
  background-color: var(--surface-primary);
  color: var(--text);
  padding: 14px 16px;
  margin: 20px 0;
  border-radius: var(--radius-lg);
}

div.admonition > .admonition-title {
  background-color: transparent;
  color: var(--primary);
  padding: 0;
  margin: 0;
}

div.admonition p.admonition-title {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 0.95em;
  letter-spacing: 0.01em;
  margin: 0 0 6px 0;
  padding: 0;
  line-height: 1.3;
}

/* Body text sits flush under the title */
div.admonition > p:last-child {
  margin-bottom: 0;
}

div.admonition-standard,
div.admonition-disclaimer {
  display: none;
}

/* ==========================================================================
   Glossary
   ========================================================================== */

dl.glossary {
  margin-left: 30px;
  font-size: 0.9em;
}

dl.glossary dt {
  font-family: var(--font-heading);
  font-weight: 600;
  margin-top: 12px;
}

dl.glossary dd {
  margin-left: 25px;
  margin-bottom: 10px;
}

/* ==========================================================================
   Responsive — Sidebar + Content scale together
   ========================================================================== */

/* Extra small phones (<480px) — sidebar hidden/stacked by theme */
@media (max-width: 480px) {
  :root {
    --content-padding: 12px;
  }

  div.bodywrapper {
    margin-left: 0;
  }

  pre {
    font-size: 0.8em;
    padding: 8px 10px;
  }

  table.docutils {
    font-size: 0.85em;
  }
}

/* Phones / small tablets (481–768px) — sidebar still collapsed by theme */
@media (min-width: 481px) and (max-width: 768px) {
  :root {
    --content-padding: 18px;
  }

  div.bodywrapper {
    margin-left: 0;
  }

  pre {
    font-size: 0.85em;
    padding: 10px 12px;
  }

  table.docutils {
    font-size: 0.9em;
  }
}

/* Tablets (769–1024px) — sidebar reappears, modest widths */
@media (min-width: 769px) and (max-width: 1024px) {
  :root {
    --content-padding: 24px;
  }
}

/* Small laptops (1025–1280px) */
@media (min-width: 1025px) and (max-width: 1280px) {
  :root {
    --content-padding: 30px;
  }
}

/* Standard laptops (1281–1440px) */
@media (min-width: 1281px) and (max-width: 1440px) {
  :root {
    --content-padding: 40px;
  }
}

/* Large desktops (1441–1920px) */
@media (min-width: 1441px) and (max-width: 1920px) {
  :root {
    --content-padding: 56px;
    --content-measure: 82rem;
  }
}

/* Ultra-wide (1921px+) */
@media (min-width: 1921px) {
  :root {
    --content-padding: 64px;
    --content-measure: 96rem;
  }
}

/* Wide→very-wide only: cap the content column and keep it anchored left, so the
   surplus width falls on the right rather than stretching prose edge-to-edge.
   Below 1441px the column simply fills the available width. */
@media (min-width: 1441px) {
  div.body {
    max-width: var(--content-measure);
  }
}

/* ==========================================================================
   FOUC Bridge — inline <head> script sets html.dark-mode-pre before <body>
   exists. The dark tokens themselves come from the `.dark-mode,
   html.dark-mode-pre` rule above (single source of truth — no drift). Here we
   just paint the root element so the very first frame is already dark.
   ========================================================================== */
html.dark-mode-pre {
    background-color: var(--bg);
    color: var(--text);
}

/* ==========================================================================
   Top Bar
   ========================================================================== */
body {
    padding-top: var(--topbar-height);
}

.gs-topbar {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: var(--topbar-height);
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 12px;
    padding: 0 16px;
    background-color: var(--bg);
    color: var(--text);
    border-bottom: 1px solid var(--border);
    z-index: var(--topbar-z);
}

/* Wordmark holds the flex spacer, so the toggle sits flush-left beside it and
   everything after (hub link, theme menu) is pushed to the far right. */
.gs-brand {
    margin-right: auto;
    display: inline-flex;
    align-items: center;
    /* inline-flex collapses the whitespace text node between "Geoscape" and
       the DOCS span, so restore the word gap explicitly. */
    gap: 0.28em;
    font-family: var(--font-brand);
    font-size: 17px;
    font-weight: 500;
    letter-spacing: -0.01em;
    color: var(--text);
    text-decoration: none;
    white-space: nowrap;
    /* Reads as a title at rest; the hover fill (below) gives it the same
       button feel as the toggle and hub link, so padding/radius live here.
       The negative left margin cancels the padding so the text aligns to the
       topbar's 12px gap (flush with the toggle), while the hover fill keeps
       its 8px breathing room. */
    padding: 5px 8px;
    margin-left: -8px;
    border-radius: var(--radius-md);
}

/* Neutralize alabaster's anchor styling so it never reads as a hyperlink —
   no underline or accent colour on any state; the hover fill does the work. */
.gs-brand,
.gs-brand:hover,
.gs-brand:visited,
.gs-brand:active,
.gs-brand:focus {
    color: var(--text);
    text-decoration: none;
}

.gs-brand:hover {
    background-color: var(--bg-hover);
}

.gs-brand:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* SVG wordmark: "Geoscape" paths inherit .gs-brand's currentColor, "Docs"
   carries var(--primary) internally. Height drives the size; width auto keeps
   the aspect ratio. display:block avoids the inline baseline gap. */
.gs-brand__logo {
    height: 28px;
    width: auto;
    display: block;
}

/* Below the phone breakpoint the wordmark would crowd the hub/theme controls,
   so hide it. It carries the margin-right:auto flex spacer, so hand that back
   to the toggle here — otherwise flex-end would drag the toggle to the right. */
@media (max-width: 560px) {
    .gs-brand { display: none; }
    .gs-nav-toggle { margin-right: auto; }
}

/* Override alabaster's white documentwrapper/sphinxsidebar backgrounds at narrow widths */
div.document,
div.documentwrapper,
div.bodywrapper {
    background-color: var(--bg);
    color: var(--text);
}

/* Push alabaster's desktop fixed sidebar below the topbar */
@media (min-width: 941px) {
    div.sphinxsidebar {
        top: var(--topbar-height) !important;
        max-height: calc(100vh - var(--topbar-height));
    }
}

/* Below the alabaster breakpoint (940px), reclaim the sidebar gutter so content uses full width */
@media (max-width: 940px) {
    div.bodywrapper,
    div.documentwrapper,
    div.footer {
        margin-left: 0 !important;
    }
    div.body {
        max-width: 100%;
    }
}

.gs-topbar button {
    background-color: var(--bg);
    border: 1px solid var(--border);
    color: var(--text);
    font-family: var(--font-body);
    font-size: 0.9em;
    padding: 6px 10px;
    border-radius: var(--radius-md);
    cursor: pointer;
    line-height: 1;
}

.gs-topbar button:hover {
    background-color: var(--bg-hover);
}

.gs-topbar button:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

/* Sidebar trigger — lucide panel-left, as in the hub. Shown at every width:
   on desktop it collapses the sidebar to give wide reference tables (e.g.
   appendix C's data dictionary) the full window; below 940px it opens the
   drawer instead. */
/* Scoped under .gs-topbar so specificity (0,2,0) beats the generic
   `.gs-topbar button` rule (0,1,1) — a bare `.gs-nav-toggle` would lose its
   border override to it. This and the theme trigger are borderless icon
   buttons, unlike the "Geoscape Website" pill. */
.gs-topbar .gs-nav-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 7px;
    border: 0;
    background-color: transparent;
}

.gs-topbar .gs-nav-toggle:hover {
    background-color: var(--bg-hover);
}

.gs-nav-toggle__icon {
    display: block;
    color: var(--text);
}

/* Desktop collapse: hide the sidebar and reclaim its gutter. Alabaster sets
   the bodywrapper margin inline-ish via its own rules, hence the !important —
   same pattern as the <=940px block above. */
@media (min-width: 941px) {
    body[data-sidebar-collapsed] div.sphinxsidebar {
        display: none;
    }

    body[data-sidebar-collapsed] div.bodywrapper,
    body[data-sidebar-collapsed] div.documentwrapper,
    body[data-sidebar-collapsed] div.footer {
        margin-left: 0 !important;
    }

    /* Deliberately no max-width override here: the column keeps its normal cap
       (--content-measure on wide→very-wide screens, 100% below that) so
       collapsing the sidebar reclaims space up to the reading measure rather
       than sprawling to the full viewport width. */
}

/* "Go to Hub" link in the topbar — a small, compact pill sitting just before
   the theme control. It's an <a> but reads as a button, so override every
   link state (alabaster styles `a`, `a:hover`, `a:visited` with the accent
   colour and an underline). */
.gs-topbar-link,
.gs-topbar-link:hover,
.gs-topbar-link:visited,
.gs-topbar-link:active,
.gs-topbar-link:focus {
    color: var(--text);
    text-decoration: none;
}

.gs-topbar-link {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background-color: var(--bg);
    border: 1px solid var(--border);
    font-family: var(--font-body);
    font-size: 0.8em;
    line-height: 1;
    padding: 5px 8px;
    border-radius: var(--radius-md);
    white-space: nowrap;
}

.gs-topbar-link:hover {
    background-color: var(--bg-hover);
}

.gs-topbar-link:focus-visible {
    outline: 2px solid var(--primary);
    outline-offset: 2px;
}

.gs-topbar-link__icon {
    display: block;
    flex: none;
    width: 14px;
    height: 14px;
    color: var(--text-muted);
}

/* Theme menu: a single icon trigger that opens a Light / Dark / System
   dropdown, mirroring the hub front-end. */
.gs-theme {
    position: relative;
    display: inline-flex;
}

.gs-topbar .gs-theme__trigger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 7px;
    color: var(--text);
    border: 0;
    background-color: transparent;
}

.gs-topbar .gs-theme__trigger:hover {
    background-color: var(--bg-hover);
}

.gs-theme__icon {
    display: block;
}

/* JS hides the non-active icons with this class. A class beats the bare
   `.gs-theme__icon` above on specificity. (These are SVG elements, so the
   HTML `hidden` attribute can't be used — hence a class.) */
.gs-theme__icon--hidden {
    display: none;
}

@media print {
    .gs-topbar { display: none; }
}

/* ==========================================================================
   Related Bar (alabaster prev/next nav)
   ========================================================================== */
div.related {
    box-sizing: border-box;
    /* flex collapses the stray "&nbsp;" text node alabaster emits before
       <nav>, which otherwise adds a blank line and inflates the bar height */
    display: flex;
    align-items: center;
    background-color: var(--bg-subtle);
    color: var(--text);
    border-top: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
    padding: 3px var(--content-padding);
    font-size: 0.9em;
    overflow: hidden;
}

div.related.top {
    margin-bottom: 1.5em;
}

div.related.bottom {
    margin-top: 2em;
}

div.related nav#rellinks {
    width: 100%;
}

div.related ul {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 12px;
}

/* Order prev/next by SEMANTICS, not DOM position. Sphinx may emit only a
   prev, only a next, or both — and a lone <li> is both first- and
   last-child, so position-based rules mis-place it. Key off the link's
   title ("Previous document" / "Next document") instead. */
div.related li:has(a[title="Next document"]) {
    margin-left: auto;   /* next always hugs the right edge */
}

div.related li {
    margin: 0;
    /* Hide the raw ←/→ text nodes that sit directly in the <li>;
       we render our own arrows via pseudo-elements on the <a>. */
    font-size: 0;
}

/* Simple text links (not buttons): coloured, arrow glyph, underline on hover */
div.related a {
    font-size: 0.9rem;
    display: inline-flex;
    align-items: center;
    gap: 0.4em;
    color: var(--primary);
    font-weight: 500;
    text-decoration: none;
    padding: 2px 0;
}

div.related a:hover {
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* Direction glyphs keyed off link semantics (not DOM position) */
div.related a[title="Previous document"]::before {
    content: "←";
    font-weight: 400;
}

div.related a[title="Next document"]::after {
    content: "→";
    font-weight: 400;
}

/* ==========================================================================
   Mobile Drawer
   ========================================================================== */
.gs-backdrop {
    position: fixed;
    inset: 0;
    background-color: rgba(0, 0, 0, 0.4);
    z-index: var(--backdrop-z);
    opacity: 0;
    transition: opacity 0.2s ease;
    pointer-events: none;
}

body[data-nav-open] .gs-backdrop {
    opacity: 1;
    pointer-events: auto;
}

body[data-nav-open] {
    overflow: hidden;
}

@media (max-width: 940px) {
    div.sphinxsidebar {
        position: fixed;
        top: var(--topbar-height);
        left: -100%;
        width: var(--drawer-width);
        /* Tailwind's `w-*` is border-box; without this the 16px padding and 1px
           border push the drawer to 321px against the hub's 288px. */
        box-sizing: border-box;
        max-width: 85vw;
        height: calc(100vh - var(--topbar-height));
        max-height: calc(100vh - var(--topbar-height));
        background-color: var(--bg);
        color: var(--text);
        border-right: 1px solid var(--border);
        padding: 16px;
        overflow-y: auto;
        z-index: var(--drawer-z);
        transition: left 0.2s ease;
        margin: 0;
    }

    /* The wrapper is hard-set to --sidebar-width for the desktop float; in the
       drawer it should fill the wider mobile width instead of leaving a gap. */
    div.sphinxsidebarwrapper {
        width: 100%;
        padding: 0;
    }

    body[data-nav-open] div.sphinxsidebar {
        left: 0;
    }

    .gs-backdrop {
        top: var(--topbar-height);
    }
}

/* ==========================================================================
   Pygments syntax highlighting — dark mode overrides
   ========================================================================== */
body.dark-mode div.highlight,
body.dark-mode pre {
    background-color: #161b22;
    color: #e6edf3;
}

body.dark-mode code,
body.dark-mode tt,
body.dark-mode code.xref,
body.dark-mode tt.xref,
body.dark-mode a code,
body.dark-mode a tt {
    background-color: var(--code-bg);
    color: var(--code-text);
    border: 1px solid var(--code-border);
}

body.dark-mode pre code {
    color: inherit;
}

body.dark-mode h1 code, body.dark-mode h2 code, body.dark-mode h3 code,
body.dark-mode h4 code, body.dark-mode h5 code, body.dark-mode h6 code {
    color: inherit;
}

body.dark-mode pre code {
    background: none;
    border: none;
}

/* Pygments token classes */
body.dark-mode .highlight .c,
body.dark-mode .highlight .c1,
body.dark-mode .highlight .cm,
body.dark-mode .highlight .cs,
body.dark-mode .highlight .cp { color: #8b949e; font-style: italic; }      /* comments */

body.dark-mode .highlight .k,
body.dark-mode .highlight .kc,
body.dark-mode .highlight .kd,
body.dark-mode .highlight .kn,
body.dark-mode .highlight .kp,
body.dark-mode .highlight .kr,
body.dark-mode .highlight .kt { color: #ff7b72; }                          /* keywords */

body.dark-mode .highlight .s,
body.dark-mode .highlight .s1,
body.dark-mode .highlight .s2,
body.dark-mode .highlight .sb,
body.dark-mode .highlight .sc,
body.dark-mode .highlight .sd,
body.dark-mode .highlight .se,
body.dark-mode .highlight .sh,
body.dark-mode .highlight .si,
body.dark-mode .highlight .sx,
body.dark-mode .highlight .sr,
body.dark-mode .highlight .ss { color: #a5d6ff; }                          /* strings */

body.dark-mode .highlight .m,
body.dark-mode .highlight .mf,
body.dark-mode .highlight .mh,
body.dark-mode .highlight .mi,
body.dark-mode .highlight .mo,
body.dark-mode .highlight .il { color: #79c0ff; }                          /* numbers */

body.dark-mode .highlight .nb,
body.dark-mode .highlight .bp { color: #79c0ff; }                          /* builtins */

body.dark-mode .highlight .nf,
body.dark-mode .highlight .fm { color: #d2a8ff; }                          /* functions */

body.dark-mode .highlight .nc,
body.dark-mode .highlight .nn { color: #ffa657; }                          /* classes / namespaces */

body.dark-mode .highlight .nd,
body.dark-mode .highlight .ni,
body.dark-mode .highlight .ne { color: #ffa657; }                          /* decorators / exceptions */

body.dark-mode .highlight .o,
body.dark-mode .highlight .ow { color: #ff7b72; }                          /* operators */

body.dark-mode .highlight .nv,
body.dark-mode .highlight .vc,
body.dark-mode .highlight .vg,
body.dark-mode .highlight .vi { color: #e6edf3; }                          /* variables */

body.dark-mode .highlight,
body.dark-mode .highlight .n,
body.dark-mode .highlight .na,
body.dark-mode .highlight .nl,
body.dark-mode .highlight .no,
body.dark-mode .highlight .nx,
body.dark-mode .highlight .py,
body.dark-mode .highlight .nt,
body.dark-mode .highlight .p,
body.dark-mode .highlight .w { color: #e6edf3; }                           /* names, punctuation, default text */

body.dark-mode .highlight .err {
    color: #ffa198;
    background-color: transparent;
}

body.dark-mode .highlight .gh,
body.dark-mode .highlight .gu { color: #79c0ff; font-weight: bold; }       /* generic headers */
body.dark-mode .highlight .gd { color: #ffa198; background-color: #67060c; } /* generic deleted */
body.dark-mode .highlight .gi { color: #aff5b4; background-color: #033a16; } /* generic inserted */
body.dark-mode .highlight .ge { font-style: italic; }
body.dark-mode .highlight .gs { font-weight: bold; }
