/* Design tokens and layout for the PMI proteome annotator (forked from the S. mutans one).
   Dark navy surfaces; teal for the annotator, amber for the evidence column (the S. mutans
   prior's colour), blue for propagated calls. The amber is warm but *unfilled* — a rule and
   a label, never a fill: the visual grammar has to keep "what the evidence says" distinct
   from "known to be right", because here nothing is known to be right. */

:root {
  --ground: #0a0e1a;
  --surface: #0f1629;
  --raise: #16203a;
  --rule: #1e2d4a;
  --rule-soft: #172440;

  --ink: #e7edf8;
  --ink-2: #9aa9c3;
  --ink-3: #66748f;

  --teal: #00e5c3;         /* the annotator */
  --amber: #f59e0b;        /* the prior */
  --violet: #a78bfa;       /* the dark population */
  --blue: #60a5fa;
  --rose: #fb7185;

  /* Layout is fluid. There is no shell cap and no reading measure: every region grows
     with the window, and text fills the box drawn around it rather than stopping short of
     it. A capped shell left the far side of a large monitor empty, and a measure narrower
     than its panel left a gutter down the right of every paragraph — both read as the
     layout being broken, which is the more expensive failure here than a long line. */

  --amber-wash: rgba(245, 158, 11, .07);
  --violet-wash: rgba(167, 139, 250, .09);
  --teal-wash: rgba(0, 229, 195, .08);

  /* The review region reads as a different surface, not a tinted one (2026-09-17). A
     collaborator asked for it to stand out, and the panel had no treatment at all while the
     prior carried an amber wash: the one region a reviewer is here to act in was the one
     that looked least like anything. Teal because it already means "your action" inside this
     panel — the selected verdict and the primary save are both teal — and because no panel
     owned a teal ground. Lighter than `--surface` rather than darker: in a dark interface,
     nearer the viewer is lighter, and this is the nearest thing on the page.
     `--review-well` is where its controls sit, darker than the panel so inputs still read as
     inset. Both are measured in tests/test_contrast.py against everything drawn on them. */
  --review-surface: #16324a;
  --review-well: #102338;

  /* Tier is ordinal, so it gets one hue stepped by confidence rather than three
     categorical colours — a scale should read as a scale. */
  --tier-a: #00e5c3;
  --tier-b: #3fae9c;
  --tier-c: #4a7d78;
  --tier-none: #4b5563;

  --radius: 4px;
  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --sans: "IBM Plex Sans", ui-sans-serif, system-ui, sans-serif;
  --serif: "Playfair Display", Georgia, serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--teal); text-decoration: none; }
a:hover { text-decoration: underline; }
:focus-visible { outline: 2px solid var(--teal); outline-offset: 2px; }

code, .mono { font-family: var(--mono); }

/* ------------------------------------------------------------------ app shell */
.shell { margin: 0 auto; padding: 0 22px 80px; }

.topbar {
  display: flex; align-items: baseline; gap: 26px; flex-wrap: wrap;
  padding: 20px 0 16px; border-bottom: 1px solid var(--rule); margin-bottom: 26px;
}
.topbar .brand {
  font-family: var(--serif); font-size: 1.22rem; font-weight: 600; letter-spacing: -.01em;
  color: var(--ink);
}
.topbar .brand em { font-style: italic; }
.topbar nav { display: flex; gap: 18px; }
.topbar nav a {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .13em; text-transform: uppercase;
  color: var(--ink-3);
}
.topbar nav a.active { color: var(--teal); }
.topbar .spacer { flex: 1; }
.topbar .note {
  font-family: var(--mono); font-size: 11px; color: var(--ink-3); letter-spacing: .06em;
}

/* -------------------------------------------------------------------- controls */
.scopebar { display: flex; gap: 2px; flex-wrap: wrap; margin-bottom: 18px; }
.scopebar a {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .1em; text-transform: uppercase;
  padding: 8px 14px; border: 1px solid var(--rule); border-radius: 2px;
  color: var(--ink-2); background: var(--surface);
}
.scopebar a:hover { color: var(--ink); text-decoration: none; }
.scopebar a .n { color: var(--ink-3); margin-left: 8px; font-variant-numeric: tabular-nums; }
.scopebar a.sel { color: var(--ground); font-weight: 600; }
.scopebar a.sel .n { color: inherit; opacity: .72; }
/* One rule per scope key (`sel reps` etc.): a selected scope with no rule of its own draws
   dark ink on the dark ground and disappears — which is what the S. mutans keys did here. */
.scopebar a.sel.reps,
.scopebar a.sel.all { background: var(--teal); border-color: var(--teal); }
.scopebar a.sel.members { background: var(--blue); border-color: var(--blue); }

/* The queue's controls, grouped by what each filter is *about* (§14). They were a flat
   stack of six identical rows: a reviewer looking for "the prior" had to read all of them
   to find which was which. Column layout so each group's heading sits above its rows and
   the eye can skip a whole subject at once. */
.filters {
  display: flex; flex-direction: column; gap: 14px; align-items: stretch;
  padding: 15px 16px 14px; background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--radius); margin-bottom: 0;
}
.fgroup { display: flex; gap: 14px; align-items: baseline; flex-wrap: wrap; }
.fgroup .gname {
  flex: 0 0 96px; font-family: var(--mono); font-size: 9.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-2); padding-top: 4px;
}
.fgroup .grows { display: flex; flex-direction: column; gap: 7px; flex: 1 1 auto; }
.frow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.frow label { min-width: 58px; }
@media (max-width: 700px) {
  .fgroup { flex-direction: column; gap: 6px; }
  .fgroup .gname { flex: none; }
}

/* Independent toggles, not one exclusive choice. The five rows above answer "which one";
   this answers "which of these are true", and identical styling had a reviewer expecting a
   click here to clear the last one. The dotted rule is the whole distinction, so it stays
   quiet — a second colour would read as a third kind of control. */
.toggles.boolean { padding-left: 9px; border-left: 1px dashed var(--rule); }

/* The search scope. Not a filter: it says which columns the box is tested against, so it
   has no "any" and narrows nothing by itself. Set apart from the filter rows because
   wearing their styling it read as a seventh filter missing its unfiltered option. */
.frow.searchrow { margin-bottom: 4px; padding-bottom: 12px; border-bottom: 1px solid var(--rule-soft); }
.toggles.searchin a { font-size: 10.5px; }

/* What the filters actually leave, and the way back out. The queue reported its scope total
   whatever was applied: narrowing Dark to Tier A left 20 proteins under a header still
   reading 199. */
.narrowed {
  display: flex; align-items: baseline; gap: 9px; margin: 9px 2px 18px;
  font-size: 12.5px; color: var(--ink-3);
}
.narrowed .n { font-family: var(--mono); font-size: 13px; color: var(--ink-2); }
.narrowed.on .n { color: var(--teal); }
.narrowed .clearall {
  margin-left: 6px; font-family: var(--mono); font-size: 10.5px; letter-spacing: .08em;
  color: var(--ink-3); border-bottom: 1px solid var(--rule);
}
.narrowed .clearall:hover { color: var(--ink); border-color: var(--ink-3); }
.filters label {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--ink-3); margin-right: 6px;
}
.filters .Select, .filters .dash-dropdown { min-width: 150px; }
.filters .dash-input-container { width: 240px; }
.filters input[type="text"] {
  background: var(--raise); border: 1px solid var(--rule); border-radius: 2px;
  color: var(--ink); padding: 7px 10px; font-family: var(--sans); font-size: 13px;
  width: 100%;
}
.filters input[type="text"]::placeholder { color: var(--ink-3); }

