:root {
  color-scheme: light dark;
  --bg: #ffffff;
  --bg-raised: #ffffff;
  --bg-alt: #f4f6f3;
  --bg-tint: #eef2ec;
  --text: #1a1f19;
  --muted: #5c6a5b;
  --border: #dbe3d6;
  --border-strong: #c3cebd;
  --accent: #256b3f;
  --accent-strong: #1c522f;
  --accent-soft: #e8f3ec;
  --needs-review: #92400e;
  --needs-review-bg: #fef3c7;
  --approved: #166534;
  --approved-bg: #dcfce7;
  --danger: #b91c1c;
  --btn-bg: #256b3f;
  --btn-text: #ffffff;
  --shadow-sm: 0 1px 2px rgba(20, 30, 20, 0.06);
  --shadow-md: 0 2px 10px rgba(20, 30, 20, 0.07), 0 1px 3px rgba(20, 30, 20, 0.06);
  --radius: 12px;
  --radius-sm: 8px;
  /* Width of the left navigation rail -- referenced by .site-rail itself and used to size
   * the mobile icon-only collapse (see the @media block near the end of this file). Narrow
   * because rail items stack icon-over-label rather than icon-beside-label. */
  --rail-w: 6rem;
  --code-bg: #eef4ee;
  --code-text: #163b23;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #141712;
    --bg-raised: #1b1f19;
    --bg-alt: #1e2319;
    --bg-tint: #212a1d;
    --text: #ecf1e8;
    --muted: #a3ad9c;
    --border: #333c2c;
    --border-strong: #445138;
    --accent: #7fd08a;
    --accent-strong: #9ee0a6;
    --accent-soft: #1e2f22;
    --needs-review: #fbbf24;
    --needs-review-bg: #3a2c0c;
    --approved: #7fd08a;
    --approved-bg: #17301f;
    --danger: #f87171;
    --btn-bg: #3d8a4a;
    --shadow-sm: none;
    --shadow-md: none;
    --code-bg: #182417;
    --code-text: #bfe8c8;
  }
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  font-family: -apple-system, "Segoe UI", "Inter", Helvetica, Arial, sans-serif;
  display: flex;
  align-items: flex-start;
  min-height: 100vh;
  margin: 0;
  padding: 0;
  line-height: 1.55;
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
}

/* The old body's max-width/centering/padding, moved onto the content column now that
 * body itself is a flex row (rail + this). Every page's own markup is unaffected -- it
 * just renders inside this instead of directly inside body. */
.site-main {
  /* flex-basis: 0% (not the shorthand's default `auto`) -- `auto` derives an initial main
   * size from content/max-width before growing/shrinking, which left stray auto-margin
   * room even on viewports narrower than max-width (the bug behind the rail/content gap).
   * 0% makes it grow purely to fill the available track, so `margin: 0 auto` below only
   * ever centers the max-width box once the viewport is wide enough to actually have
   * leftover space to center within -- zero gap below that, a normal centered column
   * above it. */
  flex: 1 1 0%;
  min-width: 0;
  max-width: 1180px;
  margin: 0 auto;
  padding: 1.75rem 1.5rem 4rem;
}

/* ---- Left navigation rail ----
 * Replaces the old horizontal top nav. Sticky/full-height so it stays put while the
 * content column scrolls. Icons are hand-drawn inline SVGs (currentColor stroke, so
 * hover/active states recolor them for free) -- see base.html for the markup. */
.site-rail {
  flex: 0 0 var(--rail-w);
  width: var(--rail-w);
  position: sticky;
  top: 0;
  height: 100vh;
  /* No overflow-y here on purpose: setting only overflow-y (leaving overflow-x at its
   * default `visible`) makes the browser compute overflow-x as `auto` too, which clips
   * the flyout .dropdown panels (position: absolute; left: 100%) that need to render
   * outside this box. The rail's own item list (5 fixed entries) never needs to scroll,
   * so there's nothing to trade off by leaving overflow visible. */
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  padding: 1.1rem 0.9rem;
  background: var(--bg);
  border-right: 1px solid var(--border);
  z-index: 10;
}

