/* NMD Predictor — styling. Plain CSS, no framework.
   Base tokens are lifted unchanged from nmd_atlas/public/style.css so the two
   sites read as one product; everything below the "predictor-only" rule is new. */
:root {
  --c-bg: #fafafa;
  --c-card: #ffffff;
  --c-text: #1f2937;
  --c-muted: #6b7280;
  --c-border: #e5e7eb;
  --c-accent: #2563eb;
  --c-accent-light: #dbeafe;

  /* Canonical NMD-figure palette (matches project conventions) */
  --c-ptc-pos: #ef8a62;
  --c-ptc-neg: #d95f02;
  --c-control: #4c72b0;   /* darkened from the atlas #67a9cf: the lighter blue
                             fails the chroma floor as a chart fill */
  --c-nmd: #ef8a62;

  /* Branch palette for the interpretability charts (Dark2; validated) */
  --c-branch-atg: #1b9e77;
  --c-branch-struct: #d95f02;
  --c-branch-stop: #7570b3;

  --c-good: #059669;
  --c-warn: #d97706;
  /* Amber is for "read this before you trust the number"; red is for input the
     page could not read at all, which is a different and louder thing. */
  --c-bad:  #dc2626;

  --font-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, monospace;
}

* { box-sizing: border-box; }
body {
  margin: 0;
  font-family: var(--font-body);
  background: var(--c-bg);
  color: var(--c-text);
  font-size: 14px;
  line-height: 1.5;
}

header {
  background: #ffffff;
  border-bottom: 1px solid var(--c-border);
  padding: 1.2em 2em;
}
.header-row { display: flex; align-items: flex-start; justify-content: space-between; gap: 1em; }
header h1 { margin: 0; font-size: 1.5em; font-weight: 600; }
header h1 a { color: inherit; text-decoration: none; }
header h1 a:hover { color: var(--c-accent); }
.subtitle { margin: 0.3em 0 0; color: var(--c-muted); font-size: 0.9em; max-width: 60em; }
.topnav { display: flex; gap: 0.5em; flex-shrink: 0; flex-wrap: wrap; }
.btn-nav {
  padding: 0.4em 0.9em; background: #fff; color: var(--c-accent);
  border: 1px solid var(--c-border); border-radius: 6px; cursor: pointer;
  font-family: var(--font-body); font-size: 0.85em; font-weight: 500;
  text-decoration: none; display: inline-block;
}
.btn-nav:hover { background: var(--c-accent-light); border-color: var(--c-accent); }
.topnav a.active, .topnav button.active {
  background: var(--c-accent-light); border-color: var(--c-accent);
}

main { padding: 1.5em 2em; max-width: 90em; margin: 0 auto; }
.hidden { display: none !important; }
.mono { font-family: var(--font-mono); }

/* ── search ── */
/* One bar over both catalogues: full width, because a merged list carries a
   source badge, an identifier and a description on the same row. */
.search-section { margin-bottom: 1.2em; position: relative; }
.search-section label { font-weight: 500; display: block; margin-bottom: 0.3em; }
.search-section input {
  width: 100%; padding: 0.6em 0.8em; font-size: 1em;
  border: 1px solid var(--c-border); border-radius: 6px;
  font-family: var(--font-body);
}
.search-section input:focus { outline: 2px solid var(--c-accent); border-color: var(--c-accent); }
#search-results {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 10;
  margin: 0.2em 0 0; padding: 0; list-style: none; max-height: 30em; overflow-y: auto;
  background: #fff; border: 1px solid var(--c-border); border-radius: 6px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}
#search-results:empty { display: none; }
#search-results li {
  padding: 0.5em 0.8em; cursor: pointer; border-bottom: 1px solid var(--c-border);
  display: flex; align-items: center; gap: 0.5em;
}
#search-results li:last-child { border-bottom: none; }
#search-results li:hover,
#search-results li.highlight { background: var(--c-accent-light); }
#search-results .sym { font-weight: 600; }
#search-results .gid { color: var(--c-muted); font-family: var(--font-mono); font-size: 0.85em; }
#search-results .spacer { flex: 1; }
#search-results .badge {
  display: inline-block; padding: 1px 6px; border-radius: 8px;
  font-size: 0.75em; background: var(--c-nmd); color: #fff;
}

/* ── cards & layout ── */
#gene-panel h2 { margin: 0.5em 0 1em; font-size: 1.3em; }
.gene-id-small { color: var(--c-muted); font-family: var(--font-mono); font-size: 0.7em; font-weight: 400; margin-left: 0.5em; }

.panel-grid { display: grid; grid-template-columns: 30em 1fr; gap: 1.2em; }
@media (max-width: 1100px) { .panel-grid { grid-template-columns: 1fr; } }

