/* ==========================================================================
   BioraX 2026 pages — shared stylesheet
   --------------------------------------------------------------------------
   Every page in the redesign: homepage, Programs landing, Program detail,
   Store and Product. Consumes bx-tokens.css only.

   Scoped to `.bx-page`, a CLASS rather than an id, so more than one page can
   wear it. `.bx-page h2` is (0,1,1) against biorax.css's bare `h2` at (0,0,1),
   which is enough to win without a single !important — and enough to matter,
   because biorax.css sets colour and font-family directly on h1-h4 and the
   store runs in dark mode. Anything left to inherit renders white on the
   light bands.

   biofit-home.css is now DEAD: no template links it any more. It stopped being
   loaded the moment home.twig was rewritten, and this comment previously said
   science and calculator still needed it — they only mention it in their own
   comments. Left on disk rather than deleted here, so removing it is its own
   reviewable change.

   Homepage section order and backgrounds, measured off the mockup:
     hero          #0b0b0b   y    0- 879
     pillars       #074a77   y  879-1058
     programs      #e8e8e8   y 1061-2665
     journey       #000000   y 2668-3713
     standards     #e8e8e8   y 3717-4509   (split, image bleeds right)
     metrics       #074a77   y 4512-4691
     faq           #e8e8e8   y 4694-5695
     cta           #010101   y 5798-6062
     footer        #032338   y 6073-6572
   ========================================================================== */

.bx-page {
  background: var(--bx-dark);
  color: var(--bx-on-dark);
  font-family: var(--bx-font-sans);
  font-size: var(--bx-text-body);
  line-height: var(--bx-leading-body);
  -webkit-font-smoothing: antialiased;
}

.bx-page *, .bx-page *::before, .bx-page *::after { box-sizing: border-box; }

.bx-page .wrap {
  width: 100%;
  max-width: var(--bx-max);
  margin-inline: auto;
  padding-inline: var(--bx-gutter);
}

.bx-page img { max-width: 100%; display: block; }
.bx-page a { color: inherit; text-decoration: none; }
.bx-page p { margin: 0; }

/* This design has no display serif. biorax.css sets font-family directly on
   h1-h4, which beats inheritance, so every heading must declare its own or the
   page silently borrows Fraunces from another stylesheet. */
.bx-page h1, .bx-page h2, .bx-page h3, .bx-page h4 {
  margin: 0;
  font-family: var(--bx-font-sans);
  font-weight: 400;
  letter-spacing: var(--bx-tracking-tight);
  line-height: var(--bx-leading-tight);
}

/* ------------------------------------------------------------- eyebrow -- */
/* A short rule, then letterspaced caps — the mockup uses this on every band. */
/* Colour is declared per band, on the headings themselves.
   biorax.css sets `color` directly on h1-h4 and the store is in dark mode, so
   without this every heading on a light band renders white-on-#e8e8e8 —
   effectively invisible. Inheriting from the band wrapper is not enough
   because a direct rule beats an inherited value. */
.bx-page .band-light,
.bx-page .band-light h1, .bx-page .band-light h2,
.bx-page .band-light h3, .bx-page .band-light h4,
.bx-page .standards-copy,
.bx-page .standards-copy h1, .bx-page .standards-copy h2,
.bx-page .standards-copy h3, .bx-page .standards-copy h4 { color: var(--bx-on-light); }

.bx-page .hero h1,
.bx-page .band-dark h1, .bx-page .band-dark h2,
.bx-page .band-dark h3, .bx-page .band-dark h4,
.bx-page .band-blue h1, .bx-page .band-blue h2,
.bx-page .band-blue h3, .bx-page .band-blue h4,
.bx-page .cta-band h2,
.bx-page .program h3,
.bx-page .site-footer h4 { color: #ffffff; }

.bx-page .eyebrow {
  display: flex;
  align-items: center;
  gap: var(--bx-space-3);
  font-family: var(--bx-font-mono);
  font-size: var(--bx-text-eyebrow);
  font-weight: 500;
  letter-spacing: var(--bx-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--bx-accent);
  margin-bottom: var(--bx-space-4);
}
.bx-page .eyebrow::before {
  content: '';
  width: 26px;
  height: 1px;
  background: currentColor;
  flex: none;
}
.bx-page .eyebrow.center { justify-content: center; }
/* --bx-accent is a light blue built for dark bands. On the #e8e8e8 light band
   it measured 1.92:1 — the worst contrast on the site, and wrong against the
   design as well: sampling the Programs mockup's eyebrow where it sits on the
   light band gives #074A77, the deep brand blue, not the accent. Same colour,
   and 8.0:1 instead of 1.92:1. */
.bx-page .band-light .eyebrow,
.bx-page .standards-copy .eyebrow { color: var(--bx-blue); }

/* ------------------------------------------------------------- buttons -- */
/* .bx-btn, never .btn — Bootstrap is loaded site-wide and owns that name.
   Both fills are the same #074a77 in the mockup; there is no second blue. */
.bx-page .bx-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 12px 28px;
  border: 1px solid transparent;
  border-radius: var(--bx-radius-btn);
  font-size: var(--bx-text-sm);
  font-weight: 500;
  cursor: pointer;
  transition: background .25s var(--bx-expo), border-color .25s var(--bx-expo);
}
.bx-page .bx-btn-primary { background: var(--bx-blue); color: #fff; }
.bx-page .bx-btn-primary:hover { background: var(--bx-blue-hover); color: #fff; }

.bx-page .bx-btn-outline {
  background: transparent;
  border-color: #FFFFFF59;   /* supplied value; 0x59 is .349, not the .34 this guessed */
  color: var(--bx-on-dark);
}
.bx-page .bx-btn-outline:hover { border-color: #fff; }

.bx-page .bx-btn-outline-dark {
  background: transparent;
  border-color: rgba(11, 11, 11, 0.34);
  color: var(--bx-on-light);
}
.bx-page .bx-btn-outline-dark:hover { border-color: var(--bx-on-light); }

/* Figma puts the hero's two CTAs 20.46 apart (217:29743 ends at 329, 217:29745
   starts at 349.46) and the closing band's 19 apart. 12 was neither. */
.bx-page .btn-row { display: flex; flex-wrap: wrap; gap: 20.46px; }
/* Supplied spec: 229x47, radius 15. Scoped to .btn-row — the CTA pair in the
   hero, the CTA band, the category pages and the wishlist — so it does not
   resize block-width form submits or the product card's Add to Cart, which
   were not part of that spec. max-width keeps 229px from overflowing a narrow
   phone; .btn-row already wraps. */
.bx-page .btn-row .bx-btn {
  width: 229px;
  max-width: 100%;
  height: 47px;
  padding: 0 20px;
  border-radius: var(--bx-radius-btn);
}
.bx-page .btn-row.center { justify-content: center; }

/* ----------------------------------------------------------------- nav -- */
/* Transparent, sitting over the hero rather than above it — and sticky.

   `fixed`, not `sticky`, because this nav lives INSIDE .hero: a sticky element
   only pins within its own containing block, so it would come unstuck the
   moment the hero scrolled past. It costs no layout shift, since the nav was
   already out of flow as `absolute`. */
.bx-page .site-nav {
  /* A1. 77 in every frame — 111:1483, 79:305, 85:862. It was drawing 76. */
  min-height: 77px;
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  transition: background .25s var(--bx-expo), box-shadow .25s var(--bx-expo);
}
/* Off the top the nav sits over page content rather than the hero photograph,
   so it needs a ground of its own — the links and logo are drawn white and
   would otherwise land unreadable on the light band. */
.bx-page .site-nav.is-stuck {
  background: rgba(11, 11, 11, 0.92);
  backdrop-filter: saturate(150%) blur(12px);
  -webkit-backdrop-filter: saturate(150%) blur(12px);
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.08), 0 10px 30px rgba(0, 0, 0, 0.28);
}
@media (prefers-reduced-motion: reduce) {
  .bx-page .site-nav { transition: none; }
}
/* Pages with no hero behind the nav — the assessment and the prescription step
   — need a ground of their own. The nav is drawn in white for a dark
   photograph; over a light band the links and the logo are all but invisible. */
/* This one IS in flow at the top of the page, so sticky is correct here: it
   holds its own space and then pins, with no compensating padding needed. */
.bx-page .site-nav--solid {
  position: sticky;
  top: 0;
  background: var(--bx-dark);
}
.bx-page .site-nav--solid.is-stuck { box-shadow: 0 10px 30px rgba(0, 0, 0, 0.28); }
.bx-page .nav-bar {
  display: flex;
  align-items: center;
  gap: var(--bx-space-6);
  min-height: 76px;
}
.bx-page .brand { flex: none; }
.bx-page .brand img { width: 141px; height: auto; display: block; }  /* mockup: 141x23 at a 1521 page */

.bx-page .nav-links {
  display: flex;
  align-items: center;
  gap: clamp(1.25rem, 2.6vw, 2.6rem);
  margin-inline: auto;
  font-size: var(--bx-text-sm);
  color: var(--bx-on-dark-muted);
}
.bx-page .nav-links a { transition: color .2s var(--bx-expo); }
.bx-page .nav-links a:hover,
.bx-page .nav-links a.is-active { color: #fff; font-weight: 500; }

/* Search / wishlist / cart. Store and Product pages only — the approved design
   puts these where someone is shopping and nowhere else. */
.bx-page .nav-tools {
  display: flex;
  align-items: center;
  gap: 10px;   /* + 6px hit-area padding either side = 22px between bounds */
  /* Full white, not the muted nav-link colour: at 66% these read as absent
     rather than as quiet. The design draws them at full contrast. */
  color: #fff;
}
/* Measured off the Store landing mockup at its 1521px width: search 18x18,
   heart 22x18 (WIDER than tall — the design heart is plump, not the narrow
   pointed one I had drawn), cart pill 30x20, and 22px between the icons'
   visual bounds. The 6px padding is hit area only; it is subtracted from the
   flex gap so the bounds still land 22px apart. Stroke measured at 1.5px;
   mine was 2 on a 24 viewBox drawn at 23px, noticeably heavier. */
.bx-page .nav-tool {
  display: grid;
  place-items: center;
  padding: 6px;
  opacity: 0.92;
  transition: opacity .2s var(--bx-expo);
}
.bx-page .nav-tool:hover { opacity: 1; }
.bx-page .nav-tool svg { height: 18px; width: auto; }
.bx-page .nav-cart__count {
  min-width: 30px;
  height: 20px;
  padding-inline: 7px;
  display: grid;
  place-items: center;
  border-radius: var(--bx-pill);
  background: #fff;
  /* Sampled #074A77 out of the mockup's pill — the count is blue, not the
     near-black this was using. */
  color: var(--bx-blue);
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1;
}

.bx-page .nav-account {
  flex: none;
  /* F1. Figma 217:29900 / 85:868 / 79:305 all give this 229x47 at radius 15,
     signed in or out — the box is specified regardless of whether the label
     reads "My Account" or "Login". It was drawing 98x42 as a pill.

     No x is set: the button's right edge already sits on the 1420 gutter, and
     the frame's 1192 + 229 = 1421, so correcting the width moves it into
     position on its own. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: 229px;
  height: 47px;
  padding: 0 30px;
  border-radius: var(--bx-radius-btn);
  background: rgba(11, 30, 43, 0.86);
  border: 1px solid rgba(255, 255, 255, 0.16);
  font-size: var(--bx-text-sm);
  font-weight: 500;
  color: #fff;
  transition: background .25s var(--bx-expo);
}
.bx-page .nav-account:hover { background: var(--bx-blue); color: #fff; }

/* Signed-out login control. Opens on hover AND on focus, so it is reachable
   from the keyboard — a menu that only exists under a pointer is not a menu.
   The padding-top on the panel keeps the pointer inside the hover area while
   travelling from the trigger down to the items. */
.bx-page .nav-login { position: relative; flex: none; }
.bx-page .nav-login__menu {
  position: absolute;
  top: 100%;
  right: 0;
  z-index: 60;
  min-width: 190px;
  margin-top: 8px;
  padding: 8px;
  border-radius: var(--bx-radius);
  background: var(--bx-blue-deep);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.45);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity .2s var(--bx-expo), transform .2s var(--bx-expo), visibility .2s;
}
.bx-page .nav-login:hover .nav-login__menu,
.bx-page .nav-login:focus-within .nav-login__menu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
/* Bridges the gap between trigger and panel so the menu does not close as the
   pointer crosses it. */
.bx-page .nav-login__menu::before {
  content: '';
  position: absolute;
  left: 0; right: 0; top: -10px;
  height: 10px;
}
.bx-page .nav-login__menu a {
  display: block;
  padding: 10px 14px;
  border-radius: var(--bx-radius);
  font-size: var(--bx-text-sm);
  color: rgba(255, 255, 255, 0.86);
}
.bx-page .nav-login__menu a:hover,
.bx-page .nav-login__menu a:focus-visible {
  background: var(--bx-blue);
  color: #fff;
}

.bx-page .nav-toggle {
  display: none;
  background: none; border: 0; padding: 6px;
  color: #fff; cursor: pointer;
}
.bx-page .nav-toggle svg { width: 24px; height: 24px; }
.bx-page .mobile-menu { display: none; }

/* ---------------------------------------------------------------- hero -- */
.bx-page .hero {
  position: relative;
  min-height: clamp(560px, 57.8vw, 878px);   /* supplied: 1519 x 878 */
  display: flex;
  align-items: center;
  overflow: hidden;
  background: var(--bx-dark);
}
.bx-page .hero .bg {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 60% center;
}
/* No scrim on desktop, because the approved design has none.
   Measured: the mockup's hero is pixel-identical to the raw banner across the
   full width (deltas of +0.1 to +0.5 luminance, i.e. encoding noise). The
   artwork is already dark enough — 6 to 16 luminance — for white type to sit
   on it directly. An earlier left-to-right gradient here put ~70% black over
   the brand chevron and effectively erased it.
   The mobile rule below still adds one, because the crop changes at that
   aspect and the type can land on the lit part of the photograph. */
.bx-page .hero::after { content: none; }
/* The copy width is capped on the CHILDREN, not on .hero-content itself.
   .hero-content is also the .wrap, which carries margin-inline:auto and 100px
   of padding — a max-width here would centre the block AND have the padding
   eaten out of it, leaving 500px of text width sitting at x=511 instead of a
   left-aligned column starting at x=100. */
.bx-page .hero-content {
  position: relative;
  z-index: 1;
  padding-block: var(--bx-space-8);
}
.bx-page .hero-content > * {
  /* Geist sets a little wider than the mockup's face, so line one needs ~700px
     to stay on one line at this size. Revisit once the Figma face is known. */
  max-width: 700px;
}
.bx-page .hero h1 {
  font-size: var(--bx-text-hero);
  font-weight: 300;
  margin-bottom: var(--bx-space-5);
}
.bx-page .hero .lede {
  color: var(--bx-on-dark-muted);
  max-width: 48ch;
  margin-bottom: var(--bx-space-7);
  font-size: var(--bx-text-sm);
}

/* A small "Overview" label between the h1 and the lede on the inner pages. */
.bx-page .hero-overline {
  font-size: var(--bx-text-sm);
  color: var(--bx-on-dark-muted);
  margin-bottom: var(--bx-space-3);
}

/* ------------------------------------------------- programmes carousel -- */
/* Full-bleed on purpose: the row runs off both edges so it reads as
   scrollable without needing arrows drawn on top of it. */
/* Two class names, not one: `.section-head { max-width: 62ch }` is declared
   further down this file, so at equal specificity it would win and cap the
   whole header at ~465px — which is what wrapped the heading and dragged the
   counter in beside the paragraph. */
.bx-page .section-head.programs-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--bx-space-6);
  max-width: none;
  /* Figma measures the heading block at ~186 against the 144 it renders at, and
     the section at 1117. Scoped here and on .programs-band below rather than on
     --bx-section-y, which every section on every page reads. */
  margin-bottom: 15px;
}
/* .section.programs-band, not .programs-band: `.section` sets padding-block
   from --bx-section-y and is declared further down, so at equal specificity
   it wins. Same trap as .section-head's max-width above. */
/* Supplied, band-relative: rail at 283, buttons at 969, band 1117 tall.
   124 + head + 15 = 283, rail 567 ends at 850, then 119 to the buttons. */
.bx-page .section.programs-band { padding-block: 124px 0; }
/* A px width, not ch. `ch` resolves against THIS element's font-size (0.95rem),
   so 62ch came out ~465px and wrapped the 41px heading onto two lines. */
.bx-page .section-head.programs-head > div:first-child { flex: 1 1 auto; max-width: 660px; }
.bx-page .programs-counter {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--bx-space-5);
  padding: 11px 18px;
  border-radius: var(--bx-pill);
  background: var(--bx-black);
  color: #fff;
  font-size: var(--bx-text-xs);
}
.bx-page .programs-counter b { font-weight: 500; color: var(--bx-on-dark-muted); }

.bx-page .programs-rail {
  display: flex;
  gap: 40px;   /* measured off the Figma frame between 368px tiles */
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-inline: var(--bx-gutter);
  scrollbar-width: none;

  /* The hover panel hangs below its tile and was being cut off mid-sentence.
     `overflow-x: auto` is the cause: CSS resolves `visible` on the other axis
     to `auto` whenever one axis scrolls, so declaring only overflow-x still
     made this a vertical scroller, and an absolutely positioned panel does not
     contribute to the height it would need.

     overflow-y: clip + overflow-clip-margin does not help — a scroll container
     ignores the clip margin, and the declaration computes to `hidden`
     (measured, not assumed).

     So the panel's overhang is reserved as real bottom padding, which puts it
     inside the scrollport, and then taken back with an equal negative margin so
     the page rhythm is unchanged. The reclaimed strip does not swallow clicks:
     a closed panel is `visibility: hidden` and untestable, and the following
     in-flow content hit-tests above the rail's padding. */
  /* 177 is the panel's actual overhang (183 tall, offset -6). 200 with 64px of
     section padding under it made the rail 646 against the supplied 567, and
     that surplus is the empty band that showed between the cards and the
     buttons. 8 + 373.7 + 8 + 177 = 567. */
  padding-block: var(--bx-space-2) calc(var(--bx-space-2) + var(--bx-rail-overhang));
  /* The reservation is NOT taken back with a negative margin. The Figma frame
     puts the section's buttons roughly 287px below the resting cards, i.e. the
     design reserves the expanded panel's space rather than overlaying it, and
     the section measures 1117 tall with that space present. The padding alone
     is what stops the clipping; the negative margin only hid it. */
}
.bx-page .programs-rail::-webkit-scrollbar { display: none; }