.toggles { display: flex; gap: 6px; flex-wrap: wrap; }
.toggles a {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase;
  padding: 5px 10px; border: 1px solid var(--rule); border-radius: 2px; color: var(--ink-3);
}
.toggles a:hover { color: var(--ink-2); text-decoration: none; }
.toggles a.on { border-color: var(--teal); color: var(--teal); background: var(--teal-wash); }

/* ----------------------------------------------------------------------- table */
.tablewrap { border: 1px solid var(--rule); border-radius: var(--radius); overflow-x: auto; }
table.proteome { width: 100%; border-collapse: collapse; font-size: 13.5px; min-width: 900px; }
table.proteome th {
  position: sticky; top: 0; z-index: 1;
  text-align: left; padding: 11px 14px; background: var(--raise);
  font-family: var(--mono); font-weight: 500; font-size: 10.5px;
  letter-spacing: .13em; text-transform: uppercase; color: var(--ink-3);
  border-bottom: 1px solid var(--rule); white-space: nowrap;
}
table.proteome td {
  padding: 11px 14px; border-bottom: 1px solid var(--rule-soft); vertical-align: top;
}
table.proteome tr:last-child td { border-bottom: 0; }
table.proteome tbody tr:hover { background: var(--raise); }
table.proteome td.lt { white-space: nowrap; }
table.proteome td.lt a { font-family: var(--mono); font-weight: 600; }
table.proteome td.prior { color: var(--ink-2); max-width: 300px; }
table.proteome td.call { max-width: 420px; }
.dimmed { color: var(--ink-3); font-style: italic; }

.pager {
  display: flex; gap: 14px; align-items: baseline; justify-content: space-between;
  padding: 16px 2px; font-family: var(--mono); font-size: 12px; color: var(--ink-3);
  flex-wrap: wrap;
}
.pager a { font-family: var(--mono); font-size: 12px; }
.pager .disabled { color: var(--rule); }

/* ---------------------------------------------------------------------- chips */
.chip {
  display: inline-block; font-family: var(--mono); font-size: 10px; letter-spacing: .09em;
  text-transform: uppercase; padding: 2px 7px; border-radius: 2px;
  border: 1px solid var(--rule); color: var(--ink-2); white-space: nowrap;
}
.chip + .chip { margin-left: 4px; }
.chip.on { border-color: var(--teal); color: var(--teal); }
.chip.essential { border-color: var(--rose); color: var(--rose); }
.chip.metabolic { border-color: var(--blue); color: var(--blue); }
.chip.curated { border-color: var(--amber); color: var(--amber); }

.tier {
  display: inline-block; font-family: var(--mono); font-size: 10px; font-weight: 600;
  letter-spacing: .1em; padding: 2px 8px; border-radius: 2px; color: var(--ground);
}
.tier.A { background: var(--tier-a); }
.tier.B { background: var(--tier-b); }
.tier.C { background: var(--tier-c); color: var(--ink); }
.tier.none { background: var(--tier-none); color: var(--ink-2); }

.provchip {
  display: inline-block; font-family: var(--mono); font-size: 9.5px; letter-spacing: .1em;
  padding: 2px 6px; border-radius: 2px; border: 1px solid currentColor;
}
.provchip.RECOVERED { color: var(--teal); }
.provchip.NEW { color: var(--violet); }
.provchip.REFINED { color: var(--blue); }
.provchip.CONCORDANT { color: var(--ink-3); }
.provchip.DIVERGENT { color: var(--amber); }
.provchip.DECLINED { color: var(--ink-3); border-style: dashed; }

/* ------------------------------------------------------------- protein detail */
.detailhead {
  display: flex; gap: 18px; align-items: baseline; flex-wrap: wrap;
  padding: 16px 18px; background: var(--surface); border: 1px solid var(--rule);
  border-radius: var(--radius); margin-bottom: 2px;
}
.detailhead .lt { font-family: var(--mono); font-size: 1.25rem; font-weight: 600; }
.detailhead .sub { color: var(--ink-3); font-size: 13px; }
.detailhead .spacer { flex: 1; }
.detailhead .nav { font-family: var(--mono); font-size: 12px; color: var(--ink-3); }
.detailhead .nav > * { margin-left: 10px; }
.detailhead .nav > *:first-child { margin-left: 0; }

.cols { display: grid; grid-template-columns: 1fr 1fr; gap: 2px; margin-bottom: 2px; }
@media (max-width: 950px) { .cols { grid-template-columns: 1fr; } }

.panel {
  background: var(--surface); border: 1px solid var(--rule); border-radius: var(--radius);
  padding: 18px 20px;
}
.panel.prior { background: linear-gradient(100deg, var(--amber-wash), transparent 70%); }
/* `--ink-3` on `--surface` is 3.82:1 — below the 4.5:1 WCAG AA needs for text this size,
   and a reviewer reported the review panel as "small and dark font". `--ink-2` is 7.57:1,
   which clears AA and AAA while staying visibly quieter than the body text it sits above.
   The accent overrides below are unaffected: amber is 8.38:1 and violet 6.61:1 already. */
.panel h3 {
  margin: 0 0 14px; font-family: var(--mono); font-size: 10.5px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-2); font-weight: 500;
  display: flex; justify-content: space-between; gap: 12px; align-items: baseline;
}
.panel.prior h3 { color: var(--amber); }

.srcrow { display: grid; grid-template-columns: 78px 1fr; gap: 5px 14px; font-size: 13px; }
.srcrow dt {
  font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); letter-spacing: .05em;
  padding-top: 2px;
}
.srcrow dd { margin: 0; }
.srcrow dd.absent { color: var(--ink-3); }

.callout { font-size: 15px; line-height: 1.55; margin: 0 0 16px; }
.callout.declined { color: var(--ink-3); font-style: italic; }

details.disc { margin-top: 8px; border-top: 1px solid var(--rule-soft); padding-top: 8px; }
details.disc > summary {
  cursor: pointer; font-family: var(--mono); font-size: 11px; letter-spacing: .08em;
  color: var(--ink-2); list-style: none;
}
details.disc > summary::-webkit-details-marker { display: none; }
details.disc > summary::before { content: "▸ "; color: var(--ink-3); }
details.disc[open] > summary::before { content: "▾ "; }
details.disc .body {
  margin-top: 10px; font-size: 13px; color: var(--ink-2); line-height: 1.62;
  white-space: pre-wrap; max-height: 420px; overflow-y: auto;
}

/* A disclosure inside a disclosure. Indented against a rule so the nesting is visible when
   both are open — otherwise "why these terms" reads as a sibling of the GO section rather
   than as part of it, and the reader cannot tell what it is scoped to. */
details.disc.nested {
  margin: 0 0 14px; padding: 0 0 0 11px; border-top: 0; border-left: 1px solid var(--rule);
}