.card {
  background: var(--c-card); border: 1px solid var(--c-border);
  border-radius: 8px; padding: 1em 1.2em;
}
.card h3 { margin: 0 0 0.5em; font-size: 1.05em; font-weight: 600; }
.card h4 { margin: 1em 0 0.4em; font-size: 0.95em; font-weight: 600; color: #374151; }
.hint { color: var(--c-muted); font-size: 0.85em; margin: 0 0 0.6em; }

.filter-bar {
  display: flex; flex-wrap: wrap; gap: 0.5em 1.3em; align-items: center;
  padding: 0.5em 0.7em; margin: 0.4em 0 0.7em;
  background: #f9fafb; border: 1px solid var(--c-border); border-radius: 6px;
  font-size: 0.85em;
}
.filter-bar label { display: flex; align-items: center; gap: 0.4em; cursor: pointer; }
.filter-bar select, .filter-bar input[type="range"] {
  font-family: var(--font-body); font-size: 1em;
}
.filter-bar input[type="range"] { width: 9em; }
.filter-bar .mono { min-width: 3em; text-align: right; font-weight: 500; }

.iso-count {
  display: inline-block; font-size: 0.75em; font-weight: 500; color: var(--c-muted);
  background: #f3f4f6; border-radius: 10px; padding: 1px 8px; margin-left: 0.5em;
}

.charts-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.2em; margin-top: 0.5em; }
@media (max-width: 900px) { .charts-row { grid-template-columns: 1fr; } }
.two-col { display: grid; grid-template-columns: 1fr 1fr; gap: 1.2em; }
@media (max-width: 900px) { .two-col { grid-template-columns: 1fr; } }

/* ── isoform tables ── */
#isoform-table-wrap { max-height: 34em; overflow: auto; }
#browse-table-wrap { max-height: 46em; overflow: auto; }
#isoform-table, #browse-table { width: 100%; border-collapse: collapse; font-size: 0.85em; }
#isoform-table th, #isoform-table td,
#browse-table th, #browse-table td {
  padding: 0.4em 0.5em; text-align: left; border-bottom: 1px solid var(--c-border);
  white-space: nowrap;
}
#isoform-table th, #browse-table th {
  position: sticky; top: 0; background: #f3f4f6; z-index: 2;
  font-weight: 600; font-size: 0.8em; text-transform: uppercase; letter-spacing: 0.03em;
}
#isoform-table tr, #browse-table tr { cursor: pointer; }
#isoform-table tr:hover, #browse-table tr:hover { background: #f9fafb; }
#isoform-table tr.selected { background: var(--c-accent-light); }
#isoform-table td.iso-id, #browse-table td.iso-id { font-family: var(--font-mono); font-size: 0.85em; }
#isoform-table td.numeric, #browse-table td.numeric {
  text-align: right; font-variant-numeric: tabular-nums;
}

/* Probability chip — the fill is the score, the number is always printed beside
   it, so the encoding never rests on colour alone. */
.pchip { display: inline-flex; align-items: center; gap: 0.45em; }
.pchip .bar {
  width: 3.6em; height: 0.55em; border-radius: 4px; background: #eef0f3;
  overflow: hidden; flex-shrink: 0;
}
.pchip .bar span { display: block; height: 100%; border-radius: 4px; background: var(--c-nmd); }
.pchip .num { font-variant-numeric: tabular-nums; min-width: 2.9em; text-align: right; }

.obs-yes { color: var(--c-nmd); font-weight: 700; }
.obs-no  { color: var(--c-muted); }

