/* Vantra. Implements DESIGN-SYSTEM.md. Tokens live in tokens.css (generated). */

/* ---------- Fonts ----------
   Outfit is Align's typeface; Cormorant Garamond is the serif they pair with it
   on tool and section headings. */
@font-face {
  font-family: "Outfit";
  src: url("../fonts/Outfit-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Outfit";
  src: url("../fonts/Outfit-500.woff2") format("woff2");
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Outfit";
  src: url("../fonts/Outfit-600.woff2") format("woff2");
  font-weight: 600; font-style: normal; font-display: swap;
}
/* Mono carries every measured value on the site: prices, SKUs, lot numbers,
   molecular weights. Self-hosted so those read identically on every machine. */
@font-face {
  font-family: "Geist Mono";
  src: url("../fonts/GeistMono-400.woff2") format("woff2");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Cormorant Garamond";
  src: url("../fonts/CormorantGaramond-600.woff2") format("woff2");
  font-weight: 600; font-style: normal; font-display: swap;
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  background: var(--v-bg);
  color: var(--v-text);
  font-family: var(--v-font);
  font-size: 0.9375rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}
img, svg, video { display: block; max-width: 100%; height: auto; }
button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: none; cursor: pointer; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; padding: 0; }
table { border-collapse: collapse; width: 100%; }

/* ---------- Type scale ----------
   Matched to alignpeptides.com: large headings at weight 400 with slightly
   negative tracking, and small body copy. */
.display {
  font-size: clamp(2.5rem, 4.6vw, 3.3rem);
  font-weight: 400; letter-spacing: -0.034em; line-height: 1.04;
  text-wrap: balance;
}
h1, .h1 {
  font-size: clamp(2.1rem, 3.8vw, 2.9rem);
  font-weight: 400; letter-spacing: -0.028em; line-height: 1.07;
  text-wrap: balance;
}
h2, .h2 {
  font-size: clamp(1.6rem, 2.6vw, 2rem);
  font-weight: 400; letter-spacing: -0.022em; line-height: 1.14;
  text-wrap: balance;
}
h3, .h3 {
  font-size: 1.3rem; font-weight: 500; letter-spacing: -0.01em; line-height: 1.25;
  text-wrap: balance;
}
h4, .h4 { font-size: 1.0625rem; font-weight: 500; line-height: 1.35; }
/* Serif display accent, as Align uses on tool headings. */
.serif {
  font-family: var(--v-font-display);
  font-weight: 600; letter-spacing: 0.01em;
}
/* Align's signature: tiny uppercase label with very wide tracking. */
/* .eyebrow is deliberately gone. A tiny uppercase wide-tracked label above every
   section heading is the clearest generated-page tell there is, and all five here
   just restated the heading below ("Process" over "How ordering works"). */
.lead { font-size: 1.0625rem; line-height: 1.6; color: var(--v-text-muted); }
.small { font-size: 0.85rem; line-height: 1.6; }
.micro {
  font-size: 0.7rem; font-weight: 500; letter-spacing: 0.12em; line-height: 1.5;
  text-transform: uppercase;
}
.mono { font-family: var(--v-font-mono); font-size: 0.85rem; line-height: 1.5; }
.muted { color: var(--v-text-muted); }
.faint { color: var(--v-text-faint); }
.prose { max-width: 68ch; color: var(--v-text-muted); text-wrap: pretty; font-size: 0.9375rem; }
.prose > * + * { margin-top: var(--sp-4); }
.prose h2, .prose h3 { color: var(--v-text); margin-top: var(--sp-10); }
.prose a { color: var(--v-text); text-decoration: underline; text-underline-offset: 3px; }
.prose strong { color: var(--v-text); font-weight: 500; }
.prose ul { list-style: disc; padding-left: 1.25em; }
.prose li + li { margin-top: var(--sp-2); }

/* ---------- Layout ---------- */
.wrap {
  max-width: var(--v-container);
  margin-inline: auto;
  padding-inline: var(--v-gutter);
}
.wrap-wide { max-width: var(--v-container-wide); margin-inline: auto; padding-inline: var(--v-gutter); }
.section { padding-block: var(--v-section-y); }
.band-surface { background: var(--v-surface); }
.band-light {
  background: var(--v-light-bg);
  color: var(--v-light-text);
}
.band-light .muted, .band-light .lead { color: var(--v-light-muted); }
.band-light .faint { color: var(--v-light-muted); }

