/* ============================================
   QuickEasy BOS Docs — site.css (CHROME ONLY)
   Header, sidebar nav, breadcrumb, footer, layout, tokens.
   Do not put documentation-content styling here — see content.css.
   ============================================ */

/* ============================================
   1. TOKENS — locked monochrome spec
   ============================================ */
:root {
  --gray-950: #050505;
  --gray-900: #0c0c0c;
  --gray-800: #262626;
  --gray-700: #404040;
  --gray-600: #525252;
  --gray-500: #6b6b6b;
  --gray-400: #a3a3a3;
  --gray-300: #d4d4d4;
  --gray-200: #e5e5e5;
  --gray-100: #f0f0f0;
  --gray-50: #f7f7f7;

  --background: #ffffff;
  --background-alt: var(--gray-50);
  --foreground: var(--gray-900);
  --muted: var(--gray-50);
  --muted-foreground: var(--gray-500);
  --border: var(--gray-200);
  --border-strong: var(--gray-300);
  --primary: var(--gray-900);
  --primary-dark: var(--gray-950);
  --primary-foreground: #ffffff;

  --destructive: #b91c1c;
  --destructive-bg: rgba(220, 38, 38, 0.1);
  --destructive-foreground: #ffffff;

  /* The Info callout's color - a deliberate, explicit deviation from the
     monochrome spec (alongside --destructive and --accent), not derived
     from the logo like --accent. See project-docs/Stylesheet.md. */
  --info: #166534;
  --info-bg: rgba(22, 101, 52, 0.08);

  /* The "BOS" wordmark teal, sampled directly from the brand PNGs in
     Sources/ (tools/make-logo.js prints it) - ~7.0:1 on white (AAA). Used in exactly three places: the h1 heading color
     (content.css), the Navigation callout's border/caption
     (content.css .callout--navigation), and sidebar group headings
     (.sidebar__group-heading) - nowhere else. See
     project-docs/Stylesheet.md for the full rationale and contrast figures. */
  --accent: #036080;
  --accent-bg: rgba(3, 96, 128, 0.08);

  /* Editable fields - the BOS app shows the captions of editable grid
     columns in this blue (DtmdlMain.sCaptionBlue, #0355df), and the docs
     mirror it on the field name in reference tables (content.css
     td.field-editable) - nowhere else. 6.2:1 on white, 5.5:1 on the
     striped rows (AA). Owner request, 2026-10-05. */
  --editable: #0355df;

  /* Callout background tints for Note and Important - a few shades
     lighter than the border/label color so callout text stays easily
     readable. --note-bg tints --muted-foreground (gray); --important-bg
     tints --foreground itself (deliberately the lowest alpha of the
     five, since --foreground is much darker/more neutral than the other
     four callout colors and would otherwise read as a near-solid fill). */
  --note-bg: rgba(107, 107, 107, 0.08);
  /* Page intro (the 💡 line): lightbulb yellow, distinct from the red Warning callout. */
  --intro: #d4a72c;
  --intro-bg: #f8f6ee;
  --important-bg: rgba(12, 12, 12, 0.06);

  --font-body: "Roboto", "Noto Sans Thai", system-ui, -apple-system, "Segoe UI", Arial, sans-serif;
  --font-mono: ui-monospace, "SFMono-Regular", "Consolas", "Liberation Mono", Menlo, monospace;

  --space-xs: 0.25rem;
  --space-sm: 0.5rem;
  --space-md: 1rem;
  --space-lg: 2rem;
  --space-xl: 3rem;

  /* Desktop and tablet only - this project doesn't support phone-width
     viewports. --breakpoint-md is the supported floor (not a mobile
     cutoff); --breakpoint-lg is where the "On this page" TOC gets
     promoted from an inline block into its own third grid column. */
  --breakpoint-md: 768px;
  --breakpoint-lg: 1100px;
  --header-height: 4.75rem;
  --sidebar-width: 17rem;
  --toc-width: 14rem;
}

