/* Two variable faces, one axis of contrast each way: Archivo is an American grotesque
   drawn for forms and signage and carries the display sizes; Atkinson Hyperlegible Next
   was drawn for low-vision reading and carries body and data, where it splits 0/O and
   1/l/I - which is the difference between reading a CAS number and guessing at it. */
/* metric-matched fallbacks: Atkinson runs ~11% wider than system-ui, so without
   these the whole page re-wraps on font swap */
@font-face { font-family: 'Atkinson Fallback'; src: local('Helvetica Neue'), local('Arial'), local('Liberation Sans'); size-adjust: 111%; ascent-override: 88.6%; descent-override: 28.5%; line-gap-override: 0%; }
@font-face { font-family: 'Archivo Fallback'; src: local('Helvetica Neue'), local('Arial'), local('Liberation Sans'); size-adjust: 105%; ascent-override: 87.8%; descent-override: 21%; line-gap-override: 0%; }
@font-face { font-family: Archivo; src: url(fonts/Archivo-Variable.woff2) format('woff2-variations'); font-weight: 100 900; font-stretch: 62% 125%; font-display: swap; }
@font-face { font-family: Atkinson; src: url(fonts/AtkinsonHyperlegibleNext-Variable.woff2) format('woff2-variations'); font-weight: 200 800; font-display: swap; }

:root {
  /* #4472e8 was the reference site's blue and failed AA everywhere it carried text
     (4.36:1 on white, 3.76:1 on panel). This one clears 6.37:1 and is not theirs. */
  --pp-blue: #2f56c9; --pp-blue-dark: #1f47ad; --pp-blue-deep: #093f95;
  --pp-tint: #f5f7fd; --pp-panel: #eceef4;
  --pp-ink: #16181d; --pp-body: #4b4f5a; --pp-muted: #6b7180; --pp-line: #e7e9f0;
  --pp-control-line: #9aa0b4;   /* 3.06:1 on white: --pp-line is a hairline, not a control edge */
  --pp-navy: #081128; --pp-deep: #03050f; --pp-black: #1a1c22;
  --r-sm: 8px; --r-md: 12px; --r-lg: 16px; --r-xl: 24px;
  /* One spacing ramp. Before this existed the file carried 42 distinct raw px
     values across 376 declarations and 22 bespoke clamp() triples for 27 uses -
     six of which were near-identical two-column gutters. Space is the only axis
     that carries rhythm in this design, and it was the one axis with no system.
     4pt base: the 8pt grid is too coarse and you need 12 between 8 and 16. */
  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px; --s-5: 24px;
  --s-6: 32px; --s-7: 48px; --s-8: 64px; --s-9: 96px; --s-10: 144px;
  /* Fluid steps. Sections vary DELIBERATELY: every section used to share one
     padding, which is a metronome, not a rhythm. */
  --sec-y: clamp(48px, 7vw, 88px);
  --sec-y-tight: clamp(28px, 3.4vw, 44px);
  --sec-y-loose: clamp(88px, 11vw, 144px);
  /* one two-column gutter for the whole site, not six that differ by 2px */
  --gap-col: clamp(32px, 5vw, 64px);
  /* the shop/cart/checkout/account panel gutter */
  --gap-panel: clamp(32px, 4vw, 44px);
  --gutter: 24px;   /* .wrap side padding */
  --shadow-1: 0 1px 2px rgba(16,24,48,.05), 0 4px 14px rgba(16,24,48,.05);
  --shadow-2: 0 2px 6px rgba(16,24,48,.07), 0 18px 40px rgba(16,24,48,.10);
  --ease: cubic-bezier(.22,.9,.28,1);
  --wrap: 1240px;
  /* Two tiers. --z-below..--z-float stack children INSIDE one component;
     --z-sticky..--z-modal stack components against the page. --z-overlay was
     declared and never used - the drawer scrim and panel are siblings in a
     positioned parent, so source order already orders them. */
  --z-below: -1; --z-raised: 2; --z-float: 3;
  --z-sticky: 20; --z-modal: 60;
  /* measured and republished by site.js; this is the value before it runs */
  --head-h: 96px;

  --f-display: Archivo, 'Archivo Fallback', system-ui, sans-serif;
  --f-text: Atkinson, 'Atkinson Fallback', system-ui, sans-serif;
  /* One ramp, every consecutive step >= 1.18 at BOTH ends of the fluid range.
     The old ladder claimed ~1.25 but only delivered it above --t-h3: the bottom
     was 13/15/17/20, i.e. 15->17 at 1.133, under the ~1.15 where two sizes stop
     reading as distinct and start reading as a mistake. --t-small and --t-body
     are the two most-used tokens on the site (46 and 50 calls), so half of all
     type sat in a 2px band. There is no valid third step between 13 and 17 at a
     1.15 floor, so the band had to widen: body went to 18. */
  --t-caption: 0.8125rem;   /* 13 - legal, disclaimer, badges */
  --t-small: 0.9375rem;     /* 15 - nav, buttons, table cells, labels   x1.154 */
  --t-body: 1.125rem;       /* 18 - body copy and every form control    x1.200 */
  --t-lead: 1.375rem;       /* 22 - lead paragraphs, card titles        x1.222 */
  --t-h3: 1.625rem;         /* 26                                       x1.182 */
  --t-h2: clamp(2rem, 2.4vw + .7rem, 2.5rem);          /* 32 - 40 */
  --t-h1: clamp(2.5rem, 3.1vw + .85rem, 3.25rem);      /* 40 - 52 */
  --t-display: clamp(3rem, 4.4vw + 1.05rem, 4.5rem);   /* 48 - 72, hero only */
  /* Display tracking lives here instead of being retyped per selector. It was
     six different negative values, and five more selectors that set
     --f-display and forgot tracking altogether. */
  --track-display: -.005em;
  /* Atkinson's 0 is 1.33x its average lowercase, so 1ch buys 1.33 real characters.
     52ch reads as ~69 and 40ch as ~53; never hand-tune a cap, use these. */
  --measure: 52ch;
  --measure-tight: 40ch;
  /* three contexts, not ten values; leading tightens as size grows */
  --lh-display: 1.06;
  --lh-heading: 1.2;
  --lh-body: 1.6;
  --lh-dark: 1.68;   /* light-on-dark reads thinner and needs the extra room */
  color-scheme: light;
}
* { box-sizing: border-box; }
/* molecular formulas, CAS numbers, batch ids and product keys are single unbreakable
   words: C101H152N28O22S2.C2HF3O2 has no break opportunity and pushed 49 product
   pages off-screen on a phone */
.spec-list, .batch dd, .varline, .ns, table.data td, .prose p, .prose li { overflow-wrap: break-word; }
/* CAS numbers, molecular formulas, batch ids, net weights. slashed-zero is a
   no-op on a face without the feature, and Atkinson was picked in the first
   place because it splits 0/O and 1/l/I - this makes that explicit rather than
   leaving it to the default figure set. */
