/* ExactAmino - product page + flagship modules */

.pdp { padding-block:32px clamp(48px,6vw,88px); }
.pdp-top { display:grid; grid-template-columns:1fr 1fr; gap:44px; align-items:start; }
@media (max-width:900px){ .pdp-top{ grid-template-columns:1fr; gap:28px; } }

/* gallery */
.gallery { position:sticky; top:calc(var(--nav-h) + 20px); }
@media (max-width:900px){ .gallery{ position:static; } }
.gallery__stage { aspect-ratio:1/1; border-radius:var(--r-xl); background:radial-gradient(ellipse at 50% 30%,var(--n-100),var(--n-50)); box-shadow:var(--sh-border),var(--sh-1); display:flex; align-items:center; justify-content:center; padding:36px; position:relative; overflow:hidden; }
.gallery__stage .vial-svg { height:88%; animation:floaty 6s ease-in-out infinite; filter:drop-shadow(0 24px 40px rgba(21,42,107,.28)); }
.gallery__stage .vial-img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; border-radius:inherit; }
@keyframes floaty { 50% { transform:translateY(-10px); } }
@media (prefers-reduced-motion:reduce){ .gallery__stage .vial-svg{ animation:none; } }
.gallery__glow { position:absolute; inset:0; background:radial-gradient(circle at 50% 40%,var(--accent-glow),transparent 55%); opacity:.5; }
.gallery__tabs { display:flex; gap:8px; margin-top:14px; }
.gtab { flex:1; padding:9px; border-radius:var(--r-md); border:1px solid var(--line); background:var(--surface); font-family:var(--font-mono); font-size:11px; text-transform:uppercase; letter-spacing:.06em; color:var(--ink-2); transition:background var(--dur),color var(--dur),border-color var(--dur),box-shadow var(--dur); }
.gtab.on { background:var(--ink); color:var(--surface); border-color:var(--ink); }
.gpane { display:none; margin-top:14px; }
.gpane.on { display:block; }
.gpane--data { padding:20px; border-radius:var(--r-lg); background:var(--surface-2); box-shadow:var(--sh-border); }

/* buy box - compact / optimized */
.buybox h1 { font-size:var(--step-3); }
.buybox__sub { font-family:var(--font-mono); text-transform:uppercase; letter-spacing:.08em; color:var(--ink-3); font-size:var(--step--2); margin-top:4px; }
.buybox__tagline { color:var(--ink-2); font-size:var(--step-0); margin-top:8px; line-height:1.45; max-width:54ch; }
.trust-chips { display:flex; gap:6px; flex-wrap:wrap; margin-top:12px; }
.buybox__price { display:flex; align-items:baseline; gap:10px; margin-top:14px; }
.buybox__price .now { font-size:var(--step-2); font-weight:700; letter-spacing:-.03em; }
.buybox__price .per { font-family:var(--font-mono); font-size:var(--step--2); color:var(--ink-3); }
.bogo-line { margin-top:5px; font-size:var(--step--1); color:var(--ok); font-weight:600; display:inline-flex; align-items:center; gap:7px; }
.bogo-line svg { width:15px; height:15px; }
.wholesale-line { color:var(--accent-ink); }

.variants { display:grid; grid-template-columns:repeat(auto-fit,minmax(130px,1fr)); gap:8px; margin-top:14px; }
.variant { position:relative; padding:8px 11px; border-radius:var(--r-md); border:1.5px solid var(--line); background:var(--surface); text-align:left; transition:border-color var(--dur),box-shadow var(--dur); cursor:pointer; }
.variant__head { display:flex; align-items:baseline; justify-content:space-between; gap:8px; }
.variant__sub { display:flex; align-items:center; justify-content:space-between; gap:6px; margin-top:2px; }
.variant:hover { border-color:var(--ink-3); }
.variant.on { border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-glow); }
.variant__size { font-weight:700; font-size:var(--step-0); letter-spacing:-.01em; }
.variant__price { font-family:var(--font-mono); font-weight:600; font-size:var(--step--1); color:var(--ink); }
.variant__unit { font-family:var(--font-mono); font-size:10px; color:var(--ink-3); }
.variant__save { font-family:var(--font-mono); font-size:9.5px; font-weight:600; color:var(--ok); background:var(--ok-tint); padding:1px 5px; border-radius:var(--r-sm); letter-spacing:.02em; }
.variant.on .variant__price { color:var(--accent-ink); }
.variant__best { position:absolute; top:-8px; left:9px; font-family:var(--font-mono); font-size:8.5px; text-transform:uppercase; letter-spacing:.06em; background:var(--accent); color:#fff; padding:2px 7px; border-radius:var(--r-pill); box-shadow:0 2px 6px var(--accent-glow); }

.buy-row { display:flex; gap:10px; margin-top:14px; align-items:stretch; }
.qty-stepper { display:inline-flex; align-items:center; border:1px solid var(--line-strong); border-radius:var(--r-md); }
.qty-stepper button { width:38px; height:44px; display:flex; align-items:center; justify-content:center; color:var(--ink-2); }
.qty-stepper button svg { width:17px; height:17px; }
.qty-stepper span { min-width:38px; text-align:center; font-weight:700; font-variant-numeric:tabular-nums; }
.buy-row .btn { min-height:44px; }

/* compact single-row trust strip (merges the old pass-row + trust-row) */
.pass-row { display:flex; gap:8px; margin-top:14px; }
.pass-cell { flex:1; padding:9px 11px; border-radius:var(--r-md); background:var(--surface-2); box-shadow:var(--sh-border); }
.pass-cell__v { display:flex; align-items:center; gap:7px; font-weight:650; font-size:var(--step--1); }
.pass-cell__v svg { width:16px; height:16px; color:var(--ok); }
.pass-cell__l { font-family:var(--font-mono); font-size:10px; color:var(--ink-3); text-transform:uppercase; letter-spacing:.05em; margin-top:2px; }

.trust-row { display:flex; gap:16px; flex-wrap:wrap; margin-top:14px; padding-top:13px; border-top:1px solid var(--line); }
.trust-row div { display:flex; align-items:center; gap:7px; font-size:var(--step--2); color:var(--ink-2); }
.trust-row svg { width:16px; height:16px; color:var(--accent-ink); }

/* sticky mini buy-bar */
.mini-buybar { position:fixed; left:0; right:0; bottom:0; z-index:70; background:rgba(255,255,255,.94); backdrop-filter:blur(12px); border-top:1px solid var(--line); box-shadow:0 -4px 20px rgba(15,18,24,.06); transform:translateY(110%); transition:transform var(--dur-mod) var(--ease-std); }
.mini-buybar.show { transform:none; }
.mini-buybar__in { display:flex; align-items:center; gap:16px; padding:12px 0; }
.mini-buybar__name { font-weight:700; }
.mini-buybar__price { font-family:var(--font-mono); color:var(--ink-2); }
.mini-buybar .btn { margin-left:auto; }
@media (max-width:560px){ .mini-buybar__name{ display:none; } }

/* section kickers */
.sec-no { font-family:var(--font-mono); font-size:11px; letter-spacing:.1em; color:var(--accent-ink); text-transform:uppercase; }
.flag-sec { padding-block:clamp(40px,5vw,72px); border-top:1px solid var(--line); }
.flag-head { margin-bottom:32px; }
.flag-head h2 { font-size:var(--step-3); max-width:24ch; margin-top:8px; }
.flag-head p { color:var(--ink-2); max-width:56ch; margin-top:10px; }

/* magnitude bars */
.mag-list { display:flex; flex-direction:column; gap:16px; }
.mag { }
.mag__top { display:flex; justify-content:space-between; font-size:var(--step--1); margin-bottom:6px; }
.mag__label { color:var(--ink-2); }
.mag__pct { font-family:var(--font-mono); font-weight:700; }
.mag__track { height:10px; border-radius:var(--r-pill); background:var(--surface-sunk); overflow:hidden; }
.mag__fill { height:100%; border-radius:var(--r-pill); background:var(--brand-grad); width:0; transition:width 1s var(--ease-std); }
.mag[data-mr].in .mag__fill { width:var(--w); }

/* mechanism cards */
.mech-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:16px; }
.mech { padding:22px; border-radius:var(--r-lg); background:var(--surface); box-shadow:var(--sh-border),var(--sh-1); }
.mech__tag { font-family:var(--font-mono); font-size:10px; text-transform:uppercase; letter-spacing:.08em; color:var(--accent-ink); }
.mech h3 { font-size:var(--step-1); margin:8px 0; }
.mech p { color:var(--ink-2); font-size:var(--step--1); }
.mech__cite { margin-top:10px; font-size:11px; color:var(--ink-3); font-family:var(--font-mono); }

