/* Palette taken from the Talon override stylesheet. Surfaces, accent, text
   opacity tiers, and pill colours all match the live site. Typefaces are a
   placeholder until the real ones are confirmed. */
:root {
  --ink: #0b1220;              /* panel / masthead */
  --ink-soft: #1b2942;
  --paper: #0b1220;            /* page background, now dark throughout */
  --surface: #111a2e;          /* cards */
  --surface-glass: rgba(17, 48, 89, 0.25);   /* frosted tiles */
  --line: rgba(255, 255, 255, 0.12);
  --line-soft: rgba(255, 255, 255, 0.08);
  --line-tile: #384459;

  --text: #ffffff;
  --text-muted: rgba(255, 255, 255, 0.80);
  --text-faint: rgba(255, 255, 255, 0.65);

  --accent: #6052d4;
  --accent-dark: #4f43b5;
  --accent-wash: rgba(96, 82, 212, 0.16);
  --glow: 0 0 0 1px rgba(96, 82, 212, 0.6), 0 0 14px rgba(96, 82, 212, 0.45);
  --glow-border: rgba(96, 82, 212, 0.9);

  /* Category colours, tuned for a dark ground */
  --cat-gene: #a78bfa;
  --cat-blood: #fb7185;
  --cat-cell: #38bdf8;
  --cat-tissue: #fbbf24;

  /* Grade pills follow the content-type pill recipe: 0.16 fill, light text */
  --grade-a: #4ade80;
  --grade-b: #38bdf8;
  --grade-c: #f59e0b;
  --grade-d: rgba(255, 255, 255, 0.45);
  --grade-none: rgba(255, 255, 255, 0.18);

  --grade-a-wash: rgba(74, 222, 128, 0.16);
  --grade-b-wash: rgba(56, 189, 248, 0.16);
  --grade-c-wash: rgba(245, 158, 11, 0.16);
  --grade-d-wash: rgba(255, 255, 255, 0.12);

  --radius: 10px;
  --radius-card: 15px;
  --shell: 1320px;   /* matches --site-max so every page is one width */
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.6;
}

.sr-only {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}

/* Duplicated deliberately. This rule and its twin in site.css are the fix
   for the page container sizing to its content instead of filling the
   window; keeping it in both files means it survives either one being
   out of date. */
.shell {
  max-width: var(--shell);
  margin: 0 auto;
  padding: 0 28px;
  box-sizing: border-box;
}

/* Only where .shell is a flex child of body. Applying it to every .shell
   broke the masthead, whose inner container is also a .shell but sits
   inside a centred flex row. */
body > .shell {
  align-self: stretch;
  width: 100%;
}

/* ---------- masthead: centred on landing, compact once searched ---------- */

.masthead {
  background: var(--ink);
  color: #ffffff;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Body is a flex column, so the masthead simply absorbs whatever height
     is left after nav and footer. No arithmetic, therefore no rounding
     sliver of page background showing through underneath. */
  flex: 1 0 auto;
  transition: padding 0.42s cubic-bezier(0.22, 0.61, 0.36, 1);
  padding: 40px 0;
  width: 100%;
}

.masthead-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
}

.brandblock {
  text-align: center;
  max-height: 240px;
  opacity: 1;
  overflow: hidden;
  transition: max-height 0.38s cubic-bezier(0.22, 0.61, 0.36, 1),
              opacity 0.22s ease, margin 0.38s ease;
  margin-bottom: 26px;
}

.hero-eyebrow {
  font: 500 11px var(--font-mono);
  text-transform: uppercase; letter-spacing: 0.14em;
  color: var(--accent); margin: 0 0 12px;
}

.hero-title {
  font-family: var(--font-display);
  /* Matched to .hero-statement h1 on the About page. The size is fluid
     rather than fixed: 5vw, floored at 30px and capped at 52px, so both
     headlines scale together at every window width instead of only
     agreeing at one. */
  font-size: clamp(30px, 5vw, 52px);
  font-weight: 500;
  letter-spacing: -0.035em;
  line-height: 1.1;
  color: #FFFFFF;
  margin: 0 auto 14px;
  max-width: 18ch;
  text-wrap: balance;
}

.context-line {
  margin: 0 auto;
  /* Matched to .chapter-body on the About page: 16px, 1.7, 80% white. */
  font-size: 16px;
  color: rgba(255,255,255,0.80);
  max-width: 72ch;
  line-height: 1.7;
  /* Distributes the words evenly across the lines instead of filling each
     one and dropping whatever is left onto the last. That is what leaves a
     single word stranded at the bottom. Browsers without support just wrap
     normally, and the wider measure alone fixes this particular sentence. */
  text-wrap: balance;
}