.bx-page .program-tile {
  position: relative;
  flex: 0 0 auto;
  width: 368px;          /* Figma: tile 368 wide */
  scroll-snap-align: start;
  color: var(--bx-on-light);
  /* A white card with the image inset, matching the design — not a bare
     photograph butted against its neighbours. */
  background: #fff;
  border-radius: var(--bx-radius);
  padding: var(--bx-space-3) var(--bx-space-3) var(--bx-space-4);
  transition: box-shadow .3s var(--bx-expo), transform .3s var(--bx-expo);
}
.bx-page .program-tile:hover,
.bx-page .program-tile:focus-visible {
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.13);
  transform: translateY(-2px);
}
.bx-page .program-tile__media {
  display: block;
  overflow: hidden;
  border-radius: 3px;
  background: #ddd;
}
.bx-page .program-tile__media img {
  width: 100%;
  /* height:auto is load-bearing. <img width="438" height="360"> maps to CSS
     presentational hints; this rule overrode `width` but not `height`, so
     height stayed 360px, which made the box non-auto and disabled
     aspect-ratio outright — the tiles rendered tall portrait instead of the
     near-square the design shows. */
  height: auto;
  /* 344x311 is the media box inside a 368px tile that lands the tile at the
     Figma height of 512 with its overview panel open. object-fit crops rather
     than distorting — the source is 260x213. */
  aspect-ratio: 344 / 311;
  object-fit: cover;
  /* Resting tiles sit back: desaturated and knocked back against the white
     card, the way the mockup shows them. The one being pointed at comes
     forward to full contrast. */
  filter: grayscale(1);
  opacity: 0.55;
  transition: filter .4s var(--bx-expo), opacity .4s var(--bx-expo), transform .5s var(--bx-expo);
}
.bx-page .program-tile:hover .program-tile__media img,
.bx-page .program-tile:focus-visible .program-tile__media img {
  filter: none;
  opacity: 1;
  transform: scale(1.03);
}
.bx-page .program-tile__name {
  display: block;
  margin-top: var(--bx-space-3);
  padding-inline: 2px;
  font-size: var(--bx-text-sm);
  color: var(--bx-on-light-muted);
  transition: color .25s var(--bx-expo);
}
.bx-page .program-tile:hover .program-tile__name,
.bx-page .program-tile:focus-visible .program-tile__name { color: var(--bx-on-light); font-weight: 500; }

/* The overview panel. In the mockup exactly one tile shows it, sitting over
   the tiles beside it — that tile is hovered, not specially authored. */
.bx-page .program-tile__panel {
  position: absolute;
  top: 100%;
  left: 0;
  width: 100%;
  z-index: 3;
  display: flex;
  flex-direction: column;
  gap: var(--bx-space-2);
  margin-top: -6px;
  padding: var(--bx-space-4);
  background: #fff;
  border-radius: var(--bx-radius);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.16);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity .25s var(--bx-expo), transform .25s var(--bx-expo), visibility .25s;
}
.bx-page .program-tile:hover .program-tile__panel,
.bx-page .program-tile:focus-visible .program-tile__panel {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.bx-page .program-tile__label {
  font-family: var(--bx-font-mono);
  font-size: var(--bx-text-eyebrow);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bx-on-light-muted);
}
.bx-page .program-tile__blurb { font-size: var(--bx-text-xs); line-height: 1.5; }
.bx-page .program-tile__more {
  font-size: var(--bx-text-xs);
  font-weight: 500;
  color: var(--bx-blue);
}

/* No hover pointer means the panel can never be opened, so show it inline. */
@media (hover: none) {
  /* The panel is in flow here, so it sizes the rail itself and the overhang
     reservation must be given back — otherwise the negative margin drags the
     next section up over the tiles. */
  .bx-page,
  .bx-page .programs-rail {
    --bx-rail-overhang: 0px;
  }
  .bx-page .program-tile__panel {
    position: static;
    opacity: 1;
    visibility: visible;
    transform: none;
    box-shadow: none;
    padding-inline: 0;
    background: transparent;
  }
}

/* ------------------------------------------------------------- pillars -- */
.bx-page .band-blue {
  background: var(--bx-blue);
  color: var(--bx-on-blue);
}
.bx-page .pillars {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}
.bx-page .pillar {
  padding: var(--bx-space-7) clamp(1.25rem, 3vw, 2.75rem);
  border-left: 1px solid var(--bx-line-blue);
}
.bx-page .pillar:first-child { border-left: 0; padding-left: 0; }
.bx-page .pillar h3 {
  font-size: 1.15rem;
  font-weight: 400;
  margin-bottom: var(--bx-space-3);
}
.bx-page .pillar p {
  font-size: var(--bx-text-xs);
  color: var(--bx-on-blue-muted);
  line-height: 1.55;
}

/* --------------------------------------------------------------- light -- */
.bx-page .band-light {
  background: var(--bx-light);
  color: var(--bx-on-light);
}
.bx-page .band-dark  { background: var(--bx-black); color: var(--bx-on-dark); }
.bx-page .section    { padding-block: var(--bx-section-y); }

.bx-page .section-head { max-width: 62ch; margin-bottom: var(--bx-space-7); }
.bx-page .section-head.center { margin-inline: auto; text-align: center; }
.bx-page .section-head h2 {
  font-size: var(--bx-text-h2);
  font-weight: 400;
  margin-bottom: var(--bx-space-4);
}
.bx-page .band-light .section-head p { color: var(--bx-on-light-muted); font-size: var(--bx-text-sm); }
.bx-page .band-dark  .section-head p { color: var(--bx-on-dark-faint); font-size: var(--bx-text-sm); }

/* ------------------------------------------------------------ programs -- */
/* Image tiles with the label and title laid over the photograph — there is no
   separate body panel under the image in this design. */
.bx-page .program-grid {
  display: grid;
  /* Figma 79:36/79:43/79:49 are 440, 440 and 439 wide in a 1320 wrap: three
     440s with no gutter at all. The 4px gap here made each card 437.33. The
     card art butts edge to edge in the frame, so the gap goes rather than the
     wrap widening. */
  grid-template-columns: repeat(3, 1fr);
  gap: 0;
}
.bx-page .program {
  position: relative;
  display: block;
  /* Figma 79:36 is 440x360, not 438. At 440 wide the old ratio drew 362. */
  aspect-ratio: 440 / 360;
  overflow: hidden;
  background: #111;
}
.bx-page .program img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform .6s var(--bx-expo);
}
.bx-page .program:hover img { transform: scale(1.04); }
.bx-page .program::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgba(0,0,0,0.42) 0%,
    rgba(0,0,0,0.10) 34%,
    rgba(0,0,0,0.72) 100%);
}
.bx-page .program-body {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: var(--bx-space-5);
  color: #fff;
}
.bx-page .program-label {
  font-family: var(--bx-font-mono);
  font-size: var(--bx-text-eyebrow);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--bx-accent);
}
.bx-page .program h3 { font-size: var(--bx-text-h3); font-weight: 500; }

/* The blurb is a hover reveal. In the mockup exactly one card shows its
   description and its title sits correspondingly higher — that card is hovered,
   not specially authored. Anything without a hover pointer gets it permanently,
   or the copy would be unreachable on a phone. */
.bx-page .program-text { display: block; }
.bx-page .program-text p {
  font-size: var(--bx-text-xs);
  color: rgba(255, 255, 255, 0.74);
  line-height: 1.5;
  max-width: 34ch;
  max-height: 0;
  margin-top: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-height .35s var(--bx-expo), opacity .25s var(--bx-expo), margin-top .35s var(--bx-expo);
}
.bx-page .program:hover .program-text p,
.bx-page .program:focus-visible .program-text p {
  max-height: 7em;
  margin-top: 8px;
  opacity: 1;
}
@media (hover: none) {
  .bx-page .program-text p { max-height: 7em; margin-top: 8px; opacity: 1; }
}

/* ------------------------------------------------------------- journey -- */
.bx-page .journey { border-top: 1px solid var(--bx-line-dark); }
.bx-page .step {
  display: grid;
  grid-template-columns: 90px 1fr;
  gap: var(--bx-space-4);
  padding-block: var(--bx-space-6);
  border-bottom: 1px solid var(--bx-line-dark);
}
.bx-page .step-num {
  font-family: var(--bx-font-mono);
  font-size: var(--bx-text-xs);
  color: var(--bx-accent);
  padding-top: 3px;
}
.bx-page .step h3 { font-size: var(--bx-text-h3); font-weight: 500; margin-bottom: var(--bx-space-3); }
.bx-page .step p  { font-size: var(--bx-text-xs); color: var(--bx-on-dark-faint); max-width: 76ch; }

/* ----------------------------------------------------------- standards -- */
/* Copy left on the light ground, photograph bleeding off the right edge. */
.bx-page .standards {
  display: grid;
  /* Figma: the photograph starts at X 753 and is 767 wide in a 1520 frame, so
     the split is not even — the image takes slightly more than half. */
  grid-template-columns: 753fr 767fr;
  align-items: stretch;
  background: var(--bx-light);
}
.bx-page .standards-copy {
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* The copy starts at x=100 in every frame that carries this section —
     217:36241/36242 and 150:133/134 on the programme pages, 79:115/116 on the
     homepage — which is also the gutter every other section on the page uses.
     The old symmetric clamp resolved to 68.4 at 1520 and put this band 32px
     left of everything above and below it. 6.25rem is 100px; 6.58vw lands on
     the same 100 at 1520 so it stays fluid below that. */
  padding-block: var(--bx-section-y);
  padding-inline: clamp(1.25rem, 6.58vw, 6.25rem) clamp(1.25rem, 4.5vw, 4.5rem);
  margin-left: auto;
  max-width: calc(var(--bx-max) / 2);
  width: 100%;
}
.bx-page .standards-copy h2 { font-size: var(--bx-text-h2); font-weight: 400; margin-bottom: var(--bx-space-4); }
/* 16/25.6 in the frames, not the 14/22.68 body default; the measure runs to
   594 (programme) / 585 (homepage) rather than the 46ch that clipped it to
   427. */
.bx-page .standards-copy p  {
  color: var(--bx-on-light-muted);
  font-size: 16px;
  line-height: 25.6px;
  margin-bottom: var(--bx-space-7);
  max-width: 594px;
}
.bx-page .standards-copy .bx-btn { align-self: flex-start; }

/* Programme pages pair the blue primary with a DARK-FILLED secondary
   (217:36256 / 150:138: #051824 ground, white label, translucent white
   hairline) — not the light-ground outline button this shares elsewhere. The
   homepage's version of this section carries a single primary, so it is left
   out of the selector rather than overridden back. */
.bx-page--program .standards .bx-btn-outline-dark {
  background: #051824;
  border-color: rgba(255, 255, 255, 0.35);
  color: #fff;
}
.bx-page--program .standards .bx-btn-outline-dark:hover {
  background: #0a2a3d;
  border-color: rgba(255, 255, 255, 0.55);
}
/* 796px is the section height in the design, and it is also the natural height
   of outcomes-767.webp (767x796) — the design column is half of a 1534px
   frame, so the photograph sits at 1:1 there. The visual drives the row and
   .standards-copy centres itself in it. 460px was my own placeholder and
   made the band 336px short. */
.bx-page .standards-visual { position: relative; min-height: 796px; }
.bx-page .standards-visual img {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}

/* ------------------------------------------------------------- metrics -- */
.bx-page .metrics {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}
/* The two bands that use this component are DIFFERENT designs, and #112
   flattened both into the homepage's. Restored here.

   Programme pages (150:57, 217:36196) are a stat block: the figure at 40px on
   its own line, the caption at ~13px underneath, both centred. That is the
   default below.

   The homepage (79:117) is not that. 79:120 is a SINGLE text node reading
   "98% Purity" at 21px, sitting on one line beside two 13.5px claims with no
   figure at all — so it is scoped to .bx-page--home rather than applied to
   everything.

   Applying the homepage treatment everywhere pushed every programme caption to
   21px, which is what made "Average Body Weight Reduction" wrap: it needed 388
   of a 352 content box. At 13.1px it needs 224. */
.bx-page .metric {
  padding: var(--bx-space-7) clamp(1.25rem, 3vw, 2.75rem);
  border-left: 1px solid var(--bx-line-blue);
  text-align: center;
}
.bx-page .metric:first-child { border-left: 0; }
.bx-page .metric .num {
  display: block;
  font-size: 40px;
  font-weight: 300;
  line-height: 1.1;
  color: #fff;
  /* A figure is one token: "12-15%" and the en-dash ranges on five other
     programmes must never break at their hyphen. */
  white-space: nowrap;
}
.bx-page .metric .lbl {
  display: block;
  font-size: 13.1px;
  line-height: 18.37px;
  color: var(--bx-on-blue-muted);
  margin-top: var(--bx-space-3);
}

/* Homepage only — one centred phrase per cell, no stacked figure. */
.bx-page--home .metric {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.32em;
}
.bx-page--home .metric .num {
  display: inline;
  font-size: 21px;
  font-weight: 500;
  line-height: 20.25px;
  flex: 0 0 auto;
}
/* All three cells share one treatment by request. The frame sets 79:120 at
   21px and 79:122 / 79:125 at 13.5px, so this is a deliberate deviation: the
   band reads as one row rather than a figure with two footnotes beside it.
   Colour was already white on all three in the frame. */
.bx-page--home .metric .lbl {
  display: inline;
  font-size: 21px;
  font-weight: 500;
  line-height: 20.25px;
  margin-top: 0;
  color: #fff;
}

/* ----------------------------------------------------------------- faq -- */
.bx-page .faq-list { border-top: 1px solid var(--bx-line-light); }
.bx-page .faq-item { border-bottom: 1px solid var(--bx-line-light); }
.bx-page .faq-q {
  width: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--bx-space-4);
  background: none; border: 0;
  color: var(--bx-on-light);
  font-family: inherit;
  font-size: var(--bx-text-sm);
  font-weight: 500;
  text-align: left;
  padding: var(--bx-space-5) 0;
  cursor: pointer;
}
.bx-page .faq-q .icon {
  flex: none;
  font-size: 1.2rem;
  line-height: 1;
  color: var(--bx-on-light-muted);
  transition: transform .25s var(--bx-expo);
}
.bx-page .faq-item.open .faq-q .icon { transform: rotate(45deg); }
.bx-page .faq-a { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .3s var(--bx-expo); }
.bx-page .faq-item.open .faq-a { grid-template-rows: 1fr; }
.bx-page .faq-a > div { overflow: hidden; }
.bx-page .faq-a p {
  font-size: var(--bx-text-xs);
  color: var(--bx-on-light-muted);
  line-height: 1.7;
  padding-bottom: var(--bx-space-5);
  max-width: 82ch;
}

/* ------------------------------------------------------------ cta band -- */
.bx-page .cta-band {
  position: relative;
  overflow: hidden;
  text-align: center;
  padding-block: clamp(3rem, 6vw, 4.5rem);
  background: var(--bx-cta);
}
.bx-page .cta-band .bg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0.7;
}
.bx-page .cta-band::after { content: ''; position: absolute; inset: 0; background: rgba(1,1,1,0.5); }
.bx-page .cta-band .wrap { position: relative; z-index: 1; }
.bx-page .cta-band h2 {
  font-size: var(--bx-text-h2);
  font-weight: 300;
  margin-bottom: var(--bx-space-6);
}

/* -------------------------------------------------------------- footer -- */
.bx-page .site-footer {
  margin-top: 0;            /* biorax.css puts 80px on every <footer> */
  /* biorax.css also puts 64px/40px on every <footer>, which stacked on top of
     the .wrap inset below and made the band 627 instead of 500. */
  padding: 0;
  position: relative;
  overflow: hidden;
  background: var(--bx-blue-deep);
  color: #fff;
}
.bx-page .site-footer .bg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  opacity: 0.5;
}
/* Figma 150:393 is 1520x500 on every frame, with its content block (150:396)
   inset 99 from the top and 73 from the bottom, making 328 of content. */
.bx-page .site-footer .wrap { position: relative; z-index: 1; padding-block: 99px 73px; }

.bx-page .footer-grid {
  display: grid;
  /* Figma 150:396 is 1320 wide with the three link columns at 394.55, 656.55
     and 918.56 — a 262 pitch after a 394.55 brand column. Fractional units put
     them on a 310 pitch, which walked the Contact column off its position. */
  grid-template-columns: 394.55px 262px 262px 1fr;
  gap: 0;
}
/* Figma 150:413 is 148 wide. */
.bx-page .footer-mark img { width: 148px; height: auto; margin-bottom: var(--bx-space-5); }
.bx-page .footer-tagline { font-size: var(--bx-text-xs); color: rgba(255,255,255,0.78); }
.bx-page .footer-col h4 {
  font-family: var(--bx-font-mono);
  font-size: var(--bx-text-eyebrow);
  font-weight: 500;
  letter-spacing: var(--bx-tracking-eyebrow);
  text-transform: uppercase;
  color: rgba(255,255,255,0.55);
  margin-bottom: var(--bx-space-5);
}
.bx-page .footer-col a,
.bx-page .footer-col p {
  display: block;
  font-size: var(--bx-text-xs);
  color: rgba(255,255,255,0.86);
  margin-bottom: var(--bx-space-3);
}
.bx-page .footer-col a:hover { color: #fff; }

.bx-page .footer-bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--bx-space-5);
  /* Sized so the footer's content block totals Figma's 328, which with the
     99/73 inset makes the band exactly 500. The link columns here run shorter
     than the file's 246 top block, so the space goes into this gap rather than
     being padded onto a column that has nothing to fill it with. */
  margin-top: 77.91px;
  padding-top: var(--bx-space-5);
  border-top: 1px solid rgba(255,255,255,0.16);
  font-size: 0.72rem;
  color: rgba(255,255,255,0.55);
  line-height: 1.65;
}
/* Supplied Figma text style for the footer disclaimer: Helvetica Neue 400,
   11.5px / 18.4px, letter-spacing 0. It inherited 0.72rem (11.52px) at
   line-height 1.65 (19.008px) in Geist from .footer-bottom above, so all three
   were slightly off. Stated in px, not rem, because the spec is in px and a
   root-size change must not drift it.

   The spec's `leading-trim: none` and `vertical-align: middle` are Figma text
   properties with no CSS effect on a block paragraph, so they are not emitted
   rather than shipped as declarations that do nothing.

   Helvetica Neue is not bundled — the stack falls back to Helvetica then Arial,
   which is what non-Apple platforms will actually render. */
/* Both paragraphs in the footer bottom — the disclaimer and the copyright —
   were rendering #4D5552 on the #032338 footer: a contrast ratio of 2.10:1,
   which fails WCAG AA (4.5:1) and is close to unreadable.

   The cause is `p { color: var(--ink-muted) }` in biorax.css:153. .footer-bottom
   sets rgba(255,255,255,0.55), but that only INHERITS, and a rule matching the
   element directly beats an inherited value no matter how specific the
   ancestor's rule is — so a bare `p` selector wins over `.bx-page .footer-bottom`.
   Every other item down there is an <a>, <h4> or <span>, which is why only these
   two were affected and the fault was easy to miss.

   #F1F1F1 as supplied: 14.29:1. */