/* animated orbit hero */
.orbit-hero { position:relative; height:320px; border-radius:var(--r-xl); background:radial-gradient(ellipse at 50% 50%,#111a30,#0a0e18); overflow:hidden; box-shadow:var(--sh-border); display:flex; align-items:center; justify-content:center; }
.orbit-hero svg { width:100%; height:100%; }

/* spec sheet */
.spec-grid { display:grid; grid-template-columns:1fr 1fr; gap:0 40px; }
@media (max-width:640px){ .spec-grid{ grid-template-columns:1fr; } }
.spec-row { display:flex; justify-content:space-between; gap:16px; padding:11px 0; border-bottom:1px solid var(--line); font-size:var(--step--1); }
.spec-row dt { color:var(--ink-3); font-family:var(--font-mono); text-transform:uppercase; font-size:11px; letter-spacing:.05em; }
.spec-row dd { margin:0; font-weight:600; text-align:right; }

/* atom cloud - light stage (matches molecular-data card) */
.atom-cloud { height:260px; border-radius:var(--r-lg); overflow:hidden;
  background:radial-gradient(ellipse at 50% 42%, #ffffff, var(--surface-2) 78%);
  box-shadow:var(--sh-border), inset 0 1px 30px rgba(15,18,24,.03); }

/* coa table on product */
.coa-mini { }
.pdp-note { font-size:11px; color:var(--ink-3); font-family:var(--font-mono); margin-top:10px; line-height:1.5; }

/* cross-sell */
.crosssell { border-top:1px solid var(--line); padding-block:clamp(40px,5vw,72px); }

/* accessory grid */
.acc-info-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(200px,1fr)); gap:16px; margin-top:8px; }

/* stat tiles */
.stat-tiles { display:grid; grid-template-columns:repeat(auto-fit,minmax(130px,1fr)); gap:14px; margin-top:26px; }
.stat-tile { padding:16px; border-radius:var(--r-md); background:var(--surface-2); box-shadow:var(--sh-border); }
.stat-tile__v { font-size:var(--step-2); font-weight:700; letter-spacing:-.02em; }
.stat-tile__l { font-family:var(--font-mono); font-size:10px; text-transform:uppercase; letter-spacing:.06em; color:var(--ink-3); margin-top:2px; }

/* ---- molecule section (Aspect-style: atom representation + data card) ---- */
.mol-layout { display:grid; grid-template-columns:1fr 1.15fr; gap:clamp(24px,4vw,56px); align-items:center; }
@media (max-width:820px){ .mol-layout{ grid-template-columns:1fr; } }
.mol-atom { display:flex; flex-direction:column; gap:14px; }
.mol-atom .atom-cloud { height:300px; width:100%; }
.mol-legend { display:flex; gap:16px; flex-wrap:wrap; justify-content:center; font-family:var(--font-mono); font-size:11px; color:var(--ink-3); letter-spacing:.04em; }
.mol-legend span { display:inline-flex; align-items:center; gap:6px; }
.mol-legend i { width:9px; height:9px; border-radius:50%; display:inline-block; }
.mol-data { background:var(--surface); border-radius:var(--r-xl); box-shadow:var(--sh-border),var(--sh-1); overflow:hidden; }
.mol-formula-box { padding:22px 24px; background:linear-gradient(180deg,var(--accent-tint),transparent); border-bottom:1px solid var(--line); }
.mol-formula-box .mono-label { color:var(--ink-3); }
.mol-formula { font-family:var(--font-mono); font-size:clamp(1.6rem,1.1rem+2vw,2.4rem); font-weight:600; letter-spacing:-.01em; color:var(--ink); margin-top:8px; line-height:1; }
.mol-formula sub { font-size:.58em; font-weight:500; color:var(--ink-2); vertical-align:-.25em; margin-left:.5px; }
.mol-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:1px; background:var(--line); margin:0; }
@media (max-width:520px){ .mol-grid{ grid-template-columns:repeat(2,1fr); } }
.mol-cell { background:var(--surface); padding:16px 18px; }
.mol-cell dt { font-family:var(--font-mono); font-size:10px; text-transform:uppercase; letter-spacing:.07em; color:var(--ink-3); }
.mol-cell dd { margin:6px 0 0; font-size:var(--step--1); font-weight:600; font-family:var(--font-mono); }
.mol-cell dd.ok { color:var(--ok); }

.accent-word { color:var(--accent); }

/* breadcrumb + inline rating (zero added height) */
.crumbs { justify-content:space-between; align-items:center; margin-bottom:10px; }
.crumbs__path { display:inline-flex; gap:6px; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.buybox__rating { display:inline-flex; align-items:center; gap:5px; flex:none; text-transform:none; letter-spacing:0; }
.buybox__rating svg { width:13px; height:13px; color:var(--warn); fill:var(--warn); }
.buybox__rating svg.off { fill:var(--n-300); color:var(--n-300); }
.buybox__rating b { font-size:12px; color:var(--ink); font-weight:700; }
.buybox__rating span { color:var(--ink-3); }
.buybox__rating:hover b { color:var(--accent-ink); }

/* reviews section */
.rev-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:16px; }
.rev-card { margin:0; padding:22px; border-radius:var(--r-lg); background:var(--surface); box-shadow:var(--sh-border),var(--sh-1); }
.rev-card__stars { display:flex; gap:2px; margin-bottom:12px; }
.rev-card__stars svg { width:15px; height:15px; color:var(--warn); fill:var(--warn); }
.rev-card blockquote { margin:0; font-size:var(--step-0); color:var(--ink); line-height:1.5; }
.rev-card figcaption { margin-top:14px; font-family:var(--font-mono); font-size:11px; text-transform:uppercase; letter-spacing:.06em; color:var(--ink-3); }

/* reconstitution calculator */
.calc { display:grid; grid-template-columns:1fr 1fr; gap:20px; align-items:start; max-width:720px; }
@media (max-width:640px){ .calc{ grid-template-columns:1fr; } }
.calc__inputs { display:flex; flex-direction:column; gap:12px; }
.calc__field { display:block; }
.calc__field .lbl { display:block; font-family:var(--font-mono); font-size:10px; text-transform:uppercase; letter-spacing:.07em; color:var(--ink-3); margin-bottom:5px; }
.calc__field input { width:100%; }
.calc__out { background:var(--surface-2); border-radius:var(--r-lg); box-shadow:var(--sh-border); padding:6px 16px; }
.calc__row { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:11px 0; border-bottom:1px solid var(--line); font-size:var(--step--1); }
.calc__row:last-child { border-bottom:0; }
.calc__row b { font-family:var(--font-mono); font-weight:700; }
.calc__row.hl b { color:var(--accent); font-size:var(--step-1); }

/* ---- research monograph cross-link band ----------------------------------
   Sits at the foot of every PDP that has an encyclopedia entry. Deliberately
   quiet: it is a pointer to deeper reading, not another sales panel. */
.mono-band {
  display:flex; align-items:center; justify-content:space-between; gap:clamp(20px,3vw,44px);
  flex-wrap:wrap;
  padding:clamp(24px,3vw,38px);
  border:1px solid var(--line); border-radius:var(--r-lg);
  background:
    radial-gradient(520px 220px at 12% 0%, var(--accent-tint), transparent 70%),
    var(--surface);
}
.mono-band__body { flex:1 1 380px; min-width:0; }
.mono-band__body h2 { font-size:var(--step-2); }
.mono-band__body p { color:var(--ink-2); line-height:1.75; margin-top:10px; max-width:62ch; }
.mono-band .btn { flex:0 0 auto; }
@media (max-width:640px){ .mono-band .btn { width:100%; justify-content:center; } }

/* ==========================================================================
   PDP prose <-> data pairing layer            added 2026-07-27 (brand re-skin)
   --------------------------------------------------------------------------
   The PDP alternates prose and data down the page: overview, magnitudes,
   mechanisms, molecule, certificates, literature. Before this layer the two
   kinds of section looked identical and read as an undifferentiated stack.
   Three components fix that:
     .csig      identity data set INSIDE the overview prose
     .mech      mechanism cards indexed and tied to their magnitude bar
     .pdp-rail  a fixed section index so the reader can move between them

   Everything here inherits --pdp-accent / --pdp-ink / --pdp-tint, published on
   <html> by product.js from the compound's research area - the same colour as
   the cap on its vial. --pdp-accent is SURFACE ONLY (raw board pastels fail AA
   as text); --pdp-ink is the contrast-fitted twin that carries type.
   ========================================================================== */
