/* THEME gpi: the Global Peptide Index design system, components/bundle.css VERBATIM from the design canvas
   https://claude.ai/artifact/SLc6U2BS6bj7QzFiQuVcYW (project/ds/gpi, version 1791226430-fc6c, sha256 324688ba). It is the live
   site stylesheet of globalpeptideindex.com (Qann-Team/global-review engine/apps/web/app/styles.css) plus its APP LAYER.
   Do not edit here: change the design system and copy it again. */
/* Spec: docs/architecture/20260831_spec_global-review_public-registry-site_SPEC-0217_v1.md
   Product foundation: docs/product/20260829_strategy_global-review_product-foundation_v1.md

   THE DESIGN SYSTEM, rewritten 2026-08-31 to match the approved homepage direction.

   The previous stylesheet was the operator console's: warm cream, one weight of type, tables for
   everything. It was correct for a control surface being read by one person who built it, and it
   was never the public property's design. The foundation asked for a workspace - "persistent left
   navigation, large central working canvas, minimal decoration and restrained colour, typography
   with editorial authority, strong tables, timelines and comparisons, light and dark themes using
   the same semantic tokens" - and the last item had never been built at all.

   BOTH THEMES EXIST FROM ONE TOKEN SET, and DARK IS THE DEFAULT (director ruling 2026-08-31).
   There is deliberately no `prefers-color-scheme` rule in this file. There briefly was one, and it
   meant the design he approved was whatever the visitor's laptop happened to prefer. Light is now
   reached by stamping `data-theme="light"` and by nothing else.

   Cool slate rather than cream, because a dense quantitative surface needs a ground that recedes.
   An editorial serif for display, because it is what stops a peptide site reading as a supplement
   shop. Every class name here is one the components already emit, so this changes how the site
   looks and nothing about what it renders. */

/* ---------------------------------------------------------------- tokens: the peptides skin
   RATIFIED 2026-10-02 (director: "1 approve", on the design canvas), Global Index brand bible
   chapters 06 to 08, ghosteam-saas cloud/brandkit/canon/globalindex. This SUPERSEDES the dark
   default of 2026-08-31: clinical white ground, one teal accent, meaning carried by pills, Geist.
   Every text pair is at least 5.25:1. Light only, so no theme block and no media query: an OS
   preference must not override a decision the property made. */
:root{
  color-scheme:light;
  --bg:#F6F8F9; --surface:#FFFFFF; --surface-2:#F0F4F6; --line:#E2E8EC; --line-2:#CBD5DB;
  --ink:#0D1B24; --ink-2:#3E4E59; --muted:#5A6A75;
  --accent:#0A6B87; --accent-ink:#064F64; --accent-soft:#E2F0F4;
  --good:#0E5F39; --warn:#874600; --bad:#9E2418;
  /* Data colours are the pill colours (06.2), so a chart and a pill can never disagree. */
  --c-done:#0E5F39; --c-live:#1B4A9E; --c-stop:#9E2418; --c-quiet:#874600; --c-grid:#E2E8EC;
  --soft:var(--accent-soft);
  --sans:Geist,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
  --mono:"Geist Mono",ui-monospace,Menlo,monospace;
  /* The dashed edge of "not read" (06.2 p-unk) and the map fills of the WorldMap board. */
  --dash:#8A99A3; --m-ok:#2E8B5E; --m-no:#A9B6BE; --m-unk:#F3F5F6;
}

*{box-sizing:border-box}
body{
  margin:0; background:var(--bg); color:var(--ink);
  font-family:var(--sans);
  font-size:15px; line-height:1.55; -webkit-font-smoothing:antialiased;
}
a{color:var(--accent); text-decoration:none}
a:hover{color:var(--accent-ink); text-decoration:underline}
:focus-visible{outline:2px solid var(--accent); outline-offset:2px}
@media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

/* ---------------------------------------------------------------- shell: the top bar
   Ratified design (Main board): a white bar, the mark and wordmark left, the sections in a row,
   one primary button. The sidebar of 2026-08-31 is retired with the dark theme it was drawn for.
   FULL WIDTH STAYS (director ruling 2026-09-03): the board drew a 1280px column, but no ruling has
   reversed that one, so the bar and the page keep their padding and take the window. */
.shell{min-height:100vh; display:flex; flex-direction:column}
.topbar{background:var(--surface); border-bottom:1px solid var(--line)}
.topbarIn{
  padding:12px 40px;
  display:flex; flex-wrap:wrap; align-items:center; gap:16px 32px;
}
/* The wordmark, and on the front page it is also the <h1>. Every property is declared here rather
   than inherited so the two render identically. */
.brand{font-family:var(--sans); font-weight:600; font-size:16px; line-height:1.2; letter-spacing:0; margin:0; padding:0}
.brandLink{color:var(--ink); text-decoration:none; display:flex; align-items:center; gap:10px}
.brandLink:hover{color:var(--ink); text-decoration:none}
.brandMark{width:32px; height:32px; flex:none}
.brandMark .bmBack{fill:#7DB6C7; stroke:#7DB6C7; stroke-width:0.6; stroke-linejoin:round}
.brandMark .bmGap{fill:var(--surface); stroke:var(--surface); stroke-width:1.2; stroke-linejoin:round}
.brandMark .bmFront{fill:var(--accent); stroke:var(--accent); stroke-width:0.6; stroke-linejoin:round}
.topCta{
  display:inline-flex; align-items:center; min-height:40px; padding:0 18px; border-radius:10px;
  background:var(--ink); color:var(--surface); font-weight:600; font-size:15px; text-decoration:none;
}
.topCta:hover{color:var(--surface); text-decoration:none; opacity:.92}
.siteFoot{border-top:1px solid var(--line); background:var(--surface); margin-top:auto}
.siteFootIn{padding:24px 40px; color:var(--muted); font-size:13px}

/* The trail. Small, quiet, above the page's own heading, and it never repeats the h1 that follows
   it: the last crumb IS that heading, which is why it is text and not a link. */
.crumbs{
  display:flex; flex-wrap:wrap; align-items:baseline; gap:8px;
  font-family:var(--mono);
  font-size:12px; letter-spacing:.02em; color:var(--muted); margin-bottom:4px;
}
.crumbs a{ color:var(--ink-2); text-decoration:none; border-bottom:1px solid var(--line) }
.crumbs a:hover{ color:var(--accent); border-bottom-color:var(--accent) }
.crumbs [aria-current="page"]{ color:var(--ink) }
.crumbSep{ color:var(--muted); opacity:.6; padding:0 2px }
.nav{display:flex; flex-wrap:wrap; gap:8px 24px; flex-grow:1}
.nav a{color:var(--ink-2); font-size:14px; font-weight:500; text-decoration:none}
.nav a:hover{color:var(--ink); text-decoration:none}
.nav a.active,.nav a[aria-current="page"]{color:var(--ink); font-weight:600}
/* FULL WIDTH IS THE DESIGN (director, 2026-09-03). A `max-width:1400px` was added here earlier
   the same day and REVERTED: the symptom was real and the diagnosis was wrong. Oversized panels
   on inner pages are a HERO problem, not a width problem, and capping the shell treated every
   page as if it were a column of prose. Do not add a cap here again. */
.main{
  padding:40px 40px 80px; min-width:0; width:100%;
  display:flex; flex-direction:column; gap:22px;
}

/* ---------------------------------------------------------------- type */
h1,h2,h3{
  font-family:var(--sans); font-weight:600;
  letter-spacing:-.02em; margin:0; text-wrap:balance;
}
.intro{display:flex; flex-direction:column; gap:14px; max-width:80ch; margin-bottom:8px}
.intro h1{font-size:clamp(32px,4.4vw,56px); line-height:1.04}
.lede{font-size:17px; line-height:1.6; color:var(--ink-2); max-width:66ch; margin:0}
.eyebrow{
  font-family:var(--mono); font-size:11px; letter-spacing:.08em; text-transform:uppercase; font-weight:500;
  color:var(--muted); margin:0 0 10px;
}
.muted{color:var(--muted)}
.mono,kbd{font-family:var(--mono); font-size:12.5px}
.disclaimer{color:var(--muted); font-size:12.5px; line-height:1.55}

/* ---------------------------------------------------------------- metric cards */
.metrics{display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr)); gap:12px}
.metric{
  background:var(--surface); border:1px solid var(--line); border-radius:12px;
  padding:17px 18px; display:flex; flex-direction:column; gap:5px;
}
.metricLabel{
  font-family:var(--mono); font-size:11px; letter-spacing:.08em; text-transform:uppercase; font-weight:500;
  color:var(--muted); margin:0;
}
.metricValue{
  font-family:var(--mono); font-weight:500; font-size:34px; line-height:1;
  letter-spacing:-.03em; margin:0; font-variant-numeric:tabular-nums;
}
.metricNote{margin:0; font-size:13px; color:var(--ink-2); line-height:1.45}
/* The two sentinels are WORDS, not figures, so they are set smaller and never in the display face:
   a sentence rendered at 36px reads as a number the reader failed to parse. */