/* Stacked icon-over-wordmark, same shape as the nav tiles below it (see .nav-item > a) --
 * a side-by-side icon+text row doesn't fit the rail's width now that it's sized for
 * stacked tiles instead of icon-beside-label rows. */
.site-rail .brand {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
  text-align: center;
  text-decoration: none;
  color: var(--text);
  font-weight: 700;
  font-size: 0.78rem;
  padding: 0.4rem 0.3rem 1rem;
  margin-bottom: 0.5rem;
  border-bottom: 1px solid var(--border);
}
.site-rail .brand:hover { color: var(--accent-strong); }
.brand-mark { flex: 0 0 auto; color: var(--accent); }

.rail-items {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}

.rail-account {
  margin-top: auto;
  padding-top: 0.75rem;
  border-top: 1px solid var(--border);
}

/* ---- Nav dropdowns (Analytes / Platforms / Clinical / Admin / Account) ----
 * Dependency-free hover/focus menus: .dropdown is positioned absolutely to the right of
 * its .nav-item and hidden until that ancestor is hovered or has focus-within (keyboard
 * nav), matching the rest of the site's no-JS approach (see the tab-panel radio-hack
 * below). Same mechanism as the old top-nav dropdowns, just opening rightward instead of
 * downward to fit a vertical rail. */
.nav-item {
  position: relative;
  display: block;
}
/* Icon above label, centered -- narrower than an icon+label row, so the rail can be
 * narrower too (see --rail-w). Label text is truncated to one line (relevant for the
 * account item, whose label is an arbitrary user name rather than a fixed short word). */
.nav-item > a {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  text-decoration: none;
  font-weight: 600;
  font-size: 0.7rem;
  color: var(--muted);
  padding: 0.55rem 0.3rem;
  border-radius: var(--radius-sm);
  transition: background 0.15s ease, color 0.15s ease;
}
.nav-item > a:hover,
.nav-item > a:focus-visible { color: var(--accent-strong); background: var(--accent-soft); }
.rail-icon { flex: 0 0 auto; }
.nav-item > a span {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.rail-login {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3rem;
  text-decoration: none;
  font-weight: 600;
  font-size: 0.7rem;
  color: var(--muted);
  padding: 0.55rem 0.3rem;
  border-radius: var(--radius-sm);
}
.rail-login:hover { color: var(--accent-strong); background: var(--accent-soft); }
.dropdown {
  display: none;
  position: absolute;
  /* Flush against the nav item (no margin gap) so the mouse never crosses a dead zone
   * between the link and the menu -- that gap was outside .nav-item's hoverable box (which
   * is sized by the link's normal-flow content, not the absolutely-positioned dropdown),
   * so the menu closed the instant the cursor left the link before reaching it. The visual
   * gap that used to come from margin is recreated with a transparent padding strip
   * instead, which *is* part of the dropdown's own hoverable box -- now on the left side
   * since the flyout opens rightward, not downward. */
  top: 0;
  left: 100%;
  padding-left: 0.5rem;
  min-width: 13rem;
  z-index: 20;
}
/* The account item is pinned to the bottom of the rail (.rail-account's margin-top:auto),
 * so a `top: 0` flyout would grow downward past the viewport edge -- worse the longer the
 * logged-in user's email wraps. Anchor this one flyout's bottom to the item's bottom
 * instead, so it grows upward and always stays on screen regardless of content height. */
.rail-account .dropdown {
  top: auto;
  bottom: 0;
}
.dropdown-panel {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.4rem;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
}
.nav-item:hover .dropdown,
.nav-item:focus-within .dropdown {
  display: block;
}
.dropdown a {
  padding: 0.45rem 0.6rem;
  border-radius: var(--radius-sm);
  font-size: 0.88rem;
  font-weight: 500;
  white-space: nowrap;
}
.dropdown-empty {
  padding: 0.45rem 0.6rem;
  font-size: 0.85rem;
  color: var(--muted);
}
.link-button {
  display: block;
  width: 100%;
  text-align: left;
  padding: 0.45rem 0.6rem;
  border-radius: var(--radius-sm);
  font-size: 0.88rem;
  font-weight: 500;
  background: none;
  border: none;
  color: var(--text);
}
.link-button:hover { color: var(--accent-strong); background: var(--accent-soft); filter: none; }

h1, h2, h3, h4 { line-height: 1.25; letter-spacing: -0.01em; }
h1 { font-size: 1.85rem; margin-bottom: 0.35rem; }
h2 { font-size: 1.3rem; margin-top: 2.5rem; }
h3 { font-size: 1.08rem; }
h4 { font-size: 0.92rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); margin-bottom: 0.5rem; }

