/* LabMap — mobile first. She is standing up, holding a phone, being interrupted.
   The trust colors are load-bearing: they are how a physician tells a confirmed
   number from a guess at a glance. Do not reuse them for decoration. */

:root {
  --ink: #14171a;
  --muted: #5c6670;
  --line: #dde2e6;
  --bg: #ffffff;
  --panel: #f6f8f9;

  --verified: #0f7b3f;
  --verified-bg: #e8f5ed;
  --published: #45505a;
  --published-bg: #eef1f3;
  --caution: #a45c00;
  --caution-bg: #fdf3e3;
  --danger: #a01b1b;
  --danger-bg: #fbeaea;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  color: var(--ink);
  background: var(--bg);
  -webkit-text-size-adjust: 100%;
}

main { padding: 1rem; max-width: 44rem; margin: 0 auto; }

.topbar {
  display: flex; justify-content: space-between; align-items: center;
  padding: .75rem 1rem; border-bottom: 1px solid var(--line);
}
.brand { font-weight: 700; letter-spacing: -.02em; text-decoration: none; color: var(--ink); }
.topbar nav a { color: var(--muted); text-decoration: none; font-size: .9rem; }

/* --- search ---------------------------------------------------------------- */

.search { display: flex; gap: .5rem; margin-bottom: 1rem; }
.search input {
  flex: 1; padding: .85rem; font-size: 1.05rem;
  border: 1px solid var(--line); border-radius: .5rem;
}
.search button {
  padding: .85rem 1.1rem; font-size: 1rem; border: 0; border-radius: .5rem;
  background: var(--ink); color: #fff;
}

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

.results { list-style: none; padding: 0; margin: 0; }
.results li { border-bottom: 1px solid var(--line); }
.results a {
  display: block; padding: .9rem .25rem; text-decoration: none; color: var(--ink);
}
.results .name { display: block; font-weight: 600; }
.results .matched { display: block; font-size: .82rem; color: var(--muted); }
.results .cat { display: inline-block; font-size: .82rem; color: var(--muted); }

/* --- browse by category ----------------------------------------------------
   The catalog's entry point when she has no name to type. Two taps to any test:
   discipline, then test. Deliberately the same row treatment as .results, so
   moving between the two levels does not feel like changing screens. */

.categories { list-style: none; padding: 0; margin: 0; }
.categories li { border-bottom: 1px solid var(--line); }
.categories a {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: .75rem; padding: .9rem .25rem; text-decoration: none; color: var(--ink);
}
.categories .name { font-weight: 600; }
.categories .cat { font-size: .82rem; color: var(--muted); white-space: nowrap; }

.crumb { margin: 0 0 .5rem; font-size: .9rem; }
.crumb a { color: var(--muted); text-decoration: none; }

.cat-title {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: .75rem; margin: 0 0 .25rem; font-size: 1.15rem;
}
.cat-count { font-size: .82rem; font-weight: 400; color: var(--muted); }

.stat-flag {
  display: inline-block; margin-left: .4rem; padding: .05rem .4rem;
  font-size: .7rem; font-weight: 700; text-transform: uppercase;
  color: var(--danger); background: var(--danger-bg); border-radius: .25rem;
}

/* --- empty states are a feature, not a failure ----------------------------- */

.empty {
  padding: 1.5rem; background: var(--panel);
  border: 1px solid var(--line); border-radius: .6rem; margin-top: 1rem;
}
.empty h2 { margin-top: 0; font-size: 1.15rem; }
.cta {
  display: inline-block; margin-top: .75rem; padding: .8rem 1rem;
  background: var(--ink); color: #fff; border-radius: .5rem;
  text-decoration: none; font-weight: 600;
}
.cta-note { font-size: .9rem; color: var(--muted); }

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

.test-head h1 { font-size: 1.4rem; margin: .25rem 0; letter-spacing: -.01em; }
.aka, .meta { color: var(--muted); font-size: .85rem; margin: .2rem 0; }
.desc { font-size: .95rem; }