:root { --pdp-accent:var(--pastel-periwinkle); --pdp-ink:var(--accent-ink); --pdp-tint:var(--accent-tint); }

/* ---- compound signature: the data half of the overview ------------------- */
.csig {
  display:grid; grid-template-columns:repeat(auto-fit,minmax(148px,1fr));
  margin-top:22px; border-radius:var(--r-md); overflow:hidden;
  background:var(--surface); box-shadow:var(--sh-border);
  border-top:2px solid var(--pdp-accent);
}
.csig__cell {
  padding:13px 16px; display:flex; flex-direction:column; gap:3px; min-width:0;
  border-right:1px solid var(--line);
}
.csig__cell:last-child { border-right:0; }
.csig__k {
  font-family:var(--font-mono); font-size:9.5px; letter-spacing:.1em;
  text-transform:uppercase; color:var(--ink-3);
}
.csig__v {
  font-family:var(--font-mono); font-size:var(--step--1); font-weight:600;
  color:var(--ink); font-variant-numeric:tabular-nums lining-nums;
  overflow-wrap:anywhere;
}
@media (max-width:640px){
  .csig { grid-template-columns:repeat(2,minmax(0,1fr)); }
  .csig__cell:nth-child(2n) { border-right:0; }
  .csig__cell { border-bottom:1px solid var(--line); }
}

/* ---- mechanism cards ---------------------------------------------------- */
.mech { position:relative; overflow:hidden; transition:box-shadow var(--dur) var(--ease-std), transform var(--dur) var(--ease-std); }
/* the colour rule ties the card to the vial cap and to its magnitude bar */
.mech::before { content:""; position:absolute; inset:0 0 auto 0; height:2px; background:var(--pdp-accent); }
.mech:hover { transform:translateY(-2px); box-shadow:var(--sh-border),var(--sh-2); }
@media (prefers-reduced-motion:reduce){ .mech:hover { transform:none; } }

.mech__idx {
  position:absolute; top:16px; right:18px;
  font-family:var(--font-mono); font-size:10px; letter-spacing:.08em;
  color:var(--ink-faint); font-variant-numeric:tabular-nums;
}
/* Stays the BRAND periwinkle, not the compound colour - see the note on
   --pdp-ink below. */
.mech__tag { color:var(--accent-ink); }

/* the spark: the same percentage as the matching bar in section 02, at card
   scale. Draws on reveal so it reads as a measurement landing, not decoration. */
.mech__link { display:flex; align-items:center; gap:10px; margin-top:14px; }
.mech__spark {
  flex:1; height:4px; border-radius:var(--r-pill);
  background:var(--surface-sunk); position:relative; overflow:hidden;
}
.mech__spark::after {
  content:""; position:absolute; inset:0 auto 0 0; width:0;
  border-radius:var(--r-pill); background:var(--pdp-accent);
  transition:width 900ms var(--ease-std) 120ms;
}
.mech.in .mech__spark::after, .mech.reveal--on .mech__spark::after { width:var(--w); }
@media (prefers-reduced-motion:reduce){
  .mech__spark::after { transition:none; width:var(--w); }
}
.mech__pct {
  font-family:var(--font-mono); font-size:10px; letter-spacing:.04em;
  color:var(--ink-3); font-variant-numeric:tabular-nums; white-space:nowrap;
}

/* ⚠️ THE COMPOUND COLOUR IS A SURFACE, NOT A THEME.
   First pass let --pdp-accent/--pdp-ink drive the page chrome as well - section
   numbers, mechanism tags, the magnitude bars. On a tan compound like MOTS-c
   that turned the entire product page olive-gold, and every PDP read as a
   different brand. That is not what the board does: there the pastel is a cap
   colour and a tile tint, small and decorative, while navy and periwinkle stay
   constant across the whole line.

   So the compound colour is now confined to thin surfaces only - the signature
   strip's top rule, the mechanism card's top rule, the spark fill, the active
   rail marker. Anything that carries TYPE or reads as brand chrome stays on
   --accent-ink. --pdp-ink is kept for the rare case that needs a compound-hued
   text colour, but nothing uses it by default. */
.mag__fill { background:var(--brand-grad); }

/* ---- fixed section rail ------------------------------------------------- */
/* Hidden below 1400px: there is no room beside a 1200px .wrap without either
   overlapping content or shrinking it, and a horizontal rail on mobile would
   compete with the sticky mini buy-bar. */
.pdp-rail { display:none; }
@media (min-width:1400px){
  .pdp-rail {
    display:flex; flex-direction:column; gap:2px;
    position:fixed; left:max(20px,calc((100vw - 1200px)/2 - 148px));
    top:50%; transform:translateY(-50%); z-index:30;
    padding:10px 0;
  }
  .pdp-rail__item {
    display:flex; align-items:center; gap:10px;
    padding:6px 10px 6px 0; border-left:2px solid var(--line);
    padding-left:12px; color:var(--ink-3);
    transition:color var(--dur) var(--ease-std), border-color var(--dur) var(--ease-std);
  }
  .pdp-rail__n {
    font-family:var(--font-mono); font-size:10px; letter-spacing:.08em;
    font-variant-numeric:tabular-nums;
  }
  .pdp-rail__t {
    font-size:12px; letter-spacing:-.01em;
    opacity:0; transform:translateX(-4px);
    transition:opacity var(--dur) var(--ease-std), transform var(--dur) var(--ease-std);
  }
  .pdp-rail:hover .pdp-rail__t { opacity:1; transform:none; }
  .pdp-rail__item:hover { color:var(--ink); }
  .pdp-rail__item.on {
    color:var(--ink); border-left-color:var(--pdp-accent);
  }
  .pdp-rail__item.on .pdp-rail__t { opacity:1; transform:none; }
  @media (prefers-reduced-motion:reduce){
    .pdp-rail__t { transition:none; }
  }
}

/* ==========================================================================
   PDP section motifs                          added 2026-07-27 (brand re-skin)
   --------------------------------------------------------------------------
   Built by assets/js/pdp-motifs.js. Each motif is decorative, aria-hidden, and
   animates once when its section scrolls into view (the JS adds .played).

   THE REDUCED-MOTION CONTRACT, and the reason this file is structured the way
   it is: every animated property has its FINISHED value declared on .played,
   and the JS adds .played immediately when prefers-reduced-motion is set. So
   the reduced-motion state is the completed drawing, not a blank box. A motif
   that draws a chromatogram still shows a chromatogram.

   Strokes are brand periwinkle at low alpha. The per-compound accent is NOT
   used here - it is a surface colour on thin rules only (see the note above
   .mag__fill), and six sections tinted per compound is exactly the mistake
   that turned a tan product page olive-gold.
   ========================================================================== */

.motif { position:relative; pointer-events:none; }
.motif__svg { display:block; width:100%; height:100%; overflow:visible; }
.motif__svg--fixed { width:auto; height:100%; margin-inline:auto; }

/* shared stroke language: hairline, round caps, periwinkle */
.motif-base, .motif-trace, .motif-tick, .motif-path, .motif-link,
.motif-ring, .motif-ring-bg, .motif-check, .motif-sweepline {
  fill:none; stroke-linecap:round; stroke-linejoin:round;
  vector-effect:non-scaling-stroke;
}
.motif-base { stroke:var(--line-strong); stroke-width:1; }
.motif-tick { stroke:var(--line-strong); stroke-width:1; opacity:.55; }

/* ---- 01 baseline: chromatogram draws once ------------------------------- */
.motif--baseline { height:120px; margin-top:26px; opacity:.9; }
.motif-trace {
  stroke:var(--accent); stroke-width:1.75;
  stroke-dasharray:2400; stroke-dashoffset:2400;
}
.motif--baseline.played .motif-trace {
  animation:motif-draw 2200ms var(--ease-std) forwards;
}
.motif-apex { fill:var(--accent); opacity:0; }
.motif--baseline.played .motif-apex { animation:motif-pop 500ms var(--ease-std) 1500ms forwards; }
@keyframes motif-draw { to { stroke-dashoffset:0; } }
@keyframes motif-pop { from { opacity:0; } to { opacity:1; } }

/* ---- 02 sweep: measurement line crossing a tick grid --------------------- */
.motif--sweep { height:64px; margin-bottom:22px; }
.motif-sweepline { stroke:var(--accent); stroke-width:1.5; }
.motif-sweep { opacity:0; }
/* 14s and opacity .5: this is the only LOOPING motif on the page, and it sits
   directly above the magnitude bars. Anything faster or stronger competes with
   the data it is framing. */