a { color: var(--accent); }

table { border-collapse: collapse; width: 100%; margin: 1rem 0; font-size: 0.93rem; }
th, td { border: 1px solid var(--border); padding: 0.55rem 0.7rem; text-align: left; vertical-align: top; }
th { background: var(--bg-alt); font-weight: 600; font-size: 0.85rem; }
table.plain { border: none; }
table.plain th, table.plain td { border: none; border-bottom: 1px solid var(--border); }

/* Click-to-sort table headers (see sortable-table.js): th.sortable-col shows a muted
 * "unsorted" arrow that hover-highlights, and lights up accent-colored once its column is
 * the active sort. */
th.sortable-col {
  cursor: pointer;
  user-select: none;
}
th.sortable-col:hover { color: var(--accent-strong); }
th.sortable-col .sort-arrow {
  display: inline-block;
  margin-left: 0.35rem;
  font-size: 0.75rem;
  color: var(--muted);
}
th.sortable-col.sort-active { color: var(--accent-strong); }
th.sortable-col.sort-active .sort-arrow { color: var(--accent-strong); }

.badge {
  display: inline-block;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
.badge.needs_review { background: var(--needs-review-bg); color: var(--needs-review); }
.badge.approved { background: var(--approved-bg); color: var(--approved); }

/* A source PDF link a visitor/read-less user can't open -- copyright, see
 * docs/ARCHITECTURE.md's permissions section. Greyed out and inert, not a real link. */
.doc-link-disabled {
  color: var(--muted);
  cursor: not-allowed;
  text-decoration: line-through;
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.25rem 0.65rem;
  border-radius: 999px;
  font-size: 0.78rem;
  font-weight: 600;
  background: var(--bg-tint);
  color: var(--text);
  border: 1px solid var(--border);
}
.chip .chip-label { color: var(--muted); font-weight: 500; }

/* A .chip that's also a link (e.g. condition tags under Clinical utility, clinical-area
 * pills on the /clinical index) -- same pill shape, but with a hover/focus state so it
 * reads as clickable. */
a.chip-link {
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
a.chip-link:hover {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent-strong);
}

.chip-row { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.6rem 0; }

.card, .panel {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.25rem 1.4rem;
  margin: 1.1rem 0;
  background: var(--bg-raised);
  box-shadow: var(--shadow-sm);
}

.muted { color: var(--muted); font-size: 0.9rem; }

form.inline { display: inline; }

button, input[type=submit] {
  font: inherit;
  font-weight: 600;
  padding: 0.45rem 1rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--btn-bg);
  background: var(--btn-bg);
  color: var(--btn-text);
  cursor: pointer;
  transition: filter 0.15s ease, transform 0.05s ease;
}
button:hover, input[type=submit]:hover { filter: brightness(1.08); }
button:active { transform: translateY(1px); }
button.secondary { background: var(--bg-raised); color: var(--btn-bg); }
button.danger { background: var(--bg-raised); color: var(--danger); border-color: var(--danger); }
button.ghost { background: transparent; color: var(--muted); border-color: var(--border); font-weight: 600; }
button.small, .btn-row button { padding: 0.3rem 0.75rem; font-size: 0.82rem; }

.search-box { display: flex; gap: 0.5rem; margin: 1rem 0 1.5rem; }
.search-box input[type=text] {
  padding: 0.55rem 0.85rem;
  font: inherit;
  width: 22rem;
  max-width: 100%;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-raised);
  color: var(--text);
}

.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; }
@media (max-width: 800px) { .grid-2 { grid-template-columns: 1fr; } }

/* ---- Homepage ---- */

