/* ============================================================
   OPTIMAL WELLNESS — shop page
   Rides on styles.css: same tokens, fonts, buttons, nav, footer.
   Dark by necessity, not preference — the vial photography is lit
   on plum, so the cards must sit on plum for the shots to blend
   edge to edge instead of floating on a lighter tile.
   ============================================================ */

/* styles.css holds the page still behind the home-page loader with
   `html:not(.ready) body { overflow: hidden }`, and only scroll-cinematic.js
   ever adds .ready. This page doesn't load that script and has no loader, so
   the lock would never lift and the page could not be scrolled. Undo it here
   rather than in JS alone, so it holds even if the script fails. */
html:not(.ready) body.shop-page { overflow: auto; }

/* The home page hides the nav over a full-bleed hero; there is no hero
   here, so the bar carries its scrolled treatment from the first pixel. */
.shop-page .nav {
  background: rgba(18, 12, 30, .88);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  box-shadow: 0 1px 0 var(--line);
}
.shop-page main { padding-top: 78px; }

/* ---------- Header ---------- */
.sp-head {
  position: relative;
  padding: clamp(46px, 6vw, 76px) 0 clamp(34px, 4.4vw, 54px);
  border-bottom: 1px solid rgba(163, 149, 228, .18);
  background:
    radial-gradient(84% 60% at 50% 0%, rgba(163, 149, 228, .17), rgba(163, 149, 228, 0) 66%),
    var(--plum);
}
.sp-head .eyebrow { color: var(--violet); }
.sp-head h1 { font-size: clamp(34px, 5vw, 60px); margin: 6px 0 0; }
.sp-head .lead { max-width: 620px; margin: 18px 0 0; color: var(--text-dim); }
.sp-legend {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px 10px;
  margin: 24px 0 0; font-size: 12.5px; color: var(--text-dim);
}
.sp-key {
  font-family: var(--font-caps); font-size: 10px; font-weight: 800;
  letter-spacing: .18em; text-transform: uppercase;
  padding: 5px 11px; border-radius: 999px;
}
.sp-key-cart { background: rgba(207, 178, 230, .17); color: var(--lav); border: 1px solid rgba(207, 178, 230, .32); }
.sp-key-rx { background: rgba(226, 169, 78, .16); color: var(--gold); border: 1px solid rgba(226, 169, 78, .32); margin-left: 10px; }

/* ---------- Goal picker ----------
   Outcome-first entry point, mirroring the drip picker on the home page.
   Categories stay below as the taxonomy axis for people who already know
   what they want; the two are mutually exclusive so they can't fight. */
/* Bottom padding matters now that this band ends at a hard colour boundary.
   It was 0 — fine while the picker and the catalogue were the same dark
   ground, and the moment the catalogue went light the chips were sitting on
   the seam. */