/* Section header: headline then one supporting line. No eyebrow. */
.sec-head { max-width: 62ch; margin-bottom: var(--sp-10); }
.sec-head p { margin-top: var(--sp-3); color: var(--v-text-muted); font-size: 1.125rem; }
.band-light .sec-head p { color: var(--v-light-muted); }

/* Labelled rule: the only permitted section label. Max two per page. */
.rule-label {
  display: flex; align-items: center; gap: var(--sp-4);
  margin-bottom: var(--sp-8);
  font-size: 0.78125rem; font-weight: 500; color: var(--v-text-faint);
}
.rule-label::after {
  content: ""; flex: 1; height: 1px; background: var(--v-line);
}
.band-light .rule-label::after { background: var(--v-light-line); }

.grid { display: grid; gap: var(--sp-6); }
.grid-auto { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.stack { display: flex; flex-direction: column; gap: var(--sp-4); }
.row { display: flex; align-items: center; gap: var(--sp-4); flex-wrap: wrap; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--sp-2);
  min-height: 44px; padding: 0 var(--sp-6);
  border-radius: var(--r-md);
  font-size: 0.9375rem; font-weight: 500;
  transition: background-color var(--d-micro) var(--ease-out),
              border-color var(--d-micro) var(--ease-out),
              transform var(--d-micro) var(--ease-out),
              opacity var(--d-micro) var(--ease-out);
  white-space: nowrap;
}
.btn:active { transform: scale(0.97); }
.btn-lg { min-height: 52px; padding: 0 var(--sp-8); font-size: 1rem; }
.btn-sm { min-height: 36px; padding: 0 var(--sp-4); font-size: 0.875rem; }

.btn-primary {
  background: var(--v-accent); color: var(--v-accent-on);
  font-weight: 500; letter-spacing: 0.02em;
}
.btn-primary:hover { background: var(--v-accent-hover); }

.btn-secondary {
  border: 1px solid var(--v-line-strong); color: var(--v-text);
}
.btn-secondary:hover { background: var(--v-accent-wash); border-color: var(--v-text); }

.btn-ghost { color: var(--v-text-muted); }
.btn-ghost:hover { background: var(--v-surface-2); color: var(--v-text); }

.btn-danger { border: 1px solid var(--v-danger); color: var(--v-danger); }
.btn-danger:hover { background: rgba(229, 118, 107, 0.1); }

.band-light .btn-secondary { border-color: var(--v-light-line); color: var(--v-light-text); }
.band-light .btn-secondary:hover { background: rgba(20, 23, 26, 0.06); }

.btn[disabled], .btn[aria-disabled="true"] {
  color: var(--v-text-disabled); background: var(--v-surface-2);
  border-color: transparent; cursor: not-allowed;
}
.btn[disabled]:active { transform: none; }
/* Loading keeps width fixed so layout never shifts. */
.btn[data-loading="true"] { color: transparent; position: relative; pointer-events: none; }
.btn[data-loading="true"]::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid rgba(10, 20, 0, 0.25); border-top-color: var(--v-accent-on);
  animation: spin 700ms linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.link-accent {
  color: var(--v-text);
  text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: rgba(255, 255, 255, 0.35);
  transition: text-decoration-color var(--d-micro) var(--ease-out);
}
.link-accent:hover { text-decoration-color: var(--v-text); }

/* ---------- Tags ---------- */
.tag {
  display: inline-flex; align-items: center; gap: var(--sp-2);
  height: 26px; padding: 0 var(--sp-3);
  border-radius: var(--r-pill);
  background: var(--v-surface-2); color: var(--v-text-muted);
  font-size: 0.78125rem; font-weight: 500;
}
.tag-accent { background: var(--v-accent-wash); color: var(--v-accent); }
.tag-warn { background: rgba(227, 179, 65, 0.12); color: var(--v-warn); }

/* ---------- Header ---------- */
.site-header {
  position: sticky; top: 0; z-index: var(--z-sticky);
  height: var(--v-nav-h);
  background: rgba(5, 5, 5, 0.92);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--v-line);
}
.site-header .wrap {
  height: 100%; display: flex; align-items: center; gap: var(--sp-8);
}
.wordmark {
  font-size: 1.0625rem; font-weight: 500; letter-spacing: 0.18em;
  flex-shrink: 0;
}
.wordmark span { color: var(--v-accent); }
.nav-main { display: flex; gap: var(--sp-6); margin-inline: auto; }
.nav-main a {
  font-size: 0.9375rem; color: var(--v-text-muted);
  padding-block: var(--sp-2);
  transition: color var(--d-micro) var(--ease-out);
}
.nav-main a:hover { color: var(--v-text); }
.nav-main a[aria-current="page"] { color: var(--v-accent); }
.nav-util { display: flex; align-items: center; gap: var(--sp-3); flex-shrink: 0; }
.cart-count { font-family: var(--v-font-mono); font-size: 0.875rem; color: var(--v-text-faint); }
.nav-toggle { display: none; }