:root[data-theme="dark"] {
  --dark-elevated: #1c1c1c;
  --background: var(--gray-950);
  --background-alt: var(--dark-elevated);
  --foreground: var(--gray-50);
  --muted: var(--dark-elevated);
  --muted-foreground: var(--gray-400);
  --border: var(--gray-800);
  --border-strong: var(--gray-700);
  --primary: var(--gray-50);
  --primary-dark: #ffffff;
  --primary-foreground: var(--gray-950);

  --destructive: #f87171;
  --destructive-bg: rgba(248, 113, 113, 0.14);
  --destructive-foreground: var(--gray-950);

  /* #166534 fails contrast on dark backgrounds - this brighter tint of
     the same green passes strongly while still reading as green. */
  --info: #22c55e;
  --info-bg: rgba(34, 197, 94, 0.14);

  /* #036080 fails contrast on dark backgrounds (~2.6:1) - the logo's own
     light cyan (the cube tops) passes strongly (~7.8:1 on --gray-950),
     so dark mode uses a real brand colour rather than a derived tint. */
  --accent: #06b3b6;
  --accent-bg: rgba(6, 179, 182, 0.14);

  /* #0355df is too dark on near-black - a lighter tint of the same blue
     (~8.5:1 on --gray-950, 6.3:1 on the striped rows). */
  --editable: #6ea8ff;

  /* See :root's comment - same tints, bumped slightly (0.08->0.12,
     0.06->0.08) to stay visible against the near-black dark background. */
  --note-bg: rgba(163, 163, 163, 0.12);
  --intro: #e6b84a;
  --intro-bg: rgba(212, 190, 120, 0.10);
  --important-bg: rgba(247, 247, 247, 0.08);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --dark-elevated: #1c1c1c;
    --background: var(--gray-950);
    --background-alt: var(--dark-elevated);
    --foreground: var(--gray-50);
    --muted: var(--dark-elevated);
    --muted-foreground: var(--gray-400);
    --border: var(--gray-800);
    --border-strong: var(--gray-700);
    --primary: var(--gray-50);
    --primary-dark: #ffffff;
    --primary-foreground: var(--gray-950);
    --destructive: #f87171;
    --destructive-bg: rgba(248, 113, 113, 0.14);
    --destructive-foreground: var(--gray-950);
    --info: #22c55e;
    --info-bg: rgba(34, 197, 94, 0.14);
    --accent: #06b3b6;
    --accent-bg: rgba(6, 179, 182, 0.14);
    --editable: #6ea8ff;
    --note-bg: rgba(163, 163, 163, 0.12);
    --intro: #e6b84a;
    --intro-bg: rgba(212, 190, 120, 0.10);
    --important-bg: rgba(247, 247, 247, 0.08);
  }
}