.sp-picker { background: var(--ink); padding: clamp(34px, 4.4vw, 54px) 0 clamp(34px, 4.4vw, 54px); }
.picker-q {
  margin: 0 0 16px; font-family: var(--font-display); font-weight: 400;
  font-size: clamp(21px, 2.6vw, 30px); color: var(--text);
}
.sp-goals { display: flex; flex-wrap: wrap; gap: 9px; }
.sp-goals .pchip {
  font-family: var(--font-caps); font-size: 11.5px; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--text); background: rgba(163, 149, 228, .08);
  border: 1px solid rgba(163, 149, 228, .28); border-radius: 999px;
  padding: 12px 18px; min-height: 44px; cursor: pointer;
  transition: color .2s ease, border-color .2s ease, background .2s ease;
}
.sp-goals .pchip:hover { border-color: var(--violet); background: rgba(163, 149, 228, .16); }
.sp-goals .pchip[aria-pressed="true"] { background: var(--violet); border-color: var(--violet); color: #171233; }
.sp-goals .pchip:focus-visible { outline: 2px solid var(--violet); outline-offset: 3px; }
.sp-goal-lead {
  margin: 16px 0 0; font-size: 15px; line-height: 1.6; color: var(--text-dim);
  max-width: 620px; border-left: 2px solid var(--violet); padding-left: 14px;
}
.sp-goal-lead b { color: var(--text); font-weight: 650; }
.sp-browse {
  margin: 0 0 12px; font-size: 10.5px; font-weight: 700; letter-spacing: .2em;
  text-transform: uppercase; color: rgba(242, 236, 242, .42);
}

/* ---------- Catalogue ---------- */
.sp-catalogue { background: var(--ink); padding: clamp(26px, 3.4vw, 40px) 0 clamp(70px, 9vw, 120px); }
.sp-filters { display: flex; flex-wrap: wrap; gap: 9px; margin: 0 0 clamp(24px, 3vw, 36px); }
.sp-chip {
  font-family: var(--font-caps); font-size: 11px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--text-dim); background: none;
  border: 1px solid var(--line); border-radius: 999px;
  padding: 11px 17px; min-height: 44px; cursor: pointer;
  transition: color .2s ease, border-color .2s ease, background .2s ease;
}
.sp-chip:hover { color: var(--text); border-color: rgba(207, 178, 230, .42); }
.sp-chip.is-on { color: #1E1033; background: var(--lav); border-color: var(--lav); }
.sp-chip:focus-visible { outline: 2px solid var(--lav); outline-offset: 3px; }

.sp-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: clamp(14px, 1.6vw, 22px); }
/* GRID, NOT FLEX, so the price aligns across a row.
 *
 * The old flex column gave .sp-blurb flex:1, which absorbed the slack and made
 * everything BELOW it line up -- buttons aligned on every row. But the price
 * sits ABOVE the variant selector in the markup, and only 13 of 36 cards have
 * one, so on those cards the price was pushed up by exactly the selector's
 * height. That is why prices missed on 6 of 17 rows while buttons never did.
 *
 * Three CSS attempts failed before this (margin-top:auto on the price,
 * min-height on the title, min-height on the blurb) because all three treated
 * it as a spacing problem. It is a structural one: the cards render different
 * child sets, so the fix is to give every card the SAME slots and reserve the
 * ones it does not fill.
 *
 * Rows, in markup order: shot, category, title, blurb, price, selector,
 * button, note. The blurb takes 1fr and absorbs the difference in copy length;
 * the selector row has a floor so a card without one still reserves it. */
.sp-card {
  display: grid;
  grid-template-rows: auto auto auto 1fr auto auto auto auto;
  background: var(--plum-2); border: 1px solid var(--plum-line); border-radius: 18px;
  padding: 0 clamp(16px, 1.5vw, 20px) clamp(18px, 1.8vw, 22px);
  transition: transform .3s ease, border-color .3s ease, box-shadow .3s ease;
}
/* .sp-card sets display:flex, which outranks the UA sheet's [hidden]{display:none}
   — without this the filters set hidden=true and every card stayed on screen. */
.sp-card[hidden] { display: none; }
/* Explicit row assignment, because auto-placement would put the BUTTON in the
   selector's row on the 23 cards that have no selector -- which is the bug
   this rule exists to prevent. */
.sp-card > .sp-shot  { grid-row: 1; }
.sp-card > .sp-cat   { grid-row: 2; }
.sp-card > h3        { grid-row: 3; }
.sp-card > .sp-blurb { grid-row: 4; align-self: start; }
/* PRICE BELOW THE SELECTOR, which is the opposite of the markup order.
   In the source the price comes first, so on the 13 cards with a selector it
   was pushed up by that selector's full 91px (65px of control plus 12/14px of
   margin, which counts toward the grid row). Reserving that slot on the other
   23 cards would align them at the cost of 91px of deliberate emptiness.
   Placing the price last instead means the bottom stack -- price, button, note
   -- is identical on every card, so the 1fr blurb row absorbs every difference
   above it and the prices line up with nothing reserved.
   Reading order is unchanged and still sensible: price, then the size picker
   that changes it. */
.sp-card > .sp-var,
.sp-card > .sp-flat  { grid-row: 5; }
.sp-card > .sp-price { grid-row: 6; margin: 14px 0 12px; }
.sp-card > .sp-act   { grid-row: 7; }
.sp-card > .sp-note  { grid-row: 8; }
/* shop.js injects a focusable Details button as a 9th child; give it a row
   rather than letting auto-placement invent one. */
.sp-card > .sp-more  { grid-row: 9; }
.sp-card:hover { transform: translateY(-4px); border-color: rgba(163, 149, 228, .42); box-shadow: 0 22px 50px rgba(11, 6, 26, .5); }
/* Negative side margins bleed the shot to the card edges — the plum in the
   photograph then meets the plum of the card with no visible seam. */