/* Methods, restructured. The page was 2,155 words in seven always-open sections; a reader
   arriving with one question met nine minutes of prose with nothing to steer by. Each
   section now shows its claim and opens for the argument. */
.panel.orientation { border-left: 3px solid var(--teal); }

/* The landing page's opening. It used to start on the bare number 1,962 with no sentence
   anywhere saying what had been counted — a poor way to meet a tool whose whole argument is
   about what it does not claim. */
.panel.lede-block { border-left: 3px solid var(--teal); }
.lede { margin: 0; font-size: 15px; line-height: 1.62; color: var(--ink-2); max-width: 86ch; }
.lede.sub { margin-top: 11px; font-size: 13.5px; color: var(--ink-3); }

/* The three cross-tabs, under one heading. Stacked as separate regions they were three
   dense grids in a row with nothing saying they shared an axis. The inner panels lose their
   own frame so the group reads as one region rather than as four nested boxes. */
.panel.tabgroup > .panel {
  border: 0; background: none; padding: 0; margin: 22px 0 0;
  border-top: 1px solid var(--rule-soft); padding-top: 18px;
}
.panel.tabgroup > .panel:first-of-type { border-top: 0; padding-top: 0; }
.panel.tabgroup .note.lead { margin: 0 0 4px; max-width: 84ch; color: var(--ink-2); }
.panel.tabgroup h3 .sub { color: var(--ink-3); }
.panel.orientation p:first-child { font-size: 15px; color: var(--ink-2); }

details.chapter {
  border: 1px solid var(--rule); border-radius: 2px; background: var(--surface);
  padding: 15px 18px; margin-bottom: 2px;
}
details.chapter > summary {
  cursor: pointer; list-style: none; display: flex; flex-direction: column; gap: 5px;
}
details.chapter > summary::-webkit-details-marker { display: none; }
details.chapter > summary .ctitle {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .13em; text-transform: uppercase;
  color: var(--ink);
}
details.chapter > summary .ctitle::before { content: "▸ "; color: var(--ink-3); }
details.chapter[open] > summary .ctitle::before { content: "▾ "; }
/* The summary carries the section's actual claim, not a teaser — a reader who never opens
   one has still read what it argues — so it is set as readable prose, not as a label. */
details.chapter > summary .csum {
  font-size: 13px; line-height: 1.55; color: var(--ink-2); padding-left: 15px; max-width: 80ch;
}
details.chapter[open] > summary .csum { color: var(--ink-3); }
details.chapter .cbody { margin-top: 16px; padding-left: 15px; }
details.chapter .cbody > h4:first-child { margin-top: 0; }

/* The reference. Two columns where there is room: these are looked up, not read through,
   and a 46-entry single column is a scroll rather than a glance. */
.glossary { display: grid; grid-template-columns: 1fr 1fr; gap: 26px 34px; }
@media (max-width: 900px) { .glossary { grid-template-columns: 1fr; } }
.gblock h4 { margin: 0 0 5px; }
.gblock .glede {
  margin: 0 0 11px; font-size: 12.5px; line-height: 1.55; color: var(--ink-3);
}
.srcrow.gloss { grid-template-columns: 132px 1fr; row-gap: 8px; align-items: baseline; }
.srcrow.gloss dt { font-family: var(--mono); font-size: 11px; color: var(--ink-2); }
/* Landing from a chip link: the browser jumps to the id and the row says so briefly, so a
   reader arriving mid-page can see which of 46 rows they were sent to. */
.srcrow.gloss dt:target { color: var(--teal); }
.srcrow.gloss dt:target + dd { border-left: 2px solid var(--teal); padding-left: 9px; }

/* A mark that links to its own definition. Deliberately not styled as a link — it is still
   a chip, and underlining 46 of them would turn the queue into a page of hyperlinks. */
a.provchip, a.chip, a.tier { text-decoration: none; cursor: help; }
a.provchip:hover, a.chip:hover, a.tier:hover { border-color: currentColor; }
details.disc.nested > summary { font-size: 10.5px; }
details.disc.nested .body { max-height: 300px; }

/* GO terms — provenance for the call (§9), so they sit in the call's column and take its
   grammar. Deliberately without a colour ramp on the confidence: the extractor's label is
   not calibrated against anything, and green/amber/red would render a measurement nobody
   made — the same error the prior's unfilled amber exists to avoid. */
details.disc .body.golist { white-space: normal; }
.golist .goasp {
  margin: 13px 0 5px; font-family: var(--mono); font-size: 10.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--ink-3);
}
.golist .goasp:first-child { margin-top: 0; }
.golist dl.goterms { margin: 0; }
.golist dl.goterms dt {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; margin-top: 9px;
}
.golist .goid { font-family: var(--mono); font-size: 11.5px; }
.golist .golabel { color: var(--ink); font-size: 13px; }
.golist .goconf {
  font-family: var(--mono); font-size: 10px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-3); border: 1px solid var(--rule); border-radius: 2px; padding: 1px 5px;
}
.golist dl.goterms dd {
  margin: 3px 0 0; padding-left: 10px; border-left: 1px solid var(--rule-soft);
  font-size: 12.5px; line-height: 1.55;
}
.golist .gospan { color: var(--ink-2); }
.golist .gosrc { color: var(--ink-3); }
.golist .empty { padding: 4px 0; }

.provenance {
  margin-top: 16px; padding-top: 13px; border-top: 1px solid var(--rule);
  font-family: var(--mono); font-size: 11px;
}
.provenance .caveat {
  display: block; margin-top: 6px; font-family: var(--sans); font-size: 11.5px;
  color: var(--ink-3);
}

/* -------------------------------------------------------------- sequence view */
.seqpanel { margin-bottom: 2px; }
.seq {
  font-family: var(--mono); font-size: 11.5px; line-height: 1.85; color: var(--ink-2);
  word-break: break-all; margin: 10px 0 14px; user-select: all;
}
.domtrack { display: flex; flex-direction: column; gap: 3px; }
.domrow { display: grid; grid-template-columns: 84px 1fr 96px; gap: 12px; align-items: center; }
.domrow .db {
  font-family: var(--mono); font-size: 10px; color: var(--ink-3); letter-spacing: .06em;
}
.domrow .lane { position: relative; height: 11px; background: var(--raise); border-radius: 2px; }
.domrow .lane i {
  position: absolute; top: 0; bottom: 0; border-radius: 2px; background: var(--teal);
  opacity: .82;
}
.domrow .coords {
  font-family: var(--mono); font-size: 10px; color: var(--ink-3); text-align: right;
  font-variant-numeric: tabular-nums;
}
.domrow .name { font-size: 12px; color: var(--ink-2); }

/* ---------------------------------------------------------------- evidence rail */
.railgroup { margin-top: 2px; }
.railgroup .grouplabel {
  font-family: var(--mono); font-size: 10px; letter-spacing: .15em; text-transform: uppercase;
  color: var(--ink-3); padding: 12px 20px 8px;
}
.railgroup.added .grouplabel { color: var(--violet); }
.tabs { display: flex; gap: 5px; flex-wrap: wrap; padding: 0 20px 14px; }
.tabs a {
  font-family: var(--mono); font-size: 11px; padding: 6px 11px; border-radius: 2px;
  border: 1px solid var(--rule); color: var(--ink-2);
}
.tabs a:hover { color: var(--ink); text-decoration: none; }
.tabs a.sel { background: var(--teal); border-color: var(--teal); color: var(--ground); font-weight: 600; }
.railgroup.added .tabs a { border-color: var(--rule); }
.railgroup.added .tabs a.sel { background: var(--violet); border-color: var(--violet); }
/* Absent evidence is a disabled tab with an em-dash, never a hidden one. */
.tabs span.off {
  font-family: var(--mono); font-size: 11px; padding: 6px 11px; border-radius: 2px;
  border: 1px dashed var(--rule); color: var(--ink-3); opacity: .7; cursor: not-allowed;
}