@font-face {
  font-family: "Roboto";
  src: url("/assets/fonts/roboto-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Roboto";
  src: url("/assets/fonts/roboto-700.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* Thai glyphs (Roboto has none): only downloaded on pages with Thai text. */
@font-face {
  font-family: "Noto Sans Thai";
  src: url("/assets/fonts/noto-sans-thai-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0E01-0E5B, U+200C-200D, U+25CC;
}
@font-face {
  font-family: "Noto Sans Thai";
  src: url("/assets/fonts/noto-sans-thai-700.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0E01-0E5B, U+200C-200D, U+25CC;
}

/* ============================================
   2. RESET / BASE
   ============================================ */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-padding-top: var(--space-md); }
body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.5;
  color: var(--foreground);
  background: var(--background);
}
img { max-width: 100%; height: auto; display: block; }
h1, h2, h3, h4, p { margin: 0 0 var(--space-md); }
a { color: inherit; }

/* ============================================
   3. LAYOUT
   ============================================ */
.container {
  max-width: 1280px;
  margin-inline: auto;
  padding-inline: var(--space-md);
}

.site-body {
  display: flex;
  flex-direction: column;
  max-width: 1280px;
  margin-inline: auto;
}

/* Desktop and tablet only (no phone-width layout), responsive down to
   half an FHD screen (960px): sidebar + content is the baseline
   two-column grid at every supported width. The "On this page" TOC
   (.doc-layout--has-toc) is a real third grid column, but only once
   there's genuinely enough room for it (--breakpoint-lg) - below that,
   it's hidden outright rather than left to fall back into the
   two-column grid, which put it in the same column as (and, on a short
   page, visually on top of) the sidebar. A hidden TOC below is still a
   fully usable page: every page also has a real "On this page" is a
   convenience, not the only way to reach a section - direct links and
   scrolling both still work. */
.doc-layout {
  display: grid;
  grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
  gap: var(--space-lg);
  align-items: start;
  padding-inline: var(--space-md);
  padding-block: var(--space-lg);
}

.doc-content-wrapper {
  min-width: 0;
  max-width: 48rem;
}

.doc-layout--has-toc .page-toc {
  display: none;
}

@media (min-width: 1100px) {
  .doc-layout--has-toc {
    grid-template-columns: var(--sidebar-width) minmax(0, 1fr) var(--toc-width);
  }
  .doc-layout--has-toc .page-toc {
    display: block;
    grid-column: 3;
    grid-row: 1;
    position: sticky;
    top: calc(var(--header-height) + var(--space-lg));
    /* Same independent-scroll fix as .sidebar above, for the rare page
       with enough headings that its TOC alone is taller than the
       viewport. */
    max-height: calc(100vh - var(--header-height) - var(--space-lg) * 2);
    overflow-y: auto;
    margin-bottom: 0;
  }
}

/* ============================================
   4. COMPONENTS
   ============================================ */

/* --- Skip link --- */
.skip-link {
  position: absolute;
  top: -3rem;
  left: var(--space-sm);
  background: var(--primary);
  color: var(--primary-foreground);
  padding: var(--space-sm) var(--space-md);
  z-index: 100;
  border-radius: 4px;
}
.skip-link:focus { top: var(--space-sm); }

/* --- Header --- */
.site-header {
  border-bottom: 1px solid var(--border);
  background: var(--background);
  position: sticky;
  top: 0;
  z-index: 20;
}
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-md);
  height: var(--header-height);
  padding-inline: var(--space-md);
  max-width: 1280px;
  margin-inline: auto;
}
.site-header__logo {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  /* The header logo (bos-logo-v3.png, "Bos-Logo_Primary Vertical") has a
     dark teal wordmark on a transparent background, so - as in
     bos-ent-docs - it sits on a hardcoded white chip (not a theme token),
     which keeps the wordmark legible in dark mode and is invisible in
     light mode. Padding matches .sidebar__link's horizontal padding
     (--space-sm) so the logo lines up with the sidebar/content edge. */
  background: #ffffff;
  padding: var(--space-sm);
  border-radius: 4px;
  text-decoration: none;
}
/* 2.5rem, not the old 3.25rem: v1's canvas had a ~28px/26px transparent
   margin baked in around the ink, so at 3.25rem tall the *visible*
   wordmark (excluding that invisible margin) actually rendered at
   ~2.5rem - 3.25rem was sized for the padded canvas, not the ink itself.
   v2 (see CLAUDE.md "Header") is cropped tight to the ink with no such
   margin, so keeping 3.25rem here would render the same wordmark
   noticeably larger than it's always looked. 2.5rem reproduces the
   original on-screen ink size against v2's tighter crop. */
.site-header__logo img { display: block; height: 2.5rem; width: auto; }

.site-header__actions {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  min-width: 0;
}

/* --- Feedback button (header) ---
   Always visible, every page - see CLAUDE.md "Feedback modal". Reuses
   the .btn/.btn-outline component. `font: inherit` (then restoring just
   the weight) copies .site-search__input's own box model exactly -
   same padding/border/line-height math - so the two sit at the same
   height by construction, not a coincidentally-matching hardcoded
   number that would drift if the base font size ever changed. */
.btn.site-header__feedback {
  flex-shrink: 0;
  padding: var(--space-xs) var(--space-md);
  font: inherit;
  font-weight: 600;
  white-space: nowrap;
}

/* --- Language switch (header) ---
   English pages link to the same page in Thai (Thai flag) and back (UK
   flag); stamped by tools/i18n/th-build.js. A flag, not text, so it stands
   out between Search and Feedback (owner, 2026-10-15); the language name is
   in the tooltip and aria-label. Outlined like the Feedback button. */
.lang-switch {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: stretch;
  padding: 0 var(--space-sm);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md, 6px);
  line-height: 0;
}
.lang-switch:hover { border-color: var(--primary); }
.lang-switch__flag {
  display: block;
  border-radius: 2px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15);
}

