/* atlas-kb — hand-maintained stylesheet (never generated).
   Clean scientific identity: light ground, sans, teal accent.

   EVERY colour is a token (2026-09-27). It used to be tokens for the
   six that repeated and hex literals for the other forty-odd — a dozen
   `#fff`, a scatter of pale teal tints — which meant the palette could
   not be changed in one place and a dark scheme was impossible. The
   light values below are exactly what those literals were, so nothing
   moved; what is new is that a reader whose machine asks for dark now
   gets one, on every page of the atlas and of an exported bundle. */
:root {
  --bg: #fafbfc;
  --code: #eef2f5;         /* inline code */
  --ok-soft: #e6f4e7; --sugg-soft: #eceafa;
  --imp: #1f6f8b; --imp-soft: #e4f1f7;
  --none-soft: #eef0f2; --dot-none: #c8d0d8;
  --ink-2: #44515c;        /* a shade of ink for secondary prose */
  --hair: #9fb3c8;         /* dotted underlines, faint rules */
  --panel: #ffffff;
  --panel-2: #f7f9fa;      /* a panel a shade down: code blocks, insets */
  --ink: #1f2933;
  --muted: #5f6b76;
  --accent: #0e7c86;
  --accent-ink: #0b616a;   /* accent as TEXT, where contrast matters */
  --on-accent: #ffffff;    /* text on an accent fill */
  --tint: #eef6f7;         /* the accent, washed: hovers and soft fills */
  --tint-2: #f2f6f7;
  --line: #e3e8ee;
  --line-2: #dbe8ea;
  --head: #f0f4f7;         /* table headers */
  --mark: #fdf6e3;         /* :target highlight */
  --ok: #2e7d32;
  --draft: #b26a00;
  --draft-soft: #fdf1df;
  --sugg: #5e548e;
  --warn: #c0392b; --warn-soft: #fdecea;
  --r: 8px;
  --shadow: 0 1px 2px rgba(16,32,40,.05);
  --lift: 0 2px 10px rgba(14,124,134,.18);
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0f161c;
    --code: #0e1720;
    --ok-soft: #14301a; --sugg-soft: #241f3a;
    --imp: #7cc4dd; --imp-soft: #132b36;
    --none-soft: #1c252d; --dot-none: #46545f;
    --ink-2: #b7c3cd;
    --hair: #46586a;
    --panel: #17212a;
    --panel-2: #131c23;
    --ink: #e6edf3;
    --muted: #94a3af;
    --accent: #3db8c3;
    --accent-ink: #7fd6de;
    --on-accent: #08171b;
    --tint: #123138;
    --tint-2: #14232b;
    --line: #26333f;
    --line-2: #2c3c48;
    --head: #1b2731;
    --mark: #33291a;
    --ok: #6cc070;
    --draft: #e0a458;
    --draft-soft: #33260f;
    --sugg: #a99ce0;
    --warn: #ff8b7e; --warn-soft: #3a201d;
    --shadow: 0 1px 2px rgba(0,0,0,.4);
    --lift: 0 2px 12px rgba(0,0,0,.5);
  }
  /* a figure is ink on white: keep it that way, on its own ground */
  .report-sec img, .fig img, img.figure { background: var(--panel); border-radius: 4px; }
}
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px;
  border-radius: 4px; }
* { box-sizing: border-box; }
body {
  margin: 0; background: var(--bg); color: var(--ink);
  font: 16px/1.6 -apple-system, "Segoe UI", Roboto, "Helvetica Neue",
        Arial, "Noto Sans", sans-serif;
}
main { max-width: 960px; margin: 0 auto; padding: 1.5rem 1rem 3rem; }
.topbar {
  display: flex; justify-content: space-between; align-items: center;
  padding: .7rem 1.2rem; background: var(--panel);
  border-bottom: 2px solid var(--accent);
}
.brand { font-weight: 700; color: var(--accent); letter-spacing: .02em; }
.topbar nav a { margin-left: 1rem; color: var(--muted); text-decoration: none; }
.topbar nav a.active, .topbar nav a:hover { color: var(--accent); }
footer { text-align: center; color: var(--muted); font-size: .8rem;
  padding: 1.5rem; border-top: 1px solid var(--line); }