.motif--sweep.played .motif-sweep {
  opacity:.5;
  animation:motif-sweep 14s linear infinite;
}
@keyframes motif-sweep {
  0%   { transform:translateX(0); opacity:0; }
  8%   { opacity:.5; }
  92%  { opacity:.5; }
  100% { transform:translateX(1200px); opacity:0; }
}

/* ---- 03 pathway: per mechanism card ------------------------------------- */
.motif--pathway { height:40px; width:120px; margin-bottom:14px; }
.motif-path { stroke:var(--accent); stroke-width:1.5; opacity:.5; stroke-dasharray:180; stroke-dashoffset:180; }
.motif--pathway.played .motif-path { animation:motif-draw 900ms var(--ease-std) forwards; }
.motif-node { fill:var(--accent); opacity:0; }
.motif--pathway.played .motif-node {
  animation:motif-pop 320ms var(--ease-std) forwards;
  animation-delay:calc(360ms + var(--i) * 130ms);
}
.motif-pulse { fill:var(--pdp-accent,var(--accent)); opacity:.85; }

/* ---- 05 seal: ring closes, check strokes -------------------------------- */
.motif--seal { height:72px; margin-bottom:20px; }
.motif-ring-bg { stroke:var(--line); stroke-width:2; }
.motif-ring {
  stroke:var(--ok); stroke-width:2;
  stroke-dasharray:170; stroke-dashoffset:170;
  transform:rotate(-90deg); transform-origin:50% 50%;
}
.motif--seal.played .motif-ring { animation:motif-draw 900ms var(--ease-std) forwards; }
.motif-check { stroke:var(--ok); stroke-width:2.6; stroke-dasharray:44; stroke-dashoffset:44; }
.motif--seal.played .motif-check { animation:motif-draw 460ms var(--ease-std) 760ms forwards; }

/* ---- 06 citation: nodes link to a hub in sequence ------------------------ */
.motif--citation { height:120px; margin-bottom:24px; }
.motif-link {
  stroke:var(--accent); stroke-width:1.25; opacity:0;
  stroke-dasharray:120; stroke-dashoffset:120;
}
.motif--citation.played .motif-link {
  animation:motif-link-in 620ms var(--ease-std) forwards;
  animation-delay:calc(var(--i) * 130ms);
}
@keyframes motif-link-in { to { opacity:.42; stroke-dashoffset:0; } }
.motif-doc { fill:var(--surface); stroke:var(--accent); stroke-width:1.25; opacity:0; }
.motif--citation.played .motif-doc {
  animation:motif-pop 380ms var(--ease-std) forwards;
  animation-delay:calc(220ms + var(--i) * 130ms);
}
.motif-hub { fill:var(--accent); opacity:0; }
.motif--citation.played .motif-hub { animation:motif-pop 420ms var(--ease-std) forwards; }

/* ---- reduced motion: show the finished frame, never a blank one ---------- */
@media (prefers-reduced-motion:reduce){
  .motif *, .motif *::before, .motif *::after { animation:none !important; transition:none !important; }
  .motif-trace, .motif-path, .motif-ring, .motif-check, .motif-link { stroke-dashoffset:0; }
  .motif-apex, .motif-node, .motif-doc, .motif-hub { opacity:1; }
  .motif-link { opacity:.42; }
  .motif-sweep { opacity:.28; }
  .motif-pulse { display:none; }
}

/* ---- section rhythm ------------------------------------------------------
   The six sections were visually identical blocks. Alternating the ground
   (paper / washed) and giving each head a consistent eyebrow + rule makes the
   prose/data alternation legible at a glance while scrolling. */
.flag-sec { position:relative; }
.flag-head { position:relative; }
.flag-head .sec-no { display:inline-block; }
/* a short rule under the section number, in the compound colour - the ONLY
   place per-section colour appears, and it is 28px wide */
.flag-head .sec-no::after {
  content:""; display:block; width:28px; height:2px; margin-top:7px;
  background:var(--pdp-accent,var(--accent));
}

/* ==========================================================================
   Section split + panel visuals            added 2026-07-27 (brand re-skin 7c)
   --------------------------------------------------------------------------
   The PDP sections put their content in a ~45% left column and left the right
   half of every band empty - roughly 600px of dead space per section, ten
   sections deep. pdp-motifs.js promotes those sections to a two-column grid at
   runtime and hangs a section-appropriate animated panel in the right column.

   The panel is ALWAYS the second column and always decorative: it is
   aria-hidden, carries no figures, and nothing in it is load-bearing. Below
   1100px it is removed entirely rather than stacked - a decorative graphic
   pushing the real content down a phone screen is worse than no graphic.
   ========================================================================== */

.sec-split {
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(0,0.82fr);
  gap:clamp(32px,5vw,72px);
  align-items:center;
}
@media (max-width:1100px){
  .sec-split { display:block; }
  .sec-split__visual { display:none; }
}
.sec-split__body { min-width:0; }
.sec-split__visual {
  min-width:0; align-self:center;
  aspect-ratio:7/5; max-height:340px;
  display:flex; align-items:center; justify-content:center;
}
.motif__svg--panel { width:100%; height:100%; }

/* shared panel stroke language ------------------------------------------- */
.motif-gridline, .motif-axis, .motif-ridge, .motif-docline,
.motif-card-body, .motif-card-rule, .motif-scanline, .motif-hub-ring {
  fill:none; stroke-linecap:round; stroke-linejoin:round;
  vector-effect:non-scaling-stroke;
}
.motif-gridline { stroke:var(--line); stroke-width:1; opacity:0; }
.motif--panel.played .motif-gridline {
  animation:motif-pop 420ms var(--ease-std) forwards;
  animation-delay:calc(var(--i) * 70ms);
}
.motif-axis { stroke:var(--line-strong); stroke-width:1.25; }

/* ---- history: research-volume ridge over a time axis --------------------- */
.motif-ridge { stroke:var(--accent); stroke-width:2; stroke-dasharray:520; stroke-dashoffset:520; }
.motif--panel.played .motif-ridge { animation:motif-draw 1700ms var(--ease-std) 260ms forwards; }
.motif-ridge-fill { fill:var(--accent); opacity:0; }
.motif--panel.played .motif-ridge-fill { animation:motif-fade-in 1100ms var(--ease-std) 900ms forwards; }
@keyframes motif-fade-in { to { opacity:.09; } }
.motif-ridge-node { fill:var(--surface); stroke:var(--accent); stroke-width:2; opacity:0; }
.motif--panel.played .motif-ridge-node {
  animation:motif-pop 340ms var(--ease-std) forwards;
  animation-delay:calc(560ms + var(--i) * 180ms);
}

/* ---- citations: panel-scale citation graph ------------------------------ */
.motif-paper { opacity:0; transform-box:fill-box; transform-origin:center; }
.motif--panel.played .motif-paper {
  animation:motif-paper-in 520ms var(--ease-std) forwards;
  animation-delay:calc(260ms + var(--i) * 90ms);
}
@keyframes motif-paper-in { from { opacity:0; transform:scale(.86); } to { opacity:1; transform:none; } }
.motif-doc { fill:var(--surface); stroke:var(--accent); stroke-width:1.25; }
.motif-docline { stroke:var(--accent); stroke-width:1; opacity:.42; }
.motif-hub-ring { stroke:var(--accent); stroke-width:1.25; opacity:0; }
.motif--panel.played .motif-hub-ring { animation:motif-ring-breathe 5.5s var(--ease-move) 1.1s infinite; }
@keyframes motif-ring-breathe {
  0%,100% { opacity:.20; transform:scale(1); }
  50%     { opacity:.42; transform:scale(1.06); }
}
.motif-hub-ring { transform-box:fill-box; transform-origin:center; }

/* ---- ledger: stacked certificates with a scan pass ---------------------- */
.motif-card { opacity:0; transform-box:fill-box; transform-origin:center; }
.motif--panel.played .motif-card {
  animation:motif-card-in 620ms var(--ease-std) forwards;
  animation-delay:calc(var(--i) * 150ms);
}
@keyframes motif-card-in { from { opacity:0; transform:translateY(10px); } to { opacity:1; transform:none; } }
.motif-card-body { fill:var(--surface); stroke:var(--line-strong); stroke-width:1.25; }
.motif-card-rule { stroke:var(--accent); stroke-width:1.75; }
.motif-scan { opacity:0; }
/* 9s, low opacity: this loops, and it sits beside a table of real lot data */
.motif--panel.played .motif-scan {
  opacity:.55;
  animation:motif-scan 9s var(--ease-move) 1.2s infinite;
}
.motif-scanline { stroke:var(--accent); stroke-width:1.5; }
@keyframes motif-scan {
  0%   { transform:translateY(30px); opacity:0; }
  12%  { opacity:.55; }
  88%  { opacity:.55; }
  100% { transform:translateY(268px); opacity:0; }
}