.searchbar {
  display: flex;
  gap: 8px;
  width: 100%;
  max-width: 560px;
  background: #0f172a;
  border: 1px solid rgba(255,255,255,0.18);
  border-radius: 100px;
  padding: 5px 5px 5px 22px;
  align-items: center;
  transition: max-width 0.42s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.searchbar:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(96, 82, 212, 0.35);
}

.searchbar input {
  flex: 1;
  min-width: 0;
  font: 400 15.5px/1.4 var(--font-body);
  padding: 10px 0;
  border: 0;
  background: none;
  color: #FFFFFF;
}
.searchbar input::placeholder { color: rgba(255,255,255,0.60); }
.searchbar input:focus { outline: none; }

.searchbar button {
  font: 500 13.5px var(--font-body);
  padding: 10px 24px;
  border: 0;
  background: var(--accent);
  color: #FFFFFF;
  border-radius: 100px;
  cursor: pointer;
  white-space: nowrap;
}
.searchbar button:hover { background: var(--accent-dark); }
.searchbar button:disabled { opacity: 0.6; cursor: progress; }

.examples {
  display: flex; flex-wrap: wrap; gap: 7px; justify-content: center;
  max-width: 560px; margin-top: 10px;
  /* Padding gives the hover lift and focus glow somewhere to render. The
     container has to clip for the collapse animation, so the room has to be
     inside it rather than around it. */
  padding: 8px 6px 10px;
  max-height: 130px; opacity: 1; overflow: hidden;
  transition: max-height 0.34s cubic-bezier(0.22, 0.61, 0.36, 1),
              opacity 0.2s ease, margin 0.34s ease;
}
.example {
  font: 400 12.5px var(--font-body);
  background: none; border: 1px solid rgba(255,255,255,0.18); color: rgba(255,255,255,0.80);
  padding: 6px 14px; border-radius: 100px; cursor: pointer;
  transition: border-color 0.14s, color 0.14s;
}
.example:hover { border-color: var(--accent); color: #FFFFFF; }
.example:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---- searched state: block collapses to a compact header band ---- */

.masthead.searched {
  /* Stops absorbing free space and sticks below the nav, so the search bar
     stays reachable without scrolling back to the top. */
  flex: 0 0 auto;
  padding: 14px 0;
  position: sticky;
  top: var(--nav-h, 58px);
  z-index: 40;
  border-bottom: 1px solid var(--ink-soft);
}
.masthead.searched .brandblock {
  max-height: 0;
  opacity: 0;
  margin-bottom: 0;
}
.masthead.searched .searchbar { max-width: 620px; }
.masthead.searched .examples {
  max-height: 0; opacity: 0; margin-top: 0;
}

@media (prefers-reduced-motion: reduce) {
  .masthead, .brandblock, .searchbar, .examples, .example { transition: none; }
}

@media (max-width: 700px) {
  .masthead { padding: 24px 0; }
  .hero-title { font-size: 27px; }
  .context-line { font-size: 15px; }
}

/* ---------- status ---------- */

/* An empty status div still occupies its top margin, which shows as a
   band of page background between the landing section and the footer.
   Collapsing it when there is no message removes that height entirely. */
.status:empty { display: none; }

.status { margin: 22px 0 0; font-size: 14px; color: var(--text-muted); }
.status.error {
  background: #FBECEA; border: 1px solid #E7C3BD; color: #7C2C1E;
  padding: 12px 14px; border-radius: var(--radius);
}
.status.notice {
  background: #FAF3E2; border: 1px solid #E4D3AA; color: #6B5010;
  padding: 12px 14px; border-radius: var(--radius);
}

/* ---------- layout ---------- */

/* The hidden attribute takes display:none from the browser default
   stylesheet, which any class selector outranks. Without this rule
   `.workspace { display: grid }` wins and the element renders even when
   marked hidden. Applies to every element using the attribute. */
[hidden] { display: none !important; }

.workspace {
  display: grid;
  grid-template-columns: 218px minmax(0, 1fr);
  gap: 34px;
  padding: 26px 0 60px;
  align-items: start;
}

/* The heading has its own top margin from the h2; the rail has none, so it
   sat higher than the text it should line up with. */
.rail > .rail-block:first-child { padding-top: 3px; }

/* ---------- rail ---------- */

/* Both columns start on the same line. The sticky offset only applies once
   the rail is being scrolled past, so it cannot be part of the resting
   position — that was what pushed it below the heading. */
.rail { position: sticky; top: calc(var(--stuck-h, 130px) + 18px); align-self: start; }

.rail-block { margin-bottom: 24px; }

.marker-search {
  width: 100%;
  box-sizing: border-box;
  font: 400 13px var(--font-body);
  padding: 7px 12px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
}
.marker-search::placeholder { color: var(--text-faint); }
.marker-search:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(96, 82, 212, 0.18);
}