.metric-unavailable .metricValue,.metric-nodata .metricValue{
  font-family:var(--sans); font-size:18px; letter-spacing:0;
}
.metric-unavailable .metricValue{color:var(--bad)}
.metric-nodata .metricValue{color:var(--muted)}

/* ---------------------------------------------------------------- panels */
/* TWO COLUMNS, and this is a REVERT of a change I shipped twice and broke twice.

   I replaced `1.35fr 1fr` with `repeat(auto-fit, minmax(440px, 1fr))` to get three and four cards
   per row on a wide monitor. It could never have worked, and the reason is the PAGE, not this rule:
   the homepage is three separate `<section class="grid">` blocks each holding exactly two panels.
   A four-column grid containing two panels leaves two empty columns, which is the dead space that
   was live for an hour.

   I also added `.panel.wide{grid-column:1/-1}`, which turned the left-hand chart card of each pair
   into a full-width band with its partner orphaned beneath it. That rule is gone too.

   To get three or four across, the SECTIONS have to merge into one grid with six panels in it.
   That is a change to page.tsx, made deliberately and looked at, not a value edited in this file. */
.grid{display:grid; grid-template-columns:repeat(2, minmax(0, 1fr)); gap:14px}

/* THREE ACROSS ON A LARGE MONITOR, and this is a viewport question, correctly.
   `.grid` is page layout, not a card's internals, so it asks about the window and that is the
   right box. The rule inside a card asks about the card; both are in this file and they measure
   different things on purpose.

   AN EXPLICIT COUNT, NOT `auto-fit`. auto-fit shipped twice and broke twice: it turns the number
   of columns into something the browser derives from a minimum width, so a section holding two
   cards silently left two columns empty and there was no value to tune that would have fixed it.
   Two, then three. A reader can predict it and so can I. */
@media(min-width:1500px){ .grid{grid-template-columns:repeat(3, minmax(0, 1fr))} }
@media(max-width:900px){ .grid{grid-template-columns:1fr} }

/* `wide` spans the row it is in. On the homepage nothing uses it any more: the six cards are peers
   and a spanning card among them is two empty columns. It stays for the pages that genuinely have
   one full-width thing, like a records table. */
.grid > .panel.wide{grid-column:1 / -1}
.grid:has(> .panel.wide:only-child){grid-template-columns:1fr}
.panel{
  background:var(--surface); border:1px solid var(--line); border-radius:12px;
  padding:20px 22px; display:flex; flex-direction:column; gap:12px; min-width:0;
  /* THE CARD IS THE CONTAINER, and this line is the fix for a live defect. Everything inside a
     panel that needs to adapt must measure THE PANEL, because after the grid learned to make three
     and four columns the window is no longer a proxy for the card: a 2000px monitor was rendering
     340px cards, so every `@media(max-width:...)` rule inside one was asking about a box it was
     not in and answering about a box that was. */
  container-type:inline-size;
}
/* flex-start, not start: autoprefixer warns that `start` has mixed support, and this is the one
   build warning the site carries. Same behaviour, one fewer thing to read past next time. */
.panelHead{display:flex; align-items:flex-start; justify-content:space-between; gap:16px}
.panel h2{font-size:20px; margin:0}
.panel button{
  border:1px solid var(--line); background:transparent; color:var(--ink);
  border-radius:8px; padding:8px 10px; font:inherit; font-size:13px;
}

/* ---------------------------------------------------------------- tables */
table{width:100%; border-collapse:collapse; font-size:13.5px}
th,td{text-align:left; padding:9px 10px; border-top:1px solid var(--line); vertical-align:top}
thead th{
  border-top:0; font-size:10px; letter-spacing:.12em; text-transform:uppercase;
  color:var(--muted); font-weight:700;
}
table.statuses th{font-weight:500; color:var(--muted)}
tbody tr:hover{background:var(--surface-2)}
td.n,.num{font-variant-numeric:tabular-nums; font-family:var(--mono)}
.exceptions td,.exceptionItem td{font-size:13px}
.scorecard td{font-size:13px}

/* ---------------------------------------------------------------- charts
   Severity is carried by the WORD in the legend. There is no coloured edge anywhere in this file
   and there must never be one: a 3px stripe that means "warning" is a second channel the reader
   has to decode, beside a label that already says it in English. */
.chart{display:block; width:100%; height:auto; overflow:visible; margin:6px 0 2px}
.chart .axis{font:500 10.5px var(--mono); fill:var(--muted)}
.chart .vlab{font:600 11px var(--mono); fill:var(--ink)}
.chart .slab{font:500 11.5px var(--sans); fill:var(--ink)}
.chart .gridline{stroke:var(--c-grid); stroke-width:1}
.legend{display:flex; flex-wrap:wrap; gap:6px 16px; font-size:12.5px; color:var(--ink-2); margin:4px 0 0}
.legend span{display:inline-flex; align-items:center; gap:6px}
.legend i{width:10px; height:10px; border-radius:2px; display:block}
.figNote{
  margin:2px 0 0; font-size:11.5px; color:var(--muted);
  font-family:var(--mono);
}