h1 { font-size: 1.6rem; margin: .5rem 0; }
h1.gene-title { font-family: ui-monospace, "SF Mono", Menlo, monospace; }
.meta, .crumbs { color: var(--muted); font-size: .9rem; }
.crumbs a { color: var(--accent); text-decoration: none; }
a { color: var(--accent); }
code { background: var(--code); padding: 0 .3em; border-radius: 3px; }

/* dataset cards */
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr));
  gap: 1rem; margin-top: 1.2rem; }
.card.unbuilt { opacity: .65; border-style: dashed; }
.card { display: block; background: var(--panel); border: 1px solid var(--line);
  border-radius: 8px; padding: 1rem; text-decoration: none; color: var(--ink);
  transition: box-shadow .15s; }
.card { box-shadow: var(--shadow); }
.card:hover { box-shadow: var(--lift); border-color: var(--accent); }
.card h3 { margin: 0 0 .3rem; color: var(--accent); }
.card p { margin: .2rem 0; font-size: .85rem; color: var(--muted); }
.card .labels { color: var(--ink); }
/* Identity chips. The card used to print every cluster label as one
   comma-run — 42 of them on the chicken bursa, mostly "cluster 17" —
   which is a wall, not a summary. Distinct named types only, so the
   line is short enough to read and each identity is its own object. */
.card .idents { display: flex; flex-wrap: wrap; gap: .25rem; margin: .35rem 0 .2rem; }
.card .idt { font-size: .78rem; line-height: 1.45; color: var(--ink);
  background: var(--tint); border: 1px solid var(--line-2); border-radius: 4px;
  padding: 0 .35em; }
.card .idt i { font-style: normal; color: var(--muted); margin-left: .25em;
  font-variant-numeric: tabular-nums; }
.card .idt.more { background: none; border-style: dashed; color: var(--muted); }

/* scatter */
.scatter-wrap { display: flex; flex-wrap: wrap; gap: 1rem; align-items: flex-start;
  background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
  padding: 1rem; margin: 1rem 0; }
#scatter { max-width: 100%; height: auto; }
.legend { font-size: .85rem; min-width: 150px; }
.legend .item { display: flex; align-items: center; gap: .45em; cursor: pointer;
  padding: .1em .3em; border-radius: 4px; }
.legend .item:hover, .legend .item.on { background: var(--tint); }
.legend .swatch { width: .8em; height: .8em; border-radius: 50%; flex: none; }
.legend .n { color: var(--muted); margin-left: auto; }

/* tables */
table.clusters, table.mini { border-collapse: collapse; width: 100%;
  background: var(--panel); font-size: .9rem; }
table.mini { width: auto; min-width: 260px; margin-bottom: 1rem; }
th, td { border: 1px solid var(--line); padding: .4rem .6rem;
  text-align: left; vertical-align: top; }
th { background: var(--head); font-weight: 600; }
td { font-variant-numeric: tabular-nums; }
td.num { text-align: right; font-variant-numeric: tabular-nums; }
.pn { color: var(--sugg); text-decoration: none; font-family: ui-monospace,
  Menlo, monospace; }
tr:target { background: var(--mark); }
.note { color: var(--muted); font-size: .85rem; margin-top: .2rem; }
.gene { font-family: ui-monospace, "SF Mono", Menlo, monospace;
  font-size: .85rem; margin-right: .15em; }
span.gene { color: var(--muted); }

/* badges */
.badge { font-size: .7rem; padding: .1em .5em; border-radius: 9px;
  vertical-align: middle; white-space: nowrap; }
.badge.ok { background: var(--ok-soft); color: var(--ok); }
.badge.draft { background: var(--draft-soft); color: var(--draft); }
/* a human SIGNED it and the numbers have moved since. Deliberately NOT
   a shade of the draft amber: an unfinished draft is a normal stage of
   the loop, and a signature standing on numbers that are no longer
   there is a defect. */
.badge.stale { background: var(--warn-soft); color: var(--warn); }
.badge.sugg { background: var(--sugg-soft); color: var(--sugg); }
.badge.imp { background: var(--imp-soft); color: var(--imp); }
.badge.none { background: var(--none-soft); color: var(--muted); }

