/* cheatah docs — a bespoke, modern reference theme. No Doxygen, no doxygen-awesome.
 * Warm, earthy, neutral-dark palette; light mode supported via [data-theme="light"]. */

:root {
  --bg: #1b1815;
  --bg-2: #211d18;
  --surface: #24201a;
  --surface-2: #2b261f;
  --border: #38322a;
  --border-soft: #2c2720;
  --fg: #ece6da;
  --fg-dim: #b3aa98;
  /* 4.80:1 against --surface (#24201a), the lightest ground it is ever drawn on, so it
     clears WCAG 1.4.3 everywhere. The old #8a8170 measured 4.21:1 there and failed. */
  --fg-faint: #948b79;
  --accent: #d6ad73;        /* warm tan */
  --accent-2: #e7c897;
  --accent-soft: rgba(214,173,115,.14);
  --code-bg: #16130f;
  --code-fg: #e6dfd0;
  --shadow: 0 18px 50px -32px rgba(0,0,0,.9);
  --radius: 14px;
  --radius-sm: 9px;
  --maxw: 960px;
  --side-w: 248px;
  --toc-w: 224px;
  /* The sticky topbar's height. Four rules must agree on it — the bar itself, the sticky
     `top` of the sidebar and the TOC, and the scroll-margin that keeps a focused element
     out from under it — so it is a token, not a literal repeated four times. */
  --topbar-h: 58px;
  --layout-maxw: 1280px;
  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Inter, sans-serif;
  --mono: ui-monospace, "JetBrains Mono", "SF Mono", "Cascadia Code", Menlo, Consolas, monospace;
  /* neutral tag accents */
  --c-complexity: #9a927f;
  --c-alloc: #a3937c;
  --c-test: #8f938b;
  --c-perf: #d6ad73;
  --perf-up: #93b06b;       /* faster — muted sage-green, warm-theme friendly */
  --perf-down: #cf8470;     /* slower — muted terracotta-red                  */
}
[data-theme="light"] {
  --perf-up: #4f7a32; --perf-down: #b14d38;   /* darker for light theme legibility */
  --bg: #f7f3ea; --bg-2: #f1ebde; --surface: #fffdf8; --surface-2: #f4eee2;
  --border: #e0d7c5; --border-soft: #ebe3d4;
  --fg: #2c2820; --fg-dim: #5f584b; --fg-faint: #6b6151;
  --accent: #835d20; --accent-2: #6f4e1a;
  --accent-soft: rgba(131,93,32,.12);
  --code-bg: #f3ecdd; --code-fg: #33302a;
  --shadow: 0 16px 40px -30px rgba(60,45,20,.4);
}
/* Honour the reader's OS setting. The theme toggle was JavaScript and the serving CSP has
   no script-src, so with it gone this media query is the ONLY way light mode is reachable
   — which is why the generator emits no hardcoded data-theme on <html>. An explicit
   data-theme="dark" still wins, so the attribute remains a real override. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --perf-up: #4f7a32; --perf-down: #b14d38;
    --bg: #f7f3ea; --bg-2: #f1ebde; --surface: #fffdf8; --surface-2: #f4eee2;
    --border: #e0d7c5; --border-soft: #ebe3d4;
    --fg: #2c2820; --fg-dim: #5f584b; --fg-faint: #6b6151;
    --accent: #835d20; --accent-2: #6f4e1a;
    --accent-soft: rgba(131,93,32,.12);
    --code-bg: #f3ecdd; --code-fg: #33302a;
    --shadow: 0 16px 40px -30px rgba(60,45,20,.4);
  }
  :root:not([data-theme="dark"]) * { scrollbar-color: #c9bda4 transparent; }
  :root:not([data-theme="dark"]) ::-webkit-scrollbar-thumb { background: #c9bda4; }
}

* { box-sizing: border-box; }
/* Neutral, theme-matched scrollbars (sidebar/TOC/code), not the default blue. */
* { scrollbar-width: thin; scrollbar-color: #5a5040 transparent; }
[data-theme="light"] * { scrollbar-color: #c9bda4 transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: #5a5040; border-radius: 999px; border: 2px solid transparent; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background: var(--fg-faint); }
[data-theme="light"] ::-webkit-scrollbar-thumb { background: #c9bda4; }
html { scroll-behavior: smooth; }
body {
  margin: 0; background: var(--bg); color: var(--fg);
  font-family: var(--font); font-size: 15.5px; line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  /* Backstop only. A stray wide element must be FIXED, not hidden — clip keeps one
     mistake from making the whole document scroll sideways on a phone. */
  overflow-x: clip;
  /* Tapping a link otherwise flashes the OS default blue-grey over a warm palette. Match
     the hover state instead of disabling it — the tap needs to acknowledge itself. */
  -webkit-tap-highlight-color: var(--accent-soft);
}
a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-2); text-decoration: underline; text-underline-offset: 3px; }
/* Visible keyboard focus (WCAG 2.4.7). */
a:focus-visible, button:focus-visible, input:focus-visible, summary:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px;
}
code, pre, .sig { font-family: var(--mono); }
/* The topbar is sticky and opaque, so anything scrolled to the very top of the viewport
   lands underneath it. scroll-margin keeps a focused or :target element clear of the bar —
   SC 2.4.11 Focus Not Obscured (Minimum), new at AA in WCAG 2.2. Applied to every id, not
   just .member: headings, overload rows and source lines are all fragment targets, and Tab
   scrolling honours scroll-margin exactly as fragment navigation does. */