@media (max-width: 900px) {
  .nav-main { display: none; }
  .nav-toggle { display: inline-flex; }
  .nav-main.is-open {
    display: flex; flex-direction: column; gap: 0;
    position: fixed; inset: var(--v-nav-h) 0 0;
    background: var(--v-bg); padding: var(--sp-6) var(--v-gutter);
    z-index: var(--z-drawer); margin: 0;
  }
  .nav-main.is-open a {
    padding-block: var(--sp-4); font-size: 1.125rem;
    border-bottom: 1px solid var(--v-line);
  }
}

/* ---------- Compliance notice ---------- */
.notice-bar {
  background: var(--v-surface-2);
  border-bottom: 1px solid var(--v-line);
  padding-block: var(--sp-2);
  text-align: center;
}
.notice-bar p { font-size: 0.78125rem; color: var(--v-text-faint); }

/* ---------- Hero ---------- */
.hero { padding-block: clamp(72px, 11vw, 148px) var(--v-section-y); }
.hero-grid {
  display: grid; gap: clamp(40px, 6vw, 80px);
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  align-items: center;
}
@media (max-width: 900px) { .hero-grid { grid-template-columns: 1fr; } }
.hero p.lead { margin-top: var(--sp-6); max-width: 52ch; }
.hero .row { margin-top: var(--sp-8); }
.hero-media {
  border: 1px solid var(--v-line); border-radius: var(--r-lg);
  background: var(--v-surface); overflow: hidden;
  aspect-ratio: 4 / 5;
  display: grid; place-items: center;
}

/* ---------- Product card ---------- */
.pcard {
  display: flex; flex-direction: column;
  border: 1px solid var(--v-line); border-radius: var(--r-lg);
  background: var(--v-surface); overflow: hidden;
  transition: transform var(--d-base) var(--ease-out),
              border-color var(--d-base) var(--ease-out);
}
.pcard:hover { transform: translateY(-2px); border-color: var(--v-line-strong); }
.pcard-media {
  aspect-ratio: 1; background: var(--v-surface-2);
  display: grid; place-items: center;
  border-bottom: 1px solid var(--v-line);
}
.pcard-body { padding: var(--sp-5); display: flex; flex-direction: column; gap: var(--sp-2); flex: 1; }
.pcard-body h2 { font-size: 1.1875rem; font-weight: 600; letter-spacing: 0; line-height: 1.35; }
.pcard-spec {
  font-family: var(--v-font-mono); font-size: 0.875rem; color: var(--v-text-faint);
}
.pcard-foot {
  margin-top: auto; padding-top: var(--sp-4);
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
}
.pcard-price { font-family: var(--v-font-mono); font-size: 1rem; color: var(--v-text); }
/* Stock state is a text label, never a coloured dot. */
.stock-in {
  color: var(--v-accent); font-size: 0.7rem; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase;
}
.stock-out {
  color: var(--v-text-faint); font-size: 0.7rem; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase;
}
/* Featured product spans two columns so cards are not identical clones. */
.pcard-feature { grid-column: span 2; }
.pcard-feature .pcard-media { aspect-ratio: 16 / 10; }
@media (max-width: 720px) { .pcard-feature { grid-column: span 1; } }

/* ---------- Spec table ---------- */
.spec-scroll { overflow-x: auto; }
.spec {
  font-size: 0.9375rem; min-width: 480px;
}
.spec thead th {
  text-align: left; font-weight: 500; font-size: 0.78125rem;
  color: var(--v-text-faint);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--v-line-strong);
  white-space: nowrap;
}
.spec tbody td { padding: var(--sp-3) var(--sp-4); vertical-align: baseline; }
/* Alternate row tint instead of a hairline under every row. */
.spec tbody tr:nth-child(even) { background: var(--v-surface-2); }
.spec .num {
  text-align: right; font-family: var(--v-font-mono); white-space: nowrap;
}
.spec .unit { color: var(--v-text-faint); font-size: 0.78125rem; }
.band-light .spec thead th { border-color: var(--v-light-line); color: var(--v-light-muted); }
.band-light .spec tbody tr:nth-child(even) { background: rgba(20, 23, 26, 0.04); }