.evbody { padding: 4px 20px 20px; }
.transferred {
  display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap;
  padding: 9px 12px; margin-bottom: 14px; border-radius: 2px;
  border: 1px solid var(--rule); border-left: 3px solid var(--amber);
  background: var(--amber-wash); font-size: 12.5px; color: var(--ink-2);
}
.transferred b { font-family: var(--mono); font-size: 11px; color: var(--amber); letter-spacing: .1em; }

.withheld {
  font-family: var(--mono); font-size: 11px; color: var(--ink-3); padding-top: 10px;
}

table.ev { width: 100%; border-collapse: collapse; font-size: 12.5px; }
table.ev th {
  text-align: left; padding: 0 12px 8px 0; font-family: var(--mono); font-weight: 500;
  font-size: 10px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3);
  border-bottom: 1px solid var(--rule);
}
table.ev td { padding: 8px 12px 8px 0; border-bottom: 1px solid var(--rule-soft); vertical-align: top; }
table.ev td.num { font-family: var(--mono); font-variant-numeric: tabular-nums; text-align: right; }
/* A header follows its own column. Left-aligned labels over right-aligned numbers put
   every label roughly one column left of its data. */
table.ev th.num { text-align: right; }
table.proteome th.num { text-align: right; }
table.ev tr.curated td { background: var(--amber-wash); }

.bar { position: relative; height: 8px; background: var(--raise); border-radius: 2px; min-width: 60px; }
.bar i { position: absolute; left: 0; top: 0; bottom: 0; border-radius: 2px; background: var(--teal); }
.bar.warm i { background: var(--amber); }

.fitbar { display: flex; align-items: center; gap: 8px; }
.fitbar .track { position: relative; width: 120px; height: 9px; background: var(--raise); border-radius: 2px; }
.fitbar .track .mid { position: absolute; left: 50%; top: -2px; bottom: -2px; width: 1px; background: var(--rule); }
.fitbar .track i { position: absolute; top: 0; bottom: 0; border-radius: 2px; }
.fitbar .track i.neg { background: var(--rose); }
.fitbar .track i.pos { background: var(--teal); }

/* -------------------------------------------------------------- gene arrow track */
.genetrack { display: flex; gap: 4px; align-items: stretch; overflow-x: auto; padding: 6px 0 12px; }
.gene {
  position: relative; min-width: 132px; flex: 0 0 auto; padding: 9px 12px;
  border: 1px solid var(--rule); border-radius: 2px; background: var(--surface);
  font-size: 12px; color: var(--ink-2);
}
.gene.query { border-color: var(--teal); background: var(--teal-wash); color: var(--ink); }
.gene .strand { font-family: var(--mono); font-size: 10px; color: var(--ink-3); }
.gene .nm { display: block; color: var(--ink); margin: 2px 0 3px; font-size: 12.5px; }
.gene .meta { font-family: var(--mono); font-size: 9.5px; color: var(--ink-3); }
.trackscale {
  font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); padding-bottom: 6px;
}

.selector { display: flex; gap: 5px; flex-wrap: wrap; padding-bottom: 12px; }
.selector a {
  font-family: var(--mono); font-size: 10.5px; padding: 4px 9px; border-radius: 2px;
  border: 1px solid var(--rule); color: var(--ink-3);
}
.selector a.sel { border-color: var(--teal); color: var(--teal); }

.empty {
  padding: 26px 4px; color: var(--ink-3); font-size: 13px;
}
.curated-card {
  border: 1px solid var(--rule); border-left: 3px solid var(--amber); border-radius: 2px;
  background: var(--amber-wash); padding: 14px 16px; margin-bottom: 12px;
}
.curated-card .head {
  display: flex; gap: 12px; align-items: baseline; flex-wrap: wrap;
  font-family: var(--mono); font-size: 10.5px; color: var(--amber); letter-spacing: .08em;
  margin-bottom: 8px;
}
.curated-card .ann { font-size: 14px; color: var(--ink); margin-bottom: 8px; }
.curated-card .comment { font-size: 13px; color: var(--ink-2); line-height: 1.6; }

.snippet { border-left: 2px solid var(--rule); padding: 2px 0 2px 14px; margin-bottom: 16px; }
.snippet .cite { font-size: 12.5px; margin-bottom: 5px; }
.snippet .cite .journal { color: var(--ink-3); }
.snippet .text { font-size: 13px; color: var(--ink-2); line-height: 1.6; }
.snippet .unresolved { font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); }

/* ------------------------------------------------------------------ review panel */
.panel.review {
  margin-bottom: 2px;
  background: var(--review-surface);
  border-color: var(--teal);
  /* A border alone reads as a selected state; a border plus a lifted ground reads as a
     region. The glow is what carries it at a glance without becoming a highlight. */
  box-shadow: 0 0 0 1px var(--teal-wash), 0 6px 24px -12px rgba(0, 229, 195, .35);
}
.panel.review h3 { align-items: center; }
/* The one thing on this page a reviewer is here to do. Every other panel heading labels
   something to read; this one asks the question the whole dashboard exists to put. It was
   10.5px in the dimmest ink on the palette, and §17 had just moved the panel onto the first
   screen precisely so it would be seen. 13px in full `--ink` is 15.31:1, and the smaller
   tracking keeps it from shouting at a size that no longer needs the letter-spacing to
   read as a heading. */
.panel.review h3 > span:first-child {
  font-size: 13px; letter-spacing: .06em; color: var(--ink); font-weight: 600;
  text-transform: none;
}
/* The question is the shrinkable half; the input must keep its intrinsic width or
   flexbox squeezes it to the label and the field overflows the panel. */
.panel.review h3 > span:first-child { min-width: 0; }
.namefield { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.namefield label {
  font-family: var(--mono); font-size: 10px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-2);
}
/* Dash 4 wraps every dcc.Input in a `.dash-input-container` div. Styling the <input>
   alone leaves that wrapper at 2px, so the field overflows whatever contains it — the
   wrapper is what needs to carry the width. */
.dash-input-container, .dash-input { display: inline-flex; flex: 0 0 auto; }
.namefield .dash-input-container { width: 190px; }
.namefield input {
  background: var(--review-well); border: 1px solid var(--rule); border-radius: 2px;
  color: var(--ink); padding: 6px 10px; font-family: var(--sans); font-size: 13px;
  width: 100%;
}
/* Placeholders stay `--ink-3` deliberately: a placeholder that reads as strongly as a
   value is a field that looks filled when it is empty. They are not content. */
.namefield input::placeholder { color: var(--ink-3); }