/* search */
#q { width: 100%; font-size: 1.05rem; padding: .55rem .8rem; margin: 1rem 0;
  border: 1px solid var(--line); border-radius: 8px; }
#q:focus { outline: 2px solid var(--accent); border-color: var(--accent); }
#results .group h2 { font-size: 1rem; color: var(--muted); margin: 1rem 0 .3rem; }
#results .hit { padding: .35rem .5rem; border-bottom: 1px solid var(--line); }
#results .hit a { text-decoration: none; }
#results .hint { color: var(--muted); }

/* gene-expression overlay control */
.expr-box { display: flex; gap: .5rem; align-items: center; margin: -0.4rem 0 1rem;
  flex-wrap: wrap; }
.expr-box input { flex: 0 1 240px; padding: .35rem .6rem; font-size: .9rem;
  border: 1px solid var(--line); border-radius: 6px; }
.expr-box button { padding: .35rem .8rem; font-size: .85rem; cursor: pointer;
  border: 1px solid var(--accent); border-radius: 6px; background: var(--panel);
  color: var(--accent); }
.expr-box button:hover { background: var(--accent); color: var(--on-accent); }

/* ============================================================
   REPORT PAGES — set as a journal article, not as a dashboard.
   Layout: a fixed contents rail beside a single measured column.
   ============================================================ */
.report-link { text-decoration: none; font-weight: 600; }

/* The home link is an ICON, not the word "Atlas": in an exported
   bundle the same link opens that bundle's landing page, which is not
   an atlas — and the site's own index is reachable from every page, so
   the label was carrying no information either way. */
.topbar nav a.home { font-size: 1.15rem; line-height: 1; padding: 0 .15rem; }
.crumbs a[title="Home"] { font-size: 1.05rem; text-decoration: none; }

/* ── the views bar: every interactive view of one dataset ─────────────
   Sits under the dataset page's meta line, and the same links (minus
   the current one) fill each explorer's own bar as .xp-act. The four
   apps used to be scattered — the cell explorer on the dataset page,
   the kernel explorer and dashboard only INSIDE that explorer, the
   pathway explorer only from a report section — so half of them were
   undiscoverable. One row, one place. */
/* The dataset page's embedding is a STILL — the umap-overview module's
   own figure — linking into the explorer. It is not a viewer: this page
   is the record (identity, provenance, the cluster table), and a third
   interactive scatter of the same cells was the redundancy that made
   the two pages hard to tell apart. */
.ds-preview { display: block; position: relative; max-width: 640px;
  margin: 0 0 1.2rem; border: 1px solid var(--line); border-radius: 10px;
  overflow: hidden; text-decoration: none; background: var(--panel); }
.ds-preview img { display: block; width: 100%; height: auto; }
.ds-preview-cta { display: block; padding: .45rem .7rem; font-size: .84rem;
  color: var(--accent); border-top: 1px solid var(--line); }
.ds-preview:hover { border-color: var(--accent); }
.ds-preview:hover .ds-preview-cta { background: var(--accent); color: var(--on-accent); }

.views { display: flex; flex-wrap: wrap; gap: .4rem; margin: .5rem 0 1.1rem; }
.view { font-size: .84rem; text-decoration: none; color: var(--accent);
  border: 1px solid var(--line); border-radius: 7px;
  padding: .3rem .7rem; white-space: nowrap; background: var(--panel);
  transition: background .12s, color .12s, border-color .12s; }