.spec-list, .batch dd, .varline, .ns { font-variant-numeric: tabular-nums slashed-zero; }
/* the UA rule for [hidden] is display:none at zero specificity, so any author
   display (.pcard is flex) silently beats it and "hidden" cards keep rendering */
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body { margin: 0; font-family: var(--f-text); color: var(--pp-ink); background: #fff; font-size: var(--t-body); line-height: var(--lh-body); font-kerning: normal; -webkit-font-smoothing: antialiased; }
img { max-width: 100%; height: auto; display: block; }
a { color: inherit; text-decoration: none; }
/* Archivo was CONDENSED to 94%, set at 600 and tracked to -.022em. That exact
   combination is Inter's silhouette, which is why the page read as generated -
   you cannot see a typeface's name, only its setting, and the setting was the
   default. Archivo's own width axis runs 62-125% and is already in this file,
   so going the other way costs zero bytes: extended, heavier and untracked
   reads as signage and institutional paperwork, which is what a research
   chemical supplier is. Weight carries hierarchy now too - h1/h2 at 700 against
   h3/h4 at 600 - because every heading on the site was one weight at one width. */
h1, h2, h3, h4 { font-family: var(--f-display); font-stretch: 112%; line-height: var(--lh-heading); margin: 0; letter-spacing: var(--track-display); text-wrap: balance; }
h1, h2 { font-weight: 700; }
h3, h4 { font-weight: 600; }
/* h1 had NO size in the design system - only seven container-scoped overrides.
   Any page whose h1 missed all seven fell back to the UA's 2em, so /checkout/
   was rendering its headline at 34px entirely by accident. */
h1 { font-size: var(--t-h1); }
p { margin: 0 0 1em; text-wrap: pretty; }
:focus-visible { outline: 2px solid var(--pp-blue); outline-offset: 3px; border-radius: 3px; }
.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 var(--gutter); }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.skip { position: absolute; left: -9999px; }
.skip:focus { left: 16px; top: 16px; z-index: var(--z-modal); background: #fff; display: inline-flex; align-items: center; min-height: 44px; padding: var(--s-3) var(--s-4); border-radius: var(--r-sm); box-shadow: var(--shadow-2); }

.mockbar { background: var(--pp-black); color: #fff; font-size: var(--t-caption); text-align: center; padding: 8px 16px calc(8px + env(safe-area-inset-top, 0px)); }
.mockbar a { color: #9dc0ff; text-decoration: underline; text-underline-offset: 2px; }

/* ---------- header ---------- */
/* Dark on purpose. The client's logo is chrome artwork with a WHITE keyline
   drawn to separate it from a dark backing - on white that keyline is invisible
   and the shark loses its top edge and tail. Every other option was worse: a
   black silhouette is not the logo they asked for, and a dark plate behind a
   colour logo inside a white bar reads as a sticker. The header also runs
   straight into the hero, which is already this colour. */
.site-head { background: var(--pp-navy); border-bottom: 0; position: sticky; top: 0; z-index: var(--z-sticky); }
/* same trap as the nav: this class sits alongside .wrap on one element and its
   shorthand padding was wiping .wrap's side gutters, which pushed the cart badge
   off the right edge of the viewport on a phone */
.head-top { display: flex; align-items: center; gap: 24px; padding: 16px 24px; }
/* the colour mark carries a wordmark and a shark, so it needs more height than
   a plain silhouette did to stay legible */
.brand { display: inline-flex; align-items: center; min-height: 44px; }
.brand img { height: 46px; width: auto; }
.quick { flex: 1 1 260px; max-width: 330px; position: relative; }
.quick input { width: 100%; font: inherit; font-size: var(--t-body); padding: 12px 16px 12px 40px; border: 1px solid rgba(255,255,255,.14); border-radius: 999px; background: rgba(255,255,255,.08); color: #fff; transition: border-color .18s, background .18s; }
/* 7.3:1 on the navy: a placeholder is body text and needs the same 4.5:1 as any other */
.quick input::placeholder { color: #9aa3b8; opacity: 1; }
.quick input:focus { border-color: #7fd4ff; background: rgba(255,255,255,.14); outline: none; box-shadow: 0 0 0 3px rgba(127,212,255,.25); }
.quick svg { position: absolute; left: 16px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: #9aa3b8; pointer-events: none; }
.usa { display: flex; align-items: center; gap: 8px; font-size: var(--t-small); color: rgba(255,255,255,.88); }
.usa .flag { width: 25px; height: 17px; border-radius: 3px; background: linear-gradient(#b22234 0 20%, #fff 20% 40%, #b22234 40% 60%, #fff 60% 80%, #b22234 80% 100%); position: relative; overflow: hidden; flex: none; box-shadow: 0 0 0 1px rgba(0,0,0,.06); }
.usa .flag::before { content: ''; position: absolute; inset: 0 55% 45% 0; background: #3c3b6e; }
.head-act { margin-left: auto; display: flex; align-items: center; gap: 24px; }
.head-act a { display: flex; align-items: center; gap: 8px; min-height: 44px; font-size: var(--t-small); color: rgba(255,255,255,.88); transition: color .16s; }
.head-act a:hover { color: #7fd4ff; }
.head-act svg { width: 19px; height: 19px; }
.cartlink { position: relative; }
/* the brand blue is only 2.1:1 against the navy; this one clears 3:1 as a non-text indicator */
.cartlink .n { position: absolute; top: -6px; left: 11px; background: #3d7dff; color: #fff; font-size: var(--t-caption); min-width: 1.25em; height: auto; padding: 0 .3em; border-radius: 999px; display: grid; place-items: center; font-weight: 600; }
.head-nav { background: #0c1730; border-top: 1px solid rgba(255,255,255,.07); }
/* margin: 0 here used to beat the margin: 0 auto on .wrap by specificity, which pinned
   the whole nav to the left edge; the side padding has to come back with it */
.head-nav ul { display: flex; justify-content: center; flex-wrap: wrap; gap: 32px; list-style: none; margin: 0 auto; padding: 16px 24px; }
.head-nav a { font-size: var(--t-small); color: rgba(255,255,255,.86); position: relative; padding: 8px 0; display: inline-flex; align-items: center; min-height: 44px; transition: color .16s; }
.head-nav a::after { content: ''; position: absolute; left: 0; right: 0; bottom: -2px; height: 2px; background: #7fd4ff; transform: scaleX(0); transform-origin: left; transition: transform .22s var(--ease); }
.head-nav a:hover { color: #fff; }
.head-nav a:hover::after, .head-nav a[aria-current]::after { transform: scaleX(1); }
.head-nav a[aria-current] { color: var(--pp-blue); }
@media (max-width: 900px) {
  .head-top { gap: 12px; }
  .quick, .usa { display: none; }
  .head-nav ul { justify-content: flex-start; gap: 24px; padding: 12px 24px; overflow-x: auto; flex-wrap: nowrap; scrollbar-width: none; }
  .head-nav ul::-webkit-scrollbar { display: none; }
  .head-nav a { white-space: nowrap; }
  .head-act { gap: 16px; }
  .head-act a span:not(.n) { display: none; }
  /* the colour mark stacks PURITY over PEPTIDES, so at the silhouette's old
     26px the lower word came out around five pixels tall and unreadable */
  .brand img { height: 36px; }
}

/* ---------- buttons ---------- */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 8px; font: inherit; font-size: var(--t-small); font-weight: 500; padding: 12px 24px; border-radius: var(--r-sm); border: 1px solid transparent; cursor: pointer; transition: background .18s, color .18s, border-color .18s, transform .18s var(--ease), box-shadow .18s; }
.btn:active { transform: translateY(1px); }
.btn-primary { background: var(--pp-blue); color: #fff; box-shadow: 0 1px 2px rgba(47,86,201,.3); }
.btn-primary:hover { background: var(--pp-blue-dark); box-shadow: 0 6px 18px rgba(47,86,201,.32); }
.btn-blue { background: var(--pp-blue); color: #fff; }
.btn-blue:hover { background: var(--pp-blue-dark); box-shadow: 0 6px 18px rgba(47,86,201,.3); }
.btn-soft { background: var(--pp-tint); color: var(--pp-blue); }
.btn-soft:hover { background: #e8ecfa; color: var(--pp-blue-deep); }
.btn-ghost { background: transparent; color: var(--pp-blue); border-color: #cfd8f5; }
.btn-ghost:hover { background: var(--pp-tint); border-color: var(--pp-blue); }
.btn-dark { background: var(--pp-black); color: #fff; border-radius: 999px; padding: 12px 24px; font-size: var(--t-small); }
.btn-dark:hover { background: #000; }
.btn-white { background: #fff; color: var(--pp-blue-deep); }
.btn-white:hover { background: #eef2ff; }
.btn-outline-white { background: rgba(255,255,255,.04); color: #fff; border-color: rgba(255,255,255,.55); }
.btn-outline-white:hover { background: rgba(255,255,255,.14); border-color: #fff; }
.btn[disabled] { background: var(--pp-line); color: var(--pp-muted); cursor: not-allowed; box-shadow: none; }
.btn[disabled]:active { transform: none; }
.btn-sm { padding: 12px 16px; font-size: var(--t-small); }
.btn-block { width: 100%; }

/* ---------- hero gallery ---------- */
/* Kadence's INLINE stylesheet sets h1..h6 colour at element level
   (h1 { color: var(--global-palette3) } and friends). An element rule beats
   inheritance, so a heading inside one of our dark sections took Kadence's
   near-black instead of the white its parent sets - the homepage headline was
   rendering at about 1.3:1 and was effectively invisible. We never set a colour
   on those headings because we were relying on inheriting the section's.
   Anywhere a section declares its own colour, its headings follow it. */
/* Light type on a dark ground blooms and reads roughly half a weight lighter.
   Leading is already compensated (--lh-dark); weight was not. Atkinson's axis
   runs 200-800, so 450 is a free interpolation - no extra file, no extra byte. */
.site-head, .site-foot, .disclaimer, .hero, .band, .section-dark { font-weight: 450; }
.hero :is(h1, h2, h3, h4, h5, h6),
.band :is(h1, h2, h3, h4, h5, h6),
.section-dark :is(h1, h2, h3, h4, h5, h6),
.disclaimer :is(h1, h2, h3, h4, h5, h6),
.site-foot :is(h1, h2, h3, h4, h5, h6) { color: inherit; }

.hero { position: relative; background: var(--pp-deep); color: #fff; overflow: hidden; min-height: min(760px, calc(100svh - 118px)); display: grid; }
.hero-slide { grid-area: 1 / 1; position: relative; display: grid; align-items: center; opacity: 0; visibility: hidden; transition: opacity .7s var(--ease), visibility 0s linear .7s; }
.hero-slide[data-active] { opacity: 1; visibility: visible; transition: opacity .7s var(--ease), visibility 0s; }
.hero-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 70% 50%; transform: scale(1.06); transition: transform 9s linear; }
.hero-slide[data-active] .hero-bg { transform: scale(1); }
.hero-slide::after { content: ''; position: absolute; inset: 0; background: linear-gradient(97deg, rgba(3,5,15,.95) 0%, rgba(3,5,15,.86) 34%, rgba(3,5,15,.28) 62%, rgba(3,5,15,0) 88%); }
.hero-copy { position: relative; z-index: var(--z-raised); padding: clamp(64px, 9vh, 112px) var(--gutter); max-width: var(--wrap); margin: 0 auto; width: 100%; }
/* the slide crossfade is the one moment; a staggered fade-up on every child on top
   of it is the generated-page default and reads as noise */
.hero-copy { opacity: 0; }
.hero-slide[data-active] .hero-copy { animation: heroIn .6s var(--ease) forwards; }
@keyframes heroIn { to { opacity: 1; } }
.hero .hero-title { font-size: var(--t-display); max-width: 14ch; margin: 0 0 16px; letter-spacing: var(--track-display); line-height: var(--lh-display); }
.hero .hero-sub { font-size: var(--t-body); color: #ccd6ea; max-width: 46ch; margin: 0 0 32px; line-height: var(--lh-dark); letter-spacing: .01em; }
.hero-btns { display: flex; gap: 12px; flex-wrap: wrap; }
.hero-slide.is-product { grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr); align-items: center; }
.hero-slide.is-product::after { background: radial-gradient(120% 90% at 78% 50%, rgba(47,86,201,.20), transparent 62%); }
.hero-slide.is-product .hero-copy { max-width: none; margin: 0; padding-left: max(22px, calc((100vw - var(--wrap)) / 2 + 22px)); padding-right: 24px; }
.hero-stage { position: relative; z-index: var(--z-raised); justify-self: center; margin: 0; width: min(430px, 88%); border-radius: var(--r-xl); overflow: hidden; background: #eef0f5; box-shadow: 0 30px 70px rgba(0,0,0,.45), 0 0 0 1px rgba(255,255,255,.10) inset; }
.hero-stage > img { aspect-ratio: 1; }
.hero-stage figcaption { background: #fff; border-top: 1px solid #dfe3ec; }

/* the record that belongs to the vial above it: label left, value right, values on
   the display face so the numbers - which are the whole argument - carry the weight */
.batch { margin: 0; padding: 16px 24px 16px; display: grid; gap: 8px; }
.batch div { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; }
.batch dt { font-size: var(--t-caption); color: var(--pp-muted); }
.batch dd { margin: 0; font-family: var(--f-display); font-size: var(--t-small); font-weight: 600; color: var(--pp-ink); font-variant-numeric: tabular-nums; }
.batch-head { padding-bottom: 12px; margin-bottom: 3px; border-bottom: 1px solid #eceef4; }
.batch-head dt { font-size: var(--t-small); color: var(--pp-ink); font-weight: 500; }
.batch-head dd { color: var(--pp-blue); }
.hero-stage img { width: 100%; height: 100%; object-fit: cover; transform: scale(1.02); transition: transform 9s linear; }
.hero-slide[data-active] .hero-stage img { transform: scale(1.09); }
@media (max-width: 980px) {
  .hero-slide.is-product { grid-template-columns: 1fr; justify-items: center; }
  .hero-slide.is-product .hero-copy { order: 2; padding: 24px 24px 96px; text-align: center; max-width: 620px; }
  .hero-slide.is-product .hero-btns { justify-content: center; }
  .hero-slide.is-product .hero-sub { margin-left: auto; margin-right: auto; }
  .hero-stage { order: 1; width: min(300px, 62%); margin-top: 48px; }
}
.hero-nav { position: absolute; z-index: var(--z-float); left: 0; right: 0; bottom: clamp(24px, 4vh, 40px); }
.hero-nav .wrap { display: flex; align-items: center; gap: 16px; }
.hero-dots { display: flex; gap: 12px; }
.hero-dot { width: 34px; height: 4px; padding: 24px 0; background-clip: content-box; box-sizing: content-box; border-radius: 999px; border: 0; padding: 0; cursor: pointer; background: rgba(255,255,255,.3); position: relative; overflow: hidden; transition: background .2s; }
.hero-dot:hover { background: rgba(255,255,255,.55); }
.hero-dot[aria-current]::after { content: ''; position: absolute; inset: 0; background: #fff; transform-origin: left; transform: scaleX(0); animation: dotFill 7s linear forwards; }
.hero[data-paused] .hero-dot[aria-current]::after { animation-play-state: paused; }
@keyframes dotFill { to { transform: scaleX(1); } }
.hero-arrows { margin-left: auto; display: flex; gap: 8px; }
.hero-arrow { width: 42px; height: 42px; border-radius: 999px; border: 1px solid rgba(255,255,255,.3); background: rgba(255,255,255,.06); color: #fff; display: grid; place-items: center; cursor: pointer; transition: background .18s, border-color .18s; }
.hero-arrow:hover { background: rgba(255,255,255,.18); border-color: #fff; }
.hero-arrow svg { width: 17px; height: 17px; }
.hero-arrow.pause .i-play, .hero-arrow.pause[aria-pressed="true"] .i-pause { display: none; }
.hero-arrow.pause[aria-pressed="true"] .i-play { display: block; }
@media (max-width: 860px) {
  .hero { min-height: auto; }
  .hero-slide::after { background: linear-gradient(180deg, rgba(3,5,15,.9) 0%, rgba(3,5,15,.72) 55%, rgba(3,5,15,.93) 100%); }
  /* A phone sees about 29% of this frame's width, so the crop has to choose.
     Centring the vials puts them directly behind the headline; panning left of
     them keeps the light shafts and the shark behind the copy, which stays
     readable and is still the brand's own image. */
  .hero-bg { object-position: 38% 45%; }
  .hero-copy { padding: 48px 24px 96px; }
  .hero .hero-title { max-width: 18ch; }
  .hero-arrows { display: none; }
}

/* ---------- sections ---------- */
.section { padding-block: var(--sec-y); }
/* Rhythm modifiers. A page that gives every section the same gutter has no
   hierarchy of its own - the reader gets a metronome instead of a beat. */
.section-tight { padding-block: var(--sec-y-tight); }
.section-loose { padding-block: var(--sec-y-loose); }
.section-flush { padding-top: 0; }
/* #f5f7fd against #fff is a ~2% luminance step - at squint the alternation
   did nothing at all, so five consecutive light sections read as one field. */
.section-tint { background: var(--pp-panel); }
/* The page had exactly one dark anchor (.band) and then ran five light
   sections in a row. This is the second anchor, at the midpoint. */
.section-dark { background: var(--pp-navy); color: #fff; }
.sec-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; margin-bottom: 32px; flex-wrap: wrap; }
.sec-head h2 { font-size: var(--t-h2); margin: 0; }
.sec-head p { color: var(--pp-body); margin: 8px 0 0; font-size: var(--t-body); max-width: var(--measure); }
.sec-head .more { font-size: var(--t-small); color: var(--pp-blue); font-weight: 500; display: inline-flex; align-items: center; min-height: 44px; gap: var(--s-2); white-space: nowrap; }
.sec-head .more svg { width: 15px; height: 15px; transition: transform .2s var(--ease); }
.sec-head .more:hover svg { transform: translateX(3px); }
.section h2.center { text-align: center; font-size: var(--t-h2); margin: 0 auto 32px; max-width: 24ch; }

/* ---------- product cards ---------- */
.prod-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; }
@media (max-width: 1100px) { .prod-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 880px) { .prod-grid { grid-template-columns: repeat(2, 1fr); gap: 16px; } }
@media (max-width: 460px) { .prod-grid { grid-template-columns: repeat(2, 1fr); gap: 12px; } }

.pcard { min-width: 0; background: #fff; border: 1px solid var(--pp-line); border-radius: var(--r-lg); padding: 16px; display: flex; flex-direction: column; gap: 16px; position: relative; box-shadow: var(--shadow-1); transition: box-shadow .26s var(--ease), transform .26s var(--ease), border-color .26s; }
.pcard:hover { box-shadow: var(--shadow-2); transform: translateY(-3px); border-color: #d8dcea; }
.pcard .thumb { display: block; background: var(--pp-panel); border-radius: var(--r-md); overflow: hidden; position: relative; }
.pcard .thumb img { width: 100%; transition: transform .5s var(--ease); }
.pcard:hover .thumb img { transform: scale(1.04); }
.pcard-body { text-align: center; display: flex; flex-direction: column; gap: 12px; flex: 1; padding: 0 4px 4px; }
/* The compound name IS the scan target on an 84-product research catalogue;
   the price is secondary. This was the other way round - blurred, the read
   order came out button, photo, price, name, so the one word a researcher is
   hunting for resolved last. order:-1 lifts the name above the price without
   moving it in the markup, where price-then-name is the right source order. */
.pcard h3 { order: -1; font-family: var(--f-display); font-size: var(--t-lead); font-weight: 600; letter-spacing: var(--track-display); margin: 0; line-height: 1.25; color: var(--pp-ink); }
.pcard .price { font-size: var(--t-small); font-weight: 500; color: var(--pp-body); margin: 0; flex: 1; font-variant-numeric: tabular-nums; }
.pcard h3 a { transition: color .16s; }
.pcard h3 a::after { content: ''; position: absolute; inset: 0; border-radius: inherit; }
.pcard .acts, .pcard .flag-badge { position: relative; z-index: var(--z-raised); }
.pcard:hover h3 a { color: var(--pp-blue); }
.pcard .acts { display: flex; flex-direction: column; gap: 8px; }
.pcard .flag-badge { position: absolute; top: 24px; left: 24px; z-index: var(--z-raised); background: var(--pp-blue); color: #fff; font-size: var(--t-caption); font-weight: 600; letter-spacing: .04em; padding: 4px 12px; border-radius: 999px; box-shadow: 0 2px 8px rgba(47,86,201,.35); }
.pcard .flag-badge.oos { background: #6b7180; box-shadow: none; }
@media (max-width: 460px) { .pcard { padding: 12px; gap: 12px; } .pcard h3 { font-size: var(--t-body); line-height: 1.3; } .pcard .flag-badge { top: 16px; left: 16px; } }

/* ---------- carousel ---------- */
.carousel { position: relative; }
.car-track { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(250px, 1fr); gap: 24px; overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth; padding: 8px 2px 16px; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.car-track::-webkit-scrollbar { display: none; }
.car-track > * { scroll-snap-align: start; }
@media (min-width: 1101px) { .car-track { grid-auto-columns: calc((100% - 66px) / 4); } }
@media (max-width: 1100px) and (min-width: 881px) { .car-track { grid-auto-columns: calc((100% - 44px) / 3); } }
@media (max-width: 880px) { .car-track { grid-auto-columns: calc((100% - 16px) / 2); gap: 16px; } }
@media (max-width: 560px) { .car-track { grid-auto-columns: 74%; } }
.car-arrow { position: absolute; top: calc(50% - 40px); width: 44px; height: 44px; border-radius: 999px; background: #fff; border: 1px solid var(--pp-line); color: var(--pp-ink); display: grid; place-items: center; cursor: pointer; box-shadow: var(--shadow-2); z-index: var(--z-float); transition: background .2s, color .2s, border-color .2s; }
.car-arrow:hover { background: var(--pp-blue); color: #fff; border-color: var(--pp-blue); }
.car-arrow svg { width: 17px; height: 17px; }
.car-arrow.prev { left: -20px; }
.car-arrow.next { right: -20px; }
@media (max-width: 1340px) { .car-arrow.prev { left: 4px; } .car-arrow.next { right: 4px; } }
@media (max-width: 880px) { .car-arrow { display: none; } }

/* ---------- ruo callout ---------- */
.ruo { background: #fff; border: 1px solid var(--pp-line); border-radius: var(--r-lg); padding: 24px 24px; display: grid; grid-template-columns: auto 1fr; gap: 16px; align-items: start; box-shadow: var(--shadow-1); }
.ruo .mark { width: 38px; height: 38px; border-radius: 10px; background: var(--pp-tint); color: var(--pp-blue); display: grid; place-items: center; }
.ruo .mark svg { width: 19px; height: 19px; }
.ruo h3 { font-size: var(--t-h3); margin: 2px 0 8px; }
.ruo p { font-size: var(--t-body); color: var(--pp-body); margin: 0; line-height: var(--lh-body); max-width: var(--measure); }
@media (max-width: 560px) { .ruo { grid-template-columns: 1fr; padding: 16px 24px; } }

/* ---------- dark band ---------- */
.band { position: relative; border-radius: var(--r-xl); overflow: hidden; background: var(--pp-deep); color: #fff; isolation: isolate; }
.band img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: var(--z-below); }
.band-in { padding: clamp(40px, 5.6vw, 80px) clamp(24px, 4.4vw, 64px); max-width: var(--measure); }
.band h2 { font-size: var(--t-h2); margin: 0 0 32px; letter-spacing: var(--track-display); }
.band ul { list-style: none; margin: 0 0 32px; padding: 0; display: grid; gap: 24px; }
.band li { display: flex; align-items: center; gap: 16px; font-size: var(--t-body); color: #e9eefb; line-height: var(--lh-dark); letter-spacing: .01em; }
.band li .tick { width: 26px; height: 26px; border-radius: 999px; border: 1.5px solid rgba(139,169,255,.6); display: grid; place-items: center; flex: none; }
.band li .tick::after { content: ''; width: 7px; height: 7px; border-radius: 999px; background: #8ba9ff; }
.band .btns { display: flex; gap: 12px; flex-wrap: wrap; }
@media (max-width: 760px) { .band-in { max-width: none; } .band::after { content: ''; position: absolute; inset: 0; background: rgba(3,5,15,.6); z-index: var(--z-below); } }

/* ---------- shop filter ---------- */
.no-hits { text-align: center; padding: var(--sec-y) var(--gutter); }
.no-hits h3 { font-size: var(--t-h3); margin: 0 0 12px; }
.no-hits p { color: var(--pp-body); margin: 0 auto 16px; max-width: var(--measure-tight); }
.shop-tools { display: flex; flex-direction: column; gap: 16px; margin-bottom: 32px; }
.searchbox { position: relative; }
.searchbox input { width: 100%; font: inherit; font-size: var(--t-body); padding: 16px 16px 16px 48px; border: 1px solid var(--pp-control-line); border-radius: var(--r-sm); background: #fff; transition: border-color .18s, box-shadow .18s; }
.searchbox input:focus { border-color: var(--pp-blue); box-shadow: 0 0 0 3px rgba(47,86,201,.13); outline: none; }
.searchbox svg { position: absolute; left: 17px; top: 50%; transform: translateY(-50%); width: 16px; height: 16px; color: var(--pp-muted); pointer-events: none; }
.pills { display: flex; flex-wrap: wrap; gap: 8px; list-style: none; margin: 0; padding: 0; }
.pill { display: inline-flex; align-items: center; min-height: 44px; font: inherit; font-size: var(--t-small); font-weight: 500; cursor: pointer; border: 1px solid var(--pp-control-line); background: #fff; color: var(--pp-body); border-radius: 999px; padding: 0 var(--s-4); transition: background .18s, color .18s, border-color .18s; }
.pill:hover { border-color: var(--pp-blue); color: var(--pp-blue); }
.pill[aria-pressed="true"], .pill[aria-current] { background: var(--pp-blue); color: #fff; border-color: var(--pp-blue); }
.tools-row { display: flex; gap: 16px; align-items: center; flex-wrap: wrap; }
.tools-row .searchbox { flex: 1 1 320px; }
.sortsel { font: inherit; font-size: var(--t-body); padding: 12px 16px; border: 1px solid var(--pp-control-line); border-radius: var(--r-sm); background: #fff; color: var(--pp-ink); cursor: pointer; }
.resultcount { font-size: var(--t-small); color: var(--pp-muted); margin: 0; }

/* ---------- testing block ---------- */
.testing { display: grid; grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr); gap: var(--gap-col); align-items: end; }
@media (max-width: 880px) { .testing { grid-template-columns: 1fr; gap: 32px; } }
.testing .ico { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.testing .ico svg { width: 26px; height: 26px; color: var(--pp-blue); flex: none; }
.testing h2 { font-size: var(--t-h2); }
.testing p { font-size: var(--t-body); color: var(--pp-body); max-width: var(--measure); }
.testing strong { color: var(--pp-ink); font-weight: 600; }
.testing img { border-radius: var(--r-lg); box-shadow: var(--shadow-2); }

/* ---------- feature cards ---------- */
.feat { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 290px), 1fr)); gap: 16px; }
.fcard { background: #fff; border: 1px solid var(--pp-line); border-radius: var(--r-lg); padding: 24px 24px; display: flex; gap: 16px; align-items: flex-start; transition: border-color .22s, box-shadow .22s var(--ease), transform .22s var(--ease); }
.fcard:hover { border-color: #d5dcf4; box-shadow: var(--shadow-1); transform: translateY(-2px); }
/* On the dark field the cards lose their boxes: six white rectangles in a grid
   is the repeated-icon-card antipattern, and the card chrome is what makes them
   read as six of one thing instead of six separate points. */
.section-dark .feat { gap: var(--s-7) var(--s-6); }
.section-dark .fcard { background: none; border: 0; border-top: 1px solid rgba(255,255,255,.16); border-radius: 0; box-shadow: none; padding: var(--s-5) 0 0; }
.section-dark .fcard:hover { border-color: rgba(255,255,255,.34); box-shadow: none; transform: none; }
.section-dark .fcard .ic { background: rgba(127,212,255,.12); color: #7fd4ff; }
.section-dark .fcard p { color: #cdd6ea; line-height: var(--lh-dark); }
.section-dark .fcard p a { color: #9dc0ff; }
.fcard .ic { width: 40px; height: 40px; border-radius: 11px; background: var(--pp-tint); color: var(--pp-blue); display: grid; place-items: center; flex: none; }
.fcard svg { width: 20px; height: 20px; }
.fcard h3 { font-size: var(--t-h3); margin: 0 0 8px; }
.fcard p { font-size: var(--t-body); color: var(--pp-body); margin: 0; line-height: var(--lh-body); }
.fcard p a { color: var(--pp-blue); }

/* ---------- mission ---------- */
.mission { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, .8fr); gap: var(--gap-col); align-items: start; }
@media (max-width: 880px) { .mission { grid-template-columns: 1fr; } }
.mission h2 { font-size: var(--t-h2); margin: 0 0 16px; }
.mission p { font-size: var(--t-body); color: var(--pp-body); max-width: var(--measure); }
.mission .stats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; }
.mission .stat { background: #fff; border: 1px solid var(--pp-line); border-radius: var(--r-md); padding: 24px; }
.mission .stat b { font-family: var(--f-display); display: block; font-size: var(--t-h3); font-weight: 700; letter-spacing: var(--track-display); color: var(--pp-blue); font-variant-numeric: tabular-nums; margin-bottom: 4px; }
.mission .stat span { font-size: var(--t-caption); color: var(--pp-muted); line-height: 1.5; display: block; }

/* ---------- faq ---------- */
.faq { display: grid; grid-template-columns: 330px 1fr; gap: var(--gap-col); align-items: start; }
@media (max-width: 880px) { .faq { grid-template-columns: 1fr; gap: 24px; } }
.faq h2 { font-size: var(--t-h2); margin: 0 0 12px; }
.faq .sub { font-size: var(--t-body); color: var(--pp-body); }
.faq details { background: #fff; border: 1px solid var(--pp-line); border-radius: var(--r-md); margin-bottom: 12px; transition: border-color .2s, box-shadow .2s; }
.faq details[open] { border-color: #d5dcf4; box-shadow: var(--shadow-1); }
.faq summary { cursor: pointer; list-style: none; padding: 16px 24px; font-size: var(--t-body); font-weight: 500; display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: ''; width: 10px; height: 10px; flex: none; border-right: 2px solid var(--pp-blue); border-bottom: 2px solid var(--pp-blue); transform: rotate(45deg) translate(-2px, -2px); transition: transform .24s var(--ease); }
.faq details[open] summary::after { transform: rotate(-135deg) translate(-3px, -3px); }
.faq .ans { padding: 0 24px 24px; font-size: var(--t-body); color: var(--pp-body); margin: 0; line-height: var(--lh-body); max-width: var(--measure); }


/* ---------- footer ---------- */
/* Dark to match the header, for the same reason: the colour logo needs a dark
   backing. It also bookends the page - navy header, light content, navy footer,
   brand-blue disclaimer bar - instead of leaving the header as the only dark
   band on the page. */
.site-foot { background: var(--pp-navy); color: rgba(255,255,255,.82); padding: 64px 0 48px; border-top: 0; }
.foot-grid { display: grid; grid-template-columns: 1.5fr 1fr 1fr; gap: 48px; }
@media (max-width: 880px) { .foot-grid { grid-template-columns: 1fr 1fr; gap: 32px; } .foot-brand { grid-column: 1 / -1; } }
@media (max-width: 520px) { .foot-grid { grid-template-columns: 1fr; } }
/* the <a> around the logo, not the column that holds it - inline-flexing the
   column laid its children out in a row and pushed the footer 16px wide */
.foot-brand > a { display: inline-flex; }
.foot-brand img.logo { height: 44px; width: auto; margin-bottom: var(--s-5); }
@media (max-width: 520px) { .foot-brand img.logo { height: 38px; } }
.pay { display: flex; gap: 8px; margin-bottom: 24px; flex-wrap: wrap; }
.pay span { border: 1px solid rgba(255,255,255,.18); border-radius: 5px; padding: 8px 12px; font-size: var(--t-caption); font-weight: 700; letter-spacing: .05em; color: rgba(255,255,255,.80); background: rgba(255,255,255,.05); }
.site-foot h3 { font-size: var(--t-h3); margin: 0 0 16px; color: #fff; }
.site-foot ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
/* 9.8:1 on the navy; light-on-dark also reads thinner, hence --lh-dark below */
.site-foot li a { font-size: var(--t-small); color: rgba(255,255,255,.82); display: inline-flex; align-items: center; min-height: 44px; }
.site-foot address { font-size: var(--t-small); color: rgba(255,255,255,.82); font-style: normal; line-height: var(--lh-dark); }
.site-foot address a { color: #7fd4ff; }
.site-foot li a { transition: color .16s; }
.site-foot li a:hover { color: #7fd4ff; }
.head-bar { background: var(--pp-blue); padding: 16px 16px; text-align: center; }
.head-bar img { height: 40px; width: auto; margin: 0 auto; display: block; }
.disclaimer { background: var(--pp-blue); color: #fff; padding: 28px 0 calc(28px + env(safe-area-inset-bottom, 0px)); font-size: var(--t-small); line-height: var(--lh-body); }
.disclaimer p { margin: 0 0 12px; color: #fff; max-width: var(--measure); line-height: var(--lh-dark); letter-spacing: .01em; }
.disclaimer p:last-child { margin: 0; }

/* ---------- library ---------- */
.lib { background: var(--pp-tint); padding-block: var(--sec-y-tight) var(--sec-y); }
/* The catalogue wore the homepage's card density: ~450px tall cards, four per
   screen, 21 identical rows, so finding one compound meant scrolling 13
   screens. The homepage carousel keeps the large card; the library gets a
   compact one. */
.lib .prod-grid { grid-template-columns: repeat(auto-fill, minmax(212px, 1fr)); gap: var(--s-4); }
.lib .pcard { padding: var(--s-3); gap: var(--s-3); border-radius: var(--r-md); }
.lib .pcard .thumb { border-radius: var(--r-sm); }
.lib .pcard-body { gap: var(--s-2); padding: 0 var(--s-1) var(--s-1); }
.lib .pcard h3 { font-size: var(--t-body); line-height: 1.3; }
/* 84 solid blue bars were the strongest repeated signal on the catalogue -
   blurred, the page read as a field of buttons with product names underneath.
   The CTA outranks the name on the product page, where there is one of it;
   here it steps back. Same target size, same label, same link. */
.lib .pcard .btn-blue:not(:disabled) { background: transparent; color: var(--pp-blue); border-color: #cfd8f5; }
.lib .pcard .btn-blue:not(:disabled):hover { background: var(--pp-blue); color: #fff; border-color: var(--pp-blue); box-shadow: none; }
.lib h1 { font-size: var(--t-h1); margin: 0 0 8px; }
.lib .lede { color: var(--pp-body); margin: 0 0 24px; max-width: var(--measure); font-size: var(--t-body); }

/* ---------- product ---------- */
/* Modelled on Polaris Peptides' product page at Nate's direction (2026-09-18),
   in this store's own light palette rather than their dark one. What was worth
   taking: every size visible as a pill instead of hidden in a select; the bulk
   table promoted to the width of its column with a headline over it; the long
   spec list folded into accordions; one large pill CTA. What was not: their
   Description ships collapsed, which hides the page's own copy from a reader
   and from a crawler, so ours opens by default. */
.pdp-top { background: var(--pp-tint); }
/* Two columns that finish together. The image was a 440px square against a
   1113px buy column, which left 673px of dead tint under the product: the page
   read as two unrelated things rather than one row. Now the columns are close
   to even, the photo is ~30% larger, and the three trust lines moved under it,
   so the left column carries the product and the right column carries only the
   buying decision. */
.pdp-grid { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); gap: clamp(28px, 3.4vw, 48px); align-items: start; }
@media (max-width: 920px) { .pdp-grid { grid-template-columns: 1fr; gap: var(--s-5); } }
.pdp-media { position: sticky; top: calc(var(--head-h, 96px) + var(--s-5)); display: grid; gap: var(--s-5); align-content: start; }
/* Stacked, the media column would put the three trust lines between the photo
   and the price. Dissolve the wrapper so the phone reads photo, buy, trust. */
@media (max-width: 920px) {
  .pdp-media { display: contents; }
  .pdp-img { order: 1; }
  .pdp-body { order: 2; }
  .pdp-media .badges { order: 3; padding-top: var(--s-5); border-top: 1px solid var(--pp-line); }
}
.pdp-img { background: var(--pp-panel); border-radius: var(--r-lg); overflow: hidden; margin: 0; box-shadow: var(--shadow-1); }
.pdp-img img { border-radius: var(--r-lg) var(--r-lg) 0 0; width: 100%; height: auto; }
.pdp-img .batch { background: #fff; border-top: 1px solid var(--pp-line); padding: var(--s-4) var(--s-5); }
.pdp-img .batch[hidden] { display: none; }
.pdp-body { padding-block: 0 var(--s-7); }
.crumbs { font-size: var(--t-caption); color: var(--pp-muted); margin: 0; padding: var(--s-5) 0 var(--s-4); }
.crumbs a { transition: color .16s; }
.crumbs a:hover { color: var(--pp-blue); }
.pdp-body h1 { font-size: var(--t-h1); margin: 0 0 var(--s-3); }

/* price and its qualifier read as one line, the way a shelf label does */
.pdp-price { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--s-3); font-family: var(--f-display); font-size: var(--t-h2); font-weight: 600; letter-spacing: var(--track-display); color: var(--pp-ink); margin: 0 0 var(--s-2); font-variant-numeric: tabular-nums; }
.pdp-qual { font-family: var(--f-text); font-size: var(--t-small); font-weight: 400; letter-spacing: 0; color: var(--pp-muted); }
.varline { font-size: var(--t-small); color: var(--pp-body); margin: 0 0 var(--s-6); max-width: var(--measure); }
.varline:empty { display: none; }

/* Size as pills. A select hides every option but one behind a click, on the
   single control that decides what the buyer is actually looking at. */
.sizes { border: 0; margin: 0 0 var(--s-5); padding: 0; min-width: 0; }
.sizes legend { padding: 0; margin-bottom: var(--s-2); font-size: var(--t-small); font-weight: 500; color: var(--pp-ink); }
.pillset { display: flex; flex-wrap: wrap; gap: var(--s-2); }
.sizepill { position: relative; }
.sizepill input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.sizepill span { display: grid; place-items: center; min-height: 44px; padding: 0 var(--s-4); border: 1px solid var(--pp-control-line); border-radius: 999px; background: #fff; font-size: var(--t-small); font-weight: 500; color: var(--pp-ink); transition: background .18s, border-color .18s, color .18s; }
.sizepill:hover span { border-color: var(--pp-blue); }
.sizepill input:checked + span { background: var(--pp-blue); border-color: var(--pp-blue); color: #fff; }
.sizepill input:focus-visible + span { outline: 2px solid var(--pp-blue); outline-offset: 3px; }

/* The bulk table was a 340px block marooned at the foot of a 690px column.
   It is the store's actual offer, so it gets the column and a headline. */
.tiers { margin: 0 0 var(--s-5); }
.tiers h2 { font-size: var(--t-h3); margin: 0 0 var(--s-3); }
.tiers table { border-collapse: collapse; width: 100%; font-size: var(--t-small); background: #fff; border-radius: var(--r-sm); overflow: hidden; box-shadow: 0 0 0 1px var(--pp-line); }
.tiers th, .tiers td { padding: 10px var(--s-4); text-align: left; border-bottom: 1px solid var(--pp-line); font-variant-numeric: tabular-nums; }
.tiers th:last-child, .tiers td:last-child { text-align: right; }
.tiers tr:last-child td { border-bottom: 0; }
.tiers th { font-weight: 600; font-size: var(--t-caption); letter-spacing: .04em; text-transform: uppercase; color: var(--pp-ink); background: var(--pp-panel); }

.atc { display: flex; gap: var(--s-3); align-items: stretch; margin: 0 0 var(--s-5); }
.atc input { width: 80px; font: inherit; font-size: var(--t-body); text-align: center; border: 1px solid var(--pp-control-line); border-radius: 999px; padding: var(--s-3) var(--s-2); background: #fff; }
.btn-pill { border-radius: 999px; padding: var(--s-4) var(--s-7); font-size: var(--t-body); }

.notice { display: flex; gap: var(--s-3); align-items: flex-start; background: #fff; border: 1px solid var(--pp-line); border-radius: var(--r-md); padding: var(--s-4); font-size: var(--t-small); color: var(--pp-ink); line-height: var(--lh-body); margin: 0; }
.notice svg { width: 17px; height: 17px; color: var(--pp-blue); flex: none; margin-top: 3px; }
.badges { display: grid; gap: var(--s-3); margin: 0; }
.badges div { display: flex; align-items: center; gap: var(--s-3); font-size: var(--t-body); color: var(--pp-body); max-width: var(--measure-tight); }
.badges svg { width: 17px; height: 17px; color: var(--pp-blue); flex: none; }
.badges b { font-weight: 600; color: var(--pp-ink); }

/* ---------- product accordions ---------- */
/* Native <details>: it opens with JS switched off, it is keyboard operable
   without a roving tabindex, and find-in-page reaches the closed ones. */
.pdp-info { padding-block: var(--sec-y); }
.acc { border-top: 1px solid var(--pp-line); }
.acc:last-of-type { border-bottom: 1px solid var(--pp-line); }
.acc summary { display: flex; align-items: center; gap: var(--s-3); min-height: 44px; padding: var(--s-4) 0; font-family: var(--f-display); font-size: var(--t-h3); font-weight: 600; letter-spacing: var(--track-display); cursor: pointer; list-style: none; }
.acc summary::-webkit-details-marker { display: none; }
.acc summary::after { content: ''; margin-left: auto; width: 9px; height: 9px; border-right: 2px solid var(--pp-muted); border-bottom: 2px solid var(--pp-muted); transform: rotate(45deg); transition: transform .2s var(--ease); }
.acc[open] summary::after { transform: rotate(-135deg); }
.acc summary:focus-visible { outline: 2px solid var(--pp-blue); outline-offset: 2px; }
.acc-ic { width: 32px; height: 32px; border-radius: var(--r-sm); background: var(--pp-tint); color: var(--pp-blue); display: grid; place-items: center; flex: none; }
.acc-ic svg { width: 17px; height: 17px; }
.acc-body { padding: 0 0 var(--s-6); }
.ns { font-size: var(--t-body); color: var(--pp-ink); margin: 0; line-height: var(--lh-body); max-width: var(--measure); }
.ns-note { font-size: var(--t-small); color: var(--pp-muted); margin: var(--s-4) 0 0; line-height: var(--lh-body); max-width: var(--measure); }
.spec-list { font-size: var(--t-body); color: var(--pp-ink); max-width: var(--measure); }
.spec-list .row { display: flex; gap: var(--s-3); padding: var(--s-2) 0; border-bottom: 1px solid var(--pp-line); }
.spec-list .row .k { color: var(--pp-muted); min-width: 160px; flex: none; }
@media (max-width: 560px) { .spec-list .row { display: block; } .spec-list .row .k { min-width: 0; display: block; margin-bottom: 2px; } }
.spec-list .head { font-weight: 600; margin-top: var(--s-5); padding-bottom: var(--s-2); }
.spec-list .note { color: var(--pp-body); padding: var(--s-2) 0; line-height: var(--lh-body); }
/* Spacing that used to be written inline on every one of the 84 generated
   product pages - values that lived outside the stylesheet the README calls
   the single source of truth. */
.pdp-ruo { padding-top: var(--s-6); }
.sec-foot { text-align: center; margin: var(--s-6) 0 0; }
.cta-after { margin: var(--s-5) 0 0; }

/* ---------- account pages ---------- */
.gate { min-height: 64vh; background: #fff; display: flex; align-items: flex-start; justify-content: center; padding: 64px 24px 96px; }
.gate-in { width: 100%; max-width: 440px; text-align: center; }
/* The shortcodes print their form and their footer link into this. It is a
   plain column on purpose: .gate is the page container and centres ONE child,
   so anything that reuses that class turns its own contents into flex siblings
   sitting side by side. */
.gate-body { display: block; text-align: left; }
.gate-body > .foot-note { text-align: center; }
.gate h1 { font-size: var(--t-h1); margin: 0 0 12px; }
.gate .sub { color: var(--pp-body); font-size: var(--t-body); margin: 0 0 32px; }
.gate form { background: #fff; border: 1px solid var(--pp-line); border-radius: var(--r-lg); box-shadow: var(--shadow-2); padding: 32px 24px; text-align: left; display: grid; gap: 16px; }
.gate label { font-size: var(--t-small); font-weight: 500; display: block; margin-bottom: 8px; }
.gate .req { color: #c0392b; }
.gate input:not([type=checkbox]):not([type=radio]), .gate select, .gate textarea { width: 100%; font: inherit; font-size: var(--t-body); padding: 12px 12px; border: 1px solid var(--pp-line); border-radius: var(--r-sm); background: #fff; }
.gate input:not([type=checkbox]):not([type=radio]):focus, .gate select:focus { border-color: var(--pp-blue); outline: none; box-shadow: 0 0 0 3px rgba(47,86,201,.13); }
.gate .inline { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: var(--t-small); }
.gate .check { display: flex; gap: 12px; align-items: flex-start; font-size: var(--t-body); color: var(--pp-body); line-height: var(--lh-body); max-width: var(--measure-tight); }
.gate .check input { margin-top: 3px; flex: none; accent-color: var(--pp-blue); }
.gate a { color: var(--pp-blue); }
/* WordPress emits its own login markup from wp_login_form(); these map it onto
   the gate styling rather than forking the form into a hand-built one */
.gate #purity-login p { margin: 0 0 16px; }
.gate #purity-login label { font-size: var(--t-small); font-weight: 500; display: block; margin-bottom: 8px; }
.gate #purity-login input[type=text], .gate #purity-login input[type=password] { width: 100%; font: inherit; font-size: var(--t-body); padding: 12px 12px; border: 1px solid var(--pp-control-line); border-radius: var(--r-sm); background: #fff; }
.gate #purity-login input:focus { border-color: var(--pp-blue); outline: none; box-shadow: 0 0 0 3px rgba(47,86,201,.13); }
.gate #purity-login .login-remember label { display: flex; align-items: center; gap: 8px; font-weight: 400; }
.gate #purity-login .login-remember input { width: auto; }
.gate #purity-login .login-submit input { width: 100%; font: inherit; font-size: var(--t-small); font-weight: 500; padding: 12px 24px; border: 0; border-radius: var(--r-sm); background: var(--pp-blue); color: #fff; cursor: pointer; }
.gate #purity-login .login-submit input:hover { background: var(--pp-blue-dark); }
.gate .field-error { color: #b32d2e; font-size: var(--t-small); margin: 8px 0 0; }
.gate .hp { position: absolute; left: -9999px; }

.gate .foot-note { font-size: var(--t-body); color: var(--pp-body); margin: 24px 0 0; max-width: var(--measure-tight); }

/* ---------- text pages ---------- */
.page-head { background: var(--pp-tint); padding-block: var(--sec-y-tight); }
.page-head h1 { font-size: var(--t-h1); margin: 0; }
.page-head p { margin: 12px 0 0; color: var(--pp-body); max-width: var(--measure); font-size: var(--t-body); }
.prose { padding-block: var(--sec-y-tight) var(--sec-y); }
.prose .col { max-width: var(--measure); }
.prose h2 { font-size: var(--t-h2); margin: var(--s-7) 0 var(--s-3); }
.prose h3 { font-size: var(--t-lead); margin: var(--s-6) 0 var(--s-2); }
.prose h2:first-child { margin-top: 0; }
.prose p, .prose li { font-size: var(--t-body); color: var(--pp-body); }
.prose ul { padding-left: 24px; margin: 0 0 1em; }
.prose li { margin-bottom: 8px; }
.prose a { color: var(--pp-blue); }
.reviewed { font-size: var(--t-small); color: var(--pp-muted); margin: 0 0 24px; }
.draft { background: #fff8e6; border: 1px solid #f0d89a; border-radius: var(--r-sm); padding: var(--s-4); font-size: var(--t-caption); color: #7a5c15; margin-bottom: var(--s-6); max-width: var(--measure); }
.tbl-wrap { overflow-x: auto; border: 1px solid var(--pp-line); border-radius: var(--r-md); }
table.data { border-collapse: collapse; width: 100%; font-size: var(--t-small); min-width: 520px; }
/* The Test Reports table is the site's flagship evidence surface - five
   columns of batch ids and purity figures - and it was set in proportional
   figures, so the numbers did not even line up in their own columns. A supplier
   whose entire pitch is documented paperwork was typing its paperwork as prose. */
table.data th, table.data td { border-bottom: 1px solid var(--pp-line); padding: 12px 16px; text-align: left; }
table.data td { font-variant-numeric: tabular-nums slashed-zero; }
table.data tr:last-child td { border-bottom: 0; }
table.data th { font-size: var(--t-caption); text-transform: uppercase; letter-spacing: .05em; color: var(--pp-muted); font-weight: 500; background: var(--pp-tint); }
table.data tbody tr:hover { background: var(--pp-tint); }
table.data a { color: var(--pp-blue); }
.pending { color: var(--pp-muted); font-size: var(--t-caption); }
.contact-grid { display: grid; grid-template-columns: 1fr minmax(0, 390px); gap: var(--gap-col); align-items: start; }
/* grid items default to min-width:auto and refuse to shrink below their content */
.contact-grid > * { min-width: 0; }
@media (max-width: 880px) { .contact-grid { grid-template-columns: 1fr; gap: 32px; } }
.cform { background: #fff; border: 1px solid var(--pp-line); border-radius: var(--r-lg); padding: 24px; display: grid; gap: 16px; box-shadow: var(--shadow-1); }
.cform label { font-size: var(--t-small); font-weight: 500; display: block; margin-bottom: 8px; }
.cform input:not([type=checkbox]):not([type=radio]), .cform textarea, .cform select { width: 100%; font: inherit; font-size: var(--t-body); padding: 12px 12px; border: 1px solid var(--pp-line); border-radius: var(--r-sm); background: #fff; }
.cform input:not([type=checkbox]):not([type=radio]):focus, .cform textarea:focus, .cform select:focus { border-color: var(--pp-blue); outline: none; box-shadow: 0 0 0 3px rgba(47,86,201,.13); }
.cform input[type=checkbox], .cform input[type=radio] { width: auto; flex: none; accent-color: var(--pp-blue); }
.cform label.check, .cform label:has(> input[type=radio]) { display: flex; gap: 10px; align-items: flex-start; font-weight: 400; }
.cform textarea { min-height: 112px; resize: vertical; }

/* ---------- cart, checkout, account ---------- */
/* Every section wrapper here sets padding-block, never the padding shorthand.
   A shorthand on an element that also carries .wrap zeroes its side gutters,
   which is how the cart and checkout lost theirs twice. tests/node/gutters.test.mjs
   fails the build if it comes back. */
.shop-page { padding-block: var(--sec-y-tight) var(--sec-y); }
.shop-page > .wrap > h1 { font-size: var(--t-h1); margin: 0 0 24px; }
.shop-page .woocommerce-notices-wrapper:empty { display: none; }

.cart-grid { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: var(--gap-panel); align-items: start; }
/* grid items default to min-width:auto and refuse to shrink below their content */
.cart-grid > * { min-width: 0; }
@media (max-width: 900px) { .cart-grid { grid-template-columns: 1fr; } }

.cart-item { display: flex; gap: 12px; align-items: center; min-width: 210px; }
.cart-item img { width: 60px; height: 60px; border-radius: var(--r-sm); background: var(--pp-tint); flex: none; object-fit: cover; }
.cart-item a { color: var(--pp-blue); }
.cart-item small { display: block; color: var(--pp-muted); font-size: var(--t-caption); }
.cart-qty input { width: 5.5em; font: inherit; font-size: var(--t-small); padding: 8px 12px; border: 1px solid var(--pp-control-line); border-radius: var(--r-sm); }
.cart-remove { color: var(--pp-muted); font-size: var(--t-caption); text-decoration: underline; }
.cart-remove:hover { color: #b32d2e; }
.coupon-row { display: flex; gap: 12px; margin-top: 24px; flex-wrap: wrap; }
.coupon-row input { font: inherit; font-size: var(--t-body); padding: 12px 12px; border: 1px solid var(--pp-control-line); border-radius: var(--r-sm); }
.coupon-row input:focus { border-color: var(--pp-blue); outline: none; box-shadow: 0 0 0 3px rgba(47,86,201,.13); }

.panel { background: var(--pp-tint); border-radius: var(--r-md); padding: 24px; }
.panel > h2 { font-size: var(--t-h3); margin: 0 0 16px; }
.panel .note { font-size: var(--t-caption); color: var(--pp-muted); margin: 16px 0 0; }
.sum { display: grid; gap: 12px; font-size: var(--t-body); }
.sum .row { display: flex; justify-content: space-between; gap: 16px; align-items: baseline; }
.sum .row > span:first-child { color: var(--pp-body); }
/* prices stack in a column; proportional digits make them ragged */
/* subtotal/shipping/tax were Atkinson 700 while Total beside them was Archivo
   600 - the same money in one box in two typefaces. */
.sum b, .sum .amount { font-family: var(--f-display); font-weight: 600; font-variant-numeric: tabular-nums slashed-zero; letter-spacing: var(--track-display); }
.sum hr { border: 0; border-top: 1px solid var(--pp-line); margin: 8px 0; width: 100%; }
.sum .total { font-size: var(--t-lead); font-weight: 700; font-family: var(--f-display); letter-spacing: var(--track-display); }
.sum .discount b { color: #1c7c4a; }

.co-grid { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: var(--gap-panel); align-items: start; }
.co-grid > * { min-width: 0; }
@media (max-width: 900px) { .co-grid { grid-template-columns: 1fr; } }
/* the summary tracks the sticky header, not the viewport top, or it hides under it */
.co-summary { position: sticky; top: calc(var(--head-h, 96px) + 18px); }
@media (max-width: 900px) { .co-summary { position: static; } }
/* a notice focused or scrolled into view natively stops below the sticky header,
   not under it; WooCommerce's own animated scroll is handled in site.js */
.woocommerce-notices-wrapper, .woocommerce-NoticeGroup, .woocommerce-error, .woocommerce-message, .woocommerce-info { scroll-margin-top: calc(var(--head-h, 96px) + var(--s-5)); }
.co-line { display: flex; gap: 12px; align-items: center; margin-bottom: 16px; font-size: var(--t-small); }
.co-line img { width: 56px; height: 56px; border-radius: var(--r-sm); background: #fff; flex: none; object-fit: cover; }
.co-line small { display: block; color: var(--pp-muted); }
.co-line b { margin-left: auto; font-size: var(--t-body); font-variant-numeric: tabular-nums; }
.co-lines { border-bottom: 1px solid var(--pp-line); margin-bottom: 16px; }

.fset { border: 0; padding: 0; margin: 16px 0 0; min-width: 0; }
.fset legend { font-family: var(--f-display); font-size: var(--t-h3); font-weight: 600; padding: 0; line-height: var(--lh-heading); }
.pay-list { display: grid; gap: 12px; margin-top: 12px; padding: 0; list-style: none; }
.pay-opt { border: 1px solid var(--pp-control-line); border-radius: var(--r-sm); padding: 12px 16px; font-size: var(--t-body); background: #fff; }
.pay-opt label { display: flex; gap: 12px; align-items: flex-start; font-weight: 400; margin: 0; cursor: pointer; }
.pay-opt input[type=radio] { margin-top: 4px; flex: none; accent-color: var(--pp-blue); }
.pay-opt b { font-weight: 500; }
.pay-opt small, .pay-opt .payment_box p { display: block; color: var(--pp-muted); font-size: var(--t-small); margin: 4px 0 0; }
.pay-opt:has(input:checked) { border-color: var(--pp-blue); box-shadow: 0 0 0 3px rgba(47,86,201,.10); }
.row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.row-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 12px; }
@media (max-width: 560px) { .row-2, .row-3 { grid-template-columns: 1fr; } }

/* order received */
.thanks-head { background: var(--pp-tint); padding-block: var(--sec-y-tight); }
.thanks-head h1 { font-size: var(--t-h1); margin: 0 0 12px; }
.thanks-head p { margin: 0; color: var(--pp-body); font-size: var(--t-body); max-width: var(--measure); }
.pay-instructions { background: #fff8e6; border: 1px solid #f0d89a; border-radius: var(--r-sm); padding: 16px 24px; margin: 0 0 32px; max-width: var(--measure); }
.pay-instructions h2 { font-size: var(--t-h3); margin: 0 0 8px; }
.pay-instructions p { font-size: var(--t-body); color: #5d4708; margin: 0 0 8px; }
.pay-instructions p:last-child { margin-bottom: 0; }

/* my account: WooCommerce's own markup, mapped onto the store's type and spacing */
.acct-grid { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: var(--gap-panel); align-items: start; }
@media (max-width: 780px) { .acct-grid { grid-template-columns: 1fr; } }
.woocommerce-MyAccount-navigation ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.woocommerce-MyAccount-navigation a { display: block; padding: 12px 16px; border-radius: var(--r-sm); font-size: var(--t-small); color: var(--pp-body); }
.woocommerce-MyAccount-navigation a:hover { background: var(--pp-tint); color: var(--pp-blue); }
.woocommerce-MyAccount-navigation .is-active a { background: var(--pp-blue); color: #fff; }
.woocommerce-MyAccount-content p, .woocommerce-MyAccount-content li { font-size: var(--t-body); color: var(--pp-body); }
.woocommerce-MyAccount-content h2, .woocommerce-MyAccount-content h3 { font-size: var(--t-h3); margin: 32px 0 12px; }
.woocommerce-MyAccount-content h2:first-child { margin-top: 0; }

/* ---------- WooCommerce's own cart, checkout and account markup ----------
   These templates are not overridden. cart.php and form-checkout.php are ~200
   lines of hooks, nonces and filters each, and a fork of them becomes ours to
   re-merge on every WooCommerce release. Styling what they already print costs
   one block of CSS and survives updates. Class names below are WooCommerce's. */
.woocommerce-notices-wrapper:empty { display: none; }
.woocommerce-message, .woocommerce-info, .woocommerce-error {
  list-style: none; margin: 0 0 24px; padding: 16px 16px; border-radius: var(--r-sm);
  font-size: var(--t-body); border: 1px solid var(--pp-line); background: var(--pp-tint); color: var(--pp-ink);
}
.woocommerce-error { background: #fdf2f2; border-color: #f0c2c2; color: #8a2222; }
.woocommerce-message { background: #f1f9f4; border-color: #bfe3cd; color: #1c5c38; }
.woocommerce-message .button, .woocommerce-info .button { float: right; }

/* the cart table */
table.shop_table { border-collapse: collapse; width: 100%; font-size: var(--t-small); border: 1px solid var(--pp-line); border-radius: var(--r-md); overflow: hidden; }
table.shop_table th, table.shop_table td { border-bottom: 1px solid var(--pp-line); padding: 16px 16px; text-align: left; vertical-align: middle; }
table.shop_table tr:last-child td { border-bottom: 0; }
table.shop_table thead th { font-size: var(--t-caption); text-transform: uppercase; letter-spacing: .05em; color: var(--pp-muted); font-weight: 500; background: var(--pp-tint); }
table.shop_table .product-thumbnail img { width: 60px; height: 60px; border-radius: var(--r-sm); background: var(--pp-tint); object-fit: cover; display: block; }
table.shop_table .product-name a { color: var(--pp-ink); font-weight: 500; }
table.shop_table .product-name a:hover { color: var(--pp-blue); }
table.shop_table .product-price, table.shop_table .product-subtotal, table.shop_table td.product-total { font-variant-numeric: tabular-nums; }
table.shop_table .product-subtotal, table.shop_table td.product-total { font-weight: 600; }
table.shop_table .variation { margin: 4px 0 0; font-size: var(--t-caption); color: var(--pp-muted); display: flex; flex-wrap: wrap; gap: 0 8px; }
table.shop_table .variation dt, table.shop_table .variation dd { margin: 0; }
table.shop_table a.remove { display: grid; place-items: center; width: 28px; height: 28px; border-radius: var(--r-sm); color: var(--pp-muted); font-size: 1.25rem; line-height: 1; text-decoration: none; }
table.shop_table a.remove:hover { color: #b32d2e; background: var(--pp-tint); }
.quantity input.qty { width: 5.5em; font: inherit; font-size: var(--t-small); padding: 8px 12px; border: 1px solid var(--pp-control-line); border-radius: var(--r-sm); text-align: center; }
.quantity input.qty:focus { border-color: var(--pp-blue); outline: none; box-shadow: 0 0 0 3px rgba(47,86,201,.13); }
td.actions { background: var(--pp-tint); }
td.actions .coupon { display: inline-flex; gap: 12px; flex-wrap: wrap; margin-right: 12px; }
td.actions input#coupon_code { font: inherit; font-size: var(--t-small); padding: 12px 12px; border: 1px solid var(--pp-control-line); border-radius: var(--r-sm); }
/* checkout's "Have a coupon?" form: one row like the cart's, not the name-field
   halves it borrows (top-aligned, button shorter than the input) */
.woocommerce form.checkout_coupon { display: flex; gap: var(--s-3); }
.woocommerce form.checkout_coupon .form-row-first, .woocommerce form.checkout_coupon .form-row-last { display: flex; width: auto; margin: 0; }
.woocommerce form.checkout_coupon .form-row-first { flex: 1; min-width: 0; }
.woocommerce form.checkout_coupon .form-row-first input.input-text { width: 100%; }
.woocommerce form.checkout_coupon .clear { display: none; }

/* WooCommerce prints .button; give it the store's primary shape once, here,
   rather than adding classes through a dozen filters */
.woocommerce .button, .woocommerce button.button, .woocommerce input.button, .woocommerce a.button {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font: inherit; font-size: var(--t-small); font-weight: 500; padding: 12px 24px;
  border-radius: var(--r-sm); border: 1px solid #cfd8f5; background: transparent;
  color: var(--pp-blue); cursor: pointer; transition: background .18s, color .18s, border-color .18s;
}
.woocommerce .button:hover { background: var(--pp-tint); border-color: var(--pp-blue); }
.woocommerce .button.alt, .woocommerce button.button.alt, .woocommerce #place_order {
  background: var(--pp-blue); border-color: var(--pp-blue); color: #fff;
}
.woocommerce .button.alt:hover, .woocommerce #place_order:hover { background: var(--pp-blue-dark); border-color: var(--pp-blue-dark); }
.woocommerce .button:disabled, .woocommerce .button[disabled] { background: var(--pp-line); border-color: var(--pp-line); color: var(--pp-muted); cursor: not-allowed; }

/* cart totals: WooCommerce's own panel, wearing .panel's clothes */
.cart-collaterals .cart_totals { background: var(--pp-tint); border-radius: var(--r-md); padding: 24px; }
.cart-collaterals .cart_totals h2 { font-size: var(--t-h3); margin: 0 0 16px; }
.cart-collaterals .cart_totals table.shop_table { border: 0; background: none; font-size: var(--t-body); }
.cart-collaterals .cart_totals table.shop_table th,
.cart-collaterals .cart_totals table.shop_table td { padding: 8px 0; border-bottom: 0; background: none; text-transform: none; letter-spacing: 0; font-size: inherit; }
.cart-collaterals .cart_totals table.shop_table th { color: var(--pp-body); font-weight: 400; }
.cart-collaterals .cart_totals table.shop_table td { text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }
.cart-collaterals .cart_totals tr.order-total th, .cart-collaterals .cart_totals tr.order-total td {
  border-top: 1px solid var(--pp-line); padding-top: 16px; font-family: var(--f-display); font-size: var(--t-lead); font-weight: 600;
}
.cart-collaterals .cart_totals tr.cart-discount td { color: #1c7c4a; }
.cart-collaterals .shipping ul#shipping_method { list-style: none; margin: 0; padding: 0; text-align: right; }
.cart-collaterals .shipping ul#shipping_method li { margin-bottom: 4px; }
.cart-collaterals .woocommerce-shipping-destination { font-size: var(--t-caption); color: var(--pp-muted); font-weight: 400; }
.wc-proceed-to-checkout { margin-top: 16px; }
.wc-proceed-to-checkout a.checkout-button { width: 100%; }
.cart-empty, .return-to-shop { font-size: var(--t-body); }
.return-to-shop { margin-top: 16px; }

/* checkout form rows */
.woocommerce form .form-row { display: block; margin: 0 0 16px; }
.woocommerce form .form-row label { font-size: var(--t-small); font-weight: 500; display: block; margin-bottom: 8px; }
.woocommerce form .form-row .required { color: #b32d2e; text-decoration: none; border: 0; }
.woocommerce form .form-row .optional { color: var(--pp-muted); font-weight: 400; }
.woocommerce form .form-row input.input-text,
.woocommerce form .form-row textarea,
.woocommerce form .form-row select,
.woocommerce form .form-row .select2-selection {
  width: 100%; font: inherit; font-size: var(--t-body); padding: 12px 12px;
  border: 1px solid var(--pp-control-line); border-radius: var(--r-sm); background: #fff; color: var(--pp-ink);
}
.woocommerce form .form-row input.input-text:focus,
.woocommerce form .form-row textarea:focus,
.woocommerce form .form-row select:focus {
  border-color: var(--pp-blue); outline: none; box-shadow: 0 0 0 3px rgba(47,86,201,.13);
}
.woocommerce form .form-row textarea { min-height: 96px; resize: vertical; }
.woocommerce form .form-row.woocommerce-invalid input.input-text { border-color: #b32d2e; }
/* WooCommerce lays first/last name out with these two halves */
.woocommerce form .form-row-first, .woocommerce form .form-row-last { display: inline-block; width: calc(50% - 6px); vertical-align: top; }
.woocommerce form .form-row-first { margin-right: 12px; }
@media (max-width: 560px) {
  .woocommerce form .form-row-first, .woocommerce form .form-row-last { display: block; width: 100%; margin-right: 0; }
}
#customer_details h3, .woocommerce-billing-fields h3, .woocommerce-shipping-fields h3,
#order_review_heading, .woocommerce-additional-fields h3 {
  font-family: var(--f-display); font-size: var(--t-h3); font-weight: 600; margin: 0 0 16px;
}
#order_review_heading { margin-top: 0; }

/* checkout review and payment */
#order_review { background: var(--pp-tint); border-radius: var(--r-md); padding: 24px; }
#order_review table.shop_table { border: 0; background: none; font-size: var(--t-small); }
#order_review table.shop_table th, #order_review table.shop_table td { padding: 8px 0; background: none; text-transform: none; letter-spacing: 0; border-bottom: 0; }
#order_review table.shop_table thead th { font-size: var(--t-caption); text-transform: uppercase; letter-spacing: .05em; color: var(--pp-muted); border-bottom: 1px solid var(--pp-line); padding-bottom: 12px; }
#order_review table.shop_table td { text-align: right; font-variant-numeric: tabular-nums; }
#order_review table.shop_table td.product-name { text-align: left; }
#order_review table.shop_table tfoot th { color: var(--pp-body); font-weight: 400; font-size: var(--t-body); }
#order_review table.shop_table tfoot td { font-weight: 600; font-size: var(--t-body); }
#order_review table.shop_table tfoot tr:first-child th, #order_review table.shop_table tfoot tr:first-child td { padding-top: 16px; border-top: 1px solid var(--pp-line); }
#order_review table.shop_table tfoot tr.order-total th, #order_review table.shop_table tfoot tr.order-total td {
  font-family: var(--f-display); font-size: var(--t-lead); font-weight: 600; border-top: 1px solid var(--pp-line); padding-top: 16px;
}
ul.wc_payment_methods { list-style: none; margin: 16px 0; padding: 0; display: grid; gap: 12px; }
li.wc_payment_method { border: 1px solid var(--pp-control-line); border-radius: var(--r-sm); background: #fff; padding: 12px 16px; }
li.wc_payment_method > label { display: inline-flex; gap: 12px; align-items: center; font-size: var(--t-body); font-weight: 500; margin: 0; cursor: pointer; }
li.wc_payment_method > input[type=radio] { accent-color: var(--pp-blue); }
li.wc_payment_method:has(input:checked) { border-color: var(--pp-blue); box-shadow: 0 0 0 3px rgba(47,86,201,.10); }
li.wc_payment_method .payment_box { margin: 12px 0 0; padding: 12px 16px; background: var(--pp-tint); border-radius: var(--r-sm); }
li.wc_payment_method .payment_box p { margin: 0 0 8px; font-size: var(--t-small); color: var(--pp-body); line-height: var(--lh-body); }
li.wc_payment_method .payment_box p:last-child { margin-bottom: 0; }
.woocommerce-terms-and-conditions-wrapper { margin: 16px 0; }
.form-row.place-order { margin: 0; }
#place_order { width: 100%; }

/* The two attestations. purity-core renders each as its own p.form-row via
   woocommerce_form_field, so these target the field, not a wrapper: the input
   sits inside the label, ahead of the text. */
.purity-attest { margin: 0 0 16px; }
.purity-attest:first-of-type { margin-top: 16px; }
.purity-attest label { display: flex; gap: 12px; align-items: flex-start; font-size: var(--t-small); color: var(--pp-body); line-height: var(--lh-body); font-weight: 400; margin: 0; }
.purity-attest input[type=checkbox] { margin-top: 3px; flex: none; accent-color: var(--pp-blue); width: auto; }
.purity-attest abbr.required { color: #b32d2e; text-decoration: none; border: 0; }
.purity-attest a { color: var(--pp-blue); text-decoration: underline; }

/* Undoing Kadence's WooCommerce sheet.
   These selectors are deliberately as specific as the ones they beat - Kadence
   uses "#payment ul.wc_payment_methods li.wc_payment_method > label" and
   ".woocommerce form .form-row label", so a shorter selector of ours loses no
   matter which stylesheet loads last. This block is the only place in the file
   that writes a selector for weight rather than for meaning. */

/* A 5px coloured stripe down one edge is decoration standing in for hierarchy.
   The border and the background already say which method is selected. */
#payment ul.wc_payment_methods li.wc_payment_method > label,
#payment ul.wc_payment_methods li.wc_payment_method > label:hover,
#payment ul.wc_payment_methods li.wc_payment_method input[type=radio]:first-child:checked + label {
  border-left: 0; background: transparent; padding: 0; margin-bottom: 0;
  font-weight: 500; font-size: var(--t-body); display: inline-flex;
}
.woocommerce .woocommerce-info, .woocommerce .woocommerce-message, .woocommerce .woocommerce-error {
  border-left-width: 1px; border-left-style: solid; border-left-color: inherit;
}
.woocommerce .woocommerce-info { border-color: var(--pp-line); }
.woocommerce .woocommerce-message { border-color: #bfe3cd; }
.woocommerce .woocommerce-error { border-color: #f0c2c2; }

/* Kadence sets every checkout label to line-height 2.4 and bold at 90% size.
   That is sensible for a one-word field label and wrong for a four-line legal
   attestation, which is what these two are. */
/* Deliberately NOT flex. WooCommerce puts the checkbox, the label text and the
   required marker inside one <label> as siblings, so flex makes each its own
   item and the trailing * ends up on a line of its own or off the end. A
   hanging indent keeps the text and its marker in one normal inline flow. */
.woocommerce form .form-row.purity-attest label,
.woocommerce form .form-row.purity-attest label.checkbox {
  display: block; position: relative; padding-left: 24px; margin: 0;
  line-height: var(--lh-body); font-weight: 400; font-size: var(--t-small); color: var(--pp-body);
}
.woocommerce form .form-row.purity-attest .input-checkbox {
  position: absolute; left: 0; top: 5px; margin: 0; accent-color: var(--pp-blue);
}
.woocommerce form .form-row.purity-attest .required { color: #b32d2e; text-decoration: none; border: 0; }

/* ---------- cart and checkout page layout ----------
   Both pages are laid out on the containers WooCommerce already prints, so
   there are no wrapper divs opened in one hook and closed in another. */
.woocommerce-cart .shop-page .woocommerce { display: block; }
/* Kadence inserts .kadence-woo-cart-form-wrap between .woocommerce and the two
   columns, so the grid has to go on whichever element actually holds the cart
   form. Matched by what it contains rather than by a class name, because that
   name belongs to the parent theme and can change under us on any update. */
.woocommerce-cart .shop-page .woocommerce:has(> .woocommerce-cart-form),
.woocommerce-cart .shop-page .woocommerce > *:has(> .woocommerce-cart-form) {
  display: grid; grid-template-columns: minmax(0, 1fr) 340px;
  gap: var(--gap-panel); align-items: start;
}
/* notices and the empty-cart message are page-wide, not a column */
.woocommerce-cart .shop-page .woocommerce > .woocommerce-notices-wrapper,
.woocommerce-cart .shop-page .woocommerce > .cart-empty,
.woocommerce-cart .shop-page .woocommerce > .return-to-shop,
.woocommerce-cart .shop-page .woocommerce > .wc-empty-cart-message { grid-column: 1 / -1; }
/* Kadence still ships the pre-grid WooCommerce layout: it floats these two,
   gives them percentage widths and places them on its own grid. A grid item
   with an explicit width does not stretch to its track, and its placement was
   putting the cart form in the second column and the totals in the first, so
   both are stated outright here rather than left to auto-placement. */
.woocommerce-cart .shop-page .woocommerce-cart-form {
  grid-area: 1 / 1 / 2 / 2;
  width: auto; max-width: none; float: none; margin: 0; padding-left: 0; padding-right: 0;
}
.woocommerce-cart .shop-page .cart-collaterals {
  grid-area: 1 / 2 / 2 / 3;
  width: auto; max-width: none; float: none; margin: 0; padding-left: 0; padding-right: 0;
}
@media (max-width: 900px) {
  .woocommerce-cart .shop-page .woocommerce:has(> .woocommerce-cart-form),
  .woocommerce-cart .shop-page .woocommerce > *:has(> .woocommerce-cart-form) { grid-template-columns: 1fr; }
  .woocommerce-cart .shop-page .woocommerce-cart-form { grid-area: 1 / 1 / 2 / 2; }
  .woocommerce-cart .shop-page .cart-collaterals { grid-area: 2 / 1 / 3 / 2; }
}
/* the page's own h1 already says Cart; WooCommerce's heading stays for screen
   readers rather than being removed from the document */
.woocommerce-cart .cart-summary > h2:first-child {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}
table.cart .product-thumbnail { width: 92px; }
table.cart .product-name { width: 38%; }
table.cart .product-remove { width: 44px; padding-right: 0; }
/* the shipping cell holds a list, a destination line and a calculator toggle;
   right-aligning the lot puts the method's own text against the panel edge */
.cart_totals tr.shipping td { text-align: right; font-weight: 400; }
.cart_totals ul#shipping_method { list-style: none; }
.cart_totals ul#shipping_method li { list-style: none; }
.cart_totals ul#shipping_method label { font-size: var(--t-small); font-weight: 500; }
.cart_totals .woocommerce-shipping-destination { display: block; margin: 8px 0 0; font-size: var(--t-caption); color: var(--pp-muted); font-weight: 400; }
.cart_totals .woocommerce-shipping-calculator > a { font-size: var(--t-caption); font-weight: 400; color: var(--pp-blue); text-decoration: underline; }
.cart_totals .shipping-calculator-form { margin-top: 12px; text-align: left; }

.woocommerce-checkout form.checkout {
  display: grid; grid-template-columns: minmax(0, 1fr) 380px;
  gap: 0 var(--gap-panel); align-items: start;
}
/* anything WooCommerce or a plugin adds to the form spans both columns and
   lands below, instead of colliding with the summary */
.woocommerce-checkout form.checkout > * { grid-column: 1 / -1; }
.woocommerce-checkout form.checkout > #customer_details { grid-area: 1 / 1 / 3 / 2; }
.woocommerce-checkout form.checkout > #order_review_heading { grid-area: 1 / 2 / 2 / 3; }
.woocommerce-checkout form.checkout > #order_review { grid-area: 2 / 2 / 3 / 3; position: sticky; top: calc(var(--head-h, 96px) + 18px); }
/* Kadence gives all three percentage widths and floats them, exactly as it does
   on the cart. A grid item with an explicit width ignores its track, which left
   the order summary 190px wide and wrapping the attestation one word per line. */
.woocommerce-checkout form.checkout > #customer_details,
.woocommerce-checkout form.checkout > #order_review_heading,
.woocommerce-checkout form.checkout > #order_review {
  width: auto; max-width: none; float: none; margin-left: 0; margin-right: 0; padding-left: 0; padding-right: 0;
}
/* billing above shipping in one column: the reference asks for one address form */
#customer_details.col2-set { display: grid; grid-template-columns: 1fr; gap: 0; }
#customer_details .col-1, #customer_details .col-2 { width: auto; max-width: none; float: none; padding-left: 0; padding-right: 0; }
@media (max-width: 900px) {
  .woocommerce-checkout form.checkout { grid-template-columns: 1fr; gap: 0; }
  .woocommerce-checkout form.checkout > #customer_details,
  .woocommerce-checkout form.checkout > #order_review_heading,
  .woocommerce-checkout form.checkout > #order_review { grid-area: auto; grid-column: 1 / -1; position: static; }
  .woocommerce-checkout form.checkout > #order_review_heading { margin-top: 32px; }
}

/* Kadence wraps the account nav in .account-navigation-wrap and gives both
   columns fixed widths, the same way it does on the cart and the checkout, so
   the two are placed outright here rather than left to auto-placement. */
.woocommerce-account.logged-in .shop-page .woocommerce {
  display: grid; grid-template-columns: 220px minmax(0, 1fr);
  gap: var(--gap-panel); align-items: start;
}
.woocommerce-account .shop-page .woocommerce > .woocommerce-notices-wrapper { grid-column: 1 / -1; }
.woocommerce-account .shop-page :is(.account-navigation-wrap, .woocommerce-MyAccount-navigation) {
  grid-area: 1 / 1 / 2 / 2; width: auto; max-width: none; float: none; margin: 0; padding-left: 0; padding-right: 0; border: 0;
}
.woocommerce-account .shop-page .woocommerce-MyAccount-content {
  grid-area: 1 / 2 / 2 / 3; width: auto; max-width: none; float: none; margin: 0; padding-left: 0; padding-right: 0;
}
/* the login and lost-password screens have no account nav to sit beside */
.woocommerce-account:not(.logged-in) .shop-page .woocommerce { display: block; }
@media (max-width: 780px) {
  .woocommerce-account.logged-in .shop-page .woocommerce { grid-template-columns: 1fr; }
  .woocommerce-account .shop-page :is(.account-navigation-wrap, .woocommerce-MyAccount-navigation) { grid-area: 1 / 1 / 2 / 2; }
  .woocommerce-account .shop-page .woocommerce-MyAccount-content { grid-area: 2 / 1 / 3 / 2; }
}

/* order received */
.woocommerce-order-overview { list-style: none; margin: 0 0 32px; padding: 24px 24px; background: var(--pp-tint); border-radius: var(--r-md); display: flex; flex-wrap: wrap; gap: 12px 32px; font-size: var(--t-small); }
.woocommerce-order-overview li { color: var(--pp-muted); }
.woocommerce-order-overview li strong { display: block; color: var(--pp-ink); font-size: var(--t-body); font-weight: 600; margin-top: 3px; }
.woocommerce-order-details, .woocommerce-customer-details { margin-bottom: 32px; }
.woocommerce-order-details h2, .woocommerce-customer-details h2, .woocommerce-column__title { font-size: var(--t-h3); margin: 0 0 16px; }
.woocommerce-thankyou-order-received { font-size: var(--t-lead); margin: 0 0 24px; }

/* ---------- cart drawer ----------
   The panel's contents are whatever woocommerce_mini_cart() prints, so these
   rules target WooCommerce's own class names rather than a structure of ours.
   The remove link is first in its source order and the image lives inside the
   product link, so the item is positioned rather than laid out in a grid. */
.drawer { position: fixed; inset: 0; z-index: var(--z-modal); }
.drawer[hidden] { display: none; }
.drawer-scrim { position: absolute; inset: 0; background: rgba(8,17,40,.46); opacity: 0; transition: opacity .26s var(--ease); }
.drawer[data-open] .drawer-scrim { opacity: 1; }
.drawer-panel { position: absolute; top: 0; right: 0; height: 100%; width: min(410px, 100%); background: #fff; box-shadow: -10px 0 40px rgba(8,17,40,.20); display: flex; flex-direction: column; transform: translateX(100%); transition: transform .3s var(--ease); }
.drawer[data-open] .drawer-panel { transform: none; }
@media (prefers-reduced-motion: reduce) { .drawer-panel, .drawer-scrim { transition: none; } }

.drawer-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 16px 24px; border-bottom: 1px solid var(--pp-line); flex: none; }
.drawer-head h2 { font-size: var(--t-h3); margin: 0; }
/* Kadence styles every bare <button> as a filled primary, which made the close
   control read as the loudest thing in the panel */
.drawer .drawer-close, .drawer .drawer-close:hover, .drawer .drawer-close:focus {
  background: none; border: 0; box-shadow: none; font: inherit; font-size: 1.6rem;
  line-height: 1; color: var(--pp-muted); cursor: pointer; padding: 4px 12px;
  border-radius: var(--r-sm); min-height: 0; text-transform: none; letter-spacing: 0;
}
.drawer .drawer-close:hover { color: var(--pp-ink); background: var(--pp-tint); }

/* a flex column so the list scrolls and the total and buttons stay pinned;
   min-height:0 is what actually lets a flex child scroll instead of growing */
.drawer-body { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.drawer-body ul.cart_list { flex: 1; min-height: 0; overflow-y: auto; list-style: none; margin: 0; padding: 4px 24px; }
.drawer-body li.mini_cart_item { position: relative; padding: 16px 32px 16px 0; border-bottom: 1px solid var(--pp-line); font-size: var(--t-small); }
.drawer-body li.mini_cart_item:last-child { border-bottom: 0; }
.drawer-body li.mini_cart_item > a:not(.remove) { display: grid; grid-template-columns: 54px minmax(0, 1fr); gap: 12px; align-items: center; color: var(--pp-ink); font-weight: 500; }
.drawer-body li.mini_cart_item img { width: 54px; height: 54px; border-radius: var(--r-sm); object-fit: cover; background: var(--pp-tint); }
.drawer-body li.mini_cart_item .quantity { display: block; margin: 8px 0 0 64px; color: var(--pp-muted); font-variant-numeric: tabular-nums; }
.drawer-body li.mini_cart_item a.remove { position: absolute; right: 0; top: 16px; width: 28px; height: 28px; display: grid; place-items: center; color: var(--pp-muted); font-size: 1.25rem; line-height: 1; text-decoration: none; border-radius: var(--r-sm); }
.drawer-body li.mini_cart_item a.remove:hover { color: #b32d2e; background: var(--pp-tint); }
.drawer-body .woocommerce-mini-cart__empty-message { margin: 0; padding: 24px 24px; color: var(--pp-muted); font-size: var(--t-body); }
.drawer-body .woocommerce-mini-cart__total { flex: none; display: flex; justify-content: space-between; gap: 12px; margin: 0; padding: 16px 24px 12px; border-top: 1px solid var(--pp-line); font-size: var(--t-lead); font-weight: 600; font-family: var(--f-display); }
.drawer-body .woocommerce-mini-cart__total .amount { font-variant-numeric: tabular-nums; }
.drawer-body .woocommerce-mini-cart__buttons { flex: none; display: grid; gap: 12px; margin: 0; padding: 0 22px calc(22px + env(safe-area-inset-bottom, 0px)); }
/* WooCommerce prints plain links here; give them the store's button shape
   without needing an override of mini-cart.php just to add two classes */
.drawer-body .woocommerce-mini-cart__buttons a { display: inline-flex; align-items: center; justify-content: center; font-size: var(--t-small); font-weight: 500; padding: 12px 24px; border-radius: var(--r-sm); border: 1px solid #cfd8f5; color: var(--pp-blue); background: transparent; }
.drawer-body .woocommerce-mini-cart__buttons a:hover { background: var(--pp-tint); border-color: var(--pp-blue); }
.drawer-body .woocommerce-mini-cart__buttons a.checkout { background: var(--pp-blue); border-color: var(--pp-blue); color: #fff; }
.drawer-body .woocommerce-mini-cart__buttons a.checkout:hover { background: var(--pp-blue-dark); }

/* ---------- reveal (enhancement only) ---------- */
@media (prefers-reduced-motion: no-preference) {
  .js [data-reveal] { opacity: 0; transform: translateY(18px); transition: opacity .6s var(--ease), transform .6s var(--ease); }
  .js [data-reveal].in { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
  .hero-slide[data-active] .hero-copy { opacity: 1; }
  .hero-bg, .hero-stage img { transform: none; }
  .car-track { scroll-behavior: auto; }
}