/* --- Theme toggle ---
   Manual override of the automatic prefers-color-scheme default. Shows the
   icon for the mode you'd switch TO. No stored preference = follows the
   OS/browser setting (handled by the same media query as every other
   token); clicking sets an explicit data-theme and remembers it. */
.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border: 0;
  background: transparent;
  cursor: pointer;
  color: var(--foreground);
  flex-shrink: 0;
}
.theme-toggle svg { width: 1.25rem; height: 1.25rem; }
.theme-toggle__icon--dark { display: block; }
.theme-toggle__icon--light { display: none; }

:root[data-theme="dark"] .theme-toggle__icon--dark { display: none; }
:root[data-theme="dark"] .theme-toggle__icon--light { display: block; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle__icon--dark { display: none; }
  :root:not([data-theme="light"]) .theme-toggle__icon--light { display: block; }
}

/* --- Sidebar tree nav ---
   A grid column from 900px up (hideable with the header menu button),
   a slide-in drawer below that - see "Menu toggle + collapsible
   sidebar" below. */
.sidebar {
  display: block;
  position: sticky;
  top: calc(var(--header-height) + var(--space-lg));
  /* Bounds the sticky nav to the viewport space actually below it (minus
     a matching --space-lg breathing room at the bottom), and makes that
     bounded box its own scroll container. Without this, a nav list
     taller than the viewport just rides along with the page scroll once
     it hits the bottom of its sticky containing block (the grid cell,
     which - align-items: start - is exactly as tall as whichever column
     is taller) - so on a long content page there's no way to reach the
     nav's own lower items without first scrolling all the way to the
     bottom of the content column. overflow-y: auto here means a mouse
     wheel over the nav scrolls the nav (not the page) the moment the
     pointer is over it - no click-to-focus step needed - and Tab/arrow
     navigation between links scrolls it too, since it's a real
     scrollable ancestor. */
  max-height: calc(100vh - var(--header-height) - var(--space-lg) * 2);
  overflow-y: auto;
}
.sidebar__list {
  list-style: none;
  margin: 0;
  padding: 0;
}
/* Group headings (Getting Started, Accounting & Finance, ...) - a purely
   visual/navigational clustering above build.js's SIDEBAR_GROUPS, not
   another collapsible layer. Accent color is the third sanctioned use of
   --accent (alongside H1 and .callout--navigation) - see Stylesheet.md.
   Title case + a thin bottom-border divider, not uppercase + letter-
   spacing: at a size matching the root menu items (see below), bold
   uppercase letter-spaced text read as heavy/shouty rather than as a
   section label - the divider does the "this is a section break" job
   instead, the same way content.css's h2 uses a border-top rule. */
.sidebar__group-heading {
  margin: var(--space-lg) 0 var(--space-sm);
  padding: 0 var(--space-sm) var(--space-xs);
  border-bottom: 1px solid var(--border);
  /* At least as large as the root-level menu items (.sidebar__link /
     .sidebar__group-link, 0.9375rem) - it was 0.75rem originally, which
     read as smaller/lower-priority than the items it groups. */
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--accent);
}
.sidebar__list:first-of-type + .sidebar__group-heading {
  margin-top: var(--space-sm);
}

.sidebar__group { margin-bottom: var(--space-xs); }
/* The category label is a real link to its own landing page (per the
   WAI-ARIA APG Disclosure pattern - see CLAUDE.md "Sidebar"); the toggle
   is a separate, small icon-only button beside it that only expands/
   collapses the sublist. Two independent controls, not one overloaded
   button - this is also what fixed the font-size mismatch bug (the old
   button used font: inherit and rendered a size larger than every other
   sidebar link). */