/* Each laboratory is a card, and which laboratory it is has to be readable at
   a glance — she is comparing them, not reading one.

   The accent is a per-lab identity colour (app/trust.py). It is applied as a
   TOP edge and to the heading, never as a left border: `border-left` already
   means trust tier on .headline below, and green/amber/red already mean
   verified/caution/danger. A lab must not be able to borrow either signal. */
.lab-card {
  border: 2px solid var(--line);
  border-top: 5px solid var(--lab-accent, var(--line));
  border-radius: .6rem;
  padding: 1rem 1rem 1.1rem;
  margin: 1.5rem 0;
  background: var(--bg);
}
.lab-card h2 {
  font-size: 1.15rem; margin: 0 0 .3rem;
  display: flex; align-items: baseline; flex-wrap: wrap; gap: .5rem;
}
/* Not uppercase any more. A laboratory's name is a proper noun with its own
   shape — 'Michigan Medicine MLabs' is quicker to recognise set normally than
   flattened into capitals, and these are scanned rather than read. */
.lab-card h2 .lab-name {
  color: var(--lab-accent, var(--ink));
  letter-spacing: -.01em; font-weight: 650;
}

/* Her own laboratory is the one she can actually send to, so it gets the extra
   weight — a tinted rail rather than another colour, which would compete with
   the identity accent it sits next to. */
.lab-card.is-mine {
  box-shadow: inset 4px 0 0 var(--lab-accent, var(--line));
  padding-left: 1.4rem;
}
.my-lab {
  font-size: .7rem; font-weight: 600; text-transform: uppercase;
  letter-spacing: .06em; color: #fff; background: var(--lab-accent, var(--muted));
  padding: .16rem .45rem; border-radius: .3rem; white-space: nowrap;
}

@media (prefers-reduced-motion: no-preference) {
  .lab-card { transition: border-color .15s ease; }
}

/* The volume block is what she came for. It gets the most visual weight. */
.volume-block {
  background: var(--panel); border-radius: .5rem;
  padding: .85rem; margin: .75rem 0;
}
.specimen { margin: 0 0 .6rem; font-size: .9rem; }