.verdicts { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 4px; }
button.verdict {
  display: inline-flex; align-items: baseline; gap: 8px;
  font-family: var(--mono); font-size: 12px; padding: 8px 14px; border-radius: 2px;
  border: 1px solid var(--rule); background: var(--review-well); color: var(--ink-2);
  cursor: pointer;
}
button.verdict:hover { color: var(--ink); border-color: var(--ink-3); }
button.verdict .key { font-size: 10.5px; color: var(--ink-2); }
button.verdict.sel {
  background: var(--teal); border-color: var(--teal); color: var(--ground); font-weight: 600;
}
button.verdict.sel .key { color: var(--ground); opacity: .6; }

.seeds { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin-bottom: 8px; }
.seedlabel {
  font-family: var(--mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-2);
}
button.seed {
  font-family: var(--mono); font-size: 11px; padding: 4px 9px; border-radius: 2px;
  border: 1px solid var(--rule); background: transparent; color: var(--ink-2); cursor: pointer;
}
button.seed:hover:not(:disabled) { border-color: var(--teal); color: var(--teal); }
button.seed:disabled { color: var(--rule); cursor: not-allowed; }

.panel.review textarea {
  width: 100%; background: var(--review-well); border: 1px solid var(--rule); border-radius: 2px;
  color: var(--ink); padding: 9px 11px; font-family: var(--sans); font-size: 13px;
  line-height: 1.55; resize: vertical;
}
.panel.review textarea::placeholder { color: var(--ink-3); }

.saverow {
  display: flex; align-items: center; gap: 10px; margin-top: 14px; padding-top: 13px;
  border-top: 1px solid var(--rule); flex-wrap: wrap;
}
.saverow .spacer { flex: 1; }
.saverow .status { font-size: 12.5px; color: var(--ink-2); }
.saverow .status.ok { color: var(--teal); }
.saverow .status.err { color: var(--amber); }
button.save {
  font-family: var(--mono); font-size: 12px; padding: 8px 16px; border-radius: 2px;
  border: 1px solid var(--rule); background: var(--review-well); color: var(--ink-2); cursor: pointer;
}
button.save:hover:not(:disabled) { color: var(--ink); border-color: var(--ink-3); }
button.save.primary { border-color: var(--teal); color: var(--teal); }
button.save.primary:hover:not(:disabled) { background: var(--teal); color: var(--ground); }
button.save:disabled { color: var(--rule); border-color: var(--rule-soft); cursor: not-allowed; }
.saverow .kbd { font-family: var(--mono); font-size: 11px; color: var(--ink-2); }

/* The dataset download offers two bundles side by side. Equal columns on purpose: the small
   one is not a lesser version of the large one, it is the right answer for a different
   reader, and sizing it down would say otherwise. Stacks below 640px. */
.dlgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 4px; }
.dlgrid .dlopt { display: flex; flex-direction: column; align-items: flex-start; gap: 9px; }
.dlgrid .dlopt button.save { white-space: nowrap; }
.dlgrid .dlnote {
  margin: 0; font-size: 12.5px; line-height: 1.55; color: var(--ink-3);
}
@media (max-width: 640px) { .dlgrid { grid-template-columns: 1fr; } }
.dlstatus {
  margin-top: 12px; min-height: 16px; font-family: var(--mono); font-size: 11.5px;
  color: var(--teal);
}

/* The working indicator, inside the button that was pressed. Drawn rather than animated as
   an image so it inherits nothing and costs no request. Teal — not currentColor — because a
   disabled button's text is deliberately near-invisible, and the one element that has to
   stay legible while the button is dead is this one. */
button.save .spin {
  display: inline-block; width: 11px; height: 11px; margin-right: 9px; vertical-align: -1px;
  border: 2px solid var(--teal); border-right-color: transparent; border-radius: 50%;
  animation: btnspin .6s linear infinite;
}
/* Beats the UA's [hidden] rule, which the display above would otherwise override. */
button.save .spin[hidden] { display: none; }
@keyframes btnspin { to { transform: rotate(360deg); } }
/* Still turns, slowly: a frozen ring beside a disabled button reads as a crash rather than
   as work in progress, which is the opposite of what the indicator is for. */
@media (prefers-reduced-motion: reduce) {
  button.save .spin { animation-duration: 2.4s; }
}

.otherreview { padding: 8px 0; border-bottom: 1px solid var(--rule-soft); }
.otherreview:last-child { border-bottom: 0; }
.otherreview .who { font-weight: 600; margin-right: 10px; }
.verdictchip {
  font-family: var(--mono); font-size: 10px; letter-spacing: .08em; padding: 2px 7px;
  border: 1px solid var(--rule); border-radius: 2px; color: var(--ink-2);
}
.otherreview .revised { font-family: var(--mono); font-size: 10px; color: var(--amber); margin-left: 8px; }
.otherreview .correction { font-size: 13px; color: var(--ink); margin-top: 5px; }
.otherreview .notes { font-size: 12.5px; color: var(--ink-3); margin-top: 3px; }

/* review state in the proteome table */
.reviewmark { font-family: var(--mono); font-size: 13px; color: var(--ink-3); }
.reviewmark.done { color: var(--teal); }
.reviewmark.double { color: var(--teal); font-weight: 600; }

.progress {
  height: 4px; background: var(--raise); border-radius: 2px; overflow: hidden;
  margin: 0 0 14px;
}
.progress i { display: block; height: 100%; background: var(--teal); border-radius: 2px; }
.progresslabel {
  font-family: var(--mono); font-size: 11px; color: var(--ink-3); margin-bottom: 6px;
  display: flex; justify-content: space-between;
}

#kbd-hint {
  position: fixed; right: 18px; bottom: 18px; z-index: 20;
  background: var(--surface); border: 1px solid var(--rule); border-radius: var(--radius);
  padding: 12px 16px; font-family: var(--mono); font-size: 11.5px; color: var(--ink-2);
  display: none; box-shadow: 0 10px 30px -18px rgba(0,0,0,.9);
}
#kbd-hint.open { display: block; }
#kbd-hint b { color: var(--teal); font-weight: 600; }

/* ---------------------------------------------------------------------- results */
.stats {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 1px; background: var(--rule); border: 1px solid var(--rule);
  border-radius: var(--radius); overflow: hidden; margin-bottom: 2px;
}
.stat { background: var(--surface); padding: 16px 18px; }
.stat b {
  display: block; font-family: var(--mono); font-weight: 500; font-size: 1.6rem;
  letter-spacing: -.02em; font-variant-numeric: tabular-nums; line-height: 1.1;
}
.stat span { display: block; margin-top: 6px; font-size: 12px; color: var(--ink-2); line-height: 1.4; }

.distbar { display: flex; gap: 2px; height: 34px; margin-bottom: 14px; }
.distbar > div { border-radius: 2px; min-width: 3px; }
.distkey { display: flex; gap: 18px; flex-wrap: wrap; font-family: var(--mono); font-size: 11.5px; color: var(--ink-2); }
.distkey span { display: flex; align-items: center; gap: 7px; }
.distkey i { width: 11px; height: 11px; border-radius: 2px; display: block; }

.panel + .panel { margin-top: 2px; }