.sidebar__group-row {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}
.sidebar__group-row .sidebar__link { flex: 1; min-width: 0; }
.sidebar__group-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 2rem;
  height: 2rem;
  border: 0;
  background: transparent;
  cursor: pointer;
  border-radius: 4px;
}
.sidebar__group-toggle:hover,
.sidebar__group-toggle:focus-visible { background: var(--muted); }
.sidebar__group-toggle-icon {
  display: inline-block;
  width: 0.4rem;
  height: 0.4rem;
  border-right: 2px solid var(--muted-foreground);
  border-bottom: 2px solid var(--muted-foreground);
  transform: rotate(45deg);
  transition: transform 0.15s ease;
  flex-shrink: 0;
}
.sidebar__group[data-open="true"] .sidebar__group-toggle-icon {
  transform: rotate(-135deg);
}
.sidebar__sublist {
  list-style: none;
  margin: 0;
  padding: 0 0 var(--space-sm) var(--space-md);
  display: none;
}
.sidebar__group[data-open="true"] .sidebar__sublist { display: block; }
.sidebar__link {
  display: block;
  padding: var(--space-xs) var(--space-sm);
  text-decoration: none;
  color: var(--muted-foreground);
  border-radius: 4px;
  font-size: 0.9375rem;
}
.sidebar__link:hover,
.sidebar__link:focus-visible { background: var(--muted); color: var(--foreground); }
/* Every top-level item reads as a peer, whether it's a childless
   category link or a category-with-children's link (now beside its own
   separate toggle button, not part of it) - one shared rule, so there's
   only one place that can drift out of sync. */
.sidebar__list > li > .sidebar__link,
.sidebar__group-link {
  color: var(--foreground);
  font-weight: 600;
}
.sidebar__link[aria-current="page"] {
  color: var(--foreground);
  font-weight: 600;
  background: var(--muted);
}

/* --- Breadcrumb --- */
.breadcrumb {
  margin-bottom: var(--space-md);
  font-size: 0.875rem;
  color: var(--muted-foreground);
}
.breadcrumb__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
}
.breadcrumb__list li:not(:last-child)::after {
  content: "/";
  margin-left: var(--space-xs);
  color: var(--border-strong);
}
.breadcrumb__list a { text-decoration: none; }
.breadcrumb__list a:hover { text-decoration: underline; }

/* --- On-page "On this page" jump list (static, no scroll-spy) ---
   A narrow right-rail column at desktop width (--breakpoint-lg+);
   hidden below that - see .doc-layout--has-toc above. No background/
   border box (matches the minimal, no-decoration language callouts and
   the sidebar group headings also use) - just a heading with a thin
   bottom-border divider, same treatment as .sidebar__group-heading, at
   a smaller/muted scale appropriate to a page-local aid rather than a
   root nav peer. */
.page-toc {
  margin-bottom: var(--space-lg);
}
.page-toc__heading {
  margin: 0 0 var(--space-sm);
  padding-bottom: var(--space-xs);
  border-bottom: 1px solid var(--border);
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--muted-foreground);
}
.page-toc__list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.page-toc__item { font-size: 0.9375rem; padding: var(--space-xs) 0; }
.page-toc__item--h3 { padding-left: var(--space-md); }
.page-toc__item a { display: block; color: var(--foreground); text-decoration: none; }
.page-toc__item a:hover { text-decoration: underline; }

/* --- Related topics ---
   Bottom-of-page nav for subpages that have no sidebar entry of their own
   (tutorials/accounting/*, setup-guides/accounting/*, tutorials/accounting/
   ledger-management/* - see tools/add-related-topics-nav.js). A plain,
   non-sequential list of sibling pages in the same folder, not a Prev/Next:
   CLAUDE.md documents that a literal Prev/Next was removed on purpose,
   since the only sibling order available (alphabetical) isn't a curated
   reading order and Prev/Next visually implies one. Sits inside
   .doc-content-wrapper (after </article>, so it's outside data-pagefind-body
   and never indexed), same heading treatment as .page-toc__heading above. */
.related-topics {
  margin-top: var(--space-lg);
  padding-top: var(--space-md);
  border-top: 1px solid var(--border);
}
.related-topics__heading {
  margin: 0 0 var(--space-sm);
  padding-bottom: var(--space-xs);
  border-bottom: 1px solid var(--border);
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--muted-foreground);
}
.related-topics__list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: var(--space-xs) var(--space-md);
  list-style: none;
  margin: 0;
  padding: 0;
}
.related-topics__list a {
  display: block;
  color: var(--foreground);
  text-decoration: none;
  font-size: 0.9375rem;
}
.related-topics__list a:hover { text-decoration: underline; }
/* The "Learn More" footer block (tools/convert-learn-more.js): the same
   compact look as bos-ent-docs' curated "Related Topics" block (small grey
   heading, smaller rows, outside <article> so search doesn't index the
   same link list on every page), but one row per topic in a single
   column, each row "Topic: short description" with the description muted. */