.headline { padding: .6rem; border-radius: .4rem; border-left: 4px solid var(--published); background: #fff; }
.headline.tier-verified { border-left-color: var(--verified); background: var(--verified-bg); }
.headline.is-stale { border-left-color: var(--danger); background: var(--danger-bg); }
.hl-label { display: block; font-size: .78rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.hl-value { display: block; font-size: 2.1rem; font-weight: 700; line-height: 1.1; letter-spacing: -.02em; }
.prov { display: block; font-size: .78rem; color: var(--muted); margin-top: .25rem; }
.headline blockquote {
  margin: .5rem 0 0; padding-left: .6rem; border-left: 2px solid var(--line);
  font-size: .85rem; color: var(--muted);
}

.supporting {
  display: flex; flex-wrap: wrap; gap: .5rem; align-items: baseline;
  margin: .5rem 0 0; font-size: .9rem;
}
.sp-label { color: var(--muted); }
.sp-value { font-weight: 600; }
.supporting.tier-estimated, .supporting.tier-reported {
  border: 1px dashed var(--caution); background: var(--caution-bg);
  border-radius: .35rem; padding: .4rem .5rem;
}
.basis { flex-basis: 100%; font-size: .75rem; color: var(--muted); }

.badge {
  font-size: .68rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; padding: .12rem .4rem; border-radius: .25rem;
  white-space: nowrap;
}
.badge-verified  { color: #fff; background: var(--verified); }
.badge-published { color: var(--published); background: var(--published-bg); }
.badge-reported,
.badge-estimated { color: var(--caution); background: var(--caution-bg); border: 1px solid var(--caution); }
.badge-stale     { color: #fff; background: var(--danger); }

.no-number { padding: .6rem; border: 1px solid var(--danger); border-radius: .4rem; background: var(--danger-bg); }
.no-number p { margin: 0 0 .25rem; }

.suppressed { font-size: .78rem; color: var(--muted); font-style: italic; margin: .5rem 0 0; }
.stale-banner {
  background: var(--danger-bg); color: var(--danger); border-radius: .35rem;
  padding: .4rem .6rem; font-size: .85rem; font-weight: 600;
}

/* A laboratory saying a test is obsolete or panel-only. Loud, because acting
   on it costs a second stick — but amber, not red: red already means a
   rejected specimen and the two are different problems. */
.offering-warning {
  background: var(--warn-bg, #fdf3e3); color: var(--warn, #8a5a2f);
  border-left: 3px solid currentColor; border-radius: .35rem;
  padding: .4rem .6rem; font-size: .85rem; margin: .5rem 0;
}
/* Collection detail the boolean handling flags cannot express. Same weight as
   .handling, which it sits beside — it is the prose half of the same answer. */
.collection-detail { font-size: .9rem; margin: .5rem 0; }
.collection-detail ul { margin: .3rem 0; padding-left: 1.1rem; }
.offering-notes { font-size: .8rem; color: var(--muted); margin: .5rem 0; }

.tube, .rejection, .shipping, .contact { font-size: .9rem; margin: .5rem 0; }
.handling { font-size: .9rem; margin: .5rem 0; }
.handling ul { margin: .3rem 0; padding-left: 1.1rem; }
.rejection { color: var(--danger); }
.verified-line { font-size: .78rem; color: var(--muted); margin: .5rem 0 0; }
.muted { color: var(--muted); }

/* --- disclaimer ------------------------------------------------------------ */

.disclaimer {
  max-width: 44rem; margin: 2rem auto 3rem; padding: 1rem;
  font-size: .8rem; color: var(--muted);
  border-top: 1px solid var(--line);
}
.disclaimer strong { display: block; color: var(--ink); margin-bottom: .25rem; }

@media (prefers-color-scheme: dark) {
  :root {
    --ink: #e9edf0; --muted: #9aa5ae; --line: #2c333a;
    --bg: #14171a; --panel: #1c2126;
    --verified: #35b06a; --verified-bg: #10301f;
    --published: #a3aeb8; --published-bg: #232a30;
    --caution: #d8951f; --caution-bg: #33260d;
    --danger: #e26868; --danger-bg: #331515;
  }
  .headline { background: #1c2126; }
  .search button, .cta { background: #2f6feb; }
}

/* --- contribution ----------------------------------------------------------
   Three questions and twenty seconds. Tap targets are sized for a thumb, on a
   phone, in a room with an alarming monitor. */

.back { display: inline-block; margin-bottom: .5rem; color: var(--muted); text-decoration: none; font-size: .9rem; }
.contribute-head h1 { font-size: 1.25rem; margin: .25rem 0 .5rem; }
.ctx-line { margin: .1rem 0; font-size: .95rem; }

.field-group { border: 0; padding: 0; margin: 1.25rem 0; }
.field-group legend, .lbl {
  padding: 0; font-size: .75rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .06em; color: var(--muted); display: block; margin-bottom: .5rem;
}

.radio {
  display: flex; align-items: center; gap: .6rem;
  padding: .7rem .25rem; border-bottom: 1px solid var(--line); cursor: pointer;
}
.radio input { width: 1.15rem; height: 1.15rem; accent-color: var(--verified); }

.value-row { display: flex; align-items: baseline; gap: .5rem; }
.value-row input {
  width: 7rem; padding: .7rem; font-size: 1.6rem; font-weight: 700;
  border: 1px solid var(--line); border-radius: .5rem; background: var(--bg); color: var(--ink);
}
.unit { font-size: 1.1rem; color: var(--muted); }
.current-value { font-size: .85rem; color: var(--muted); margin: .5rem 0 0; }

textarea, input.wide, input[type=date] {
  width: 100%; padding: .7rem; font-size: 1rem; font-family: inherit;
  border: 1px solid var(--line); border-radius: .5rem;
  background: var(--bg); color: var(--ink);
}
textarea { resize: vertical; }

.chips { display: flex; flex-wrap: wrap; gap: .4rem; margin-bottom: .6rem; }
.chip { position: relative; }
.chip input { position: absolute; opacity: 0; pointer-events: none; }
.chip span {
  display: inline-block; padding: .5rem .75rem; font-size: .9rem;
  border: 1px solid var(--line); border-radius: 1.2rem; cursor: pointer;
}
.chip input:checked + span { background: var(--ink); color: var(--bg); border-color: var(--ink); }

.submit {
  width: 100%; padding: .95rem; font-size: 1.05rem; font-weight: 700;
  border: 0; border-radius: .5rem; background: var(--verified); color: #fff;
}
.promise { font-size: .82rem; color: var(--muted); margin-top: .75rem; }
.form-error {
  background: var(--danger-bg); color: var(--danger); border: 1px solid var(--danger);
  border-radius: .4rem; padding: .6rem .75rem; font-size: .9rem; font-weight: 600;
}
/* An affordance, not a footnote. This is the only way into the growth engine,
   and a plain inline link reads as boilerplate next to the volume block. */
.add-learned { margin: .85rem 0 0; }
.add-learned a {
  display: block; padding: .7rem .8rem; font-size: .9rem; font-weight: 600;
  text-align: center; text-decoration: none; color: var(--ink);
  border: 1px dashed var(--line); border-radius: .5rem; background: var(--panel);
}
.record-after-call { margin: .6rem 0 0; }
.record-after-call a {
  display: inline-block; font-weight: 700; font-size: .9rem; color: var(--danger);
}
.record-after-call .cta-note { display: block; margin-top: .15rem; font-size: .8rem; }

.saved-banner {
  background: var(--verified-bg); border-left: 4px solid var(--verified);
  border-radius: .4rem; padding: .7rem .85rem; font-size: .9rem;
}
.my-pending {
  border: 1px dashed var(--caution); background: var(--caution-bg);
  border-radius: .5rem; padding: .75rem .85rem; margin: 1rem 0;
}
.my-pending h2 { font-size: .8rem; text-transform: uppercase; letter-spacing: .06em; margin: 0 0 .5rem; color: var(--caution); }
.pending-row { margin: .3rem 0; font-size: .9rem; display: flex; flex-wrap: wrap; gap: .4rem; align-items: baseline; }

/* --- my contributions ------------------------------------------------------ */

.contrib-list { list-style: none; padding: 0; margin: 1rem 0; }
.contrib { border: 1px solid var(--line); border-radius: .5rem; padding: .85rem; margin-bottom: .75rem; }
.contrib-head { margin: 0 0 .25rem; font-weight: 600; }
.contrib-head a { color: var(--ink); }
.contrib-claim { margin: .25rem 0; }
.contrib-meta { font-size: .8rem; color: var(--muted); margin: .5rem 0 0; }
.contrib blockquote {
  margin: .4rem 0; padding-left: .6rem; border-left: 2px solid var(--line);
  font-size: .88rem; color: var(--muted);
}
.status-badge {
  display: inline-block; font-size: .68rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: .05em; padding: .12rem .4rem; border-radius: .25rem; margin-right: .35rem;
}
.status-badge.status-pending,
.status-badge.status-needs_info { color: var(--caution); background: var(--caution-bg); border: 1px solid var(--caution); }
.status-badge.status-approved { color: #fff; background: var(--verified); }
.status-badge.status-rejected,
.status-badge.status-duplicate { color: var(--muted); background: var(--panel); border: 1px solid var(--line); }
.review-note { font-size: .85rem; color: var(--muted); margin: .4rem 0 0; font-style: italic; }

/* --- review queue ----------------------------------------------------------
   Triage, not a form. Under fifteen seconds an item, keyboard only. */

.queue-head h1 { font-size: 1.3rem; margin: .25rem 0; }
.review-item {
  border: 1px solid var(--line); border-left: 4px solid transparent;
  border-radius: .5rem; padding: .9rem; margin: 1rem 0;
}
.review-item[data-active] { border-left-color: var(--ink); background: var(--panel); }
.review-item h2 { font-size: 1rem; margin: 0 0 .4rem; }
.review-item .sep { color: var(--muted); }
.claim { margin: .25rem 0; font-size: 1.05rem; }
.claim strong { font-size: 1.35rem; }
.current { margin: .4rem 0; font-size: .9rem; }
.review-item blockquote {
  margin: .5rem 0; padding-left: .6rem; border-left: 2px solid var(--line);
  font-size: .9rem; color: var(--muted);
}

/* The dangerous direction. Loud on purpose. */
.drop-warning {
  background: var(--danger-bg); color: var(--danger); border: 1px solid var(--danger);
  border-radius: .4rem; padding: .55rem .7rem; font-weight: 700; font-size: .9rem;
}
.delta-up { font-size: .85rem; color: var(--muted); }
.manual-note {
  font-size: .85rem; color: var(--caution); background: var(--caution-bg);
  border-radius: .35rem; padding: .5rem .65rem;
}

.prov-grid {
  display: grid; grid-template-columns: auto 1fr; gap: .2rem .75rem;
  font-size: .85rem; margin: .6rem 0;
}
.prov-grid dt { color: var(--muted); text-transform: uppercase; font-size: .7rem; letter-spacing: .05em; padding-top: .15rem; }
.prov-grid dd { margin: 0; }

.review-actions { margin-top: .75rem; }
.btn-row { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .5rem; }
.btn {
  padding: .55rem .7rem; font-size: .85rem; font-weight: 600; font-family: inherit;
  border: 1px solid var(--line); border-radius: .4rem;
  background: var(--bg); color: var(--ink); cursor: pointer;
}
.btn-verified { background: var(--verified); color: #fff; border-color: var(--verified); }
.btn-danger { color: var(--danger); border-color: var(--danger); }
.btn-skip { color: var(--muted); }

/* --- staging ---------------------------------------------------------------- */

.staged .field-group { margin: .75rem 0; }
.staged .radio { border-bottom: 1px solid var(--line); }
.staged-blocked { opacity: .82; border-left-color: var(--caution); }

/* The line the number was read from. If it does not support the figure above,
   nothing else on the card matters — so it is set apart, not buried. */
.verbatim {
  margin: .5rem 0; padding: .5rem .7rem;
  border-left: 3px solid var(--published); background: var(--panel);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: .82rem; color: var(--ink);
}
.prov-grid dd a { word-break: break-all; font-size: .82rem; }

.pill, .pill-on {
  display: inline-block; padding: .2rem .55rem; margin-right: .3rem;
  border-radius: 1rem; font-size: .78rem; text-decoration: none;
  border: 1px solid var(--line); color: var(--muted);
}
.pill-on { background: var(--ink); color: var(--bg); border-color: var(--ink); }

/* --- gap report ------------------------------------------------------------ */
.gaps { width: 100%; border-collapse: collapse; margin: 1rem 0; font-size: .9rem; }
.gaps th, .gaps td { text-align: left; padding: .45rem .5rem; border-bottom: 1px solid var(--line); }
.gaps th { font-size: .75rem; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }
.gaps a { color: var(--ink); }
.gaps .row-critical { background: var(--danger-bg); }
.gaps .row-critical td:first-child { font-weight: 700; }

/* --- curation queue --------------------------------------------------------
   Triage like /review, but with editable text: the reviewer is correcting
   wording, not only approving a number. */

.batch-bar { list-style: none; display: flex; flex-wrap: wrap; gap: .4rem;
  padding: 0; margin: 0 0 1rem; }
.batch-bar a {
  display: inline-block; padding: .3rem .6rem; font-size: .82rem;
  text-decoration: none; color: var(--muted);
  border: 1px solid var(--line); border-radius: .4rem;
}
.batch-bar strong { color: var(--ink); }

.prov-line { font-size: .78rem; color: var(--muted); margin: .2rem 0 .6rem; }

.curate-form label {
  display: block; margin-bottom: .5rem;
  font-size: .78rem; font-weight: 600; color: var(--muted);
}
.curate-form input[type="text"], .curate-form textarea {
  display: block; width: 100%; margin-top: .15rem; padding: .5rem;
  font: inherit; font-size: .92rem; font-weight: 400; color: var(--ink);
  /* Token, not #fff — the stylesheet has a prefers-color-scheme block and a
     hardcoded white field renders as white-on-white text in dark mode. */
  border: 1px solid var(--line); border-radius: .35rem; background: var(--bg);
  resize: vertical;
}
/* An empty box here means "the rule refused to guess this", which is a
   deliberate state and should look like one rather than like an oversight. */
.curate-form textarea:placeholder-shown, .curate-form textarea:empty {
  background: var(--panel);
}
.curate-item[data-active] { box-shadow: 0 0 0 2px var(--ink); }