.sp-shot {
  margin: 0 calc(clamp(16px, 1.5vw, 20px) * -1) 4px;
  border-radius: 18px 18px 0 0; overflow: hidden; aspect-ratio: 1 / 1;
}
.sp-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.sp-cat {
  margin: 0 0 6px; font-family: var(--font-caps); font-size: 9.5px; font-weight: 800;
  letter-spacing: .2em; text-transform: uppercase; color: var(--violet);
}
.sp-card h3 { font-size: 19px; line-height: 1.2; margin: 0; }
.sp-blurb { margin: 7px 0 0; font-size: 13px; line-height: 1.5; color: var(--text-dim); }
.sp-price { font-family: var(--font-display); font-size: 26px; color: var(--gold); margin: 14px 0 12px; }
.sp-price span { font-family: var(--font-body); font-size: 12px; color: var(--text-dim); margin-left: 3px; }
.sp-act { align-self: stretch; justify-content: center; text-align: center; }
/* Reserves TWO lines. The note is the last element in the card, so any
   variation in its height pushes everything above it -- the button, the
   price -- out of line with its neighbours. 2.6em held one line, and the
   prescription notes wrap to two, which is what knocked the BioBox card out
   of alignment with the Rx cards beside it. */
.sp-note { margin: 8px 0 0; min-height: 3.3em; font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: rgba(242, 236, 242, .42); text-align: center; }
.sp-empty { text-align: center; color: var(--text-dim); padding: 40px 0; }

/* ---------- How it works ---------- */
.sp-fineprint { background: var(--ink-2); border-top: 1px solid var(--line); padding: clamp(56px, 7vw, 92px) 0; }
.sp-fineprint h2 { font-size: clamp(24px, 3vw, 36px); margin: 0 0 clamp(22px, 2.6vw, 32px); }
.sp-fineprint ol { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(18px, 2.4vw, 32px); }
.sp-fineprint li { font-size: 14.5px; line-height: 1.6; color: var(--text-dim); border-top: 1px solid var(--line); padding-top: 16px; }
.sp-fineprint li strong { display: block; font-family: var(--font-display); font-weight: 400; font-size: 19px; color: var(--text); margin-bottom: 6px; }
.sp-fineprint .fine { margin: clamp(26px, 3vw, 38px) 0 0; max-width: 760px; text-transform: none; letter-spacing: .01em; font-size: 13px; line-height: 1.7; }

/* ---------- Cart ---------- */
.sp-cartbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 58; display: flex; justify-content: center; padding: 0 0 16px; pointer-events: none; }
.sp-cartbar[hidden] { display: none; }
.sp-cartbar-open {
  pointer-events: auto; cursor: pointer;
  font-family: var(--font-caps); font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  background: var(--lav); color: #1E1033; border: none; border-radius: 999px;
  padding: 15px 26px; min-height: 48px;
  box-shadow: 0 14px 40px rgba(8, 4, 14, .55);
  display: inline-flex; align-items: center; gap: 10px;
}
.sp-cart-count { background: #1E1033; color: var(--lav); border-radius: 999px; padding: 2px 9px; font-size: 11px; }
.sp-cart-total { margin-left: 6px; }

.sp-cart {
  position: fixed; top: 0; right: 0; bottom: 0; width: min(420px, 100%); z-index: 62;
  background: var(--plum); border-left: 1px solid var(--plum-line);
  display: flex; flex-direction: column;
  box-shadow: -30px 0 80px rgba(2, 6, 14, .6);
}
.sp-cart[hidden] { display: none; }
.sp-cart header { display: flex; align-items: center; justify-content: space-between; padding: 22px 24px; border-bottom: 1px solid var(--plum-line); }
.sp-cart header h2 { font-size: 22px; margin: 0; }
.sp-cart-close { position: relative; width: 44px; height: 44px; flex: none; background: none; border: 1px solid rgba(163, 149, 228, .3); border-radius: 999px; cursor: pointer; }
.sp-cart-close::before, .sp-cart-close::after { content: ""; position: absolute; left: 50%; top: 50%; width: 15px; height: 2px; background: var(--text); border-radius: 2px; }
.sp-cart-close::before { transform: translate(-50%, -50%) rotate(45deg); }
.sp-cart-close::after  { transform: translate(-50%, -50%) rotate(-45deg); }
.sp-cart-lines { list-style: none; margin: 0; padding: 8px 24px; overflow-y: auto; flex: 1; }
.sp-cart-lines li { display: grid; grid-template-columns: 1fr auto; gap: 4px 12px; padding: 16px 0; border-bottom: 1px dashed rgba(163, 149, 228, .2); }
.sp-cart-lines b { font-family: var(--font-body); font-weight: 650; font-size: 14.5px; }
.sp-cart-lines .ln-price { font-family: var(--font-display); font-size: 17px; color: var(--gold); }
.sp-qty { display: flex; align-items: center; gap: 4px; }
.sp-qty button { width: 30px; height: 30px; border-radius: 8px; border: 1px solid rgba(163, 149, 228, .3); background: none; color: var(--text); font-size: 15px; cursor: pointer; line-height: 1; }
.sp-qty button:hover { border-color: var(--violet); color: var(--violet); }
.sp-qty span { min-width: 22px; text-align: center; font-size: 14px; }
.sp-cart-empty { padding: 30px 24px; color: var(--text-dim); font-size: 14.5px; }
.sp-cart footer { padding: 20px 24px 24px; border-top: 1px solid var(--plum-line); }
.sp-cart-sum { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 16px; }
.sp-cart-sum span { font-size: 11px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase; color: var(--text-dim); }
.sp-cart-sum b { font-family: var(--font-display); font-weight: 400; font-size: 30px; color: var(--gold); }
.sp-checkout { width: 100%; justify-content: center; }
.sp-cart footer .fine { display: block; margin: 12px 0 0; text-align: center; font-size: 11px; text-transform: none; letter-spacing: .02em; }

.sp-scrim { position: fixed; inset: 0; z-index: 60; background: rgba(2, 8, 10, .6); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px); }
.sp-scrim[hidden] { display: none; }