.view:hover { background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
.view.sm { font-size: .78rem; padding: .22rem .55rem; }
.paper-head .views { margin: .5rem 0 0; }
/* which dataset a report's views bar belongs to — a LABEL, not a chip:
   no border, no hover, so it never reads as one more thing to click.
   Rows in a two-column grid: the tag column is as wide as the LONGEST
   name (capped), so the chips start at the same x on every row. */
.ds-views { display: grid; grid-template-columns: max-content 1fr;
  gap: .4rem .55rem; align-items: center; margin: .5rem 0 0; }
.ds-views .views { margin: 0; }
.ds-views .ds-tag { font-size: .74rem; font-weight: 600;
  color: var(--ink); background: var(--line); border-radius: 4px;
  padding: .18rem .5rem; white-space: nowrap; box-sizing: border-box;
  max-width: 16rem; overflow: hidden; text-overflow: ellipsis;
  text-align: center; }

body.reading { --serif: Charter, "Bitstream Charter", "Iowan Old Style",
  "Palatino Linotype", Georgia, "Times New Roman", serif; }
/* main must widen with the reader's choice too, or Wide/Wider/Full
   all stop at the same place: the article is inside this column,
   so capping it here silently caps them. */
body.reading main { max-width: var(--main-max, 1160px); padding-top: 1rem; }

.rlayout { display: grid; grid-template-columns: 208px minmax(0, 1fr);
  gap: 2.6rem; align-items: start; }

/* ---- the fixed contents rail ---- */
.toc-rail { position: sticky; top: 1rem; }
.toc-inner { max-height: calc(100vh - 3rem); overflow-y: auto;
  border-right: 1px solid var(--line); padding-right: .8rem; }
.toc-head { font-size: .7rem; text-transform: uppercase;
  letter-spacing: .09em; color: var(--muted); font-weight: 700;
  margin: 0 0 .5rem; }
.toc-rail nav { display: flex; flex-direction: column; }
.toc-rail nav a { display: flex; align-items: baseline; gap: .45rem;
  padding: .3rem .4rem .3rem .5rem; font-size: .82rem; line-height: 1.35;
  color: var(--muted); text-decoration: none; border-left: 2px solid transparent;
  border-radius: 0 4px 4px 0; }
.toc-rail nav a:hover { background: var(--tint); color: var(--ink); }
/* the current section: the rail's one job beyond linking */
.toc-rail nav a.on { color: var(--accent); font-weight: 600;
  border-left-color: var(--accent); background: var(--tint); }
.toc-rail .tnum { font-variant-numeric: tabular-nums; font-size: .72rem;
  color: var(--muted); min-width: .85em; flex: none; }
.toc-rail nav a.on .tnum { color: var(--accent); }
.toc-rail .tlbl { flex: 1; }
/* lifecycle at a glance — which sections a human has actually signed off */
.toc-rail .tdot { width: 6px; height: 6px; border-radius: 50%; flex: none;
  align-self: center; }
.tdot.ok { background: var(--ok); }
.tdot.draft { background: var(--draft); }
.tdot.stale { background: var(--warn); }
.tdot.none { background: var(--dot-none); }
.toc-prog { font-size: .72rem; color: var(--muted); margin: .6rem 0 0;
  padding: 0 .5rem; }
.toc-foot { margin-top: .7rem; padding: 0 .3rem; }
.toc-foot .btn-dl { display: block; text-align: center; font-size: .8rem;
  padding: .35rem .4rem; }
.toc-toggle { display: none; }

/* reading progress, thin and unobtrusive */
.readbar { position: fixed; top: 0; left: 0; height: 2px; width: 0;
  background: var(--accent); z-index: 40; transition: width .1s linear; }

/* ---- the article ---- */
/* --paper-width is set by the reader's width control (report-nav.js);
   46rem is the default ~72-character measure. */
.paper { max-width: var(--paper-width, 46rem); }
.paper-head { border-bottom: 2px solid var(--ink); padding-bottom: 1rem;
  margin-bottom: 1.6rem; }
.paper-head h1 { font-family: var(--serif); font-size: 2.05rem;
  line-height: 1.2; margin: .5rem 0 .4rem; letter-spacing: -.01em; }
.paper-head .subtitle { font-family: var(--serif); font-size: 1.08rem;
  color: var(--ink-2); margin: 0 0 .9rem; line-height: 1.45; }
.paper-head .byline { font-size: .95rem; margin: 0 0 .15rem;
  font-weight: 600; }
.paper-head .affil { font-size: .82rem; color: var(--muted); margin: 0; }
.paper-head .affil a { color: var(--muted); }

.report-sec { margin: 0 0 2.1rem; }
.report-sec .sec-head { display: flex; align-items: baseline; gap: .6rem;
  margin: 2rem 0 .7rem; }
.report-sec .sec-head h2 { margin: 0; font-size: 1.12rem; font-weight: 700;
  letter-spacing: .005em; flex: 1; }
.report-sec .secno { color: var(--accent); font-variant-numeric: tabular-nums; }
.report-sec .secno:not(:empty) { margin-right: .5em; }
.report-sec .sec-ds { font-size: .78rem; color: var(--muted);
  font-family: ui-monospace, Menlo, monospace; }
.report-sec .sec-head .badge { flex: none; }
/* a LIVE view the author attached to this section (a board, an
   exploration): a card at the end of the prose, not a chip in the
   heading — it is part of what the section says, and it is the one
   thing on the page a reader can drive. Printing drops it: the PDF
   says the same in words (reportshop/compile.py). */
.sec-link { display: flex; align-items: center; gap: .8rem;
  margin: 1.1rem 0 0; padding: .7rem .9rem; text-decoration: none;
  border: 1px solid var(--line); border-left: 3px solid var(--accent);
  border-radius: 9px; background: var(--panel); color: inherit; }
.sec-link:hover { border-color: var(--accent); background: var(--tint); }
.sec-link .sl-icon { font-size: 1.25rem; color: var(--accent); }
.sec-link .sl-body { display: flex; flex-direction: column; flex: 1; }
.sec-link .sl-what { font-size: .78rem; color: var(--muted); }
.sec-link .sl-go { font-size: .78rem; color: var(--accent);
  white-space: nowrap; }
.sec-link.gone { color: var(--muted); font-size: .82rem;
  border-left-color: var(--line); }
@media print { .sec-link { display: none; } }

/* prose: serif, and a measure that stops at ~72 characters.
   --prose-size is set on .paper by the reader's A-/A+ control
   (report-nav.js) and persisted per browser; everything that scales
   with reading size derives from it rather than being set again. */
.paper { --prose-size: 1.02rem; }
.report-sec p, .report-sec li { font-family: var(--serif);
  font-size: var(--prose-size); line-height: 1.68; }
.report-sec p { margin: 0 0 .85rem; }
.report-sec h3 { font-size: .95rem; margin: 1.3rem 0 .3rem;
  letter-spacing: .02em; }
.report-sec h4 { font-size: .87rem; margin: 1rem 0 .2rem; color: var(--muted); }

/* the abstract, set apart the way a journal sets it */
.report-sec.front { background: var(--tint-2); border-left: 3px solid var(--accent);
  padding: .3rem 1.2rem .9rem; border-radius: 0 6px 6px 0; }
.report-sec.front .sec-head { margin-top: 1rem; }
.report-sec.front p { font-size: calc(var(--prose-size) * 0.94); }

/* figures: numbered, captioned, centred */
.fig { margin: 1.3rem 0 1.5rem; text-align: center; }
/* width:100% (not max-width) because a module SVG may carry only a
   viewBox: with no intrinsic size, max-width has nothing to resolve
   against and the figure collapses. Given an explicit width the browser
   takes the aspect ratio from the viewBox, so both old and new figures
   lay out correctly. */
/* …but width:100% UPSCALES a narrow figure, and height:auto then
   multiplies its height by the same factor. marker-heatmap is 520x1048
   at its 60-gene cap, so in a 760px column it rendered 1497px tall and
   ran off the screen — the taller the figure, the worse the rule that
   was meant to help it. max-height clamps the box; object-fit keeps the
   aspect ratio inside it, letterboxed rather than squashed. Squat
   figures are untouched: they never reach the clamp. */
.fig img { display: block; width: 100%; height: auto;
  max-height: 82vh; object-fit: contain; }
/* Safety net for any image NOT wrapped as a figure — module markdown is
   free-form and a future module may emit one mid-paragraph. Without
   this an 1000px-wide pathway SVG simply runs out of the column. */
.report-sec img { max-width: 100%; height: auto; }
.fig-zoom { display: block; border: 1px solid var(--line);
  border-radius: 4px; padding: .3rem; background: var(--panel); }
.fig-zoom:hover { border-color: var(--accent); }
.fig figcaption { font-size: calc(var(--prose-size) * 0.80); color: var(--muted); line-height: 1.5;
  margin-top: .5rem; text-align: left; }
.fig figcaption b { color: var(--ink); }

/* tables: horizontal rules only (booktabs), the way papers print them */
.report-sec table { border-collapse: collapse;
  font-size: calc(var(--prose-size) * 0.83);
  margin: 1rem 0 1.2rem; width: 100%; }
.report-sec th, .report-sec td { border: none;
  border-bottom: 1px solid var(--line); padding: .38rem .55rem;
  text-align: left; }
.report-sec thead th, .report-sec tr:first-child th {
  border-top: 1.5px solid var(--ink); border-bottom: 1px solid var(--ink);
  background: none; font-weight: 600; }
.report-sec tr:last-child td { border-bottom: 1.5px solid var(--ink); }

.paper-foot { border-top: 1px solid var(--line); margin-top: 2.5rem;
  padding-top: 1rem; color: var(--muted); font-size: .82rem; }
.paper-foot p { margin: .4rem 0; }

/* ---- narrow screens: the rail becomes a drawer ---- */
@media (max-width: 860px) {
  .rlayout { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .toc-rail { position: sticky; top: 0; z-index: 20; background: var(--bg);
    padding: .4rem 0; margin-bottom: .5rem; }
  .toc-toggle { display: block; width: 100%; text-align: left;
    font: 600 .82rem/1 inherit; color: var(--accent); cursor: pointer;
    background: var(--panel); border: 1px solid var(--line);
    border-radius: 6px; padding: .5rem .7rem; }
  .toc-toggle::before { content: "☰ "; }
  .toc-inner { display: none; background: var(--panel); margin-top: .3rem;
    border: 1px solid var(--line); border-right: 1px solid var(--line);
    border-radius: 6px; padding: .6rem .5rem;
    max-height: 60vh; }
  .toc-rail.open .toc-inner { display: block; }
  .toc-head { display: none; }
  .paper { max-width: none; }
  .paper-head h1 { font-size: 1.6rem; }
}

/* composed report cards (factory products) */
.report-card { border-left: 4px solid var(--accent); }
/* A PROJECT card leads the home page (2026-09-26): it carries its own
   reports as lines rather than sending the reader to a flat gallery of
   every report in the atlas. */
.ws-card { border-left: 4px solid var(--accent); }
.ws-card .rline { margin: .3rem 0; font-size: .88rem; color: var(--ink); }
.ws-card .rline a { color: var(--accent); text-decoration: none; }
.ws-card .rline a:hover { text-decoration: underline; }
.ws-card .rline .labels { color: var(--muted); font-size: .78rem; }
h2 { font-size: 1.25rem; margin: 1.6rem 0 .4rem; }

/* multi-layer explorer (scaffold) */
.xp-frame { position: relative; height: 72vh; min-height: 420px;
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 8px; overflow: hidden; touch-action: none;
  cursor: grab; }
.xp-frame:active { cursor: grabbing; }
.xp-canvases, .xp-svg { position: absolute; inset: 0; width: 100%;
  height: 100%; }
.xp-canvases canvas { position: absolute; inset: 0; }
.xp-svg { pointer-events: none; }
.xp-label { font: 600 12px/1 -apple-system, sans-serif; fill: var(--ink);
  paint-order: stroke; stroke: rgba(255,255,255,.85); stroke-width: 3px; }
.xp-hull-label { font-size: 12px; }
.xp-panel { position: absolute; top: 10px; right: 10px; z-index: 5;
  background: rgba(255,255,255,.94); border: 1px solid var(--line);
  border-radius: 8px; padding: .5rem .7rem; font-size: .82rem;
  max-width: 230px; }
.xp-row { display: flex; gap: .4em; align-items: center; margin: .2em 0; }
.xp-subpanel { margin: .1em 0 .4em 1.4em; }
.xp-subpanel input { width: 90px; padding: .15em .35em;
  border: 1px solid var(--line); border-radius: 4px; }
.xp-subpanel button { padding: .15em .5em; border: 1px solid var(--accent);
  border-radius: 4px; background: var(--panel); color: var(--accent);
  cursor: pointer; }
.xp-tip { position: absolute; z-index: 6; background: var(--ink); color: var(--bg);
  font-size: .78rem; padding: .2em .5em; border-radius: 4px;
  pointer-events: none; }

/* gene symbols in a data report link to that dataset's expression
   explorer (?gene=SYM) — dotted so a table of them does not read as a
   wall of blue */
.gene-link { text-decoration: none; border-bottom: 1px dotted var(--hair); }
.gene-link:hover { border-bottom-style: solid; background: var(--tint); }
#expr-box input[list] { min-width: 12rem; }

/* download button on a composed report page */
.dl-row { margin: .6rem 0 1rem; }
.btn-dl { display: inline-block; text-decoration: none; font-weight: 600;
  border: 1px solid var(--accent); color: var(--accent);
  border-radius: 6px; padding: .4rem .8rem; background: var(--panel); }
.btn-dl:hover { background: var(--accent); color: var(--on-accent); }
.btn-dl span { font-weight: 400; opacity: .75; font-size: .85em; }

/* report card: title links to the page, a small link takes the PDF */
.report-card h3 a { color: var(--accent); text-decoration: none; }
.report-card h3 a:hover { text-decoration: underline; }
.pdf-mini { display: inline-block; margin-top: .45rem; font-size: .8rem;
  text-decoration: none; border: 1px solid var(--line); border-radius: 5px;
  padding: .15rem .5rem; color: var(--accent); background: var(--panel); }
.pdf-mini:hover { border-color: var(--accent); background: var(--tint); }

/* ============================================================
   FIGURE VIEWER (figure.html) — a full-window pan/zoom surface.
   ============================================================ */
body.figview { height: 100vh; display: flex; flex-direction: column;
  overflow: hidden; }
body.figview .topbar, body.figview footer { display: none; }
body.figview main { max-width: none; margin: 0; padding: 0; flex: 1;
  display: flex; flex-direction: column; min-height: 0; }

.fv-bar { display: flex; align-items: center; gap: .45rem; flex: none;
  padding: .45rem .8rem; background: var(--panel);
  border-bottom: 2px solid var(--accent); }
.fv-bar b { font-size: .9rem; font-weight: 600; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; max-width: 46vw; }
.fv-bar .fv-sp { flex: 1; }
.fv-bar button, .fv-raw, .fv-back { border: 1px solid var(--line);
  background: var(--panel); color: var(--accent); border-radius: 6px;
  padding: .2rem .6rem; font-size: .85rem; cursor: pointer;
  text-decoration: none; line-height: 1.5; }
.fv-bar button:hover, .fv-raw:hover, .fv-back:hover {
  background: var(--accent); color: var(--on-accent); border-color: var(--accent); }
#zoomlabel { font-size: .8rem; color: var(--muted); min-width: 3.4em;
  text-align: center; font-variant-numeric: tabular-nums; }

.fv-stage { flex: 1; min-height: 0; background: var(--panel); cursor: grab;
  touch-action: none; overflow: hidden; }
.fv-stage.grabbing { cursor: grabbing; }
.fv-stage svg { width: 100%; height: 100%; display: block; }
.fv-hint { flex: none; margin: 0; padding: .35rem .8rem; font-size: .75rem;
  color: var(--muted); background: var(--panel);
  border-top: 1px solid var(--line); }
.fv-hint kbd { border: 1px solid var(--line); border-bottom-width: 2px;
  border-radius: 3px; padding: 0 .3em; font-family: ui-monospace, monospace;
  font-size: .95em; background: var(--panel-2); }
.fv-status { margin: 1.5rem auto; color: var(--warn);
  font-size: .9rem; }

/* ============================================================
   EXPLORER as an APPLICATION (body.appview) — one compact bar, then
   the canvas takes every remaining pixel. The document layout it
   replaced (site header + breadcrumb + 960px column + caption) left a
   1340px window showing the data in about half its area.
   ============================================================ */
body.appview { height: 100vh; display: flex; flex-direction: column;
  overflow: hidden; }
body.appview .topbar, body.appview footer { display: none; }
body.appview main { max-width: none; margin: 0; padding: 0; flex: 1;
  display: flex; flex-direction: column; min-height: 0; }

.xp-bar { flex: none; display: flex; align-items: center; gap: .5rem;
  padding: .4rem .75rem; background: var(--panel);
  border-bottom: 2px solid var(--accent); }
.xp-home { text-decoration: none; color: var(--accent); font-size: 1rem;
  border: 1px solid var(--line); border-radius: 6px; padding: .05rem .5rem; }
.xp-home:hover { background: var(--accent); color: var(--on-accent); }
.xp-title { font-size: .92rem; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; max-width: 42vw; }
.xp-where { font-size: .78rem; color: var(--muted);
  text-transform: uppercase; letter-spacing: .08em; }
.xp-bar .xp-sp { flex: 1; }
.xp-act { font-size: .82rem; text-decoration: none; color: var(--accent);
  border: 1px solid var(--line); border-radius: 6px; padding: .2rem .6rem;
  white-space: nowrap; }
.xp-act:hover, .xp-act.on { background: var(--accent); color: var(--on-accent);
  border-color: var(--accent); }

/* the canvas: all remaining space, no card chrome */
body.appview .xp-frame { flex: 1; height: auto; min-height: 0;
  border: none; border-radius: 0; }
.xp-hint { flex: none; margin: 0; padding: .28rem .75rem; font-size: .74rem;
  color: var(--muted); background: var(--panel);
  border-top: 1px solid var(--line); }

/* the layers panel floats over the canvas, as an app's inspector does */
body.appview .xp-panel { top: 12px; right: 12px; max-height: calc(100% - 24px);
  overflow-y: auto; box-shadow: 0 2px 12px rgba(31,41,51,.13); }

@media (max-width: 700px) {
  .xp-title { max-width: 30vw; }
  .xp-where { display: none; }
  body.appview .xp-panel { max-width: 62vw; }
}

/* reading-size control, injected into the rail by report-nav.js */
.toc-size { display: flex; align-items: center; gap: .3rem; margin: .7rem 0 0;
  padding: .5rem .3rem 0; border-top: 1px solid var(--line); }
.toc-size b { font-size: .7rem; text-transform: uppercase;
  letter-spacing: .08em; color: var(--muted); font-weight: 700; flex: 1; }
.toc-size button { border: 1px solid var(--line); background: var(--panel);
  color: var(--accent); border-radius: 5px; cursor: pointer; line-height: 1;
  padding: .2rem .45rem; font-family: var(--serif); }
.toc-size button:hover { background: var(--accent); color: var(--on-accent);
  border-color: var(--accent); }
.toc-size button:disabled { opacity: .35; cursor: default; }
.toc-size button:disabled:hover { background: var(--panel);
  color: var(--accent); border-color: var(--line); }
.toc-size .sm { font-size: .78rem; }
.toc-size .lg { font-size: 1.02rem; }
.toc-size select { font-size: .75rem; padding: .12rem .2rem; max-width: 6.4rem; }

/* citations and the reference list (rx-myst's model: [@key] -> [n]) */
.cite { font-size: .72em; line-height: 0; }
.cite a { text-decoration: none; padding: 0 .1em; }
.cite a:hover { text-decoration: underline; }
.refs-sec .biblio { font-family: var(--serif); font-size: calc(var(--prose-size) * 0.88);
  line-height: 1.5; padding-left: 1.6em; margin: .4rem 0 0; }
.refs-sec .biblio li { margin: 0 0 .5rem; }
.refs-sec .biblio li:target { background: var(--mark); }
.cite-missing { color: var(--warn); }

/* link from a report to the interactive cell explorer */
.xp-link { white-space: nowrap; text-decoration: none; font-weight: 600;
  border-bottom: 1px dotted currentColor; }
.xp-link:hover { border-bottom-style: solid; }

/* datasets/ folders on the atlas index */
h3.ds-group { margin: 1.4rem 0 .3rem; font-size: .76rem; font-weight: 700;
  letter-spacing: .09em; text-transform: uppercase; color: var(--muted); }
h3.ds-group::before { content: "\1F4C1  "; }
p.ds-group-sub { margin: -.15rem 0 .3rem; font-family: ui-monospace, Menlo,
  monospace; font-size: .72rem; opacity: .75; }
.ws-card .rline .pdf-mini { margin-top: 0; margin-left: .3rem; }