/* ---- lattice: quiet dot field ------------------------------------------- */
.motif-dot { fill:var(--ink-faint); opacity:0; }
.motif--panel.played .motif-dot { animation:motif-dot-in 700ms var(--ease-std) forwards; animation-delay:calc(var(--i) * 45ms); }
@keyframes motif-dot-in { to { opacity:.30; } }
.motif-dot--lit { fill:var(--accent); }
.motif--panel.played .motif-dot--lit {
  animation:motif-dot-in 700ms var(--ease-std) forwards,
            motif-dot-breathe 6s var(--ease-move) 900ms infinite;
  animation-delay:calc(var(--i) * 45ms), calc(900ms + var(--i) * 140ms);
}
@keyframes motif-dot-breathe { 0%,100% { opacity:.34; } 50% { opacity:.85; } }

/* ---- reduced motion: finished frame, no loops --------------------------- */
@media (prefers-reduced-motion:reduce){
  .motif-gridline { opacity:1; }
  .motif-ridge { stroke-dashoffset:0; }
  .motif-ridge-fill { opacity:.09; }
  .motif-ridge-node, .motif-paper, .motif-card { opacity:1; transform:none; }
  .motif-hub-ring { opacity:.30; }
  .motif-dot { opacity:.30; }
  .motif-dot--lit { opacity:.60; }
  .motif-scan { opacity:0; }   /* a static scan line reads as a stray rule */
}

/* ---- 01 overview hero: Mol3D stage on the dark band -----------------------
   Replaces the orbit SVG. The stage is a real canvas renderer, so it needs a
   measurable box before it mounts - aspect-ratio gives it one without a
   height guess, and Mol3D re-fits on resize. */
.mol-hero { display:flex; flex-direction:column; align-items:center; gap:14px; }
.mol-hero__stage { width:100%; max-width:400px; aspect-ratio:1/1; }
.mol-hero__stage canvas { display:block; width:100%; height:100%; }
.mol-hero__cap { display:flex; flex-direction:column; align-items:center; gap:3px; text-align:center; }
.mol-hero__f { font-family:var(--font-mono); font-size:var(--step--1); color:var(--d-ink-2);
  font-variant-numeric:tabular-nums; letter-spacing:.02em; }
/* states plainly what the render is and is not - the same disclosure the
   section-04 molecule carries, because a spinning 3D model is exactly the kind
   of visual a reader would otherwise take as a measured structure */
.mol-hero__k { font-family:var(--font-mono); font-size:10px; text-transform:uppercase;
  letter-spacing:.07em; color:var(--d-ink-3); }
@media (max-width:900px){ .mol-hero__stage { max-width:300px; } }

/* ---- PDP ambient field ---------------------------------------------------
   Full-bleed canvas behind each prose/data section. Absolutely positioned so
   it inherits the section box and CANNOT collapse to 0x0 the way the withdrawn
   SVG panels did. pointer-events:none so it never intercepts a click, and the
   content wrap is lifted above it. */
.pdp-field { position:absolute; inset:0; width:100%; height:100%;
  display:block; pointer-events:none; z-index:0; }
section[data-sec] > .wrap,
section[data-sec] > .wrap-wide,
.flag-sec[data-sec] > .wrap,
.flag-sec[data-sec] > .wrap-wide { position:relative; z-index:1; }

/* ==========================================================================
   Animated lot-record document                        added 2026-07-27 (7d)
   --------------------------------------------------------------------------
   Fills the right half of the certificates section with a document that is
   actually filled in from coa-data.js and cycles the product's real lots.
   Deliberately NOT a facsimile of the signed certificate - no letterhead, no
   analyst, no signature, no seal, and it says so on its face.
   ========================================================================== */

.coa-split {
  display:grid;
  grid-template-columns:minmax(0,1.15fr) minmax(300px,0.85fr);
  gap:clamp(28px,4vw,56px);
  align-items:start;
}
@media (max-width:1000px){
  .coa-split { grid-template-columns:1fr; }
  .coa-split__doc { max-width:420px; margin-inline:auto; }
}
.coa-split__tbl { min-width:0; }
.coa-split__doc { min-width:0; position:sticky; top:calc(var(--nav-h) + 24px); }

/* ---- the document ------------------------------------------------------- */
.coad {
  position:relative; overflow:hidden;
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--r-lg, 16px);
  padding:22px 24px 18px;
  box-shadow:var(--sh-2);
  opacity:0; transform:translateY(10px) scale(.985);
  transition:opacity var(--dur-mid,420ms) var(--ease-std),
             transform var(--dur-mid,420ms) var(--ease-std);
}
.coad.in  { opacity:1; transform:none; }
.coad.out { opacity:0; transform:translateY(-8px) scale(.99); }

.coad-head {
  display:flex; align-items:baseline; justify-content:space-between;
  padding-bottom:12px; margin-bottom:14px;
  border-bottom:1px solid var(--line);
}
.coad-brand { font-family:var(--font-display); font-weight:600; letter-spacing:-.01em; color:var(--ink); }
.coad-title {
  font-family:var(--font-mono); font-size:10px; text-transform:uppercase;
  letter-spacing:.12em; color:var(--ink-3);
}

/* the purity figure is the point of the panel, so it gets the emphasis */
.coad-purity { display:flex; align-items:baseline; gap:7px; margin-bottom:4px; }
.coad-purity__n {
  font-family:var(--font-mono); font-variant-numeric:tabular-nums;
  font-size:clamp(30px,4.4vw,40px); font-weight:600; line-height:1;
  color:var(--ink); letter-spacing:-.02em;
}
.coad-purity__u { font-family:var(--font-mono); font-size:12px; color:var(--ink-3); }

.coad-trace { width:100%; height:52px; display:block; margin:2px 0 14px; overflow:visible; }
.coad-trace__base { stroke:var(--line); stroke-width:1; vector-effect:non-scaling-stroke; }
.coad-trace__line {
  stroke:var(--accent); stroke-width:1.75; stroke-linejoin:round; stroke-linecap:round;
  vector-effect:non-scaling-stroke;
  stroke-dasharray:340; stroke-dashoffset:340;
}
.coad.in .coad-trace__line { animation:coad-draw 1250ms var(--ease-std) 220ms forwards; }
@keyframes coad-draw { to { stroke-dashoffset:0; } }

.coad-grid { display:grid; gap:0; }
.coad-row {
  display:flex; align-items:baseline; justify-content:space-between; gap:14px;
  padding:7px 0; border-bottom:1px solid var(--line);
  opacity:0; transform:translateY(5px);
}
.coad-row:last-child { border-bottom:0; }
.coad.in .coad-row {
  animation:coad-row-in 420ms var(--ease-std) forwards;
  animation-delay:calc(180ms + var(--i) * 62ms);
}
@keyframes coad-row-in { to { opacity:1; transform:none; } }
.coad-k {
  font-family:var(--font-mono); font-size:10px; text-transform:uppercase;
  letter-spacing:.08em; color:var(--ink-3); white-space:nowrap;
}
.coad-v { font-size:var(--step--1); color:var(--ink); text-align:right; }
.coad-v--mono { font-family:var(--font-mono); font-variant-numeric:tabular-nums; }

.coad-foot { margin-top:12px; padding-top:10px; border-top:1px solid var(--line); }
.coad-note {
  font-family:var(--font-mono); font-size:10px; letter-spacing:.05em;
  color:var(--ink-faint);
}

/* one instrument pass per lot, then it rests - a looping scanner beside a
   table of real figures reads as a gimmick */
.coad-scan {
  position:absolute; left:0; right:0; top:0; height:34%;
  background:linear-gradient(180deg,
    color-mix(in srgb, var(--accent) 0%, transparent),
    color-mix(in srgb, var(--accent) 9%, transparent),
    color-mix(in srgb, var(--accent) 0%, transparent));
  opacity:0; pointer-events:none;
}
.coad.in .coad-scan { animation:coad-scan 1650ms var(--ease-move) 320ms 1 both; }
@keyframes coad-scan {
  0%   { transform:translateY(-40%); opacity:0; }
  18%  { opacity:1; }
  82%  { opacity:1; }
  100% { transform:translateY(320%); opacity:0; }
}