.rail-sort {
  width: 100%;
  box-sizing: border-box;
  font: 400 13px var(--font-body);
  padding: 7px 28px 7px 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text);
  color-scheme: dark;
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='%238A959A' fill-opacity='0.9' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 10px;
  cursor: pointer;
}
.rail-sort option { background: var(--surface); color: var(--text); }

.rail-head { display: flex; align-items: baseline; justify-content: space-between; }

.rail h2 {
  font: 500 11px/1 var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--text-faint);
  margin: 0 0 10px;
}

.linkbtn {
  border: 0; background: none; padding: 0;
  font: 400 12px var(--font-body);
  color: var(--accent); cursor: pointer; margin-bottom: 10px;
}
.linkbtn:hover { text-decoration: underline; }

.chipset { display: flex; flex-wrap: wrap; gap: 6px; }

/* Category chips get a fixed two-per-row width, same reasoning as the grade
   chips below: the count is a variable-width number, and without a floor the
   chip resizes with it, which reads as the rail shifting. 96px fits the
   longest label ("Tissue") with a three-digit count at this font size. */
.chipset:not(.chipset-grade) .chip {
  flex: 0 0 calc(50% - 3px);
  box-sizing: border-box;
  justify-content: center;
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
}

.chip {
  font: 400 13px var(--font-body);
  padding: 5px 11px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text-muted);
  border-radius: 100px;
  cursor: pointer;
  text-align: center;
}
.chip:hover { border-color: rgba(255,255,255,0.28); color: var(--text); }
.chip[aria-pressed="true"] {
  background: var(--ink); border-color: var(--ink); color: #FFFFFF;
}
.chip .count {
  font-family: var(--font-mono);
  font-size: 11px; opacity: 0.65; margin-left: 5px;
}
/* Category chips use flex gap for spacing instead, since they are laid out
   with align-items/justify like the grade chips are. */
.chipset:not(.chipset-grade) .chip .count { margin-left: 0; }
.chip[disabled] { opacity: 0.4; cursor: default; }

/* Fixed width so all four sit on one row and D does not wrap beneath. The
   counts vary in digit count, which is what made them uneven. */
.chipset-grade { gap: 4px; flex-wrap: nowrap; }
.chipset-grade .chip {
  text-align: center;
  flex: 0 0 auto;
  min-width: 48px;
  padding: 5px 6px;
  justify-content: center;
  display: inline-flex;
  align-items: baseline;
  gap: 4px;
}
.chipset-grade .chip .count { margin-left: 0; }







.rail-note { font-size: 11.5px; color: var(--text-faint); margin: 8px 0 0; }



.reset {
  width: 100%;
  font: 400 13px var(--font-body);
  padding: 8px;
  border: 1px solid var(--line);
  background: none;
  color: var(--text-muted);
  border-radius: var(--radius);
  cursor: pointer;
}
.reset:hover { border-color: rgba(255,255,255,0.28); color: var(--text); }

/* ---------- results head ---------- */

.results-head {
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 20px; margin-bottom: 14px; flex-wrap: wrap;
}

.results-head h2 {
  font-family: var(--font-display);
  font-size: 21px; font-weight: 500; letter-spacing: -0.02em;
  margin: 0; color: var(--text);
}

.results-meta {
  margin: 3px 0 0; font-size: 13px; color: var(--text-muted);
  font-family: var(--font-mono);
}


.legend { display: flex; gap: 14px; align-items: center; }
.legend-item {
  display: flex; align-items: center; gap: 5px;
  font: 400 11px var(--font-mono); color: var(--text-faint);
  text-transform: uppercase; letter-spacing: 0.06em;
}
.legend-swatch { width: 9px; height: 9px; border-radius: 2px; }
.legend-swatch[data-cat="gene"]   { background: var(--cat-gene); }
.legend-swatch[data-cat="blood"]  { background: var(--cat-blood); }
.legend-swatch[data-cat="cell"]   { background: var(--cat-cell); }
.legend-swatch[data-cat="tissue"] { background: var(--cat-tissue); }
.legend-note {
  border-left: 1px solid var(--line); padding-left: 12px;
  text-transform: none; letter-spacing: 0; font-style: italic;
}