.related-topics__rows {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
  gap: var(--space-xs) var(--space-lg);
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 0.875rem;
  line-height: 1.5;
}
.related-topics__rows--single { grid-template-columns: 1fr; }
.related-topics__rows a {
  color: var(--foreground);
  font-weight: 600;
  text-decoration: none;
}
.related-topics__rows a:hover { text-decoration: underline; }
.related-topics__note { color: var(--muted-foreground); }

/* --- Feedback modal ---
   Trigger is the "Feedback" button in the header (site.css
   .site-header__feedback above) - always visible, every page. Opens
   directly to the form if text was already selected on the page;
   otherwise opens to a prompt (.feedback-prompt) suggesting the user
   select the relevant text first, or continue without it. */
.feedback-modal {
  width: min(32rem, calc(100vw - 2 * var(--space-md)));
  max-height: min(85vh, 42rem);
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: var(--background);
  color: var(--foreground);
}
.feedback-modal::backdrop {
  background: rgba(0, 0, 0, 0.5);
}
.feedback-modal__header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-md);
  padding: var(--space-lg) var(--space-lg) 0;
}
.feedback-modal__header h2 { margin: 0; font-size: 1.25rem; }
.feedback-prompt {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  padding: var(--space-md) var(--space-lg) var(--space-lg);
}
.feedback-prompt p { margin: 0; color: var(--muted-foreground); }
.feedback-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  padding: var(--space-md) var(--space-lg) var(--space-lg);
  overflow-y: auto;
}
/* The plain [hidden] attribute needs an explicit rule here: an author
   stylesheet's own `display` declaration always wins over the
   UA stylesheet's default `[hidden] { display: none }`, regardless of
   selector specificity or source order - so without this, toggling
   .hidden in JS (feedback-prompt/feedback-form/a .form-group) would do
   nothing visually, since .feedback-prompt/.feedback-form/.form-group
   above already set their own `display`. */
.feedback-prompt[hidden],
.feedback-form[hidden],
.form-group[hidden] {
  display: none;
}
.feedback-modal__close {
  flex-shrink: 0;
  width: 2rem;
  height: 2rem;
  border: 0;
  background: transparent;
  color: var(--muted-foreground);
  font-size: 1.25rem;
  line-height: 1;
  cursor: pointer;
  border-radius: 4px;
}
.feedback-modal__close:hover,
.feedback-modal__close:focus-visible { background: var(--muted); color: var(--foreground); }