@media (prefers-reduced-motion:reduce){
  .coad { opacity:1; transform:none; transition:none; }
  .coad-row { opacity:1; transform:none; animation:none; }
  .coad-trace__line { stroke-dashoffset:0; animation:none; }
  .coad-scan { display:none; }
}

/* ==========================================================================
   Data-driven section visuals                          added 2026-07-27 (7e)
   --------------------------------------------------------------------------
   Right-column visuals for the timeline and literature sections, generated
   from the same data the section already lists.

   ⚠️ min-height is LOAD-BEARING. The withdrawn panel system relied on
   aspect-ratio alone inside a grid, measured 0x0, never fired its observer and
   painted stray fragments. The host must have a real box before any observer
   runs, and pdp-sectionviz.js asserts it at runtime.
   ========================================================================== */

.sviz-split {
  display:grid;
  grid-template-columns:minmax(0,1fr) minmax(260px,0.72fr);
  gap:clamp(28px,4vw,64px);
  align-items:center;
}
@media (max-width:1000px){
  .sviz-split { display:block; }
  .sviz-split__vis { display:none; }   /* never push content down a phone */
}
.sviz-split__body { min-width:0; }
.sviz-split__vis {
  min-width:0;
  min-height:260px;                    /* <- the fix */
  display:flex; align-items:center; justify-content:center;
}
.sviz__svg { width:100%; height:100%; max-height:400px; overflow:visible; }

/* ---- shared stroke language -------------------------------------------- */
.sviz-spine, .sviz-tick, .sviz-ring, .sviz-arc, .sviz-hub-ring, .sviz-card {
  fill:none; stroke-linecap:round; vector-effect:non-scaling-stroke;
}

/* ---- timeline ----------------------------------------------------------- */
.sviz-spine {
  stroke:var(--line-strong); stroke-width:1.25;
  stroke-dasharray:600; stroke-dashoffset:600;
}
.sviz.played .sviz-spine { animation:sviz-draw 900ms var(--ease-std) forwards; }
@keyframes sviz-draw { to { stroke-dashoffset:0; } }

.sviz-ev { opacity:0; transform:translateX(-8px); }
.sviz.played .sviz-ev {
  animation:sviz-ev-in 500ms var(--ease-std) forwards;
  animation-delay:calc(240ms + var(--i) * 130ms);
}
@keyframes sviz-ev-in { to { opacity:1; transform:none; } }

.sviz-tick  { stroke:var(--line-strong); stroke-width:1; }
.sviz-ring  { stroke:var(--accent); stroke-width:1.75; }
.sviz-core  { fill:var(--accent); }
.sviz-year  {
  font-family:var(--font-mono); font-size:12px; font-weight:600;
  fill:var(--ink); font-variant-numeric:tabular-nums; letter-spacing:-.01em;
}
.sviz-bar { fill:var(--accent); opacity:.16; }

.sviz-pulse { fill:var(--accent); opacity:0; }
.sviz.played .sviz-pulse { opacity:.5; }

/* ---- literature --------------------------------------------------------- */
.sviz-arc {
  stroke:var(--accent); stroke-width:1.25; opacity:0;
  stroke-dasharray:260; stroke-dashoffset:260;
}
.sviz.played .sviz-arc {
  animation:sviz-arc-in 760ms var(--ease-std) forwards;
  animation-delay:calc(200ms + var(--i) * 110ms);
}
@keyframes sviz-arc-in { to { opacity:.42; stroke-dashoffset:0; } }

.sviz-cite { opacity:0; transform:translateX(10px); }
.sviz.played .sviz-cite {
  animation:sviz-cite-in 520ms var(--ease-std) forwards;
  animation-delay:calc(360ms + var(--i) * 110ms);
}
@keyframes sviz-cite-in { to { opacity:1; transform:none; } }
.sviz-card { fill:var(--surface); stroke:var(--line); stroke-width:1.25; }
.sviz-cite__y {
  font-family:var(--font-mono); font-size:12px; font-weight:600;
  fill:var(--ink); font-variant-numeric:tabular-nums;
}
.sviz-cite__j { font-family:var(--font-mono); font-size:9.5px; fill:var(--ink-3); }

.sviz-hub-ring { stroke:var(--accent); stroke-width:1.5; opacity:0; transform-box:fill-box; transform-origin:center; }
.sviz.played .sviz-hub-ring { animation:sviz-breathe 5s var(--ease-move) 900ms infinite; }
@keyframes sviz-breathe {
  0%,100% { opacity:.26; transform:scale(1); }
  50%     { opacity:.5;  transform:scale(1.07); }
}
.sviz-hub { fill:var(--accent); opacity:0; }
.sviz.played .sviz-hub { animation:sviz-pop 420ms var(--ease-std) 320ms forwards; }
@keyframes sviz-pop { to { opacity:1; } }
.sviz-hub__lab {
  font-family:var(--font-mono); font-size:9px; fill:var(--ink-3);
  letter-spacing:.04em; opacity:0;
}
.sviz.played .sviz-hub__lab { animation:sviz-pop 420ms var(--ease-std) 520ms forwards; }

@media (prefers-reduced-motion:reduce){
  .sviz-spine { stroke-dashoffset:0; }
  .sviz-ev, .sviz-cite { opacity:1; transform:none; animation:none; }
  .sviz-arc { opacity:.42; stroke-dashoffset:0; animation:none; }
  .sviz-hub, .sviz-hub__lab { opacity:1; animation:none; }
  .sviz-hub-ring { opacity:.3; animation:none; }
  .sviz-pulse { display:none; }
}

/* ==========================================================================
   Full-width animated charts                           added 2026-07-27 (7f)
   --------------------------------------------------------------------------
   03 half-life axis · 04 radar + per-axis readout · 05 PK curve.
   All one-shot: they draw when the section scrolls in and then hold the
   finished frame. Nothing here loops - these sit beside numbers people are
   reading, and a looping chart is a distraction rather than polish.
   Motion is driven entirely by the `.in` class the section observer adds.
   ========================================================================== */

/* ---- 03 · half-life log axis ------------------------------------------- */
.hla { margin-top:34px; }
.hla__label {
  font-family:var(--font-mono); font-size:10px; text-transform:uppercase;
  letter-spacing:.1em; color:var(--ink-3); margin-bottom:26px;
}
.hla__rail { position:relative; height:76px; }
.hla__line {
  position:absolute; left:0; right:0; top:34px; height:1px;
  background:var(--line-strong); transform:scaleX(0); transform-origin:left;
}
.hla.in .hla__line { animation:hla-line 700ms var(--ease-std) forwards; }
@keyframes hla-line { to { transform:scaleX(1); } }

.hla__tick {
  position:absolute; left:var(--x); top:42px; transform:translateX(-50%);
  font-family:var(--font-mono); font-size:9.5px; color:var(--ink-faint);
  opacity:0; white-space:nowrap;
}
.hla.in .hla__tick { animation:hla-fade 420ms var(--ease-std) 620ms forwards; }
@keyframes hla-fade { to { opacity:1; } }

.hla__dot {
  position:absolute; left:var(--x); top:34px; transform:translate(-50%,-50%);
  display:flex; flex-direction:column; align-items:center; gap:6px;
  opacity:0;
}
.hla.in .hla__dot {
  animation:hla-drop 560ms cubic-bezier(.22,1.2,.36,1) forwards;   /* spring settle */
  animation-delay:calc(420ms + var(--i) * 90ms);
}
@keyframes hla-drop {
  from { opacity:0; transform:translate(-50%,-160%); }
  to   { opacity:1; transform:translate(-50%,-50%); }
}
.hla__dot i {
  width:9px; height:9px; border-radius:50%;
  background:var(--surface); border:1.75px solid var(--ink-faint);
}
.hla__dot b {
  position:absolute; top:14px; font-family:var(--font-mono); font-size:9.5px;
  font-weight:400; color:var(--ink-3); white-space:nowrap;
}
/* this compound: larger, accent, and its label carries weight */
.hla__dot--me i { border-color:var(--accent); background:var(--accent); width:13px; height:13px; }
.hla__dot--me b { color:var(--ink); font-weight:600; top:16px; }
.hla__note { font-size:var(--step--2); margin-top:6px; }

/* ---- 04 · radar full width --------------------------------------------- */
.radar-full {
  display:grid; grid-template-columns:minmax(0,300px) minmax(0,1fr);
  gap:clamp(28px,4vw,64px); align-items:center; margin-top:8px;
}
@media (max-width:860px){ .radar-full { grid-template-columns:1fr; } }
.radar-full__chart { min-width:0; }
.radar-svg { width:100%; height:auto; display:block; overflow:visible; }
.radar-full__side { min-width:0; }