.breakdownhead {
  display: flex; justify-content: space-between; gap: 20px; align-items: baseline;
  flex-wrap: wrap; font-family: var(--mono); font-size: 10.5px; color: var(--ink-2);
  letter-spacing: .06em; padding-bottom: 8px;
}
.breakdownhead > span:first-child { text-transform: uppercase; letter-spacing: .12em; }

.resumerow { margin: 0 0 16px; }
a.resume {
  display: inline-block; font-family: var(--mono); font-size: 12px; padding: 8px 16px;
  border: 1px solid var(--teal); border-radius: 2px; color: var(--teal);
}
a.resume:hover { background: var(--teal); color: var(--ground); text-decoration: none; }

/* ------------------------------------------------------------------- overview */
.popkey { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 20px; }
.popkey > div { border-top: 2px solid; padding-top: 12px; }
.popkey .k {
  display: flex; justify-content: space-between; gap: 10px; align-items: baseline;
  font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink); font-weight: 600; margin-bottom: 7px;
}
.popkey .k em { font-style: normal; color: var(--ink-3); letter-spacing: 0; }
.popkey p { font-size: 12.5px; color: var(--ink-2); margin: 0 0 9px; line-height: 1.5; }
.popkey .outcome {
  display: flex; gap: 7px; font-family: var(--mono); font-size: 12px; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.popkey .tiersplit {
  font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); margin-top: 4px;
}

table.heat { border-collapse: separate; border-spacing: 2px; font-size: 13px; min-width: 460px; }
table.heat th {
  font-family: var(--mono); font-weight: 500; font-size: 10px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--ink-3); padding: 4px 10px; text-align: center;
  white-space: nowrap;
}
table.heat th.row { text-align: left; padding-right: 16px; }
table.heat td {
  padding: 10px 14px; text-align: center; border-radius: 2px; min-width: 86px;
  font-family: var(--mono); font-variant-numeric: tabular-nums;
}
table.heat td .pc { display: block; font-weight: 600; font-size: 13.5px; }
table.heat td .ct { display: block; font-size: 10.5px; opacity: .74; margin-top: 1px; }
.heatkey {
  display: flex; align-items: center; gap: 7px; margin-top: 14px; font-family: var(--mono);
  font-size: 10.5px; letter-spacing: .08em; color: var(--ink-3);
}
.heatkey i { width: 26px; height: 11px; border-radius: 2px; display: block; }

.cov { display: flex; flex-direction: column; gap: 8px; }
.covrow { display: grid; grid-template-columns: minmax(160px, 240px) 1fr 54px; gap: 14px; align-items: center; }
.covrow .nm { font-family: var(--mono); font-size: 11.5px; color: var(--ink-2); overflow-wrap: anywhere; }
.covrow .tr { background: var(--raise); height: 13px; border-radius: 2px; overflow: hidden; }
.covrow .tr i { display: block; height: 100%; border-radius: 0 2px 2px 0; background: var(--teal); }
.covrow.low .tr i { background: var(--amber); }
.covrow .vl {
  font-family: var(--mono); font-size: 12px; text-align: right; color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.covrow.low .vl { color: var(--amber); font-weight: 600; }

/* -------------------------------------------------------------------- methods */
.panel h4 {
  margin: 22px 0 8px; font-family: var(--mono); font-size: 10.5px; letter-spacing: .13em;
  text-transform: uppercase; color: var(--ink-3); font-weight: 500;
}
.panel h4:first-of-type { margin-top: 18px; }
.panel ul { margin: 0; padding-left: 20px; }
.panel li { margin-bottom: 10px; line-height: 1.6; }
.panel .srcrow dt { text-transform: none; letter-spacing: .04em; }

/* Methods spans the shell like every other page — its panels are containers, not a
   column, so prose fills them. */
.reading .ev { min-width: 0; }
.reading .tablewrap, .reading table.ev { width: 100%; }

/* A paragraph under a chart or a table. It fills its panel; only the colour and the
   spacing above it are set here. */
.panel .note { color: var(--ink-2); margin-top: 16px; }
.panel .note:first-child { margin-top: 0; }

/* ------------------------------------------------------- missing-data notice */
.panel.notice h3 {
  font-family: var(--serif); font-size: 1.4rem; letter-spacing: -.01em; color: var(--ink);
  text-transform: none; margin-bottom: 14px; display: block;
}
.buildsteps { display: flex; flex-direction: column; gap: 8px; margin: 16px 0 20px; }
.buildstep {
  display: flex; gap: 16px; align-items: baseline; flex-wrap: wrap;
  padding: 11px 14px; background: var(--raise); border: 1px solid var(--rule);
  border-left: 3px solid var(--teal); border-radius: 2px;
}
.buildstep .cmd { font-family: var(--mono); font-size: 13px; color: var(--teal); background: none; }
.buildstep .note { font-size: 12.5px; color: var(--ink-3); }

/* The calibration cross-tab labels its rows by what the darkness tier means, with the
   code kept alongside so the row still ties back to the queue's Prior filter. */
table.heat th.row { max-width: 260px; }
table.heat th.row .meaning {
  display: block; font-family: var(--sans); font-size: 12.5px; letter-spacing: 0;
  text-transform: none; color: var(--ink-2); line-height: 1.35;
}
table.heat th.row .code {
  display: block; font-family: var(--mono); font-size: 9.5px; letter-spacing: .12em;
  color: var(--ink-3); margin-top: 2px;
}

/* The GO panel's prior column. Two spans that were never given a rule at all, so the code
   ran straight into the description — `T0well annotated in the prior`. Inline rather than
   stacked like `th.row` above, because this table has one reading column instead of three
   and the row can afford the width; the typography is the same pair either way, so the two
   tables in the group still read as siblings. */
table.heat td .tcode {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .12em; color: var(--ink-3);
  margin-right: 9px;
}
table.heat td .tlabel { font-size: 12.5px; color: var(--ink-2); }

/* The cross-tab's own scroll container. The wrapper was named `scroll` and never given a
   rule, so on a narrow window the heat table pushed the whole page sideways instead of
   scrolling inside its own box — the one thing a table this wide must not do. */
.scroll { overflow-x: auto; }

/* Alignment coverage. Percent identity cannot tell a full-length homolog from a shared
   domain, so coverage travels beside it everywhere a homolog is detailed. Below the
   bundle's own 80% gate on either axis it is marked, because that is the case where
   identity reads stronger than the alignment supports. */
.cov { font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); white-space: nowrap; }
.cov.partial { color: var(--amber); }

/* The Methods definition list for homolog flags puts the chip itself in the term column,
   so the reader matches the mark they saw on the protein page rather than a paraphrase. */
dl.srcrow dt .chip { font-size: 9.5px; }
/* The flag list's terms are chips, which are short; the definitions are full sentences.
   Give the term column only what a chip needs so the definition keeps the width. */
dl.srcrow dt .chip { font-size: 9.5px; white-space: nowrap; }

/* A value the warehouse cut short. Deliberately quiet — it is a caveat on the evidence,
   not a finding, and 40% of prior rows carry it. Amber ties it to the prior's own accent
   rather than introducing a warning colour the rest of the page does not use. */
.cut { color: var(--amber); opacity: .7; cursor: help; padding-left: 1px; }

/* The added rail says why the annotator did not see this evidence. Without it the split
   reads as a quality ranking rather than a difference in retrieval scope. */
