/**
 * Velonix Labs — Shared Components
 * Loaded on every page, after tokens.css. Everything in this file is a
 * genuinely reusable component — not specific to the homepage or the
 * catalogue. If a future page needs something that looks close to one of
 * these, EXTEND it (a modifier class, a scoped override) rather than
 * inventing a new pattern. See design-rules §9.
 */

/* ===== section layout primitives — used on every page ===== */
.section{padding:var(--section-padding-desktop) 0;}
/* Mobile section padding — these two tokens (tokens.css) existed since
   the original build but were never actually wired to anything; .section
   had zero responsive behaviour at all until now. Desktop value
   (--section-padding-desktop, 112px) is completely untouched — this only
   adds tablet/mobile downsizing using tokens that were already there. */
@media (max-width:1023px){ .section{padding:var(--section-padding-tablet) 0;} }
@media (max-width:767px){ .section{padding:var(--section-padding-mobile) 0;} }

/* Reusable section-top-spacing utilities, for the handful of sections
   across the site that need a specific desktop padding-top different
   from .section's own default (About's narrative beats continuing
   from the hero, single-product's opening section) — previously
   inline `style="padding-top:NNpx;"` on each, which (like the hero
   padding problem above) can never respond to a mobile media query,
   since an inline style always wins over anything external regardless
   of viewport. These values repeat across more than one page (72px:
   About x2; 96px: About + single-product), so real reusable classes,
   not one-off inline styles. */
.section-top-56{ padding-top:56px; }
.section-top-72{ padding-top:72px; }
.section-top-96{ padding-top:96px; }
@media (max-width:767px){
  .section-top-56, .section-top-72, .section-top-96{ padding-top:var(--section-padding-mobile); }
}
.section-alt{background:var(--bg-2);}
.section-head{max-width:600px; margin-bottom:64px;}

/* ===== registration-mark crosshair — a subtle corner device that visually
   echoes the logo's own crosshair icon. Deliberately scoped to appear only
   on the Certificate of Analysis card, where it earns its place as part of
   the "document" metaphor — hidden everywhere else it might get added by
   mistake (trust cards, CTA panels, etc). ===== */
.reg-mark{position:absolute; top:16px; right:16px; opacity:0.35; color:var(--ink-faint); pointer-events:none; z-index:2;}
.reg-mark svg{width:var(--icon-sm); height:var(--icon-sm);}
.trust-card .reg-mark, .cta-band .reg-mark{display:none;}

/* ===== identity tags — small dot-marker label row, used under the
   "who we are" intro copy ===== */
.identity-tags{display:flex; flex-wrap:wrap; gap:28px; padding-top:8px;}
.identity-tags span{font-family:'IBM Plex Mono',monospace; font-size:12px; color:var(--ink-faint); position:relative; padding-left:14px;}
.identity-tags span::before{content:''; position:absolute; left:0; top:50%; transform:translateY(-50%); width:5px; height:5px; border-radius:50%; background:var(--accent); opacity:0.5;}

/* ===== eyebrow label (used above every section/page heading) ===== */
.eyebrow{font-size:12px; font-weight:600; letter-spacing:0.05em; color:var(--accent); margin-bottom:20px; display:flex; align-items:center; gap:9px;}
.eyebrow::before{content:''; width:6px; height:6px; border-radius:50%; background:var(--accent); display:inline-block; flex-shrink:0;}