.sp-done { position: fixed; inset: 0; z-index: 70; display: grid; place-items: center; padding: 24px; background: rgba(2, 8, 10, .82); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px); }
.sp-done[hidden] { display: none; }
.sp-done-card { background: var(--plum-2); border: 1px solid rgba(163, 149, 228, .3); border-radius: 20px; padding: clamp(28px, 4vw, 44px); max-width: 460px; text-align: center; }
.sp-done-card .eyebrow { color: var(--violet); }
.sp-done-card h2 { font-size: clamp(26px, 3.4vw, 38px); margin: 8px 0 12px; }
.sp-done-card p { color: var(--text-dim); font-size: 14.5px; line-height: 1.6; margin: 0 0 22px; }

/* ---------- Responsive ---------- */
@media (max-width: 1020px) {
  .sp-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .sp-fineprint ol { grid-template-columns: 1fr; }
}
@media (max-width: 760px) {
  .sp-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .sp-card h3 { font-size: 17px; }
  .sp-blurb { font-size: 12.5px; }
  .sp-price { font-size: 23px; }
}
@media (max-width: 520px) {
  /* Stay two-up rather than dropping to one: a single square shot per row
     puts one product on a whole phone screen, which is a long scroll for a
     24-item catalogue. Blurb drops out to keep the tiles compact. */
  .sp-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
  .sp-card { padding: 0 12px 14px; border-radius: 15px; }
  .sp-shot { margin: 0 -12px 4px; border-radius: 15px 15px 0 0; }
  .sp-card h3 { font-size: 15.5px; }
  .sp-blurb { display: none; }
  .sp-cat { font-size: 9px; }
  /* auto top margin (not margin-top, which the shorthand would reset) pins the
     price+button group to the card bottom so actions line up across a row. */
  .sp-price { font-size: 20px; margin: auto 0 10px; }
  .sp-price span { font-size: 11px; }
  .sp-act { padding-left: 8px; padding-right: 8px; font-size: 11px; letter-spacing: .08em; }
  .sp-note { font-size: 9px; letter-spacing: .06em; min-height: 2.8em; }
  .sp-legend { font-size: 12px; }
  .sp-key-rx { margin-left: 0; }
  .sp-chip { padding: 11px 13px; font-size: 10.5px; }
}

/* ==========================================================================
   Product detail drawer
   --------------------------------------------------------------------------
   Slides in from the right on desktop, rises as a sheet on phones. The panel
   is filled by shop.js on open rather than shipped 24 times over.
   ========================================================================== */

/* z-index on this page, so the next panel added does not repeat the bug this
   one shipped with:
       58  .sp-cartbar     the persistent bottom bar
       60  .sp-scrim       the dimming + blurring backdrop
       62  .sp-cart        cart panel, above the scrim
       64  .pdp            product drawer, above the scrim
       70  .sp-done        checkout confirmation, above everything
   The drawer was 60 — level with the scrim. The scrim is appended to <body>
   after the drawer, and at equal z-index later-in-DOM paints on top, so the
   scrim's blur(3px) and 60% black were being applied OVER the drawer. That is
   what made the copy look soft. */