.bx-page .footer-bottom p { color: #F1F1F1; }

.bx-page .footer-legal {
  /* Figma 150:421 is 611 wide; 62ch resolved to 396 here, which ran the same
     sentence to five lines and took the legal block from 50 tall to 92. */
  max-width: 611px;
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-weight: 400;
  font-style: normal;
  font-size: 11.5px;
  line-height: 18.4px;
  letter-spacing: 0;
}

/* ========================================================= store ======== */
/* .hero is display:flex, so a second child would sit BESIDE the copy — which
   put the filter pills up in the nav row. The store hero stacks instead and
   pins its filters to the bottom. */
.bx-page .hero--store {
  /* 741px, measured off the Store mockup: the blue sort bar starts at y=742,
     so the hero band is 0..741. This was capped at 620 and cropped 121px off
     the banner. 48.78vw is 741/1519, so it holds the ratio below 1519. */
  /* 741px, measured off the Store mockup: the blue sort bar starts at y=742, so
     the hero band is 0..741. The Store LISTING overrides this below; the product
     page, which shares this class, keeps it. */
  min-height: clamp(440px, 48.78vw, 741px);
  flex-direction: column;
  justify-content: center;
  align-items: stretch;
}
/* Only the product page carries the filter row, and there the copy sits above
   it rather than centred in the frame. */
.bx-page .hero--filtered { justify-content: flex-end; }
.bx-page .hero--store .hero-content { padding-top: 132px; padding-bottom: var(--bx-space-6); }

/* Store listing: a shorter hero than the frame's 741. Reduced 30% from the
   previous 589 to 412.

   589 was set when the hero still carried an "Overview" label above the
   description; that label has since gone, and measurement showed the block —
   heading, description and filter row — occupying 350px inside a 589px hero,
   leaving 239px of dead space. 412 keeps 62px of slack over that 350, so the
   pills stay inside the hero and the heading still clears the fixed 77px nav.

   min-height alone could not deliver the full 30%: the hero's own content
   measured 446px, so anything below that simply stopped binding. The missing
   34px comes off .hero-content's top padding, which exists only to clear the
   fixed 77px nav and was carrying 132px — the heading started 152px down the
   hero, 75px more clearance than it needed. At 98px it starts at 118px, still
   41px clear of the nav, and the natural height now equals the 412 target
   rather than overriding it.

   Both rules are scoped to .bx-page--store, the listing. The product page
   shares .hero--store and is NOT changed here; it keeps its 741 and its
   original 132px padding. */
.bx-page--store .hero--store { min-height: 412px; }
/* Must stay after the .bx-page .hero--store .hero-content rule above: same
   specificity (0,3,0), so source order is what decides. */
.bx-page--store .hero--store .hero-content { padding-top: 98px; }

/* Programme filter pills across the foot of the store hero. */
.bx-page .store-filters {
  position: relative;
  z-index: 1;
  display: flex;
  /* One line, as specified (1322x36). The ten programmes in the design need
     1184px and fit; the catalogue currently carries an eleventh, GLP-1 Weight
     Loss, which takes the run to 1334 and wrapped it onto a second row at
     113px tall. Scrolling rather than wrapping keeps every programme reachable
     and holds the height — and it still holds when another is added, which
     dropping one to make the numbers work would not. */
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  /* Figma: items at x 0/60/190/380/506... — a uniform 10px gap, not 8. */
  gap: 10px;
  /* Pinned to the foot of the hero, not centred with the copy. The supplied
     position is top 666 in a 741 hero, so the row's 36px sits 39px clear of the
     bottom. .hero--store is a flex column with justify-content:center, so the
     auto top margin takes the free space and drops this to the foot while the
     copy stays above it. */
  margin-top: auto;
  /* 19, not 39. The supplied position leaves 39px between the pills and the
     hero's outer bottom edge, but .hero already carries 20px of its own
     padding, so the row only has to add the remaining 19. */
  padding-bottom: 19px;
}
.bx-page .store-filters::-webkit-scrollbar { display: none; }
.bx-page .store-filter {
  display: inline-flex;
  align-items: center;
  height: 36px;          /* the supplied height, rather than 37 from padding */
  flex: none;            /* nowrap must not squeeze the labels */
  /* Figma 85:842-861: 19px text inset, 15px radius (not a full pill),
     Geist Regular 14/18.2, full-white label on a 12% border. */
  padding: 0 19px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: var(--bx-radius-btn);
  font-size: 14px;
  line-height: 18.2px;
  color: #ffffff;
  white-space: nowrap;
  transition: border-color .2s var(--bx-expo), color .2s var(--bx-expo), background .2s var(--bx-expo);
}
.bx-page .store-filter:hover { border-color: #fff; color: #fff; }
/* The selected pill is inverted against the rest: a solid fill with a matching
   border and a white label, not the white chip this used to draw. The fill is
   --bx-blue (#074a77), the one brand blue, rather than the black it carried —
   a literal hex here would be a second source for a colour the token already
   owns. */
.bx-page .store-filter.is-active {
  background: var(--bx-blue);
  border-color: var(--bx-blue);
  color: #fff;
}

.bx-page .store-bar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bx-space-5);
  min-height: 76px;
}
.bx-page .store-sort select {
  appearance: none;
  padding: 10px 40px 10px 18px;
  border-radius: var(--bx-radius-btn);
  border: 1px solid rgba(255, 255, 255, 0.24);
  background: var(--bx-black) url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") no-repeat right 14px center / 14px;
  color: #fff;
  font-family: inherit;
  font-size: var(--bx-text-xs);
  cursor: pointer;
}
.bx-page .store-sort__label { font-size: var(--bx-text-xs); color: var(--bx-on-blue-muted); margin-right: var(--bx-space-2); }
.bx-page .store-sort { display: inline-flex; align-items: center; }

/* "Showing" sits above the figure, with a hairline to its right — the design
   treats it as a caption, not a sentence. */
.bx-page .store-count {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  padding-right: var(--bx-space-5);
  border-right: 1px solid rgba(255, 255, 255, 0.3);
  font-size: var(--bx-text-xs);
  color: #fff;
  text-align: right;
}
.bx-page .store-count span { font-size: 0.68rem; color: var(--bx-on-blue-muted); }
.bx-page .store-bar__inner--right { justify-content: flex-end; }

/* Selected by #product-list, NOT by .store-grid, and this is not a preference.
   catalog/view/javascript/common.js runs, on EVERY page load:

       if (localStorage.getItem('display') == 'list') { ... }
       else { $('#product-list').attr('class', 'row row-cols-1 row-cols-sm-2 ...') }

   attr('class', ...) REPLACES the attribute, so `store-grid` is deleted from
   the element a moment after render — for first-time visitors too, since the
   else branch is the default. The class in the markup is therefore decorative;
   the id is the only stable hook. That is why the cards were touching: the
   grid below never applied, and the page fell back to Bootstrap's .row, whose
   gutter is padding on the children — padding .bx-prod resets to 0.

   Specificity: `.bx-page #product-list` (id+class) beats `.row` and
   `.row-cols-lg-3 > *` (single class), so Bootstrap is overridden without
   !important and without editing core. */
.bx-page .store-grid,
.bx-page #product-list {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  /* Figma 85:950: columns at x 0/448/895 -> 24 across; rows at y 0/624 with a
     586 card -> 38 down. The two axes are not the same. */
  column-gap: 24px;
  row-gap: 38px;
  margin: 0;          /* .row applies negative inline margins */
  --bs-gutter-x: 0;
}
/* Undo .row > * and .row-cols-* > * so the grid, not flex, does the layout. */
.bx-page #product-list > * {
  flex: none;
  width: auto;
  max-width: none;
  padding: 0;
  margin: 0;
}

/* ---------------------------------------------------------- product card -- */
/* Named bx-prod, NOT bx-card: biorax.css already owns .bx-card, .bx-card__badge,
   .bx-card__body, .bx-card__icon and .bx-card__title for the old condition
   cards. Reusing those names leaked a background, a 1px border, 20px of padding
   and display:flex into every product card — properties this file did not
   declare, so there was nothing here to win against them.
   Everything the old rules set is now declared explicitly below, so a future
   collision shows up as a conflict rather than as a silent inheritance. */
.bx-page .bx-prod {
  position: relative;
  display: block;
  background: transparent;
  border: 0;
  padding: 0;
}
.bx-page .bx-prod form { margin: 0; }
.bx-page .bx-prod__media {
  position: relative;
  overflow: hidden;
  /* Figma 85:952: 15px radius on a 5% black ground. */
  border-radius: var(--bx-radius-btn);
  background: rgba(0, 0, 0, 0.05);
}
.bx-page .bx-prod__link { display: block; }
/* <picture> is inline by default, so the img inside it would size against the
   inline box rather than the card. Block, and the img's width:100% resolves
   against the media panel exactly as it did before the element existed. */
.bx-page .bx-prod__pic { display: block; }
.bx-page .bx-prod__img {
  width: 100%;
  /* Figma 85:952 is 424x461, not square. */
  aspect-ratio: 424 / 461;
  /* cover, as the design bleeds the photograph to the card edge. The seeded
     placeholder is a white-background PNG so this currently reads as a pale
     card; that is the asset, not the rule. Do not switch to contain to flatter
     the placeholder — real photography would then letterbox. */
  object-fit: cover;
  transition: transform .5s var(--bx-expo);
}
.bx-page .bx-prod:hover .bx-prod__img { transform: scale(1.03); }

.bx-page .bx-prod__badge {
  position: absolute;
  /* Figma 85:1375: 170x40 at 10,10 — 15px radius, 18px label, capitalised.
     min-width rather than width: the design's sample label is "Weight Loss",
     but "Hormone Optimization" at 18px needs more than 170 and a fixed width
     would clip it. */
  top: 10px; left: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  min-width: 170px;
  height: 40px;
  padding: 0 16px;
  border-radius: var(--bx-radius-btn);
  background: var(--bx-blue);
  color: #fff;
  font-size: 18px;
  line-height: 16.8px;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: capitalize;
}
.bx-page .bx-prod__wish {
  position: absolute;
  top: 10px; right: 10px;
  width: 30px; height: 30px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.9);
  border: 1px solid rgba(11, 11, 11, 0.12);
  color: var(--bx-on-light);
  cursor: pointer;
  transition: background .2s var(--bx-expo), color .2s var(--bx-expo);
}
.bx-page .bx-prod__wish:hover { background: #fff; color: var(--bx-blue); }
.bx-page .bx-prod__wish svg { width: 16px; height: 16px; }

/* Slides up on hover. Kept in the layout and reachable by keyboard, because a
   control that exists only under a mouse pointer is not a control. */
/* Always visible. It was a hover reveal, which meant the primary action on a
   product card did not exist until you pointed at it — and on touch, where
   there is no hover, it only appeared via a media-query fallback. Hover now
   changes its colour rather than its existence. */
.bx-page .bx-prod__add {
  position: absolute;
  /* Figma 85:1369 sits inside two nested import offsets (85:953 at -33,-35 and
     85:954 at 0,-15), which resolve in card space to left 26, right 31, bottom
     19 — a 367-wide button. The 26/31 split is import noise, not a design
     decision, so it is centred at 28 rather than shipped 2.5px off-axis. */
  left: 28px; right: 28px; bottom: 19px;
  /* Figma 85:1369/85:1370: 47px tall, 15px radius, blue label on white. */
  display: flex;
  align-items: center;
  justify-content: center;
  height: 47px;
  padding: 0 14px;
  border: 0;
  border-radius: var(--bx-radius-btn);
  background: #fff;
  color: var(--bx-blue);
  font-family: inherit;
  font-size: 14.5px;
  line-height: 21.75px;
  font-weight: 400;
  cursor: pointer;
  /* Hidden until the card is hovered. opacity rather than display/visibility so
     the button stays in the tab order: :focus-within then reveals it for
     keyboard users, who otherwise would focus an invisible control. */
  opacity: 0;
  transform: translateY(6px);
  pointer-events: none;
  transition: background .2s var(--bx-expo), color .2s var(--bx-expo),
              opacity .2s var(--bx-expo), transform .2s var(--bx-expo);
}
.bx-page .bx-prod:hover .bx-prod__add,
.bx-page .bx-prod:focus-within .bx-prod__add {
  opacity: 1;
  transform: none;
  pointer-events: auto;
  background: var(--bx-blue);
  color: #fff;
}
.bx-page .bx-prod__add:hover,
.bx-page .bx-prod__add:focus-visible { background: var(--bx-blue); color: #fff; }

/* Touch has no hover state, so there would be no way to reach the button at
   all. Keep it permanently visible there, in the resting white treatment. */
@media (hover: none) {
  .bx-page .bx-prod__add { opacity: 1; transform: none; pointer-events: auto; }
}

/* Figma 85:951 stacks image 0-461, title top 481, description 510, price 563
   in a 586 card — so 20 under the image, 8 under the title, 20 under the copy. */
.bx-page .bx-prod__body { padding-top: 20px; }
.bx-page .bx-prod__name { font-size: 18px; line-height: 21.6px; font-weight: 700; margin-bottom: 8px; }
.bx-page .bx-prod__desc {
  font-size: 14px;
  line-height: 19.6px;
  color: #777770;
  margin-bottom: 20px;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.bx-page .bx-prod__price { font-size: 16px; line-height: 22.4px; color: rgba(0, 0, 0, 0.6); }
.bx-page .bx-prod__cur { color: var(--bx-on-light-muted); }
.bx-page .bx-prod__price b { font-weight: 600; }
.bx-page .bx-prod__price s { color: var(--bx-on-light-muted); margin-left: 6px; }

/* Pagination — OpenCart emits its own markup, so this restyles what it gives. */
.bx-page .store-pagination { display: flex; justify-content: center; margin-top: var(--bx-space-8); }
.bx-page .store-pagination ul { display: flex; gap: var(--bx-space-2); list-style: none; margin: 0; padding: 0; }
.bx-page .store-pagination li a,
.bx-page .store-pagination li span {
  display: grid;
  place-items: center;
  min-width: 34px;
  height: 34px;
  padding-inline: 10px;
  border-radius: var(--bx-pill);
  font-size: var(--bx-text-xs);
  color: var(--bx-on-light);
}
.bx-page .store-pagination li.active span,
.bx-page .store-pagination li a:hover { background: var(--bx-black); color: #fff; }

.bx-page .store-empty { text-align: center; padding-block: var(--bx-space-8); }
.bx-page .store-empty p { color: var(--bx-on-light-muted); margin-bottom: var(--bx-space-5); }

.bx-page .visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ======================================================= product ======== */
.bx-page .hero-title--store { font-size: var(--bx-text-hero); font-weight: 300; }

.bx-page .pdp-crumbs {
  display: flex;
  margin-bottom: var(--bx-space-6);
  color: var(--bx-on-light-muted);
  flex-wrap: wrap;
  gap: var(--bx-space-2);
  font-family: var(--bx-font-mono);
  font-size: var(--bx-text-eyebrow);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bx-on-blue-muted);
}
.bx-page .pdp-crumbs a { display: inline-flex; align-items: center; }
.bx-page .pdp-crumbs a:hover { color: var(--bx-on-light); }
.bx-page .pdp-crumbs svg { width: 15px; height: 15px; }
.bx-page .pdp-crumbs span { opacity: 0.5; }

.bx-page .pdp {
  display: grid;
  /* Figma 85:1246: gallery 576 wide, the copy column starting at x=794 in a
     wrap that begins at 100 — so 576 plus a 118 gutter. Fractions gave 567/681
     and started the copy at 739. */
  grid-template-columns: minmax(0, 576px) minmax(0, 1fr);
  gap: 118px;
  align-items: start;
}
.bx-page .pdp-gallery__main {
  display: block;
  /* 15px on a 5% ground, matching the store card. The white ground plus the
     32px inset below drew a wide white border round the photograph. */
  border-radius: var(--bx-radius-btn);
  overflow: hidden;
  background: rgba(0, 0, 0, 0.05);
}
/* Figma 85:1246: the gallery is 576 x 742 and the photograph fills it. It was
   square with 32px of padding — that padding was the white border. */
.bx-page .pdp-gallery__main img { width: 100%; aspect-ratio: 576 / 742; object-fit: cover; padding: 0; }
.bx-page .pdp-gallery__thumbs { display: flex; gap: var(--bx-space-3); margin-top: var(--bx-space-3); flex-wrap: wrap; }
.bx-page .pdp-gallery__thumb {
  width: 84px;
  border-radius: 4px;
  overflow: hidden;
  background: #fff;
  border: 1px solid var(--bx-line-light);
}
.bx-page .pdp-gallery__thumb img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }

.bx-page .pdp-gallery__frame { position: relative; }
.bx-page .pdp-wish {
  position: absolute;
  top: 14px; right: 14px;
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border: 0; border-radius: 50%;
  background: rgba(255,255,255,0.9);
  color: var(--bx-on-light);
  cursor: pointer;
}
.bx-page .pdp-wish:hover { color: var(--bx-blue); }
.bx-page .pdp-wish svg { width: 17px; height: 17px; }

.bx-page .pdp-badge {
  position: absolute;
  top: 14px; left: 14px;
  padding: 6px 14px;
  border-radius: var(--bx-pill);
  background: var(--bx-blue);
  color: #fff;
  font-size: var(--bx-text-eyebrow);
  font-weight: 500;
  margin-bottom: var(--bx-space-4);
}
.bx-page .pdp-title { font-size: clamp(1.7rem, 3vw, 2.4rem); font-weight: 400; margin-bottom: var(--bx-space-3); }
.bx-page .pdp-subtitle { font-size: var(--bx-text-sm); font-weight: 600; color: var(--bx-on-light); margin-bottom: var(--bx-space-4); }
.bx-page .pdp-intro { font-size: var(--bx-text-sm); color: var(--bx-on-light-muted); margin-bottom: var(--bx-space-6); max-width: 56ch; }
.bx-page .pdp-price { font-size: 1.6rem; margin-bottom: var(--bx-space-5); }
.bx-page .pdp-price__cur { color: var(--bx-blue); font-size: var(--bx-text-sm); }
.bx-page .pdp-price b { font-weight: 600; }
.bx-page .pdp-price s { color: var(--bx-on-light-muted); font-size: var(--bx-text-sm); margin-left: 8px; }

/* The core cart form, restyled in place. Selectors target the markup OpenCart
   emits — its ids and names are untouched. */
.bx-page #product .input-group { display: flex; gap: var(--bx-space-3); align-items: stretch; margin-bottom: var(--bx-space-4); }
.bx-page #product .input-group-text {
  display: grid;
  place-items: center;
  padding-inline: 14px;
  /* Bootstrap gives this a grey fill and biorax.css darkens it in dark mode,
     which rendered the quantity label as a black square on the light band. */
  background: #fff;
  border: 1px solid var(--bx-line-light);
  border-radius: var(--bx-radius);
  font-size: var(--bx-text-xs);
  color: var(--bx-on-light-muted);
}
.bx-page #product #input-quantity {
  width: 72px;
  padding: 12px;
  text-align: center;
  border: 1px solid var(--bx-line-light);
  border-radius: var(--bx-radius);
  font-family: inherit;
  background: #fff;
  color: var(--bx-on-light);
}
/* The core cart form and the Checkout link share one row. The form is not
   restructured to achieve it — it is simply the first flex child. */