[id] { scroll-margin-top: calc(var(--topbar-h) + 14px); }
.skip { position: absolute; left: -999px; }
.skip:focus { left: 12px; top: 8px; background: var(--accent); color: var(--bg); padding: 6px 10px; border-radius: 6px; z-index: 200; }

/* ---- top bar ---- */
/* min-height, not height: under the text-spacing overrides SC 1.4.12 requires us to survive
   (line-height 1.5, letter-spacing .12em, word-spacing .16em) a fixed height clips the brand
   instead of growing. If the bar does grow, the sticky offsets below go slightly stale and
   the nav is marginally overlapped — graceful degradation, versus losing content. */
.topbar {
  position: sticky; top: 0; z-index: 100; min-height: var(--topbar-h);
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: saturate(150%) blur(12px); -webkit-backdrop-filter: saturate(150%) blur(12px);
  border-bottom: 1px solid var(--border);
}
/* Mirror the body grid: brand over the sidebar, then the package switcher.
   EVERY fixed column here must be dropped by the responsive block at the breakpoint that
   hides its content — otherwise the header keeps a 248+224px floor and the whole document
   scrolls sideways on a phone (WCAG 1.4.10 Reflow). docs_a11y_gate.sh gates exactly that. */
.topbar-inner {
  display: grid; grid-template-columns: var(--side-w) max-content minmax(0,1fr) var(--toc-w);
  align-items: center; gap: 18px; min-height: var(--topbar-h);
  max-width: none; margin: 0; padding: 0 24px; min-width: 0;
}
/* Centred over the sidebar column, matching the centred nav beneath it. The responsive
   block re-points it to `start` at =<1000px, where the brand owns the flexible column and
   centring would float it in open space. */
.brand { justify-self: center; display: flex; align-items: center; gap: 10px; font-weight: 800; letter-spacing: -.02em; color: var(--fg); font-size: 1.12rem; min-width: 0; }
.brand:hover { text-decoration: none; }
.brand img { width: 26px; height: 26px; border-radius: 6px; }
/* The package switcher: cheatah · gpu · gpu-linalg · … · standard, current highlighted. */
.pkgs { display: flex; align-items: center; gap: 1px; white-space: nowrap; font-size: .82rem; }
.pkgs a { color: var(--fg-dim); padding: 3px 8px; border-radius: 999px; font-family: var(--mono);
  display: inline-flex; align-items: center; min-height: 24px; }   /* 24px: WCAG 2.5.8 */