.pdp {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 64;
  width: min(520px, 100vw);
  background: var(--ink-2);
  border-left: 1px solid rgba(207, 178, 230, .22);
  box-shadow: -30px 0 80px rgba(8, 4, 14, .6);
  transform: translateX(100%);
  transition: transform .34s cubic-bezier(.4, 0, .2, 1);
  will-change: transform;
  display: flex; flex-direction: column;
}
/* transform:none rather than translateX(0) — a zero translate keeps the element
   on its own composited layer, where subpixel positioning can soften text. */
.pdp.is-open { transform: none; will-change: auto; }
.pdp[hidden] { display: none; }

.pdp-close {
  position: absolute; top: 14px; right: 14px; z-index: 2;
  width: 44px; height: 44px; border-radius: 50%;
  border: 1px solid rgba(207, 178, 230, .28);
  background: rgba(18, 12, 30, .7); color: var(--text);
  font-size: 24px; line-height: 1; cursor: pointer;
}
.pdp-close:hover { border-color: var(--lav); color: var(--lav); }

.pdp-scroll { overflow-y: auto; -webkit-overflow-scrolling: touch; padding: clamp(22px, 4vw, 34px); }

.pdp-head { display: grid; grid-template-columns: 96px 1fr; gap: 18px; align-items: start; }
.pdp-shot {
  width: 96px; height: 96px; object-fit: cover; border-radius: 14px;
  border: 1px solid rgba(207, 178, 230, .2); background: var(--ink-3);
}
.pdp-cat {
  font-family: var(--font-caps); font-size: 10.5px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--gold); margin: 0 0 6px;
}
.pdp h2 { font-family: var(--font-display); font-weight: 400; font-size: clamp(1.4rem, 3.4vw, 1.75rem); line-height: 1.15; margin: 0; color: var(--porcelain); }
.pdp-line { margin: 8px 0 0; font-size: 14.5px; line-height: 1.55; color: var(--text-dim); }
.pdp-price { font-family: var(--font-display); font-size: 27px; color: var(--gold); margin: 12px 0 0; }
.pdp-price span { font-family: var(--font-body); font-size: 13px; color: var(--text-dim); margin-left: 3px; }

/* Prescription items say so before anything else — it changes what the page
   is even offering you. */
.pdp-rx {
  margin: 20px 0 0; padding: 14px 16px; border-radius: 12px;
  background: rgba(226, 169, 78, .09);
  border: 1px solid rgba(226, 169, 78, .34);
  font-size: 13.5px; line-height: 1.6; color: var(--text);
}
.pdp-rx b { color: var(--gold); }

.pdp-fields { margin: 22px 0 0; }
.pdp-row, .pdp-pairs, .pdp-sources { padding: 15px 0; border-top: 1px solid rgba(207, 178, 230, .14); }
.pdp-fields dt {
  font-family: var(--font-caps); font-size: 10px; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase; color: var(--lav);
  margin: 0 0 7px;
}
.pdp-fields dd { margin: 0; font-size: 14.5px; line-height: 1.65; color: var(--text); }

.pdp-pairs dd { display: flex; flex-wrap: wrap; gap: 7px; }
.pdp-pairs dd span {
  font-size: 12.5px; color: var(--text-dim);
  border: 1px solid rgba(207, 178, 230, .24); border-radius: 999px; padding: 5px 11px;
}
.pdp-sources ul { list-style: none; margin: 0; padding: 0; }
.pdp-sources li { font-size: 12.5px; line-height: 1.55; margin-bottom: 7px; color: var(--text-dim); }
.pdp-sources a { color: var(--lav); word-break: break-word; }
.pdp-sources i { font-style: normal; opacity: .75; }

.pdp-foot {
  margin: 24px 0 0; padding-top: 20px;
  border-top: 1px solid rgba(207, 178, 230, .18);
  display: flex; flex-direction: column; gap: 10px; align-items: flex-start;
}
.pdp-cta { min-height: 48px; }
.pdp-legal { margin: 18px 0 0; font-size: 11.5px; line-height: 1.6; color: rgba(242, 236, 242, .55); }