/* ---------- Trust band ---------- */
.trust {
  display: grid; gap: 0;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  border: 1px solid var(--v-line); border-radius: var(--r-lg);
  overflow: hidden;
}
.trust > * {
  padding: var(--sp-6);
  border-right: 1px solid var(--v-line);
  display: flex; flex-direction: column; gap: var(--sp-2);
  transition: background-color var(--d-micro) var(--ease-out);
}
.trust > *:last-child { border-right: none; }
.trust a:hover { background: var(--v-surface); }
.trust h2, .trust h3 { font-size: 1rem; font-weight: 600; letter-spacing: 0; }
.trust p { font-size: 0.875rem; color: var(--v-text-muted); }

/* ---------- Steps (a real sequence, so numbers earn their place) ---------- */
.steps { counter-reset: step; display: grid; gap: var(--sp-8); }
.steps-3 { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.step { counter-increment: step; padding-top: var(--sp-5); border-top: 1px solid var(--v-light-line); }
.step::before {
  content: counter(step, decimal-leading-zero);
  display: block; font-family: var(--v-font-mono); font-size: 0.875rem;
  color: var(--v-light-muted); margin-bottom: var(--sp-3);
}
.step h3 { font-size: 1.1875rem; font-weight: 600; margin-bottom: var(--sp-2); }
.step p { font-size: 0.9375rem; color: var(--v-light-muted); }

/* ---------- FAQ ---------- */
.faq { border-top: 1px solid var(--v-line); }
.faq details { border-bottom: 1px solid var(--v-line); }
.faq summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-4);
  min-height: 44px; padding-block: var(--sp-4);
  font-size: 1.0625rem; font-weight: 500; cursor: pointer;
  list-style: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; flex-shrink: 0;
  width: 9px; height: 9px;
  border-right: 1.5px solid var(--v-text-faint);
  border-bottom: 1.5px solid var(--v-text-faint);
  transform: rotate(45deg);
  transition: transform var(--d-base) var(--ease-out);
}
.faq details[open] summary::after { transform: rotate(225deg); }
.faq .faq-body { padding-bottom: var(--sp-5); color: var(--v-text-muted); max-width: 68ch; }

/* ---------- Forms ---------- */
.field { display: flex; flex-direction: column; gap: var(--sp-2); }
.field label { font-size: 0.875rem; font-weight: 500; }
.field .hint { font-size: 0.78125rem; color: var(--v-text-faint); }
.field .err { font-size: 0.8125rem; color: var(--v-danger); }
.input, .select, .textarea {
  min-height: 44px; padding: var(--sp-3) var(--sp-4);
  background: var(--v-surface); color: var(--v-text);
  border: 1px solid var(--v-line-strong); border-radius: var(--r-sm);
  transition: border-color var(--d-micro) var(--ease-out);
  width: 100%;
}
.textarea { min-height: 120px; padding-block: var(--sp-3); resize: vertical; }
.input::placeholder, .textarea::placeholder { color: var(--v-text-faint); }
.input:hover, .select:hover, .textarea:hover { border-color: var(--v-text-faint); }
.input[aria-invalid="true"] { border-color: var(--v-danger); }

/* ---------- Footer ---------- */
.site-footer {
  border-top: 1px solid var(--v-line);
  padding-block: var(--sp-16) var(--sp-8);
  margin-top: var(--v-section-y);
}
.footer-grid {
  display: grid; gap: var(--sp-10);
  grid-template-columns: minmax(0, 1.4fr) repeat(auto-fit, minmax(140px, 1fr));
  margin-bottom: var(--sp-12);
}
/* Footer column labels are navigation labels, not document headings, so they
   are <p> now: an <h4> after the page's <h2>s failed heading-order checks. */
.footer-grid .footer-label {
  font-size: 0.78125rem; font-weight: 500; color: var(--v-text-faint);
  margin-bottom: var(--sp-4);
  letter-spacing: 0.08em; text-transform: uppercase;
}
.footer-grid li + li { margin-top: var(--sp-3); }
.footer-grid a { font-size: 0.9375rem; color: var(--v-text-muted); }
.footer-grid a:hover { color: var(--v-text); }
.footer-legal {
  border-top: 1px solid var(--v-line); padding-top: var(--sp-6);
  display: flex; justify-content: space-between; gap: var(--sp-4); flex-wrap: wrap;
}
.footer-legal p { font-size: 0.78125rem; color: var(--v-text-faint); max-width: 62ch; }