.pkgs a:hover { color: var(--fg); background: var(--accent-soft); text-decoration: none; }
.pkgs a.current { color: var(--accent); background: var(--accent-soft); font-weight: 600; }
.pkgs .pkgs-sep { color: var(--fg-faint); opacity: .55; user-select: none; }
/* The two outbound links — Source (the repository) and BigBrain (the storefront) — share ONE
   grid cell instead of taking a column each. Spans to the last column so the pair lands on the
   true right edge whether or not the toc column is showing; the responsive block re-points this
   wrapper as columns are dropped. Keeping them in one cell is what lets a second link be added
   without touching the track counts in the three media blocks below — and without the width
   floor a fourth fixed track would set on a phone. Unlike .pkgs the pair survives every
   breakpoint: mobile readers are still readers who might read the source, or buy something. */
.topbar-right { grid-column: 3 / -1; justify-self: end; display: flex; align-items: center; gap: 14px; min-width: 0; }
.repo, .bb { color: var(--fg-dim); font-size: .82rem; white-space: nowrap;
  display: inline-flex; align-items: center; min-height: 24px; padding: 0 2px; }   /* 24px: WCAG 2.5.8 */
.repo:hover, .bb:hover { color: var(--accent); text-decoration: none; }

/* ---- member source link + permalink ---- */
.member-actions { margin-left: auto; display: flex; align-items: center; gap: 12px; }
.member-actions .anchor { margin-left: 0; }
.src-link { font-size: .7rem; text-transform: uppercase; letter-spacing: .06em; color: var(--fg-faint); white-space: nowrap;
  display: inline-flex; align-items: center; min-height: 24px; }   /* 24px: WCAG 2.5.8 */
.src-link:hover { color: var(--accent); text-decoration: none; }

/* ---- source-listing pages ---- */
.srcview { border: 1px solid var(--border); border-radius: var(--radius-sm); background: var(--code-bg);
  overflow-x: auto; font-family: var(--mono); font-size: .84rem; line-height: 1.6; }
.srcline { display: flex; }
.srcline:target { background: var(--accent-soft); }
.srcline:target .lnno { color: var(--accent); }
.srcline .lnno { flex: 0 0 54px; text-align: right; padding: 0 14px 0 8px; color: var(--fg-faint); user-select: none; }
.srcline .lnno:hover { color: var(--accent); text-decoration: none; }
.srcline .lc { white-space: pre; color: var(--code-fg); background: none; padding: 0 14px 0 0; }

/* ---- layout ---- */
.layout {
  display: grid; grid-template-columns: var(--side-w) minmax(0,1fr) var(--toc-w);
  gap: 0; align-items: start; max-width: none; margin: 0;
}
/* Pages with no headings to list (the landings) drop the aside entirely — the generator
   omits the element rather than shipping an empty labelled landmark, so the column that
   would hold it must go too. */
.layout.no-toc { grid-template-columns: var(--side-w) minmax(0,1fr); }
.sidebar {
  position: sticky; top: var(--topbar-h); overflow-y: auto;
  height: calc(100vh - var(--topbar-h));
  /* dvh, not vh: on mobile 100vh is the LARGE viewport (URL bar hidden), so while the bar
     is showing the last links sit below the fold and cannot be reached. The vh line above
     stays as the fallback for engines that do not know dvh. */
  height: calc(100dvh - var(--topbar-h));
  padding: 22px 14px 40px; border-right: 1px solid var(--border-soft); font-size: 1rem;
}
/* Nav labels are CENTRED, and the hit areas stay full-width. The two are separate concerns:
   `align-items: stretch` on the ul is what satisfies SC 2.5.8 Target Size (a centred
   shrink-to-fit li is only as wide as its label), and the label is then centred INSIDE that
   stretched box. Nothing at AA constrains text alignment — SC 1.4.8 prohibits JUSTIFIED
   text, not centred, and is Level AAA. */