.bx-page .pdp-buy { display: flex; gap: var(--bx-space-3); align-items: flex-start; flex-wrap: wrap; }
.bx-page .pdp-buy #product { flex: 1 1 260px; }
.bx-page .pdp-buy #product .input-group { margin-bottom: 0; }
.bx-page .bx-btn-checkout {
  flex: 0 1 190px;
  padding: 13px 30px;
  background: var(--bx-blue-deep);
  color: #fff;
  border-radius: var(--bx-radius-btn);
  font-weight: 600;
}
.bx-page .bx-btn-checkout:hover { background: var(--bx-blue); color: #fff; }
.bx-page #product #button-cart {
  flex: 1;
  padding: 13px 30px;
  border: 0;
  border-radius: var(--bx-radius-btn);
  background: var(--bx-blue);
  color: #fff;
  font-family: inherit;
  font-size: var(--bx-text-sm);
  font-weight: 600;
  cursor: pointer;
  transition: background .25s var(--bx-expo);
}
.bx-page #product #button-cart:hover { background: var(--bx-blue-hover); }
.bx-page #product label { display: block; font-size: var(--bx-text-xs); margin-bottom: 6px; color: var(--bx-on-light-muted); }
.bx-page #product select,
.bx-page #product input[type="text"],
.bx-page #product textarea {
  width: 100%;
  padding: 11px 14px;
  border: 1px solid var(--bx-line-light);
  border-radius: var(--bx-radius);
  font-family: inherit;
  background: #fff;
  color: var(--bx-on-light);
}
.bx-page #product .invalid-feedback { display: none; color: #b3261e; font-size: var(--bx-text-xs); margin-top: 6px; }
.bx-page #product .invalid-feedback.d-block { display: block; }
.bx-page #product .is-invalid { border-color: #b3261e; }
.bx-page #product h3 { font-size: var(--bx-text-h4); margin-block: var(--bx-space-5) var(--bx-space-3); }
.bx-page #product hr { border: 0; border-top: 1px solid var(--bx-line-light); margin-block: var(--bx-space-5); }

.bx-page .pdp-meta { list-style: none; margin: var(--bx-space-5) 0 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.bx-page .pdp-meta li { font-size: var(--bx-text-xs); color: var(--bx-on-light-muted); }
.bx-page .pdp-meta span { color: var(--bx-on-light); font-weight: 500; margin-right: 6px; }

.bx-page .pdp-tabs { margin-top: var(--bx-space-8); }
.bx-page .pdp-tablist { display: flex; gap: var(--bx-space-6); border-bottom: 1px solid var(--bx-line-light); }
.bx-page .pdp-tab {
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  padding: 0 0 var(--bx-space-3);
  margin-bottom: -1px;
  font-family: var(--bx-font-mono);
  font-size: var(--bx-text-eyebrow);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bx-on-light-muted);
  cursor: pointer;
}
.bx-page .pdp-tab.is-active { color: var(--bx-blue); border-bottom-color: var(--bx-blue); }

.bx-page .pdp-panel { display: none; padding-top: var(--bx-space-6); }
.bx-page .pdp-panel.is-active { display: block; }
.bx-page .pdp-prose { max-width: 80ch; font-size: var(--bx-text-sm); color: var(--bx-on-light-muted); }
.bx-page .pdp-prose h4 { font-size: var(--bx-text-h4); color: var(--bx-on-light); margin-block: var(--bx-space-5) var(--bx-space-2); }
.bx-page .pdp-prose p { margin-bottom: var(--bx-space-3); }
.bx-page .pdp-prose ul { margin: 0 0 var(--bx-space-4); padding-left: 1.15rem; }
.bx-page .pdp-prose li { margin-bottom: 4px; }
.bx-page .pdp-prose small { font-size: var(--bx-text-xs); color: var(--bx-on-light-muted); }
.bx-page .pdp-tags { margin-top: var(--bx-space-5); font-size: var(--bx-text-xs); color: var(--bx-on-light-muted); }
.bx-page .pdp-tags a { color: var(--bx-blue); }

.bx-page .pdp-spec-group { font-size: var(--bx-text-h4); margin-bottom: var(--bx-space-3); }
.bx-page .pdp-spec { display: grid; grid-template-columns: minmax(160px, 240px) 1fr; gap: var(--bx-space-3) var(--bx-space-5); margin: 0 0 var(--bx-space-6); }
.bx-page .pdp-spec dt { font-size: var(--bx-text-xs); color: var(--bx-on-light-muted); }
.bx-page .pdp-spec dd { margin: 0; font-size: var(--bx-text-sm); }

/* OpenCart's cart.add writes its success and error alerts in here. */
.bx-page .toast-container:empty { display: none; }
.bx-page .toast-container .alert {
  padding: 12px 16px;
  border-radius: var(--bx-radius);
  background: #e6f4ea;
  color: #10361d;
  font-size: var(--bx-text-sm);
  margin-bottom: var(--bx-space-5);
}
.bx-page .toast-container .alert a { color: var(--bx-blue); text-decoration: underline; }

/* ============================================ utility pages ============= */
/* Login, register, account, cart and search. A shorter hero than the marketing
   pages — these are places to do something, not to be sold to. */
.bx-page .hero--compact {
  min-height: clamp(280px, 26vw, 380px);
  flex-direction: column;
  justify-content: center;
  align-items: stretch;
}
.bx-page .hero--compact .hero-content { padding-top: 88px; padding-bottom: var(--bx-space-6); }
/* The supplied account banner is 1520x589 and the design's Sign In / My Account
   heroes measure the same. .hero--compact alone clamps to 380px, which crops it.
   Scoped to these two pages rather than raising .hero--compact, because cart,
   search, wishlist and checkout share that class and I have no design for their
   hero height. */
.bx-page .hero--account { min-height: clamp(420px, 38.75vw, 589px); }
.bx-page .hero--compact h1 { font-size: clamp(1.8rem, 3.4vw, 2.6rem); font-weight: 300; }
.bx-page .hero--compact .lede { margin-bottom: 0; margin-top: var(--bx-space-3); }

.bx-page .bx-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--bx-space-5);
  align-items: start;
}
.bx-page .bx-links { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.bx-page .bx-links a {
  display: block;
  padding: 9px 0;
  font-size: var(--bx-text-sm);
  color: var(--bx-on-light-muted);
  border-bottom: 1px solid var(--bx-line-light);
}
.bx-page .bx-links li:last-child a { border-bottom: 0; }
.bx-page .bx-links a:hover { color: var(--bx-blue); }

.bx-page .bx-narrow { max-width: 760px; }

/* Search bar, sitting in the blue band like the store's sort row. */
.bx-page .bx-search { display: flex; gap: var(--bx-space-3); flex: 1; }
.bx-page .bx-search input[type="text"],
.bx-page .bx-search select {
  padding: 11px 16px;
  border-radius: var(--bx-radius-btn);
  border: 1px solid rgba(255, 255, 255, 0.24);
  background: rgba(0, 0, 0, 0.25);
  color: #fff;
  font-family: inherit;
  font-size: var(--bx-text-sm);
}
.bx-page .bx-search input[type="text"] { flex: 1; min-width: 200px; }
.bx-page .bx-search input::placeholder { color: rgba(255, 255, 255, 0.5); }
.bx-page .bx-search__opt { display: inline-flex; align-items: center; gap: 8px; font-size: var(--bx-text-xs); color: var(--bx-on-blue-muted); white-space: nowrap; }

.bx-page .bx-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--bx-space-6);
  align-items: start;
}
.bx-page .bx-panel {
  background: #fff;
  border-radius: var(--bx-radius);
  padding: clamp(1.5rem, 3vw, 2.25rem);
}
.bx-page .bx-panel--quiet { background: transparent; border: 1px solid var(--bx-line-light); }
.bx-page .bx-panel__title { font-size: var(--bx-text-h3); font-weight: 500; margin-bottom: var(--bx-space-3); }
.bx-page .bx-panel__lede { font-size: var(--bx-text-sm); color: var(--bx-on-light-muted); margin-bottom: var(--bx-space-6); }

/* Forms. Selectors are on the elements OpenCart emits, so its ids and names
   are untouched and its validation still lands where it expects. */
.bx-page .bx-form { display: flex; flex-direction: column; gap: var(--bx-space-4); }
.bx-page .bx-field { display: flex; flex-direction: column; gap: 6px; }
.bx-page .bx-field label { font-size: var(--bx-text-xs); color: var(--bx-on-light-muted); }
.bx-page .bx-field input,
.bx-page .bx-field select,
.bx-page .bx-field textarea,
.bx-page .band-light input[type="text"],
.bx-page .band-light input[type="email"],
.bx-page .band-light input[type="password"],
.bx-page .band-light input[type="tel"],
.bx-page .band-light select,
.bx-page .band-light textarea {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--bx-line-light);
  border-radius: var(--bx-radius);
  background: #fff;
  color: var(--bx-on-light);
  font-family: inherit;
  font-size: var(--bx-text-sm);
}
/* The rule above gives every field width:100%, which is right for a field that
   owns its row and wrong for one sharing a Bootstrap .input-group with a prefix
   addon or a button. Bootstrap sets .input-group > .form-control to width:1% so
   flex can size it, but that selector is 0,2,0 and loses to the 0,3,1 above —
   so the control claimed the full row, overflowed the group, and .input-group's
   flex-wrap:wrap dropped it onto its own line. That is the stacked "+971 above
   the number" on register and the icon / select / Choose stack on checkout.

   Restores Bootstrap's intent at a weight that survives. flex-wrap is left
   alone: .invalid-feedback is width:100% and is supposed to take its own line
   under the control. */
.bx-page .band-light .input-group > .form-control,
.bx-page .band-light .input-group > .form-select,
.bx-page .bx-field .input-group > .form-control,
.bx-page .bx-field .input-group > .form-select,
.bx-page .band-light .input-group > input,
.bx-page .band-light .input-group > select,
.bx-page .bx-field .input-group > input,
.bx-page .bx-field .input-group > select {
  width: 1%;
  min-width: 0;
  flex: 1 1 auto;
}
/* The addon and the trailing button size to their content and must not be the
   things that give way when the row is tight. */
.bx-page .band-light .input-group > .input-group-text,
.bx-page .band-light .input-group > .btn,
.bx-page .bx-field .input-group > .input-group-text,
.bx-page .bx-field .input-group > .btn {
  flex: 0 0 auto;
  width: auto;
}

.bx-page .band-light input:focus,
.bx-page .band-light select:focus,
.bx-page .band-light textarea:focus {
  outline: 2px solid var(--bx-blue);
  outline-offset: 1px;
  border-color: transparent;
}
.bx-page .bx-field__aside { font-size: var(--bx-text-xs); color: var(--bx-blue); align-self: flex-start; }
.bx-page .bx-btn-block { width: 100%; }

/* OpenCart writes validation errors into .invalid-feedback and flags the input
   with .is-invalid; both are its class names, so they are styled, not renamed. */