/* ---------------------------------------------------------------- notices */
.banner{
  border:1px solid var(--line); background:var(--surface-2); color:var(--ink-2);
  border-radius:10px; padding:14px 16px; font-size:13px; line-height:1.55;
}
/* STATUS PILLS (06.2). Always a word inside; colour is never the only signal. */
.pill{
  display:inline-flex; align-items:center; gap:6px; height:24px; padding:0 10px; border-radius:999px;
  font-size:12px; font-weight:500; white-space:nowrap;
  border:1px solid transparent; background:#EEF1F3; color:var(--ink-2);
}
.p-ok{background:#E1F3EA; color:#0E5F39}
.p-trial{background:#E4ECFA; color:#1B4A9E}
.p-rx{background:#FFF0DB; color:#874600}
.p-ban{background:#FBE4E1; color:#9E2418}
.p-no{background:#EEF1F3; color:#3E4E59}
.p-unk{background:#FFFFFF; color:#3E4E59; border:1px dashed #8A99A3}
/* EVIDENCE GRADES (06.3). */
.g{display:inline-flex; align-items:center; height:20px; padding:0 6px; border-radius:4px; font-family:var(--mono);
   font-size:10px; letter-spacing:.06em; text-transform:uppercase; border:1px solid transparent; white-space:nowrap}
.g-reg{background:var(--ink); color:#FFFFFF}
.g-trial{border-color:var(--accent); color:var(--accent-ink); background:#FFFFFF}
.g-ind{border-color:var(--ink); color:var(--ink); background:#FFFFFF}
.g-co{border-color:#8A99A3; color:var(--ink-2); background:#FFFFFF}
.g-proxy{border:1px dashed #8A99A3; color:var(--ink-2); background:#FFFFFF}
/* THE ANSWER BOX: the first line of a page that answers a question. */
.answer{background:var(--accent-soft); border-radius:12px; padding:18px 20px; color:var(--accent-ink); font-size:16px; line-height:1.55}
.rowAction{display:flex; gap:8px; align-items:center}
.rowAction input{
  border:1px solid var(--line); border-radius:7px; padding:6px 8px; font-size:12px;
  width:120px; background:var(--surface); color:var(--ink);
}

/* ---------------------------------------------------------------- responsive */
@media(max-width:1000px){
  .topbarIn{padding:12px 16px}
  .nav{order:3; flex-basis:100%; overflow-x:auto; flex-wrap:nowrap; gap:20px}
  .main{padding:24px 16px 56px}
  .grid{grid-template-columns:1fr}
  .metrics{grid-template-columns:repeat(2,1fr)}
}
@media(max-width:560px){
  .metrics{grid-template-columns:1fr}
  .intro h1{font-size:32px}
  /* Wide content scrolls in its own box; the page body must never scroll sideways. */
  .panel{overflow-x:auto}
}

/* ---------------------------------------------------------------- ranked bars and ladder
   The bar IS the row. A ranked list of 60 compounds as a plain table asks the reader to compare
   numbers in a column; as bars it asks them to compare lengths, which is the one comparison people
   do accurately without effort. */
.ranked{display:flex; flex-direction:column}
.rankRow{
  display:grid; grid-template-columns:minmax(120px,1.1fr) 2fr auto; gap:12px;
  align-items:center; padding:7px 0; border-top:1px solid var(--line);
}
.rankRow:first-child{border-top:0}
.rankRow:hover{background:var(--surface-2)}
.rankLabel{font-size:13.5px; min-width:0; overflow-wrap:anywhere}
.rankLabel a{text-decoration:none}
.rankLabel a:hover{text-decoration:underline}
.rankLabel .muted{font-size:11.5px}
.rankTrack{height:12px; background:var(--surface-2); border-radius:3px; overflow:hidden}
.rankFill{height:100%; background:var(--accent); opacity:.8; border-radius:3px}
.rankValue{font-size:12.5px; color:var(--ink-2); text-align:right; min-width:56px}

/* The ladder: a numbered disc per rung, filled when reached. The state is a WORD beside it, never
   a colour on its own, and there is no edge painted anywhere. */
.ladder{display:flex; flex-direction:column}
.rung{
  display:grid; grid-template-columns:26px 1fr auto; gap:12px; align-items:center;
  padding:11px 0; border-top:1px solid var(--line);
}
.rung:first-child{border-top:0}
.rung i{
  width:22px; height:22px; border-radius:50%; display:grid; place-items:center; font-style:normal;
  font-family:var(--mono); font-size:11px; font-weight:600;
  border:1px solid var(--line); background:var(--surface-2); color:var(--muted);
}
.rung.on i{background:var(--accent); border-color:var(--accent); color:var(--surface)}
.rung b{font-weight:600; font-size:14px; color:var(--muted)}
.rung.on b{color:var(--ink)}
.rung .ev{font-family:var(--mono); font-size:12px; color:var(--muted)}
.rung.on .ev{color:var(--accent)}

@container (max-width:560px){
  .rankRow{grid-template-columns:1fr auto; gap:6px}
  .rankTrack{grid-column:1 / -1; order:3}
}

/* ---------------------------------------------------------------- console action buttons
   SCOPED UNDER .rowAction ON PURPOSE, and the specificity is load-bearing. `.panel button` above
   sets `background:transparent`, and a plainer `.btn-activate` rule loses to it on specificity
   while still winning on colour - which once rendered white text on a transparent button. These
   are console-only; they do not appear anywhere on the public site. */
.rowAction .btn-activate{background:var(--good); color:var(--surface); border-color:var(--good)}
.rowAction .btn-pause{background:var(--surface); color:var(--warn); border-color:var(--warn)}
.rowAction button:disabled{
  background:var(--surface-2); color:var(--muted); border-color:var(--line); cursor:not-allowed;
}

/* ---------------------------------------------------------------- donut
   THE RING FILLS THE CARD. It takes the largest square the card allows, and nothing caps it below
   that.

   THIRD ATTEMPT, and the first two were wrong in opposite directions, which is worth writing down
   because the second one's own comment argued confidently for the thing that kept it small. V1
   sized the ring off the panel's WIDTH, so it sat in the top third of a card stretched tall by the
   chart beside it. V2 switched to height and added `max-height:360px` as a safety rail. The switch
   was right and THE RAIL WAS THE BUG: the wrap grew past 700px, the ring stopped at 360, and
   `align-items:center` did exactly as told and parked a small ring in the middle of a lot of empty
   card. The measured gap in the director's screenshot was about 170px of dead space above the ring
   and about 150px below it.

   So: no height cap at all. `aspect-ratio:1` with `height:100%` makes the ring the smaller of the
   card's height and 52% of its width, which is the largest square that leaves the key its column.
   A rail that overrides the rule it was added to protect is not a safety rail, it is the rule.

   The pair is CENTRED as a group rather than pushed to the two edges: the key is capped instead of
   stretched, so a wide card gives the ring the middle of the card rather than the far left of it. */
.donutWrap{
  flex:1 1 auto; display:flex; align-items:center; justify-content:center;
  gap:40px; flex-wrap:nowrap; min-height:320px; padding:8px 0;
}
.donut{
  flex:0 1 auto; height:100%; width:auto; aspect-ratio:1;
  max-width:52%; min-height:240px; overflow:visible;
}
.donutBig{
  font-family:var(--sans); font-size:33px; font-weight:500;
  fill:var(--ink); letter-spacing:-.02em;
}
.donutCap{
  font:600 9px var(--sans); fill:var(--muted); letter-spacing:.12em; text-transform:uppercase;
}
.donutKey{
  /* CAPPED, not stretched. Left to flex-grow it pinned itself to the card's right edge and the
     ring to the left edge, which reads as two things in a card rather than one figure. */
  list-style:none; margin:0; padding:0; flex:0 1 440px; min-width:0;
  display:flex; flex-direction:column; justify-content:center;
}
.donutKey li{
  display:grid; grid-template-columns:12px 1fr auto auto; gap:12px; align-items:baseline;
  padding:11px 0; border-top:1px solid var(--line); font-size:14px;
}
.donutKey li:first-child{border-top:0}
.donutKey i{width:12px; height:12px; border-radius:3px; display:block; transform:translateY(1px)}
.donutKey .k{color:var(--ink-2); overflow-wrap:anywhere}
.donutKey .v{font-weight:600; color:var(--ink); font-size:14px}
.donutKey .c{font-size:12.5px}

/* A CONTAINER QUERY, NOT A MEDIA QUERY, and the difference was a live bug on 2026-08-31.
   This block used to read `@media(max-width:820px)`, which asks how wide the WINDOW is. The window
   was 2000px and the card holding this donut was 340px, so the side-by-side layout stayed on in a
   card that could not hold it: the ring shrank to a bullet and the legend wrapped one letter per
   line. The rule was correct and it was measuring the wrong box, which is this project's most
   expensive recurring defect wearing a stylesheet. */
@container (max-width:560px){
  .donutWrap{flex-wrap:wrap; gap:20px; min-height:0; justify-content:stretch}
  .donut{height:auto; width:100%; max-width:min(86%,340px); margin:0 auto; min-height:0}
  .donutKey{flex:1 1 100%}
  .donutKey li{grid-template-columns:12px 1fr auto auto; gap:10px}
}
/* ---------------------------------------------------------------- heatmap
   One hue, varying density. A rainbow ramp would make the reader learn a key before they could
   read the picture, and the picture is the point. */
.heatWrap{overflow-x:auto}
table.heat{border-collapse:separate; border-spacing:3px; width:auto; min-width:100%}
table.heat th,table.heat td{border:0; padding:0}
table.heat thead th{
  font:600 10px var(--mono); color:var(--muted);
  text-align:center; padding-bottom:4px; letter-spacing:0;
}
table.heat tbody th{
  font-weight:500; font-size:12.5px; text-align:left; padding-right:10px;
  white-space:nowrap; color:var(--ink);
}
table.heat tbody th a{text-decoration:none}
table.heat tbody th a:hover{text-decoration:underline}
.cell{
  display:block; width:100%; min-width:22px; height:18px; border-radius:3px;
  background:var(--accent);
}

/* ---------------------------------------------------------------- dot grid
   One cell per record. Cells are small on purpose: the SHAPE of the fill is the message, and a
   grid built from chunky squares reads as decoration rather than as a count. */
.dotgrid{display:flex; flex-direction:column; gap:14px}
.dots{display:grid; gap:3px}
.dot{
  display:block; aspect-ratio:1; border-radius:2px;
  background:var(--surface-2); border:1px solid var(--line);
}
.dot.on{background:var(--c-stop); border-color:var(--c-stop)}

/* ---------------------------------------------------------------- compare picker (SPEC-0263)
   A GRID OF TAP TARGETS, not a list. The first cut reused `.pairList`, which is one column built
   for 548 text links, so 60 compounds rendered as a 60-row column with a 12px native checkbox at
   the end of each line: correct, and unusable. The whole chip is the target, it is 44px tall,
   and `auto-fill` reflows it from one column on a phone to seven on a monitor with no query. */
.pickList{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(180px, 1fr)); gap:8px;
  margin:14px 0 0;
}
.pick{
  display:flex; align-items:center; gap:10px; min-height:44px;
  padding:8px 12px; border:1px solid var(--line); border-radius:8px;
  background:var(--surface-2); color:var(--ink-2);
  font-size:14px; line-height:1.3; cursor:pointer; user-select:none;
}
.pick:hover{color:var(--ink)}
.pick input{width:16px; height:16px; margin:0; flex:0 0 auto; accent-color:var(--accent); cursor:pointer}
/* SELECTED IS A FILL AND A WEIGHT, never a painted edge. The border stays the neutral `--line`
   token in both states: an edge carrying meaning is banned house-wide (director ruling
   2026-08-31), and the state is already said by the checkbox itself. */
.pick.on{background:var(--accent-soft); color:var(--ink); font-weight:600}
.pick:focus-within{outline:2px solid var(--accent); outline-offset:2px}
/* Wide content scrolls INSIDE its own box. A table that widens the page pushes every other card
   off screen, which is how one component's overflow becomes the whole layout's problem. */
.tableWrap{overflow-x:auto}

/* ---------------------------------------------------------------- process flow */
.flow{display:flex; flex-direction:column}
.flowStep{display:grid; grid-template-columns:34px 1fr; gap:16px}
.flowMark{display:flex; flex-direction:column; align-items:center; gap:6px}
.flowNum{
  width:30px; height:30px; border-radius:50%; display:grid; place-items:center; flex:0 0 auto;
  background:var(--accent-soft); color:var(--accent); font-weight:700; font-size:13px;
  font-family:var(--mono);
}
.flowLine{flex:1; width:2px; background:var(--line); min-height:14px}
.flowStep:last-of-type .flowLine{background:linear-gradient(var(--line),transparent)}
.flowBody{padding-bottom:20px; min-width:0}
.flowBody h3{font-size:17px; margin:4px 0 5px}
.flowBody p{margin:0; color:var(--ink-2); font-size:13.5px; line-height:1.55; max-width:70ch}
.flowFork{display:grid; grid-template-columns:1fr 1fr; gap:12px; margin-left:50px}
.flowOut{
  background:var(--surface-2); border:1px solid var(--line); border-radius:10px; padding:14px 16px;
}
.flowOut h3{font-size:16px; margin:0 0 5px}
.flowOut p{margin:0; font-size:13px; color:var(--ink-2); line-height:1.55}
@container (max-width:640px){
  .flowFork{grid-template-columns:1fr; margin-left:0}
}

/* ---------------------------------------------------------------- EU status
   No painted edge, in any of the three states. A refusal is announced by the WORDS "Refused by the
   European Commission", which every reader understands, rather than by a colour they have to
   decode. House rule, and it applies hardest exactly where the temptation is strongest. */
.euBox{display:flex; flex-direction:column; gap:8px}
.euLine{
  font-family:var(--sans); font-weight:500; font-size:22px; line-height:1.2;
  letter-spacing:-.02em; margin:0; color:var(--ink);
}
.euLine.muted{color:var(--muted); font-size:19px}

/* The roadmap board's exit gates and its state pills. State is the WORD, never a painted edge. */
.gate{margin:2px 0 0; padding-left:18px; display:flex; flex-direction:column; gap:7px;
      font-size:13.5px; color:var(--ink-2); line-height:1.5}
.gate li::marker{color:var(--muted); font-family:ui-monospace,Menlo,monospace; font-size:12px}
.pill-done{color:var(--good)}
.pill-in-progress{color:var(--accent)}
.pill-not-started{color:var(--muted)}
.pill-unknown{color:var(--warn)}
.pill-measured{color:var(--good)}
.pill-no-data-yet{color:var(--muted)}
.pill-unavailable{color:var(--warn)}
.pill-not-measurable-yet{color:var(--muted)}
.pill-failing{color:var(--bad)}

/* ---------------------------------------------------------------- coverage grid
   A labelled tile per jurisdiction. Not a choropleth: 30 covered jurisdictions carry one identical
   value, so a shaded map would be one colour over Europe and grey everywhere else. The information
   is WHICH jurisdictions, and a tile with a code on it states that in less space. */
.covGrid{
  display:grid; grid-template-columns:repeat(auto-fill, minmax(46px, 1fr)); gap:5px; margin:4px 0 2px;
}
.covCell{
  aspect-ratio:1; border-radius:5px; display:grid; place-items:center;
  font:600 11.5px/1 var(--mono); letter-spacing:.02em;
  border:1px solid var(--line); background:var(--surface-2); color:var(--muted);
}
.covCell a{color:inherit; text-decoration:none; display:grid; place-items:center; width:100%; height:100%}
.cov-on{background:var(--accent-soft); border-color:var(--accent); color:var(--accent)}
.cov-on a:hover{color:var(--ink)}
.cov-dec{border-color:var(--warn); color:var(--warn)}
.cov-off{opacity:.55}
.sw{width:11px; height:11px; border-radius:3px; display:inline-block; border:1px solid var(--line);
    background:var(--surface-2); vertical-align:-1px; margin-right:6px}
.sw-on{background:var(--accent-soft); border-color:var(--accent)}
.sw-dec{border-color:var(--warn)}
.sw-off{opacity:.55}

/* ---------------------------------------------------------------- the hero (SPEC-0260)
   The map opens the landing page. It is its own section, above the metrics and outside the single
   card grid, and it carries no heading of its own: the masthead is the h1 and a headline here
   would be the thesis block the front page deliberately does not have.

   No media query reaches inside a card, because this is not a card. */
.hero{margin:0 0 18px}
.heroMap{margin:0}
.heroNote{
  margin:6px 2px 0; font-size:13px; color:var(--ink-2); max-width:70ch;
}
.heroNote a{font-weight:600}

/* ---------------------------------------------------------------- world map (SPEC-0258)
   The map answers WHERE and the grid above answers WHICH. Both, not either: a reader scanning for
   a country name uses the grid, and a reader who does not know where Liechtenstein is uses this.

   THREE STATES, THREE CHANNELS, AND COLOUR IS THE LAST OF THEM. Covered is a solid fill, register
   declared is a hatch PATTERN, no register is empty. Every shape also carries a <title> naming its
   state in words. Roughly 8% of men are colour blind, and a map whose only channel is hue is a map
   they cannot read.

   NO COLOURED EDGE (director ruling 2026-08-31). Every stroke here is the neutral --line token in
   both themes. State is never carried by a painted border. */
/* THE LIGHTNESS RAMP, AND THE FIRST VERSION HAD IT INVERTED. The sea was --surface-2 and the land
   --surface, so the water was LIGHTER than the land, and worse, a catalogued country with no
   register was painted the exact colour of the sea. Brazil, India, Japan and Australia are all in
   the catalogue and all disappeared into the ocean. Four steps now, darkest first:

     sea            --bg
     land, not catalogued   --surface-2
     catalogued, no register  --line
     covered        --accent

   BORDERS ARE DRAWN IN THE SEA COLOUR. On a dark map that is what makes a coastline read: the
   landmass is a shape with clean separations rather than a blur with grey seams. */
.worldMap{
  display:block; width:100%; height:auto; margin:2px 0 6px;
  background:var(--bg); border:1px solid var(--line); border-radius:8px;
}
/* Strokes are non-scaling: a coastline hairline stays a hairline whatever the canvas is, so the
   geometry could go from a 1000 unit box to 2000 without every stroke halving on screen. */
.jmBg{fill:var(--surface-2); stroke:var(--bg); stroke-width:1; vector-effect:non-scaling-stroke}
.jmLand{stroke:var(--bg); stroke-width:1; vector-effect:non-scaling-stroke}
.jmDot{stroke:var(--bg); stroke-width:1; vector-effect:non-scaling-stroke}
/* .jmBloc is GONE, not commented out and not kept "in case". Amendment B, 2026-09-03: the EU bloc
   is drawn nowhere, so nothing emits the class, and a rule that paints a class no shape carries is
   how a future session concludes the shape still exists. */
/* The hatch needs its own backdrop or the gaps are TRANSPARENT and a declared jurisdiction shows
   the sea through itself, which reads as water rather than as a state. */
.jmHatchBg{fill:var(--line)}
.jmHatchLine{stroke:var(--accent); stroke-width:1.5; vector-effect:non-scaling-stroke}
.jmStippleBg{fill:var(--accent); fill-opacity:.55}
.jmStippleDot{fill:var(--bg); fill-opacity:.5}
/* COVERED IS A LIGHTNESS STEP, NOT A HUE STEP, and the first cut got this wrong. It filled covered
   with --accent-soft, which sits at almost the same lightness as --surface-2, so on a rendered
   screenshot the two states separated by hue alone. The legend and the titles still carried the
   words, so the eval was green and the map was still hard to read. --accent at partial opacity is
   plainly lighter than the uncovered fill in dark and plainly darker in light. */
.jmOn{fill:var(--accent); fill-opacity:.55}
/* Covered THROUGH a bloc authorisation rather than by its own national register. Same lightness as
   covered, because it is covered; a stipple over it, because it was reached differently. */
.jmVia{fill:url(#jmStipple)}
.jmDec{fill:url(#jmHatch)}
.jmOff{fill:var(--line)}
/* SPEC-0275, the density channel. Five steps of ONE hue, carried entirely by fill-opacity on the
   accent already used for covered, so no new colour is authored and nothing here is a second hue
   competing with the coverage treatment. Declared and untracked have no jmD class at all and are
   never on this scale: a country nobody has looked at must not read as a country where nothing is
   authorised. Ordered after .jmOn and .jmVia so the band wins the opacity; the fill, including the
   bloc stipple, is untouched. */
.jmD0{fill-opacity:.16}
.jmD1{fill-opacity:.32}
.jmD2{fill-opacity:.50}
.jmD3{fill-opacity:.70}
.jmD4{fill-opacity:.92}
.jmLink{cursor:pointer}
.jmLink:hover .jmLand,.jmLink:hover .jmDot{fill:var(--accent)}
.jmLink:focus-visible{outline:2px solid var(--accent); outline-offset:1px}
/* The legend is words first. The swatch repeats the map's treatment and carries no meaning alone. */
.jmLegend{display:flex; flex-wrap:wrap; gap:6px 16px; font-size:12.5px; color:var(--ink-2); margin:0}
.jmLegend span{display:inline-flex; align-items:center; gap:6px}
.jmKey{width:12px; height:12px; border-radius:3px; display:block; border:1px solid var(--line)}
.jmKeyOn{background:var(--accent); opacity:.6}
.jmKeyVia{background:var(--accent); opacity:.6;
  background-image:radial-gradient(var(--bg) 1.2px, transparent 1.3px); background-size:4px 4px}
.jmKeyDec{background:repeating-linear-gradient(45deg,transparent,transparent 2px,var(--accent) 2px,var(--accent) 3px)}
.jmKeyOff{background:var(--line)}
/* Density swatches: the same five steps, so the key is the map's own scale rather than a redrawing
   of it. The range in numerals sits beside each one; the swatch alone carries no meaning. */
.jmKeyD0{background:var(--accent); opacity:.16}
.jmKeyD1{background:var(--accent); opacity:.32}
.jmKeyD2{background:var(--accent); opacity:.50}
.jmKeyD3{background:var(--accent); opacity:.70}
.jmKeyD4{background:var(--accent); opacity:.92}

/* COVERED JURISDICTIONS, GROUPED BY REGION. Director ruling 2026-09-03: one panel of lists, not 39
   cards. Thirty of the rows carry identical numbers because they share one EU authorisation, so a
   card each repeated 29 and 31 thirty times and pushed the countries that differ off the screen.
   Rows are separated by a hairline in the neutral line token: that is STRUCTURE, not a painted
   edge, and it carries no meaning of its own. */
/* A BOARD, COLUMNS BY REGION. Replaces one table per region, which sized its columns independently
   and made the numbers step left and right down the page, and replaces the flags, which on Windows
   render as two letter blocks beside the country code they duplicate. Nothing here shares a column
   measurement across regions, so there is no alignment left to get wrong. */
.covBoard{display:grid; grid-template-columns:repeat(auto-fit,minmax(230px,1fr)); gap:18px;
  margin-top:14px; align-items:start}
.covCol{min-width:0}
.covColHead{margin:0 0 8px; padding-bottom:6px; border-bottom:1px solid var(--line);
  font-size:11.5px; letter-spacing:.09em; text-transform:uppercase; color:var(--ink-2)}
.covColHead .num{font-weight:600}
.covItems{list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:2px}
/* Each country is one row of its own column: a fixed-width code chip, the name, then the count.
   The chip is fixed width so the names line up inside a column without a table. */
.covItem{display:grid; grid-template-columns:2.6em minmax(0,1fr) auto; align-items:baseline;
  column-gap:8px; padding:4px 0; font-size:13.5px}
.covChip{font-size:10.5px; letter-spacing:.07em; color:var(--ink-2); font-variant-numeric:tabular-nums}
.covLink{min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.covCount{font-variant-numeric:tabular-nums; white-space:nowrap}
.covCount b{font-weight:600}
.covOf{color:var(--ink-2); font-size:11.5px}
/* The source sits on its own line under the name, indented past the chip, so it never competes
   with the count for horizontal room in a narrow column. */
.covMeta{grid-column:2 / -1; color:var(--ink-2); font-size:11px; letter-spacing:.02em;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap}

/* SPEC-0283, the regulatory-action rows. A quotation is set apart by indentation and a lighter
   weight, never by a coloured edge: a painted stripe is banned house-wide and a quote does not need
   one to read as a quote. */
.actWhere{display:block; font-variant-numeric:tabular-nums; letter-spacing:.04em}
.actClass{display:block; margin-top:2px; font-size:11px; letter-spacing:.08em;
  text-transform:uppercase; color:var(--ink-2)}
.actQuote{margin:6px 0 4px; padding-left:12px; border-left:1px solid var(--line);
  color:var(--ink-2); font-size:13.5px; white-space:pre-line}

/* SPEC-0344 capture form. Beside a status block, never a footer strip. Neutral edges only. */
.alertSignup form{display:flex; flex-direction:column; gap:10px; margin-top:4px}
.alertSignup label{display:flex; flex-direction:column; gap:4px; font-size:12.5px; color:var(--ink-2)}
.alertSignup input, .alertSignup select{
  border:1px solid var(--line); border-radius:7px; padding:8px 10px; font:inherit; font-size:14px;
  background:var(--surface-2); color:var(--ink); width:100%;
}
.alertSignup button[type=submit]{
  align-self:flex-start; margin-top:4px; padding:8px 14px;
  background:var(--accent); color:var(--bg); border-color:var(--accent);
}
.alertSignup button[type=submit]:disabled{opacity:.6}
.alertSignupDone{margin:8px 0 0; font-size:14px; color:var(--ink)}
.alertSignupErr{margin:0; font-size:13px; color:var(--ink)}

/* Pair list on /compare. Dense, one line each, no decoration. */
.pairList{display:flex; flex-direction:column; gap:1px; margin-top:2px}
.pairLink{
  display:block; padding:7px 9px; border-radius:6px; font-size:13.5px;
  color:var(--ink-2); text-decoration:none;
}
.pairLink:hover{background:var(--surface-2); color:var(--ink)}

/* GPI Task B: the weekly signup at the foot of every page. One field and a button on one line. */
.weeklySignup{margin-top:12px}
.weeklyForm{flex-direction:row !important; align-items:flex-end; flex-wrap:wrap}
.weeklyForm label{flex:1 1 240px; max-width:360px}
.weeklyForm button[type=submit]{align-self:flex-end}


/* ================================================================ M1.17 steps 2 and 3
   Home, peptide hub and the interactive world map, on the Main, Peptide and WorldMap boards
   (SPEC-PENDING 2026-10-03, home-hub-and-world-map). Bible 08: one series is the accent, status is
   the pill colours with the word, "other" is line-2, not read is a dashed outline, bars start at
   zero with their values printed, and every figure carries its source and read date underneath. */

.visuallyHidden{position:absolute; width:1px; height:1px; overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap}
.ic{width:18px; height:18px; flex:none; stroke:currentColor; fill:none; stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round}
.btn{display:inline-flex; align-items:center; justify-content:center; gap:8px; min-height:44px; padding:0 18px;
  border-radius:10px; font:600 15px var(--sans); border:1px solid transparent; cursor:pointer; text-decoration:none}
.btn:hover{text-decoration:none}
.btn-pri,.btn-pri:hover{background:var(--ink); color:var(--surface)}
.btn-sec,.btn-sec:hover{background:var(--surface); color:var(--ink); border-color:var(--line-2)}
.btn-light,.btn-light:hover{background:var(--surface); color:var(--ink)}
.pill i{width:6px; height:6px; border-radius:50%; background:currentColor; display:block; flex:none}
.pillRow{display:flex; flex-wrap:wrap; gap:6px}
.viz-src{font-size:12px; color:var(--muted); margin:0; line-height:1.5}
.cardHead{display:flex; justify-content:space-between; align-items:baseline; gap:12px; flex-wrap:wrap}
.cardHead h2{font-size:18px}
.secHead{display:flex; justify-content:space-between; align-items:baseline; gap:16px; flex-wrap:wrap}
.secHead h2{font-size:24px}
.statInline{font:500 22px var(--mono); font-variant-numeric:tabular-nums}

/* ---- the home hero: a white band across the page, text left and four tiles right */
.homeHero{
  margin:-40px -40px 0; padding:64px 40px 48px; background:var(--surface); border-bottom:1px solid var(--line);
  display:grid; grid-template-columns:repeat(auto-fit,minmax(min(520px,100%),1fr)); gap:40px; align-items:end;
}
.homeHeroText{display:flex; flex-direction:column; gap:18px; min-width:0}
.homeHeroText .eyebrow{margin:0}
.homeHero h1{font-size:clamp(34px,4.2vw,56px); line-height:1.04}
.searchRow{display:flex; gap:8px; flex-wrap:wrap; margin-top:6px}
.searchBox{flex:1 1 240px; display:flex; align-items:center; gap:10px; height:52px; padding:0 16px;
  border:1px solid var(--line-2); border-radius:12px; background:var(--surface); color:var(--muted)}
.searchBox input{border:0; outline:0; flex:1; min-width:0; font:inherit; font-size:16px; color:var(--ink); background:transparent}
.searchBox:focus-within{outline:2px solid var(--accent); outline-offset:2px}
.searchRow .btn{min-height:52px}
.chips{display:flex; flex-wrap:wrap; gap:8px; align-items:center}
.chips .eyebrow{margin:0 4px 0 0}
.chips .pill{text-decoration:none}
.chips .pill:hover{background:var(--line); text-decoration:none}

.statGrid{display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:12px}
.statRow{display:grid; grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr)); gap:12px}
.statTile{background:var(--surface); border:1px solid var(--line); border-radius:12px; padding:20px;
  display:flex; flex-direction:column; gap:6px; color:var(--ink); text-decoration:none; min-width:0}
a.statTile:hover{border-color:var(--accent); text-decoration:none; color:var(--ink)}
.statTile .eyebrow{margin:0}
.statVal{font:500 36px/1.05 var(--mono); letter-spacing:-.02em; font-variant-numeric:tabular-nums}
.statSrc{font-size:13px; color:var(--muted); line-height:1.4}

/* ---- peptide cards */
.pcardsWrap{display:flex; flex-direction:column; gap:16px; margin-top:22px}
.pcards{display:grid; grid-template-columns:repeat(auto-fill,minmax(min(280px,100%),1fr)); gap:14px}
.pcard{background:var(--surface); border:1px solid var(--line); border-radius:12px; padding:20px;
  display:flex; flex-direction:column; gap:12px; color:var(--ink); text-decoration:none}
.pcard:hover{border-color:var(--accent); color:var(--ink); text-decoration:none}
.pcardName{font-size:18px; font-weight:600}
.pcardClass{font-size:13px; color:var(--muted); margin-top:-8px}
.pcardFoot{display:flex; gap:20px; border-top:1px solid var(--line); padding-top:12px; font-size:13px; color:var(--muted); margin-top:auto}
.pcardFoot b{font:500 13px var(--mono); color:var(--ink)}

/* ---- horizontal bars (.hb): name, track from zero, value printed */
.hbList{display:flex; flex-direction:column; gap:10px}
.hb{display:grid; grid-template-columns:minmax(90px,140px) 1fr 64px; gap:12px; align-items:center; font-size:14px; color:var(--ink); text-decoration:none}
a.hb:hover{color:var(--accent); text-decoration:none}
.hbName{overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.hb .t{height:14px; border-radius:4px; background:var(--surface-2); display:block; overflow:hidden}
.hb .t span{height:14px; border-radius:4px; background:var(--accent); display:block; min-width:2px}
.hbVal{font:500 13px var(--mono); text-align:right; font-variant-numeric:tabular-nums}

/* ---- the trial-status stack. Status colours are the pill colours; "other" is line-2. */
.stk{display:flex; height:28px; border-radius:6px; overflow:hidden; gap:2px}
.stkTall{height:36px}
.stk span{display:block; height:100%; min-width:2px}
.s-running{background:var(--c-live)}
.s-completed{background:var(--c-done)}
.s-stopped{background:var(--c-stop)}
.s-unknown{background:repeating-linear-gradient(45deg,var(--dash) 0 3px,var(--surface) 3px 6px)}
.s-other{background:var(--line-2)}
.key{display:flex; flex-wrap:wrap; gap:8px 16px; font-size:12.5px; color:var(--ink-2); align-items:center}
.key > span{display:inline-flex; gap:6px; align-items:center}
.key b{font:500 12.5px var(--mono); color:var(--ink)}
.key i{width:12px; height:12px; border-radius:3px; display:block; flex:none}

/* ---- the coverage waffle: one square per jurisdiction, read filled, not read dashed */
.waf{display:grid; grid-template-columns:repeat(18,minmax(0,1fr)); gap:4px}
.waf i{aspect-ratio:1/1; border-radius:3px; display:block}
.waf .on,.key .wOn{background:var(--accent)}
.waf .off{border:1px dashed var(--dash); background:var(--surface)}
.key .wOff{border:1px dashed var(--dash); background:var(--surface)}

/* ---- a figure that is not held: its frame, and the pull that fills it */
.phchart{border:1px dashed var(--dash); border-radius:10px; min-height:150px; display:flex; flex-direction:column;
  align-items:center; justify-content:center; gap:8px; padding:16px; text-align:center;
  background:repeating-linear-gradient(0deg,var(--surface) 0 29px,var(--surface-2) 29px 30px)}
.ph{color:var(--muted); font:12px var(--mono); border:1px dashed var(--dash); border-radius:6px; padding:3px 6px}

/* ---- official actions list */
.evList{list-style:none; margin:0; padding:0; display:flex; flex-direction:column}
.evList li{display:grid; grid-template-columns:96px 1fr; gap:12px; padding:10px 0; border-top:1px solid var(--line); font-size:14px}
.evList li:first-child{border-top:0}

/* ---- "Is it legal?": the one dark card on the home page (Main board) */
.panel:has(> .legalPick){background:var(--ink); border-color:var(--ink); color:var(--surface)}
.panel:has(> .legalPick) .eyebrow{color:#9FB2BD}
.panel:has(> .legalPick) h2{color:var(--surface)}
.legalPick{display:flex; flex-direction:column; gap:12px}
.legalPick label{display:flex; flex-direction:column; gap:6px; font-size:13px; color:#C9D5DC}
.legalPick select{height:44px; border-radius:10px; border:1px solid var(--ink-2); background:#13252F; color:var(--surface); padding:0 12px; font:inherit}
.legalAnswer{display:flex; flex-direction:column; align-items:flex-start; gap:6px; padding:12px; border-radius:10px; background:#13252F}
.legalMeta{font-size:12.5px; color:#C9D5DC}

/* ---- the hub */
.hubHead{display:flex; flex-direction:column; gap:12px}
.hubHead .eyebrow{margin:0}
.hubHead h1{font-size:clamp(36px,4.4vw,56px); line-height:1}
.answer{display:flex; flex-direction:column; gap:10px; padding:24px 28px}
.answer .eyebrow{margin:0; color:var(--accent-ink)}
.answerLead{margin:0; font-size:20px; line-height:1.5; font-weight:500; color:var(--ink); max-width:920px}
.answerSrc{margin:0; display:flex; flex-wrap:wrap; gap:8px; align-items:center; font-size:13px; color:var(--ink-2)}
.answer .muted{margin:0; font-size:12.5px}
.duo{display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:14px; align-items:start}
.duoWide{grid-template-columns:minmax(0,3fr) minmax(0,2fr)}
.sideStack{display:flex; flex-direction:column; gap:14px; min-width:0}
.teaser{color:var(--ink); text-decoration:none}
.teaser:hover{border-color:var(--accent); color:var(--ink); text-decoration:none}
.teaserMore{font-weight:500; color:var(--accent)}

/* vertical bars from zero, value printed on top; the incomplete year is hatched */
.vbars{display:grid; grid-auto-flow:column; grid-auto-columns:minmax(0,72px); justify-content:start; gap:8px; align-items:end; height:180px}
.vbar{display:flex; flex-direction:column; align-items:stretch; gap:4px; height:100%}
.vbarVal{font:500 11px var(--mono); text-align:center}
.vbarCol{flex:1; display:flex; align-items:flex-end}
.vbarCol span{display:block; width:100%; background:var(--accent); border-radius:3px 3px 0 0; min-height:2px}
.vbar.part .vbarCol span{background:repeating-linear-gradient(45deg,var(--accent) 0 3px,var(--accent-soft) 3px 6px)}
.vbarLab{font:500 10.5px var(--mono); color:var(--muted); text-align:center}

/* the equal tile map, one tile per register (bible 08, "in tight spaces") */
.tm{display:grid; grid-template-columns:repeat(13,minmax(0,1fr)); gap:5px}
.tm b{aspect-ratio:1/1; border-radius:7px; display:flex; align-items:center; justify-content:center;
  font:500 11px var(--mono); position:relative}
.t-ok{background:#E1F3EA; color:#0E5F39; border:1px solid #9FD3B8}
.t-no{background:#EEF1F3; color:var(--ink-2); border:1px solid var(--line-2)}
.t-unk{background:var(--surface); color:var(--muted); border:1px dashed var(--dash)}
.stTable{border-collapse:collapse; width:100%; font-size:14px}
.stTable th{text-align:left; padding:10px 12px 10px 0; border-bottom:1px solid var(--line);
  font:500 11px var(--mono); letter-spacing:.08em; text-transform:uppercase; color:var(--muted)}
.stTable td{padding:12px 12px 12px 0; border-bottom:1px solid var(--line); vertical-align:middle}
.stTable tr:last-child td{border-bottom:0}

/* ---- the interactive world map (WorldMap board). Fills are read from data-s, one rule set. */
.pmSection{display:flex; flex-direction:column; gap:14px}
.pmSection > h2{font-size:clamp(26px,3vw,40px); line-height:1.1}
.pm{display:flex; flex-direction:column; gap:14px}
.pmPick{display:flex; flex-wrap:wrap; gap:8px; align-items:center}
.pk{display:inline-flex; align-items:center; min-height:44px; padding:0 16px; border-radius:999px; font:500 15px var(--sans);
  border:1px solid var(--line-2); background:var(--surface); color:var(--ink); cursor:pointer}
.pk-on{background:var(--ink); color:var(--surface); border-color:var(--ink)}
.pmSelect select{min-height:44px; border-radius:999px; border:1px solid var(--line-2); background:var(--surface); padding:0 14px; font:inherit; color:var(--ink)}
.pmBody{display:grid; grid-template-columns:minmax(0,3fr) minmax(260px,1fr); gap:14px; align-items:start}
.pmMapCard,.pmSide{background:var(--surface); border:1px solid var(--line); border-radius:12px; padding:22px; display:flex; flex-direction:column; gap:14px; min-width:0}
.pmHead{display:flex; justify-content:space-between; align-items:baseline; gap:12px; flex-wrap:wrap}
.pmSummary{font-size:17px; font-weight:600}
.pmCanvas svg{display:block; width:100%; height:auto}
.pmBg{fill:var(--surface-2); stroke:var(--surface); stroke-width:.6; vector-effect:non-scaling-stroke}
.pm [data-code]{stroke:var(--surface); stroke-width:.8; vector-effect:non-scaling-stroke; cursor:pointer; stroke-linejoin:round}
.pm [data-code]:hover{opacity:.82}
.pm [data-code]:focus{outline:none}
.pm [data-code]:focus-visible,.pm [data-code][aria-pressed="true"]{stroke:var(--ink); stroke-width:2}
.pm [data-s="p-ok"]{fill:var(--m-ok)}
.pm [data-s="p-no"]{fill:var(--m-no)}
.pm [data-s="p-unk"]{fill:var(--m-unk); stroke:var(--dash); stroke-dasharray:3 2}
.pm .key .kOk{background:var(--m-ok)}
.pm .key .kNo{background:var(--m-no)}
.pm .key .kUnk{background:var(--m-unk); border:1px dashed var(--dash)}
.pmSide h3{font-size:26px; margin:0}
.pmSide .eyebrow{margin:0}
.pmSide .pill{align-self:flex-start}
.pmNote{margin:0; font-size:14.5px; line-height:1.5; color:var(--ink-2)}
.pmFacts{margin:0; display:grid; grid-template-columns:auto 1fr; gap:6px 14px; border-top:1px solid var(--line); padding-top:12px; font-size:14px}
.pmFacts dt{font:500 11px var(--mono); letter-spacing:.08em; text-transform:uppercase; color:var(--muted); padding-top:2px}
.pmFacts dd{margin:0; overflow-wrap:anywhere}

@media(max-width:1000px){
  .homeHero{margin:-24px -16px 0; padding:36px 16px 32px; gap:24px}
  .duo,.duoWide,.pmBody{grid-template-columns:1fr}
}
@media(max-width:560px){
  .statGrid,.statRow{grid-template-columns:1fr 1fr}
  .statTile{padding:14px}
  .answer{padding:18px}
  .answerLead{font-size:17px}
  .pmMapCard,.pmSide{padding:14px}
  .pk{min-height:40px; padding:0 12px; font-size:14px}
  .statVal{font-size:28px}
  .hb{grid-template-columns:minmax(80px,110px) 1fr 52px; gap:8px}
  .tm{gap:3px}
  .tm b{font-size:9px; border-radius:4px}
  .waf{grid-template-columns:repeat(12,minmax(0,1fr))}
  .evList li{grid-template-columns:1fr; gap:2px}
  .vbars{gap:4px}
  .vbarVal{font-size:9.5px}
  .vbarLab{font-size:9px; writing-mode:vertical-rl; transform:rotate(180deg); justify-self:center}
}

/* ---- paired bars (.pair): a side effect, the peptide rate and the placebo rate from the same trials */
.pairList{display:flex; flex-direction:column; gap:12px; margin-top:14px}
.pair{display:grid; grid-template-columns:minmax(120px,220px) 1fr; gap:14px; align-items:center; font-size:14px}
.pairName{color:var(--ink); overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.pairBars{display:flex; flex-direction:column; gap:2px}
.pairBar{display:flex; align-items:center; gap:8px; min-width:0}
.pairBar b{font:500 12.5px var(--mono); color:var(--ink-2); font-variant-numeric:tabular-nums; white-space:nowrap}
.pb{height:10px; border-radius:0 4px 4px 0; display:block; flex:none; max-width:calc(100% - 56px)}
.pb-a{background:var(--accent)}
.pb-p{background:var(--dash)}
@media (max-width:640px){ .pair{grid-template-columns:1fr; gap:4px} }
.hbTwo .hb{grid-template-columns:minmax(90px,140px) 1fr 108px}
@media (max-width:640px){ .hbTwo .hb{grid-template-columns:minmax(80px,110px) 1fr 96px} }

/* ---- peptide tabs (.ptabs): one URL per tab, the current one underlined in the accent */
.ptabs{display:flex; gap:4px; border-bottom:1px solid var(--line); margin:4px 0 20px; overflow-x:auto; scrollbar-width:none}
.ptabs::-webkit-scrollbar{display:none}
.ptabs a{padding:10px 14px; font-size:14px; color:var(--ink-2); text-decoration:none; white-space:nowrap; border-bottom:2px solid transparent; margin-bottom:-1px}
.ptabs a:hover{color:var(--ink)}
.ptabs a.on{color:var(--ink); border-bottom-color:var(--accent); font-weight:500}
.ptabN{font:500 11.5px var(--mono); color:var(--muted); margin-left:6px}

.labelBlock{padding:12px 0; border-top:1px solid var(--line)}
.labelBlock:first-of-type{border-top:0}
.labelBlock p{margin:4px 0}
.faqItem{padding:12px 0; border-top:1px solid var(--line)}
.faqItem h3{font-size:16px; margin:0 0 4px}
.faqItem p{margin:0; color:var(--ink-2)}

/* ---------------------------------------------------------------- APP LAYER (design system v1, 2026-10-04)
   Not on the public site yet. Shared by the admin app and the client (company) app, drawn on the
   same tokens as the site so a claimed page, the client portal and the admin read as one product.
   MCI design logic carried over: a value always names its layer (register, independent, company
   says); paid data is shown locked, never faked; one claim call to action at the end of a page. */
.appShell{display:flex; flex-wrap:wrap; min-height:100vh; background:var(--bg)}
.appSide{flex:1 1 220px; max-width:260px; background:var(--surface); border-right:1px solid var(--line); padding:16px 12px; display:flex; flex-direction:column; gap:16px}
.appNav{display:flex; flex-direction:column; gap:2px}
.appNav a{display:flex; align-items:center; gap:10px; min-height:40px; padding:0 12px; border-radius:8px; color:var(--ink-2); font-size:14px; font-weight:500; text-decoration:none}
.appNav a:hover{background:var(--surface-2); color:var(--ink); text-decoration:none}
.appNav a.on{background:var(--accent-soft); color:var(--accent-ink); font-weight:600}
.appNav .n{margin-left:auto; font:500 11.5px var(--mono); color:var(--muted)}
.appMain{flex:999 1 560px; min-width:0; padding:28px 32px 64px; display:flex; flex-direction:column; gap:20px}
.appBar{display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:12px}
.appBar h1{font-size:28px; line-height:1.15}
/* KeyValue: a fact, its value, and the layer it comes from. */
.kv{display:grid; grid-template-columns:minmax(120px,180px) 1fr auto; gap:10px 16px; align-items:baseline; padding:10px 0; border-top:1px solid var(--line); font-size:14px}
.kv:first-child{border-top:0}
.kv dt{color:var(--muted); font-size:13px}
.kv dd{margin:0; color:var(--ink)}
/* Locked: Pro and Business data a visitor does not have. Placeholder text blurred, never real figures. */
.locked{position:relative; background:var(--surface); border:1px solid var(--line); border-radius:12px; padding:20px; overflow:hidden}
.locked .blur{filter:blur(5px); user-select:none; pointer-events:none; color:var(--ink-2)}
.locked .lockNote{position:absolute; inset:0; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:10px; background:rgba(255,255,255,.72); text-align:center; padding:16px}
.locked .lockNote p{margin:0; font-size:14px; color:var(--ink); max-width:36ch}
/* Claim: one call to action at the end of a company page, never at the top. */
.claimCta{background:var(--accent-soft); border-radius:12px; padding:22px 24px; display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:16px}
.claimCta h2{font-size:20px; color:var(--accent-ink)}
.claimCta p{margin:4px 0 0; color:var(--accent-ink); font-size:14px; max-width:60ch}
/* Alert row: one register change, its date and the peptide it is about. */
.alertRow{display:grid; grid-template-columns:110px 1fr auto; gap:12px; align-items:start; padding:12px 0; border-top:1px solid var(--line)}
.alertRow:first-child{border-top:0}
.alertRow time{font:500 12.5px var(--mono); color:var(--muted)}
.alertRow b{font-weight:600}
.alertRow p{margin:2px 0 0; font-size:13.5px; color:var(--ink-2)}
/* Plan card: a tier, its price and what it adds. The current plan is a fill, never an edge. */
.plans{display:grid; grid-template-columns:repeat(auto-fit,minmax(min(220px,100%),1fr)); gap:14px}
.plan{background:var(--surface); border:1px solid var(--line); border-radius:12px; padding:20px; display:flex; flex-direction:column; gap:10px}
.plan.on{background:var(--accent-soft)}
.plan .price{font:500 28px/1 var(--mono); letter-spacing:-.02em}
.plan ul{margin:0; padding-left:18px; font-size:13.5px; color:var(--ink-2); display:flex; flex-direction:column; gap:4px}
/* Review queue state, a word in a pill: Waiting, Approved, Refused (with the rule it broke). */
.p-wait{background:#FFF0DB; color:#874600}
.field{display:flex; flex-direction:column; gap:6px; font-size:13px; color:var(--ink-2)}
.field input,.field select,.field textarea{min-height:44px; border:1px solid var(--line-2); border-radius:8px; padding:8px 12px; font:inherit; font-size:15px; color:var(--ink); background:var(--surface)}
.field textarea{min-height:96px}