/* ---------- Utility ---------- */
.skip-link {
  position: absolute; left: var(--sp-4); top: -100px;
  background: var(--v-accent-deep); color: var(--v-text);
  padding: var(--sp-3) var(--sp-4); border-radius: var(--r-sm);
  z-index: var(--z-toast);
  transition: top var(--d-micro) var(--ease-out);
}
.skip-link:focus { top: var(--sp-4); }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0;
  margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.divider { height: 1px; background: var(--v-line); border: none; }

/* Price is withheld until the catalogue is finalised. */
.price-tbd { font-family: var(--v-font-mono); font-size: 0.875rem; color: var(--v-text-faint); }

/* ---------- Hero side panel ----------
   Used instead of an empty image placeholder: states what ships with an order. */
.ship-panel {
  border: 1px solid var(--v-line);
  border-radius: var(--r-lg);
  background: var(--v-surface);
  padding: var(--sp-6);
}
.ship-panel > h2 { margin-bottom: var(--sp-2); }
.ship-panel ul { margin-block: var(--sp-4); }
.ship-panel li {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--sp-4);
  padding-block: var(--sp-3);
  border-bottom: 1px solid var(--v-line);
  font-size: 0.9375rem;
}
.ship-panel li:last-child { border-bottom: none; }
.ship-panel li > span:first-child { color: var(--v-text-muted); }
.ship-panel .mono { font-size: 0.8125rem; white-space: nowrap; }

/* ---------- Page header ----------
   pageHead sits directly above another .section, so it owns only its top
   padding. Without this the two section paddings plus the sec-head margin
   stacked into a large dead gap under every page title. */
.page-head { padding-top: var(--v-section-y); }
.page-head .sec-head p { margin-top: var(--sp-4); }
.section-tight { padding-top: var(--sp-10); }

/* Card footer: keep the price and stock labels on one line each. At the
   narrowest grid column they were wrapping mid-phrase. */
.pcard-foot { flex-wrap: wrap; gap: var(--sp-2) var(--sp-3); }
.pcard-foot .price-tbd,
.pcard-foot .stock-in,
.pcard-foot .stock-out { white-space: nowrap; }
.pcard-foot .price-tbd { font-size: 0.8125rem; }

/* ==========================================================================
   Motion and polish
   Transform and opacity only. Nothing over 300ms. Reduced motion respected
   in the block at the end of tokens.css and again explicitly below.
   ========================================================================== */

/* ---------- Scroll reveals ---------- */
[data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition:
    opacity var(--d-slow) var(--ease-out),
    transform var(--d-slow) var(--ease-out);
  will-change: opacity, transform;
}
[data-reveal].is-revealed {
  opacity: 1;
  transform: none;
}
/* Once revealed, drop the hint so it never blocks later compositing. */
[data-reveal].is-revealed { will-change: auto; }

/* ---------- Header state ---------- */
.site-header {
  transition:
    background-color var(--d-base) var(--ease-out),
    border-color var(--d-base) var(--ease-out);
}
.site-header.is-scrolled {
  background: rgba(5, 5, 5, 0.97);
  border-bottom-color: var(--v-line-strong);
}

/* ---------- Nav underline that grows from the left ---------- */
.nav-main a {
  position: relative;
}
.nav-main a::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: var(--v-accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--d-base) var(--ease-out);
}
.nav-main a:hover::after,
.nav-main a[aria-current="page"]::after { transform: scaleX(1); }

/* ---------- Product cards ---------- */
.pcard {
  will-change: transform;
}
.pcard-media {
  overflow: hidden;
}
.pcard-media > * {
  transition: transform var(--d-slow) var(--ease-out);
}
.pcard:hover .pcard-media > * { transform: scale(1.03); }
.pcard:hover { border-color: var(--v-accent); }
/* Product name picks up the accent on hover, so the whole card reads as a link. */
.pcard h2 { transition: color var(--d-micro) var(--ease-out); }
.pcard:hover h2 { color: var(--v-accent); }

/* ---------- Trust band ---------- */
.trust > a { position: relative; }
.trust > a::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 2px;
  background: var(--v-accent);
  transform: scaleY(0);
  transform-origin: top;
  transition: transform var(--d-base) var(--ease-out);
}
.trust > a:hover::before { transform: scaleY(1); }
/* Was h4, which no trust block has ever rendered, so the colour change below
   landed with no transition at all. */
.trust > a h2, .trust > a h3 { transition: color var(--d-micro) var(--ease-out); }
.trust > a:hover h2, .trust > a:hover h3 { color: var(--v-accent); }