.form-honeypot { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form-group { display: flex; flex-direction: column; gap: var(--space-xs); }
.form-group label { font-size: 0.875rem; font-weight: 600; }
.form-group .required { color: var(--destructive); }
.form-group input,
.form-group textarea {
  padding: var(--space-sm);
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  background: var(--background);
  color: var(--foreground);
  font: inherit;
  resize: vertical;
}
.form-group input[readonly] { color: var(--muted-foreground); background: var(--muted); }

.feedback-form__actions {
  display: flex;
  gap: var(--space-sm);
}
.feedback-status {
  margin: 0;
  font-size: 0.875rem;
  color: var(--muted-foreground);
  min-height: 1.25em;
}
.feedback-status--success { color: var(--foreground); font-weight: 600; }
.feedback-status--error { color: var(--destructive); }

/* --- Image lightbox ---
   Clicking any doc-content figure image (assets/js/main.js) opens it
   here at full/native size - images are scaled down to the content
   column's width in place (see content.css .doc-content figure img),
   so this is how a reader gets back to a legible full-size view. A
   <dialog> built once and reused for every click, same pattern as the
   feedback modal: showModal() gives focus-trapping/top-layer/Escape for
   free, and backdrop-click-to-close needs one manual listener. */
.lightbox {
  padding: 0;
  border: 0;
  background: transparent;
  max-width: 95vw;
  max-height: 95vh;
}
.lightbox::backdrop {
  background: rgba(0, 0, 0, 0.85);
}
.lightbox img {
  display: block;
  max-width: 95vw;
  max-height: 95vh;
  width: auto;
  height: auto;
  cursor: zoom-out;
}

/* --- Search (header box - submits to /search/) --- */
.site-search { flex: 1; min-width: 0; max-width: 26rem; margin: 0; }
.site-search__input {
  width: 100%;
  padding: var(--space-xs) var(--space-sm);
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  background: var(--background);
  color: var(--foreground);
  font: inherit;
}

/* --- Search results page (/search/) ---
   Two columns; stacked (results first) at phone width - see "Phone
   width" below. */
.doc-layout.search-layout {
  grid-template-columns: 14rem minmax(0, 1fr);
}
.search-filters__heading {
  font-size: 1rem;
  font-weight: 700;
  margin: 0 0 var(--space-sm);
}
.search-filters__list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.search-filters__item label {
  display: flex;
  align-items: baseline;
  gap: var(--space-xs);
  padding: var(--space-xs) 0;
  cursor: pointer;
  font-size: 0.9375rem;
}
.search-filters__label { flex: 1; }
.search-filters__count { color: var(--muted-foreground); font-size: 0.8125rem; }
/* Group labels between the category checkboxes - the same groups as the
   sidebar, so 39 categories stay scannable. Deliberately monochrome, not
   --accent (whose uses are limited to three places - see Stylesheet.md). */
.search-filters__group-heading {
  margin: var(--space-md) 0 var(--space-xs);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted-foreground);
}
.search-filters__group-heading:first-child { margin-top: 0; }
.search-filters__item--empty .search-filters__label,
.search-filters__item--empty .search-filters__count {
  color: var(--muted-foreground);
  opacity: 0.6;
}

.search-heading { margin-bottom: var(--space-xs); }
.search-toolbar {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-sm);
  margin-bottom: var(--space-lg);
}
.search-status { color: var(--muted-foreground); }
.search-sort {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: 0.875rem;
  color: var(--muted-foreground);
  flex-shrink: 0;
}
.search-sort select {
  padding: var(--space-xs) var(--space-sm);
  border: 1px solid var(--border-strong);
  border-radius: 4px;
  background: var(--background);
  color: var(--foreground);
  font: inherit;
  font-size: 0.875rem;
}

.search-results-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}
.search-result-card {
  display: block;
  padding: var(--space-md);
  border: 1px solid var(--border);
  border-radius: 6px;
  text-decoration: none;
  color: inherit;
}
.search-result-card:hover,
.search-result-card:focus-visible {
  border-color: var(--border-strong);
  background: var(--muted);
}
.search-result-card__title {
  font-size: 1.0625rem;
  font-weight: 600;
  color: var(--foreground);
  margin: 0 0 var(--space-xs);
}
.search-result-card__url {
  display: block;
  font-size: 0.8125rem;
  color: var(--muted-foreground);
  margin-bottom: var(--space-xs);
}
.search-result-card__excerpt {
  font-size: 0.9375rem;
  color: var(--muted-foreground);
  line-height: 1.5;
  margin: 0;
}
.search-result-card__excerpt mark {
  background: none;
  color: var(--foreground);
  font-weight: 700;
}

/* --- Buttons --- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-sm);
  padding: 0.75rem 1.5rem;
  border-radius: 4px;
  font-weight: 600;
  font-family: var(--font-body);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
}
.btn-primary { background: var(--primary); color: var(--primary-foreground); }
.btn-primary:hover { background: var(--primary-dark); }
/* A button-styled link inside an article (e.g. the 404 page's "Go to the
   documentation home page") must not pick up content.css's link colour -
   that made its text the same colour as the button. */
.doc-content a.btn { text-decoration: none; }
.doc-content a.btn-primary,
.doc-content a.btn-primary:hover { color: var(--primary-foreground); }
.btn-outline { background: transparent; border-color: var(--border-strong); color: var(--foreground); }
.btn-outline:hover { border-color: var(--primary); }

/* --- Footer ---
   Just the copyright line - the old Browse/Contact/blurb columns were
   superfluous (this page's own header/sidebar already cover finding
   things and reporting an issue) and were removed. */