.side-home { display: block; font-weight: 600; color: var(--fg); padding: 6px 10px; border-radius: 7px; margin-bottom: 8px; text-align: center; }
.side-home:hover { background: var(--accent-soft); text-decoration: none; }
.side-group { margin: 16px 0; }
.side-h { text-transform: uppercase; letter-spacing: .08em; color: var(--fg-dim); padding: 0 10px 8px; font-size: .8rem; text-align: center; }
.sidebar ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; align-items: stretch; }
.sidebar li a { display: flex; align-items: center; justify-content: center; min-height: 28px; padding: 5px 10px; border-radius: 7px; color: var(--fg-dim); font-family: var(--mono); font-size: .98rem; }
.sidebar li a:hover { background: var(--accent-soft); color: var(--fg); text-decoration: none; }
.sidebar li a.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }

/* Submodule dropdowns (os.path, parsers.json, …) nested in the Modules list. */
.side-sub { width: 100%; }
.side-sub > summary { list-style: none; cursor: pointer; display: flex; align-items: center;
  gap: 5px; border-radius: 7px; min-height: 28px; }
.side-sub > summary::-webkit-details-marker { display: none; }
.side-sub > summary::after { content: "\25B8"; font-size: .68rem; color: var(--fg-dim);
  margin-left: auto; transition: transform .15s ease; }
.side-sub[open] > summary::after { transform: rotate(90deg); }
.side-sub > summary:hover { background: var(--accent-soft); }
/* flex:1 lets the label centre in the space left over by the caret, which stays pinned to
   the right edge (its margin-left:auto then resolves to 0 — no free space remains). */
.side-sub > summary > a { padding: 5px 4px; flex: 1; text-align: center; }
.side-sub > ul { margin: 2px 0 6px; padding-bottom: 2px; padding-left: 12px; }
.side-sub > ul a { font-size: .9rem; color: var(--fg-dim); }

/* Classes listed on a module's own page (in place of a sidebar Classes column). */
ul.class-list { list-style: none; margin: 8px 0 0; padding: 0; }
ul.class-list li { padding: 5px 0; color: var(--fg-dim); }
ul.class-list li a code { color: var(--accent); }

/* Site-wide copyright footer. */
.sitefoot { text-align: center; padding: 22px 24px; border-top: 1px solid var(--border-soft);
  color: var(--fg-faint); font-size: .8rem; }

.content { padding: 36px 48px 120px; min-width: 0; max-width: none; }
.toc { position: sticky; top: var(--topbar-h); overflow-y: auto;
  height: calc(100vh - var(--topbar-h)); height: calc(100dvh - var(--topbar-h));
  padding: 30px 16px; font-size: .95rem; }
.toc-h { text-transform: uppercase; letter-spacing: .08em; color: var(--fg-dim); margin-bottom: 8px; font-size: .8rem; padding: 0 10px; text-align: center; }
.toc ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; align-items: stretch; }
/* block, NOT flex: text-overflow has no effect on a flex container, so a flex entry clips
   long headings with no ellipsis. Block keeps the ellipsis, allows text-align, and the
   min-height still clears the 24px of SC 2.5.8. */
.toc li a { display: block; text-align: center; min-height: 26px; color: var(--fg-dim); font-family: var(--mono); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-radius: 6px; font-size: .9rem; padding: 4px 10px; }
.toc li a:hover { color: var(--accent); background: var(--accent-soft); text-decoration: none; }

/* ---- page head ---- */
.page-head { border-bottom: 1px solid var(--border-soft); padding-bottom: 18px; margin-bottom: 22px; }
.eyebrow { text-transform: uppercase; letter-spacing: .1em; font-size: .72rem; color: var(--accent); font-weight: 700; }
.page-head h1 { margin: .25em 0 .2em; font-size: 2rem; letter-spacing: -.02em; }
.page-head h1 code { background: none; padding: 0; color: var(--fg); }
.lede { color: var(--fg-dim); font-size: 1.05rem; margin: 0; }
/* extension pages: the version badge line (extension release — Biome Standard) */
.ext-badge { display: inline-block; margin: 0 0 .5em; padding: 2px 10px; font-size: .78rem;
  color: var(--accent); background: var(--accent-soft); border: 1px solid var(--border-soft);
  border-radius: 999px; }