.radar-rings polygon { stroke:var(--line-2); fill:none; opacity:0; transform-box:fill-box; transform-origin:center; }
.radar-full.in .radar-rings polygon:nth-child(1) { animation:radar-ring 460ms var(--ease-std) 0ms forwards; }
.radar-full.in .radar-rings polygon:nth-child(2) { animation:radar-ring 460ms var(--ease-std) 70ms forwards; }
.radar-full.in .radar-rings polygon:nth-child(3) { animation:radar-ring 460ms var(--ease-std) 140ms forwards; }
.radar-full.in .radar-rings polygon:nth-child(4) { animation:radar-ring 460ms var(--ease-std) 210ms forwards; }
@keyframes radar-ring { from { opacity:0; transform:scale(.82); } to { opacity:1; transform:none; } }

.radar-vs { fill:rgba(148,160,189,.18); stroke:#94a0bd; stroke-width:1.5; opacity:0; }
.radar-full.in .radar-vs { animation:radar-fade 620ms var(--ease-std) 340ms forwards; }
@keyframes radar-fade { to { opacity:1; } }

/* the active polygon sweeps closed rather than just fading up */
.radar-me {
  fill:color-mix(in srgb, var(--accent) 20%, transparent);
  stroke:var(--accent); stroke-width:2;
  opacity:0; transform-box:fill-box; transform-origin:center;
}
.radar-full.in .radar-me { animation:radar-sweep 760ms cubic-bezier(.22,1,.36,1) 460ms forwards; }
@keyframes radar-sweep {
  from { opacity:0; transform:scale(.7) rotate(-14deg); }
  to   { opacity:1; transform:none; }
}
.radar-vtx { fill:var(--accent); opacity:0; }
.radar-full.in .radar-vtx {
  animation:radar-fade 300ms var(--ease-std) forwards;
  animation-delay:calc(820ms + var(--i) * 70ms);
}

/* per-axis readout - the numbers the polygon encodes, spelled out */
.rdo-list { display:grid; gap:9px; margin-top:18px; }
.rdo {
  display:grid; grid-template-columns:minmax(84px,auto) 1fr 34px;
  align-items:center; gap:12px; opacity:0; transform:translateX(8px);
}
.radar-full.in .rdo {
  animation:rdo-in 420ms var(--ease-std) forwards;
  animation-delay:calc(560ms + var(--i) * 80ms);
}
@keyframes rdo-in { to { opacity:1; transform:none; } }
.rdo__ax { font-family:var(--font-mono); font-size:10.5px; color:var(--ink-3); }
.rdo__track { position:relative; height:7px; border-radius:4px; background:var(--paper-wash); overflow:hidden; }
.rdo__vs, .rdo__me { position:absolute; inset:0 auto 0 0; border-radius:4px; width:0; }
.rdo__vs { background:#94a0bd; opacity:.4; }
.rdo__me { background:var(--accent); }
.radar-full.in .rdo__vs, .radar-full.in .rdo__me {
  animation:rdo-fill 760ms cubic-bezier(.22,1,.36,1) forwards;
  animation-delay:calc(640ms + var(--i) * 80ms);
}
@keyframes rdo-fill { to { width:var(--w); } }
.rdo__n {
  font-family:var(--font-mono); font-size:11px; color:var(--ink);
  font-variant-numeric:tabular-nums; text-align:right;
}

/* ---- 05 · PK curve full width ------------------------------------------ */
.pk-full { margin-top:8px; }
.pk-svg { width:100%; height:clamp(240px,30vw,340px); display:block; overflow:visible; }
.pk-vs {
  fill:none; stroke:#94a0bd; stroke-width:2; stroke-dasharray:4 4;
  vector-effect:non-scaling-stroke; opacity:0;
}
.pk-full.in .pk-vs { animation:pk-fade 700ms var(--ease-std) 260ms forwards; }
@keyframes pk-fade { to { opacity:1; } }

.pk-me {
  fill:none; stroke:var(--accent); stroke-width:2.5;
  stroke-linecap:round; stroke-linejoin:round; vector-effect:non-scaling-stroke;
  stroke-dasharray:2400; stroke-dashoffset:2400;
}
.pk-full.in .pk-me { animation:pk-draw 1500ms var(--ease-std) forwards; }
@keyframes pk-draw { to { stroke-dashoffset:0; } }

/* area resolves only after the line has finished, so the shape reads as a
   consequence of the curve rather than creeping in beside it */
.pk-area { opacity:0; }
.pk-full.in .pk-area { animation:pk-fade 900ms var(--ease-std) 1250ms forwards; }

.pk-rider { fill:var(--accent); opacity:0; }
.pk-full.in .pk-rider { animation:pk-fade 260ms var(--ease-std) 500ms forwards; }

.pk-peak { opacity:0; }
.pk-full.in .pk-peak { animation:pk-fade 460ms var(--ease-std) 1500ms forwards; }
.pk-peak__stem { stroke:var(--accent); stroke-width:1; stroke-dasharray:3 3; opacity:.5; vector-effect:non-scaling-stroke; }
.pk-peak__lab {
  font-family:var(--font-mono); font-size:10px; fill:var(--ink-3);
  letter-spacing:.03em;
}

@media (prefers-reduced-motion:reduce){
  .hla__line { transform:none; animation:none; }
  .hla__tick, .hla__dot { opacity:1; transform:translate(-50%,-50%); animation:none; }
  .hla__tick { transform:translateX(-50%); }
  .radar-rings polygon, .radar-vs, .radar-me, .radar-vtx, .rdo { opacity:1; transform:none; animation:none; }
  .rdo__vs, .rdo__me { width:var(--w); animation:none; }
  .pk-vs, .pk-area, .pk-peak { opacity:1; animation:none; }
  .pk-me { stroke-dashoffset:0; animation:none; }
  .pk-rider { display:none; }   /* a parked dot mid-curve reads as a data point */
}

/* ==========================================================================
   02 · Published evidence                              added 2026-07-27 (7g)
   --------------------------------------------------------------------------
   Stat cards + a cited dose-response chart, for compounds that have a VERIFIED
   entry in evidence-data.js. Layout follows Brandon's reference; colour is the
   ExactAmino board palette, not the reference's navy/orange.

   Card accent colour is decorative and encodes nothing - the figure and its
   citation carry the meaning. Every card and every chart row keeps its source
   visible, because this section states human trial outcomes on an RUO page and
   the attribution is what makes that defensible.
   ========================================================================== */

.ev-grid {
  display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);
  gap:clamp(28px,4vw,60px); align-items:start;
}
@media (max-width:1000px){ .ev-grid { grid-template-columns:1fr; } }
.ev-left, .ev-right { min-width:0; }

/* ---- stat cards --------------------------------------------------------- */
.ev-cards {
  display:grid; grid-template-columns:repeat(2,minmax(0,1fr));
  gap:14px; margin-top:26px;
}
@media (max-width:520px){ .ev-cards { grid-template-columns:1fr; } }

.ev-card {
  position:relative; overflow:hidden;
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-md,12px); padding:18px 18px 14px;
  box-shadow:var(--sh-1);
  opacity:0; transform:translateY(10px);
}
/* the coloured top rule, drawn on rather than a border so it can animate */
.ev-card::before {
  content:''; position:absolute; inset:0 0 auto 0; height:3px;
  background:var(--rule); transform:scaleX(0); transform-origin:left;
}
.ev-grid.in .ev-card {
  animation:ev-card-in 520ms var(--ease-std) forwards;
  animation-delay:calc(var(--i) * 90ms);
}
.ev-grid.in .ev-card::before {
  animation:ev-rule 620ms var(--ease-std) forwards;
  animation-delay:calc(160ms + var(--i) * 90ms);
}
@keyframes ev-card-in { to { opacity:1; transform:none; } }
@keyframes ev-rule   { to { transform:scaleX(1); } }

.ev-card__v {
  font-family:var(--font-display); font-size:clamp(30px,3.4vw,38px);
  font-weight:600; line-height:1; letter-spacing:-.025em; color:var(--ink);
  font-variant-numeric:tabular-nums;
}
.ev-card__u { font-size:.5em; font-weight:500; margin-left:2px; color:var(--ink-2); }
.ev-card__l {
  font-size:var(--step--1); color:var(--ink-2); line-height:1.5;
  margin:10px 0 12px;
}
.ev-card__c {
  display:block; font-family:var(--font-mono); font-size:9.5px;
  font-style:normal; letter-spacing:.03em; color:var(--ink-faint);
}