.bx-page .band-light .invalid-feedback { display: none; font-size: var(--bx-text-xs); color: #b3261e; }
.bx-page .band-light .invalid-feedback.d-block { display: block; }
.bx-page .band-light .is-invalid { border-color: #b3261e; }

/* OpenCart emits its own Bootstrap buttons inside these forms — the register
   submit, the cart's update/remove/checkout, the search controls. They are its
   class names, so they are restyled rather than renamed, and they take the same
   pill, the same #074a77 and the same outline as .bx-btn on the homepage. A
   page should not have two button languages on it. */
.bx-page .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--bx-space-2);
  padding: 12px 28px;
  border: 1px solid transparent;
  border-radius: var(--bx-radius-btn);
  font-family: inherit;
  font-size: var(--bx-text-sm);
  font-weight: 500;
  line-height: 1.2;
  cursor: pointer;
  transition: background .25s var(--bx-expo), border-color .25s var(--bx-expo), color .25s var(--bx-expo);
}
.bx-page .btn-primary,
.bx-page .btn-success {
  background: var(--bx-blue);
  border-color: var(--bx-blue);
  color: #fff;
}
.bx-page .btn-primary:hover,
.bx-page .btn-success:hover { background: var(--bx-blue-hover); border-color: var(--bx-blue-hover); color: #fff; }

/* Secondary actions on a light band: outlined pill, matching "Explore Peptides". */
.bx-page .btn-light,
.bx-page .btn-secondary,
.bx-page .btn-outline-primary,
.bx-page .btn-outline-secondary {
  background: transparent;
  border-color: rgba(11, 11, 11, 0.34);
  color: var(--bx-on-light);
}
.bx-page .btn-light:hover,
.bx-page .btn-secondary:hover,
.bx-page .btn-outline-primary:hover,
.bx-page .btn-outline-secondary:hover { border-color: var(--bx-on-light); background: transparent; }

/* Destructive stays legible as destructive — same shape, its own colour. */
.bx-page .btn-danger {
  background: transparent;
  border-color: rgba(179, 38, 30, 0.5);
  color: #b3261e;
}
.bx-page .btn-danger:hover { background: #b3261e; border-color: #b3261e; color: #fff; }

/* Icon-only controls in the cart rows stay square-ish rather than stretched. */
.bx-page .btn-sm { padding: 8px 14px; font-size: var(--bx-text-xs); }
.bx-page .input-group .btn { border-radius: var(--bx-radius-btn); }
/* Icon-only controls: square-ish, and sized by the SVG rather than by text. */
.bx-page .bx-icon-btn { width: 38px; height: 38px; padding: 0; flex: none; }
.bx-page .bx-icon-btn svg { width: 16px; height: 16px; }

.bx-page .bx-note {
  padding: 12px 16px;
  border-radius: var(--bx-radius);
  font-size: var(--bx-text-sm);
  margin-bottom: var(--bx-space-5);
}
.bx-page .bx-note--ok  { background: #e6f4ea; color: #10361d; }
.bx-page .bx-note--bad { background: #fdecea; color: #7f1d1a; }

/* ==================================================== responsive ======== */
@media (max-width: 1000px) {
  .bx-page .program-grid,
  .bx-page .store-grid, .bx-page #product-list { grid-template-columns: repeat(2, 1fr); }
  .bx-page .pdp { grid-template-columns: 1fr; }
  .bx-page .bx-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--bx-space-5);
  align-items: start;
}
.bx-page .bx-links { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.bx-page .bx-links a {
  display: block;
  padding: 9px 0;
  font-size: var(--bx-text-sm);
  color: var(--bx-on-light-muted);
  border-bottom: 1px solid var(--bx-line-light);
}
.bx-page .bx-links li:last-child a { border-bottom: 0; }
.bx-page .bx-links a:hover { color: var(--bx-blue); }

.bx-page .bx-narrow { max-width: 760px; }

/* Search bar, sitting in the blue band like the store's sort row. */
.bx-page .bx-search { display: flex; gap: var(--bx-space-3); flex: 1; }
.bx-page .bx-search input[type="text"],
.bx-page .bx-search select {
  padding: 11px 16px;
  border-radius: var(--bx-radius-btn);
  border: 1px solid rgba(255, 255, 255, 0.24);
  background: rgba(0, 0, 0, 0.25);
  color: #fff;
  font-family: inherit;
  font-size: var(--bx-text-sm);
}
.bx-page .bx-search input[type="text"] { flex: 1; min-width: 200px; }
.bx-page .bx-search input::placeholder { color: rgba(255, 255, 255, 0.5); }
.bx-page .bx-search__opt { display: inline-flex; align-items: center; gap: 8px; font-size: var(--bx-text-xs); color: var(--bx-on-blue-muted); white-space: nowrap; }

.bx-page .bx-split { grid-template-columns: 1fr; }
  .bx-page .bx-cards { grid-template-columns: repeat(2, 1fr); }
  .bx-page .pdp-spec { grid-template-columns: 1fr; gap: 2px var(--bx-space-5); }
  .bx-page .pdp-spec dd { margin-bottom: var(--bx-space-3); }
  .bx-page .standards { grid-template-columns: 1fr; }
  .bx-page .standards-copy { max-width: none; margin-left: 0; }
  .bx-page .standards-visual { min-height: 320px; order: -1; }
  .bx-page .footer-grid { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 860px) {
  .bx-page .nav-links, .bx-page .nav-account { display: none; }
  .bx-page .nav-toggle { display: block; margin-left: auto; }
  /* The nav stays ABSOLUTE here. Making it position:relative turned it into a
     flex child of .hero, which is `display:flex; align-items:center` — so the
     logo and burger were being centred vertically in the middle of the hero
     instead of sitting at the top. It only needs a ground of its own so the
     open menu stays readable over the photograph. */
  .bx-page .site-nav {
    background: rgba(11, 11, 11, 0.94);
    backdrop-filter: saturate(150%) blur(12px);
    -webkit-backdrop-filter: saturate(150%) blur(12px);
  }
  .bx-page .hero-content { padding-top: 132px; }
  .bx-page .mobile-menu {
    display: none;
    flex-direction: column;
    gap: var(--bx-space-4);
    padding-bottom: var(--bx-space-5);
    font-size: var(--bx-text-sm);
  }
  .bx-page .mobile-menu.open { display: flex; }
  .bx-page .hero::after {
    content: '';
    background: linear-gradient(180deg, rgba(11,11,11,0.55) 0%, rgba(11,11,11,0.85) 100%);
  }
  .bx-page .pillars, .bx-page .metrics { grid-template-columns: 1fr; }
  .bx-page .pillar, .bx-page .metric {
    border-left: 0;
    border-top: 1px solid var(--bx-line-blue);
    padding-inline: 0;
    padding-block: var(--bx-space-5);
  }
  .bx-page .pillar:first-child, .bx-page .metric:first-child { border-top: 0; }
}

@media (max-width: 620px) {
  .bx-page .program-grid,
  .bx-page .store-grid, .bx-page #product-list { grid-template-columns: 1fr; }
  .bx-page .store-bar__inner { flex-direction: column; align-items: stretch; gap: var(--bx-space-3); padding-block: var(--bx-space-4); }
  .bx-page .bx-cards { grid-template-columns: 1fr; }
  .bx-page .bx-search { flex-direction: column; }
  .bx-page .store-count { text-align: left; }
  .bx-page .footer-grid { grid-template-columns: 1fr; }
  .bx-page .step { grid-template-columns: 1fr; gap: var(--bx-space-2); }
  .bx-page .btn-row .bx-btn { width: 100%; }
}

@media (prefers-reduced-motion: reduce) {
  .bx-page * { transition: none !important; }
}

/* ============================================================== sign in == */
/* Patient / Clinic / Physician. A white pill track with the active segment
   filled blue, per the design. */
.bx-page .signin-seg {
  display: inline-flex;
  gap: 4px;
  padding: 5px;
  background: #fff;
  border-radius: var(--bx-radius-btn);
}
/* Figma 185:23266: 89.49 x 40.25. The tablist is 285.17 in the frame, which is
   three tabs — this site has four since Trainers was added, so the tab is the
   spec and the list width follows from it. */
.bx-page .signin-seg__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  min-width: 89.49px;
  height: 40.25px;
  padding: 0 18px;
  border-radius: var(--bx-radius-btn);
  font-size: var(--bx-text-sm);
  font-weight: 500;
  color: var(--bx-on-light);
  text-decoration: none;
  transition: background .2s var(--bx-expo), color .2s var(--bx-expo);
}
.bx-page .signin-seg__btn:hover { background: rgba(7, 74, 119, 0.08); }
.bx-page .signin-seg__btn.is-active { background: var(--bx-blue); color: #fff; }

.bx-page .signin-sub {
  margin: var(--bx-space-4) 0 var(--bx-space-7);
  font-size: var(--bx-text-sm);
  color: var(--bx-on-light-muted);
}

.bx-page .signin-grid {
  display: grid;
  /* Figma 185:23271 / 185:23286: the form card is 626.36 and the aside 513.64
     in a 1320 section, at x=5 and x=806 — a 174.64 gutter between them. */
  grid-template-columns: minmax(0, 626.36px) minmax(0, 513.64px);
  gap: 174.64px;
  align-items: start;
}
.bx-page .signin-card,
.bx-page .signin-aside {
  /* Figma 185:23274: the form starts at x=40.89 inside the card, so 36 left the
     form and its button ~9.78 wider than the frame's 544.58. */
  padding: 40.89px;
  border-radius: var(--bx-radius-btn);
}
.bx-page .signin-card  { background: #fff; }
.bx-page .signin-aside { background: #dde5ec; }

/* biorax.css sets colour on h1–h4 directly, so both cards declare their own. */
.bx-page .signin-card h2,
.bx-page .signin-aside h2 {
  font-size: 1.35rem;
  font-weight: 500;
  color: var(--bx-on-light);
  margin-bottom: var(--bx-space-2);
}
.bx-page .signin-card__lede,
.bx-page .signin-aside p {
  font-size: var(--bx-text-sm);
  color: var(--bx-on-light-muted);
  margin-bottom: var(--bx-space-6);
}
.bx-page .signin-aside p { margin-bottom: var(--bx-space-7); }

.bx-page .signin-form .bx-field { margin-bottom: var(--bx-space-5); }
.bx-page .signin-form label,
.bx-page .contact-card label {
  display: block;
  margin-bottom: 8px;
  font-family: var(--bx-font-mono);
  font-size: var(--bx-text-eyebrow);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bx-on-light-muted);
}
.bx-page .signin-form input {
  width: 100%;
  padding: 14px 16px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: #e9e9e9;
  color: var(--bx-on-light);
  font-family: inherit;
  font-size: var(--bx-text-sm);
}
.bx-page .signin-form input:focus-visible {
  outline: none;
  border-color: var(--bx-blue);
  background: #fff;
}
.bx-page .signin-forgot {
  display: block;
  margin-top: 8px;
  text-align: right;
  font-size: var(--bx-text-xs);
  color: var(--bx-blue);
}
/* .btn-row sizes CTA buttons at 229x47; these are block-width by design.
   Figma 185:23284 gives the sign-in button 51.75 and 185:23289 the aside's
   "Create an account" 53.53. */
.bx-page .signin-card .bx-btn-block,
.bx-page .signin-aside .bx-btn-block {
  width: 100%;
  height: 51.75px;
  border-radius: var(--bx-radius-btn);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-size: var(--bx-text-xs);
  font-weight: 600;
}
.bx-page .signin-aside .bx-btn-block { height: 53.53px; }

/* Figma 185:23276/185:23280: inputs are 43.78 tall. */
.bx-page .signin-form input { height: 43.78px; padding-block: 0; }
.bx-page .bx-btn-light { background: #fff; color: var(--bx-on-light); }
.bx-page .bx-btn-light:hover { background: var(--bx-blue); color: #fff; }

@media (max-width: 1000px) {
  .bx-page .signin-grid { grid-template-columns: 1fr; gap: var(--bx-space-6); }
}

/* ============================================================== account == */
.bx-page .acct-hero__row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--bx-space-4);
  /* .hero-content > * caps its children at 700px for the headline measure.
     This row is a layout band, not a text block: left at 700 the
     space-between edge lands mid-hero and the signed-in line reads as
     left-aligned. Cap the copy inside instead. */
  max-width: none;
  width: 100%;
}
.bx-page .acct-hero__row .lede { max-width: 700px; }
.bx-page .acct-signedin { text-align: right; margin-left: auto; }
.bx-page .acct-signedin { font-size: var(--bx-text-sm); color: var(--bx-on-dark-muted); }
.bx-page .acct-signedin b { color: #fff; font-weight: 600; }
.bx-page .acct-signedin a { color: var(--bx-on-dark-muted); text-decoration: underline; }

.bx-page .acct-protocol {
  padding: 36px 40px 28px;
  border-radius: var(--bx-radius-btn);
  background: var(--bx-black);
  color: var(--bx-on-dark);
  margin-bottom: var(--bx-space-5);
}
.bx-page .acct-protocol h2 { font-size: 1.35rem; font-weight: 500; color: #fff; }
.bx-page .acct-protocol__lede {
  margin-bottom: var(--bx-space-5);
  font-size: var(--bx-text-xs);
  color: var(--bx-on-dark-muted);
}

.bx-page .acct-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--bx-space-5);
  /* No align-items: start. That sized each card to its own content, so
     Preferences with one link ended far shorter than Orders & shop with four.
     Grid's default stretch gives the three the same height, as the design
     shows. */
}
/* The links sit at the top; the card just gets taller. */
.bx-page .acct-card { display: flex; flex-direction: column; }
.bx-page .acct-card {
  padding: 28px 32px 20px;
  height: 100%;
  border-radius: var(--bx-radius-btn);
  background: #fff;
}
.bx-page .acct-card h2 { font-size: 1.15rem; font-weight: 500; color: var(--bx-on-light); }
.bx-page .acct-card__lede {
  margin-bottom: var(--bx-space-4);
  font-size: var(--bx-text-xs);
  color: var(--bx-on-light-muted);
}

.bx-page .acct-links { list-style: none; margin: 0; padding: 0; }
.bx-page .acct-links--split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: var(--bx-space-8);
}
.bx-page .acct-links a,
.bx-page .acct-links .is-soon {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bx-space-4);
  padding: 15px 0;
  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
  font-size: var(--bx-text-sm);
  color: var(--bx-on-light);
  text-decoration: none;
  transition: color .2s var(--bx-expo);
}
.bx-page .acct-links a:hover { color: var(--bx-blue); }
.bx-page .acct-protocol .acct-links a,
.bx-page .acct-protocol .acct-links .is-soon {
  color: var(--bx-on-dark);
  border-bottom-color: rgba(255, 255, 255, 0.16);
}
.bx-page .acct-protocol .acct-links a:hover { color: var(--bx-accent); }
/* No route behind these yet, so they are not links and must not look like one. */
.bx-page .acct-links .is-soon { color: var(--bx-on-dark-faint); cursor: default; }
.bx-page .acct-links .is-soon em {
  font-style: normal;
  font-family: var(--bx-font-mono);
  font-size: var(--bx-text-eyebrow);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  opacity: 0.7;
}

@media (max-width: 1000px) {
  .bx-page .acct-cards,
  .bx-page .acct-links--split { grid-template-columns: 1fr; }
  .bx-page .acct-protocol { padding: 28px 24px 20px; }
}

/* ================================================================ about == */
/* Cap the CHILDREN, never .hero-content itself — it is the .wrap element, and
   .wrap is `margin-inline: auto`, so a max-width here centres the whole block
   instead of narrowing the text. That is what pushed this hero's content to
   x=550 rather than the 100px gutter, and it also squeezed .btn-row to 420px,
   below the 470px two 229px buttons need, so they wrapped and stacked. */
.bx-page .about-hero__label {
  margin-bottom: var(--bx-space-2);
  font-size: var(--bx-text-sm);
  color: var(--bx-on-dark-muted);
}
.bx-page .hero--about .btn-row { margin-top: var(--bx-space-6); }

/* Image left, copy right — the mirror of the homepage band. */
.bx-page .standards--flip { grid-template-columns: 767fr 753fr; }
.bx-page .standards--flip .standards-copy { margin-left: 0; margin-right: auto; }
.bx-page .standards--flip .standards-copy p { margin-bottom: var(--bx-space-4); }
.bx-page .standards--flip .standards-copy .bx-btn { margin-top: var(--bx-space-4); }

.bx-page .about-pillars .pillars { grid-template-columns: repeat(3, 1fr); }
.bx-page .about-pillars .pillar h3 {
  font-size: 1.1rem;
  font-weight: 500;
  color: var(--bx-on-blue);
  margin-bottom: var(--bx-space-3);
}
.bx-page .about-pillars .pillar p { font-size: var(--bx-text-xs); color: var(--bx-on-blue-muted); }

.bx-page .gov-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--bx-space-5);
}
.bx-page .gov-card {
  display: flex;
  align-items: flex-start;
  gap: var(--bx-space-4);
  padding: 24px;
  border-radius: var(--bx-radius-btn);
  background: #fff;
}
.bx-page .gov-card__icon { flex: none; color: var(--bx-blue); }
.bx-page .gov-card__icon svg { width: 28px; height: 28px; }
.bx-page .gov-card h3 {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--bx-on-light);
  margin-bottom: 6px;
}
.bx-page .gov-card p { font-size: var(--bx-text-xs); color: var(--bx-on-light-muted); }

.bx-page .contact-band {
  background: var(--bx-black);
  color: var(--bx-on-dark);
  padding-block: var(--bx-section-y);
}
.bx-page .contact-grid {
  display: grid;
  grid-template-columns: 1fr minmax(0, 560px);
  gap: var(--bx-space-8);
  align-items: start;
}
.bx-page .contact-copy h2 {
  font-size: var(--bx-text-h2);
  font-weight: 400;
  color: #fff;
  margin-bottom: var(--bx-space-4);
}
.bx-page .contact-copy > p {
  max-width: 46ch;
  margin-bottom: var(--bx-space-7);
  font-size: var(--bx-text-sm);
  color: var(--bx-on-dark-muted);
}
.bx-page .contact-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--bx-space-5); }
.bx-page .contact-list li { display: flex; align-items: center; gap: var(--bx-space-4); }
.bx-page .contact-list__icon {
  flex: none;
  display: grid;
  place-items: center;
  width: 40px; height: 40px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}
.bx-page .contact-list__icon svg { width: 18px; height: 18px; }
.bx-page .contact-list__label {
  display: block;
  font-family: var(--bx-font-mono);
  font-size: var(--bx-text-eyebrow);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bx-on-dark-faint);
}
.bx-page .contact-list a,
.bx-page .contact-list div > span:last-child { font-size: var(--bx-text-sm); color: var(--bx-on-dark); }

.bx-page .contact-card {
  padding: 32px;
  border-radius: var(--bx-radius-btn);
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: #0e0e0e;
}
.bx-page .contact-card h3 { font-size: 1.2rem; font-weight: 500; color: #fff; margin-bottom: var(--bx-space-5); }
.bx-page .contact-card .bx-field { margin-bottom: var(--bx-space-4); }
.bx-page .contact-card label { color: var(--bx-on-dark-faint); }
.bx-page .contact-card input,
.bx-page .contact-card textarea {
  width: 100%;
  padding: 13px 15px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.06);
  color: #fff;
  font-family: inherit;
  font-size: var(--bx-text-sm);
  resize: vertical;
}
.bx-page .contact-card input::placeholder,
.bx-page .contact-card textarea::placeholder { color: rgba(255, 255, 255, 0.35); }
.bx-page .contact-card input:focus-visible,
.bx-page .contact-card textarea:focus-visible { outline: none; border-color: var(--bx-accent); }
.bx-page .contact-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--bx-space-4); }
.bx-page .contact-card .bx-btn-block {
  width: 100%;
  height: 48px;
  border-radius: var(--bx-radius-btn);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-size: var(--bx-text-xs);
  font-weight: 600;
}

@media (max-width: 1000px) {
  .bx-page .standards--flip { grid-template-columns: 1fr; }
  .bx-page .standards--flip .standards-visual { order: -1; }
  .bx-page .about-pillars .pillars,
  .bx-page .gov-grid { grid-template-columns: 1fr; }
  .bx-page .contact-grid { grid-template-columns: 1fr; }
  .bx-page .contact-row { grid-template-columns: 1fr; }
}

/* =============================================================== outcome == */
/* common/success.twig — order confirmation, failed payment, sign-out, return,
   contact and GDPR all render through here, so nothing below assumes success.
   The mark is the only thing that differs. */
.bx-page .outcome-card {
  max-width: 760px;
  padding: 44px 48px 40px;
  border-radius: var(--bx-radius-btn);
  background: #fff;
}
.bx-page .outcome-mark {
  display: grid;
  place-items: center;
  width: 56px; height: 56px;
  margin-bottom: var(--bx-space-5);
  border-radius: 50%;
  background: rgba(7, 74, 119, 0.10);
  color: var(--bx-blue);
}
.bx-page .outcome-card--bad .outcome-mark {
  background: rgba(150, 40, 40, 0.10);
  color: #962828;
}
.bx-page .outcome-mark svg { width: 26px; height: 26px; }

/* text_message is language-file HTML: a stack of <p>, some carrying links. */
.bx-page .outcome-body p {
  margin-bottom: var(--bx-space-4);
  font-size: var(--bx-text-sm);
  line-height: 1.65;
  color: var(--bx-on-light-muted);
}
.bx-page .outcome-body p:first-child {
  font-size: 1.05rem;
  color: var(--bx-on-light);
}
.bx-page .outcome-body p:last-child { margin-bottom: 0; }
.bx-page .outcome-body a {
  color: var(--bx-blue);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.bx-page .outcome-body a:hover { text-decoration-thickness: 2px; }
.bx-page .outcome-card .btn-row { margin-top: var(--bx-space-7); }

@media (max-width: 700px) {
  .bx-page .outcome-card { padding: 32px 24px 28px; }
}


/* =============================================================== science == */
/* Supplied: hero 1519x741, and the CTA pair at top 502/503 with the second at
   left 346 — 17px after the first ends at 329, not the 12px .btn-row uses
   elsewhere. */
.bx-page .hero--science { min-height: clamp(440px, 48.78vw, 741px); }
.bx-page .hero--science .btn-row { gap: 17px; margin-top: var(--bx-space-6); }

/* Featured story. Supplied as 1520x796 directly under the hero, image left.
   Same split proportion as the homepage band so the two read as one system. */
.bx-page .sci-featured {
  display: grid;
  grid-template-columns: 753fr 767fr;
  min-height: 796px;
  background: var(--bx-light);
}
.bx-page .sci-featured__visual { position: relative; order: -1; }
.bx-page .sci-featured__visual img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.bx-page .sci-featured__copy {
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* 52px, not the shared 4.5vw: the column splits at 753 and the supplied
     content starts at 805. */
  padding: var(--bx-section-y) clamp(1.25rem, 3.4vw, 52px);
  max-width: calc(var(--bx-max) / 2);
}
/* biorax.css paints h1-h4 directly, so the light band declares its own. */
.bx-page .sci-featured__copy,
.bx-page .sci-featured__copy h2 { color: var(--bx-on-light); }
.bx-page .sci-featured__copy h2 {
  font-size: var(--bx-text-h2);
  font-weight: 400;
  margin-bottom: var(--bx-space-4);
}
.bx-page .sci-featured__copy > p {
  max-width: 46ch;
  margin-bottom: var(--bx-space-7);
  font-size: var(--bx-text-sm);
  color: var(--bx-on-light-muted);
}
.bx-page .sci-featured__row { display: flex; align-items: center; gap: 17px; flex-wrap: wrap; }

/* 94x47 r15 for the pills, 229x47 r15 for Read Now — supplied. min-width, not
   width: "5 min read" is wider than "New" and must not be clipped to fit a
   number taken from the shorter one. */
.bx-page .sci-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 94px;
  height: 47px;
  padding: 0 16px;
  border: 1px solid rgba(0, 0, 0, 0.22);
  border-radius: var(--bx-radius-btn);
  font-size: var(--bx-text-xs);
  color: var(--bx-on-light);
  white-space: nowrap;
}
.bx-page .sci-read { width: 229px; height: 47px; border-radius: var(--bx-radius-btn); }