.stat-grid {
  display: grid;
  /* Fixed column count rather than auto-fit -- auto-fit reflows unpredictably as the
   * window resizes (e.g. 7-then-1 on a wide window); a fixed 4 keeps the arrangement
   * stable and wraps evenly at 4x2 for today's 8 tiles. */
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
  margin: 1.5rem 0;
}
@media (max-width: 800px) {
  .stat-grid { grid-template-columns: repeat(2, 1fr); }
}
.stat-tile {
  display: block;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-raised);
  box-shadow: var(--shadow-sm);
  padding: 1.1rem 1.3rem;
  text-align: center;
  text-decoration: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.stat-tile:hover { border-color: var(--accent); box-shadow: var(--shadow-md); }
.stat-tile .stat-number { font-size: 1.8rem; font-weight: 700; color: var(--accent-strong); }
.stat-tile .stat-label { color: var(--muted); font-size: 0.85rem; margin-top: 0.2rem; }

.home-links {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1.5rem;
  margin: 1.5rem 0;
}
a.card.home-link {
  display: block;
  text-decoration: none;
  color: inherit;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
a.card.home-link:hover { border-color: var(--accent); box-shadow: var(--shadow-md); }
a.card.home-link h3 { margin-top: 0; color: var(--accent); }
a.card.home-link p { margin-bottom: 0; }

.announcements { display: flex; flex-direction: column; gap: 0.75rem; margin: 1rem 0 1.5rem; }
.announcement {
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent);
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  padding: 0.8rem 1.1rem;
}
.announcement-date {
  display: inline-block;
  color: var(--muted);
  font-size: 0.85rem;
  font-weight: 600;
  margin-right: 0.6rem;
}

pre.source-text {
  white-space: pre-wrap;
  max-height: 32rem;
  overflow-y: auto;
  background: var(--bg-alt);
  padding: 0.75rem;
  border-radius: var(--radius-sm);
  font-size: 0.8rem;
}

.markdown-box {
  width: 100%;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.85rem;
  line-height: 1.5;
  padding: 0.75rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  resize: vertical;
  background: var(--bg-raised);
  color: var(--text);
}

.revision-list {
  list-style: none;
  padding: 0;
}
.revision-list li {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.85rem;
  margin-bottom: 0.6rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  background: var(--bg-raised);
}

/* ---- Method comparison cards ---- */

.method-card {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.4rem 1.5rem;
  margin: 1.1rem 0;
  background: var(--bg-raised);
  box-shadow: var(--shadow-md);
  /* Each card is also a tree-nav anchor target (id="method-N"). Without this, jumping
   * to one via the tree nav lands its top flush at the viewport top, under the sticky
   * .analyte-sticky-header column -- hiding its title. scroll-margin-top tells the
   * browser's own anchor-scroll/scrollIntoView to stop short by this much instead. Now
   * that nav is a left rail rather than a horizontal top bar, there's nothing to clear
   * but a small comfortable gap. */
  scroll-margin-top: 1.25rem;
}

/* Title (with the fold arrow, when folded -- see below) on its own line, left-aligned;
 * the chip row wraps on the line below rather than sharing the title's line -- avoids
 * the two competing for space on one row at any card width. */
.method-card-header {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.5rem;
  margin-bottom: 0.25rem;
}
.method-card-header h3 { margin: 0; }
.method-card-header h3 a { color: var(--text); text-decoration: none; }
.method-card-header h3 a:hover { color: var(--accent); }

/* .method-card is now also a <details> (method-section) so each method's body can be
 * folded -- open by default. The header (.method-card-header) doubles as its <summary>.
 * The fold arrow lives on h3::before (not the summary itself) so it sits directly next
 * to the title text on the same line, rather than competing as its own flex item. */