.site-footer {
  background: var(--background-alt);
  margin-top: var(--space-xl);
  border-top: 1px solid var(--border);
}
.site-footer__bottom {
  padding-block: var(--space-sm);
  padding-inline: var(--space-md);
  font-size: 0.875rem;
  color: var(--muted-foreground);
  max-width: 1280px;
  margin-inline: auto;
}

/* --- Menu toggle + collapsible sidebar ---
   The header's menu (hamburger) button shows/hides the sidebar
   (assets/js/main.js). Two modes, split at 900px:
   - Wide (900px+): the sidebar is a grid column, shown by default. The
     button collapses it (html.sidebar-collapsed, remembered in
     localStorage and applied before first paint by the <head> script),
     giving the content the full width.
   - Compact (under 900px - phones, portrait tablets, a narrowed desktop
     window): the sidebar is hidden by default and the button slides it
     in as a drawer over the content (html.sidebar-open, not remembered),
     with a backdrop that closes it. --header-height is set from the
     header's real height by main.js in this mode, since the phone header
     wraps onto two rows. */
.menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  margin-inline-start: calc(var(--space-sm) * -1);
  border: 0;
  border-radius: 4px;
  background: transparent;
  cursor: pointer;
  color: var(--foreground);
  flex-shrink: 0;
}
@media (hover: hover) {
  .menu-toggle:hover { background: var(--muted); }
}
.menu-toggle svg { width: 1.5rem; height: 1.5rem; }
/* Logo stays next to the menu button; the actions keep to the right. */
.site-header__logo { margin-inline-end: auto; }

@media (min-width: 900px) {
  .sidebar-collapsed .doc-layout:not(.search-layout) {
    grid-template-columns: minmax(0, 1fr);
  }
  .sidebar-collapsed .sidebar { display: none; }
}
@media (min-width: 1100px) {
  .sidebar-collapsed .doc-layout--has-toc {
    grid-template-columns: minmax(0, 1fr) var(--toc-width);
  }
  .sidebar-collapsed .doc-layout--has-toc .page-toc { grid-column: 2; }
}

.sidebar-backdrop {
  position: fixed;
  inset: var(--header-height) 0 0 0;
  z-index: 14;
  background: rgba(0, 0, 0, 0.4);
}

@media (max-width: 899.98px) {
  .doc-layout:not(.search-layout) { grid-template-columns: minmax(0, 1fr); }
  .sidebar {
    position: fixed;
    top: var(--header-height);
    bottom: 0;
    left: 0;
    z-index: 15;
    width: min(20rem, 85vw);
    max-height: none;
    padding: 0 var(--space-md) var(--space-lg);
    background: var(--background);
    border-right: 1px solid var(--border);
    overscroll-behavior: contain;
    transform: translateX(-100%);
    visibility: hidden;
    transition: transform 0.2s ease, visibility 0s linear 0.2s;
  }
  .sidebar-open .sidebar {
    transform: none;
    visibility: visible;
    transition: transform 0.2s ease;
  }
  .sidebar-open body { overflow: hidden; }
}
@media (prefers-reduced-motion: reduce) {
  .sidebar, .sidebar-open .sidebar { transition: none; }
}

/* --- Phone width (under 600px) ---
   The header wraps: menu button, logo, Feedback and theme toggle on the
   first row, the search box full width on the second (the actions
   wrapper steps aside with display: contents so its children can be
   placed individually). Search results come before the filters. */
@media (max-width: 599.98px) {
  .site-header__inner {
    flex-wrap: wrap;
    height: auto;
    column-gap: var(--space-sm);
    row-gap: var(--space-sm);
    padding-block: var(--space-sm);
  }
  .site-header__actions { display: contents; }
  .site-header__logo img { height: 2rem; }
  .site-search { order: 1; flex: 1 1 100%; max-width: none; }
  /* The language link shares the search row, so the first row still fits. */
  .site-header__inner:has(.lang-switch) .site-search { flex-basis: calc(100% - 5.5rem); }
  .lang-switch { order: 2; }
  .btn.site-header__feedback { padding-inline: var(--space-sm); }
  .doc-layout { padding-block: var(--space-md); }
  .doc-layout.search-layout { grid-template-columns: minmax(0, 1fr); }
  .search-layout .search-filters { order: 1; }
}

/* ============================================
   5. UTILITIES
   ============================================ */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.text-center { text-align: center; }