/* ---------- list ---------- */

.list { list-style: none; margin: 0; padding: 0; min-width: 0; }

.row {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  margin-bottom: 7px;
  overflow: hidden;
}
.row.open { border-color: rgba(255,255,255,0.24); }

.row-btn {
  display: grid;
  grid-template-columns: 62px minmax(0, 1fr) auto;
  align-items: center;
  gap: 16px;
  width: 100%;
  padding: 13px 16px;
  border: 0; background: none; cursor: pointer; text-align: left;
  font: inherit; color: inherit;
}
.row-btn:hover { background: rgba(255,255,255,0.03); }
.row-btn:focus-visible {
  outline: 2px solid var(--accent); outline-offset: -2px;
}

/* signature element: four-segment channel bar */
.channels {
  display: flex; gap: 3px; align-items: flex-end; height: 26px;
}
.channel {
  width: 11px; border-radius: 2px 2px 0 0;
  position: relative; cursor: help;
}
.channel[data-cat="gene"]   { background: var(--cat-gene); }
.channel[data-cat="blood"]  { background: var(--cat-blood); }
.channel[data-cat="cell"]   { background: var(--cat-cell); }
.channel[data-cat="tissue"] { background: var(--cat-tissue); }
.channel[data-empty="true"] {
  height: 3px; background: var(--grade-none);
}

.row-ident { min-width: 0; }
.symbol {
  font: 600 15.5px var(--font-body);
  letter-spacing: -0.01em;
}
.alias {
  font: 400 12.5px var(--font-mono);
  color: var(--accent); margin-left: 8px;
}
.row-summary {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  font-size: 13px; color: var(--text-muted);
  overflow: hidden; line-height: 1.45; margin-top: 1px;
}

.row-right { display: flex; align-items: center; gap: 14px; }
.papercount {
  font: 400 12px var(--font-mono); color: var(--text-faint);
  white-space: nowrap;
}
.caret { color: var(--text-faint); font-size: 12px; transition: transform 0.15s; }
.row.open .caret { transform: rotate(180deg); }

/* ---------- detail ---------- */

.detail {
  border-top: 1px solid var(--line-soft);
  background: rgba(255,255,255,0.03);
  padding: 16px;
}

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr));
  gap: 10px;
}

/* Four things per card, in reading order: what it is and how much evidence,
   the grade as the anchor, then the way in to the service. */
.card {
  display: flex;
  flex-direction: column;
  min-height: 168px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 14px 16px 16px;
  text-align: left;
  font: inherit;
  color: inherit;
}

/* Every element in the card is its own control. They are given generous
   padding so the tap target is bigger than the visible text — the grade and
   the category name are small, and a 40px letter is still a thin target. */
.card-hit {
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  padding: 3px 5px;
  margin: -3px -5px;
  border-radius: 5px;
  text-align: inherit;
  transition: background 0.12s, color 0.12s;
}
.card-hit:hover { background: rgba(96, 82, 212, 0.14); color: #ffffff; }

/* The grade is 40px type — a tinted box behind it reads as a shape rather
   than as feedback. Brightening the letter is enough. */
.card-grade.card-hit:hover {
  background: none;
  filter: brightness(1.45);
}
.card-hit:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* The service prompt is the one that matters most, so it carries weight the
   other three do not. */
.card-foot-prompt.card-hit {
  border-color: rgba(96, 82, 212, 0.4);
  margin: 0;
}
.card-foot-prompt.card-hit:hover {
  background: rgba(96, 82, 212, 0.22);
  border-color: var(--accent);
}

.card.absent {
  background: rgba(255, 255, 255, 0.02);
  border-style: dashed;
}

.card-papers {
  font: 400 11.5px var(--font-mono);
  color: var(--text-faint);
}

/* The grade is the anchor of the card, so it gets the space. */
.card-grade-wrap {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px 0 6px;
}

.card-grade {
  font-family: var(--font-display);
  display: inline-block;
  font-size: 40px;
  font-weight: 500;
  line-height: 1;
  letter-spacing: -0.03em;
}
.card-grade[data-grade="A"] { color: var(--grade-a); }
.card-grade[data-grade="B"] { color: var(--grade-b); }
.card-grade[data-grade="C"] { color: var(--grade-c); }
.card-grade[data-grade="D"] { color: var(--grade-d); }
.card-grade[data-grade="-"] { color: var(--grade-none); font-size: 30px; }

.grade-popover-sub {
  margin: 8px 0 0;
  font: 400 12px var(--font-mono);
  color: rgba(255, 255, 255, 0.6);
  line-height: 1.5;
}

/* Text and button variants occupy the same box, so a "No standard assay
   applies" card lines up with a "How we measure this" card beside it. The
   border on the button is inside that box rather than adding to it. */
.card-foot-prompt {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 36px;
  padding: 7px 10px;
  box-sizing: border-box;
  width: 100%;
  border: 1px solid transparent;
  border-radius: 6px;
  font: 500 13px var(--font-body);
  color: var(--accent);
  text-align: center;
  line-height: 1.35;
}
.card.absent .card-foot-prompt,
.card:not(.card-action) .card-foot-prompt {
  color: var(--text-faint);
  font-weight: 400;
}

/* ---------- scrollbars ---------- */

/* The default track is a pale slab that cuts across the dark surfaces. This
   is a thin pill on a transparent track, inset from the edge so it floats
   rather than framing the panel. */
.modal,
.grade-popover,
.card-refs,
.refs {
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.22) transparent;
}