.method-section > summary.method-card-header {
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.method-section > summary.method-card-header::-webkit-details-marker { display: none; }
.method-card-header h3::before {
  content: "▾";
  display: inline-block;
  color: var(--muted);
  font-size: 0.8rem;
  margin-right: 0.4rem;
}
.method-section:not([open]) > summary.method-card-header h3::before { content: "▸"; }

/* ---- Method/product tab: method list + "on this page" tree nav ----
 * DOM order in analyte_detail.html is unchanged (.toc-nav's markup still comes
 * first, preserving today's reading/landmark order for assistive tech) -- the *visual*
 * flip to the right is done with `order` alone, which grid auto-placement honors, so no
 * template diff is needed. */
.toc-layout {
  display: grid;
  grid-template-columns: 1fr 13rem;
  gap: 2rem;
  align-items: start;
}
/* Grid items default to min-width: auto -- i.e. never narrower than their content's
 * intrinsic min-content size. Wide content here (the equation block, interference
 * table) has its own overflow-x: auto specifically so IT scrolls instead of forcing
 * this column wider, but that only kicks in once the column itself is actually
 * constrained -- without min-width: 0, the grid track grows to fit anyway, pushing the
 * whole page wider than the column next to it. */
.toc-content { order: 1; min-width: 0; }
.toc-nav {
  /* A plain <div>, not <nav> -- the site's unscoped `nav {}` rule would otherwise cascade
   * onto any bare <nav> element and fight with the rules below. */
  order: 2;
  position: sticky;
  top: 1.25rem;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 0.9rem;
  font-size: 0.85rem;
  padding-left: 0.75rem;
  border-left: 1px solid var(--border);
}
.toc-link {
  display: block;
  font-weight: 600;
  color: var(--text);
  text-decoration: none;
}
.toc-link:hover { color: var(--accent); }
.toc-sublist {
  list-style: none;
  margin: 0.3rem 0 0;
  padding-left: 0.7rem;
  border-left: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.toc-sublist a { color: var(--muted); text-decoration: none; }
.toc-sublist a:hover { color: var(--accent); }

@media (max-width: 800px) {
  .toc-layout { grid-template-columns: 1fr; }
  .toc-nav {
    /* Both columns are full-width stacked blocks at this width -- put the tree nav back
     * above the list (order: -1) so it reads as a quick-jump strip before the content,
     * same as its pre-redesign left-side position did. */
    order: -1;
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0.4rem 1.2rem;
    border-left: none;
    border-bottom: 1px solid var(--border);
    padding-left: 0;
    padding-bottom: 0.9rem;
    margin-bottom: 0.5rem;
  }
  .toc-sublist { flex-direction: row; flex-wrap: wrap; gap: 0.2rem 0.7rem; border-left: none; padding-left: 0; margin-left: 0.4rem; }
}

/* A reaction equation ("A + B --enzyme--> C + D"), or a coupled group of them, set off
 * from surrounding prose: monospace, bold, tinted box, sized to its content rather than
 * spanning the full card width. Produced by the `reactionFormat` filter. */
.equation-block {
  display: inline-block;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-weight: 700;
  font-size: 0.85rem;
  line-height: 1.7;
  background: var(--code-bg);
  color: var(--code-text);
  border-radius: var(--radius-sm);
  padding: 0.6rem 0.9rem;
  margin: 0.5rem 0;
  max-width: 100%;
  overflow-x: auto;
  white-space: pre;
}

/* The plain-language line(s) that follow an equation-block, rendered in the normal body
 * font so they read as prose rather than code. */
p.eq-desc {
  margin: 0.4rem 0;
}

/* reaction_procedure, rendered by the stepListFormat filter -- one step per <li> instead of
 * a single dense paragraph, so a multi-step procedure stays skimmable. */
ol.step-list {
  margin: 0.5rem 0 1rem;
  padding-left: 1.4rem;
}
ol.step-list > li {
  margin-bottom: 0.55rem;
  padding-left: 0.3rem;
}

.bullet-list {
  list-style: none;
  padding: 0;
  margin: 0.5rem 0 1rem;
}
.bullet-list > li {
  position: relative;
  padding-left: 1.1rem;
  margin-bottom: 0.55rem;
}
.bullet-list > li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--accent);
}
.bullet-list > li strong { color: var(--text); }

ul.plain-list { margin: 0.4rem 0 1rem; padding-left: 1.2rem; }
ul.plain-list li { margin-bottom: 0.3rem; }