.grouplabel .why {
  display: block; text-transform: none; letter-spacing: 0; font-size: 10.5px;
  color: var(--ink-3); margin-top: 3px; cursor: help; font-family: var(--sans);
}

/* Sortable column headers. The whole header is the target, not a small glyph beside it —
   a 12px arrow is a hard thing to hit and gives no hint that the label itself is live. */
table.proteome th a.sortlink {
  color: inherit; text-decoration: none; display: inline-flex; align-items: baseline;
  gap: 4px; cursor: pointer;
}
table.proteome th a.sortlink:hover { color: var(--ink); }
table.proteome th a.sortlink.on { color: var(--teal); }
/* Drawn only on the column in effect, so the arrow reads as the table's state rather
   than as an affordance every column is offering. */
table.proteome th .dir { font-size: 9px; line-height: 1; }

/* The queue's free-text filter. Dash 4 wraps dcc.Input in .dash-input-container, which
   collapses to a couple of pixels if only the <input> is styled. */
.filters .dash-input-container { display: inline-block; }
/* Targeted by type, not by class: Dash 4 replaces dcc.Input's className with its own
   `dash-input-element`, so a class set at the call site silently never matches. */
.filters input[type="search"] {
  background: var(--ground); border: 1px solid var(--rule); border-radius: var(--radius);
  color: var(--ink); font-family: var(--sans); font-size: 12px; padding: 4px 9px;
  width: 250px; outline: none;
}
.filters input[type="search"]:focus { border-color: var(--teal); }
.filters input[type="search"]::placeholder { color: var(--ink-3); }

/* Two columns, always. The corroboration band is a row of its own beneath them (§11.5),
   so the column count no longer varies with whether the workbook was ingested — which is
   why the old `cols-3` rule and its two breakpoints are gone. */
/* Named rather than left to the `.cols` base rule: `cols-2` falling through happened to
   give the right answer, which is not the same as saying so. */
/* The detail view as a whole: the two-column row, then the corroboration band beneath it.
   It owns nothing but the relationship between those rows — the 2px gap the panels use
   between themselves, so the band reads as another panel in the same stack rather than as
   a separate region. */
.detail { display: flex; flex-direction: column; gap: 2px; }
.cols-2 { grid-template-columns: 1fr 1fr; }

/* The corroboration band takes the prior's grammar — a rule and a label, never a fill.
   These are machine annotators of the same class as the LLM, and a filled panel would read
   as an answer key (DESIGN.md §8.3, §11.1). */
.panel.band { margin-bottom: 2px; }
.panel.corroboration h3 { color: var(--violet); }
.panel.corroboration h3 .count { color: var(--ink-3); cursor: help; }
.corroboration .framing {
  margin: 0 0 16px; max-width: 78ch; font-size: 12.5px; line-height: 1.6; color: var(--ink-3);
}

/* The comparison, laid out as two values facing each other rather than as a verdict with a
   number attached — that is the shape of the claim. Centred and roomy because on the 615
   proteins where it exists it is the point of the band. */
.ecpanel {
  border: 1px solid var(--rule); border-left: 3px solid var(--violet); border-radius: 2px;
  padding: 16px 18px; margin-bottom: 16px;
}
.ecfacing {
  display: flex; align-items: center; gap: 26px; flex-wrap: wrap;
}
.ecfacing .pole { display: flex; flex-direction: column; gap: 4px; }
.ecfacing .side {
  font-family: var(--mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-3);
}
.ecfacing .vs { color: var(--ink-3); font-size: 17px; }
.ecnum.big { font-size: 17px; letter-spacing: .02em; }
.banddecision { margin-top: 13px; display: flex; align-items: baseline; gap: 12px; }
.banddecision .score { font-family: var(--mono); font-size: 11px; color: var(--ink-3); }
.ecsingle { display: flex; align-items: baseline; gap: 12px; margin: 11px 0 4px; }
.ecsingle .side {
  font-family: var(--mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-3);
}
.ecsingle .score { font-family: var(--mono); font-size: 11px; color: var(--ink-3); }

/* The three absent cases. Unfilled and uncoloured: an absence is not a finding, and two
   thirds of the proteome lands here. */
.ecpanel.absent { border-left-color: var(--rule); }
.ecpanel.absent .head { font-size: 13.5px; color: var(--ink-2); }
.ecpanel.absent .note {
  margin-top: 7px; max-width: 78ch; font-size: 12.5px; line-height: 1.6; color: var(--ink-3);
}
/* Except this one. 272 proteins where the other annotators named an enzyme and the call did
   not is the one absence a reviewer would act on, and the old label buried it with the 1,061
   where nobody named anything (§11.6). A rule, not a fill — it is a question, not a fault. */
.ecpanel.absent.tools_only { border-left-color: var(--amber); }

/* The GO half of the band (§16). A second instrument under the EC one, set apart by a rule
   rather than a panel of its own: the two answer the same question with different reach, and
   two boxes would invite reading them as two verdicts that might disagree. */
.goblock { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--rule); }
.goblock h4 {
  margin: 0 0 12px; display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
}
.goblock h4 .gohead {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-2);
}
.goblock h4 .count { font-family: var(--mono); font-size: 10px; color: var(--ink-3); cursor: help; }
.ecpanel.gocase { margin-bottom: 14px; }
.ecpanel.gocase .head { font-size: 13.5px; color: var(--ink-2); }
.ecpanel.gocase .score {
  margin-top: 6px; font-family: var(--mono); font-size: 11px; color: var(--ink-3);
}
.ecpanel.gocase .note {
  margin-top: 8px; max-width: 78ch; font-size: 12.5px; line-height: 1.6; color: var(--ink-3);
}
/* Only a disagreement is coloured, and amber not rose: two annotations differing is a
   question for a reviewer, not a fault found in the call (§8.3). `same` and the three absent
   cases stay unfilled — 851 proteins land in those, and marking them would make the common
   case look like a finding. */
.ecpanel.gocase.disjoint { border-left-color: var(--amber); }

.gogrid { display: grid; gap: 1px; }
.gorow {
  display: grid; grid-template-columns: 96px 1fr; gap: 14px; align-items: baseline;
  padding: 6px 0; border-top: 1px solid var(--rule-soft); font-size: 13px;
}
.gorow .tool {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .08em; color: var(--ink-2);
}
.gorow.absent .dimmed { color: var(--ink-3); }
/* The prior sits in the same list and outside the verdict. A rule and dimmed ticks rather
   than a separate block: it belongs with the terms it is being read against, and moving it
   elsewhere would cost the comparison the eye makes for free. */
.gorow.context { border-top: 1px solid var(--rule); margin-top: 6px; padding-top: 10px; }
.gorow.context .tool, .gorow.context .golabel { color: var(--ink-3); }
.gorow.context .agree { opacity: .45; }
.goterms { display: flex; flex-direction: column; gap: 4px; }
.goline { display: grid; grid-template-columns: 14px 86px 1fr; gap: 8px; align-items: baseline; }
.goline .agree { font-size: 11px; }
.goline .goid { font-family: var(--mono); font-size: 11px; }
.goline .golabel { color: var(--ink-2); font-size: 12.5px; }
.gofoot {
  margin: 12px 0 0; font-size: 12px; line-height: 1.55; color: var(--ink-3); max-width: 78ch;
}
@media (max-width: 760px) {
  .gorow { grid-template-columns: 1fr; gap: 2px; }
  .goline { grid-template-columns: 14px 1fr; }
  .goline .golabel { grid-column: 2; }
}