.tag {
  display: inline-block; padding: 1px 7px; border-radius: 8px;
  font-size: 0.75em; font-weight: 500; border: 1px solid transparent;
}
.tag-test    { background: #ecfdf5; color: #065f46; border-color: #a7f3d0; }
.tag-val     { background: #eff6ff; color: #1e40af; border-color: #bfdbfe; }
.tag-train   { background: #fef3c7; color: #92400e; border-color: #fde68a; }
.tag-paralog { background: #f5f3ff; color: #5b21b6; border-color: #ddd6fe; }
.tag-plain   { background: #f3f4f6; color: #4b5563; border-color: #e5e7eb; }

/* ── prediction readout ── */
.pred-readout {
  display: grid; grid-template-columns: auto 1fr; gap: 0.6em 1.2em;
  align-items: center;
  padding: 1em 1.2em; margin: 0.3em 0 0.8em;
  border: 1px solid var(--c-border); border-radius: 8px; background: #fbfcfe;
}
.pred-readout .hero { font-size: 2.6em; font-weight: 600; line-height: 1;
  font-variant-numeric: tabular-nums; }
.pred-readout .hero-label { color: var(--c-muted); font-size: 0.8em; margin-top: 0.35em; }
.pred-readout .band { font-size: 1.05em; font-weight: 600; margin-bottom: 0.15em; }
.pred-readout .band-detail { color: var(--c-muted); font-size: 0.87em; }
.pred-meter { grid-column: 1 / -1; height: 0.7em; border-radius: 5px; background: #eef0f3;
  position: relative; overflow: hidden; }
.pred-meter span { display: block; height: 100%; border-radius: 5px; background: var(--c-nmd); }
.pred-scale { grid-column: 1 / -1; display: flex; justify-content: space-between;
  color: var(--c-muted); font-size: 0.75em; font-variant-numeric: tabular-nums; }

.notice {
  padding: 0.6em 0.9em; border-radius: 6px; font-size: 0.87em;
  border-left: 4px solid; margin: 0 0 0.9em;
}
.notice-warn { background: #fffbeb; border-color: var(--c-warn); }
.notice-ok   { background: #ecfdf5; border-color: var(--c-good); }
.notice-info { background: #eff6ff; border-color: var(--c-accent); }
.notice strong { display: block; margin-bottom: 0.15em; }

.meta-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(11em, 1fr));
  gap: 0.5em 1em; margin: 0.4em 0 1em;
}
.meta-grid div { font-size: 0.85em; }
.meta-grid .label { color: var(--c-muted); display: block; }
.meta-grid .value { font-weight: 500; }

.stat-row {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(9em, 1fr));
  gap: 0.8em; margin-top: 1em;
}
.stat-tile {
  background: #f9fafb; border: 1px solid var(--c-border); border-radius: 6px;
  padding: 0.7em 0.9em;
}
.stat-tile .v { font-size: 1.5em; font-weight: 600; font-variant-numeric: tabular-nums; }
.stat-tile .k { color: var(--c-muted); font-size: 0.8em; }

/* ── mini tables (model card) ── */
.mini-table { width: 100%; border-collapse: collapse; font-size: 0.85em; margin: 0.4em 0 1em; }
.mini-table th, .mini-table td {
  padding: 0.35em 0.6em; text-align: left; border-bottom: 1px solid var(--c-border);
}
.mini-table th {
  background: #f3f4f6; font-weight: 600; font-size: 0.82em;
  text-transform: uppercase; letter-spacing: 0.03em;
}
.mini-table th.numeric, .mini-table td.numeric {
  text-align: right; font-variant-numeric: tabular-nums;
}
.mini-table td.mono, .mini-table th.mono { font-family: var(--font-mono); font-size: 0.9em; }
.mini-table tr.highlight-row td { background: #ecfdf5; font-weight: 600; }
#layer-table-wrap { max-height: 22em; overflow: auto; }

.warn-box {
  background: #fffbeb; border: 1px solid #fde68a; border-left: 4px solid var(--c-warn);
  border-radius: 6px; padding: 0.9em 1.2em; margin: 0.6em 0 1em;
}
.warn-box p:first-child { margin-top: 0; font-weight: 600; }

/* ── architecture diagram ── */
#arch-diagram { background: #fff; border: 1px solid var(--c-border); border-radius: 6px;
  padding: 0.6em; margin: 0.6em 0 1em; overflow-x: auto; }
#arch-diagram svg { display: block; margin: 0 auto; }

/* ── documentation pages ── */
.docs-page {
  max-width: 62em; margin: 0 auto 3em;
  background: var(--c-card); border: 1px solid var(--c-border);
  border-radius: 8px; padding: 1.5em 2em; line-height: 1.65;
}
.docs-page h2 {
  margin: 0 0 0.4em; font-size: 1.5em; font-weight: 600;
  border-bottom: 2px solid var(--c-accent); padding-bottom: 0.3em;
}
.docs-page h3 { margin: 1.4em 0 0.4em; font-size: 1.05em; font-weight: 600; color: #374151; }
.docs-page h4 { margin: 1.1em 0 0.3em; font-size: 0.95em; font-weight: 600; color: #374151; }
.docs-page h5 { margin: 0.6em 0 0.3em; font-size: 0.88em; font-weight: 600; color: var(--c-muted);
  text-transform: uppercase; letter-spacing: 0.03em; }
.docs-page .docs-lead { font-size: 1.05em; color: #374151; margin: 0.6em 0 1.2em; }
.docs-page p { margin: 0.5em 0; }
.docs-page ul, .docs-page ol { padding-left: 1.4em; margin: 0.4em 0 0.6em; }
.docs-page li { margin: 0.2em 0; }
.docs-page code {
  font-family: var(--font-mono); font-size: 0.85em;
  background: #f3f4f6; padding: 1px 5px; border-radius: 3px;
}
.docs-page a { color: var(--c-accent); text-decoration: none; }
.docs-page a:hover { text-decoration: underline; }
.docs-page blockquote.cite-block {
  margin: 0.6em 0 1em; padding: 0.8em 1.1em;
  background: #f9fafb; border-left: 3px solid var(--c-accent);
  border-radius: 0 6px 6px 0; font-size: 0.95em;
}
.docs-page .tbd { color: var(--c-muted); font-style: italic; }
#browse.docs-page { max-width: 80em; }
#model.docs-page { max-width: 74em; }

.welcome {
  background: var(--c-card); border: 1px solid var(--c-border);
  border-radius: 8px; padding: 1em 1.5em; max-width: 55em;
}
.welcome h2 { margin: 0 0 0.4em; font-size: 1.15em; }
.welcome a { color: var(--c-accent); text-decoration: none; }
.welcome a:hover { text-decoration: underline; }

footer {
  padding: 1.5em 2em; color: var(--c-muted); border-top: 1px solid var(--c-border);
  margin-top: 3em; background: #ffffff;
}
footer a { color: var(--c-accent); text-decoration: none; }
footer code { font-family: var(--font-mono); }

/* ── charts (charts.js) ── */
.chart-host {
  position: relative; background: #fff; border: 1px solid var(--c-border);
  border-radius: 6px; padding: 0.5em 0.6em 0.3em; margin: 0.2em 0 0.8em;
}
.chart-tip {
  position: absolute; pointer-events: none; opacity: 0; transition: opacity 90ms;
  background: #111827; color: #f9fafb; font-size: 0.78em; line-height: 1.45;
  padding: 0.45em 0.65em; border-radius: 5px; white-space: nowrap; z-index: 20;
  box-shadow: 0 4px 12px rgba(0,0,0,0.18);
}
.chart-tip.on { opacity: 1; }
.chart-tip .sw { display: inline-block; width: 8px; height: 8px; border-radius: 2px; margin-right: 5px; }
.chart-legend {
  display: flex; flex-wrap: wrap; gap: 0.4em 1.1em; justify-content: center;
  padding: 0.35em 0.2em 0.15em; font-size: 0.8em; color: var(--c-muted);
}
.chart-legend .lg { display: inline-flex; align-items: center; gap: 0.4em; }
.chart-legend .sw { width: 10px; height: 10px; border-radius: 2px; display: inline-block; }

/* ── scanner-only ── */
.input-card { max-width: 74em; }
.input-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1.2em; margin-bottom: 0.9em; }
@media (max-width: 900px) { .input-grid { grid-template-columns: 1fr; } }

/* ── one search bar, three catalogues ── */
.source-row {
  display: flex; align-items: center; gap: 1.1em; flex-wrap: wrap;
  margin: 0 0 0.5em;
}
.source-label { font-size: 0.85em; color: var(--c-muted); font-weight: 500; }
.source-row .inline-check { font-size: 0.88em; }
.rel-tag {
  font-family: var(--font-mono); font-size: 0.85em; color: var(--c-muted);
  background: var(--c-bg); border: 1px solid var(--c-border);
  border-radius: 4px; padding: 0 0.3em; margin-left: 0.15em;
}
.source-note { color: var(--c-muted); }

/* A result carries its source, because "which catalogue said so" changes what
   the number means — only the study rows have an observed label behind them. */
.src-badge {
  font-size: 0.68em; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  padding: 0.15em 0.45em; border-radius: 3px; color: #fff; flex-shrink: 0;
}
.src-study   { background: #7570b3; }
.src-ensembl { background: #d95f02; }

#search-results li.src-head {
  cursor: default; background: var(--c-bg); border-bottom: 1px solid var(--c-border);
  font-size: 0.78em; color: var(--c-muted); font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.04em; padding: 0.35em 0.7em; gap: 0.5em;
}
#search-results li.src-head:hover { background: var(--c-bg); }

/* ── the expanded window ──
   One catalogue on top of the page, a page of rows at a time. A dropdown that
   grew to hold hundreds of rows would be anchored under the input and boxed in
   by the card; this is not that. */
.modal { position: fixed; inset: 0; z-index: 100; display: flex;
         align-items: center; justify-content: center; padding: 2em 1.5em; }
.modal-backdrop { position: absolute; inset: 0; background: rgba(17, 24, 39, 0.45); }
body.modal-open { overflow: hidden; }
.modal-panel {
  position: relative; display: flex; flex-direction: column;
  width: min(62em, 100%); max-height: min(46em, 88vh);
  background: #fff; border-radius: 10px; border: 1px solid var(--c-border);
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.28);
  overflow: hidden;
}
.modal-head {
  display: flex; align-items: center; gap: 0.6em; flex-wrap: wrap;
  padding: 0.7em 0.9em; padding-right: 3.4em;   /* room for the corner button */
  border-bottom: 1px solid var(--c-border); background: var(--c-bg);
  font-size: 0.85em; color: var(--c-muted);
}
/* Pinned to the corner of the window rather than sitting in the header's flow:
   a close control belongs where every other window keeps one, and it must not
   drift when the header wraps on a narrow screen. */
.modal-close {
  position: absolute; top: 0.5em; right: 0.6em; z-index: 3;
  border: 1px solid var(--c-border); background: #fff; border-radius: 5px;
  width: 2em; height: 2em; line-height: 1; font-size: 1.15em; cursor: pointer;
  color: var(--c-muted); flex-shrink: 0;
}
.modal-close:hover { background: var(--c-accent-light); border-color: var(--c-accent); color: var(--c-accent); }
#expand-list { margin: 0; padding: 0; list-style: none; overflow-y: auto; flex: 1; }
#expand-list li {
  padding: 0.55em 0.9em; cursor: pointer; border-bottom: 1px solid var(--c-border);
  display: flex; align-items: center; gap: 0.5em;
}
#expand-list li:hover { background: var(--c-accent-light); }
#expand-list li.src-msg { cursor: default; color: var(--c-muted); font-size: 0.9em; white-space: normal; }
#expand-list li.src-msg:hover { background: transparent; }
#expand-list .sym { font-weight: 600; }
#expand-list .gid { color: var(--c-muted); font-family: var(--font-mono); font-size: 0.85em; }
#expand-list .spacer { flex: 1; }
#expand-list .badge {
  display: inline-block; padding: 1px 6px; border-radius: 8px;
  font-size: 0.75em; background: var(--c-nmd); color: #fff;
}
#expand-list .badge-mane { background: var(--c-good); }
.modal-foot {
  display: flex; align-items: center; gap: 0.7em; flex-wrap: wrap;
  padding: 0.6em 0.9em; border-top: 1px solid var(--c-border); background: var(--c-bg);
  font-size: 0.85em; color: var(--c-muted);
}
.modal-foot button:disabled { opacity: 0.4; cursor: not-allowed; }
.modal-foot button:disabled:hover { background: #fff; border-color: var(--c-border); }
#expand-note { flex-basis: 100%; margin: 0; }

/* "Show all" hands one catalogue the whole list. It sits in the group header
   rather than at the end of the rows, so it is visible without scrolling past
   the five that are already there. */
.src-expand, .src-back {
  font-family: var(--font-body); font-size: 0.95em; font-weight: 600;
  text-transform: none; letter-spacing: 0;
  color: var(--c-accent); background: #fff;
  border: 1px solid var(--c-border); border-radius: 5px;
  padding: 0.15em 0.6em; cursor: pointer; flex-shrink: 0;
}
.src-expand:hover, .src-back:hover { background: var(--c-accent-light); border-color: var(--c-accent); }
.src-back { margin-right: 0.2em; }
.src-filter {
  font-family: var(--font-body); font-size: 0.95em; text-transform: none; letter-spacing: 0;
  padding: 0.2em 0.5em; border: 1px solid var(--c-border); border-radius: 5px;
  min-width: 12em; max-width: 20em;
}
.src-filter:focus { outline: 2px solid var(--c-accent); border-color: var(--c-accent); }
#search-results li.src-msg {
  cursor: default; white-space: normal; color: var(--c-muted); font-size: 0.85em;
}
#search-results li.src-msg:hover { background: transparent; }
#search-results .spin { color: var(--c-accent); }
.field-label { display: block; font-weight: 600; font-size: 0.88em; margin: 0 0 0.35em; }
.field-label .opt { font-weight: 400; color: var(--c-muted); font-size: 0.85em; }
.field-label .req { font-weight: 500; color: var(--c-warn); font-size: 0.85em; }
.hint.tight { margin: 0.3em 0 0; font-size: 0.8em; }
.mono-input, #sequence {
  width: 100%; padding: 0.55em 0.7em; border: 1px solid var(--c-border);
  border-radius: 6px; font-family: var(--font-mono); font-size: 0.85em;
  background: #fff; color: var(--c-text); resize: vertical;
}
.mono-input:focus, #sequence:focus { outline: 2px solid var(--c-accent); border-color: var(--c-accent); }
#sequence { line-height: 1.45; letter-spacing: 0.02em; }
.seq-status { font-size: 0.82em; color: var(--c-muted); margin: 0.4em 0 0.2em; min-height: 1.2em; }
.ok-inline { color: var(--c-good); font-weight: 600; }
.warn-inline { color: var(--c-warn); font-weight: 600; }
.err-inline  { color: var(--c-bad);  font-weight: 700; }
.run-row { display: flex; align-items: center; gap: 1em; flex-wrap: wrap; margin-top: 0.7em; }
.btn-primary {
  padding: 0.55em 1.4em; border-radius: 6px; border: 1px solid var(--c-accent);
  background: var(--c-accent); color: #fff; font-weight: 600; font-size: 0.92em;
  cursor: pointer; font-family: var(--font-body);
}
.btn-primary:disabled { background: #cbd5e0; border-color: #cbd5e0; cursor: not-allowed; }
.btn-primary:not(:disabled):hover { background: #1d4ed8; }
.inline-check { display: flex; align-items: center; gap: 0.4em; font-size: 0.85em; cursor: pointer; }
/* Reset sits in the card's bottom-right corner: the note before it takes up the
   slack, so the button holds the corner however long the note runs. */
#run-note { flex: 1 1 16em; }   /* wide enough that a narrow row wraps it whole */
.btn-reset { margin-left: auto; color: var(--c-muted); }
.btn-reset:hover { color: var(--c-accent); }
.progress { height: 4px; background: #eef0f3; border-radius: 3px; margin-top: 0.8em; overflow: hidden; }
.progress span { display: block; height: 100%; background: var(--c-accent); width: 0; transition: width 120ms; }
.iso-context { margin-top: 0.7em; padding: 0.7em 0.9em; background: #f9fafb;
  border: 1px solid var(--c-border); border-radius: 6px; }
.iso-context .meta-grid { margin: 0 0 0.4em; }
#search-results li.no-hit { cursor: default; white-space: normal; color: var(--c-muted); font-size: 0.85em; }
#search-results li.no-hit code { font-family: var(--font-mono); }
/* MANE Select is the transcript most people mean, so it reads as a fact about
   the record rather than as the NMD-substrate warning the orange badge is. */
#search-results .badge-mane { background: var(--c-good); }
/* The result view is rendered by detail.js and can be on the page more than
   once at a time, so it is addressed by class rather than by id. */
#results { margin-top: 1.2em; }
.cand-table-wrap { max-height: 26em; overflow: auto; }
.cand-table { width: 100%; border-collapse: collapse; font-size: 0.82em; }
.cand-table th, .cand-table td { padding: 0.3em 0.45em; text-align: left;
  border-bottom: 1px solid var(--c-border); white-space: nowrap; }
.cand-table th { position: sticky; top: 0; background: #f3f4f6; z-index: 2;
  font-weight: 600; font-size: 0.85em; text-transform: uppercase; letter-spacing: 0.03em; }
.cand-table tr { cursor: pointer; }
.cand-table tr:hover { background: #f9fafb; }
.cand-table tr.selected { background: var(--c-accent-light); }
.cand-table td.numeric { text-align: right; font-variant-numeric: tabular-nums; }
.cand-table td.mono { font-family: var(--font-mono); }
.cand-table td.strong { font-weight: 600; }
.scan-track g[data-k]:hover rect:first-child { stroke: #111827; stroke-width: 1; }
.scan-track g.row-selected rect:first-child { stroke: #111827; stroke-width: 1.5; }
.selected-card { margin-top: 1.2em; }
.formula { font-size: 1.02em; text-align: center; margin: 0.8em 0; color: #374151; }
.notice-ok { background: #ecfdf5; border-color: var(--c-good); }
.notice-info { background: #eff6ff; border-color: var(--c-accent); }
.notice strong { display: block; margin-bottom: 0.15em; }

/* ── bulk scan ── */
#bulk .card { margin-bottom: 1.2em; }
#bulk input[type="file"] { font-size: 0.85em; max-width: 100%; }
.num-input { width: 7em; }
/* Same corner treatment as the scanner card's Reset: the estimate takes up the
   slack so the button holds the bottom-right however long the estimate runs. */
#bulk-estimate { flex: 1 1 16em; }
.bulk-stage { font-size: 0.9em; margin-bottom: 0.5em; }
.bulk-bar-row { display: flex; align-items: center; gap: 0.8em; }
.bulk-bar-row .progress { flex: 1; height: 10px; margin-top: 0; border-radius: 5px; }
.bulk-pct { font-size: 0.85em; color: var(--c-muted);
  font-variant-numeric: tabular-nums; min-width: 3.6em; text-align: right; }
.bulk-counts { font-size: 0.85em; color: var(--c-muted); margin-top: 0.5em; }
/* Length unknown — a gzipped input has no honest denominator, so the bar says
   "working" rather than inventing a percentage. */
.progress.indeterminate span {
  width: 34% !important;
  animation: bulk-sweep 1.3s ease-in-out infinite;
}
@keyframes bulk-sweep {
  0%   { margin-left: 0; }
  50%  { margin-left: 66%; }
  100% { margin-left: 0; }
}

.bulk-row {
  display: grid; grid-template-columns: 1.8em 2.2em 1fr auto auto;
  align-items: center; gap: 0.6em;
  padding: 0.4em 0.5em; border-bottom: 1px solid var(--c-border);
}
.bulk-row:hover { background: #f9fafb; }
.bulk-row.open { background: var(--c-accent-light); }
.bulk-rank { color: var(--c-muted); font-size: 0.8em;
  font-variant-numeric: tabular-nums; text-align: right; }
.bulk-star {
  background: none; border: none; cursor: pointer; padding: 0;
  font-size: 1.15em; line-height: 1; color: #cbd5e0;
}
.bulk-star:hover, .bulk-star.on { color: var(--c-warn); }
.bulk-open {
  background: none; border: none; padding: 0; text-align: left; cursor: pointer;
  font-family: var(--font-body); font-size: 1em; color: inherit;
  display: flex; align-items: baseline; gap: 0.6em; min-width: 0;
}
.bulk-open:hover .bulk-sym { text-decoration: underline; }
.bulk-sym { font-weight: 600; }
.bulk-id { font-family: var(--font-mono); font-size: 0.8em; color: var(--c-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bulk-expand {
  background: #fff; border: 1px solid var(--c-border); border-radius: 5px;
  padding: 0.15em 0.6em; font-size: 0.78em; cursor: pointer;
  font-family: var(--font-body); color: var(--c-accent);
}
.bulk-expand:hover { background: var(--c-accent-light); border-color: var(--c-accent); }
.bulk-detail { padding: 0.6em 0 1em; border-bottom: 1px solid var(--c-border); }
.bulk-detail-head { padding: 0 0.5em; }
.bulk-detail .panel-grid { grid-template-columns: 28em 1fr; }
@media (max-width: 1100px) { .bulk-detail .panel-grid { grid-template-columns: 1fr; } }

.bulk-search-input {
  width: 100%; max-width: 42em; padding: 0.6em 0.8em; font-size: 1em;
  border: 1px solid var(--c-border); border-radius: 6px; font-family: var(--font-body);
}
.bulk-search-input:focus { outline: 2px solid var(--c-accent); border-color: var(--c-accent); }
#bulk-search-results { margin-top: 0.6em; max-height: 34em; overflow-y: auto; }

/* Reuses .modal / .modal-backdrop / .modal-panel from the catalogue window
   above; only the width and the scrolling differ, because this one holds a
   whole result view rather than a list. */
.bulk-modal-panel { max-width: 84em; width: 100%; max-height: 92vh; overflow-y: auto; }
#bulk-modal-head { margin-bottom: 0.6em; }
#bulk-modal-title { display: inline-flex; align-items: baseline; gap: 0.6em; }

/* ── hover help ── */
/* A "?" beside an option, explaining what it does without spending a paragraph
   of the form on it. Hover or keyboard focus opens it, so it is reachable
   without a mouse; `title` alone would not be, and would not hold this much. */
.help {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.25em; height: 1.25em; margin-left: 0.15em;
  border: 1px solid var(--c-border); border-radius: 50%;
  font-size: 0.75em; font-weight: 700; color: var(--c-muted);
  background: #fff; cursor: help; position: relative; flex-shrink: 0;
}
.help:hover, .help:focus-visible { border-color: var(--c-accent); color: var(--c-accent); }
.help-bubble {
  position: absolute; bottom: calc(100% + 0.5em); left: 50%; transform: translateX(-50%);
  width: 26em; max-width: 80vw; z-index: 60;
  background: #111827; color: #f9fafb; text-align: left;
  font-size: 1.15em; font-weight: 400; line-height: 1.5;
  padding: 0.7em 0.9em; border-radius: 6px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
  opacity: 0; visibility: hidden; transition: opacity 120ms;
  cursor: auto;
}
.help-bubble strong { color: #fff; }
.help-bubble::after {                      /* the little tail */
  content: ""; position: absolute; top: 100%; left: 50%; margin-left: -6px;
  border: 6px solid transparent; border-top-color: #111827;
}
.help:hover .help-bubble, .help:focus .help-bubble, .help:focus-within .help-bubble {
  opacity: 1; visibility: visible;
}
/* Near the right edge the bubble would run off the card, so the last option in
   a row anchors its bubble to the right instead of centring it. */
.run-row > label:last-of-type .help-bubble { left: auto; right: -0.6em; transform: none; }
.run-row > label:last-of-type .help-bubble::after { left: auto; right: 0.6em; }

/* ── splice tab ── */
#splice .card { margin-bottom: 1.2em; }
#splice select.num-input { width: auto; padding: 0.3em 0.4em; }
#splice-results .mini-table td:first-child { white-space: nowrap; }
/* Groups and Productive share stack in one card and now share exactly one
   leading column — the group name — since the cell type moved out of the tables
   and into its own box. Pinning a second column here squeezed "productive,
   DMSO" onto two lines in the table that has no Isoforms column. */
#splice-results .mini-table th:nth-child(1),
#splice-results .mini-table td:nth-child(1) { width: 8em; }
#splice-head .meta-grid { margin-bottom: 0.6em; }
/* Isoform models. The figure sizes itself from its box's pixel width, so it
   gets a width to measure and a scroll of its own on a narrow screen rather
   than pushing the card wider. */
.models-head { display: flex; align-items: baseline; gap: 0.8em; }
.models-head h3, .models-head h4 { margin: 0; }
.models-head .btn-nav { margin-left: auto; font-size: 0.8em; padding: 0.25em 0.7em; }
/* The count of unproductive isoforms, above the figure. Its colour is set from
   splice_models.js so it is the same value the dots are drawn with. */
.unprod-line { margin: 0.35em 0 0; font-size: 0.88em; font-weight: 600; }
.unprod-line:empty { display: none; }
.unprod-line .dot { font-size: 1.1em; line-height: 1; }
.unprod-line .rest { font-weight: 400; color: var(--c-muted); }

/* The two feature menus stack in one field and must read as one control, so
   they share the size of every other box on the card rather than being shrunk
   to fit their longest option. */
#splice-intron, #splice-exon { margin-top: 0.35em; }
#splice-intron { margin-top: 0; }
#splice-models { width: 100%; overflow-x: auto; margin: 0.4em 0 0.6em; }
#splice-models svg { display: block; min-width: 620px; }
#splice-models text { pointer-events: none; }

/* The expression filter. */
.filter-row {
  display: flex; align-items: center; gap: 1.1em; flex-wrap: wrap;
  margin: 0.5em 0 0.2em; padding: 0.5em 0.7em;
  background: #f9fafb; border: 1px solid var(--c-border); border-radius: 6px;
}
.filter-slider { display: flex; align-items: center; gap: 0.55em; font-size: 0.85em; }
.filter-slider input[type="range"] { width: 170px; }
.floor-input { width: 6.2em; padding: 0.2em 0.4em; font-size: 0.9em; }
.floor-unit { font-size: 0.85em; color: var(--c-muted); margin-left: -0.25em; }
/* The two conditions and the rule that combines them read as one control, the
   way the atlas groups them, so the rule is visibly about the boxes beside it
   rather than a stray pair of radios. */
.combine-group {
  display: inline-flex; align-items: center; gap: 0.7em;
  padding: 0.2em 0.6em; border: 1px solid var(--c-border); border-radius: 6px;
  background: #fff;
}
.combine-sep {
  width: 1px; align-self: stretch; margin: 0.15em 0.1em; background: var(--c-border);
}
.filter-slider output {
  min-width: 6.5em; text-align: right; font-size: 0.9em;
  font-variant-numeric: tabular-nums; color: var(--c-muted);
}

/* The aim readout, above the figure it belongs to. It keeps its place in the
   layout when idle rather than collapsing, so the figure does not jump the
   moment the cursor enters it. */
.pick-aim {
  font-size: 0.85em; padding: 0.45em 0.7em; border-radius: 5px;
  background: #fffbeb; border: 1px solid #fde68a; margin-top: 0.5em;
  /* ONE LINE, ALWAYS. The figure sits directly below this box and is aimed at by
     cursor position. If the text reflows from one line to two when the readout
     changes, everything under it shifts by a line — and the click then lands on
     a different row than the hover reported. That is exactly what happened:
     hovering an exon produced a shorter message, the box shrank, the figure rose
     38px, and the click selected the junction now under the cursor instead. */
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  /* Explicit, so a bold word in the readout cannot make the line a pixel
     taller than the plain idle text and nudge the figure. */
  line-height: 1.45;
}
.pick-aim:empty { display: none; }
.pick-aim .muted { color: var(--c-muted); }
/* Results the boxes above no longer describe. They stay legible — the numbers
   are still real, they are just about a different question — but recede, so no
   one reads them as an answer to what is currently typed. */
#splice-results.stale .card { opacity: 0.5; }
#splice-stale { margin-bottom: 0.8em; }
#splice-stale:empty { display: none; }
/* A cell type's two rows read as one block: the rule goes above the first. */
.mini-table tr.ct-first td { border-top: 2px solid var(--c-border); }
.mini-table tr.ct-first:first-child td { border-top: none; }

/* Gene suggestions on the Splice tab — the catalogue search's list, reused. */
.suggest-wrap { position: relative; }
#splice-gene-results {
  position: absolute; top: 100%; left: 0; right: 0; z-index: 10;
  margin: 0.2em 0 0; padding: 0; list-style: none; max-height: 22em; overflow-y: auto;
  background: #fff; border: 1px solid var(--c-border); border-radius: 6px;
  box-shadow: 0 4px 12px rgba(0,0,0,0.08);
}
#splice-gene-results:empty { display: none; }
#splice-gene-results li {
  padding: 0.45em 0.8em; cursor: pointer; border-bottom: 1px solid var(--c-border);
}
#splice-gene-results li:last-child { border-bottom: none; }
#splice-gene-results li:hover,
#splice-gene-results li.highlight { background: var(--c-accent-light); }
#splice-gene-results .sym { font-weight: 600; }
#splice-gene-results li.no-hit {
  cursor: default; color: var(--c-muted); font-size: 0.85em; white-space: normal;
}