/* A .plain-list nested inside another .plain-list's <li> -- used by the immunoassay
 * "Assay design" bead/antibody/buffer tree (see analyte_detail.html) so each reagent's own
 * facts (host, clonality, composition, ...) read as sub-bullets instead of table cells.
 * Tighter than the outer list's default UA nesting so 2-3 short facts don't sprawl. */
ul.plain-list ul.plain-list { margin: 0.2rem 0 0.5rem; padding-left: 1.1rem; }
ul.plain-list ul.plain-list li { margin-bottom: 0.15rem; }

/* Interference substance names, colored by how confident the source insert is: a stated
 * effect (red), hedged/theoretical language (amber), or explicitly ruled out (green) --
 * reuses the same three colors as the review-status badges. */
.interferent-known { color: var(--danger); font-weight: 700; }
.interferent-suspected { color: var(--needs-review); font-weight: 700; }
.interferent-none { color: var(--approved); font-weight: 700; }

h5.interference-subhead {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 0.9rem 0 0.35rem;
  display: flex;
  align-items: center;
  gap: 0.4rem;
}
h5.interference-subhead::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 999px;
  display: inline-block;
}
h5.interference-subhead.known { color: var(--danger); }
h5.interference-subhead.known::before { background: var(--danger); }
h5.interference-subhead.suspected { color: var(--needs-review); }
h5.interference-subhead.suspected::before { background: var(--needs-review); }
h5.interference-subhead.none { color: var(--approved); }
h5.interference-subhead.none::before { background: var(--approved); }

details.more-details {
  margin-top: 0.9rem;
  border-top: 1px solid var(--border);
  padding-top: 0.6rem;
}
details.more-details > summary {
  cursor: pointer;
  font-weight: 600;
  font-size: 0.88rem;
  color: var(--accent);
  list-style: none;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  user-select: none;
}
details.more-details > summary::-webkit-details-marker { display: none; }
details.more-details > summary::before {
  content: "▸";
  display: inline-block;
  transition: transform 0.15s ease;
  font-size: 0.75rem;
}
details.more-details[open] > summary::before { transform: rotate(90deg); }
details.more-details > summary:hover { color: var(--accent-strong); }
details.more-details .details-body { padding-top: 0.9rem; }

.method-card-meta {
  margin-top: 1rem;
  padding-top: 0.75rem;
  border-top: 1px solid var(--border);
}

/* ---- Highlights callout ---- */

.callout {
  border-radius: var(--radius);
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent);
  background: var(--accent-soft);
  padding: 1.1rem 1.4rem;
  margin: 1.1rem 0 1.75rem;
}
.callout h2 { margin-top: 0; }
.callout .bullet-list > li::before { background: var(--accent-strong); }
.callout-empty {
  border-radius: var(--radius);
  border: 1px dashed var(--border-strong);
  padding: 1rem 1.25rem;
  margin: 1.1rem 0 1.75rem;
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

/* ---- Analyte page tabs (Overview / Method-product / Insight / Labs) ----
 * Dependency-free "radio-hack" tabs: no JS. The radio inputs, .analyte-sticky-header (which
 * contains .tab-bar), and .tab-panels are siblings (all direct children of .tabs) so the
 * :checked ~ sibling-combinator rules below can reach both the active label and the active
 * panel from each input -- through .analyte-sticky-header for the label, since .tab-bar
 * itself is now nested one level in (see .analyte-sticky-header below).
 *
 * .tabs is a 2-column grid: .analyte-sticky-header (name + vertical tab list) in column 1,
 * .tab-panels (the active panel's content) in column 2 -- mirroring a docs site's "section
 * heading, then flat sub-page list" sidebar pattern. This is a purely visual restyle; the
 * DOM order (radios, then header, then panels, all direct .tabs children) is unchanged, so
 * every :checked ~ rule below still matches exactly as before. */
.tabs {
  display: grid;
  grid-template-columns: 12rem 1fr;
  column-gap: 2.5rem;
  align-items: start;
}

.tab-input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

/* The analyte name (h1), LOINC line, and vertical tab list stick to the viewport top while
 * the active panel's content scrolls in the column next to it. No horizontal bar sits above
 * it anymore (nav is a left rail, not a top bar), so this is just a small comfortable gap,
 * not nav-clearance math. */
.analyte-sticky-header {
  position: sticky;
  top: 1.25rem;
}
.analyte-sticky-header h1 { font-size: 1.4rem; margin-bottom: 0.35rem; }

.tab-bar {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  margin: 1.1rem 0 0;
}

.tab-label {
  cursor: pointer;
  padding: 0.55rem 0.75rem;
  font-weight: 600;
  font-size: 0.92rem;
  color: var(--muted);
  border-left: 2px solid transparent;
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  user-select: none;
  transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
.tab-label:hover { color: var(--accent-strong); background: var(--accent-soft); }

.tab-panel { display: none; }

#tab-overview:checked ~ .analyte-sticky-header .tab-bar label[for="tab-overview"],
#tab-methods:checked ~ .analyte-sticky-header .tab-bar label[for="tab-methods"],
#tab-insight:checked ~ .analyte-sticky-header .tab-bar label[for="tab-insight"],
#tab-labs:checked ~ .analyte-sticky-header .tab-bar label[for="tab-labs"],
#tab-questions:checked ~ .analyte-sticky-header .tab-bar label[for="tab-questions"] {
  color: var(--accent);
  background: var(--accent-soft);
  border-left-color: var(--accent);
}

#tab-overview:checked ~ .tab-panels .panel-overview,
#tab-methods:checked ~ .tab-panels .panel-methods,
#tab-insight:checked ~ .tab-panels .panel-insight,
#tab-labs:checked ~ .tab-panels .panel-labs,
#tab-questions:checked ~ .tab-panels .panel-questions {
  display: block;
}