.corroboration .spoke {
  font-family: var(--mono); font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-3); margin-bottom: 8px;
}

/* One row per annotator, always all five. Which annotators were silent is information:
   a 3/4 consensus reads differently once you can see the fifth had no opinion. */
.toolgrid { display: grid; gap: 1px; }
.toolrow {
  display: grid; grid-template-columns: 96px 128px 18px 1fr; gap: 14px; align-items: baseline;
  padding: 7px 0; border-top: 1px solid var(--rule-soft); font-size: 13px;
}
.toolrow .tool {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .08em; color: var(--ink-2);
}
.toolrow.absent .ann, .toolrow .dimmed { color: var(--ink-3); font-style: italic; }
.toolrow .ecline { display: flex; gap: 7px; align-items: baseline; }
.toolrow .agree { font-size: 12px; }
.toolrow .agree.yes { color: var(--violet); }
.toolrow .agree.no { color: var(--rose); }
@media (max-width: 760px) {
  .toolrow { grid-template-columns: 1fr; gap: 2px; }
  .toolrow .agree { display: none; }
}
.ecnum { font-family: var(--mono); font-size: 11.5px; color: var(--violet); }
.ecsrc {
  font-family: var(--mono); font-size: 9.5px; letter-spacing: .06em; color: var(--ink-3);
  cursor: help;
}
.curated-card.consensus { border-left-color: var(--violet); }
.curated-card.consensus .score {
  font-family: var(--mono); font-size: 11px; color: var(--ink-3); margin-left: 8px;
}

/* The EC agreement chip. Only a real disagreement is coloured: marking every verdict
   would make the common case (no EC to compare, two thirds of the proteome) look like a
   finding. */
.chip.ec-none { color: var(--rose); border-color: var(--rose); }
.chip.ec-class { color: var(--amber); border-color: var(--amber); }
.chip.ec-exact { color: var(--ink-2); }
.chip.ec-no-consensus, .chip.ec-no-ai-ec { color: var(--ink-3); }

/* The queue's EC agreement column. Only a stated disagreement is coloured — two thirds of
   the proteome has no EC to compare, and colouring that would make the common case look
   like a finding. */
table.proteome td.ec { white-space: nowrap; }
.ecverdict { font-family: var(--mono); font-size: 10.5px; letter-spacing: .04em; cursor: help; }
.ecverdict.ec-none { color: var(--rose); }
.ecverdict.ec-class { color: var(--amber); }
.ecverdict.ec-exact { color: var(--ink-2); }
.ecverdict.ec-no-consensus, .ecverdict.ec-no-ai-ec { color: var(--ink-3); }
table.proteome td.ec .ecnum { font-size: 10.5px; margin-top: 2px; }

/* The EC cross-tab pairs a count with the share of the denominator that applies to it.
   Stacked, because side by side they read as one number — `600` above `53%` was rendering
   as "60053%". The `.pc`/`.ct` pair used by the darkness table is scoped to `table.heat`
   and does not reach here. */
table.ev td.ecpair .n { display: block; font-family: var(--mono); font-size: 12.5px; }
table.ev td.ecpair .share {
  display: block; font-family: var(--mono); font-size: 10px; color: var(--ink-3);
  margin-top: 2px;
}
table.ev td.ecpair.lead .n { color: var(--teal); }


/* ---------------------------------------------------------------- PMI additions */
/* Genome and cluster-role chips in the protein header. The role is the first thing a
   reviewer needs — was this call made from this sequence or copied onto it — so a member
   carries the propagation blue and a representative the annotator's teal. */
.chip.genome { color: var(--ink); }
.chip.role.rep { border-color: var(--teal); color: var(--teal); }
.chip.role.member { border-color: var(--blue); color: var(--blue); }
.chip.cluster.shared { border-color: var(--blue); color: var(--blue); }

/* The evidence column: the S. mutans prior panel's amber grammar, with a wider label column
   because "Closest FB homolog" does not fit the prior's 78px. */
.panel.context .srcrow { grid-template-columns: 118px 1fr; }
.panel.context h3 .sub { text-transform: none; letter-spacing: 0; font-family: var(--sans, inherit); color: var(--ink-3); }
.panel.context .entry { line-height: 1.5; }
.panel.context .entry .span, .panel.context .more { color: var(--ink-3); font-size: 11.5px; font-family: var(--mono); }
.panel.context .acc { color: var(--amber); font-size: 11.5px; }
.panel.context .terms { display: flex; flex-wrap: wrap; gap: 4px 14px; font-size: 12px; color: var(--ink-2); }
.panel.context .terms b { font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); font-weight: 500; }
.panel.context .detail { color: var(--ink-3); font-size: 12px; margin-top: 2px; }
.panel.context .caveat { color: var(--ink-3); font-size: 12px; margin: 14px 0 0; font-style: italic; }
.support { font-family: var(--mono); font-size: 10.5px; color: var(--ink-3); white-space: nowrap; }

/* A member's call panel says whose call it is, under the heading. */
.inherited {
  margin: -6px 0 14px; padding: 6px 10px; border-left: 2px solid var(--blue);
  color: var(--ink-2); font-size: 12.5px;
}

/* The cluster panel. */
.panel.cluster .note { color: var(--ink-2); font-size: 13px; margin: 0 0 12px; }
table.ev.cluster tr.here td { background: var(--raise); }
table.ev.cluster .here { color: var(--teal); }
table.ev.cluster td.role { color: var(--ink-3); font-size: 12px; }
table.ev.cluster td.role.rep { color: var(--teal); }

/* A member's review panel: a pointer to the representative, not a form. */
.panel.review.member .note { color: var(--ink-2); font-size: 13px; }

/* Queue additions. */
table.proteome td.prior .ctxtext {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
table.proteome td.lt .member { color: var(--blue); font-family: var(--mono); }
table.proteome td.num.shared { color: var(--blue); }

/* Overview: one thin stacked bar per genome. */
.scoperows { display: flex; flex-direction: column; gap: 6px; }
.scoperow { display: grid; grid-template-columns: 64px 1fr 116px; gap: 12px; align-items: center; }
.scoperow .nm { font-size: 11.5px; color: var(--ink-2); }
.scoperow .vl { font-size: 11px; color: var(--ink-3); text-align: right; }
.distbar.thin { height: 14px; margin-bottom: 0; }
.scoperows .distkey { margin-top: 10px; }

/* Genome context: the isolate's own neighbours, with gaps for ORFs outside the dashboard. */
.panel.genomectx .note { color: var(--ink-2); font-size: 13px; margin: 0 0 12px; }
table.ev.genomectx tr.here td { background: var(--raise); }
table.ev.genomectx .here { color: var(--teal); }
table.ev.genomectx td.call { color: var(--ink-2); }
table.ev.genomectx .member { color: var(--blue); font-family: var(--mono); }
table.ev.genomectx tr.gaprow td.gap { font-family: var(--mono); font-size: 11px; font-style: italic; }