.modal::-webkit-scrollbar,
.grade-popover::-webkit-scrollbar,
.card-refs::-webkit-scrollbar,
.refs::-webkit-scrollbar {
  width: 10px;
  background: transparent;
}

.modal::-webkit-scrollbar-track,
.grade-popover::-webkit-scrollbar-track,
.card-refs::-webkit-scrollbar-track,
.refs::-webkit-scrollbar-track {
  background: transparent;
}

.modal::-webkit-scrollbar-thumb,
.grade-popover::-webkit-scrollbar-thumb,
.card-refs::-webkit-scrollbar-thumb,
.refs::-webkit-scrollbar-thumb {
  background-color: rgba(255, 255, 255, 0.2);
  border-radius: 100px;
  /* Transparent border with background-clip is what insets the pill from the
     edge without needing a wider track. */
  border: 3px solid transparent;
  background-clip: content-box;
}

.modal::-webkit-scrollbar-thumb:hover,
.grade-popover::-webkit-scrollbar-thumb:hover,
.card-refs::-webkit-scrollbar-thumb:hover,
.refs::-webkit-scrollbar-thumb:hover {
  background-color: rgba(255, 255, 255, 0.38);
}

.modal::-webkit-scrollbar-corner { background: transparent; }

/* ---------- grade rationale popover ---------- */

.grade-popover {
  position: absolute;
  z-index: 120;
  width: min(300px, calc(100vw - 24px));
  background: var(--ink);
  border: 1px solid rgba(96, 82, 212, 0.5);
  border-radius: 10px;
  padding: 14px 16px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
}

.grade-popover-title {
  margin: 0 0 7px;
  font: 500 11px var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--accent);
}

.grade-popover-body {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.86);
}



.card-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px;
}
.card-title {
  font: 500 11px var(--font-mono);
  text-transform: uppercase; letter-spacing: 0.09em; color: var(--text-muted);
}