/* ===== buttons — exactly three variants, no exceptions (design-rules §9.5) ===== */
.btn{display:inline-flex; align-items:center; justify-content:center; gap:8px; font-family:'Plus Jakarta Sans',sans-serif; font-weight:600; font-size:14px; border-radius:var(--radius); cursor:pointer; border:1px solid transparent; white-space:nowrap; transition:background-color 0.18s ease, border-color 0.18s ease, color 0.18s ease, opacity 0.18s ease;}
.btn-primary{background:var(--accent); color:#0D1017; padding:13px 26px;}
.btn-primary:hover{background:#6E94EA;}
.btn-secondary{background:transparent; color:var(--ink); border:1px solid var(--line); padding:12px 25px;}
.btn-secondary:hover{border-color:var(--accent); color:var(--accent);}
.btn-ghost{background:transparent; color:var(--accent); padding:8px 0; font-weight:500; transition:opacity 0.18s ease;}
.btn-ghost:hover{opacity:0.75;}
.btn-sm{padding:9px 18px; font-size:13px;}

/* ===== compact page intro — title only, no breadcrumb (Research Catalogue and any generic content page use this) ===== */
/* breadcrumb component removed sitewide — every page now opens with its
   own custom introduction instead of a breadcrumb/default-title banner.
   See page-intro below for what replaced it. */

.page-intro{padding:64px 0 40px;}
.page-intro h1{font-size:34px; font-weight:600; letter-spacing:-0.015em; margin-bottom:0; font-family:'Plus Jakarta Sans',sans-serif;}
.legal-updated{font-family:'IBM Plex Mono',monospace; font-size:13px; color:var(--ink-faint); margin-top:16px;}
@media (max-width:767px){
  .page-intro{padding:32px 0 24px;}
  .page-intro h1{font-size:26px;}
}

/* ===== .prose — automatic styling for long-form WordPress editor
   content (Legal & Policy pages, and the generic page fallback in
   index.php). Covers every standard element the editor can produce:
   headings, paragraphs, lists, links, tables, blockquotes,
   strong/emphasis, horizontal rules. Reuses existing colour and radius
   tokens throughout — nothing here is a one-off value. Content authors
   never need to add custom HTML/classes; every element is styled by
   tag, matching whatever the WordPress editor outputs natively. ===== */
.prose{max-width:720px; font-size:16px; color:var(--ink-soft); line-height:1.8;}

.prose h1, .prose h2, .prose h3, .prose h4, .prose h5, .prose h6{
  font-family:'Plus Jakarta Sans',sans-serif; font-weight:600; color:var(--ink);
  line-height:1.3; margin-top:48px; margin-bottom:16px;
}
.prose > *:first-child{margin-top:0;}
.prose h1{font-size:28px;}
.prose h2{font-size:24px;}
.prose h3{font-size:20px;}
.prose h4{font-size:17px;}
.prose h5{font-size:15px;}
.prose h6{font-size:14px; text-transform:uppercase; letter-spacing:0.03em; color:var(--ink-soft);}

.prose p{margin-bottom:24px;}
.prose p:last-child{margin-bottom:0;}

.prose ul, .prose ol{margin:0 0 24px; padding-left:22px;}
.prose li{margin-bottom:8px;}
.prose li::marker{color:var(--accent);}
.prose ul ul, .prose ul ol, .prose ol ul, .prose ol ol{margin-top:8px; margin-bottom:0;}

.prose a{color:var(--accent); text-decoration:underline; text-underline-offset:2px; transition:opacity 0.18s ease;}
.prose a:hover{opacity:0.75;}

.prose strong{color:var(--ink); font-weight:600;}
.prose em{font-style:italic;}

.prose blockquote{margin:0 0 24px; padding:2px 0 2px 24px; border-left:2px solid var(--accent); color:var(--ink-soft); font-style:italic;}
.prose blockquote p:last-child{margin-bottom:0;}

.prose hr{border:none; border-top:1px solid var(--line); margin:48px 0;}

.prose table{width:100%; border-collapse:collapse; margin:0 0 32px; font-size:14px;}
.prose th{text-align:left; font-family:'Plus Jakarta Sans',sans-serif; font-weight:600; color:var(--ink); padding:12px 16px; border-bottom:1px solid var(--line); background:var(--surface);}
.prose td{padding:12px 16px; border-bottom:1px solid var(--line);}
.prose tr:last-child td{border-bottom:none;}

.prose img{max-width:100%; height:auto; border-radius:var(--radius); margin:8px 0 24px; display:block;}

@media (max-width:767px){
  .prose table{display:block; overflow-x:auto; white-space:nowrap;}
}

/* ===== trust card grid (currently homepage only, but the pattern — 3-up icon/heading/body — is fair game to reuse anywhere a short credibility statement is needed) ===== */
.grid-3{display:grid; grid-template-columns:repeat(3,1fr); gap:28px;}
@media (max-width:1023px){ .grid-3{grid-template-columns:repeat(2,1fr); gap:20px;} }
@media (max-width:767px){ .grid-3{grid-template-columns:1fr; gap:16px;} }
.trust-card{position:relative; background:var(--surface); border:1px solid var(--line); border-radius:var(--radius); padding:34px 30px; transition:border-color 0.2s ease, transform 0.2s ease;}
.trust-card:hover{border-color:var(--accent); transform:translateY(-2px);}
/* ===== hero — promoted from page-home.css. Used by front-page.php
   (two-column, with .hero-grid/.hero-visual/.hero-photo) AND
   page-about.php (single column, typography only) AND
   single-product.php (.hero-grid/.hero-visual/.hero-photo for the
   product image, without the .hero section wrapper itself). Genuinely
   shared — must not live in a page-scoped stylesheet.

   Same typography/spacing/tokens everywhere — alignment is controlled
   entirely by the Utility Layout block further down (body.layout-utility),
   not by a per-hero modifier class. Editorial pages (Home, About,
   Product) get no body class and stay exactly as they've always been:
   left-aligned, .hero-content simply naming the max-width:600px wrapper
   these pages already used inline. ===== */
.hero{padding:112px 0 104px; position:relative; overflow:hidden;}
@media (max-width:1023px){ .hero{padding:64px 0 56px;} }
@media (max-width:767px){ .hero{padding:40px 0 40px;} }
.hero-content{max-width:600px;}
.hero-grid{display:grid; grid-template-columns:1.05fr 0.95fr; gap:72px; align-items:center;}
@media (max-width:1023px){ .hero-grid{grid-template-columns:1fr; gap:40px;} }
h1.hero-h{font-size:52px; line-height:1.14; letter-spacing:-0.015em; font-weight:600; margin-bottom:22px;}
@media (max-width:1023px){ h1.hero-h{font-size:36px;} }
@media (max-width:767px){ h1.hero-h{font-size:27px;} }
.hero p.lead{font-size:17px; line-height:1.75; color:var(--ink-soft); max-width:460px; margin-bottom:36px;}
@media (max-width:767px){ .hero p.lead{font-size:15px; max-width:none;} }

.hero-visual{aspect-ratio:4/5; position:relative;}
.hero-photo{position:relative; width:100%; height:100%; border-radius:16px; overflow:hidden; background:radial-gradient(130% 110% at 25% 18%, #1B2230 0%, #0D0F14 68%); box-shadow:inset 0 0 90px rgba(0,0,0,0.55);}
.hero-photo img{width:100%; height:100%; object-fit:cover;}

/* .hero-compact: the exact same desktop padding five pages (About,
   Laboratory Analysis, FAQ, Contact, Peptide Calculator) were already
   setting inline (style="padding:64px 0 56px;") — moved into a real
   class specifically so it can have a real mobile override, which an
   inline style never could regardless of viewport. Desktop value is
   byte-identical to what was already there; only mobile changes. */
.hero-compact{ padding:64px 0 56px; }
@media (max-width:767px){ .hero-compact{ padding:40px 0 32px; } }

/* ===== Utility Layout — reusable layout variant, applied automatically
   via body.layout-utility (see velonix_body_class_utility_layout() in
   inc/theme-setup.php) rather than per-element page overrides. Currently
   active on Laboratory Analysis, FAQ, Contact and Order Tracking.

   Principle throughout: the BLOCK is centred on the page's vertical
   axis — hero, section intro, accordion, card group each sit centred
   as a unit. Body copy WITHIN those blocks (FAQ answers, form labels,
   paragraph text) stays left-aligned; centring running text hurts
   readability and was never what "centred" meant here.

   .section-head and .faq-list are shared components also used
   elsewhere (.section-head e.g. on Laboratory Analysis' own document
   library heading), so centring them is scoped to body.layout-utility
   rather than applied globally — an Editorial page using .section-head
   in the future keeps its normal left-aligned behaviour by default.

   .section-head svg needs its own margin:0 auto rather than relying on
   text-align:center: tokens.css sets a sitewide img,svg{display:block}
   reset (no inline-baseline gap under icons), so text-align never
   affects them — the same reason .empty-state svg already uses
   margin:0 auto 20px elsewhere in this file. Reused here, not a new
   technique. */
body.layout-utility .hero-content{margin:0 auto; text-align:center;}
body.layout-utility .hero .eyebrow{justify-content:center;}
body.layout-utility .hero p.lead{margin-left:auto; margin-right:auto;}

body.layout-utility .section-head{margin-left:auto; margin-right:auto; text-align:center;}
body.layout-utility .section-head .eyebrow{justify-content:center;}
body.layout-utility .section-head svg{margin-left:auto; margin-right:auto;}

body.layout-utility .faq-list{margin-left:auto; margin-right:auto;}

/* ===== quality-grid — promoted from page-home.css. Used by
   front-page.php and page-about.php. ===== */
.quality-grid{display:grid; grid-template-columns:1fr 0.95fr; gap:64px; align-items:start;}
@media (max-width:1023px){ .quality-grid{grid-template-columns:1fr; gap:40px;} }
.quality-copy p{font-size:15px; color:var(--ink-soft); line-height:1.8; margin-bottom:28px; max-width:480px;}

/* ===== why-grid / why-list — promoted from page-home.css. Used by
   front-page.php and page-about.php. This is also the exact rule whose
   absence caused the oversized-icon bug: .why-item svg was defined here
   all along, but this file wasn't loaded on the About page at all. ===== */
.why-grid{display:grid; grid-template-columns:0.85fr 1.15fr; gap:64px; align-items:center;}
@media (max-width:1023px){ .why-grid{grid-template-columns:1fr; gap:32px;} }
.why-copy p{font-size:16px; color:var(--ink-soft); line-height:1.8; max-width:420px;}
.why-list{display:flex; flex-direction:column;}
.why-item{position:relative; display:flex; align-items:flex-start; gap:18px; padding:26px 0;}
.why-item:hover svg{color:#7C9EE8;}
.why-item svg{width:var(--icon-lg); height:var(--icon-lg); color:var(--accent); flex-shrink:0; margin-top:2px; transition:color 0.2s ease;}
.why-item h4{font-size:15px; font-weight:600; margin-bottom:6px;}

.trust-icon{width:var(--icon-xl); height:var(--icon-xl); margin-bottom:20px; color:var(--accent);}
.trust-card h3{font-size:16px; font-weight:600; margin-bottom:10px;}
.trust-card p{font-size:var(--text-body-sm); color:var(--ink-soft); line-height:1.7;}

/* ===== trust chips (compact honest quality-assurance statements) ===== */
.trust-chip-row{display:flex; gap:12px; flex-wrap:wrap;}
.trust-chip{display:flex; align-items:center; gap:9px; background:var(--surface); border:1px solid var(--line); border-radius:var(--radius); padding:13px 18px; font-size:13px; color:var(--ink); font-weight:500;}
.trust-chip svg{width:var(--icon-xs); height:var(--icon-xs); color:var(--accent); flex-shrink:0;}

/* ===== specimen-index list — THE reusable product-row pattern.
   Used by: Research Catalogue, and should be reused for related products
   on the Product Detail page, order line-items on the Account pages, and
   any future search-results view. Never rebuild this as a card grid. ===== */
.index-list{border:1px solid var(--line); border-radius:var(--radius); overflow:hidden;}
.index-row{display:flex; align-items:center; gap:24px; padding:24px 28px; border-bottom:1px solid var(--line); position:relative; transition:background-color 0.18s ease;}
.index-row:last-child{border-bottom:none;}
.index-row:hover{background:var(--surface);}
.index-thumb{width:72px; height:72px; border-radius:6px; overflow:hidden; flex-shrink:0; position:relative;}
.index-thumb img{width:100%; height:100%; object-fit:cover;}
/* Quiet placeholder background behind product photography in the index
   thumbnail — shows through on any product without a photo yet uploaded,
   rather than a jarring blank/broken-image box.
   Deliberately contains ONLY the background — position/size/radius/
   overflow all come from .index-thumb. This class used to also set its
   own width/height/border-radius/overflow, which — combined on the same
   element as .index-thumb, at equal CSS specificity, later in the
   cascade — silently overrode .index-thumb's 72×72 sizing with 100%,
   expanding the thumbnail to fill nearly the entire row. That was the
   actual cause of the "enormous product rows" bug seen with real
   WooCommerce data (a short placeholder image in testing never
   triggered it the same way real product photos did). */
.vial-plate{background:linear-gradient(155deg, #1B2028 0%, #14171D 75%);}
.vial-plate .vial-svg{position:absolute; bottom:9%; left:50%; transform:translateX(-50%); width:34%; opacity:0.92;}
.index-thumb .vial-svg{width:46%;}
.index-main{flex:1; min-width:0;}
.index-cat{font-size:11px; text-transform:uppercase; letter-spacing:0.05em; color:var(--ink-soft); font-weight:600; margin-bottom:6px;}
.index-name{font-size:16px; font-weight:600; margin-bottom:6px;}
.index-specs{display:flex; gap:18px; font-family:'IBM Plex Mono',monospace; font-size:12px; color:var(--ink-faint);}
.index-meta{display:flex; align-items:center; gap:32px; flex-shrink:0;}

@media (max-width:767px){
  .index-row{padding:16px 20px; gap:14px; flex-wrap:wrap;}
  .index-thumb{width:52px; height:52px;}
  /* min-width:0 (not a fixed px value) — with a fixed min-width, a
     longer product name forced this whole block onto its own line
     below the thumbnail, while shorter names stayed beside it: the
     same component rendering two different layouts depending on
     content length, not a deliberate design. min-width:0 lets the
     text wrap within its own column instead of pushing the column
     itself to wrap, so thumbnail+name+specs stay grouped together
     consistently regardless of how long the product name is. */
  .index-main{flex:1 1 0%; min-width:0;}
  .index-cat{font-size:10px;}
  .index-name{font-size:14px;}
  .index-specs{font-size:11px; gap:12px; flex-wrap:wrap;}
  /* flex-wrap added specifically because of the new, wider Research
     Pack price display (crossed-out + reduced price, plus the
     percentage label beneath it) — confirmed by measuring a genuine
     52px overflow of .index-link past its row at 390px before this
     fix (the link was being silently clipped by an ancestor, not
     causing a visible page-level scrollbar, which is why the earlier
     zero-horizontal-overflow check alone didn't catch it). An ordinary
     product's short price ("£28.00") never came close to triggering
     this, which is why it was never a problem before. Same underlying
     fix already used once for this exact component (see this theme's
     own HANDOVER.md, Section 12.3) for the same reason: two flex
     children whose combined natural width can exceed the row need
     flex-wrap to drop the second one to its own line rather than
     silently overflowing. */
  .index-meta{flex:1 0 100%; flex-wrap:wrap; justify-content:space-between; gap:8px 16px; padding-left:66px; margin-top:4px;}
}
.index-price{font-family:'IBM Plex Mono',monospace; font-size:14px; color:var(--ink-soft); white-space:nowrap;}
/* Research Pack — same restrained, text-only treatment as
   page-product.css's .pack-saving-label (not duplicated there; this is
   the shared row template's own copy, since content-product-row.php is
   reused across the catalogue, the homepage's "New in store", and the
   Basket's own "New in store" — placed in components.css rather than
   a single page's CSS file for exactly that reason, matching where
   .index-price/.index-link (its immediate neighbours) already live).

   .index-price-group wraps .index-price + .pack-saving-label together
   — .index-meta itself is display:flex (a horizontal row, gap:32px)
   for its own direct children, so without this wrapper the label
   would sit 32px to the right of the price as if it were an unrelated
   third item in that row, not directly grouped under the price the
   way the brief's own example shows (price, then the percentage
   directly beneath it). The wrapper is a plain block, so its two
   children stack vertically by normal flow — no flex/grid needed on
   it at all — while .index-link remains .index-meta's other direct
   flex child, still spaced the original 32px away as before. */
.index-price-group{ display:flex; flex-direction:column; gap:2px; }
.pack-saving-label{
  font-family:'IBM Plex Mono',monospace; font-size:11.5px; color:var(--ink-faint); white-space:nowrap;
}
.index-link{font-size:13px; color:var(--accent); font-weight:500; white-space:nowrap; transition:opacity 0.18s ease;}
.index-link:hover{opacity:0.7;}

/* stock status — text-only, no invented colour-coded severity system */
/* Targets WooCommerce's own wc_get_stock_html() output directly
   (a <p class="stock in-stock|out-of-stock|available-on-backorder">) —
   used as-is rather than wrapped in an extra element, since wrapping a
   block-level <p> inside an inline <span> is invalid HTML. Flexbox
   "blockifies" any direct child regardless of its own display type, so
   the <p> still behaves correctly as a flex item wherever it's used
   (.index-specs, .product-stock-row). */
.stock{font-size:12px; font-family:'IBM Plex Mono',monospace; color:var(--ink-soft); margin:0;}
.stock.out-of-stock{color:var(--ink-faint);}
.stock.low-stock{color:var(--ink-soft);}

/* ===== pagination — reused by the Catalogue now, and by Account > Orders later ===== */
.pagination{display:flex; align-items:center; justify-content:center; gap:4px; margin-top:48px;}
.page-btn{display:inline-flex; align-items:center; justify-content:center; width:36px; height:36px; border-radius:var(--radius); border:1px solid transparent; color:var(--ink-faint); font-family:'IBM Plex Mono',monospace; font-size:13px; transition:color 0.18s ease, background-color 0.18s ease;}
.page-btn:hover{color:var(--ink);}
.page-btn.active{background:var(--surface); color:var(--ink); border-color:var(--line);}
.page-arrow{color:var(--ink-soft);}
.page-arrow:hover{color:var(--ink);}
.page-ellipsis{color:var(--ink-faint); font-family:'IBM Plex Mono',monospace; font-size:13px; padding:0 4px;}

/* ===== empty state — reused for "no products found", "no orders yet", "cart is empty" ===== */
.empty-state{border:1px solid var(--line); border-radius:var(--radius); padding:64px 40px; text-align:center;}
.empty-state svg{width:var(--icon-xl); height:var(--icon-xl); color:var(--ink-faint); margin:0 auto 20px;}
.empty-state h3{font-size:18px; font-weight:600; margin-bottom:8px; font-family:'Plus Jakarta Sans',sans-serif;}
.empty-state p{font-size:14px; color:var(--ink-soft); line-height:1.7; max-width:420px; margin:0 auto 24px;}

/* ===== form fields — the ONE input pattern for the whole site (search, filters,
   Order Tracking, and later: checkout fields, account fields). Do not invent
   a second input style. ===== */
.field-label{display:block; font-size:13px; font-weight:600; color:var(--ink); margin-bottom:8px;}
.field-input{width:100%; background:var(--bg); border:1px solid var(--line); border-radius:var(--radius); padding:13px 16px; color:var(--ink); font-family:'Inter',sans-serif; font-size:14px; outline:none; transition:border-color 0.18s ease;}
.field-input::placeholder{color:var(--ink-faint);}
.field-input:focus{border-color:var(--accent);}

/* Lighter-weight borderless field variant — used where a form should feel
   like part of the page rather than a data-entry form (e.g. catalogue
   search/filters). Prefer .field-input for anything transactional
   (checkout, account) where a clearer field boundary is appropriate. */
.field-borderless{background:transparent; border:none; border-bottom:1px solid var(--line); border-radius:0; padding:8px 0;}
.field-borderless:focus{border-color:var(--accent);}

/* ===== CTA band — one closing call-to-action panel, reusable on any page ===== */
.cta-band{position:relative; background:var(--surface); border:1px solid var(--line); border-radius:var(--radius-lg); padding:64px 56px; text-align:center;}
.cta-band h2{margin-bottom:12px;}
.cta-band p{font-size:15px; color:var(--ink-soft); margin-bottom:32px;}

/* ===== Certificate of Analysis card — reused as-is on the Product Detail page ===== */
.coa{position:relative; background:var(--surface); border:1px solid var(--line); border-radius:var(--radius); overflow:hidden;}
.coa-mast{display:flex; align-items:center; justify-content:space-between; padding:22px 26px; border-bottom:1px solid var(--line);}
.coa-mast-brand{font-family:'Plus Jakarta Sans',sans-serif; font-weight:600; font-size:14px;}
.coa-mast-brand img.custom-logo, .coa-mast-brand img{height:var(--coa-logo-height-desktop); width:auto; max-width:none; display:block;}
@media (max-width:767px){ .coa-mast-brand img{height:var(--coa-logo-height-mobile);} }
.coa-body{padding:26px;}
.coa-title{font-family:'Plus Jakarta Sans',sans-serif; font-size:18px; font-weight:600; margin-bottom:6px;}
.coa-sub{font-size:13px; color:var(--ink-soft); line-height:1.6; margin-bottom:22px;}
.coa-rows{margin-bottom:24px;}
.coa-row{display:flex; justify-content:space-between; padding:11px 0; border-bottom:1px solid var(--line); font-size:13px;}
.coa-row .k{color:var(--ink-faint);}
.coa-row .v{font-family:'IBM Plex Mono',monospace; color:var(--ink-soft);}
.coa-action{margin-top:4px;}

/* ===== research-use disclaimer banner — reused above the footer on every page ===== */
.research-notice{padding:64px 0; text-align:center;}
@media (max-width:767px){ .research-notice{padding:40px 0;} }
.research-notice .wrap{max-width:720px; margin:0 auto;}
.research-notice .eyebrow{justify-content:center;}
.research-notice p{font-size:var(--text-body-sm); color:var(--ink-soft); line-height:1.8; max-width:560px; margin:0 auto;}

/* About's own .research-notice instance used an inline
   style="padding:80px 0;" override — same inline-blocks-media-query
   problem as the hero/section cases above. This is the only page that
   needs a different value from the sitewide default, so its own
   scoped class rather than a shared name that would misleadingly
   suggest other pages use it too. */
.research-notice-wide{ padding:80px 0; }
@media (max-width:767px){ .research-notice-wide{ padding:40px 0; } }

/* ===== FAQ accordion — native <details>/<summary>, no JS required and
   accessible by default (keyboard + screen reader support come from the
   browser, not custom ARIA wiring). Reusable anywhere a Q&A list is
   needed, not specific to Laboratory Analysis. ===== */
.faq-list{max-width:760px;}
.faq-item{border-bottom:1px solid var(--line);}
.faq-item:first-child{border-top:1px solid var(--line);}
.faq-item summary{
  display:flex; align-items:center; justify-content:space-between; gap:24px;
  padding:22px 0; font-family:'Plus Jakarta Sans',sans-serif; font-weight:600; font-size:15px; color:var(--ink);
  cursor:pointer; list-style:none;
}
.faq-item summary::-webkit-details-marker{display:none;}
.faq-item summary::after{
  content:''; flex-shrink:0; width:9px; height:9px; border-right:1.4px solid var(--ink-soft); border-bottom:1.4px solid var(--ink-soft);
  transform:rotate(45deg); transition:transform 0.2s ease;
}
.faq-item[open] summary::after{transform:rotate(-135deg);}
.faq-item summary:hover{color:var(--accent);}
.faq-answer{font-size:var(--text-body-sm); color:var(--ink-soft); line-height:1.75; padding:0 0 22px; max-width:640px;}

/* ===== lightweight browsing search/filter controls — promoted from
   page-catalogue.css since the Laboratory Analysis page's documentation
   library needs the exact same borderless, "part of the page" pattern
   (as distinct from .field-input, the heavier boxed pattern used for
   transactional contexts like Order Tracking and Checkout). ===== */
.search-field{position:relative; flex:1; min-width:220px; max-width:360px;}
.search-field svg{position:absolute; left:0; top:50%; transform:translateY(-50%); width:var(--icon-sm); height:var(--icon-sm); color:var(--ink-faint); pointer-events:none;}
.search-field input{width:100%; background:transparent; border:none; border-bottom:1px solid var(--line); padding:8px 0 8px 24px; color:var(--ink); font-family:'Inter',sans-serif; font-size:14px; outline:none; transition:border-color 0.18s ease;}
.search-field input::placeholder{color:var(--ink-faint);}
.search-field input:focus{border-color:var(--accent);}

.filter-group{display:flex; gap:24px; flex-wrap:wrap; align-items:center;}
.filter-field select{
  color-scheme:dark; appearance:none; -webkit-appearance:none; background-color:transparent;
  border:none; border-bottom:1px solid var(--line); padding:8px 20px 8px 0;
  color:var(--ink-soft); font-family:'Inter',sans-serif; font-size:13px; outline:none; cursor:pointer;
  transition:border-color 0.18s ease, color 0.18s ease;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7' viewBox='0 0 10 7' fill='none' stroke='%23828C9B' stroke-width='1.5'%3E%3Cpath d='M1 1.2L5 5.5L9 1.2'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right center;
}
.filter-field select:hover, .filter-field select:focus{border-color:var(--accent); color:var(--ink);}
.filter-field select option{background-color:var(--surface); color:var(--ink);}

@media (max-width: 700px){
  /* .filter-group's align-items:center (above) is correct for the
     desktop row — it vertically centres the three dropdowns relative
     to each other. align-items is a cross-axis property though, and
     the cross axis flips from vertical to horizontal the moment
     flex-direction switches to column here — so that same inherited
     value was silently *horizontally* centring each dropdown instead,
     each stuck at its own narrow content width rather than lining up
     with the full-width search field above it. Confirmed by rendering
     and measuring the actual computed layout, not assumed. Overriding
     to stretch (fills the row, left edge aligned with the search
     field) and giving the select itself width:100% (a <select> doesn't
     automatically fill a stretched flex item the way a block div
     would) fixes both the stray centring and the wasted whitespace
     around each dropdown. Tighter gap (16px, an already-established
     value elsewhere in the theme) replaces the row layout's 24px,
     appropriate for a horizontal gap but too loose for a vertical
     stack of full-width fields. */
  .filter-group{flex-direction:column; align-items:stretch; gap:16px;}
  .filter-field{min-width:0;}
  .filter-field select{width:100%;}
}