/* ---- chart card --------------------------------------------------------- */
.ev-chart {
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-lg,16px); padding:22px 24px 18px;
  box-shadow:var(--sh-2);
  opacity:0; transform:translateY(12px);
}
.ev-grid.in .ev-chart { animation:ev-card-in 620ms var(--ease-std) 180ms forwards; }
.ev-chart__h {
  font-family:var(--font-display); font-weight:600; font-size:var(--step-0);
  color:var(--ink); letter-spacing:-.01em;
}
.ev-chart__s {
  font-family:var(--font-mono); font-size:10.5px; color:var(--ink-3);
  margin-top:4px; margin-bottom:18px; letter-spacing:.01em;
}

.ev-rows { display:grid; gap:10px; }
.ev-row {
  display:grid; grid-template-columns:minmax(60px,auto) 1fr minmax(52px,auto);
  align-items:center; gap:12px;
  opacity:0;
}
.ev-grid.in .ev-row {
  animation:ev-fade 380ms var(--ease-std) forwards;
  animation-delay:calc(320ms + var(--i) * 80ms);
}
@keyframes ev-fade { to { opacity:1; } }
.ev-row__lab {
  font-family:var(--font-mono); font-size:11px; color:var(--ink-2);
  white-space:nowrap; font-variant-numeric:tabular-nums;
}
.ev-row__track {
  position:relative; height:9px; border-radius:5px;
  background:var(--paper-wash); overflow:hidden;
}
.ev-row__fill {
  position:absolute; inset:0 auto 0 0; width:0; border-radius:5px;
  background:linear-gradient(90deg, var(--pastel-periwinkle), var(--pastel-lavender));
}
.ev-grid.in .ev-row__fill {
  animation:ev-fill 900ms cubic-bezier(.22,1,.36,1) forwards;
  animation-delay:calc(400ms + var(--i) * 80ms);
}
@keyframes ev-fill { to { width:var(--w); } }
.ev-row__val {
  font-family:var(--font-mono); font-size:11.5px; font-weight:600;
  color:var(--ink); text-align:right; font-variant-numeric:tabular-nums;
}

.ev-note {
  margin-top:18px; padding:12px 14px;
  border-left:3px solid var(--accent);
  background:var(--paper-wash); border-radius:0 8px 8px 0;
  font-size:var(--step--1); color:var(--ink-2); line-height:1.55;
  opacity:0;
}
.ev-note b { color:var(--ink); font-weight:600; }
.ev-grid.in .ev-note { animation:ev-fade 500ms var(--ease-std) 900ms forwards; }

/* the citation line is not fine print to be hidden - it is the reason this
   section is allowed to exist, so it stays legible */
.ev-foot {
  margin-top:16px; padding-top:12px; border-top:1px solid var(--line);
  font-family:var(--font-mono); font-size:9.5px; line-height:1.6;
  color:var(--ink-3); letter-spacing:.01em;
}

@media (prefers-reduced-motion:reduce){
  .ev-card, .ev-chart, .ev-row, .ev-note { opacity:1; transform:none; animation:none; }
  .ev-card::before { transform:scaleX(1); animation:none; }
  .ev-row__fill { width:var(--w); animation:none; }
}

/* ---- "Verified" pill on the lot-record card ------------------------------
   A checkmark in a green-gradient box plus the word, sitting where the plain
   "Lot record" label used to be.

   Colour notes, because the board palette does not contain a usable green for
   this and one had to be derived:
     · The board mint #8fd4c1 is 1.70:1 on white - it cannot carry a label, and
       a white check on it is illegible. It stays a surface colour.
     · The gradient runs #35a488 -> #15705d. A checkmark is a GRAPHICAL object,
       so the threshold is 3:1, not 4.5:1 - the lightest point of the gradient
       measures 3.08:1 against white and the darkest 5.99:1, so the glyph holds
       everywhere along the ramp.
     · The word "Verified" is set in #1b7565 (5.02:1 on the mint tint), not in
       the gradient - text gets the AA-safe deep tone, never the pastel.
   -------------------------------------------------------------------------- */
.coad-badge {
  display:inline-flex; align-items:center; gap:7px;
  padding:4px 10px 4px 4px;
  border-radius:999px;
  background:#eaf6f2;
  border:1px solid #cfe9e0;
}
.coad-badge__box {
  display:grid; place-items:center;
  width:18px; height:18px; border-radius:5px;
  background:linear-gradient(135deg, #35a488, #15705d);
  box-shadow:0 1px 2px rgba(21,112,93,.35);
  flex:none;
}
.coad-badge__box svg { width:12px; height:12px; display:block; }
.coad-badge__box path {
  fill:none; stroke:#fff; stroke-width:2.1;
  stroke-linecap:round; stroke-linejoin:round;
  /* the tick strokes itself in as each lot loads, then rests */
  stroke-dasharray:16; stroke-dashoffset:16;
}
.coad.in .coad-badge__box path { animation:coad-tick 460ms var(--ease-std) 260ms forwards; }
@keyframes coad-tick { to { stroke-dashoffset:0; } }
.coad-badge__t {
  font-family:var(--font-mono); font-size:10px; font-weight:600;
  text-transform:uppercase; letter-spacing:.09em; color:#1b7565;
}
@media (prefers-reduced-motion:reduce){
  .coad-badge__box path { stroke-dashoffset:0; animation:none; }
}

/* citation card text ------------------------------------------------------
   The first build rendered year + journal only, which said nothing. The title
   now leads; provenance sits under it in mono. Truncation happens in JS on a
   word boundary, so nothing here needs to clip. */
.sviz-cite__t {
  font-family:var(--font-sans); font-size:12.5px; font-weight:600;
  fill:var(--ink); letter-spacing:-.005em;
}
.sviz-cite__m {
  font-family:var(--font-mono); font-size:10px;
  fill:var(--ink-3); letter-spacing:.02em;
}
.sviz-card__spine { opacity:.9; }
.sviz-hub__n {
  font-family:var(--font-mono); font-size:9.5px;
  fill:var(--ink-faint); letter-spacing:.05em;
}

/* ---- receptor-engagement orbit -------------------------------------------
   ⚠️ Node fills are the RAW board pastels under NAVY text, not the darkened
   deeps under white. The first build used the deeps and read heavy and muddy
   against this paper-white page. Navy on the raw pastels measures 5.63:1
   (periwinkle), 8.18:1 (tan), 10.78:1 (mint) - all clear AA, so the nodes show
   the actual brand colours. Fills come from per-node radial gradients built in
   receptor-orbit.js so each reads as a sphere lit from the upper left. */
.rorb { width:100%; max-width:520px; margin:0 auto 22px; }
.rorb__svg { width:100%; height:auto; display:block; overflow:visible; }

.rorb-track {
  fill:none; stroke:var(--line-strong); stroke-width:1.25;
  stroke-dasharray:2 8; stroke-linecap:round; opacity:.85;
}
.rorb-hub {
  fill:var(--surface); stroke:var(--line); stroke-width:1.25;
  filter:url(#rorbHubShadow);
}
.rorb-hub__n {
  font-family:var(--font-display); font-weight:600; font-size:23px;
  fill:var(--ink); letter-spacing:-.02em;
}
.rorb-hub__c {
  font-family:var(--font-mono); font-size:10.5px; fill:var(--ink-faint);
  letter-spacing:.06em;
}
.rorb-spoke { stroke-width:1.5; stroke-linecap:round; }
.rorb-pulse { opacity:0; }

/* nodes: sphere gradient + soft cast shadow + white separator ring */
.rorb-node { filter:url(#rorbShadow); }
.rorb-node__ring { fill:none; stroke:#fff; stroke-width:6; }
.rorb-node__edge { opacity:.55; }
.rorb-node__glow { pointer-events:none; }
.rorb-node__k {
  font-family:var(--font-display); font-weight:700; font-size:17px;
  fill:var(--ink); letter-spacing:-.01em;
}
.rorb-node__v {
  font-family:var(--font-mono); font-size:10.5px;
  fill:var(--ink-2); letter-spacing:.04em;
}

/* beads riding the dotted track */
.rorb-orb { filter:drop-shadow(0 1px 3px rgba(22,33,62,.25)); }
.rorb-orb__glow { pointer-events:none; }

@media (max-width:600px){
  .rorb-hub__n { font-size:20px; }
  .rorb-node__k { font-size:15px; }
}