/* ---------- FAQ ---------- */
.faq summary { transition: color var(--d-micro) var(--ease-out); }
.faq summary:hover { color: var(--v-accent); }
.faq details[open] summary { color: var(--v-accent); }
/* Animate the answer open via grid rows; height is not animatable. */
.faq .faq-body {
  display: grid;
  grid-template-rows: 1fr;
  animation: faq-open var(--d-base) var(--ease-out);
}
@keyframes faq-open {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}

/* ---------- Steps ---------- */
.step { transition: border-color var(--d-base) var(--ease-out); }
.step:hover { border-top-color: var(--v-accent); }

/* ---------- Spec table rows ---------- */
.spec tbody tr { transition: background-color var(--d-micro) var(--ease-out); }
.spec tbody tr:hover { background: var(--v-accent-wash); }

/* ---------- Ship panel rows ---------- */
.ship-panel li { transition: color var(--d-micro) var(--ease-out); }

/* ---------- Buttons: accent ring on focus, subtle lift on hover ---------- */
.btn-primary { box-shadow: 0 0 0 0 var(--v-accent-wash); transition-property: background-color, transform, box-shadow; }
.btn-primary:hover { box-shadow: 0 0 0 4px var(--v-accent-wash); }

/* ---------- Inputs ---------- */
.input, .select, .textarea {
  transition: border-color var(--d-micro) var(--ease-out),
              box-shadow var(--d-micro) var(--ease-out);
}
.input:focus, .select:focus, .textarea:focus {
  border-color: var(--v-accent);
}

/* ---------- Reduced motion: strip movement, keep legibility ---------- */
@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  .pcard:hover .pcard-media > * { transform: none; }
  .nav-main a::after { transition: none; }
  .faq .faq-body { animation: none; }
}

/* ---------- Glossary ---------- */
.glossary { display: grid; gap: 0; }
.gloss-row {
  display: grid;
  grid-template-columns: minmax(140px, 220px) 1fr;
  gap: var(--sp-6);
  padding-block: var(--sp-5);
  border-bottom: 1px solid var(--v-line);
}
.gloss-row dt { font-weight: 500; color: var(--v-text); }
.gloss-row dd { color: var(--v-text-muted); font-size: 0.9375rem; }
@media (max-width: 640px) {
  .gloss-row { grid-template-columns: 1fr; gap: var(--sp-2); }
}

/* ---------- Checkout ----------
   Form beside an order summary on desktop, stacked on narrow screens with the
   summary first so the buyer sees the total before the fields. */
.checkout-grid {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  gap: var(--sp-7);
  align-items: start;
}
@media (max-width: 860px) {
  .checkout-grid { grid-template-columns: 1fr; gap: var(--sp-5); }
  .checkout-grid > aside { order: -1; }
}
/* 44px minimum, the same rule the rest of the site holds itself to. A form field
   is the one place a short target costs an order rather than a click. */
.checkout-grid input,
.checkout-grid select { min-height: 44px; }

/* ---------- Touch targets ----------
   btn-sm is 36px, which is fine for a mouse but under the 44px minimum for
   touch. On pointer-coarse devices the header utilities get the full height. */
@media (pointer: coarse) {
  .btn-sm { min-height: 44px; }
}

/* The header carried three buttons next to the wordmark. At 900px and below the
   drawer already owns navigation, and Account, Cart and Menu together measured
   251px against a 320px viewport: every page scrolled sideways on a small
   phone. Account moves into the drawer, where the rest of the navigation
   already lives, and the two remaining gaps tighten. */
@media (max-width: 900px) {
  .nav-util .btn-sm { min-height: 44px; }
  .site-header .wrap { gap: var(--sp-4); }
  .nav-util { gap: var(--sp-2); }
  .nav-util .btn-account { display: none; }
  .nav-main .nav-account { display: block; }
}
.nav-main .nav-account { display: none; }

/* The wordmark is a link in a 72px header but its box was only the 27px of its
   own text. Stretching it to the header height costs nothing visually and gives
   the most-tapped link in the site a real target. */
.site-header .wordmark {
  display: flex; align-items: center; align-self: stretch;
}

/* Footer links sat at 19px tall, under the 24px minimum in WCAG 2.5.8. The
   wordmark down there is a standalone link too, so it gets the same treatment;
   the inline links inside sentences are exempt and are left alone. */
.site-footer li a {
  display: inline-block;
  padding-block: 4px;
}
.site-footer .wordmark {
  display: inline-block;
  padding-block: 6px;
}

/* Reduced motion: cancel the effects that move distance. The transition itself
   stays short rather than zero, so hover still acknowledges the pointer. */
@media (prefers-reduced-motion: reduce) {
  .pcard:hover { transform: none; }
  .pcard:hover .pcard-media > * { transform: none; }
}