/* Collection tabs + category filters. */
.bx-page .sci-bar { background: var(--bx-blue); color: var(--bx-on-blue); }
.bx-page .sci-bar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bx-space-5);
  flex-wrap: wrap;
  padding-block: var(--bx-space-6);
}
.bx-page .sci-tabs { display: flex; gap: var(--bx-space-6); }
.bx-page .sci-tab {
  background: none;
  border: 0;
  padding: 0;
  font-family: inherit;
  font-size: 1.35rem;
  font-weight: 400;
  color: var(--bx-on-blue-muted);
  cursor: pointer;
}
.bx-page .sci-tab.is-active { color: #fff; }
.bx-page .sci-filters { display: flex; flex-wrap: wrap; gap: var(--bx-space-2); }
.bx-page .sci-filter {
  height: 34px;
  padding: 0 18px;
  border: 1px solid rgba(255, 255, 255, 0.34);
  border-radius: var(--bx-radius-btn);
  background: transparent;
  font-family: inherit;
  font-size: var(--bx-text-xs);
  color: var(--bx-on-blue);
  cursor: pointer;
  transition: background .2s var(--bx-expo), color .2s var(--bx-expo), border-color .2s var(--bx-expo);
}
.bx-page .sci-filter:hover { border-color: #fff; }
.bx-page .sci-filter.is-active { background: var(--bx-black); border-color: var(--bx-black); color: #fff; }

/* Cards: 425x452, radius 8, first at the 100px gutter. Three across the 1320
   content box leaves 45px for two gaps — 22.5 each, which is what lands 425. */
/* Supplied: the first card sits at top 1759 and the bar above ends at 1636. */
.bx-page .sci-grid-band { padding-block: 123px var(--bx-section-y); }
.bx-page .sci-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 22.5px;
}
.bx-page .sci-card {
  display: flex;
  flex-direction: column;
  height: 452px;
  padding: 12px 12px 0;
  border-radius: 8px;
  background: #fff;
  color: var(--bx-on-light);
  text-decoration: none;
  overflow: hidden;
  transition: box-shadow .3s var(--bx-expo), transform .3s var(--bx-expo);
}
.bx-page .sci-card:hover { box-shadow: 0 10px 28px rgba(0,0,0,.13); transform: translateY(-2px); }
.bx-page .sci-card__media { position: relative; display: block; border-radius: 6px; overflow: hidden; }
.bx-page .sci-card__media img { width: 100%; height: auto; aspect-ratio: 401/223; object-fit: cover; display: block; }
.bx-page .sci-card__tags { position: absolute; top: 10px; left: 10px; display: flex; gap: 6px; }
.bx-page .sci-pill--sm {
  min-width: 0;
  height: 24px;
  padding: 0 10px;
  border: 0;
  background: rgba(255, 255, 255, 0.92);
  font-size: 0.68rem;
}
.bx-page .sci-card__body { display: flex; flex-direction: column; gap: 8px; padding: 16px 6px 18px; }
.bx-page .sci-card__title { font-size: 1rem; font-weight: 500; }
.bx-page .sci-card__excerpt {
  font-size: var(--bx-text-xs);
  line-height: 1.55;
  color: var(--bx-on-light-muted);
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.bx-page .sci-card__date { margin-top: auto; font-size: var(--bx-text-xs); color: var(--bx-on-light-muted); }
.bx-page .sci-empty { padding: var(--bx-space-8) 0; color: var(--bx-on-light-muted); }

@media (max-width: 1000px) {
  .bx-page .sci-featured { grid-template-columns: 1fr; min-height: 0; }
  .bx-page .sci-featured__visual { min-height: 320px; }
  .bx-page .sci-featured__copy { max-width: none; }
  .bx-page .sci-grid { grid-template-columns: 1fr; }
  .bx-page .sci-card { height: auto; }
}

/* ======================================================= science article == */
/* Supplied: hero 1519 x 771. */
.bx-page .hero--article { min-height: clamp(460px, 50.76vw, 771px); }
.bx-page .sa-tags { display: flex; gap: 12px; margin-top: var(--bx-space-6); }
.bx-page .sa-tag {
  display: inline-flex;
  align-items: center;
  height: 47px;
  padding: 0 24px;
  border: 1px solid rgba(255, 255, 255, 0.34);
  border-radius: var(--bx-radius-btn);
  font-size: var(--bx-text-sm);
  color: var(--bx-on-dark);
  white-space: nowrap;
}
.bx-page .sa-tag--solid { background: var(--bx-blue); border-color: var(--bx-blue); color: #fff; }

/* The pager bar under the hero. */
.bx-page .sa-bar { background: var(--bx-blue); color: var(--bx-on-blue); }
.bx-page .sa-bar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--bx-space-5);
  flex-wrap: wrap;
  padding-block: var(--bx-space-7);
}
.bx-page .sa-bar__all { font-size: var(--bx-text-sm); color: var(--bx-on-blue); }
.bx-page .sa-bar__all:hover { color: #fff; }
.bx-page .sa-pager { display: flex; align-items: center; gap: var(--bx-space-4); }
.bx-page .sa-pager__btn {
  display: grid;
  place-items: center;
  width: 34px; height: 34px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  font-size: 0.9rem;
}
.bx-page .sa-pager__btn--solid { background: var(--bx-black); }
.bx-page .sa-pager__label { font-size: var(--bx-text-sm); color: var(--bx-on-blue); }
.bx-page .sa-pager__label:hover { color: #fff; }
/* At the first or last article the control keeps its shape and stops being a
   link, rather than disappearing and reflowing the bar between articles. */
.bx-page .sa-pager .is-off { opacity: 0.4; cursor: default; }

/* Body: a share rail on the left, the article on the right. */
.bx-page .sa-band { padding-block: var(--bx-section-y); }
.bx-page .sa-intro {
  max-width: 700px;
  padding-bottom: var(--bx-space-7);
  border-bottom: 1px solid rgba(0, 0, 0, 0.14);
  margin-bottom: var(--bx-space-7);
  font-size: var(--bx-text-sm);
  line-height: 1.7;
  color: var(--bx-on-light);
}
.bx-page .sa-split {
  display: grid;
  grid-template-columns: 1fr 614px;
  gap: var(--bx-space-8);
  align-items: start;
}
/* Sticky, so the share links stay reachable through a long article rather than
   scrolling away in the first screen. Offset clears the fixed nav. */
.bx-page .sa-share { position: sticky; top: 108px; }
.bx-page .sa-share__label {
  margin-bottom: var(--bx-space-4);
  font-size: var(--bx-text-xs);
  color: var(--bx-on-light-muted);
}
.bx-page .sa-share__links { display: flex; gap: 12px; }
.bx-page .sa-share__links a {
  display: grid;
  place-items: center;
  width: 38px; height: 38px;
  border-radius: 50%;
  background: #fff;
  color: var(--bx-on-light);
  transition: background .2s var(--bx-expo), color .2s var(--bx-expo);
}
.bx-page .sa-share__links a:hover { background: var(--bx-blue); color: #fff; }
.bx-page .sa-share__links svg { width: 16px; height: 16px; }

.bx-page .sa-body { color: var(--bx-on-light); }
.bx-page .sa-body h2 {
  font-size: 1.75rem;
  font-weight: 400;
  line-height: 1.25;
  color: var(--bx-on-light);
  margin: var(--bx-space-8) 0 var(--bx-space-5);
}
.bx-page .sa-body h2:first-child { margin-top: 0; }
.bx-page .sa-body h3 { font-size: 1.15rem; font-weight: 500; color: var(--bx-on-light); margin: var(--bx-space-6) 0 var(--bx-space-3); }
.bx-page .sa-body p {
  margin-bottom: var(--bx-space-5);
  font-size: var(--bx-text-sm);
  line-height: 1.75;
  color: var(--bx-on-light-muted);
}
.bx-page .sa-body ul, .bx-page .sa-body ol { margin: 0 0 var(--bx-space-5) 1.1rem; }
.bx-page .sa-body li { margin-bottom: 8px; font-size: var(--bx-text-sm); line-height: 1.75; color: var(--bx-on-light-muted); }
.bx-page .sa-body a { color: var(--bx-blue); text-decoration: underline; text-underline-offset: 2px; }
.bx-page .sa-top {
  display: inline-block;
  margin-top: var(--bx-space-7);
  font-size: var(--bx-text-xs);
  color: var(--bx-on-light-muted);
}
.bx-page .sa-top:hover { color: var(--bx-blue); }

@media (max-width: 1000px) {
  .bx-page .sa-split { grid-template-columns: 1fr; gap: var(--bx-space-6); }
  .bx-page .sa-share { position: static; }
}

/* ====================================================== programme pages == */
/* Supplied: the strip under the hero is 1519 x 182 on #074A77, with a hairline
   on its top and left only. Scoped to the band that directly follows a hero, so
   the metrics band on a programme page and the pillars band on the landing both
   get it, while other .band-blue sections are untouched. */
.bx-page .hero + .band-blue {
  min-height: 182px;
  display: flex;
  align-items: center;
  padding-block: 0;
  border-width: 0.91px 0 0 0.91px;
  border-style: solid;
  border-color: #00000021;
}
.bx-page .hero + .band-blue > .wrap { width: 100%; }

/* The CTA pair below the programme rail. The supplied colours invert the usual
   pair: Start my assessment is the dark one here and Explore Peptides carries
   the blue, which is the reverse of the hero. Left 521 and 769 in a 1519 frame
   is a centred pair 19px apart, so it is centred rather than positioned. */
.bx-page .btn-row--programs {
  gap: 19px;
  padding-top: 119px;     /* rail ends at 850, buttons at 969 */
  padding-bottom: 101px;  /* 1016 -> 1117 */
}
.bx-page .btn-row--programs .bx-btn-primary { background: #0E212D; border-color: #0E212D; }
.bx-page .btn-row--programs .bx-btn-primary:hover { background: #16323f; border-color: #16323f; }
.bx-page .btn-row--programs .bx-btn-outline-dark {
  background: #074A77;
  border: 1px solid #FFFFFF59;
  color: #fff;
}
.bx-page .btn-row--programs .bx-btn-outline-dark:hover { background: #095c93; }

/* The programme you are on stays in the rail, centred and already open, rather
   than being dropped from it. */
.bx-page .program-tile.is-current {
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.13);
  /* The rail is scroll-snap-type: x mandatory and its tiles snap to `start`,
     so setting scrollLeft to a centred position was immediately snapped back —
     the tile landed 168px off. Snapping THIS tile to centre lets the snap do
     the centring instead of fighting the script. */
  scroll-snap-align: center;
}
.bx-page .program-tile.is-current .program-tile__media img { filter: none; opacity: 1; }
.bx-page .program-tile.is-current .program-tile__name { color: var(--bx-on-light); font-weight: 500; }
.bx-page .program-tile.is-current .program-tile__panel {
  opacity: 1;
  visibility: visible;
  transform: none;
}

/* The rail reserves --bx-rail-overhang so an open panel is not clipped, and
   that reservation has to stay on the page.

   This previously carried an equal negative margin on the Store and Product
   pages, on the reasoning that the strip read as empty there because nothing is
   expanded by default. That reasoning was wrong. The negative margin does not
   just hide an empty strip — it pulls the CLOSING CTA up over the exact region
   an open panel drops into, so hovering or tab-focusing a tile opened the panel
   underneath the dark band and cut it in half. The Programmes pages never
   showed it because their current programme is expanded on load, which fills
   the space and makes the collision obvious rather than latent.

   Raising the panel's z-index instead would paint a white popover over the dark
   CTA, which is not what the Programmes pages do. Keeping the space is what
   makes Store and Product behave like path=70_71. */

/* ==================================================== programmes dropdown == */
/* Mirrors .nav-login rather than inventing a second dropdown: same open/close
   behaviour, same ground, so the two menus in one bar cannot drift apart.
   Opens on hover AND on :focus-within, so it is reachable by keyboard. */
.bx-page .nav-drop { position: relative; }
.bx-page .nav-drop__menu {
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translate(-50%, -6px);
  z-index: 60;
  min-width: 232px;
  margin-top: 8px;
  padding: 8px;
  border-radius: var(--bx-radius);
  background: var(--bx-blue-deep);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.45);
  opacity: 0;
  visibility: hidden;
  transition: opacity .2s var(--bx-expo), transform .2s var(--bx-expo), visibility .2s;
}
.bx-page .nav-drop:hover .nav-drop__menu,
.bx-page .nav-drop:focus-within .nav-drop__menu {
  opacity: 1;
  visibility: visible;
  transform: translate(-50%, 0);
}
/* Bridges the 8px gap between the label and the panel, so crossing it does not
   close the menu mid-move. */
.bx-page .nav-drop__menu::before {
  content: '';
  position: absolute;
  left: 0; right: 0; top: -10px;
  height: 10px;
}
.bx-page .nav-drop__menu a {
  display: block;
  padding: 9px 14px;
  border-radius: var(--bx-radius);
  font-size: var(--bx-text-sm);
  color: rgba(255, 255, 255, 0.86);
  white-space: nowrap;
}
.bx-page .nav-drop__menu a:hover,
.bx-page .nav-drop__menu a:focus-visible { background: var(--bx-blue); color: #fff; }
.bx-page .nav-drop__all {
  margin-bottom: 4px;
  padding-bottom: 12px !important;
  border-bottom: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 0 !important;
}

/* The mobile drawer lists the programmes flat — there is no hover on touch. */
.bx-page .mobile-menu__sub {
  padding-left: var(--bx-space-4);
  font-size: var(--bx-text-xs);
  color: var(--bx-on-dark-muted);
}


/* Hero actions on the account dashboard. */
.bx-page .hero--account .btn-row { margin-top: var(--bx-space-6); }

/* Floating WhatsApp, as it was in the previous build: 56px circle, bottom
   right, WhatsApp green. z-index sits under the nav's 50... deliberately not:
   the nav is fixed across the top and this is bottom-right, so they never meet,
   and 60 keeps it above page content that sets its own stacking. */
.bx-page .wa-widget {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: #2f8f5b;
  color: #fff;
  box-shadow: 0 10px 24px -8px rgba(0, 0, 0, 0.4);
  transition: transform .16s ease;
}
.bx-page .wa-widget:hover { transform: scale(1.06); color: #fff; }
@media (prefers-reduced-motion: reduce) {
  .bx-page .wa-widget { transition: none; }
}

/* ==================================================== dosage calculator == */
/* Supplied: the hero CTA is 229x47 r15 #074A77 at left 100. */
.bx-page .hero--calc { min-height: clamp(440px, 48.78vw, 741px); }
.bx-page .hero--calc .btn-row { margin-top: var(--bx-space-6); }

.bx-page .dc-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--bx-space-8);
  align-items: start;
}
.bx-page .dc-card {
  padding: 36px;
  border-radius: var(--bx-radius-btn);
  background: #fff;
}
.bx-page .dc-field { margin-bottom: var(--bx-space-5); }
.bx-page .dc-field label,
.bx-page .dc-row label {
  display: block;
  margin-bottom: 8px;
  font-family: var(--bx-font-mono);
  font-size: var(--bx-text-eyebrow);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bx-on-light-muted);
}
.bx-page .dc-card input,
.bx-page .dc-card select {
  width: 100%;
  padding: 14px 16px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: #e9e9e9;
  color: var(--bx-on-light);
  font-family: inherit;
  font-size: var(--bx-text-sm);
}
.bx-page .dc-card input:focus-visible,
.bx-page .dc-card select:focus-visible { outline: none; border-color: var(--bx-blue); background: #fff; }
.bx-page .dc-row { display: grid; grid-template-columns: 2fr 1fr; gap: var(--bx-space-4); }
.bx-page .dc-hint { font-size: var(--bx-text-xs); color: var(--bx-on-light-muted); }

.bx-page .dc-results {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--bx-space-4);
  margin-top: var(--bx-space-6);
  padding-top: var(--bx-space-6);
  border-top: 1px solid rgba(0, 0, 0, 0.12);
}
.bx-page .dc-result, .bx-page .dc-results > div { display: flex; flex-direction: column; gap: 6px; }
.bx-page .dc-results .lbl {
  font-family: var(--bx-font-mono);
  font-size: var(--bx-text-eyebrow);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bx-on-light-muted);
}
.bx-page .dc-results .val { font-size: 1.9rem; font-weight: 400; color: var(--bx-blue); }
/* A dosing warning must not be quiet — this is the one thing on the page that
   says a number looks wrong. */
.bx-page .dc-warn {
  grid-column: 1 / -1;
  margin-top: var(--bx-space-3);
  padding: 12px 14px;
  border-radius: 8px;
  background: rgba(150, 40, 40, 0.10);
  color: #7d2020;
  font-size: var(--bx-text-xs);
}
.bx-page .dc-aside h2 { font-size: 1.35rem; font-weight: 500; color: var(--bx-on-light); margin-bottom: var(--bx-space-3); }
.bx-page .dc-aside p, .bx-page .dc-aside li { font-size: var(--bx-text-sm); line-height: 1.7; color: var(--bx-on-light-muted); }
.bx-page .dc-aside ol { margin: var(--bx-space-3) 0 0 1.1rem; }
.bx-page .dc-aside li { margin-top: 8px; }
.bx-page .dc-example {
  margin-top: var(--bx-space-6);
  padding: 20px;
  border-radius: var(--bx-radius-btn);
  background: #fff;
}
.bx-page .dc-example .mono { font-family: var(--bx-font-mono); font-size: var(--bx-text-xs); color: var(--bx-blue); }
.bx-page .dc-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* The shared button width is 229px, but this label is a full sentence and
     overflowed the pill on both edges. Size to the text, keeping 229 as the
     floor so it never reads narrower than its siblings. */
  min-width: 229px;
  padding-inline: 28px;
  white-space: nowrap;
  height: 47px;
  margin-top: var(--bx-space-6);
  border-radius: var(--bx-radius-btn);
  background: var(--bx-blue);
  color: #fff;
  font-size: var(--bx-text-sm);
  font-weight: 500;
}
.bx-page .dc-cta:hover { background: #095c93; color: #fff; }
.bx-page .dc-disclaimer { margin-top: var(--bx-space-7); font-size: var(--bx-text-xs); color: var(--bx-on-light-muted); }

@media (max-width: 1000px) {
  .bx-page .dc-grid { grid-template-columns: 1fr; gap: var(--bx-space-6); }
  .bx-page .dc-card { padding: 24px; }
}

/* ============================================================== cart ==== */
/* Supplied: section 1320 wide at left 100, summary 430.78 starting at
   section-x 889. 1320 - 430.78 - 889 leaves the gap at 59, and the items
   column takes the rest. */
.bx-page .cart-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 430.78px;
  gap: 59px;
  align-items: start;
}
.bx-page .cart-items { display: flex; flex-direction: column; }
.bx-page .cart-row {
  display: grid;
  grid-template-columns: 88px minmax(0, 1fr) auto auto 24px;
  align-items: center;
  gap: var(--bx-space-5);
  padding: 24px 0;
  border-bottom: 1px solid rgba(0, 0, 0, 0.12);
}
.bx-page .cart-row:first-child { border-top: 1px solid rgba(0, 0, 0, 0.12); }
/* 88x88 radius 12, supplied. */
.bx-page .cart-row__thumb {
  display: block;
  width: 88px;
  height: 88px;
  border-radius: 12px;
  overflow: hidden;
  background: #ddd;
}
.bx-page .cart-row__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.bx-page .cart-row__name {
  display: block;
  font-size: var(--bx-text-sm);
  font-weight: 600;
  color: var(--bx-on-light);
}
.bx-page .cart-row__name:hover { color: var(--bx-blue); }
.bx-page .cart-row__opts { list-style: none; margin: 6px 0 0; padding: 0; }
.bx-page .cart-row__opts li,
.bx-page .cart-row__sub { margin-top: 4px; font-size: var(--bx-text-xs); color: var(--bx-on-light-muted); }

.bx-page .cart-row__qty {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px;
  border: 1px solid rgba(0, 0, 0, 0.18);
  border-radius: var(--bx-pill);
  background: #fff;
}
.bx-page .cart-qty__step {
  width: 26px; height: 26px;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--bx-on-light);
  font-family: inherit;
  font-size: 1rem;
  line-height: 1;
  cursor: pointer;
}
.bx-page .cart-qty__step:hover { background: rgba(0, 0, 0, 0.06); }
.bx-page .cart-qty__input {
  width: 34px;
  border: 0;
  background: transparent;
  color: var(--bx-on-light);
  font-family: inherit;
  font-size: var(--bx-text-sm);
  text-align: center;
}
.bx-page .cart-qty__input:focus-visible { outline: none; }
.bx-page .cart-row__price { font-size: var(--bx-text-sm); font-weight: 600; color: var(--bx-on-light); white-space: nowrap; }
.bx-page .cart-row__remove { display: grid; place-items: center; width: 24px; height: 24px; color: var(--bx-on-light-muted); }
.bx-page .cart-row__remove:hover { color: #962828; }
.bx-page .cart-row__remove svg { width: 18px; height: 18px; }
.bx-page .cart-row__min { grid-column: 2 / -1; margin-top: 6px; font-size: var(--bx-text-xs); color: #962828; }
.bx-page .cart-continue { margin-top: var(--bx-space-6); font-size: var(--bx-text-sm); color: var(--bx-on-light-muted); }
.bx-page .cart-continue:hover { color: var(--bx-blue); }

/* Summary: 430.78 wide, radius 16, 1px #00000024, padding 32.89 so its content
   box is exactly the supplied 365 button width. */
.bx-page .cart-summary {
  /* 31.89, not 32.89: the supplied 32.89 is from the border box, and the 1px
     border on each side is inside the 430.78. 430.78 - 2 - 2x31.89 = 365, the
     supplied button width. */
  padding: 31.89px;
  border-radius: 16px;
  border: 1px solid #00000024;
  background: #FFFFFF;
}
.bx-page .cart-summary h2 {
  font-size: 1.35rem;
  font-weight: 500;
  color: var(--bx-on-light);
  margin-bottom: var(--bx-space-6);
}
.bx-page .cart-totals { display: flex; flex-direction: column; gap: var(--bx-space-4); }
.bx-page .cart-total {
  display: flex;
  justify-content: space-between;
  gap: var(--bx-space-4);
  font-size: var(--bx-text-sm);
  color: var(--bx-on-light-muted);
}
.bx-page .cart-total--grand {
  margin-top: var(--bx-space-3);
  padding-top: var(--bx-space-5);
  border-top: 1px solid rgba(0, 0, 0, 0.12);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--bx-on-light);
}
/* 365 x 51, radius 15, #074A77, supplied. Width comes from the card's content
   box rather than being set, so the two cannot drift. */
.bx-page .cart-checkout {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 51px;
  margin-top: var(--bx-space-7);
  border-radius: var(--bx-radius-btn);
  background: #074A77;
  box-shadow: 0 1px 2px 0 #00000026;
  color: #fff;
  font-size: var(--bx-text-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.bx-page .cart-checkout:hover { background: #095c93; color: #fff; }
.bx-page .cart-note { margin-top: var(--bx-space-4); text-align: center; font-size: var(--bx-text-xs); color: var(--bx-on-light-muted); }
.bx-page .cart-modules { margin-top: var(--bx-space-8); }

@media (max-width: 1000px) {
  .bx-page .cart-grid { grid-template-columns: 1fr; gap: var(--bx-space-6); }
  .bx-page .cart-row { grid-template-columns: 64px minmax(0, 1fr) auto; row-gap: var(--bx-space-3); }
  .bx-page .cart-row__thumb { width: 64px; height: 64px; }
  .bx-page .cart-row__qty { grid-column: 2 / -1; justify-self: start; }
}

/* About: the two buttons that sit outside a .btn-row and so never picked up the
   229x47 / radius 15 the CTA pairs use — Explore Standards was 176x49 on a pill
   radius, and the contact Submit was on a pill too. */
.bx-page--about .standards-copy .bx-btn {
  width: 229px;
  height: 47px;
  padding: 0 20px;
  border-radius: var(--bx-radius-btn);
}
.bx-page--about .contact-card .bx-btn-block {
  height: 47px;
  border-radius: var(--bx-radius-btn);
}

/* ================================================== assessment (theme) == */
/* The assessment carries a 346-line inline <style> built on the legacy
   biorax.css palette — --ink, --border, --surface — plus hardcoded #2563eb,
   #0927f2, #16a34a and #dc2626. Rather than rewrite that block and risk the
   flow it drives, the theme's colours, radii and button treatment are applied
   over it here. Loaded after, and every rule carries .bx-page--assessment, so
   these win on specificity without !important.

   The fonts already resolve to Geist through --font-sans, so they are left. */

.bx-page--assessment .bxa-card {
  border-radius: var(--bx-radius-btn);
  border: 1px solid #00000024;
  box-shadow: 0 1px 2px 0 #00000026;
}

/* Progress: the brand blue, not the legacy ink. */
.bx-page--assessment .bxa-progress__fill,
.bx-page--assessment .bxa-progress__bar > * { background: var(--bx-blue); }
.bx-page--assessment .bxa-progress__label {
  font-family: var(--bx-font-mono);
  font-size: var(--bx-text-eyebrow);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bx-on-light-muted);
}

.bx-page--assessment .bxa-section-label {
  font-family: var(--bx-font-mono);
  font-size: var(--bx-text-eyebrow);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bx-blue);
}
.bx-page--assessment .bxa-question__text,
.bx-page--assessment .bxa-header__title { color: var(--bx-on-light); }
.bx-page--assessment .bxa-header__title {
  font-family: var(--bx-font-mono);
  font-size: var(--bx-text-eyebrow);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--bx-on-light-muted);
}

/* Answer options: the theme's radius, and the brand blue when chosen. */
.bx-page--assessment .bxa-opt {
  border-radius: var(--bx-radius-btn);
  border: 1px solid #00000024;
  background: #fff;
  color: var(--bx-on-light);
  font-size: var(--bx-text-sm);
  transition: border-color .2s var(--bx-expo), background .2s var(--bx-expo), color .2s var(--bx-expo);
}
.bx-page--assessment .bxa-opt:hover { border-color: var(--bx-blue); }
.bx-page--assessment .bxa-opt.is-selected,
.bx-page--assessment .bxa-opt[aria-pressed="true"],
.bx-page--assessment .bxa-opt[data-selected="1"] {
  background: var(--bx-blue);
  border-color: var(--bx-blue);
  color: #fff;
}

/* Actions on the supplied button spec: 229x47, radius 15, #074A77. */
.bx-page--assessment .bxa-nav-next,
.bx-page--assessment .bxa-btn:not(.bxa-btn--outline):not(.bxa-btn--wa) {
  min-width: 229px;
  height: 47px;
  padding: 0 20px;
  border-radius: var(--bx-radius-btn);
  background: #074A77;
  border: 1px solid #074A77;
  color: #fff;
  font-size: var(--bx-text-sm);
  font-weight: 500;
}
.bx-page--assessment .bxa-nav-next:hover,
.bx-page--assessment .bxa-btn:not(.bxa-btn--outline):not(.bxa-btn--wa):hover {
  background: #095c93; border-color: #095c93; opacity: 1;
}
.bx-page--assessment .bxa-btn--outline {
  min-width: 229px;
  height: 47px;
  border-radius: var(--bx-radius-btn);
  border: 1px solid #00000024;
  color: var(--bx-on-light);
}
.bx-page--assessment .bxa-btn--outline:hover { border-color: var(--bx-blue); color: var(--bx-blue); }
/* WhatsApp keeps its own green — it is a brand mark, not a theme colour. */
.bx-page--assessment .bxa-btn--wa { border-radius: var(--bx-radius-btn); height: 47px; }

.bx-page--assessment .bxa-nav-back,
.bx-page--assessment .bxa-header__back { color: var(--bx-on-light-muted); font-size: var(--bx-text-sm); }
.bx-page--assessment .bxa-nav-back:hover,
.bx-page--assessment .bxa-header__back:hover { color: var(--bx-blue); }

/* ==================================================== checkout (theme) == */
/* Checkout renders core's Bootstrap fieldsets, so the theme is applied over
   them here. Scoped to the page and loaded after Bootstrap, so no !important. */
.bx-page--checkout fieldset {
  padding: 28px 32px;
  margin-bottom: var(--bx-space-5);
  border: 1px solid #00000024;
  border-radius: var(--bx-radius-btn);
  background: #fff;
}
.bx-page--checkout legend {
  float: none;
  width: auto;
  margin-bottom: var(--bx-space-5);
  font-size: 1.15rem;
  font-weight: 500;
  color: var(--bx-on-light);
}
.bx-page--checkout label,
.bx-page--checkout .form-label {
  font-family: var(--bx-font-mono);
  font-size: var(--bx-text-eyebrow);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--bx-on-light-muted);
}
.bx-page--checkout .form-control,
.bx-page--checkout .form-select {
  padding: 13px 15px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: #e9e9e9;
  color: var(--bx-on-light);
  font-family: inherit;
  font-size: var(--bx-text-sm);
}
.bx-page--checkout .form-control:focus,
.bx-page--checkout .form-select:focus {
  border-color: var(--bx-blue);
  background: #fff;
  box-shadow: none;
}
/* Every checkout action on the supplied button spec. */
.bx-page--checkout .btn-primary,
.bx-page--checkout .bxt-confirm-btn {
  height: 47px;
  padding: 0 24px;
  border-radius: var(--bx-radius-btn);
  background: #074A77;
  border: 1px solid #074A77;
  color: #fff;
  font-size: var(--bx-text-sm);
  font-weight: 500;
}
.bx-page--checkout .btn-primary:hover,
.bx-page--checkout .bxt-confirm-btn:hover { background: #095c93; border-color: #095c93; }
.bx-page--checkout .input-group > .btn-primary { border-radius: 0 var(--bx-radius-btn) var(--bx-radius-btn) 0; }
.bx-page--checkout .input-group > .form-control { border-radius: 8px 0 0 8px; }

/* Bootstrap only paints .invalid-feedback when a sibling carries .is-invalid.
   Checkout writes its errors straight into #error-payment-method and the like,
   so "Payment address required!" was set and never shown — clicking Choose
   looked like it did nothing at all. Shown whenever it has text. */
.bx-page--checkout .invalid-feedback:not(:empty) {
  display: block;
  margin-top: 8px;
  padding: 10px 12px;
  border-radius: 8px;
  background: rgba(150, 40, 40, 0.10);
  color: #7d2020;
  font-size: var(--bx-text-xs);
}
.bx-page--checkout .alert { border-radius: var(--bx-radius-btn); font-size: var(--bx-text-sm); }

/* Assessment result: email capture. */
.bx-page--assessment .bxa-capture { margin: var(--bx-space-6) 0 var(--bx-space-5); }
.bx-page--assessment .bxa-capture__line {
  margin-bottom: var(--bx-space-4);
  font-size: var(--bx-text-sm);
  line-height: 1.6;
  color: var(--bx-on-light);
}
.bx-page--assessment .bxa-capture__link {
  color: #074A77;
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.bx-page--assessment .bxa-capture__link:hover { text-decoration-thickness: 2px; }
.bx-page--assessment .bxa-capture__row { display: flex; gap: 12px; flex-wrap: wrap; }
.bx-page--assessment #bxa-capture-email {
  flex: 1 1 220px;
  height: 47px;
  padding: 0 16px;
  border: 1px solid #00000024;
  border-radius: var(--bx-radius-btn);
  background: #fff;
  font-family: inherit;
  font-size: var(--bx-text-sm);
  color: var(--bx-on-light);
}
.bx-page--assessment #bxa-capture-email:focus-visible { outline: none; border-color: #074A77; }
.bx-page--assessment .bxa-capture__btn {
  height: 47px;
  padding: 0 24px;
  border-radius: var(--bx-radius-btn);
  background: #074A77;
  border: 1px solid #074A77;
  color: #fff;
  font-size: var(--bx-text-sm);
  font-weight: 500;
  cursor: pointer;
}
.bx-page--assessment .bxa-capture__btn:hover { background: #095c93; opacity: 1; }

/* Wishlist hearts, hidden for now at your request. Hidden rather than removed
   from the templates: the buttons are real <button type="submit"> carrying
   OpenCart's wishlist_add formaction inside the product form, so deleting them
   would mean editing that wiring back in later. display:none also takes them
   out of the tab order, so they are not reachable while hidden.

   The nav's wishlist icon is left alone — it links to the saved list rather
   than adding to it, and you asked about the store pages. */
.bx-page .bx-prod__wish,
.bx-page .pdp-wish { display: none; }

/* Assessment: skip straight to booking. */
.bx-page--assessment .bxa-header { justify-content: space-between; }
.bx-page--assessment .bxa-skip {
  margin-left: auto;
  height: 36px;
  padding: 0 16px;
  border: 1px solid #074A77;
  border-radius: var(--bx-radius-btn);
  background: transparent;
  color: #074A77;
  font-family: inherit;
  font-size: var(--bx-text-xs);
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
}
.bx-page--assessment .bxa-skip:hover { background: #074A77; color: #fff; }
.bx-page--assessment .bxa-skip[disabled] { opacity: .6; cursor: default; }
/* Explicit rather than relying on the UA sheet: the rule above sets no
   display, so [hidden] would work unaided today, but a later display
   declaration on .bxa-skip would silently un-hide it mid-assessment. */
.bx-page--assessment .bxa-skip[hidden] { display: none; }

/* ===================================== Store landing, to Figma 85:835 ==== */
/* C and D of the Store - Landing Page comparison. The closing CTA is scoped to
   the store page on purpose: bx_cta.twig is shared, and the approved homepage
   carries 229x47 buttons in a shorter band. Widening it globally would undo
   that, so the store's own numbers stay on the store. */

/* D. The frame puts the heading at y=280, "Overview" at 373 and a 554-wide
   description at 405.25 in a 741 hero. The Store listing no longer uses that
   hero — it is a compact banner now (see .hero--store above), so those anchors
   have nothing to anchor to and the padding that produced them is gone. The
   heading and description rules below still apply on any page that keeps the
   full hero. */
/* Figma's text boxes are tighter than the rendered line boxes (its overline is
   16.86 tall against 22.68 here), so the gaps are set to land each block on its
   designed y — 373 and 405.25 — rather than to copy the gaps themselves. */
/* h1.hero-title--store, not .hero-title--store: `.bx-page .hero h1` carries an
   element selector and would otherwise outrank this on specificity. */
.bx-page--store .hero--store h1.hero-title--store { margin-bottom: 28.05px; }
.bx-page--store .hero--store .hero-overline { margin-bottom: 9.6px; }
.bx-page--store .hero--store .lede { max-width: 554px; }

/* The listing starts 20px under the blue bar, not 88. Figma 85:891 ends at 923
   and 85:950 begins at 943; the shared .section rhythm was adding its own 88px
   on top of a bar that is already a full band of spacing. programs-band is
   excluded — its 124px top is its own designed value. */
.bx-page--store .band-light.section:not(.programs-band) { padding-top: 20px; }

/* C. Closing CTA — GLOBAL, per Figma 217:29886 (1519 x 375).
   That node is the canonical band and its buttons are 229x47 with a 19px gap,
   which is what every other page already draws. The Store frame's own copy
   (85:912/85:914) has them at 278x48 and 279x50 with a 1px vertical offset —
   one-off drift in that frame, not the spec, so it is deliberately not used.
   Heading sits at y=100 and the buttons at y=213, leaving 115 beneath. The
   heading renders 48.26 tall here against the file's 53, so the gap under it is
   set to land the buttons on 213 rather than to copy the file's own gap. */
.bx-page .cta-band { padding-block: 100px 115px; }
.bx-page .cta-band h2 { margin-bottom: 64.74px; }
.bx-page .cta-band .btn-row { gap: 19px; }

/* ================================== homepage hero rotator (79:3 / 217:26739) */
/* Both frames are 1519x878, so the two banners are interchangeable in place and
   only cross-fade. The slides share one grid cell rather than being stacked
   with position:absolute, so the taller slide still sets the hero's height and
   rotating never reflows the page. */
.bx-page .hero-slides { display: grid; width: 100%; }
.bx-page .hero-slide {
  grid-area: 1 / 1;
  display: flex;
  align-items: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity .6s var(--bx-expo), visibility .6s;
}
.bx-page .hero-slide.is-active { opacity: 1; visibility: visible; }
/* The image belongs to its slide, so it fades with the copy. */
.bx-page .hero-slide .bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: 60% center; }
.bx-page .hero-slide .hero-content { position: relative; z-index: 1; width: 100%; }

.bx-page .hero-dots {
  position: absolute;
  left: 100px;
  bottom: 40px;
  z-index: 2;
  display: flex;
  gap: 10px;
}
.bx-page .hero-dot {
  width: 34px;
  height: 4px;
  padding: 0;
  border: 0;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.32);
  cursor: pointer;
  transition: background .3s var(--bx-expo);
}
.bx-page .hero-dot.is-active { background: #ffffff; }
.bx-page .hero-dot:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

/* A rotation nobody asked for is a motion problem: with reduced motion the
   fade is removed and the rotator stops advancing (handled in bx-pages.js). */
@media (prefers-reduced-motion: reduce) {
  .bx-page .hero-slide { transition: none; }
}

@media (max-width: 900px) {
  .bx-page .hero-dots { left: 24px; bottom: 24px; }
}

/* ============================== homepage section stack, Figma 79:2 ======== */
/* Live ran 150px short of the frame overall. Every value below is the frame's:
   sections are anchored on the y positions of their own first element, and the
   two inter-section gaps the frame carries were missing entirely.

   Scoped to the homepage: .band-light.section, .band-dark.section and
   .cta-band are shared, and the Store and Programmes pages have their own
   rhythm that is already signed off. */

/* A1 is now global — see the .site-nav rule near the top of this file. Every
   frame gives the header 77 (111:1483 homepage, 79:305 Programs, 85:862 Store),
   so it is not a homepage value. */

/* A2. Programs 1060..2667 = 1607. Its eyebrow sits at y=113 inside the
   section (79:32), which is the top padding; the remainder goes below. */
.bx-page--home .band-light.section:not(#faq) { padding-block: 113px 127.31px; }

/* A3. Journey 2667..3561 = 894, eyebrow at 112.9 (79:92). */
.bx-page--home .band-dark.section { padding-block: 112.9px 80px; }

/* A4. Outcomes is 978 in the frame (79:112) and splits as the 796 standards
   panel plus a 182 metrics band — the same 182 as the pillars band under the
   hero. The metrics band was drawing 164.63. */
.bx-page--home .standards + .band-blue { min-height: 182px; display: flex; align-items: center; }

/* A5. The frame leaves 81 between Outcomes and the FAQ (4539..4620).

   Padding, NOT margin. .bx-page is rgb(11,11,11), so a margin here exposed the
   page ground and drew a black band between the blue metrics strip and the light
   FAQ. In the frame that space is the light ground, continuous with the FAQ, so
   it has to belong to the light band. The gap is the same either way; only which
   element paints it changes. */
.bx-page--home #faq { padding-top: 81px; }

/* A6. FAQ 4620..5382 = 762. Its eyebrow sits at the very top of the section in
   the frame (79:133 at y=0.91), so the top padding is the 81 gap above rather
   than padding of its own. */
/* 72.58 of the frame's own bottom space, plus the 80 it leaves before the
   closing band. That 80 was a margin on .cta-band, which exposed .bx-page's
   #0B0B0B above the band's #010101 — two near-blacks meeting, which read as a
   black rectangle above the artwork because the CTA's photo does not extend
   into a margin. In the frame that space is the light ground continuing from
   the FAQ, so it belongs to the light band. */
.bx-page--home #faq.band-light.section { padding-bottom: 152.58px; }

/* A7. The 80 between the FAQ and the closing band (5382..5462) is carried by
   the FAQ's padding above — see the note there. */

/* ============================ Programs landing, Figma 79:218 ============= */
/* The rail band plus its button row already measure 1117 together, which is the
   frame's CONDITIONS block — those are left alone. What follows is the rest of
   the stack, which ran 253 short.

   Scoped to the Programs page: these sections are shared, and the homepage and
   Store have their own signed-off rhythm. */

/* A2. The pillars band is 182 in the frame (79:326), the same as every other
   blue band on the site. It was drawing 209. */
.bx-page--programs .band-blue { min-height: 182px; display: flex; align-items: center; }
/* With the frame's copy the pillars come to 188.82 against the band's 182. The
   6.82 comes off the pillars' own vertical padding rather than the type, so the
   text keeps its shared size and leading. */
.bx-page--programs .pillar { padding-block: calc(var(--bx-space-7) - 3.41px); }

/* C1/C2. Hero lede is 554 wide at y=454 (80:530); the heading sits at 310
   (80:528) and the button row at 551.98 (79:338).

   Anchored from the top rather than nudged with margins: .hero centres its
   content, so a margin added inside also grows the block and re-centres it,
   landing about half of every increment and dragging the heading and buttons
   off their own anchors while chasing the lede. */
.bx-page--programs .hero { align-items: flex-start; }
.bx-page--programs .hero .hero-content { padding-top: 255.85px; padding-bottom: 0; }
/* Gaps set to land each block on its own anchor rather than to copy the file's
   gaps. The "Overview" line is gone from this hero — the Program Landing frame
   has no such node, unlike the Store, Product, Program Inner, Science, Blog and
   About frames, which all carry one — so this gap covers the space it held. The
   eyebrow above still has no counterpart in the frame and is left in place. */
.bx-page--programs .hero h1 { margin-bottom: 79.06px; }
.bx-page--programs .hero .lede { max-width: 554px; margin-bottom: 29.94px; }

/* The frame leaves 6 between the CONDITIONS block and Journey (2177..2183). */
.bx-page--programs .band-dark.section { margin-top: 6px; }

/* A4. Journey is 894 (285:2), eyebrow at 112.9. It was 877. */
/* The bottom padding grew when step 04 came out: the frame's Journey is 894
   with three steps, so the space the fourth held stays in the section. */
.bx-page--programs .band-dark.section { padding-block: 112.9px 174.52px; }

/* A5. 273 between Journey and the FAQ (3077..3350) — the frame's largest gap
   and it was missing entirely. */
/* A6. FAQ is 762 (79:277) against 865, and its eyebrow sits at the top of the
   section (y=0.91), so the space above it is the gap rather than padding.
   D1. It is also 872 wide at x=316 on this page — a narrow inset column, not
   the full 1320 wrap the homepage FAQ uses. */
.bx-page--programs .band-light.section:not(.programs-band) {
  /* Padding, not margin: .bx-page is near-black, so a margin drew a dark band
     between the metrics strip and the light FAQ. See the homepage note above. */
  /* 127, not the frame's 273. The Programmes frame (79:218) leaves 273 above
     its FAQ, but the programme pages leave 127 and those are the ones a visitor
     moves between — a 273 gap here read as a broken page beside them. Asked for
     explicitly; this is the one place the site is deliberately off its frame. */
  padding-top: 127px;
  /* 72.58 of its own, plus the 87 before the closing band — carried here rather
     than as a margin on .cta-band, which would show the page's near-black above
     the band's. See the homepage note. */
  padding-bottom: 159.58px;
}
.bx-page--programs .band-light.section:not(.programs-band) > .wrap {
  width: 872px;
  max-width: 100%;
  margin-inline: 316px auto;
  padding-inline: 0;
}

/* A7. The 87 before the closing band is carried by the FAQ's padding above. */

/* ============== programme detail FAQ, Figma 217:29945 (Program Inner) ==== */
/* 872 wide at x=324, 762 tall, with 127 above it.

   NOT 760 at x=380: that is 217:29858, which sits in the "Banner Only" frame —
   a homepage variant, not a programme page. The Program Inner frames are the
   ones these pages render, and they put the FAQ at 872/324 like the Programs
   landing's 872/316.

   The eyebrow sits at y=0.91 inside the section, so the section carries no top
   padding of its own and the 127 above it is a margin. Without that margin the
   FAQ butted straight against the section before it, which is the missing space
   at the top border. */
.bx-page--program .band-light.section:not(.programs-band) {
  /* Padding, not margin — same reason as the homepage and Programs landing. */
  padding-top: 127px;
  padding-bottom: 72.59px;
}
.bx-page--program .band-light.section:not(.programs-band) > .wrap {
  width: 872px;
  max-width: 100%;
  margin-inline: 324px auto;
  padding-inline: 0;
}

/* Homepage Journey is 894 in the frame (79:90), eyebrow at 112.9, same as the
   Programs landing. Removing step 04 took it to 799.48. */
.bx-page--home .band-dark.section { padding-block: 112.9px 174.53px; }

/* ============ programme hero "Designed around" panel, Figma 150:74/150:77 == */
/* Label at x=1198.5 y=551, list at x=1198 y=580, 211 wide and 155 tall. The
   hero is a flex row with the copy on the left, so this is positioned rather
   than placed in flow — the copy block is already anchored to its own y values
   and must not move to make room. */
.bx-page--program .hero { position: relative; }
.bx-page--program .hero-aside {
  position: absolute;
  left: 1198px;
  top: 551px;
  z-index: 1;
  width: 211px;
}
.bx-page--program .hero-aside__label {
  display: block;
  font-family: var(--bx-font-mono);
  font-size: var(--bx-text-eyebrow);
  font-weight: 500;
  letter-spacing: var(--bx-tracking-eyebrow);
  text-transform: uppercase;
  color: var(--bx-on-dark-muted);
  margin-bottom: 12px;
}
/* Figma 150:75 bullets each item. The Item frame sits at x=13 inside the list
   while the "Designed around" label above it sits at x=0, so the text is
   indented and the disc hangs to its left — which is what list-style-position
   outside does with that padding. */
.bx-page--program .hero-aside__list {
  list-style: disc;
  margin: 0;
  padding: 0 0 0 13px;
}
.bx-page--program .hero-aside__list li {
  font-size: var(--bx-text-sm);
  line-height: 31px;      /* 5 items in the frame's 155 */
  color: #fff;
}
.bx-page--program .hero-aside__list li::marker {
  /* The List node's own fill, not the item text's white. */
  color: #f1f1f1;
  font-size: 0.85em;
}

/* Journey is 884 on the programme pages (150:2 / 217:33165). The bottom padding
   was calibrated against the old step copy; the supplied copy and the Insight
   Score footnote added 44.72, which took the section to 928.72 and the page to
   5565 against the frame's 5496. */
.bx-page--program .band-dark.section { padding-block: 112.9px 119.8px; }

/* Conditions is 951 here: the rail ends at 850 with 101 below it. The frame
   then leaves 41 before the closing band. Both belong to the light band as
   padding rather than a margin — .bx-page is near-black and a margin would draw
   a dark strip, the same defect fixed on the FAQ gaps. */
.bx-page--program .section.programs-band { padding-bottom: 142.55px; }

/* Journey footnote — right-aligned under the last step, as the design has it. */
.bx-page .journey-note {
  margin-top: var(--bx-space-5);
  text-align: right;
  font-size: var(--bx-text-xs);
  color: var(--bx-on-dark-muted);
}

/* Quantity is hidden on the product page: every peptide is dispensed against a
   prescription, so a quantity stepper is not the control that decides how much
   a visitor receives. The input stays in the form — OpenCart posts it with the
   add-to-cart and removing it would post nothing — it is only not shown.

   #product is in the selector because the rule it overrides carries that id;
   a class-only selector loses to it however specific it looks. */
.bx-page .pdp-buy #product .input-group-text,
.bx-page .pdp-buy #product #input-quantity { display: none; }

/* Figma 85:1246: both buttons 229 x 47, at x=794 and x=1030 — a 7px gutter.
   Add to Cart was flex:1 and stretched to 362; Checkout was pinned to 190. */
.bx-page .pdp-buy { gap: 7px; }
.bx-page .pdp-buy #product { flex: 0 0 auto; }
.bx-page .pdp-buy #product #button-cart,
.bx-page .pdp-buy .bx-btn-checkout {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  flex: 0 0 229px;
  width: 229px;
  height: 47px;
  padding: 0;
}

/* Supplied governance-card artwork replaces the drawn SVGs. width:auto with a
   fixed height so each keeps its own aspect — the pin is portrait, the network
   near-square and the DHA mark landscape, so one square box would distort them.
   The DHA mark is a logo rather than an icon and carries its own size. */
.bx-page .gov-card__img { display: block; height: 28px; width: auto; }
.bx-page .gov-card__img--logo { height: 44px; }

/* ------------------------------------------------------- register form -- */
/* col-sm-2 resolves to 97px in this 584px form, which wrapped every two-word
   label: "First Name" broke across two lines, and so did "Last Name", "Date of
   birth" and "Emirates ID". A fixed column wide enough for the longest label,
   with the control column taking whatever is left. Scoped to .bx-register so
   the other account forms keep their current proportions until they are
   looked at on their own. */
@media (min-width: 576px) {
  .bx-page.bx-acct-form .row > .col-form-label.col-sm-2,
  .bx-page.bx-acct-form .row > .col-form-label.col-md-3,
  .bx-page.bx-register .row > .col-form-label.col-sm-2 {
    flex: 0 0 150px;
    width: 150px;
    max-width: none;
    white-space: nowrap;
  }
  .bx-page.bx-acct-form .row > .col-sm-10,
  .bx-page.bx-acct-form .row > .col-md-9,
  .bx-page.bx-register .row > .col-sm-10 {
    flex: 1 1 0;
    width: auto;
    max-width: none;
  }
  /* The agreement and submit rows sit under the controls, so their offset has
     to track the label column rather than Bootstrap's 16.667%. */
  .bx-page.bx-acct-form .row > .col-sm-10.offset-sm-2,
  .bx-page.bx-register .row > .col-sm-10.offset-sm-2 {
    margin-left: 150px;
  }
}

/* form-switch-lg was applied in the markup but never defined, so the switches
   rendered at Bootstrap's default size and the label — where there was one —
   sat wherever the float left it. */
.bx-page.bx-register .form-check.form-switch.form-switch-lg {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding-left: 0;
  min-height: 0;
}
.bx-page.bx-register .form-check.form-switch.form-switch-lg .form-check-input {
  flex: 0 0 auto;
  float: none;
  margin: 0;
  width: 2.75rem;
  height: 1.5rem;
}
.bx-page.bx-register .form-check.form-switch.form-switch-lg .form-check-label {
  margin: 0;
  line-height: 1.4;
}


/* --------------------------------------------------- account sub-pages -- */
/* Order history, edit account, change password and the address book, on the
   2026 theme. The forms inside are core's, so these style what OpenCart emits
   rather than replacing it — that is what keeps every customer_token link and
   every #error-<field> target intact. */

/* Core wraps each field in .row > label.col-* + div.col-*, which at the default
   widths wrapped every two-word label. The shared rule above gives the label a
   fixed 150px and hands the rest to the control; these two just remove the
   Bootstrap margins that assumed a grid. */
.bx-page.bx-acct-form fieldset { border: 0; padding: 0; margin: 0 0 var(--bx-space-7); }
.bx-page.bx-acct-form legend {
  font-size: var(--bx-text-h3);
  font-weight: 500;
  color: var(--bx-on-light);
  margin-bottom: var(--bx-space-5);
  padding: 0;
  border: 0;
  float: none;
  width: auto;
}
.bx-page.bx-acct-form .row.mb-3 { margin-bottom: var(--bx-space-4); }
.bx-page.bx-acct-form .col-form-label { padding-top: 14px; }
/* The asterisk core puts on .required rows. */
.bx-page.bx-acct-form .required .col-form-label::before {
  content: '*';
  color: #c0392b;
  margin-right: 4px;
}

/* Action row: back on the left, primary on the right, never stacked. */
.bx-page.bx-acct-form .bx-acct-actions,
.bx-page.bx-acct-form .bx-acct-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bx-space-3);
  align-items: center;
  justify-content: space-between;
  margin-top: var(--bx-space-6);
}
.bx-page.bx-acct-form .bx-acct-actions .bx-btn:only-child { margin-left: auto; }

/* Tables. Core emits .table.table-bordered inside .table-responsive for the
   address list; the order list is rewritten but both land here. */
.bx-page.bx-acct-form .bx-acct-table { overflow-x: auto; }
.bx-page.bx-acct-form .bx-acct-table table {
  width: 100%;
  border-collapse: collapse;
  background: #fff;
  border: 1px solid var(--bx-line-light);
  border-radius: var(--bx-radius);
  overflow: hidden;
}
.bx-page.bx-acct-form .bx-acct-table th,
.bx-page.bx-acct-form .bx-acct-table td {
  padding: 14px 18px;
  text-align: left;
  border-bottom: 1px solid var(--bx-line-light);
  font-size: var(--bx-text-sm);
  color: var(--bx-on-light);
  /* A cell is one line unless its content genuinely cannot fit — the reason
     order ids, statuses and dates were breaking mid-value. */
  white-space: nowrap;
}
.bx-page.bx-acct-form .bx-acct-table th {
  font-size: var(--bx-text-xs);
  font-weight: 500;
  color: var(--bx-on-light-muted);
  background: rgba(0, 0, 0, 0.02);
}
.bx-page.bx-acct-form .bx-acct-table tr:last-child td { border-bottom: 0; }
.bx-page.bx-acct-form .bx-acct-table .num,
.bx-page.bx-acct-form .bx-acct-table td.text-end,
.bx-page.bx-acct-form .bx-acct-table th.text-end { text-align: right; }
/* The address list is free text and is the one column that should wrap. */
.bx-page.bx-acct-form .bx-acct-table td:first-child { white-space: normal; }
.bx-page.bx-acct-form .bx-acct-table__id { font-weight: 500; }
.bx-page.bx-acct-form .bx-acct-table__date { color: var(--bx-on-light-muted); }
.bx-page.bx-acct-form .bx-acct-table__link { color: var(--bx-blue); font-weight: 500; }
.bx-page.bx-acct-form .bx-acct-status {
  display: inline-block;
  padding: 3px 10px;
  border-radius: var(--bx-pill);
  background: rgba(7, 74, 119, 0.08);
  color: var(--bx-blue);
  font-size: var(--bx-text-xs);
}

.bx-page.bx-acct-form .bx-acct-pagination {
  display: flex;
  flex-wrap: wrap;
  gap: var(--bx-space-3);
  align-items: center;
  justify-content: space-between;
  margin-top: var(--bx-space-5);
}
.bx-page.bx-acct-form .bx-acct-results { color: var(--bx-on-light-muted); font-size: var(--bx-text-xs); }
.bx-page.bx-acct-form .bx-acct-empty {
  padding: var(--bx-space-7);
  border: 1px dashed var(--bx-line-light);
  border-radius: var(--bx-radius);
  text-align: center;
  color: var(--bx-on-light-muted);
}
.bx-page.bx-acct-form .bx-acct-empty p { margin: 0; }
.bx-page.bx-acct-form .bx-acct-alert {
  padding: 12px 16px;
  border-radius: var(--bx-radius);
  margin-bottom: var(--bx-space-5);
  font-size: var(--bx-text-sm);
}
.bx-page.bx-acct-form .bx-acct-alert--ok {
  background: rgba(7, 74, 119, 0.08);
  color: var(--bx-blue);
}

@media (max-width: 575.98px) {
  .bx-page.bx-acct-form .bx-acct-actions { justify-content: stretch; }
  .bx-page.bx-acct-form .bx-acct-actions .bx-btn { flex: 1 1 auto; }
}

/* Assessment: programme picker and the sign-in / details gate.
   Both are server-rendered hidden and shown in turn by bx-assessment.js, so
   they start display:none rather than relying on JS to hide them — otherwise
   they would flash before the script runs. Same 47px control height, --bx-blue
   and radius as the results-screen capture form above, so the three steps read
   as one flow. */
.bx-page--assessment .bxa-picker,
.bx-page--assessment .bxa-gate { display: none; padding: var(--bx-space-5) 0 var(--bx-space-4); }

.bx-page--assessment .bxa-picker__eyebrow,
.bx-page--assessment .bxa-gate__eyebrow {
  margin: 0 0 var(--bx-space-2);
  font-size: var(--bx-text-xs);
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--bx-on-light-muted, #6b7280);
}
.bx-page--assessment .bxa-picker__title,
.bx-page--assessment .bxa-gate__title {
  margin: 0 0 var(--bx-space-3);
  font-size: var(--bx-text-xl);
  font-weight: 400;
  line-height: 1.25;
  color: var(--bx-on-light);
}
.bx-page--assessment .bxa-picker__lede {
  margin: 0 0 var(--bx-space-5);
  font-size: var(--bx-text-sm);
  line-height: 1.6;
  color: var(--bx-on-light-muted, #6b7280);
}

/* auto-fit rather than a fixed column count: nine items reflow from three
   columns to one without a media query per breakpoint. */
.bx-page--assessment .bxa-picker__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 12px;
  margin-bottom: var(--bx-space-5);
}
.bx-page--assessment .bxa-picker__option {
  display: flex;
  align-items: center;
  min-height: 56px;
  padding: 12px 18px;
  border: 1px solid #00000024;
  border-radius: var(--bx-radius-btn);
  background: #fff;
  font-size: var(--bx-text-sm);
  color: var(--bx-on-light);
  text-decoration: none;
  transition: border-color .2s, background .2s;
}
.bx-page--assessment .bxa-picker__option:hover,
.bx-page--assessment .bxa-picker__option:focus-visible {
  border-color: #074A77;
  background: #074A770A;
  outline: none;
}
.bx-page--assessment .bxa-picker__skip {
  border: 0;
  background: none;
  padding: 0;
  font-family: inherit;
  font-size: var(--bx-text-sm);
  color: #074A77;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.bx-page--assessment .bxa-gate__signin {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  font-size: var(--bx-text-sm);
  color: var(--bx-on-light-muted, #6b7280);
}
.bx-page--assessment .bxa-gate__signin-link {
  color: #074A77;
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.bx-page--assessment .bxa-gate__divider {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: var(--bx-space-4) 0;
  font-size: var(--bx-text-xs);
  color: var(--bx-on-light-muted, #6b7280);
}
.bx-page--assessment .bxa-gate__divider::before,
.bx-page--assessment .bxa-gate__divider::after {
  content: "";
  flex: 1;
  height: 1px;
  background: #00000018;
}

.bx-page--assessment .bxa-gate__form { display: flex; flex-direction: column; gap: var(--bx-space-3); }
.bx-page--assessment .bxa-gate__row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--bx-space-3);
}
.bx-page--assessment .bxa-gate__form label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: var(--bx-text-xs);
  color: var(--bx-on-light-muted, #6b7280);
}
.bx-page--assessment .bxa-gate__form input,
.bx-page--assessment .bxa-gate__form select {
  height: 47px;
  padding: 0 16px;
  border: 1px solid #00000024;
  border-radius: var(--bx-radius-btn);
  background: #fff;
  font-family: inherit;
  font-size: var(--bx-text-sm);
  color: var(--bx-on-light);
}
.bx-page--assessment .bxa-gate__form input:focus-visible,
.bx-page--assessment .bxa-gate__form select:focus-visible { outline: none; border-color: #074A77; }

/* The +971 prefix sits outside the input, as on the register form, so the
   value posted is the national part only. */
.bx-page--assessment .bxa-gate__tel { display: flex; align-items: stretch; }
.bx-page--assessment .bxa-gate__tel-prefix {
  display: flex;
  align-items: center;
  padding: 0 12px;
  border: 1px solid #00000024;
  border-right: 0;
  border-radius: var(--bx-radius-btn) 0 0 var(--bx-radius-btn);
  background: #00000008;
  font-size: var(--bx-text-sm);
  color: var(--bx-on-light-muted, #6b7280);
}
.bx-page--assessment .bxa-gate__tel input {
  flex: 1;
  min-width: 0;
  border-radius: 0 var(--bx-radius-btn) var(--bx-radius-btn) 0;
}

.bx-page--assessment .bxa-gate__err,
.bx-page--assessment .bxa-gate__error {
  font-size: var(--bx-text-xs);
  color: #b42318;
}
.bx-page--assessment .bxa-gate__error:empty { display: none; }
.bx-page--assessment .bxa-gate__submit {
  align-self: flex-start;
  height: 47px;
  padding: 0 24px;
  border-radius: var(--bx-radius-btn);
  background: #074A77;
  border: 1px solid #074A77;
  color: #fff;
  font-family: inherit;
  font-size: var(--bx-text-sm);
  font-weight: 500;
  cursor: pointer;
}
.bx-page--assessment .bxa-gate__submit:disabled { opacity: .6; cursor: default; }