.grade-pill {
  font: 500 11px var(--font-mono);
  padding: 2px 8px; border-radius: 3px; letter-spacing: 0.05em;
}
.grade-pill[data-grade="A"] { background: var(--grade-a-wash); color: #bbf7d0; }
.grade-pill[data-grade="B"] { background: var(--grade-b-wash); color: #bae6fd; }
.grade-pill[data-grade="C"] { background: var(--grade-c-wash); color: #fde68a; }
.grade-pill[data-grade="D"] { background: var(--grade-d-wash); color: rgba(255,255,255,0.80); }
.grade-pill[data-grade="-"] { background: rgba(255,255,255,0.08); color: rgba(255,255,255,0.55); }










.card-foot a {
  font: 400 12px var(--font-body);
  color: var(--accent); text-decoration: none; white-space: nowrap;
}
.card-foot a:hover { text-decoration: underline; }

.rationale {
  font-size: 11.5px; color: var(--text-faint); margin: 8px 0 0;
  line-height: 1.5;
}

.refs { margin-top: 14px; }
.refs h3 {
  font: 500 11px var(--font-mono);
  text-transform: uppercase; letter-spacing: 0.09em;
  color: var(--text-faint); margin: 0 0 7px;
}
.refs ul { list-style: none; margin: 0; padding: 0; }
.refs li {
  font-size: 13px; margin-bottom: 5px; line-height: 1.45;
  padding-left: 12px; position: relative;
}
.refs li::before {
  content: ""; position: absolute; left: 0; top: 7px;
  width: 4px; height: 4px; border-radius: 50%; background: var(--line);
}
.refs a { color: var(--text-muted); text-decoration: none; }
.refs a:hover { color: #ffffff; text-decoration: underline; }
.refs .meta {
  font-family: var(--font-mono); font-size: 11.5px;
  color: var(--text-faint); margin-left: 6px;
}
.trial-flag {
  font: 500 10px var(--font-mono);
  background: var(--grade-a-wash); color: #bbf7d0;
  padding: 1px 5px; border-radius: 3px; margin-left: 6px;
  text-transform: uppercase; letter-spacing: 0.05em;
}

/* ---------- empty ---------- */

.empty {
  background: var(--surface); border: 1px dashed var(--line);
  border-radius: var(--radius); padding: 34px 26px; text-align: center;
}
.empty h3 {
  font-family: var(--font-display);
  font-size: 17px; font-weight: 500; margin: 0 0 6px;
}
.empty p { margin: 0; color: var(--text-muted); font-size: 14px; }

@media (max-width: 860px) {
  .workspace { grid-template-columns: 1fr; }
  .rail { position: static; }
  .shell { padding: 0 18px; }
  .row-btn { grid-template-columns: 62px minmax(0, 1fr); }
  .row-right { grid-column: 1 / -1; justify-content: space-between; }
}

/* per-category source lists */




.card-refs {
  margin-top: 10px; border-top: 1px solid var(--line-soft); padding-top: 9px;
}
.card-refs ul { list-style: none; margin: 0 0 9px; padding: 0; }
.card-refs li {
  font-size: 12.5px; line-height: 1.45; margin-bottom: 6px;
  padding-left: 11px; position: relative;
}
.card-refs li::before {
  content: ""; position: absolute; left: 0; top: 7px;
  width: 4px; height: 4px; border-radius: 50%; background: var(--line);
}
.card-refs a { color: var(--text-muted); text-decoration: none; }
.card-refs a:hover { color: #ffffff; text-decoration: underline; }
.card-refs .meta {
  font-family: var(--font-mono); font-size: 11px;
  color: var(--text-faint); margin-left: 5px;
}
.card-refs .bulk {
  display: inline-block; font: 400 12px var(--font-body);
  color: var(--accent); text-decoration: none;
}
.card-refs .bulk:hover { text-decoration: underline; }


/* ---------- service recommendations ---------- */

.service-name {
  font: 500 13.5px var(--font-body);
  margin: 0 0 4px; color: var(--text);
}

.service-pitch {
  font-size: 12.5px; line-height: 1.5; color: var(--text);
  margin: 0 0 5px;
}

.service-detail {
  font: 400 11.5px var(--font-mono);
  color: var(--text-faint); line-height: 1.45; margin: 0;
}

.service-link {
  display: inline-block; margin-top: 6px;
  font: 400 12px var(--font-body);
  color: var(--accent); text-decoration: none;
}
.service-link:hover { text-decoration: underline; }

/* ---------- contact call to action ---------- */

.contact {
  margin-top: 14px; padding: 13px 15px;
  background: var(--ink); border-radius: var(--radius);
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
}

.contact-note {
  margin: 0; font-size: 13px; color: rgba(255,255,255,0.80); flex: 1; min-width: 220px;
}

.contact-cta {
  font: 500 13.5px var(--font-body);
  background: var(--accent); color: #FFFFFF;
  padding: 9px 18px; border-radius: var(--radius);
  text-decoration: none; white-space: nowrap;
}
.contact-cta:hover { background: var(--accent-dark); }

/* ---------- clickable category title ---------- */

.card-title-action {
  border: 0; background: none; padding: 0; cursor: pointer;
  display: flex; align-items: baseline; gap: 7px;
  font: 500 11px var(--font-mono);
  text-transform: uppercase; letter-spacing: 0.09em;
  color: var(--text-muted); text-align: left;
}
.card-title-action:hover { color: var(--accent); }
.card-title-action:hover .card-title-hint { opacity: 1; }
.card-title-action:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 2px;
}

.card-title-hint {
  font: 400 10px var(--font-body);
  text-transform: none; letter-spacing: 0;
  color: var(--accent); opacity: 0; transition: opacity 0.12s;
  white-space: nowrap;
}

/* ---------- modal ---------- */

.modal-overlay {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(0,0,0,0.65);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
}

.modal {
  position: relative;
  background: var(--surface);
  border-radius: 10px;
  max-width: 520px; width: 100%;
  max-height: 85vh; overflow-y: auto;
  padding: 26px 28px 24px;
}

.modal-close {
  position: absolute; top: 12px; right: 14px;
  border: 0; background: none; cursor: pointer;
  font-size: 24px; line-height: 1; color: var(--text-faint);
  padding: 4px 8px; border-radius: var(--radius);
}
.modal-close:hover { color: var(--text); background: var(--paper); }

.modal-eyebrow {
  font: 500 10.5px var(--font-mono);
  text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--text-faint); margin: 0 0 7px;
}

.modal-title {
  font-family: var(--font-display);
  font-size: 20px; font-weight: 500; letter-spacing: -0.02em;
  margin: 0 0 9px; color: var(--text);
}

.modal-evidence {
  font-size: 13.5px; color: var(--text-muted); line-height: 1.55;
  margin: 0 0 18px; padding-bottom: 16px;
  border-bottom: 1px solid var(--line-soft);
}

.modal-service { margin-bottom: 18px; }
.modal-service:last-of-type { margin-bottom: 4px; }

.modal .service-name {
  font: 500 15px var(--font-body);
  margin: 0 0 5px; color: var(--text);
}
.modal .service-pitch {
  font-size: 13.5px; line-height: 1.6; color: var(--text); margin: 0 0 6px;
}
.modal .service-detail {
  font: 400 11.5px var(--font-mono);
  color: var(--text-faint); line-height: 1.45; margin: 0;
}

@media (prefers-reduced-motion: reduce) {
  .card-title-hint { transition: none; }
}

@media (max-width: 560px) {
  .modal { padding: 22px 20px 20px; }
  .card-title-hint { display: none; }
}

/* While a search is running there is nothing to filter, so the rail stays
   out of the way rather than showing empty headings. */
.workspace.loading { grid-template-columns: minmax(0, 1fr); }
.workspace.loading .rail { display: none; }
/* Search and sort live inside .rail now, so hiding the rail during loading
   already covers them - nothing else needed here. The legend stays put; it
   is harmless to see while loading and used to sit in the same wrapper as
   search/sort for layout reasons only, not because it needed hiding too. */

/* ---------- Talon visual system ---------- */

/* Frosted tile treatment from the live site: translucent navy, 15px radius,
   30px padding, soft border, blur, no shadow. */
/* Nothing inside an expanded row may widen it. A long unbroken string — a
   gene symbol, an assay name, a paper title — would otherwise set the row's
   minimum width and push the whole list out when opened. */
.row { min-width: 0; overflow: hidden; }
.detail, .cards, .card, .refs, .card-refs { min-width: 0; }

/* Every text element inside an expanded row. A single long unbroken string —
   a gene alias, a compound assay label, a paper title with a long identifier —
   otherwise sets the element's minimum width, which propagates outward and
   widens the whole list. This is why a typed disease could stretch the layout
   while the suggested ones did not: it is a property of the content, not the
   query. */
.detail *,
.row-ident *,
.card-title, .card-detail, .card-absent-note, .rationale,
.tag, .refs li, .refs a, .card-refs li, .card-refs a,
.service-name, .service-pitch, .service-detail,
.symbol, .alias, .row-summary {
  overflow-wrap: anywhere;
  word-break: break-word;
  min-width: 0;
}

/* Belt and braces: the results column can never be widened from inside. */
.results { min-width: 0; max-width: 100%; overflow-x: clip; }

.row {
  background: var(--surface-glass);
  border: 1px solid var(--line-tile);
  border-radius: var(--radius-card);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  box-shadow: none;
}
.row.open { border-color: rgba(96, 82, 212, 0.35); }
.row-btn:hover { background: rgba(255, 255, 255, 0.03); }

.detail { background: rgba(0, 0, 0, 0.18); }

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 12px;
}
.card.absent { background: rgba(255, 255, 255, 0.02); }

/* The blue glow is the signature interaction across the live site. */
.searchbar button:hover,
.example:hover,
.chip:hover,
.reset:hover,
.contact-cta:hover,
.modal-close:hover {
  box-shadow: var(--glow);
  border-color: var(--glow-border);
  transform: translateY(-1px);
}
.searchbar button:focus-visible,
.example:focus-visible,
.chip:focus-visible,
.reset:focus-visible {
  box-shadow: var(--glow);
  border-color: var(--glow-border);
  outline: none;
}

.chip[aria-pressed="true"] {
  background: var(--accent-wash);
  border-color: rgba(96, 82, 212, 0.45);
  color: #ffffff;
}



.reset {
  background: rgba(255, 255, 255, 0.04);
  color: #ffffff;
  border-color: var(--line);
}

/* A translucent background on a native select leaves the dropdown list
   rendering against the OS default, which put white text on white. The
   control and its options both need an opaque colour, and color-scheme
   tells the browser to draw the native parts dark. */




.modal { background: var(--ink); border: 1px solid var(--line); }
.contact { background: rgba(255, 255, 255, 0.04); border: 1px solid var(--line); }
.contact-cta { background: var(--accent-wash); border: 1px solid rgba(96, 82, 212, 0.45); }
.contact-cta:hover { background: rgba(96, 82, 212, 0.24); }

.empty { background: var(--surface-glass); border-color: var(--line-tile); }

.status.error { background: rgba(244,63,94,0.16); border-color: rgba(244,63,94,0.32); color: #fecdd3; }
.status.notice { background: rgba(245,158,11,0.16); border-color: rgba(245,158,11,0.32); color: #fde68a; }

@media (prefers-reduced-motion: reduce) {
  .searchbar button:hover, .example:hover, .chip:hover,
  .reset:hover, .contact-cta:hover { transform: none; }
}

/* ---------- loading panel ---------- */

.loading-panel {
  list-style: none;
  max-width: 420px;
  margin: 48px auto;
  text-align: center;
}

.loading-term {
  font: 500 17px var(--font-display);
  color: #ffffff;
  margin: 0 0 18px;
  letter-spacing: -0.01em;
}

.loading-bar {
  height: 2px;
  background: rgba(255, 255, 255, 0.10);
  border-radius: 2px;
  overflow: hidden;
  margin-bottom: 16px;
}
.loading-bar span {
  display: block;
  height: 100%;
  width: 38%;
  border-radius: 2px;
  background: linear-gradient(90deg,
    rgba(96, 82, 212, 0) 0%,
    rgba(96, 82, 212, 0.95) 50%,
    rgba(96, 82, 212, 0) 100%);
  animation: track 1.5s cubic-bezier(0.45, 0, 0.55, 1) infinite;
}
@keyframes track {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(363%); }
}

.loading-stage {
  font-size: 13.5px;
  color: rgba(255, 255, 255, 0.80);
  margin: 0 0 5px;
  min-height: 20px;
}

.loading-elapsed {
  font: 400 12px var(--font-mono);
  color: rgba(255, 255, 255, 0.45);
  margin: 0;
  font-variant-numeric: tabular-nums;
}

@media (prefers-reduced-motion: reduce) {
  .loading-bar span { animation: none; width: 100%; opacity: 0.5; }
}

/* ---------- spelling suggestion ---------- */

/* Sits on its own line under whatever message is showing, so it reads as an
   offer rather than a continuation of an error. */
.suggest {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-wrap: wrap;
  margin-top: 9px;
  padding-top: 9px;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  font-size: 13.5px;
}

.suggest-link {
  background: rgba(96, 82, 212, 0.16);
  border: 1px solid rgba(96, 82, 212, 0.45);
  border-radius: 100px;
  padding: 4px 14px;
  font: 500 13.5px var(--font-body);
  color: #ffffff;
  cursor: pointer;
}
.suggest-link:hover {
  background: rgba(96, 82, 212, 0.26);
  box-shadow: var(--glow);
  border-color: var(--glow-border);
}
.suggest-link:focus-visible {
  outline: none;
  box-shadow: var(--glow);
  border-color: var(--glow-border);
}

.suggest-count {
  font: 400 12px var(--font-mono);
  color: rgba(255, 255, 255, 0.55);
}

/* ---------- routing reasoning in the service modal ---------- */

.reason-facts {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 0 14px;
}

.reason-fact {
  font: 400 11.5px var(--font-mono);
  background: var(--accent-wash);
  border: 1px solid rgba(96, 82, 212, 0.4);
  color: #ffffff;
  padding: 3px 9px;
  border-radius: 3px;
}

.reason-note {
  margin: 0 0 8px;
  font-size: 13.5px;
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.86);
}

/* Sits between the reasoning and the offer, quieter than both — it explains
   how the choice was reached rather than making the case for it. */
.reason-basis {
  margin: 12px 0 18px;
  padding-top: 12px;
  border-top: 1px solid var(--line-soft);
  font: 400 12.5px var(--font-body);
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.6);
}

/* ---------- in-house vs partnered ---------- */

.service-head-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 5px;
}
.service-head-row .service-name { margin: 0; }

.service-delivery {
  font: 500 10.5px var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: 3px 9px;
  border-radius: 3px;
  white-space: nowrap;
}
.service-delivery[data-mode="in-house"] {
  background: rgba(45, 212, 191, 0.16);
  border: 1px solid rgba(45, 212, 191, 0.32);
  color: #99f6e4;
}
.service-delivery[data-mode="partnered"] {
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.2);
  color: rgba(255, 255, 255, 0.75);
}