/* ---------- Narrow content ----------
   These sections used a centred 680-820px wrap, which pushed the content into
   the middle of the page while the page heading stayed on the gutter. The outer
   wrap now matches every other section so the left edges line up, and the
   measure is constrained on the children instead. */
.wrap-measure > * { max-width: 820px; }
.wrap-measure > .faq,
.wrap-measure > .glossary,
.wrap-measure > form { max-width: 820px; }

/* ==========================================================================
   Align-matched section rhythm and light product cards
   Align alternates aggressively: dark hero, WHITE product grid, #0a0a0a
   documentation, #050505, then #f9f9f9. Their product cards on white are
   borderless with no radius, background or shadow: image, title, price.
   ========================================================================== */

/* Pure white band, as Align uses behind the product grid. */
.band-white {
  background: #ffffff;
  color: #111111;
}
.band-white .sec-head p,
.band-white .muted,
.band-white .lead { color: rgba(17, 17, 17, 0.68); }
/* 0.45 measured 3.03:1 on white and failed. 0.62 measures 5.2:1. */
.band-white .faint { color: rgba(17, 17, 17, 0.62); }
.band-white h1, .band-white h2, .band-white h3, .band-white h4 { color: #111111; }
/* Eyebrows go to the deeper lime so they hold contrast on white. */
.band-white .eyebrow { color: var(--v-accent-deep); }
.band-white .btn-secondary { border-color: rgba(17, 17, 17, 0.22); color: #111111; }
.band-white .btn-secondary:hover { background: rgba(17, 17, 17, 0.05); border-color: #111111; }
.band-white .divider { background: rgba(17, 17, 17, 0.12); }

/* Slightly raised dark band, Align's #0a0a0a. */
.band-deep { background: #0A0A0A; }

/* ---------- Product cards on a light band: borderless, as Align ---------- */
.band-white .pcard,
.band-light .pcard {
  background: transparent;
  border: none;
  border-radius: 0;
  box-shadow: none;
}
.band-white .pcard:hover,
.band-light .pcard:hover {
  transform: translateY(-2px);
  border: none;
}
.band-white .pcard-media,
.band-light .pcard-media {
  background: #F4F4F2;
  border-bottom: none;
  border-radius: 0;
}
/* Placeholder label sits on #F4F4F2, so it needs its own value: 0.5 measured
   3.49:1 there, 0.65 measures 5.7:1. */
.band-white .pcard-media .faint,
.band-light .pcard-media .faint { color: rgba(17, 17, 17, 0.65); }
.band-white .pcard-body,
.band-light .pcard-body {
  padding: var(--sp-4) 0 0;
}
.band-white .pcard-body h2,
.band-light .pcard-body h2 {
  font-size: 0.9375rem;
  font-weight: 600;
  color: #111111;
  letter-spacing: 0;
}
.band-white .pcard:hover h2,
.band-light .pcard:hover h2 { color: var(--v-accent-deep); }
/* 0.5 measured 3.54:1 on white. 0.62 measures 5.2:1. */
.band-white .pcard-spec,
.band-light .pcard-spec { color: rgba(17, 17, 17, 0.62); }
.band-white .pcard-price,
.band-white .price-tbd,
.band-light .price-tbd {
  font-size: 0.9375rem; font-weight: 600; color: #111111;
  font-family: var(--v-font);
}
.band-white .stock-in { color: var(--v-accent-deep); }
.band-white .stock-out { color: rgba(17, 17, 17, 0.62); }
.band-white .pcard-foot { padding-top: var(--sp-2); }

/* Trust band on white */
.band-white .trust { border-color: rgba(17, 17, 17, 0.14); }
.band-white .trust > * { border-right-color: rgba(17, 17, 17, 0.14); }
.band-white .trust a:hover { background: rgba(17, 17, 17, 0.03); }
.band-white .trust > a:hover h2,
.band-white .trust > a:hover h3 { color: var(--v-accent-deep); }

/* Spec table on white */
.band-white .spec thead th { border-color: rgba(17, 17, 17, 0.22); color: rgba(17, 17, 17, 0.68); }
.band-white .spec tbody tr:nth-child(even) { background: rgba(17, 17, 17, 0.03); }
.band-white .spec tbody tr:hover { background: rgba(132, 204, 22, 0.10); }
.band-white .spec .unit { color: rgba(17, 17, 17, 0.62); }

/* FAQ on white */
.band-white .faq, .band-white .faq details { border-color: rgba(17, 17, 17, 0.14); }
.band-white .faq summary { color: #111111; }
.band-white .faq summary::after { border-color: rgba(17, 17, 17, 0.45); }
.band-white .faq .faq-body { color: rgba(17, 17, 17, 0.75); }
.band-white .faq summary:hover,
.band-white .faq details[open] summary { color: var(--v-accent-deep); }

/* Links on white */
.band-white .link-accent { color: #111111; text-decoration-color: rgba(17, 17, 17, 0.4); }
.band-white .link-accent:hover { text-decoration-color: #111111; }
.band-white .prose { color: rgba(17, 17, 17, 0.75); }
.band-white .prose h2, .band-white .prose h3 { color: #111111; }
.band-white .prose a { color: #111111; }
.band-white .prose strong { color: #111111; }

/* ---------- Announcement bar, with Align's lime underline ---------- */
.notice-bar {
  border-bottom: 1px solid rgba(132, 204, 22, 0.32);
}
.notice-bar p {
  font-size: 0.7rem; font-weight: 500;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--v-text-muted);
}
.notice-bar .sep { color: var(--v-accent); margin-inline: var(--sp-2); }

/* Uniform product grid, as Align. The spanning feature card broke row alignment
   once cards went borderless, and Align does not use one. */
.pcard-feature { grid-column: auto; }
.pcard-feature .pcard-media { aspect-ratio: 1; }

/* Cards stretch to equal height per row, and the foot pins to the bottom via
   its margin-top:auto, so prices line up across a row even when a descriptor
   wraps to two lines. `align-items: start` sized each card to its own content,
   which is what knocked the prices out of line. */
.grid-auto { align-items: stretch; }
.pcard { height: 100%; }
.pcard-body { display: flex; flex-direction: column; flex: 1; }
/* Reserve two lines for the descriptor so single-line cards do not sit short. */
.pcard-spec { min-height: 2.6em; }

/* ---------- Browser surfaces ----------
   The parts nobody draws still ship with defaults belonging to no design
   system: the selection highlight, the caret, the scrollbar, the focus ring. On
   a near-black canvas the browser's own focus outline is close to invisible, so
   this is an accessibility fix as much as a craft one. */

::selection { background: var(--v-accent); color: var(--v-accent-on); }
.band-white ::selection,
.band-light ::selection { background: var(--v-accent-deep); color: #fff; }

/* The caret is the one piece of UI a buyer stares straight at while typing an
   address. The default is invisible on a dark field. */
.input, .select, .textarea { caret-color: var(--v-accent); }

/* :focus-visible only, so a mouse click leaves no ring but every tab stop is
   unmistakable. The offset keeps it clear of the element's own border. */
:focus-visible { outline: 2px solid var(--v-accent); outline-offset: 3px; border-radius: 2px; }
.band-white :focus-visible,
.band-light :focus-visible { outline-color: var(--v-accent-deep); }

/* Firefox takes the two-value standard, WebKit needs the pseudo elements. Both
   read the same tokens so they cannot drift apart. */
* { scrollbar-color: var(--v-line-strong) transparent; scrollbar-width: thin; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--v-line-strong); border-radius: 99px; border: 3px solid var(--v-bg);
}
::-webkit-scrollbar-thumb:hover { background: var(--v-text-faint); }

/* Numerals in data. Prices, quantities, molecular weights and lot numbers are
   read down a column; proportional digits leave that column ragged. */
.mono, .pcard-price, .price, .price-tbd, .cart-count, .num,
td.num, .spec-table td, input[type="number"] {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* ---------- Media band ----------
   A photograph or a short loop used as a rule between two blocks of text. Fixed
   height so it cannot shift layout while loading, and clipped short: a
   full-height motion panel would read as a second hero and compete with the
   real one. */
.band-media, .band-image {
  position: relative;
  overflow: hidden;
  height: clamp(180px, 26vw, 340px);
  background: var(--v-surface-2);
}
.band-media__video, .band-image img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}

/* One treatment layer over all media, so a photo and a video from different
   sources still read as one system. The gradient ties both edges into the page
   instead of leaving a bright rectangle floating on a near-black canvas. */
.band-media::after, .band-image::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(to bottom, var(--v-bg) 0%, transparent 24%, transparent 76%, var(--v-bg) 100%);
  pointer-events: none;
}

/* Motion is decorative here, so it goes away entirely when it is not wanted.
   The poster frame still shows: the content is the lab, not the movement. */
@media (prefers-reduced-motion: reduce) {
  .band-media__video { display: none; }
  .band-media {
    background-image: url("/assets/img/stock/lab-poster.jpg");
    background-size: cover;
    background-position: center;
  }
}