/* The card-level affordance shop.js injects. */
/* 44px in BOTH directions — a tall thin target is still a miss on a phone. */
.sp-more {
  margin-top: 10px; align-self: flex-start;
  background: none; border: 0; padding: 8px 14px 8px 0;
  min-width: 88px; text-align: left;
  font-family: var(--font-body); font-size: 12.5px; font-weight: 600;
  color: var(--lav); cursor: pointer;
  border-bottom: 1px solid rgba(207, 178, 230, .35);
  min-height: 44px;
}
.sp-more:hover { color: #E1C9F2; border-bottom-color: #E1C9F2; }
.sp-card { cursor: pointer; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

@media (max-width: 620px) {
  .pdp {
    top: auto; left: 0; width: 100vw; height: 92vh;
    border-left: 0; border-top: 1px solid rgba(207, 178, 230, .22);
    border-radius: 20px 20px 0 0;
    transform: translateY(100%);
  }
  .pdp.is-open { transform: none; }
  .pdp-head { grid-template-columns: 72px 1fr; gap: 14px; }
  .pdp-shot { width: 72px; height: 72px; }
  .pdp-cta { width: 100%; justify-content: center; }
}

@media (prefers-reduced-motion: reduce) {
  .pdp { transition: none; }
}

/* ==========================================================================
   Light room — 2026-08-25
   --------------------------------------------------------------------------
   The catalogue was one unbroken plum field with white text on it, which is
   both monotonous and inconsistent: the home page's apothecary section is a
   LIGHT room, and it hands straight over to this page. Walking from a light
   room into a dark one and calling it the same shop never made sense.

   So the page now runs dark masthead -> light catalogue -> dark fine print,
   the same three-zone shape the Journal uses. Gold carries value (prices, the
   Rx key, the flagship), violet carries language on light, and white is the
   surface rather than the ink.
   ========================================================================== */

/* The picker STAYS dark and the grid goes light, so the page alternates:
   dark masthead -> dark picker -> light catalogue -> dark fine print. Making
   the whole thing light just swapped one monotony for another; the point is
   rhythm, not brightness. The picker belongs with the chrome — it is the
   control surface — and the catalogue is the thing you read. */
.sp-catalogue { background: var(--porcelain); border-top: 1px solid rgba(226, 169, 78, .3); }
.sp-catalogue h2 { color: var(--ink-light); }
.sp-empty { color: var(--dim-light); }

/* The goal chips live in the DARK picker and keep their dark treatment.
   The category chips live in the LIGHT catalogue and need the opposite — they
   were left with light-on-dark styling and all but disappeared on porcelain.
   Scope by section, not by class, or one of the two rows always loses. */
.sp-picker .pchip[aria-pressed="true"] {
  color: #2A1D06; background: var(--gold); border-color: var(--gold);
}

.sp-catalogue .sp-browse { color: var(--dim-light); }
.sp-catalogue .sp-chip {
  color: var(--violet-deep);
  background: #fff;
  border-color: rgba(101, 64, 147, .34);
}
.sp-catalogue .sp-chip:hover {
  color: var(--gold-deep); border-color: var(--gold-deep);
}
.sp-catalogue .sp-chip.is-on {
  color: #2A1D06; background: var(--gold); border-color: var(--gold);
}
.sp-catalogue .sp-chip:focus-visible { outline: 2px solid var(--violet-deep); outline-offset: 3px; }

/* Cards: white, with the dark product shot reading as a photographic tile. */
.sp-card {
  background: #fff;
  border: 1px solid rgba(26, 16, 32, .10);
  box-shadow: 0 12px 30px rgba(26, 16, 32, .07);
}
.sp-card:hover {
  border-color: rgba(168, 120, 31, .5);
  box-shadow: 0 22px 48px rgba(26, 16, 32, .14);
}
.sp-card h3 { color: var(--ink-light); }
.sp-blurb { color: var(--dim-light); }
.sp-cat { color: var(--gold-deep); }
.sp-price { color: var(--gold-deep); }
.sp-price span { color: var(--dim-light); }
.sp-note { color: rgba(26, 16, 32, .5); }
.sp-more { color: var(--violet-deep); border-bottom-color: rgba(101, 64, 147, .4); }
.sp-more:hover { color: var(--gold-deep); border-bottom-color: var(--gold-deep); }
.sp-shot { background: var(--ink-2); }

/* The buy action needs to read on white now. */
.sp-card .btn-drip { background: var(--ink-light); color: var(--gold); }
.sp-card .btn-drip:hover { background: var(--ink); color: #EDBB69; }
.sp-empty { color: var(--dim-light); }

/* The masthead keeps its dark band, and the key chips sit on it. */
.sp-head { border-bottom: 1px solid rgba(226, 169, 78, .3); }

/* What each cart line actually sells — a credit, or (BioBox only) a kit. */
.sp-line-kind {
  display: block; font-family: var(--font-caps); font-size: 9.5px;
  letter-spacing: .16em; text-transform: uppercase; color: var(--gold);
  margin-top: 3px;
}

/* ---- Variant picker on a product card ----
   Their store sells most items in packs and the GLP-1s by escalating monthly
   dose, so a card with one price was telling only part of the truth. The
   chosen option's price is what the cart charges — see shop.js. */
/* 14px of clear air before the action. These were touching, which put a
   44px select flush against a 44px button — the two easiest things on the
   card to confuse for one another. */
.sp-var { display: block; margin: 12px 0 14px; }
.sp-var > span {
  display: block; margin-bottom: 5px;
  font-size: 10px; font-weight: 800; letter-spacing: .16em; text-transform: uppercase;
  color: var(--dim-light);
}
.sp-variant {
  width: 100%; min-height: 44px; padding: 9px 34px 9px 12px;
  font: inherit; font-size: 13px; color: var(--ink-light);
  background: #fff url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%235B3E96' stroke-width='1.6' fill='none' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat right 12px center/12px 8px;
  border: 1px solid rgba(91, 62, 150, .28); border-radius: 10px;
  -webkit-appearance: none; appearance: none; cursor: pointer;
}
.sp-variant:focus-visible { outline: 2px solid var(--violet-deep); outline-offset: 2px; }

/* Consult products cannot be added to a cart, so their schedule is a price
   list rather than a control — a select you cannot act on is a lie about what
   the card does. Collapsed because the GLP-1s carry seven rows each. */
/* Semaglutide is one price at every dose, so it gets a flat statement instead
   of a seven-row schedule listing $250 seven times (Justin, 2026-08-28). */
/* Who is buying — asked in the cart, once, at the point of checkout. */
.sp-who { display: grid; gap: 8px; margin: 4px 0 12px; }
.sp-who label { display: grid; gap: 4px; }
.sp-who span {
  font-family: var(--font-caps); font-size: 10px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--text-dim);
}
.sp-who input {
  font-family: var(--font-body); font-size: 15px; color: var(--text);
  background: rgba(242, 236, 242, .05); border: 1px solid rgba(163, 149, 228, .22);
  border-radius: 10px; padding: 10px 12px; width: 100%; min-height: 44px;
}
.sp-who input:focus-visible { outline: 2px solid var(--lav); outline-offset: 2px; }
.sp-checkout-err {
  margin: 8px 0 0; font-size: 13px; line-height: 1.5; color: #FFC9C9;
}
.sp-checkout-err[hidden] { display: none; }

.sp-flat {
  margin: 10px 0 14px; padding-top: 10px;
  border-top: 1px solid rgba(91, 62, 150, .14);
  font-size: 13px; line-height: 1.5; color: var(--dim-light);
}

.sp-tiers { margin: 10px 0 14px; border-top: 1px solid rgba(91, 62, 150, .14); padding-top: 9px; }
.sp-tiers summary {
  cursor: pointer; list-style: none; min-height: 44px; display: flex; align-items: center; gap: 6px;
  font-size: 10px; font-weight: 800; letter-spacing: .16em; text-transform: uppercase;
  color: var(--violet-deep);
}
.sp-tiers summary::-webkit-details-marker { display: none; }
.sp-tiers summary::after { content: "+"; margin-left: auto; font-size: 15px; color: var(--gold-deep); }
.sp-tiers[open] summary::after { content: "–"; }
.sp-tiers summary span { color: var(--dim-light); letter-spacing: .06em; }
.sp-tiers summary:focus-visible { outline: 2px solid var(--violet-deep); outline-offset: 3px; border-radius: 4px; }
.sp-tiers ul { margin: 4px 0 2px; padding: 0; list-style: none; }
.sp-tiers li {
  display: flex; justify-content: space-between; gap: 12px; padding: 5px 0;
  font-size: 12.5px; color: var(--dim-light); border-bottom: 1px dotted rgba(91, 62, 150, .16);
}
.sp-tiers li:last-child { border-bottom: 0; }
.sp-tiers li b { font-family: var(--font-display); font-weight: 400; color: var(--gold-deep); }

@media (max-width: 560px) {
  /* The catalogue grid is 2-up on phones, which leaves a select about 134px
     wide. Most option text fits; BioBox's panel names ("Men's Vitality
     Essential Panel — $260") need 216px and were being clipped, so that one
     card takes the full row rather than having its wording cut down. */
  .sp-card[data-slug="biobox"] { grid-column: 1 / -1; }
  .sp-variant { font-size: 12.5px; padding-right: 30px; }
}

/* ---- Detail panel, light lavender skin ----
   Every other product opens in this instead of the dark panel, so scrolling
   the catalogue does not read as one unbroken dark surface. Same layout, same
   type; only the colour roles flip — ink on lavender-white, gold still money,
   deep purple carrying the labels and links. */
.pdp.pdp-light {
  background: linear-gradient(180deg, #F4F0FC 0%, #EDE6F9 100%);
  border-left-color: rgba(91, 62, 150, .22);
  box-shadow: -30px 0 80px rgba(26, 16, 32, .28);
  color: var(--ink-light);
}
.pdp-light .pdp-close {
  background: rgba(255, 255, 255, .8); color: var(--violet-deep);
  border-color: rgba(91, 62, 150, .3);
}
.pdp-light .pdp-close:hover { border-color: var(--violet-deep); color: var(--ink-light); }
.pdp-light .pdp-shot { background: #fff; border-color: rgba(91, 62, 150, .16); }
.pdp-light .pdp-cat { color: var(--violet-deep); }
.pdp-light h2 { color: var(--ink-light); }
.pdp-light .pdp-line { color: var(--dim-light); }
.pdp-light .pdp-price { color: var(--gold-deep); }
.pdp-light .pdp-price span { color: var(--dim-light); }
.pdp-light .pdp-rx {
  background: rgba(226, 169, 78, .14);
  border-color: rgba(168, 120, 31, .4); color: var(--ink-light);
}
.pdp-light .pdp-rx b { color: var(--gold-deep); }
.pdp-light .pdp-row,
.pdp-light .pdp-pairs,
.pdp-light .pdp-sources { border-top-color: rgba(91, 62, 150, .16); }
.pdp-light .pdp-fields dt { color: var(--violet-deep); }
.pdp-light .pdp-fields dd { color: var(--ink-light); }
.pdp-light .pdp-pairs dd span {
  background: rgba(198, 179, 247, .22); color: var(--lav-deep);
  border-color: rgba(91, 62, 150, .24);
}
.pdp-light .pdp-sources li { color: var(--dim-light); }
.pdp-light .pdp-sources a { color: var(--violet-deep); }
.pdp-light .pdp-foot { border-top-color: rgba(91, 62, 150, .16); }
.pdp-light .pdp-legal { color: rgba(26, 16, 32, .62); }
.pdp-light .sp-var > span { color: var(--dim-light); }
.pdp-light .fine { color: var(--dim-light); }

/* Cart totals — subtotal / delivery / tax, mirroring what their checkout
   itemises today. Delivery hides itself when nothing in the cart ships. */
.sp-cart-totals { margin: 0 0 4px; padding: 0 0 10px; border-bottom: 1px solid rgba(207, 178, 230, .14); }
.sp-cart-totals > div { display: flex; justify-content: space-between; gap: 12px; padding: 4px 0; }
.sp-cart-totals > div[hidden] { display: none; }
.sp-cart-totals dt { font-size: 13px; color: var(--text-dim); }
.sp-cart-totals dd { margin: 0; font-size: 13px; color: var(--text); }
/* Pair every display: rule with a [hidden] rule — a bare display:block
   outranks the UA sheet's [hidden]{display:none}, which is how this page once
   shipped 24 "hidden" cards that were all still on screen. */
.sp-deliv { display: block; margin: 0 0 12px; }
.sp-deliv[hidden] { display: none; }
.sp-deliv > span {
  display: block; margin-bottom: 5px;
  font-size: 10px; font-weight: 800; letter-spacing: .16em; text-transform: uppercase;
  color: var(--text-dim);
}
.sp-deliv-sel {
  width: 100%; min-height: 44px; padding: 9px 34px 9px 12px;
  font: inherit; font-size: 12.5px; color: var(--text);
  background: rgba(207, 178, 230, .07) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23CFB2E6' stroke-width='1.6' fill='none' stroke-linecap='round'/%3E%3C/svg%3E") no-repeat right 12px center/12px 8px;
  border: 1px solid rgba(207, 178, 230, .26); border-radius: 10px;
  -webkit-appearance: none; appearance: none; cursor: pointer;
}
.sp-deliv-sel:focus-visible { outline: 2px solid var(--lav); outline-offset: 2px; }

/* Gift-card path — deliberately separate from the cart: the portal is the
   client's own Factor4 store, so money and balances live in their system. */
.sp-gift {
  margin: 14px 0 0; padding: 12px 16px; font-size: 14px; line-height: 1.6;
  color: var(--text); background: rgba(226, 169, 78, .10);
  border: 1px solid rgba(226, 169, 78, .3); border-radius: 12px;
}
.sp-gift a { color: var(--gold); font-weight: 700; }