/* Overview tab: Clinical utility / How it's measured / Typical reference interval each get
 * their own bordered card (.overview-subcard, just an alias of the generic .card spacing/
 * shadow) instead of being stacked in one block -- a clear box boundary per section is more
 * scannable than relying on heading weight alone to separate them. */
.overview-subcard h3:first-child { margin-top: 0; }
/* Anchor targets for the Overview tab's "on this page" tree (see .toc-nav reused
 * in analyte_detail.html's panel-overview) -- lands the jump below the sticky tab rail's
 * top edge instead of flush against it. */
.overview-subcard h3,
#clinical-indication {
  scroll-margin-top: 1.25rem;
}

/* "## Family name" headings from reactionFormat (e.g. "Chemical Methods" vs "Enzymatic
 * Methods" under Overview -> How it's measured) -- a real section break, not the small
 * uppercase muted label the bare `h4` rule above uses for in-card subsections
 * (Interferences, Pre-analytical, ...). Colored left bar + background tint make it
 * scannable at a glance when skimming past several method families. */
h4.method-family-heading {
  font-size: 1.05rem;
  font-weight: 700;
  text-transform: none;
  letter-spacing: normal;
  color: var(--text);
  margin: 1.75rem 0 0.75rem;
  padding: 0.4rem 0.75rem;
  border-left: 4px solid var(--accent);
  background: var(--bg-tint);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  scroll-margin-top: 1.25rem;
}
h4.method-family-heading:first-child { margin-top: 0; }

/* "### Method name" sub-headings within a family (e.g. the three enzymatic creatinine
 * pathways under a "## Enzymatic Methods" heading) -- clearly bolder than body text and
 * indented/underlined to read as nested one level below the family heading above it. */
h5.overview-subhead {
  font-size: 0.98rem;
  font-weight: 700;
  color: var(--accent-strong);
  margin: 1.1rem 0 0.35rem 0.1rem;
  padding-bottom: 0.2rem;
  border-bottom: 1px solid var(--border);
  scroll-margin-top: 1.25rem;
}

/* Reference-interval tables (analyte_overviews.reference_interval_summary, rendered via
 * reactionFormat) -- wrapped so a wide table (many demographic groups) scrolls within
 * itself on narrow viewports instead of breaking the page's own horizontal layout. */
.table-scroll {
  overflow-x: auto;
  margin: 0.75rem 0;
}
.table-scroll table { margin: 0; }

.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
}