.overview { margin-bottom: 30px; }
h2.group { margin: 40px 0 8px; font-size: 1.3rem; letter-spacing: -.01em; padding-bottom: 6px; border-bottom: 1px solid var(--border-soft); }
.content h2 { letter-spacing: -.01em; }

/* ---- member cards ---- */
.member {
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface);
  padding: 16px 18px; margin: 16px 0; box-shadow: var(--shadow);
}
.member-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.badge { font-size: .64rem; text-transform: uppercase; letter-spacing: .06em; font-weight: 700;
  padding: 2px 7px; border-radius: 6px; background: var(--surface-2); color: var(--fg-faint); border: 1px solid var(--border); }
.badge-fn { color: var(--accent); }
.sig { font-size: .94rem; color: var(--fg); overflow-x: auto; }
.sig .mtype { color: var(--fg-dim); }
.sig .mname { color: var(--accent); font-weight: 600; }
.sig .kw { color: #c69; color: var(--c-alloc); }
/* The permalink is a real focusable link, and `opacity` applies to an element's WHOLE
   rendering — its outline included. Revealed on hover alone, a keyboard user tabbing here
   gets an invisible link AND an invisible focus ring (SC 2.4.7 Focus Visible: hover is not
   a mode of operation a keyboard has). :focus-within/:focus-visible are what make it a
   pass. 24px square: SC 2.5.8 — a bare "#" glyph is ~10px wide, and sitting in a flex row
   rather than a sentence it does not get the criterion's inline exception. */
.anchor { margin-left: auto; color: var(--fg-faint); opacity: 0; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center; min-width: 24px; min-height: 24px; }
.member:hover .anchor, .member:focus-within .anchor, .anchor:focus-visible { opacity: 1; }
.member-brief { margin: 10px 0 6px; color: var(--fg); }
.member-body { color: var(--fg-dim); }
.member-body p { margin: .5em 0; }
/* Consolidated overloads: every concrete signature of one function, each with its
   own source link + permalink, listed above the shared description. */
.overload-count { color: var(--fg-faint); font-weight: 500; font-size: .82rem; }
.overload-list { margin: 10px 0 4px; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.overload { display: flex; align-items: center; gap: 10px; padding: 8px 12px; background: var(--surface-2); }
.overload + .overload { border-top: 1px solid var(--border); }
.overload .sig { flex: 1; }
.overload .anchor { opacity: 0; }
.overload:hover .anchor, .overload:focus-within .anchor { opacity: 1; }

/* ---- params / returns ---- */
.params { margin: 12px 0; }
.params-h, .ret-h { font-size: .7rem; text-transform: uppercase; letter-spacing: .07em; color: var(--fg-faint); font-weight: 700; }
.params-t { border-collapse: collapse; margin-top: 6px; width: auto; }
.params-t td { padding: 3px 0; vertical-align: baseline; border: none; }
.params-t .pname { white-space: nowrap; width: 1%; padding-right: 16px; }
.params-t .pname code { color: var(--accent); background: none; }
.params-t .pdesc { color: var(--fg-dim); }
.params-t .pdesc p { margin: 0; }

/* paw-print emoji recolored to a soft neutral grey (system fonts render 🐾 blue) */
.paw { filter: grayscale(100%) opacity(.72); }
.ret { margin: 10px 0; color: var(--fg-dim); }
.ret-h { color: var(--accent); margin-right: 6px; }

/* ---- @complexity / @alloc / @test chips ---- */
.tag { display: flex; gap: 10px; align-items: baseline; margin: 6px 0; padding: 7px 12px;
  border-left: 3px solid var(--border); border-radius: 8px; background: var(--bg-2); }
.tag-k { font-size: .66rem; text-transform: uppercase; letter-spacing: .07em; font-weight: 700; color: var(--fg-faint); min-width: 78px; }
.tag-v { color: var(--fg-dim); }
.tag-v p { margin: 0; display: inline; }
.tag-complexity { border-left-color: var(--c-complexity); }
.tag-alloc { border-left-color: var(--c-alloc); }
.tag-test { border-left-color: var(--c-test); }
.tag-perf { border-left-color: var(--c-perf); }
.tag-perf .tag-v strong { color: var(--accent); }
/* @test rows: a gtest Suite.Case read as a warm-toned qualified symbol (no blue). */
.tn-suite { color: var(--fg-faint); }
.tn-case  { color: var(--accent); }
.tag-perf .tag-v strong.perf-faster, .perf-faster { color: var(--perf-up); }
.tag-perf .tag-v strong.perf-slower, .perf-slower { color: var(--perf-down); }
.tag-crtest { border-left-color: #8c9488; }       /* neutral slate-grey */
.tag-systest { border-left-color: #97918a; }      /* neutral warm-grey */
.tag-gpualloc { border-left-color: #7f9a8f; }     /* @gpualloc — device memory, muted jade */
.tag-destroy { border-left-color: #cf8470; }      /* @destroy — lifetime/caller-must-release, terracotta */
.tag-gpualloc .tag-k, .tag-destroy .tag-k { min-width: 92px; }
/* Qualified gtest names (Suite.Case) are long single tokens with no space to break at —
   let them break anywhere rather than push the page wider than the viewport. */
.tag-test .tag-v, .tag-crtest .tag-v, .tag-systest .tag-v { font-family: var(--mono); font-size: .85rem;
  min-width: 0; overflow-wrap: anywhere; }
.tag-v .more { color: var(--fg-faint); cursor: help; padding: 0 2px; }
.tag-test .tag-k, .tag-crtest .tag-k, .tag-systest .tag-k { min-width: 92px; }

/* ---- admonitions ---- */
.admon { margin: 12px 0; border-left: 3px solid var(--accent); border-radius: 8px; background: var(--bg-2); padding: 8px 12px; }
.admon-h { font-size: .68rem; text-transform: uppercase; letter-spacing: .07em; font-weight: 700; color: var(--accent); }
.admon-b { color: var(--fg-dim); }

/* ---- code & tables ---- */
code { background: var(--code-bg); padding: .12em .4em; border-radius: 5px; font-size: .88em; color: var(--code-fg);
  overflow-wrap: anywhere; }   /* long symbols must not set the page width on a phone */
pre.code { background: var(--code-bg); border: 1px solid var(--border); border-radius: var(--radius-sm); padding: 14px 16px; overflow-x: auto; }
pre.code code { background: none; padding: 0; }
/* Syntax highlighting (tokens emitted by docs/gen/generate.py) — warm, theme-matched.
   Unscoped so it applies to BOTH block (pre.code) and inline `code` (e.g. guide tables). */
.tok-kw    { color: var(--accent); }            /* fn let struct if for … */
.tok-str   { color: #9fae6e; }                  /* string literals (olive)  */
.tok-num   { color: #cf9b6a; }                  /* numbers (amber)          */
.tok-const { color: #cf9b6a; }                  /* true false None          */
.tok-fn    { color: #8fb3a8; }                  /* call sites (muted teal)  */
.tok-com   { color: var(--fg-faint); font-style: italic; }
.tok-doc   { color: #9d92c4; font-weight: 600; }  /* @param @return @complexity @alloc @test … */
[data-theme="light"] .tok-doc   { color: #6b5e9c; }
.tok-ns    { color: #82a7c0; }                    /* namespace/type qualifiers: io:: std:: parsers:: */
[data-theme="light"] .tok-ns    { color: #3f6785; }
[data-theme="light"] .tok-str   { color: #5d6b2e; }
[data-theme="light"] .tok-num   { color: #9a5f2c; }
[data-theme="light"] .tok-const { color: #9a5f2c; }
[data-theme="light"] .tok-fn    { color: #3f6f63; }
/* ---- transpiler page: .purr ↔ .gen.cpp side by side ---- */
.xpile-ex { margin: 26px 0; }
.xpile-blurb { color: var(--fg-dim); margin: 2px 0 12px; }
/* Panes bottom-align so the shorter source lines up with the end of its transpiled C++;
   the filename/lang caption sits UNDER each block. */
.xpile { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: end; }
.xpile-pane { margin: 0; min-width: 0; }                 /* min-width:0 lets panes shrink + scroll */
.xpile-pane figcaption { display: flex; align-items: baseline; justify-content: space-between;
  gap: 10px; font-family: var(--mono); font-size: .8rem; color: var(--fg-faint); margin-top: 6px; }
.xpile-pane .fname { color: var(--fg-dim); }
.xpile-pane .xpile-lang { text-transform: uppercase; letter-spacing: .04em; font-size: .68rem;
  border: 1px solid var(--border); border-radius: 999px; padding: 1px 8px; }
.xpile-pane pre.code { margin: 0; font-size: .82rem; line-height: 1.55; white-space: pre; }
@media (max-width: 1000px) { .xpile { grid-template-columns: 1fr; } }
/* A wide table scrolls INSIDE this wrapper, so it can never widen the document (WCAG 2.1
   SC 1.4.10). The WRAPPER — not the table — carries the frame and the overflow: a <table>
   cannot be its own scroll container, because `display:block` takes it out of table layout,
   the rows collapse into an anonymous shrink-to-fit box, and `width:100%` then sizes only
   the frame while the cells hug the left. The generators emit tabindex="0" on this div so
   the scroller is keyboard-operable (SC 2.1.1) — a scroll region containing no focusable
   element cannot be reached by keyboard in Safari; the [tabindex]:focus-visible rule above
   gives it a ring. overscroll-behavior keeps a horizontal swipe off the back gesture. */
.tscroll { margin: 14px 0; border: 1px solid var(--border); border-radius: var(--radius-sm);
  overflow-x: auto; overscroll-behavior-x: contain; }
/* No min-width: the table squeezes to its natural min-content first (inline `code` carries
   overflow-wrap:anywhere, so most tables never need to scroll at all) and the wrapper only
   scrolls past that point. */
.dtable, table.dtable { border-collapse: collapse; width: 100%; margin: 0; border: none; }
.dtable th, .dtable td { padding: 8px 12px; border-bottom: 1px solid var(--border-soft); text-align: left; }
.dtable th { background: var(--surface-2); font-size: .8rem; text-transform: uppercase; letter-spacing: .05em; color: var(--fg-dim); }
.dtable tr:last-child td { border-bottom: none; }
hr { border: none; border-top: 1px solid var(--border); margin: 28px 0; }

/* ---- the Biome Standard page + extension landings ---- */
/* The dependency diagram: static inline SVG, themed via the CSS variables. */
.dep-svg { display: block; width: 100%; max-width: 640px; height: auto; margin: 16px auto; }
.dep-svg .dep-box { fill: var(--surface); stroke: var(--border); stroke-width: 1.5; }
.dep-svg .dep-box-core { stroke: var(--accent); }
.dep-svg text { fill: var(--fg); font-family: var(--mono); font-size: 14px; }
.dep-svg a:hover .dep-box { fill: var(--surface-2); stroke: var(--accent); }
.dep-svg .dep-edge { stroke: var(--fg-faint); stroke-width: 1.5; }
.dep-svg .dep-arrowhead { fill: var(--fg-faint); }
.ext-deps { color: var(--fg-dim); }

/* ---- home ---- */
.hero { display: flex; align-items: center; gap: 18px; padding-bottom: 18px; margin-bottom: 10px; border-bottom: 1px solid var(--border-soft); }
.hero-logo { width: 58px; height: 58px; border-radius: 13px; }
.hero-text { display: flex; flex-direction: column; gap: 2px; }
.hero-title { font-size: 2.7rem; letter-spacing: -.03em; margin: 0; font-weight: 800; }
.hero-tagline { margin: 0; color: var(--fg-dim); font-style: italic; font-size: 1.05rem; }
.home h1 { font-size: 2.3rem; letter-spacing: -.02em; }
.home h2 { margin-top: 1.8em; }

/* ---- responsive ----
   RULE: when a breakpoint hides a column's content, that breakpoint must also drop the
   column from BOTH grids (.layout and .topbar-inner). A fixed track left behind sets a
   width floor the viewport cannot satisfy, and the whole document scrolls sideways.
   scripts/docs_a11y_gate.sh asserts scrollWidth <= innerWidth down to 320px. */

/* The TOC column goes first. */
@media (max-width: 1100px) {
  .toc { display: none; }
  .layout, .layout.no-toc { grid-template-columns: var(--side-w) minmax(0,1fr); }
  .topbar-inner { grid-template-columns: var(--side-w) max-content minmax(0,1fr); }
  .topbar-right { grid-column: 3; }
}
/* Then the package switcher: brand on the left, the way back to the company on the right. */
@media (max-width: 1000px) {
  .pkgs { display: none; }
  .topbar-inner { grid-template-columns: minmax(0,1fr) max-content; }
  .topbar-right { grid-column: 2; }
  /* The brand now owns the flexible column instead of the sidebar-width one — centring it
     there would float it in open space, so it goes back to the left edge. */
  .brand { justify-self: start; }
}
/* Phone: one column. The sidebar is CAPPED and scrolls in place instead of stacking its
   full ~40-link height above the article — otherwise a reader meets two screens of nav
   before the first word of documentation. A height cap (rather than a <details>
   disclosure) because it behaves identically in Blink, Gecko and WebKit: Chrome's
   ::details-content no longer hides content the way a CSS force-open would assume. */
@media (max-width: 760px) {
  /* minmax(0,1fr), NOT 1fr: a bare 1fr track has an auto minimum, so a wide code block or
     signature grows the track past the viewport instead of scrolling inside itself. */
  .layout, .layout.no-toc { grid-template-columns: minmax(0,1fr); }
  .sidebar {
    position: static; height: auto; overflow-y: auto;
    max-height: 38vh; max-height: 38dvh;          /* dvh: the URL bar must not eat the cap */
    border-right: none; border-bottom: 1px solid var(--border); padding: 10px 8px;
    overscroll-behavior: contain;                 /* don't chain scroll to the document */
  }
  .content { padding: 24px 18px 80px; }
  .topbar-inner { padding: 0 16px; gap: 12px; }
  /* At 320px the brand plus both outbound links is the tightest row on the site. Tighten the
     pair's own gap rather than hiding one: a dropped link is a dead end, a closer pair is not.
     docs_a11y_gate.sh is what proves this still clears the viewport. */
  .topbar-right { gap: 10px; }
  /* A backdrop blur under a sticky bar makes the compositor re-blur what is behind it on
     every scroll frame — the single biggest source of scroll jank on a mid-range phone.
     An opaque bar costs nothing visually at this size. */
  .topbar { backdrop-filter: none; -webkit-backdrop-filter: none; background: var(--bg); }
  /* Primary nav on touch: 44px targets (WCAG 2.5.5). */
  .sidebar li a, .side-sub > summary, .side-home { min-height: 44px; }
  .side-home { display: flex; align-items: center; justify-content: center; }
}
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

/* The donate button in the site footer — every page carries it. It links to the storefront's
   /cheatah/donate explainer (a voluntary pay-what-you-want purchase from BigBrain LLC, never
   framed as a charitable donation — the landing page carries the plain-words legal part). */
.sitefoot .donate {
  display: inline-block; margin-left: 10px; padding: 3px 12px;
  border: 1px solid var(--accent); border-radius: 999px;
  color: var(--accent); text-decoration: none; font-weight: 600; white-space: nowrap;
}
.sitefoot .donate:hover { background: var(--accent-soft); color: var(--accent-2); }