/* ---- Narrow-viewport collapse: rail + analyte tabs ----
 * Rail collapses to icon-only (text labels hidden) rather than an off-canvas drawer --
 * keeps it always visible with zero new JS/checkbox-hack machinery, narrow enough to leave
 * real room for content on a phone-width screen. Flyout submenus still work via tap/
 * :focus-within. The analyte page's vertical tab column reverts to a horizontal wrapping
 * bar stacked above its content, matching the pre-redesign mobile behavior. */
@media (max-width: 800px) {
  :root { --rail-w: 3.5rem; }

  .site-rail .brand span,
  .nav-item > a span,
  .rail-login span {
    display: none;
  }
  .site-rail .brand { justify-content: center; padding-left: 0; padding-right: 0; }

  .site-main { padding: 1.25rem 1rem 3rem; }

  .tabs { grid-template-columns: 1fr; }
  .analyte-sticky-header { position: static; top: auto; }
  .tab-bar {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0.3rem;
    border-bottom: 1px solid var(--border);
  }
  .tab-label {
    border-left: none;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    margin-bottom: -1px;
  }
  #tab-overview:checked ~ .analyte-sticky-header .tab-bar label[for="tab-overview"],
  #tab-methods:checked ~ .analyte-sticky-header .tab-bar label[for="tab-methods"],
  #tab-insight:checked ~ .analyte-sticky-header .tab-bar label[for="tab-insight"],
  #tab-labs:checked ~ .analyte-sticky-header .tab-bar label[for="tab-labs"],
  #tab-questions:checked ~ .analyte-sticky-header .tab-bar label[for="tab-questions"] {
    background: none;
    border-left-color: transparent;
    border-bottom-color: var(--accent);
  }
}

/* --- Self-assessment ------------------------------------------------------
 * Practice questions. Colours come only from the theme vars so the answered
 * state reads correctly in both light and dark. */
.question-stem { font-size: 1.05rem; margin: 1rem 0 1.2rem; }
.question-stem p:first-child { margin-top: 0; }

.question-figure {
  display: block;
  max-width: 100%;
  height: auto;
  margin: 1rem 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: #fff;
}

.option-list {
  list-style: none;
  margin: 0.8rem 0 1.2rem;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.option {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-raised);
  transition: border-color 0.15s ease, background 0.15s ease;
}
.option > label {
  display: flex;
  gap: 0.6rem;
  align-items: baseline;
  padding: 0.65rem 0.9rem;
  cursor: pointer;
}
/* Once graded the inputs are disabled, so the pointer would otherwise go to
 * not-allowed on a row the reader is still meant to read. */
.option > label:has(input:disabled) { cursor: default; }
.option:not(.option-correct):not(.option-wrong):hover { border-color: var(--border-strong); }
.option input { margin: 0; flex: none; align-self: center; }
.option-letter { font-weight: 600; color: var(--muted); flex: none; }
.option-text { flex: 1; }

.option-correct { border-color: var(--approved); background: var(--approved-bg); }
.option-correct .option-letter { color: var(--approved); }
.option-wrong { border-color: var(--danger); }
.option-wrong .option-letter { color: var(--danger); }

.result-banner {
  padding: 0.75rem 1rem;
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
  margin: 1.2rem 0;
}
.result-correct { border-color: var(--approved); background: var(--approved-bg); color: var(--approved); }
.result-incorrect { border-color: var(--danger); background: var(--needs-review-bg); color: var(--danger); }
.result-banner .muted { color: inherit; opacity: 0.85; }

.question-answer h3:first-child { margin-top: 0; }
.question-meta { margin: 0.8rem 0 0.2rem; }

.quiz-progress {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1rem;
  justify-content: space-between;
  align-items: baseline;
  padding: 0.6rem 0.9rem;
  margin-bottom: 1rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
}

.quiz-form { display: flex; flex-direction: column; gap: 1rem; max-width: 34rem; }
.quiz-field { display: flex; flex-direction: column; gap: 0.35rem; }
.quiz-field > span { font-weight: 600; }
.quiz-field select {
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg-raised);
  color: var(--text);
  font: inherit;
}
