/*
 * CORE LABS v2 brand theme.
 *
 * Loaded ONLY when the v2 preview is on (inc/theme-v2.php), appended after
 * woocommerce.css rather than editing it. Turning the preview off is a true
 * revert.
 *
 * SPECIFICITY IS THE WHOLE GAME HERE. woocommerce.css is 21,000+ lines and its
 * rules are written as e.g.
 *     html body ul.products li.product.product { background: var(--paper) !important }
 * which is (0,3,4). A sane-looking override like
 *     html body.cl-v2 ul.products li.product        -> (0,3,3)
 * LOSES, because it has one fewer type selector. Measured in the browser, not
 * assumed. So every rule below is prefixed `html body.cl-v2` and repeats the
 * trailing class where the theme does, putting it at (0,4,4)+.
 *
 * Noah's brief: premium, minimal, clinical, bright. White + black + purple.
 */

body.cl-v2 {
  /* purple */
  --cl-purple: #6D28D9;
  --cl-purple-bright: #8B5CF6;
  --cl-lavender: #C4B5FD;
  --cl-lavender-pale: #F5F3FF;
  --cl-purple-deep: #4C1D95;
  /* neutrals */
  --cl-ink: #111118;
  --cl-charcoal: #27272A;
  --cl-gray: #71717A;
  --cl-gray-light: #E4E4E7;
  --cl-offwhite: #FAFAFA;
  --cl-white: #FFFFFF;
  --cl-grad: linear-gradient(135deg, #4C1D95 0%, #6D28D9 45%, #A78BFA 100%);
}

/* ===========================================================================
 * THE REMAP.
 *
 * The theme is fully tokenised — ~40 custom properties drive all 21,000 lines.
 * Overriding rules one at a time was the wrong approach: 144 rules paint a dark
 * background and each needed its own winning selector. Re-pointing the TOKENS
 * flips the whole site at once, and it is a true revert when the flag is off.
 *
 * Mapping, dark -> v2:
 *   paper / surfaces   near-black glass      -> white and #FAFAFA
 *   ink-*              dark greys (surfaces) -> light greys
 *   ink-strong/soft    white / pale on dark  -> near-black / grey on white
 *   mist-*             pale text on dark     -> darker, so it stays readable
 *   accent/ui/plum     muted purple          -> Noah's #6D28D9 family
 * ========================================================================= */
html body.cl-v2 {
  /* surfaces */
  --paper:          #FFFFFF;
  --paper-solid:    #FFFFFF;
  --paper-2:        #FAFAFA;
  --paper-line:     #E4E4E7;
  --cl-surface:     #FFFFFF;
  --cl-surface-card:#FFFFFF;
  --cl-edge:        #E4E4E7;
  --border-purple:  rgba(109, 40, 217, .18);
  --glow-purple:    rgba(167, 139, 250, .18);
  --deep-purple:    #F5F3FF;

  /* these were dark SURFACES in the old theme, so they go light */
  --ink-950: #FFFFFF;
  --ink-900: #FFFFFF;
  --ink-800: #FAFAFA;
  --ink-700: #F4F4F5;
  --ink-600: #EEEEF0;
  --ink-500: #E4E4E7;

  /* text */
  --ink-strong: #111118;   /* was white on dark */
  --ink-soft:   #52525B;
  --mist-50:    #27272A;
  --mist-100:   #3F3F46;
  --mist-300:   #52525B;
  --mist-400:   #71717A;
  --mist-500:   #71717A;

  /* purple */
  --accent-300: #C4B5FD;
  --accent-400: #8B5CF6;
  --accent-500: #6D28D9;
  --accent-600: #5B21B6;
  --accent-700: #4C1D95;
  --ui-400: #8B5CF6;
  --ui-500: #6D28D9;
  --ui-600: #5B21B6;
  --ui-ring: #8B5CF6;
  --plum: #6D28D9;
  --plum-tint: rgba(109, 40, 217, .12);
}

/* The page itself and anything painting a hard dark colour rather than a token. */
html body.cl-v2,
html body.cl-v2 .cl-bg,
html body.cl-v2 .cl-site-bg { background: #FFFFFF !important; color: #111118 !important; }

/* Product images were shot on a dark backdrop; on white they need the new
   white-background vials. Until those are swapped in on the products
   themselves, keep them from sitting in a dark box. */
html body.cl-v2 ul.products li.product.product img,
html body.cl-v2 .woocommerce-product-gallery img { background: transparent !important; }

/* ======================================================================
 * CORE10 pop-up, v2 (Noah, 2026-10-04: "make the pop-ups look like this")
 *
 * Split panel: copy left, vial right, on near-white. Two steps — claim,
 * then email. Mobile stacks and drops the vial, because at 390px a product
 * shot costs the whole fold and the offer is what has to be readable.
 * ====================================================================== */
html body.cl-v2 .cl-wb__scrim { background: rgba(17,17,24,.45) !important; }

html body.cl-v2 .cl-wb__panel {
  background: #F5F8FF !important;
  border: 1px solid #E5E1F2 !important;
  border-radius: 20px !important;
  box-shadow: 0 40px 90px -40px rgba(17,17,24,.45) !important;
  color: #111118 !important;
  max-width: 940px !important;
  padding: 34px 26px !important;
  overflow: hidden !important;
  position: relative !important;
}
html body.cl-v2 .cl-wb__x {
  background: #fff !important;
  border: 1px solid #E5E1F2 !important;
  color: #27272A !important;
  border-radius: 999px !important;
  width: 40px !important; height: 40px !important;
}
html body.cl-v2 .cl-wb__badge {
  background: transparent !important;
  color: #6D28D9 !important;
  font-weight: 600 !important;
  letter-spacing: .16em !important;
  font-size: 12.5px !important;
  padding: 0 !important;
}
html body.cl-v2 .cl-wb__title {
  color: #111118 !important;
  font-weight: 800 !important;
  font-size: clamp(26px, 6.4vw, 40px) !important;
  line-height: 1.08 !important;
  letter-spacing: -.02em !important;
}
html body.cl-v2 .cl-wb__sub { color: #52525B !important; font-size: 16px !important; }

html body.cl-v2 .cl-wb__yes {
  background: linear-gradient(135deg,#4C1D95 0%,#6D28D9 45%,#A78BFA 100%) !important;
  color: #fff !important; border: 0 !important;
  border-radius: 999px !important;
  font-weight: 700 !important; font-size: 16px !important;
  padding: 15px 30px !important;
}
html body.cl-v2 .cl-wb__no,
html body.cl-v2 .cl-wb__back {
  background: none !important; border: 0 !important;
  color: #52525B !important; text-decoration: underline !important;
  font-weight: 500 !important; font-size: 14px !important; cursor: pointer !important;
}
html body.cl-v2 .cl-wb__back { text-decoration: none !important; font-weight: 700 !important; }
html body.cl-v2 .cl-wb__input {
  background: #fff !important; color: #111118 !important;
  border: 1px solid #E5E1F2 !important; border-radius: 12px !important;
  font-size: 16px !important;   /* 16px stops iOS zooming the page on focus */
  padding: 14px 16px !important;
}
html body.cl-v2 .cl-wb__input::placeholder { color: #A1A1AA !important; }
html body.cl-v2 .cl-wb__fine { color: #71717A !important; font-size: 12.5px !important; }
html body.cl-v2 .cl-wb__err  { color: #B91C1C !important; }

/* proof strip */
html body.cl-v2 .cl-wb__proof {
  list-style: none !important; display: flex !important; gap: 30px !important;
  margin: 24px 0 0 !important; padding: 20px 0 0 !important;
  border-top: 1px solid #D4D4D8 !important;
}
html body.cl-v2 .cl-wb__proof li { display: grid !important; gap: 2px !important; }
html body.cl-v2 .cl-wb__proof b { color: #6D28D9 !important; font-weight: 800 !important; font-size: 19px !important; }
html body.cl-v2 .cl-wb__proof span { color: #71717A !important; font-size: 12.5px !important; }

/* the vial, right-hand half. Desktop only. */
@media (min-width: 820px) {
  html body.cl-v2 .cl-wb__panel { padding: 44px 440px 44px 46px !important; }
  html body.cl-v2 .cl-wb__panel::after {
    content: "" !important; position: absolute !important;
    right: 0 !important; top: 0 !important; bottom: 0 !important; width: 420px !important;
    background: #fff url("promo-vial.webp") center/contain no-repeat !important;
    border-left: 1px solid #D4D4D8 !important;
  }
}

/* ===========================================================================
 * Components that hard-code a colour instead of reading a token, so the remap
 * above cannot reach them. Measured on the live preview, not guessed:
 *   header .95 black · ticker · pagenav · footer cols · mobile scrim
 *   chips / onsale / save tags were on the OLD purple (#7B3FB2, #6C34A0)
 * .cl-footer__col was also dark text on a dark panel — invisible either way.
 * ========================================================================= */
html body.cl-v2 header.cl-header {
  background: rgba(255,255,255,.90) !important;
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid #D4D4D8 !important;
}
html body.cl-v2 header.cl-header a,
html body.cl-v2 header.cl-header button { color: #27272A !important; }
html body.cl-v2 header.cl-header a:hover { color: #6D28D9 !important; }

html body.cl-v2 div.cl-ticker {
  background: #F5F3FF !important;
  color: #4C1D95 !important;
  border-bottom: 1px solid #D4D4D8 !important;
}
html body.cl-v2 div.cl-ticker a,
html body.cl-v2 div.cl-ticker span { color: #4C1D95 !important; }

html body.cl-v2 nav.cl-pagenav,
html body.cl-v2 a.cl-pagenav__home {
  background: rgba(255,255,255,.95) !important;
  color: #27272A !important;
  border-color: #E5E1F2 !important;
}
html body.cl-v2 nav.cl-pagenav a { color: #27272A !important; }
html body.cl-v2 nav.cl-pagenav a[aria-current],
html body.cl-v2 nav.cl-pagenav a:hover { color: #6D28D9 !important; }

html body.cl-v2 div.cl-footer__col,
html body.cl-v2 .cl-footer {
  background: #FAFAFA !important;
  color: #52525B !important;
  border-color: #E5E1F2 !important;
}
html body.cl-v2 .cl-footer a,
html body.cl-v2 div.cl-footer__col a { color: #27272A !important; }
html body.cl-v2 .cl-footer a:hover { color: #6D28D9 !important; }
html body.cl-v2 .cl-footer h3,
html body.cl-v2 div.cl-footer__col strong { color: #111118 !important; }

html body.cl-v2 div.cl-mobile__overlay { background: rgba(17,17,24,.45) !important; }
html body.cl-v2 div.cl-mobile__panel {
  background: #FFFFFF !important; color: #111118 !important;
  border-color: #E5E1F2 !important;
}
html body.cl-v2 div.cl-mobile__panel a { color: #27272A !important; }

/* accents: move the old purples onto Noah's */
html body.cl-v2 a.cl-chip,
html body.cl-v2 span.onsale,
html body.cl-v2 span.cl-feat__tag--save {
  background: linear-gradient(135deg,#4C1D95 0%,#6D28D9 45%,#A78BFA 100%) !important;
  color: #fff !important; border: 0 !important;
}
html body.cl-v2 a.cl-chip:hover { filter: brightness(1.06); }

/* search field on white */
html body.cl-v2 .cl-search,
html body.cl-v2 .cl-search input {
  background: #FFFFFF !important; color: #111118 !important;
  border-color: #E5E1F2 !important;
}
html body.cl-v2 .cl-search input::placeholder { color: #A1A1AA !important; }

/* strike-through "was" price needs to stay legible on white */
html body.cl-v2 del, html body.cl-v2 del .amount { color: #A1A1AA !important; }
html body.cl-v2 ins, html body.cl-v2 ins .amount { color: #111118 !important; text-decoration: none !important; }

/* ------------------------------------------------------------------
 * HOMEPAGE SECTIONS
 *
 * Measured on the live page under ?clv2=1, 2026-10-03. These six paint
 * their own dark colour literally rather than through a token, so the
 * token remap above cannot reach them and they stayed near-black on a
 * white page.
 *
 * Specificity: the theme writes `html body:not(.cl-x) .cl-bundles`
 * = (0,2,2) !important. `html body.cl-v2:not(.cl-x)` is (0,3,2), so
 * these win on specificity, not on source order — which matters because
 * woocommerce.css is 21k lines and later rules in it would otherwise
 * outrank anything appended here (see the prove-it note in memory).
 * ------------------------------------------------------------------ */

/* hero wash: the dark radial becomes the spec's faint violet bloom */
html body.cl-v2:not(.cl-x) section.cl-hero2 {
  background-image: radial-gradient(circle at 68% 38%,
      rgba(139, 92, 246, .10) 0%,
      rgba(196, 181, 253, .06) 38%,
      rgba(255, 255, 255, 0) 70%) !important;
}

html body.cl-v2:not(.cl-x) section.cl-bundles {
  background: #FAFAFA !important;
  border-color: #E5E1F2 !important;
}
html body.cl-v2:not(.cl-x) a.cl-bundle__media,
html body.cl-v2:not(.cl-x) .cl-bundle__media {
  background: #FFFFFF !important;
  border: 1px solid #E5E1F2 !important;
}

/* the four trust pillars: translucent dark card -> white card */
html body.cl-v2:not(.cl-x) div.cl-pillar,
html body.cl-v2:not(.cl-x) .cl-pillar {
  background: #FFFFFF !important;
  border-color: #E5E1F2 !important;
  color: #27272A !important;
}
html body.cl-v2:not(.cl-x) .cl-pillar h3 { color: #111118 !important; }
html body.cl-v2:not(.cl-x) .cl-pillar p  { color: #52525B !important; }

/* carousel arrows: solid purple on white reads better than a dark disc */
html body.cl-v2:not(.cl-x) button.cl-picks__arrow,
html body.cl-v2:not(.cl-x) .cl-picks__arrow {
  background: #FFFFFF !important;
  border: 2px solid #6D28D9 !important;
  color: #6D28D9 !important;
}
html body.cl-v2:not(.cl-x) .cl-picks__arrow:hover {
  background: #6D28D9 !important;
  border-color: #6D28D9 !important;
  color: #FFFFFF !important;
}
html body.cl-v2:not(.cl-x) .cl-picks__arrow:active {
  background: #4C1D95 !important;
  border-color: #4C1D95 !important;
  color: #FFFFFF !important;
}

/* the name pill under each floating hero vial */
html body.cl-v2:not(.cl-x) span.cl-vial__pill,
html body.cl-v2:not(.cl-x) .cl-vial__pill {
  background: #FFFFFF !important;
  border: 1px solid #E5E1F2 !important;
  color: #111118 !important;
  box-shadow: 0 2px 10px rgba(17, 17, 24, .08) !important;
}
html body.cl-v2:not(.cl-x) .cl-vial:hover .cl-vial__pill {
  background: #F5F3FF !important;
  border-color: #C4B5FD !important;
}

/* "scroll for more" cue */
html body.cl-v2:not(.cl-x) button.cl-scrollcue,
html body.cl-v2:not(.cl-x) .cl-scrollcue {
  background: #FFFFFF !important;
  border: 1px solid #E5E1F2 !important;
  color: #27272A !important;
  box-shadow: 0 4px 16px rgba(17, 17, 24, .10) !important;
}
html body.cl-v2:not(.cl-x) .cl-scrollcue:hover { background: #F5F3FF !important; border-color: #C4B5FD !important; }
html body.cl-v2:not(.cl-x) .cl-scrollcue__arrow,
html body.cl-v2:not(.cl-x) .cl-scrollcue__text { color: #6D28D9 !important; }

/* ------------------------------------------------------------------
 * HERO VIGNETTE
 *
 * .cl-hero2::after was a near-black vignette (rgba(8,7,11,.52)) whose
 * whole job was to make the old dark vials pop. On a white page it read
 * as a grey slab behind the hero — and nothing in the token remap could
 * reach it, because it is a pseudo-element painting literal colours. It
 * is also redeclared inside @media (max-width:767px), so the mobile hero
 * needs its own override or the phone keeps the grey slab.
 *
 * Replaced with the spec's faint violet bloom rather than deleted: the
 * element also carries the hero's depth, and removing it flattens the
 * floating vials onto the page.
 * ------------------------------------------------------------------ */
/*
 * The violet wash that used to sit over the hero is gone: it existed to give a
 * flat white band some colour, and the real artwork now does that. Leaving
 * both stacked grey-washes the ribbon.
 */
html body.cl-v2:not(.cl-x) .cl-hero2::after { background: none !important; }

/* ------------------------------------------------------------------
 * TOP BAR
 *
 * The one place the brand gradient earns its keep: a thin strip, white
 * text, used once. Its text colours are set literally here because the
 * bar inherits --mist-100, which the remap above turns DARK for use on
 * white — leaving dark-grey text on a purple strip.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-topbar {
  background: linear-gradient(135deg, #4C1D95 0%, #6D28D9 45%, #A78BFA 100%) !important;
  border-bottom: 0 !important;
}
/*
 * EVERY descendant, not a list of them.
 *
 * The first version named .cl-topbar, __label, a and __link — and missed
 * .cl-topbar__calltag, .cl-topbar__promo and the price inside the
 * free-shipping line, which kept the dark ink the remap gives text on white
 * and rendered as dark grey on a purple strip. On a bar this small, listing
 * the children is how one gets left behind.
 */
html body.cl-v2:not(.cl-x) .cl-topbar,
html body.cl-v2:not(.cl-x) .cl-topbar *,
html body.cl-v2:not(.cl-x) .cl-topbar .amount,
html body.cl-v2:not(.cl-x) .cl-topbar bdi { color: #FFFFFF !important; }
html body.cl-v2:not(.cl-x) .cl-topbar svg { stroke: #FFFFFF !important; color: #FFFFFF !important; }
html body.cl-v2:not(.cl-x) .cl-topbar__link:hover { color: #F5F3FF !important; }

/* ------------------------------------------------------------------
 * THE MOVING BACKGROUND — HERO ONLY
 *
 * Noah, 2026-10-04: "matte white is the move because it looks more clinical",
 * and then: "there still needs to be a background around the floating heroes
 * at the beginning... I want that background to move."
 *
 * So the drifting texture is no longer a page-wide layer. .cl-bg is a fixed,
 * full-viewport element that sat behind every section; at an opacity low
 * enough not to spoil the matte white it was invisible anyway, and at an
 * opacity high enough to see it tinted the entire site. It is switched off
 * and the texture moved onto the hero, where it has something to do: give the
 * floating vials a surface to float over.
 *
 * It rides on .cl-hero2::before so that ::after — the violet wash — still
 * paints on top of it, and both sit under the content. The drift uses
 * cl-bg-drift, the animation the old background layer already used, so the
 * movement is the same one that was tuned for this site rather than a new one.
 * ------------------------------------------------------------------ */
html.cl-v2-root, html:has(body.cl-v2) { background: #FFFFFF !important; }
html body.cl-v2 { background: transparent !important; }

/* the page-wide texture layer is off: the rest of the site is matte white */
html body.cl-v2 .cl-bg { display: none !important; }

html body.cl-v2 .cl-hero2 { position: relative !important; }
html body.cl-v2 .cl-hero2::before {
  content: "" !important;
  position: absolute !important;
  inset: -6% !important;
  z-index: 0 !important;
  pointer-events: none !important;
  overflow: hidden !important;
  background-image: url("/wp-content/uploads/corelabs-hero/corelabs-bg-v2-1536.webp") !important;
  background-repeat: no-repeat !important;
  opacity: 1 !important;
  will-change: transform;
  /*
   * SPIRAL, not a drift.
   *
   * Noah, 2026-10-04: "I want the purple twisty thing to spiral... like a
   * double helix. I want it to spin. I don't like that it's just moving in and
   * out."
   *
   * A rotation needs the plate oversized or the corners sweep into frame: a
   * rectangle turned through 360 degrees must be scaled by at least sqrt(2)
   * (1.414) to keep covering its box. 1.5 leaves margin at every angle.
   *
   * 120s because this sits behind the headline and the buy button — at
   * anything faster the eye tracks it instead of the copy. Linear, so it never
   * appears to pause and restart.
   */
  animation: coreLabsSpiral 120s linear infinite !important;
}
/*
 * Which file, by how many pixels the box actually needs.
 *
 * The plate is scaled 1.5x by the spin, so the requirement is
 *     css width  x  device pixel ratio  x  1.5
 * A 390px phone at 2x needs 1170 (1536 covers it). An 890px window at 2x
 * needs 2670 — and the first set of breakpoints keyed the big file to
 * min-width 900, so that window was served 1536 and looked exactly as soft as
 * Noah said. Keyed to resolution as well as width now.
 */
@media (min-width: 600px), (min-resolution: 1.5dppx) {
  html body.cl-v2 .cl-hero2::before {
    background-image: url("/wp-content/uploads/corelabs-hero/corelabs-bg-v2-2560.webp") !important;
  }
}
@media (min-width: 1200px), (min-resolution: 1.5dppx) and (min-width: 820px) {
  html body.cl-v2 .cl-hero2::before {
    background-image: url("/wp-content/uploads/corelabs-hero/corelabs-bg-v2-3840.webp") !important;
  }
}

@keyframes coreLabsSpiral {
  from { transform: rotate(0deg) scale(1.5); }
  to   { transform: rotate(360deg) scale(1.5); }
}
@media (prefers-reduced-motion: reduce) {
  html body.cl-v2 .cl-hero2::before { animation: none !important; transform: scale(1.5); }
}

/* the hero's own contents stay above the texture */
html body.cl-v2 .cl-hero2 > * { position: relative; z-index: 1; }

/* ------------------------------------------------------------------
 * STARTER BUNDLE CARDS
 *
 * The card itself is a near-black gradient with white text inside it.
 * Both halves have to move together — recolouring the card alone leaves
 * white name/price/spec text on white.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) li.cl-bundle,
html body.cl-v2:not(.cl-x) .cl-bundle {
  background: #FFFFFF !important;
  border: 1px solid #E5E1F2 !important;
  box-shadow: 0 8px 28px rgba(17, 17, 24, .07) !important;
}
html body.cl-v2:not(.cl-x) .cl-bundle__name,
html body.cl-v2:not(.cl-x) .cl-bundle__name a,
html body.cl-v2:not(.cl-x) .cl-bundle__price,
html body.cl-v2:not(.cl-x) .cl-bundle__price .amount,
html body.cl-v2:not(.cl-x) .cl-bundle__price bdi,
html body.cl-v2:not(.cl-x) h2.cl-bundles__title { color: #111118 !important; }
html body.cl-v2:not(.cl-x) .cl-bundle__desc,
html body.cl-v2:not(.cl-x) .cl-bundle__spec { color: #52525B !important; }
html body.cl-v2:not(.cl-x) .cl-bundle__spec span,
html body.cl-v2:not(.cl-x) .cl-bundle__ruo { color: #71717A !important; }
/*
 * These two are not the same thing despite the name. .cl-bundles__eyebrow is a
 * line of text above a heading; .cl-picks__eyebrow is a filled purple PILL.
 * Grouping them gave the pill purple text on its own purple fill.
 */
html body.cl-v2:not(.cl-x) p.cl-bundles__eyebrow { color: #6D28D9 !important; }
html body.cl-v2:not(.cl-x) .cl-picks__eyebrow { color: #FFFFFF !important; }

/* ------------------------------------------------------------------
 * TEXT THAT WAS WHITE BECAUSE THE PAGE WAS BLACK
 *
 * Each of these sets a literal light colour, so the token remap cannot
 * reach them. Measured by walking every text node and comparing its
 * colour against the nearest ANCESTOR THAT ACTUALLY PAINTS — including
 * gradient buttons, which an earlier sweep scored as white backgrounds
 * and nearly had me "fixing" the legible white text on every purple
 * button on the site.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-hero2__titleTop,
html body.cl-v2:not(.cl-x) h2.cl-feat__title,
html body.cl-v2:not(.cl-x) .cl-feat__now,
html body.cl-v2:not(.cl-x) .cl-contact__value,
html body.cl-v2:not(.cl-x) main h2 { color: #111118 !important; }

html body.cl-v2:not(.cl-x) .cl-intent__text,
html body.cl-v2:not(.cl-x) .cl-zbar__txt,
html body.cl-v2:not(.cl-x) .cl-icon-btn__cap { color: #52525B !important; }
html body.cl-v2:not(.cl-x) .cl-zbar__txt b { color: #111118 !important; }
html body.cl-v2:not(.cl-x) .cl-header .cl-icon-btn:hover .cl-icon-btn__cap { color: #6D28D9 !important; }

/* the strength chips: light violet on violet-tinted glass -> readable */
html body.cl-v2:not(.cl-x) .cl-cardsizes,
html body.cl-v2:not(.cl-x) .cl-feat__sizes {
  color: #5B21B6 !important;
  background: #F5F3FF !important;
  border: 1px solid #E5E1F2 !important;
}

/* "How to save" is a link, not a button — it was styled to sit on black */
html body.cl-v2:not(.cl-x) a.cl-hero2__aside { color: #6D28D9 !important; }

/* sold-out button: light text on a light disabled fill */
html body.cl-v2:not(.cl-x) button.cl-atc__btn[disabled],
html body.cl-v2:not(.cl-x) button.cl-atc__btn.disabled {
  color: #71717A !important;
  background: #F4F4F5 !important;
  border: 1px solid #E5E1F2 !important;
}

/* the two side tabs ("AI helper", "Call a human") were dark glass */
html body.cl-v2:not(.cl-x) button.cl-ask__tab {
  background: linear-gradient(145deg, #6D28D9, #4C1D95) !important;
  border-color: #4C1D95 !important;
  color: #FFFFFF !important;
}
html body.cl-v2:not(.cl-x) a.cl-calltab {
  background: linear-gradient(145deg, #1F7A4D, #14603A) !important;
  /* NOT #000000. The "no green" line pass blackened this border because the
   * value it replaced was the old green #14603A. But block 3353 repaints the
   * tab purple, so the result was a small purple tab wearing a hard black
   * ring — Noah: "The talk to someone button's all fucked up."
   * It takes the dark end of its own gradient instead. */
  border-color: #4C1D95 !important;
  color: #FFFFFF !important;
}


/* ------------------------------------------------------------------
 * HEADINGS THAT WERE WHITE BECAUSE THE PAGE WAS BLACK
 *
 * The content pages (About, Contact, Shipping, COA, My Account) set h1/h2
 * to a literal white rather than through a token, so the remap left them
 * white on white — invisible, with no layout clue that anything was wrong.
 * Scoped to main so the white headings INSIDE purple panels are untouched.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) main h1,
html body.cl-v2:not(.cl-x) main h2,
html body.cl-v2:not(.cl-x) main h3,
html body.cl-v2:not(.cl-x) main h4,
html body.cl-v2:not(.cl-x) .cl-content h1,
html body.cl-v2:not(.cl-x) .cl-content h2,
html body.cl-v2:not(.cl-x) .cl-content h3,
html body.cl-v2:not(.cl-x) h1.product_title,
html body.cl-v2:not(.cl-x) h2.cl-contact__title { color: #111118 !important; }

/* ...but a heading sitting on a purple panel stays white */
html body.cl-v2:not(.cl-x) .cl-feat h2,
html body.cl-v2:not(.cl-x) .cl-chero h1,
html body.cl-v2:not(.cl-x) .cl-chero h2,
html body.cl-v2:not(.cl-x) [class*="--purple"] h2,
html body.cl-v2:not(.cl-x) .cl-callsheet h2 { color: inherit !important; }

/* product page odds and ends that set a literal white */
html body.cl-v2:not(.cl-x) span.sku,
html body.cl-v2:not(.cl-x) .sku_wrapper,
html body.cl-v2:not(.cl-x) .cl-pack__what,
html body.cl-v2:not(.cl-x) .cl-pack__lede,
html body.cl-v2:not(.cl-x) .woocommerce-breadcrumb,
html body.cl-v2:not(.cl-x) .woocommerce-breadcrumb a { color: #52525B !important; }
html body.cl-v2:not(.cl-x) .cl-pack__what { color: #111118 !important; }

/* prices: the amount, the symbol and the "From" label all set white */
html body.cl-v2:not(.cl-x) main .woocommerce-Price-amount,
html body.cl-v2:not(.cl-x) main .woocommerce-Price-currencySymbol,
html body.cl-v2:not(.cl-x) main bdi,
html body.cl-v2:not(.cl-x) .cl-price small,
html body.cl-v2:not(.cl-x) .price small { color: #111118 !important; }
html body.cl-v2:not(.cl-x) .cl-price small,
html body.cl-v2:not(.cl-x) .price small { color: #71717A !important; }

/* the shop hero's dark haze, same job as the homepage vignette */
html body.cl-v2:not(.cl-x) .cl-chero__haze {
  background: radial-gradient(54% 50% at 28% 40%,
      rgba(139, 92, 246, .10) 0%,
      rgba(196, 181, 253, .05) 60%,
      transparent 100%) !important;
}

/* the product page's tab strip */
html body.cl-v2:not(.cl-x) ul.tabs.wc-tabs,
html body.cl-v2:not(.cl-x) .woocommerce-tabs ul.tabs {
  background: #FAFAFA !important;
  border-color: #E5E1F2 !important;
}
html body.cl-v2:not(.cl-x) ul.tabs.wc-tabs a { color: #52525B !important; }
html body.cl-v2:not(.cl-x) ul.tabs.wc-tabs li.active a { color: #6D28D9 !important; }

/* the shop trust bar */
html body.cl-v2:not(.cl-x) ul.cl-trustbar {
  background: #FAFAFA !important;
  border-color: #E5E1F2 !important;
  color: #52525B !important;
}
html body.cl-v2:not(.cl-x) ul.cl-trustbar strong { color: #111118 !important; }


/* ------------------------------------------------------------------
 * THE LAST OF THE WHITE-ON-WHITE
 *
 * Everything here was measured by sc/v2scan.js against the nearest ancestor
 * that actually paints, then confirmed one by one in the browser — not
 * guessed from the class name. Two were the opposite of what the name
 * suggested: the "→" on .cl-pagenav__shop needed to go WHITE (it sits on a
 * purple gradient and had been left dark grey), and the strength chip needed
 * a specificity bump, because the theme sets it from
 * `.woocommerce ul.products li.product .cl-cardsizes` = (0,4,2) and a plain
 * `.cl-v2 .cl-cardsizes` at (0,3,2) silently loses.
 * ------------------------------------------------------------------ */

/*
 * The two page-nav buttons are NOT a pair, despite the shared block.
 * .cl-pagenav__shop is a filled purple gradient and needs white; the
 * neighbouring .cl-pagenav__home is a pale grey chip (#E4E4E7 at 96%) and
 * white on it is invisible. Treating them alike swapped one bug for another.
 */
html body.cl-v2:not(.cl-x) a.cl-pagenav__shop,
html body.cl-v2:not(.cl-x) a.cl-pagenav__shop * { color: #FFFFFF !important; }
html body.cl-v2:not(.cl-x) a.cl-pagenav__home,
html body.cl-v2:not(.cl-x) a.cl-pagenav__home * { color: #27272A !important; }

/* strength chips: enough specificity to beat the theme's own card rule */
html body.cl-v2:not(.cl-x) ul.products li.product .cl-cardsizes,
html body.cl-v2:not(.cl-x) ul.products li.product .cl-cardsizes,
html body.cl-v2:not(.cl-x) .cl-cardsizes,
html body.cl-v2:not(.cl-x) .cl-feat__sizes {
  color: #5B21B6 !important;
  background: #F5F3FF !important;
  border: 1px solid #E5E1F2 !important;
}

/* the shop hero's word blocks */
html body.cl-v2:not(.cl-x) .cl-chero__word,
html body.cl-v2:not(.cl-x) .cl-chero__title { color: #111118 !important; }

/* the cart drawer and the payment notice: both dark panels, now light */
html body.cl-v2:not(.cl-x) .cl-drawer__title,
html body.cl-v2:not(.cl-x) .cl-paynotice__title { color: #111118 !important; }
html body.cl-v2:not(.cl-x) .cl-paynotice li,
html body.cl-v2:not(.cl-x) .cl-paynotice p,
html body.cl-v2:not(.cl-x) .cl-paynotice b,
html body.cl-v2:not(.cl-x) .cl-faqhelp__title,
html body.cl-v2:not(.cl-x) .cl-faqhelp__sub { color: #27272A !important; }

/* body copy on the content pages, light because the page used to be black */
html body.cl-v2:not(.cl-x) main p,
html body.cl-v2:not(.cl-x) main li,
html body.cl-v2:not(.cl-x) .cl-content p,
html body.cl-v2:not(.cl-x) .cl-content li { color: #27272A !important; }

/* header nav labels */
html body.cl-v2:not(.cl-x) .cl-nav-label,
html body.cl-v2:not(.cl-x) .cl-header .cl-nav-label { color: #27272A !important; }

/* prices anywhere, not only inside <main> */
html body.cl-v2:not(.cl-x) .woocommerce-Price-amount,
html body.cl-v2:not(.cl-x) .woocommerce-Price-currencySymbol,
html body.cl-v2:not(.cl-x) .cl-bundle__spec span,
html body.cl-v2:not(.cl-x) .cl-bundle__spec { color: #111118 !important; }
/* ...except inside the purple top bar and on purple fills, which stay white */
html body.cl-v2:not(.cl-x) .cl-topbar .woocommerce-Price-amount,
html body.cl-v2:not(.cl-x) .cl-topbar .woocommerce-Price-currencySymbol,
html body.cl-v2:not(.cl-x) .cl-feat .woocommerce-Price-amount,
html body.cl-v2:not(.cl-x) .cl-feat .woocommerce-Price-currencySymbol { color: #FFFFFF !important; }


/* ------------------------------------------------------------------
 * SPECIFICITY, NOT COLOUR
 *
 * Each of these was already set to the right colour and still rendered the
 * old one, because the theme writes them from a longer selector. The numbers
 * are worth keeping: the product card is styled from
 * `html body:not(.cl-x) ul.products li.product.product ...` = (0,3,4), and
 * the bundle spec row from `...​.cl-bundle__spec li span:first-child` =
 * (0,3,4). A sensible-looking `.cl-v2 .thing` is (0,3,2) and loses in silence
 * — it matches, it is !important, and it does nothing.
 * ------------------------------------------------------------------ */

/* product-card prices: the amount, the symbol, the en dash and "From" */
html body.cl-v2:not(.cl-x) ul.products li.product.product .price,
html body.cl-v2:not(.cl-x) ul.products li.product.product .price *,
html body.cl-v2:not(.cl-x) ul.products li.product.product .woocommerce-Price-amount,
html body.cl-v2:not(.cl-x) ul.products li.product.product .woocommerce-Price-currencySymbol,
html body.cl-v2:not(.cl-x) ul.products li.product.product bdi { color: #111118 !important; }
html body.cl-v2:not(.cl-x) ul.products li.product.product .price small,
html body.cl-v2:not(.cl-x) ul.products li.product.product .price del,
html body.cl-v2:not(.cl-x) ul.products li.product.product .price del * { color: #A1A1AA !important; }

/* bundle spec rows: "TIRZ 10MG", "Bacteriostatic water", "Reconstitution sticks" */
html body.cl-v2:not(.cl-x) .cl-bundle__spec li span:first-child { color: #111118 !important; }
html body.cl-v2:not(.cl-x) .cl-bundle__spec li span:last-child { color: #71717A !important; }

/* ------------------------------------------------------------------
 * THE MAIN ADD TO CART BUTTON
 *
 * It was `background: rgba(155, 93, 229, .13)` with white text — a 13% purple
 * tint, which on the old black page read as a dark button and on white reads
 * as white-on-white. The generator correctly maps the hue and correctly keeps
 * the alpha, so it stays invisible: the alpha is the problem, and alpha is
 * exactly what a colour map must not touch. This is the one button a product
 * page exists for, so it gets a solid fill written by hand.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) button.single_add_to_cart_button,
html body.cl-v2:not(.cl-x) button.button.alt,
html body.cl-v2:not(.cl-x) button.single_add_to_cart_button.button {
  background-color: #6D28D9 !important;
  background-image: linear-gradient(135deg, #6D28D9 0%, #8B5CF6 100%) !important;
  border: 0 !important;
  color: #FFFFFF !important;
}
html body.cl-v2:not(.cl-x) button.single_add_to_cart_button:hover,
html body.cl-v2:not(.cl-x) button.button.alt:hover {
  background-image: linear-gradient(135deg, #5B21B6 0%, #6D28D9 100%) !important;
}
html body.cl-v2:not(.cl-x) button.single_add_to_cart_button[disabled],
html body.cl-v2:not(.cl-x) button.single_add_to_cart_button.disabled {
  background-image: none !important;
  background-color: #F4F4F5 !important;
  color: #71717A !important;
  border: 1px solid #E5E1F2 !important;
}

/* ------------------------------------------------------------------
 * THE HERO'S SECOND LINE
 *
 * "without limits" was gradient-FILLED text on the old site, then a later
 * rule in the same stylesheet overrode `color: transparent` with a solid
 * colour and a glow — so the clip stopped mattering and the gradient began
 * painting the whole box. On white that is a solid purple bar with purple
 * text on it, which is how it rendered. The glow and the four stacked
 * drop-shadows existed to lift light text off a black page and do nothing
 * but muddy it on white.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-hero2__titleBottom,
html body.cl-v2:not(.cl-x) .cl-hero2__titleBottom.is-revealed {
  background-image: none !important;
  background-color: transparent !important;
  color: #6D28D9 !important;
  -webkit-text-fill-color: #6D28D9 !important;
  text-shadow: none !important;
  filter: none !important;
}
html body.cl-v2:not(.cl-x) .cl-hero2__titleTop,
html body.cl-v2:not(.cl-x) .cl-hero2__title {
  text-shadow: none !important;
  filter: none !important;
}

/* ------------------------------------------------------------------
 * ANYTHING ON A PURPLE FILL GETS WHITE TEXT — INCLUDING ITS CHILDREN
 *
 * woocommerce.css contains
 *     body, p, li, td, dd, dt, span, a, strong, em, label { color: var(--mist-100) }
 * which SETS a colour on every bare <span> rather than letting it inherit. The
 * v2 remap turns --mist-100 dark for use on white, so every unclassed span
 * inside a purple button went dark grey: the "→" on "Explore products", on
 * "View all", on the page-nav — on every page of the site. Colouring the
 * button alone never reaches them.
 *
 * This is an explicit list of the purple-filled components rather than a
 * blanket rule, because several controls are deliberately the other way round
 * and a blanket rule would wreck them: .cl-picks__arrow is white with purple
 * text, .cl-feat__tag--stock is a pale chip with green text, .cl-vial__pill is
 * white with near-black text, and .cl-atc__opt and .cl-wait__open have no fill
 * at all. All four are verified in the inventory dump.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) a.cl-btn,
html body.cl-v2:not(.cl-x) a.cl-btn *,
html body.cl-v2:not(.cl-x) span.cl-feat__btn,
html body.cl-v2:not(.cl-x) span.cl-feat__btn *,
html body.cl-v2:not(.cl-x) a.cl-bundle__btn,
html body.cl-v2:not(.cl-x) a.cl-bundle__btn *,
html body.cl-v2:not(.cl-x) a.cl-hero2__shop,
html body.cl-v2:not(.cl-x) a.cl-hero2__shop *,
html body.cl-v2:not(.cl-x) a.cl-chip,
html body.cl-v2:not(.cl-x) a.cl-chip *,
html body.cl-v2:not(.cl-x) span.onsale,
html body.cl-v2:not(.cl-x) span.onsale *,
html body.cl-v2:not(.cl-x) span.cl-feat__tag--save,
html body.cl-v2:not(.cl-x) span.cl-feat__tag--save *,
html body.cl-v2:not(.cl-x) span.cl-intent__num,
html body.cl-v2:not(.cl-x) span.cl-zbar__tag,
html body.cl-v2:not(.cl-x) p.cl-picks__eyebrow,
html body.cl-v2:not(.cl-x) span.cl-picks__namebtn-arrow,
html body.cl-v2:not(.cl-x) .woocommerce-product-search button,
html body.cl-v2:not(.cl-x) .woocommerce-product-search button[type="submit"],
html body.cl-v2:not(.cl-x) .cl-search button[type="submit"] { color: #FFFFFF !important; }

/* the active item in the desktop nav is a filled purple pill */
html body.cl-v2:not(.cl-x) .cl-nav li a[aria-current="page"],
html body.cl-v2:not(.cl-x) .cl-nav li a[aria-current="page"] *,
html body.cl-v2:not(.cl-x) .cl-nav .current-menu-item > a,
html body.cl-v2:not(.cl-x) .cl-nav .current-menu-item > a *,
html body.cl-v2:not(.cl-x) .cl-nav .current_page_item > a,
html body.cl-v2:not(.cl-x) .cl-nav .current_page_item > a * { color: #FFFFFF !important; }
/*
 * .menu-item-home is NOT the active state — WordPress puts it on the Home
 * entry of every page. Including it turned "Home" white on all twelve other
 * pages, where it is a plain link on a white bar. Only aria-current and the
 * current-item classes mean "this page".
 */

/* ------------------------------------------------------------------
 * SOLD OUT
 *
 * A purple "Out of stock" button invites the tap it is there to prevent, and
 * it carried near-black text on the purple as well. Specificity here is
 * deliberately high: the generated palette file also targets .cl-atc__btn, and
 * it loads first, so matching its specificity is not enough.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) button.cl-btn.cl-atc__btn[disabled],
html body.cl-v2:not(.cl-x) button.cl-btn.cl-atc__btn:disabled,
html body.cl-v2:not(.cl-x) button.cl-btn.cl-atc__btn.disabled {
  background-image: none !important;
  background-color: #F4F4F5 !important;
  border: 1px solid #E5E1F2 !important;
  color: #71717A !important;
  cursor: not-allowed !important;
}

/* ==================================================================
 * POP-UPS, SHEETS AND DRAWERS
 *
 * Noah, 2026-10-04: "all the pop-ups and everything, make sure the colors and
 * the transparencies and all that are adjusted accordingly."
 *
 * These were invisible to the page scan: every one is `hidden` or at opacity 0
 * until something opens it, so nothing had ever measured them. sc/v2overlays.js
 * opens each one and measures it COMPOSITED over what is actually behind it,
 * because alpha is the whole problem here. A scrim at rgba(6,5,9,.66) over a
 * black page is invisible; over white it is a dark grey wash. A panel declared
 * `rgba(0,0,0,0)` composited to #121B16 — transparent, over something dark.
 * Reading the declared colours alone would have found none of this.
 *
 * Scrims keep their alpha and change their colour: a modal still needs the
 * page behind it pushed back, just with ink rather than tar.
 * ================================================================== */

/* ---- the checkout modal: the darkest thing left on the site ---- */
html body.cl-v2:not(.cl-x) div.cl-co__panel,
html body.cl-v2:not(.cl-x) div.cl-co__body,
html body.cl-v2:not(.cl-x) iframe.cl-co__frame {
  background: #FFFFFF !important;
  color: #27272A !important;
}
html body.cl-v2:not(.cl-x) header.cl-co__head {
  background: #FAFAFA !important;
  border-bottom: 1px solid #D4D4D8 !important;
  color: #111118 !important;
}
html body.cl-v2:not(.cl-x) header.cl-co__head * { color: #111118 !important; }
html body.cl-v2:not(.cl-x) a.cl-co__call {
  background: #F0FAF5 !important;
  border: 1px solid #E5E1F2 !important;
  color: #14603A !important;
}
html body.cl-v2:not(.cl-x) a.cl-co__call svg { color: #1F7A4D !important; }
/* the AI helper's twin button in the checkout header; the helper is gone, but
   the markup survives in a couple of cached templates — keep it legible */
html body.cl-v2:not(.cl-x) button.cl-co__pepper {
  background: #F5F3FF !important;
  border: 1px solid #E5E1F2 !important;
  color: #5B21B6 !important;
}

/* ---- "Call a human" sheet ---- */
html body.cl-v2:not(.cl-x) div.cl-callsheet__scrim {
  background: rgba(17, 17, 24, .45) !important;
}
html body.cl-v2:not(.cl-x) div.cl-callsheet__card {
  background: #FFFFFF !important;
  border: 1px solid #E5E1F2 !important;
  box-shadow: 0 20px 60px rgba(17, 17, 24, .18) !important;
}
html body.cl-v2:not(.cl-x) h2.cl-callsheet__title,
html body.cl-v2:not(.cl-x) .cl-callsheet__num { color: #111118 !important; }
html body.cl-v2:not(.cl-x) .cl-callsheet__eyebrow,
html body.cl-v2:not(.cl-x) .cl-callsheet__live { color: #1F7A4D !important; }
html body.cl-v2:not(.cl-x) .cl-callsheet__x { color: #52525B !important; }
html body.cl-v2:not(.cl-x) a.cl-callsheet__btn--call,
html body.cl-v2:not(.cl-x) a.cl-callsheet__btn--call * {
  background-image: linear-gradient(180deg, #1F7A4D, #14603A) !important;
  color: #FFFFFF !important;
  border: 0 !important;
}
html body.cl-v2:not(.cl-x) a.cl-callsheet__btn--text,
html body.cl-v2:not(.cl-x) a.cl-callsheet__btn--text * {
  background-image: none !important;
  background-color: #F0FAF5 !important;
  border: 1px solid #E5E1F2 !important;
  color: #14603A !important;
}

/* ---- the "please bear with us" payment notice ---- */
html body.cl-v2:not(.cl-x) div.cl-paynotice__scrim {
  background: rgba(17, 17, 24, .45) !important;
}
html body.cl-v2:not(.cl-x) div.cl-paynotice__box {
  background: #FFFFFF !important;
  border: 1px solid #E5E1F2 !important;
  box-shadow: 0 20px 60px rgba(17, 17, 24, .18) !important;
  color: #27272A !important;
}
html body.cl-v2:not(.cl-x) .cl-paynotice__box li {
  background: #FAFAFA !important;
  border: 1px solid #E5E1F2 !important;
  color: #27272A !important;
}
html body.cl-v2:not(.cl-x) p.cl-paynotice__zelle {
  background: #F0FAF5 !important;
  border: 1px solid #E5E1F2 !important;
  color: #14603A !important;
}
html body.cl-v2:not(.cl-x) div.cl-paynotice__code {
  background: #F5F3FF !important;
  border: 1px solid #E5E1F2 !important;
  color: #4C1D95 !important;
}
html body.cl-v2:not(.cl-x) div.cl-paynotice__code * { color: #4C1D95 !important; }
html body.cl-v2:not(.cl-x) button.cl-paynotice__cta,
html body.cl-v2:not(.cl-x) button.cl-paynotice__cta * {
  background-image: linear-gradient(135deg, #6D28D9 0%, #8B5CF6 100%) !important;
  color: #FFFFFF !important;
  border: 0 !important;
}

/* ---- the cart drawer ---- */
html body.cl-v2:not(.cl-x) a.cl-drawer__cta,
html body.cl-v2:not(.cl-x) a.cl-drawer__cta * {
  background-image: linear-gradient(135deg, #6D28D9 0%, #8B5CF6 100%) !important;
  background-color: #6D28D9 !important;
  color: #FFFFFF !important;
  border: 0 !important;
}
/* "from" and "Estimated total" are white spans in the drawer foot */
html body.cl-v2:not(.cl-x) .cl-drawer__foot,
html body.cl-v2:not(.cl-x) .cl-drawer__foot span,
html body.cl-v2:not(.cl-x) .cl-drawer__inner span,
html body.cl-v2:not(.cl-x) .cl-drawer__empty { color: #27272A !important; }
html body.cl-v2:not(.cl-x) .cl-drawer__foot strong,
html body.cl-v2:not(.cl-x) .cl-drawer__foot .amount { color: #111118 !important; }

/* ==================================================================
 * SOLID WHITE — EVERYWHERE EXCEPT THE HERO
 *
 * Noah, 2026-10-04: "i dont want the website to be transparent and opaque i
 * want solid white except where the moving background is."
 *
 * The old design was built as glass: almost every surface was a tinted panel
 * at 34-95% alpha with a backdrop-filter behind it, so the dark page showed
 * through and gave each card depth. Remapped onto white, the same rules give
 * a dozen slightly different lilacs — #F5F3FF at .34, at .40, at .55, at .58,
 * at .62, at .86 — which is the "transparent and opaque" look. Measured on
 * the live preview: 24 translucent surfaces outside the hero.
 *
 * Every one is made solid here, and the backdrop-filters come off: a blur
 * behind an opaque surface costs a compositor layer and renders nothing.
 *
 * ONLY TWO THINGS STAY TRANSLUCENT, both deliberately:
 *   - modal scrims, which exist to show the page behind them pushed back
 *   - the hero, which is where the moving background lives
 *
 * Specificity note, learned the hard way: the generated palette file writes
 * `html body.cl-v2:not(.cl-x) .thing` = (0,3,2). An earlier hand-written rule
 * here used `html body.cl-v2 div.cl-thing` = (0,2,3) and LOST — more elements,
 * fewer classes, and class count is compared first. Every rule below carries
 * :not(.cl-x) so it ranks at or above the generated one.
 * ================================================================== */
html body.cl-v2:not(.cl-x) header.cl-header,
html body.cl-v2:not(.cl-x) div.cl-ticker,
html body.cl-v2:not(.cl-x) footer.cl-footer,
html body.cl-v2:not(.cl-x) section.cl-picks,
html body.cl-v2:not(.cl-x) section.cl-intent,
html body.cl-v2:not(.cl-x) section.cl-section,
html body.cl-v2:not(.cl-x) section.cl-section--white,
html body.cl-v2:not(.cl-x) section.cl-section--alt,
html body.cl-v2:not(.cl-x) section.cl-contact,
html body.cl-v2:not(.cl-x) section.cl-contact--footer,
html body.cl-v2:not(.cl-x) div.cl-picks__panel,
html body.cl-v2:not(.cl-x) li.cl-intent__step,
html body.cl-v2:not(.cl-x) li.product,
html body.cl-v2:not(.cl-x) a.cl-feat__link,
html body.cl-v2:not(.cl-x) div.cl-pillar,
html body.cl-v2:not(.cl-x) li.cl-bundle,
html body.cl-v2:not(.cl-x) a.cl-bundle__media {
  background-color: #FFFFFF !important;
  background-image: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}

/* the one place a second tone earns its keep: separating bands of content */
html body.cl-v2:not(.cl-x) section.cl-section--alt,
html body.cl-v2:not(.cl-x) section.cl-bundles,
html body.cl-v2:not(.cl-x) div.cl-ticker,
html body.cl-v2:not(.cl-x) footer.cl-footer { background-color: #FAFAFA !important; }

/* pale purple chips and tiles become one solid tint, not six */
/*
 * .cl-feat__img is NOT a tile — it shows the product as a BACKGROUND IMAGE.
 * It was in this list, so `background-image: none` blanked the vial on every
 * featured card and the homepage showed four empty boxes. It only ever needed
 * its purple wash neutralised, which the generated palette already handles.
 */
html body.cl-v2:not(.cl-x) a.cl-picks__namebtn,
html body.cl-v2:not(.cl-x) a.cl-contact__link,
html body.cl-v2:not(.cl-x) a.cl-contact__link--email,
html body.cl-v2:not(.cl-x) a.cl-contact__link--phone {
  background-color: #F5F3FF !important;
  background-image: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
html body.cl-v2:not(.cl-x) span.cl-feat__img {
  background-color: transparent !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
html body.cl-v2:not(.cl-x) aside.cl-zbar {
  background-color: #F0FAF5 !important;
  background-image: none !important;
  border: 1px solid #E5E1F2 !important;
}
html body.cl-v2:not(.cl-x) button.cl-picks__arrow {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}

/* the one scrim the generator turned white — it has to darken, not vanish */
html body.cl-v2:not(.cl-x) div.cl-mobile__overlay {
  background-color: rgba(17, 17, 24, .45) !important;
  background-image: none !important;
}

/* ------------------------------------------------------------------
 * THE MOVING BACKGROUND, BEHIND THE HERO VIALS
 *
 * Noah: "put the moving background behind the heros."
 *
 * z-index 0 on the texture and z-index 1 on the hero's children is what puts
 * it behind the floating vials rather than over them. The hero's own panel is
 * transparent so the texture shows; everything below it is solid white, which
 * is what makes this read as a deliberate band rather than a tint over the
 * whole site.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) section.cl-hero2 {
  background-color: transparent !important;
}
html body.cl-v2:not(.cl-x) section.cl-hero2::before {
  /* full strength: the plate Noah supplied is already pale, and dimming it
     was a leftover from the faint placeholder ribbon it replaced */
  opacity: 1 !important;
  z-index: 0 !important;
}
html body.cl-v2:not(.cl-x) .cl-hero2__stageWrap,
html body.cl-v2:not(.cl-x) .cl-hero2__stage,
html body.cl-v2:not(.cl-x) .cl-vial,
html body.cl-v2:not(.cl-x) .cl-hero2__inner { position: relative; z-index: 1 !important; }

/* ------------------------------------------------------------------
 * THE LAST OF THE GLASS — WRITTEN AT THE THEME'S OWN SPECIFICITY
 *
 * Three survived the block above by being written from longer selectors:
 * the product card from `html body:not(.cl-x) ul.products li.product.product`
 * = (0,3,4), and the white section band from a similar chain. Matching the
 * element count as well as the class count is the only thing that settles it;
 * a shorter selector with !important matches, applies, and still loses.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products li.product.product,
html body.cl-v2:not(.cl-x) ul.products li.product.product {
  background-color: #FFFFFF !important;
  background-image: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  border: 1px solid #E5E1F2 !important;
}
html body.cl-v2:not(.cl-x) main section.cl-section.cl-section--white,
html body.cl-v2:not(.cl-x) body section.cl-section.cl-section--white,
html body.cl-v2:not(.cl-x) section.cl-section.cl-section--white {
  background-color: #FFFFFF !important;
  background-image: none !important;
}
html body.cl-v2:not(.cl-x) main section.cl-section.cl-section--alt,
html body.cl-v2:not(.cl-x) section.cl-section.cl-section--alt {
  background-color: #FAFAFA !important;
  background-image: none !important;
}

/*
 * Buttons: these carry a solid gradient in background-IMAGE and a leftover
 * 5-14% purple tint in background-COLOR underneath it. Nothing shows through,
 * but "solid white except the hero" should be true of the paint as well as
 * the pixels, so the tint is replaced rather than left to be discovered later.
 */
html body.cl-v2:not(.cl-x) a.cl-btn,
html body.cl-v2:not(.cl-x) a.cl-btn.cl-btn--secondary,
html body.cl-v2:not(.cl-x) button.cl-btn.cl-atc__btn,
html body.cl-v2:not(.cl-x) span.cl-feat__btn,
html body.cl-v2:not(.cl-x) a.cl-bundle__btn { background-color: #6D28D9 !important; }
html body.cl-v2:not(.cl-x) a.cl-contact__link,
html body.cl-v2:not(.cl-x) a.cl-contact__link--phone,
html body.cl-v2:not(.cl-x) a.cl-contact__link--email,
html body.cl-v2:not(.cl-x) a.cl-picks__namebtn { background-color: #F5F3FF !important; }

/* ==================================================================
 * FIT
 *
 * From sc/v2fit.js, which measures at 360, 375, 390 and 1440 — phones first,
 * and three of them, because a layout that survives 390 and breaks at 360 is
 * the usual shape of this bug.
 * ================================================================== */

/* ------------------------------------------------------------------
 * NOTHING GETS SQUASHED
 *
 * Both of the images this redesign introduced were rendering 5% out of their
 * true proportions, because the CSS boxes were sized for the artwork they
 * replaced: the old lockup is 640x221 and the new one 640x239, and the old
 * vial cut-outs are a different crop from the white ones. `object-fit` is
 * `fill` by default, so the browser stretched both to fit rather than letting
 * them keep their shape — which is exactly the "everything is mashing
 * together" failure the vials went through once already.
 *
 * `contain` lets each one keep the proportions it was drawn at and letterbox
 * inside whatever box the layout gives it.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) img.cl-logo__img,
html body.cl-v2:not(.cl-x) .cl-logo img,
html body.cl-v2:not(.cl-x) .cl-vial img,
html body.cl-v2:not(.cl-x) .cl-vial__img,
html body.cl-v2:not(.cl-x) li.product img,
html body.cl-v2:not(.cl-x) .cl-feat__img img,
html body.cl-v2:not(.cl-x) .cl-picks__art img,
html body.cl-v2:not(.cl-x) .cl-bundle__img {
  object-fit: contain !important;
}

/* ------------------------------------------------------------------
 * TAP TARGETS
 *
 * Pagination was 25x32 and 30x32 — under the 44px minimum on every phone
 * width. The carousel dots were 4px tall, which is a progress indicator being
 * asked to work as a button.
 *
 * The "Call a human" tab and the top-bar phone link are NOT fixed here and
 * are excluded in the scanner instead: the tab already carries a 44px-wide
 * invisible tap area on its ::after (see assets/calltab.css), which no
 * measurement of the visible box can see.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .page-numbers,
html body.cl-v2:not(.cl-x) a.page-numbers,
html body.cl-v2:not(.cl-x) span.page-numbers {
  min-width: 44px !important;
  min-height: 44px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
}
html body.cl-v2:not(.cl-x) ul.page-numbers { min-height: 44px !important; }

html body.cl-v2:not(.cl-x) button.cl-picks__dot {
  position: relative !important;
}
/* an invisible 44px tap area over a 4px dot, the same trick the edge tab uses */
html body.cl-v2:not(.cl-x) button.cl-picks__dot::after {
  content: "" !important;
  position: absolute !important;
  inset: -20px -6px !important;
}

html body.cl-v2:not(.cl-x) button.show-password-input {
  min-width: 44px !important;
  min-height: 44px !important;
}

/* ==================================================================
 * THE GLOW COMES OFF THE BOXES
 *
 * Noah, 2026-10-04: "the glowy theme was to keep us to be able to see on a
 * black background, but we're on a white background. So keep it glowy, but on
 * specific things... I want this website to have a lot of white, solid white."
 *
 * Measured with sc/v2glow.js, which separates a GLOW (coloured, soft, centred
 * — the thing that lifts an element off black) from a drop SHADOW (neutral,
 * offset downward — which a card on white still wants).
 * ================================================================== */

/* ------------------------------------------------------------------
 * 1. THE TEXT GLOW, WHICH WAS ON EVERYTHING
 *
 * woocommerce.css carries
 *     body, p, li, span, a, strong, em, small, h1..h6, .price, ...
 *     { text-shadow: 0 1px 2px #08070B, 0 2px 10px #08070B, 0 0 20px rgba(123,63,178,.28) }
 * — three stacked shadows on every piece of text on the site, there to pull it
 * off a black page. The palette generator mapped the colours faithfully, which
 * made it worse: a light halo plus a purple bloom behind every word on white.
 * It appeared on 26 element types per page.
 *
 * On white, text needs no shadow at all.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x),
html body.cl-v2:not(.cl-x) *,
html body.cl-v2:not(.cl-x) *::before,
html body.cl-v2:not(.cl-x) *::after { text-shadow: none !important; }

/* ------------------------------------------------------------------
 * 2. COLOURED GLOW OFF EVERY BOX THAT IS NOT A PRIMARY ACTION
 *
 * Cards keep an elevation shadow — neutral, offset down, barely there. That is
 * what gives a white card on a white page an edge without tinting it.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) a.cl-chip,
html body.cl-v2:not(.cl-x) a.cl-topbar__link,
html body.cl-v2:not(.cl-x) a.cl-contact__link,
html body.cl-v2:not(.cl-x) aside.cl-zbar,
html body.cl-v2:not(.cl-x) article,
html body.cl-v2:not(.cl-x) a.cl-btn.cl-btn--secondary,
html body.cl-v2:not(.cl-x) a.cl-btn.cl-chero__explore,
html body.cl-v2:not(.cl-x) a.cl-btn.cl-feat__all,
html body.cl-v2:not(.cl-x) .woocommerce-product-search button,
html body.cl-v2:not(.cl-x) span.cl-feat__btn,
html body.cl-v2:not(.cl-x) div.cl-pillar,
html body.cl-v2:not(.cl-x) li.cl-intent__step,
html body.cl-v2:not(.cl-x) section,
html body.cl-v2:not(.cl-x) div.cl-picks__panel { box-shadow: none !important; }

/* a card on white needs an edge, not a halo */
html body.cl-v2:not(.cl-x) a.cl-feat__link,
html body.cl-v2:not(.cl-x) ul.products li.product.product,
html body.cl-v2:not(.cl-x) li.cl-bundle,
html body.cl-v2:not(.cl-x) aside.cl-drawer__panel {
  box-shadow: 0 1px 2px rgba(17, 17, 24, .04), 0 8px 24px rgba(17, 17, 24, .06) !important;
}

/* ------------------------------------------------------------------
 * 3. WHERE THE GLOW STAYS
 *
 * "Keep it glowy, but on specific things." These are the specific things: the
 * one button each surface is built around. Everything else on the page is flat
 * white, so a soft purple bloom under the primary action now reads as emphasis
 * rather than as the house style.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) a.cl-hero2__shop,
html body.cl-v2:not(.cl-x) a.cl-bundle__btn,
html body.cl-v2:not(.cl-x) a.cl-drawer__cta,
html body.cl-v2:not(.cl-x) button.cl-paynotice__cta,
html body.cl-v2:not(.cl-x) button.single_add_to_cart_button,
html body.cl-v2:not(.cl-x) ul.products li.product.product button.cl-atc__btn:not(:disabled) {
  box-shadow: 0 8px 28px -8px rgba(109, 40, 217, .55) !important;
}
html body.cl-v2:not(.cl-x) a.cl-callsheet__btn--call {
  box-shadow: 0 8px 28px -8px rgba(31, 122, 77, .5) !important;
}

/* ==================================================================
 * BUTTON TEXT — THE TWO THAT STAYED BLACK
 *
 * Both were already told to be white and both lost, for the same reason and
 * by different amounts. The arithmetic is the point:
 *
 *   category chips   theme/palette `html body.cl-v2:not(.cl-x) .cl-chips .cl-chip`
 *                    = (0,4,2); the earlier override `html body.cl-v2 a.cl-chip`
 *                    = (0,2,3) — more elements, fewer classes, and class count
 *                    is compared first, so it lost.
 *   out of stock     theme `html body ul.products li.product.product .cl-atc__btn:disabled`
 *                    = (0,5,4); the earlier override was (0,5,3) — equal
 *                    classes, one element short.
 *
 * Both are rewritten here through the theme's own selector chain so they win
 * on specificity rather than on hope.
 * ================================================================== */
html body.cl-v2:not(.cl-x) .cl-chips .cl-chip,
html body.cl-v2:not(.cl-x) .cl-chips a.cl-chip,
html body.cl-v2:not(.cl-x) .cl-chips .cl-chip.is-active,
html body.cl-v2:not(.cl-x) .cl-chips .cl-chip *,
html body.cl-v2:not(.cl-x) nav .cl-chips .cl-chip { color: #FFFFFF !important; }

html body.cl-v2:not(.cl-x) ul.products li.product.product button.cl-atc__btn:disabled,
html body.cl-v2:not(.cl-x) ul.products li.product.product button.cl-atc__btn[disabled],
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc--out button.cl-atc__btn {
  background-image: none !important;
  background-color: #F4F4F5 !important;
  border: 1px solid #E5E1F2 !important;
  color: #71717A !important;
  box-shadow: none !important;
}

/* the last two coloured box-shadows: the edge tab and the contact tile */
html body.cl-v2:not(.cl-x) a.cl-calltab,
html body.cl-v2:not(.cl-x) a.cl-contact__link--phone,
html body.cl-v2:not(.cl-x) a.cl-contact__link--email {
  box-shadow: 0 2px 10px rgba(17, 17, 24, .10) !important;
}

/* the rest of the coloured glows, named from the scan rather than guessed */
html body.cl-v2:not(.cl-x) a.cl-contact__link.cl-contact__link--phone,
html body.cl-v2:not(.cl-x) a.cl-contact__link.cl-contact__link--email,
html body.cl-v2:not(.cl-x) button.cl-faqhelp__btn,
html body.cl-v2:not(.cl-x) button.woocommerce-button,
html body.cl-v2:not(.cl-x) button.woocommerce-button.button,
html body.cl-v2:not(.cl-x) details.cl-faq,
html body.cl-v2:not(.cl-x) div.cl-content,
html body.cl-v2:not(.cl-x) .woocommerce-product-search button[type="submit"],
html body.cl-v2:not(.cl-x) form.woocommerce-product-search button {
  box-shadow: none !important;
}
/* the two tiles keep a plain edge shadow, like every other card */
html body.cl-v2:not(.cl-x) a.cl-contact__link.cl-contact__link--phone,
html body.cl-v2:not(.cl-x) a.cl-contact__link.cl-contact__link--email {
  box-shadow: 0 1px 2px rgba(17, 17, 24, .04), 0 8px 24px rgba(17, 17, 24, .06) !important;
}

/* ------------------------------------------------------------------
 * THE PRICE GLOW, AND THE LAST TWO BOXES
 *
 * The universal `* { text-shadow: none }` above clears text glow everywhere
 * except where the theme wrote a LONGER selector with !important. Prices are
 * the main one:
 *     .woocommerce div.product p.price { text-shadow: ... } !important
 * = (0,3,2), against the universal rule's (0,2,2). Both are !important, so
 * specificity decides and the universal rule loses — on every price on the
 * site, which is the one number a customer actually reads.
 *
 * Written through the theme's own chain so it wins by arithmetic.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products li.product .price,
html body.cl-v2:not(.cl-x) ul.products li.product .price *,
html body.cl-v2:not(.cl-x) div.product p.price,
html body.cl-v2:not(.cl-x) div.product p.price *,
html body.cl-v2:not(.cl-x) div.product span.price,
html body.cl-v2:not(.cl-x) div.product span.price *,
html body.cl-v2:not(.cl-x) p.price,
html body.cl-v2:not(.cl-x) p.price *,
html body.cl-v2:not(.cl-x) span.price,
html body.cl-v2:not(.cl-x) span.price * { text-shadow: none !important; }

html body.cl-v2:not(.cl-x) select.orderby,
html body.cl-v2:not(.cl-x) select.orderby,
html body.cl-v2:not(.cl-x) .woocommerce-ordering select,
html body.cl-v2:not(.cl-x) details.cl-faq.is-revealed,
html body.cl-v2:not(.cl-x) details.cl-faq[open],
html body.cl-v2:not(.cl-x) .cl-faqs details.cl-faq {
  box-shadow: none !important;
}
html body.cl-v2:not(.cl-x) .cl-faqs details.cl-faq {
  border: 1px solid #E5E1F2 !important;
}

/* the product page's price carries .is-revealed, which outranks a plain p.price */
html body.cl-v2:not(.cl-x) div.product p.price.is-revealed,
html body.cl-v2:not(.cl-x) div.product p.price.is-revealed *,
html body.cl-v2:not(.cl-x) div.product p.price.is-revealed,
html body.cl-v2:not(.cl-x) div.product p.price.is-revealed *,
html body.cl-v2:not(.cl-x) p.price.is-revealed,
html body.cl-v2:not(.cl-x) p.price.is-revealed * { text-shadow: none !important; }

/* the "how ordering works" band */
html body.cl-v2:not(.cl-x) section.cl-intent,
html body.cl-v2:not(.cl-x) section.cl-intent::before { box-shadow: none !important; }

/* ------------------------------------------------------------------
 * VIALS OUTSIDE THE HERO
 *
 * Every vial render carries a purple drop-shadow so it floats rather than
 * sits pasted on. Inside the hero that is right — the hero is the one band
 * that is deliberately not flat white, and the bloom belongs to it. Anywhere
 * else (the Core Picks carousel, the cards) it is the old look on a white
 * panel, so the shadow stays and only its colour changes.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) img.attachment-woocommerce_single,
html body.cl-v2:not(.cl-x) .cl-picks__art img,
html body.cl-v2:not(.cl-x) li.product img {
  filter: drop-shadow(0 10px 18px rgba(17, 17, 24, .14)) !important;
}
/* ...but not inside the hero, which keeps its own */
html body.cl-v2:not(.cl-x) .cl-hero2 img.cl-vial__img,
html body.cl-v2:not(.cl-x) .cl-hero2 .cl-vial img {
  filter: drop-shadow(0 12px 22px rgba(109, 40, 217, .22)) !important;
}

/* the catalog hero vial: an <img> the earlier object-fit list did not reach */
html body.cl-v2:not(.cl-x) .cl-chero img,
html body.cl-v2:not(.cl-x) .cl-chero__art img,
html body.cl-v2:not(.cl-x) img[src*="-wv2-cut-"],
html body.cl-v2:not(.cl-x) img[srcset*="-wv2-cut-"] { object-fit: contain !important; }

/*
 * The top bar's phone link gets a thumb's worth of height — WITHOUT touching
 * `display`.
 *
 * The first version set `display: inline-flex !important` to centre the text
 * in a 44px box. On phones the theme hides three of the bar's items with
 * `display: none`, including the email link, and an !important display
 * override un-hid them: the row went from 375px wide to 470px and the bar was
 * cut off at both edges. Live was unaffected and correct, which is how it was
 * caught — the regression was mine, not the theme's.
 *
 * Padding gives the same hit area and cannot resurrect a hidden element.
 */
html body.cl-v2:not(.cl-x) .cl-topbar a.cl-topbar__link {
  padding-top: 12px !important;
  padding-bottom: 12px !important;
}


/* ------------------------------------------------------------------
 * THE FLOATING VIAL LABELS
 *
 * "SEMAGLUTIDE" needs 110px and the pill gives it 94, so the longest compound
 * name on the site renders as "SEMAGLU…" under its own vial. (Live does the
 * same with "LIPO-C - 10 mL" — this is not a v2 regression, but it is exactly
 * the "cropped bad" case Noah asked about, so it is fixed here.)
 *
 * The font size stays at 12px: that is the floor this site holds everywhere
 * and shrinking the label would trade one defect for another. The room comes
 * from the letter-spacing and the side padding instead, plus permission to
 * run a little wider than the vial column it sits under — three pills across
 * a 360px screen still clear each other at this size.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) span.cl-vial__pill {
  /*
   * Let the label WRAP rather than widen.
   *
   * Widening worked for the text and broke the layout: at 132% the pills under
   * the first two vials overlapped by 4px at 375, and the longest name still
   * did not fit at 360. Wrapping has no such ceiling — any compound name fits
   * at any width, each pill stays inside its own column, and the 12px floor is
   * untouched. Two short lines read better than "SEMAGLU…" anyway.
   */
  max-width: 100% !important;
  white-space: normal !important;
  overflow-wrap: anywhere !important;
  line-height: 1.15 !important;
  text-align: center !important;
  padding-left: 8px !important;
  padding-right: 8px !important;
  letter-spacing: .02em !important;
  text-overflow: clip !important;
}

/* ==================================================================
 * GLOW, PUT BACK — ON BUTTONS AND ON PURPLE TEXT
 *
 * Noah, 2026-10-04: "I wanted some buttons and some text to glow. You can make
 * buttons and text glow that were glowing — it just didn't need to be on boxes
 * or on things that made it look weird on solid white."
 *
 * So the rule is about WHAT glows, not how much. A glow is light coming off a
 * coloured thing: under a purple button or purple type on white it reads as
 * emphasis. Under a white card, a white panel or a section band it has nothing
 * to come off, and shows up as a grey-violet smudge around a rectangle — which
 * is what the earlier pass removed and must stay removed.
 *
 *   glows   every purple-filled button, and purple TEXT
 *   never   cards, panels, sections, articles, tiles, FAQ rows, the Zelle bar
 *   never   black or grey body text (a halo on near-black type is just mud —
 *           this is what the old site put on all 26 element types per page)
 * ================================================================== */

/* ---- buttons: every purple fill, not only the primary ones ---- */
html body.cl-v2:not(.cl-x) a.cl-btn,
html body.cl-v2:not(.cl-x) a.cl-btn.cl-btn--secondary,
html body.cl-v2:not(.cl-x) a.cl-btn.cl-feat__all,
html body.cl-v2:not(.cl-x) a.cl-btn.cl-chero__explore,
html body.cl-v2:not(.cl-x) span.cl-feat__btn,
html body.cl-v2:not(.cl-x) button.woocommerce-button,
html body.cl-v2:not(.cl-x) .woocommerce-product-search button,
html body.cl-v2:not(.cl-x) form.woocommerce-product-search button,
html body.cl-v2:not(.cl-x) button.cl-faqhelp__btn {
  box-shadow: 0 8px 22px -8px rgba(109, 40, 217, .50) !important;
}
/* the money buttons glow a touch harder */
html body.cl-v2:not(.cl-x) a.cl-hero2__shop,
html body.cl-v2:not(.cl-x) a.cl-bundle__btn,
html body.cl-v2:not(.cl-x) a.cl-drawer__cta,
html body.cl-v2:not(.cl-x) button.cl-paynotice__cta,
html body.cl-v2:not(.cl-x) button.single_add_to_cart_button,
html body.cl-v2:not(.cl-x) ul.products li.product.product button.cl-atc__btn:not(:disabled) {
  box-shadow: 0 10px 30px -8px rgba(109, 40, 217, .62) !important;
}
/* ...and a sold-out button still glows at nobody */
html body.cl-v2:not(.cl-x) ul.products li.product.product button.cl-atc__btn:disabled,
html body.cl-v2:not(.cl-x) button.cl-btn.cl-atc__btn[disabled] { box-shadow: none !important; }

/* ---- text: ONLY where the type is already purple ---- */
html body.cl-v2:not(.cl-x) .cl-hero2__titleBottom,
html body.cl-v2:not(.cl-x) .cl-hero2__titleBottom.is-revealed {
  text-shadow: 0 0 22px rgba(109, 40, 217, .38), 0 0 46px rgba(139, 92, 246, .22) !important;
}
html body.cl-v2:not(.cl-x) p.cl-bundles__eyebrow,
html body.cl-v2:not(.cl-x) p.cl-feat__eyebrow,
html body.cl-v2:not(.cl-x) .cl-section__eyebrow,
html body.cl-v2:not(.cl-x) h3.cl-footer__heading {
  text-shadow: 0 0 16px rgba(109, 40, 217, .30) !important;
}
/* text sitting ON a purple fill gets a white lift, not a purple one */
html body.cl-v2:not(.cl-x) a.cl-hero2__shop,
html body.cl-v2:not(.cl-x) a.cl-bundle__btn,
html body.cl-v2:not(.cl-x) button.single_add_to_cart_button,
html body.cl-v2:not(.cl-x) p.cl-picks__eyebrow {
  text-shadow: 0 0 14px rgba(255, 255, 255, .35) !important;
}

/* ------------------------------------------------------------------
 * THE STICKY CART BAR AND THE "NEED HELP" BAR
 *
 * Both found by sc/v2buy.js, which walks the actual purchase path — neither
 * is on a page at rest, so no amount of page scanning would have reached them.
 *
 * The sticky bar's "Secure checkout" is a bare <span> inside a purple gradient
 * button, so it inherited the dark colour from woocommerce.css's
 *     body, p, li, span, a, ... { color: var(--mist-100) }
 * exactly like the "→" arrows did. It is the button a phone customer taps to
 * check out, and it was dark grey on purple.
 *
 * The help bar is the opposite mistake: the generator correctly turned its
 * near-black panel into a light one, but `.cl-helpbar__text b { color: #fff }`
 * is written literally, so "Stuck? A real person picks up, 24/7." went white
 * on near-white.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) a.cl-sticky-cart__btn,
html body.cl-v2:not(.cl-x) a.cl-sticky-cart__btn *,
html body.cl-v2:not(.cl-x) .cl-sticky-cart__btn--go,
html body.cl-v2:not(.cl-x) .cl-sticky-cart__btn--go *,
html body.cl-v2:not(.cl-x) .cl-sticky-cart__btn.cl-secure,
html body.cl-v2:not(.cl-x) .cl-sticky-cart__btn.cl-secure * { color: #FFFFFF !important; }

html body.cl-v2:not(.cl-x) .cl-helpbar,
html body.cl-v2:not(.cl-x) .cl-needhelp.cl-helpbar {
  background-color: #FFFFFF !important;
  box-shadow: inset 0 0 0 1px #E4E4E7, 0 16px 36px -14px rgba(17, 17, 24, .28) !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
html body.cl-v2:not(.cl-x) .cl-helpbar__text { color: #52525B !important; }
html body.cl-v2:not(.cl-x) .cl-helpbar__text b { color: #111118 !important; }
html body.cl-v2:not(.cl-x) .cl-helpbar__x { color: #71717A !important; }

/* ------------------------------------------------------------------
 * "WHAT HAPPENS NEXT" UNDER EACH PAYMENT METHOD
 *
 * inc/manual-gateways.php prints a line of copy under the selected method
 * explaining what happens after Place order, with the important part in <b>.
 * woocommerce.css sets `.cl-paynow__next b { color: #fff }` literally, so on
 * the white checkout the one emphasised phrase in that sentence disappeared —
 * found by walking the purchase path into the embedded checkout frame, which
 * is the only place this markup exists.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) p.cl-paynow__next { color: #52525B !important; }
html body.cl-v2:not(.cl-x) p.cl-paynow__next b { color: #111118 !important; }
html body.cl-v2:not(.cl-x) p.cl-paynow__next a { color: #6D28D9 !important; }

/* ==================================================================
 * THE EMBEDDED CHECKOUT ON PHONES
 *
 * Every field label on the checkout rendered WHITE ON WHITE at 390px. Desktop
 * was fine. Six rules in woocommerce.css, all inside @media (max-width: 767px)
 * and all scoped to body.cl-embed, set
 *     color: #FFFFFF !important
 * on the form labels — correct when the embedded checkout was a black sheet.
 *
 * The palette generator could not fix this one, and the reason is worth
 * keeping: it skips any colour already in the brand palette, and #FFFFFF IS a
 * brand colour. White is right as a surface and right as text on a purple
 * button; it is only wrong here. There is no rule that tells those three apart
 * from the stylesheet alone — which is why this was found by WALKING THE
 * CHECKOUT at phone width rather than by reading CSS.
 *
 * Mobile is ~90% of this site's traffic, so this was every customer's
 * checkout.
 * ================================================================== */
@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x).cl-embed form.checkout p.form-row > label,
  html body.cl-v2:not(.cl-x).cl-embed .cl-am p.form-row > label,
  html body.cl-v2:not(.cl-x).cl-embed .woocommerce-shipping-fields label,
  html body.cl-v2:not(.cl-x).cl-embed .woocommerce-billing-fields label,
  html body.cl-v2:not(.cl-x).cl-embed .cl-am label,
  html body.cl-v2:not(.cl-x).cl-embed .cl-am .cl-am__body p.form-row > label,
  html body.cl-v2:not(.cl-x).cl-embed .cl-am__dialog .cl-am__body p.form-row > label,
  html body.cl-v2:not(.cl-x).cl-embed form.checkout label,
  html body.cl-v2:not(.cl-x) form.checkout p.form-row > label,
  html body.cl-v2:not(.cl-x) .woocommerce-shipping-fields label,
  html body.cl-v2:not(.cl-x) .woocommerce-billing-fields label { color: #27272A !important; }

  html body.cl-v2:not(.cl-x).cl-embed form.checkout p.form-row > label .required,
  html body.cl-v2:not(.cl-x).cl-embed .cl-am__dialog label .required,
  html body.cl-v2:not(.cl-x) label .required { color: #6D28D9 !important; }

  html body.cl-v2:not(.cl-x).cl-embed .cl-coupon__label,
  html body.cl-v2:not(.cl-x).cl-embed .cl-ck__payTitle,
  html body.cl-v2:not(.cl-x).cl-embed .cl-ck__aside { color: #52525B !important; }
}


/* ------------------------------------------------------------------
 * ONE LAYER IN THE HERO, NOT TWO
 *
 * .cl-hero2::after carried a violet wash that existed to give a flat white
 * band some colour. The supplied plate now does that, and stacking the two
 * greys the ribbon out — most visibly on phones, where the wash was declared
 * a second time inside its own media query and survived the first removal.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-hero2::after,
html body.cl-v2:not(.cl-x) section.cl-hero2::after {
  background: none !important;
  background-image: none !important;
}

/* ------------------------------------------------------------------
 * FRAMING THE PLATE ON A PHONE
 *
 * The artwork is 16:9 and the hero on a phone is tall and narrow, so `cover`
 * crops to the middle — which is the one part of this plate that is almost
 * plain white. The ribbons live down the left and right edges. Sizing by
 * HEIGHT and sitting right of centre brings a real curve into frame instead
 * of cropping it away.
 * ------------------------------------------------------------------ */
/*
 * FRAMING, NOW THAT IT TURNS
 *
 * A spinning plate has to COVER its box at every angle, so the width/height
 * fitting used while it only drifted no longer applies — `cover` plus the 1.5
 * scale is what keeps the frame full through a whole revolution. The crop
 * moves continuously as it turns, so both edge ribbons come through the frame
 * rather than one being chosen and parked.
 */
html body.cl-v2:not(.cl-x) .cl-hero2::before {
  background-size: cover !important;
  background-position: center center !important;
}


/* ==================================================================
 * NOAH'S PASS, 2026-10-04
 * ================================================================== */

/* ---- the Zelle bar: filled green, not a pale tint ----
 * "these green pop-ups need to be filled in green because that's hard to
 * read." The pale mint wash came from mapping a dark-page panel onto white;
 * on white it reads as almost nothing. Solid green, white text, and it keeps
 * a glow.
 */
html body.cl-v2:not(.cl-x) aside.cl-zbar,
html body.cl-v2:not(.cl-x) aside.cl-zbar--home,
html body.cl-v2:not(.cl-x) aside.cl-zbar--shop,
html body.cl-v2:not(.cl-x) aside.cl-zbar--product {
  background-color: #1F7A4D !important;
  background-image: linear-gradient(135deg, #1F7A4D 0%, #2FA86B 100%) !important;
  border: 0 !important;
  box-shadow: 0 8px 24px -8px rgba(31, 122, 77, .55) !important;
}
html body.cl-v2:not(.cl-x) aside.cl-zbar,
html body.cl-v2:not(.cl-x) aside.cl-zbar *,
html body.cl-v2:not(.cl-x) span.cl-zbar__txt,
html body.cl-v2:not(.cl-x) span.cl-zbar__txt b { color: #FFFFFF !important; }
/* the SAVE 5% pill has to stay readable ON the green now */
html body.cl-v2:not(.cl-x) span.cl-zbar__tag {
  background-color: #FFFFFF !important;
  background-image: none !important;
  color: #14603A !important;
  font-weight: 800 !important;
}

/* ---- "HOW TO SAVE": a real button, not an outline on white ----
 * It was a transparent pill with a hairline border, which worked on black and
 * disappears on white.
 */
/* the generated rule is `.cl-v2:not(.cl-x) .cl-hero2 .cl-hero2__aside` = (0,4,2);
   an `a.cl-hero2__aside` version is (0,3,3) and loses on class count */
html body.cl-v2:not(.cl-x) .cl-hero2 a.cl-hero2__aside,
html body.cl-v2:not(.cl-x) .cl-hero2 a.cl-hero2__aside * {
  background-color: #FFFFFF !important;
  background-image: none !important;
  border: 2px solid #6D28D9 !important;
  color: #5B21B6 !important;
  box-shadow: 0 8px 22px -8px rgba(109, 40, 217, .45) !important;
}
html body.cl-v2:not(.cl-x) .cl-hero2 a.cl-hero2__aside:hover {
  background-color: #6D28D9 !important;
  color: #FFFFFF !important;
}
html body.cl-v2:not(.cl-x) .cl-hero2 a.cl-hero2__aside:hover * { color: #FFFFFF !important; }

/* ---- text that is too light to read on white ----
 * Body copy inherited a grey tuned for a black page. On white the same grey
 * is weak, so the small print goes darker and the lead-ins go bold.
 */
html body.cl-v2:not(.cl-x) p.cl-contact__note,
html body.cl-v2:not(.cl-x) p.cl-contact__lede,
html body.cl-v2:not(.cl-x) p.cl-footer__blurb,
html body.cl-v2:not(.cl-x) p.cl-footer__ruo,
html body.cl-v2:not(.cl-x) p.cl-footer__disclaimer,
html body.cl-v2:not(.cl-x) .cl-bundle__ruo,
html body.cl-v2:not(.cl-x) .woocommerce-result-count,
html body.cl-v2:not(.cl-x) main p,
html body.cl-v2:not(.cl-x) main li { color: #27272A !important; }
html body.cl-v2:not(.cl-x) p.cl-contact__note { font-weight: 500 !important; }
html body.cl-v2:not(.cl-x) main p strong,
html body.cl-v2:not(.cl-x) main li strong,
html body.cl-v2:not(.cl-x) main p b { color: #111118 !important; font-weight: 700 !important; }

/* ---- hero vials: lose the hard shadow, let them sit on the plate ----
 * "the hero vials still have that shadow, they're not blended well." The
 * renders carry their own soft contact shadow; the CSS drop-shadow on top of
 * it is what reads as a second, harder edge.
 */
html body.cl-v2:not(.cl-x) .cl-hero2 img.cl-vial__img,
html body.cl-v2:not(.cl-x) .cl-hero2 .cl-vial img {
  filter: none !important;
}
/*
 * NO shadow under the floating hero vials at all (Noah, 2026-10-04).
 *
 * .cl-vial::before and ::after are two blurred violet ellipses that sat under
 * each vial to lift it off the black page. Softening them was not the ask —
 * on the white plate any pool of colour under the glass reads as a smudge,
 * and the renders already carry their own contact shadow.
 */
html body.cl-v2:not(.cl-x) .cl-vial::before,
html body.cl-v2:not(.cl-x) .cl-vial::after {
  display: none !important;
  content: none !important;
}
html body.cl-v2:not(.cl-x) .cl-vial,
html body.cl-v2:not(.cl-x) .cl-vial__shot,
html body.cl-v2:not(.cl-x) .cl-hero2 .cl-vial img {
  box-shadow: none !important;
  filter: none !important;
}

/* ------------------------------------------------------------------
 * THE STICKY CART THUMBNAIL
 *
 * The icon box is `aspect-ratio: 600/1318` — 0.455, the OLD tall vial's
 * shape — and 22px wide. The v2 vials are 0.693 and the starter packs are
 * square, so `object-fit: contain` fitted a 1200x1200 pack into a 20x46 slot:
 * 20x20 of artwork with 26px of empty box under it. That is the cramped
 * thumbnail in the cart bar.
 *
 * A square box fits both shapes without letterboxing, and at 44px the product
 * is actually identifiable. The bar itself goes white with the rest of the
 * site; it was a grey left over from the dark design.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) span.cl-sticky-cart__icon {
  aspect-ratio: 1 / 1 !important;
  width: 44px !important;
  height: 44px !important;
  background-color: #F5F3FF !important;
  border: 1px solid #E5E1F2 !important;
  border-radius: 12px !important;
  overflow: hidden !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  flex: 0 0 44px !important;
}
html body.cl-v2:not(.cl-x) img.cl-sticky-cart__vial {
  width: 100% !important;
  height: 100% !important;
  object-fit: contain !important;
  padding: 3px !important;
  box-sizing: border-box !important;
}
html body.cl-v2:not(.cl-x) div.cl-sticky-cart {
  background-color: #FFFFFF !important;
  border-top: 1px solid #D4D4D8 !important;
  box-shadow: 0 -8px 28px rgba(17, 17, 24, .10) !important;
}

/* ------------------------------------------------------------------
 * PRODUCT CARDS: THE GAP, AND THE VIAL FILLING THE BOX
 *
 * Measured on a shop card (265x465):
 *   the link block is a FIXED 354px tall
 *   its contents — image 263 + title 38 + price 30 + margins — fall short
 *   so ~53px of slack collects at the bottom, which renders as a 56px hole
 *   between the compound name and the MG chip.
 *
 * And the image is laid out `aspect-ratio: 1/1` at 263px in a 265px card, so
 * the vial is drawn edge to edge with no margin — "about to bust out of the
 * box".
 *
 * Both come from the same place: a fixed box sized for the old artwork. The
 * block gets its height back from its contents, and the image is given a
 * shorter box with breathing room, so the name sits under the vial and the
 * chip sits under the name.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link {
  height: auto !important;
  min-height: 0 !important;
  /* was `block`, which pinned every pixel of the grid's row-stretch slack to
     the bottom of this anchor and rendered it as the hole above the MG chip.
     See "1. THE HOLE IN THE PRODUCT CARDS" at the end of this file. */
  display: flex !important;
  flex-direction: column !important;
  align-items: stretch !important;
  justify-content: flex-start !important;
  overflow: visible !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link img {
  aspect-ratio: auto !important;
  width: 100% !important;
  height: 208px !important;
  max-height: 208px !important;
  object-fit: contain !important;
  padding: 10px 14px 4px !important;
  box-sizing: border-box !important;
  margin: 0 auto !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product h2.woocommerce-loop-product__title {
  margin: 2px 0 4px !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product .price {
  margin: 0 0 8px !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-cardsizes {
  margin-top: 0 !important;
  margin-bottom: 8px !important;
}
/* the cards still have to line up, so the grid keeps them equal height */
html body.cl-v2:not(.cl-x) ul.products li.product.product {
  display: flex !important;
  flex-direction: column !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc { margin-top: auto !important; }

/* ==================================================================
 * CONTRAST — measured with real WCAG ratios (sc/v2contrast.js)
 *
 * Each value below was chosen to clear the pass mark against what is actually
 * painted behind it, not picked by eye:
 *   body text  4.5:1      large or bold text  3.0:1
 * ================================================================== */

/* the trust ticker: #8B5CF6 on #FAFAFA measured 4.1:1 — just under.
   #5B21B6 on the same ground is 7.4:1. */
html body.cl-v2:not(.cl-x) .cl-ticker li,
html body.cl-v2:not(.cl-x) .cl-ticker__list li,
html body.cl-v2:not(.cl-x) ul.cl-trustbar li,
html body.cl-v2:not(.cl-x) .cl-trustbar__text { color: #5B21B6 !important; font-weight: 600 !important; }

/* the Zelle bar: white on the #27915C the gradient averaged to was 4.0:1.
   Darkening the gradient to #15683F..#1F7A4D puts white at 6.6:1. */
html body.cl-v2:not(.cl-x) aside.cl-zbar,
html body.cl-v2:not(.cl-x) aside.cl-zbar--home,
html body.cl-v2:not(.cl-x) aside.cl-zbar--shop,
html body.cl-v2:not(.cl-x) aside.cl-zbar--product {
  background-image: linear-gradient(135deg, #15683F 0%, #1F7A4D 100%) !important;
  background-color: #15683F !important;
}
html body.cl-v2:not(.cl-x) span.cl-zbar__txt,
html body.cl-v2:not(.cl-x) span.cl-zbar__txt b { font-weight: 600 !important; }
html body.cl-v2:not(.cl-x) span.cl-zbar__txt b { font-weight: 800 !important; }

/* "Check COA for this product": #C4B5FD on white measured 1.8:1 */
/* ...but NOT when the COA link IS a filled button: that rule put #5B21B6 text
   on the #733FD6 "View COA Portal" button and measured 1.5:1. */
html body.cl-v2:not(.cl-x) a[href*="coa"]:not(.cl-btn):not(.button),
html body.cl-v2:not(.cl-x) .cl-coa-link:not(.cl-btn),
html body.cl-v2:not(.cl-x) .cl-product__coa a:not(.cl-btn) { color: #5B21B6 !important; font-weight: 600 !important; }

/* ------------------------------------------------------------------
 * THE PRODUCT PAGE'S ADD TO CART WAS WHITE ON WHITE — 1:1.
 *
 * The earlier rule gave it a purple gradient, and something later in the
 * cascade put the background back to the page colour while the text stayed
 * white. Written here through the WooCommerce chain the theme itself uses, so
 * it cannot be undercut, and with the fill stated as both image and colour.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) div.product form.cart button.single_add_to_cart_button,
html body.cl-v2:not(.cl-x) div.product button.single_add_to_cart_button,
html body.cl-v2:not(.cl-x) div.product form.cart button.single_add_to_cart_button,
html body.cl-v2:not(.cl-x) button.single_add_to_cart_button.button.alt,
html body.cl-v2:not(.cl-x) button.single_add_to_cart_button {
  background-color: #5B21B6 !important;
  background-image: linear-gradient(135deg, #5B21B6 0%, #7C3AED 100%) !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
  border: 0 !important;
}

/* ------------------------------------------------------------------
 * THE PANELS NOAH CALLED HARD TO READ
 *
 * The contact tiles and footer columns use a pale lilac label on a paler
 * lilac ground. Filling the ground properly and darkening the label is what
 * makes them legible, rather than nudging one of the two.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-contact__label,
html body.cl-v2:not(.cl-x) .cl-contact__eyebrow,
html body.cl-v2:not(.cl-x) h3.cl-footer__heading,
html body.cl-v2:not(.cl-x) .cl-footer__col h3 {
  color: #4C1D95 !important;
  font-weight: 800 !important;
}
html body.cl-v2:not(.cl-x) .cl-contact__value,
html body.cl-v2:not(.cl-x) .cl-footer__col a,
html body.cl-v2:not(.cl-x) .cl-footer a {
  color: #27272A !important;
  font-weight: 600 !important;
}
html body.cl-v2:not(.cl-x) a.cl-contact__link,
html body.cl-v2:not(.cl-x) a.cl-contact__link--phone,
html body.cl-v2:not(.cl-x) a.cl-contact__link--email {
  background-color: #F5F3FF !important;
  border: 2px solid #C4B5FD !important;
}

/* ------------------------------------------------------------------
 * THE TOP BAR AND THE TICKER
 *
 * Noah: "you see all this up here? hard to read... the buttons and the text
 * needs to be bolded on the moving banner and maybe the banner should be
 * filled in."
 *
 * Two different problems in two stacked bars:
 *   top bar  white text on the brand gradient is fine for contrast, but the
 *            two pills were translucent white — barely separable from the
 *            purple behind them. They get a solid fill and a weight.
 *   ticker   purple on near-white measured 4.1:1, under the 4.5 pass mark,
 *            and at 13px with letterspacing it reads thin. Darker ink, more
 *            weight, and a filled band so it is a band rather than text
 *            floating on the page.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-topbar,
html body.cl-v2:not(.cl-x) .cl-topbar * { font-weight: 700 !important; }
html body.cl-v2:not(.cl-x) .cl-topbar a.cl-topbar__link {
  background-color: rgba(255, 255, 255, .18) !important;
  border: 1px solid #E5E1F2 !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}
html body.cl-v2:not(.cl-x) .cl-topbar a.cl-topbar__link--email {
  background-color: rgba(255, 255, 255, .92) !important;
  border-color: #E5E1F2 !important;
  color: #4C1D95 !important;
  -webkit-text-fill-color: #4C1D95 !important;
}
html body.cl-v2:not(.cl-x) .cl-topbar a.cl-topbar__link--email svg { stroke: #4C1D95 !important; color: #4C1D95 !important; }

html body.cl-v2:not(.cl-x) div.cl-ticker {
  background-color: #F5F3FF !important;
  border-top: 1px solid #D4D4D8 !important;
  border-bottom: 1px solid #D4D4D8 !important;
}
html body.cl-v2:not(.cl-x) div.cl-ticker li,
html body.cl-v2:not(.cl-x) div.cl-ticker .cl-ticker__list li,
html body.cl-v2:not(.cl-x) div.cl-ticker * {
  color: #4C1D95 !important;
  -webkit-text-fill-color: #4C1D95 !important;
  font-weight: 700 !important;
}


/* ---- the last five, each measured ---- */

/* section eyebrows: #C4B5FD on white was 1.8:1 */
html body.cl-v2:not(.cl-x) p.cl-eyebrow,
html body.cl-v2:not(.cl-x) p.cl-feat__eyebrow,
html body.cl-v2:not(.cl-x) .cl-eyebrow {
  color: #5B21B6 !important;
  -webkit-text-fill-color: #5B21B6 !important;
  font-weight: 700 !important;
}

/* the numbered step bubbles: white on #8A5AEA was 4.4:1, just under */
html body.cl-v2:not(.cl-x) span.cl-intent__num {
  background-image: linear-gradient(135deg, #5B21B6, #6D28D9) !important;
  background-color: #5B21B6 !important;
}

/* add to cart: white on #8D5FD7 was 4.4:1 — the same near miss */
html body.cl-v2:not(.cl-x) div.product form.cart button.single_add_to_cart_button,
html body.cl-v2:not(.cl-x) div.product button.single_add_to_cart_button,
html body.cl-v2:not(.cl-x) button.single_add_to_cart_button {
  background-image: linear-gradient(135deg, #4C1D95 0%, #6D28D9 100%) !important;
  background-color: #4C1D95 !important;
}

/* pagination's current page: #816F98 on #E9E6ED was 3.6:1 */
html body.cl-v2:not(.cl-x) span.page-numbers.current,
html body.cl-v2:not(.cl-x) nav.woocommerce-pagination span.current {
  background-color: #6D28D9 !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
  font-weight: 700 !important;
}

/* ------------------------------------------------------------------
 * THE LAST TWO NEAR-MISSES
 *
 * Both were self-inflicted and both measured just under 4.5:1 — close enough
 * to look fine and still fail.
 *
 *   topbar pill   a white 18% tint over the brand gradient lifted its own
 *                 background to #8E66D6, which drops white text to 4.2:1. The
 *                 pill needed to go DARKER than the bar, not lighter.
 *   add to cart   the gradient set earlier is still being outranked; the
 *                 painted fill measured #8D5FD7 (4.4:1). Stated flat, through
 *                 the longest WooCommerce chain, with no gradient to average.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-topbar a.cl-topbar__link,
html body.cl-v2:not(.cl-x) div.cl-topbar a.cl-topbar__link {
  background-color: #3B1573 !important;
  background-image: none !important;
  border: 1px solid #E5E1F2 !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}
html body.cl-v2:not(.cl-x) .cl-topbar a.cl-topbar__link--email,
html body.cl-v2:not(.cl-x) div.cl-topbar a.cl-topbar__link--email {
  background-color: #FFFFFF !important;
  border-color: #E5E1F2 !important;
  color: #3B1573 !important;
  -webkit-text-fill-color: #3B1573 !important;
}

html body.cl-v2:not(.cl-x) div.product form.cart button.single_add_to_cart_button.button,
html body.cl-v2:not(.cl-x) div.product form.cart button.single_add_to_cart_button,
html body.cl-v2:not(.cl-x) div.product button.single_add_to_cart_button.button.alt,
html body.cl-v2:not(.cl-x) div.product form.cart button.single_add_to_cart_button.button {
  background-image: none !important;
  background-color: #4C1D95 !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}

/* the required-field asterisk: #C4B5FD on #FAFAFA measured 1.8:1 */
html body.cl-v2:not(.cl-x) span.required,
html body.cl-v2:not(.cl-x) abbr.required,
html body.cl-v2:not(.cl-x) label .required {
  color: #B91C4A !important;
  -webkit-text-fill-color: #B91C4A !important;
}

/* ------------------------------------------------------------------
 * ADD TO CART BEFORE A STRENGTH IS CHOSEN
 *
 * On a variable product the button carries `.disabled
 * .wc-variation-selection-needed` until a strength is picked, and the theme
 * fades it. Its fill computes to the full #4C1D95 but paints at reduced
 * opacity, which composites to #A68ECA — white text at 2.9:1, and it still
 * looks like a live purple button.
 *
 * Given a real disabled treatment instead: a flat grey at full opacity, which
 * reads unmistakably as "pick a strength first" and is legible while it waits.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) button.single_add_to_cart_button.disabled,
html body.cl-v2:not(.cl-x) button.single_add_to_cart_button[disabled],
html body.cl-v2:not(.cl-x) button.single_add_to_cart_button.wc-variation-selection-needed,
html body.cl-v2:not(.cl-x) div.product form.cart button.single_add_to_cart_button.disabled,
html body.cl-v2:not(.cl-x) div.product form.cart button.single_add_to_cart_button.wc-variation-selection-needed {
  background-color: #F4F4F5 !important;
  background-image: none !important;
  color: #52525B !important;
  -webkit-text-fill-color: #52525B !important;
  border: 1px solid #E5E1F2 !important;
  opacity: 1 !important;
  box-shadow: none !important;
  cursor: not-allowed !important;
}

/* ==================================================================
 * NOAH'S 2026-10-04 ROUND — measured, not eyeballed
 *
 * Eight separate complaints, each one reduced to a number first with
 * sc/v2cards.js, sc/v2round.js, sc/v2explore.js and sc/v2mid.js, so the fix
 * targets the cause rather than the symptom. The numbers are quoted in each
 * block, because in a 20,000-line stylesheet the next person (me, next week)
 * needs to know what "fixed" meant.
 * ================================================================== */


/* ------------------------------------------------------------------
 * 1. THE HOLE IN THE PRODUCT CARDS
 *
 * Noah: "on GHKCU, look at that spacing. It's like that for Klow as well...
 * Semax is doing it still. You need to scan all of the product cards."
 *
 * Measured: a 28-66px dead band between the price and the strengths chip on
 * 14 of the 17 cards, and 43-85px between the price and the buy button on the
 * starter packs (which have no chip). Not a margin — the grid stretches every
 * card in a row to the tallest, and the <a> that wraps image+title+price is
 * `flex: 1 1 auto`, so it swallows ALL of the slack. Its children are stacked
 * from its top, so the slack falls out of the bottom as a hole.
 *
 * The anchor keeps growing — it has to, or the cards stop being equal height.
 * It becomes a flex column instead, and the IMAGE takes the slack. That both
 * closes the hole and answers the older complaint that the vials look
 * "almost about to bust out of the box": the extra room now goes to the vial.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products li.product a.woocommerce-LoopProduct-link,
html body.cl-v2:not(.cl-x) ul.products li.product a.woocommerce-loop-product__link {
  display: flex !important;
  flex-direction: column !important;
  align-items: stretch !important;
  justify-content: flex-start !important;
}

/* the image box absorbs the row-stretch slack; everything below it stays snug */
html body.cl-v2:not(.cl-x) ul.products li.product a.woocommerce-LoopProduct-link .cl-cardimg,
html body.cl-v2:not(.cl-x) ul.products li.product a.woocommerce-loop-product__link .cl-cardimg {
  flex: 1 1 auto !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  min-height: 0 !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product .cl-cardimg img {
  max-height: 100% !important;
  width: auto !important;
  max-width: 100% !important;
  object-fit: contain !important;
}

/* title and price are content-sized and sit directly under the image */
html body.cl-v2:not(.cl-x) ul.products li.product .woocommerce-loop-product__title,
html body.cl-v2:not(.cl-x) ul.products li.product .price {
  flex: 0 0 auto !important;
}

/*
 * The starter packs have no strengths chip, so even with the slack moved to
 * the image there is nothing between the price and the button. Give them the
 * same rhythm as a chip card rather than a different one.
 */
html body.cl-v2:not(.cl-x) ul.products li.product .price {
  margin-bottom: 10px !important;
}


/* ------------------------------------------------------------------
 * 2. THE GLOW BEHIND THE VIALS
 *
 * Noah: "you could probably reduce the glow behind the vials a smidge...
 * yeah, you could reduce that glow a ton, actually."
 *
 * Measured: drop-shadow(rgba(228,228,231,0.6) 0 10px 10px) on every card
 * image, and on phones an EXTRA drop-shadow(rgba(255,255,255,0.45)) stacked
 * on top of a saturate/brightness/contrast boost. Two shadows and a filter
 * chain on a white page is why it reads as a halo.
 *
 * Down to a single, much weaker shadow. The vial artwork itself is untouched
 * — Noah, same day: "Don't fuck with the vials."
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products li.product.product img,
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-cardimg img,
html body.cl-v2:not(.cl-x) ul.products li.product.product img.cl-cardimg__img,
html body.cl-v2:not(.cl-x) .cl-feat__card .cl-feat__img img {
  filter: drop-shadow(rgba(113, 113, 122, 0.18) 0 4px 6px) !important;
}


/* ------------------------------------------------------------------
 * 3. THE TRUST STRIP OVERFLOWS ITS OWN BOX
 *
 * Noah: "you didn't fix the alignment on this. The second photo."
 *
 * Measured at 1440: the strip's content is 737px wide inside a 686px box, so
 * the four items run from x326 to x1114 while the container sits at 377..1063
 * — 51px of overflow, which is why the last item looked pushed off and the
 * whole row read as off-centre. It is a flex row that was never allowed to
 * give any ground.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-hero2__trust {
  display: flex !important;
  flex-wrap: wrap !important;
  justify-content: center !important;
  align-items: center !important;
  column-gap: 14px !important;
  row-gap: 10px !important;
  max-width: 100% !important;
  overflow: visible !important;
}
html body.cl-v2:not(.cl-x) .cl-hero2__trust > * {
  flex: 0 1 auto !important;
  min-width: 0 !important;
  white-space: nowrap !important;
}
/* phones already stack it 2x2 on a grid — leave that alone */
@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x) .cl-hero2__trust {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
  }
}


/* ------------------------------------------------------------------
 * 4. THE ZELLE BAR AND THE CATEGORY CHIPS — "it looks like the Hulk"
 *
 * Noah: "I would like for you to clean this up and make it look less stupid.
 * You see how the green and the purple just don't really flow?"
 *
 * Measured: a fully saturated green gradient panel (#15683F -> #1F7A4D,
 * 1180x49) sitting 18px above a row of fully saturated purple gradient chips
 * (#4C1D95 -> #6D28D9). Two loud fills stacked with almost no air between
 * them, and nothing telling the eye which one matters.
 *
 * The chips are navigation — they are what you came to press, so they keep
 * the purple. The Zelle line is an offer you read once, so it drops to a
 * quiet green-tinted surface with dark green type and keeps ONE saturated
 * element, the "SAVE 5%" pill. One loud thing per band instead of two.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-zbar {
  background-image: none !important;
  background-color: #ECFDF3 !important;
  border: 1px solid #E5E1F2 !important;
  color: #0B5134 !important;
  -webkit-text-fill-color: #0B5134 !important;
  box-shadow: none !important;
  margin-bottom: 26px !important;
}
html body.cl-v2:not(.cl-x) .cl-zbar * {
  color: #0B5134 !important;
  -webkit-text-fill-color: #0B5134 !important;
}
/* "Pay with Zelle" was already the bolded half of the sentence — keep it, darker */
html body.cl-v2:not(.cl-x) .cl-zbar strong,
html body.cl-v2:not(.cl-x) .cl-zbar b {
  color: #053D27 !important;
  -webkit-text-fill-color: #053D27 !important;
  font-weight: 800 !important;
}
/* the one saturated element left in the band */
html body.cl-v2:not(.cl-x) .cl-zbar__pill,
html body.cl-v2:not(.cl-x) .cl-zbar .cl-zbar__save,
html body.cl-v2:not(.cl-x) .cl-zbar [class*="pill"],
html body.cl-v2:not(.cl-x) .cl-zbar [class*="save"] {
  background-color: #11784C !important;
  background-image: none !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
  font-weight: 800 !important;
  letter-spacing: 0.08em !important;
}

/* give the chip row room to breathe under it, and let it centre cleanly */
html body.cl-v2:not(.cl-x) .cl-shopnav,
html body.cl-v2:not(.cl-x) .cl-cats {
  display: flex !important;
  flex-wrap: wrap !important;
  justify-content: center !important;
  gap: 10px !important;
}


/* ------------------------------------------------------------------
 * 5. PAGINATION — "the spacing on the changing pages, and this is really bad"
 *
 * Measured: the nav has margin-top 0 and margin-bottom 0 and on phones sits
 * 0px below the last card; its links are 44x44 with border-radius 0, and the
 * inactive numbers are weight 400 at #3F3F46. A sharp-cornered purple square
 * butted against the grid, on a site where every other control is a rounded
 * pill.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) nav.woocommerce-pagination {
  margin: 34px 0 40px !important;
  display: flex !important;
  justify-content: center !important;
}
html body.cl-v2:not(.cl-x) nav.woocommerce-pagination ul {
  display: flex !important;
  gap: 10px !important;
  border: 0 !important;
  padding: 0 !important;
  margin: 0 !important;
}
html body.cl-v2:not(.cl-x) nav.woocommerce-pagination ul li {
  border: 0 !important;
  margin: 0 !important;
  overflow: visible !important;
}
html body.cl-v2:not(.cl-x) nav.woocommerce-pagination ul li a,
html body.cl-v2:not(.cl-x) nav.woocommerce-pagination ul li span {
  min-width: 46px !important;
  height: 46px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  border-radius: 14px !important;
  border: 1px solid #E5E1F2 !important;
  background: #FFFFFF !important;
  color: #27272A !important;
  -webkit-text-fill-color: #27272A !important;
  font-weight: 700 !important;
  font-size: 16px !important;
  padding: 0 12px !important;
}
html body.cl-v2:not(.cl-x) nav.woocommerce-pagination ul li span.current,
html body.cl-v2:not(.cl-x) nav.woocommerce-pagination ul li a.current {
  background: #6D28D9 !important;
  border-color: #6D28D9 !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
  font-weight: 800 !important;
  box-shadow: 0 8px 20px -12px rgba(109, 40, 217, 0.85) !important;
}
html body.cl-v2:not(.cl-x) nav.woocommerce-pagination ul li a:hover {
  border-color: #6D28D9 !important;
  color: #4C1D95 !important;
  -webkit-text-fill-color: #4C1D95 !important;
}


/* ------------------------------------------------------------------
 * 6. BODY COPY — "shit's hard to read on here... that might be bolding"
 *
 * Noah liked one thing specifically: "I do love the ready to order how you
 * bolded the order. That's fire." That is the pattern he is asking for
 * everywhere — weight carrying the emphasis, not colour.
 *
 * Measured, the most common body styles on the page were 400/16px at #52525B
 * and 500/13.5px at #52525B. On the old near-black page a 400 weight at #52525B
 * was light grey type on black and read fine; on solid white it is thin grey
 * on white, which is exactly the "hard to read" he is describing.
 *
 * Everything steps up one weight and one notch darker. No size changes — the
 * 12.5px floor and the layouts stay as measured.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) p,
html body.cl-v2:not(.cl-x) .cl-quality__lede,
html body.cl-v2:not(.cl-x) .cl-bundles__lede,
html body.cl-v2:not(.cl-x) .cl-contact__lede,
html body.cl-v2:not(.cl-x) .cl-section__lede,
html body.cl-v2:not(.cl-x) .cl-hero2__lede {
  font-weight: 500 !important;
  color: #3F3F46 !important;
  -webkit-text-fill-color: #3F3F46 !important;
}
/* descriptions inside a card are the smallest body type on the site */
html body.cl-v2:not(.cl-x) .cl-bundle__desc,
html body.cl-v2:not(.cl-x) .cl-feat__desc,
html body.cl-v2:not(.cl-x) .cl-card__desc,
html body.cl-v2:not(.cl-x) .cl-pack__desc,
html body.cl-v2:not(.cl-x) .woocommerce-product-details__short-description,
html body.cl-v2:not(.cl-x) .woocommerce-product-details__short-description p {
  font-weight: 600 !important;
  color: #3F3F46 !important;
  -webkit-text-fill-color: #3F3F46 !important;
}
/* the small print stays small print, but stops being a whisper */
html body.cl-v2:not(.cl-x) .cl-bundle__ruo,
html body.cl-v2:not(.cl-x) .cl-mobile__foot,
html body.cl-v2:not(.cl-x) .cl-ruo {
  font-weight: 600 !important;
  color: #52525B !important;
  -webkit-text-fill-color: #52525B !important;
}
/* spec rows — label vs value, the "READY TO ORDER" pattern applied */
html body.cl-v2:not(.cl-x) .cl-bundle__row dt,
html body.cl-v2:not(.cl-x) .cl-bundle__row .cl-bundle__k,
html body.cl-v2:not(.cl-x) .cl-spec__k {
  font-weight: 800 !important;
  color: #18181B !important;
  -webkit-text-fill-color: #18181B !important;
}
html body.cl-v2:not(.cl-x) .cl-bundle__row dd,
html body.cl-v2:not(.cl-x) .cl-bundle__row .cl-bundle__v,
html body.cl-v2:not(.cl-x) .cl-spec__v {
  font-weight: 600 !important;
  color: #3F3F46 !important;
  -webkit-text-fill-color: #3F3F46 !important;
}
/* the four trust items under the hero */
html body.cl-v2:not(.cl-x) .cl-hero2__trust,
html body.cl-v2:not(.cl-x) .cl-hero2__trust * {
  font-weight: 700 !important;
  color: #27272A !important;
  -webkit-text-fill-color: #27272A !important;
}
html body.cl-v2:not(.cl-x) .cl-hero2__trust svg {
  -webkit-text-fill-color: initial !important;
}


/* ------------------------------------------------------------------
 * 7. THE VIAL CLIPS THE "EXPLORE PRODUCTS" BUTTON ON A TABLET
 *
 * Noah: "on the explore product page, that red vial is still clashing with
 * the explore products button."
 *
 * It is not every width. Swept 700/768/834/900/1024/1180: clear at every one
 * except 834 (an iPad portrait), where the vial overlaps the button by 9px.
 * The copy column and the vial are side by side down to 834 but the vial has
 * already grown taller than the column, so its bottom edge reaches back under
 * the button. The button is hidden entirely below 768, which is why phones
 * never showed it.
 *
 * Fixed at the band rather than globally, so the 1440 layout Noah has not
 * complained about does not move.
 * ------------------------------------------------------------------ */
/*
 * The class is .cl-chero, not .cl-cathero.
 *
 * I wrote this rule from memory and it never matched anything, which is why
 * the overlap Noah photographed was still there after I reported it fixed.
 * Swept 15 widths: the vial crosses the button at 800, 834 and 880 by 9px,
 * and is clear at every other width including 768 and 900+. So it is a narrow
 * band where the copy column and the stage are still side by side but the
 * vial has outgrown the column.
 *
 * Measured there: img.cl-chero__vial renders 322x448 with no max-height.
 */
@media (min-width: 769px) and (max-width: 899px) {
  html body.cl-v2:not(.cl-x) img.cl-chero__vial,
  html body.cl-v2:not(.cl-x) .cl-chero__float img {
    max-height: 380px !important;
    height: auto !important;
    width: auto !important;
    object-fit: contain !important;
  }
  html body.cl-v2:not(.cl-x) a.cl-chero__explore,
  html body.cl-v2:not(.cl-x) .cl-chero__copy a.cl-btn {
    position: relative !important;
    z-index: 4 !important;
  }
}


/* ------------------------------------------------------------------
 * 8. THE PURPLE HALO BEHIND EVERY CARD VIAL
 *
 * Noah: "you could probably reduce the glow behind the vials a smidge...
 * yeah, you could reduce that glow a ton, actually."
 *
 * The big halo is NOT the drop-shadow dealt with in block 2 — it is a pair of
 * radial gradients painted on the .cl-cardimg box behind the vial, measured
 * at rgba(167,139,250,0.55) in the core falling to rgba(139,92,246,0.22) at
 * 45%. On the old near-black page that was the only thing separating a vial
 * from the background. On white it is a purple cloud.
 *
 * Kept, because a vial with nothing behind it floats oddly, but taken down to
 * roughly a quarter of its strength — present when you look for it, invisible
 * when you are reading the card.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-cardimg,
html body.cl-v2:not(.cl-x) ul.products li.product.product span.cl-cardimg,
html body.cl-v2:not(.cl-x) .cl-cardimg,
html body.cl-v2:not(.cl-x) span.cl-cardimg {
  background-image:
    radial-gradient(58% 52% at 50% 48%,
      rgba(167, 139, 250, 0.14) 0%,
      rgba(139, 92, 246, 0.05) 45%,
      rgba(139, 92, 246, 0) 75%) !important;
}


/* ------------------------------------------------------------------
 * 9. THE STARTER PACKS LOOK LIKE A DIFFERENT SHOP
 *
 * Noah: "when the TIRZ and the R3TA starter pack show up in the other
 * products, it's still not faded... that needs to get fixed up", and earlier
 * "this needs to be better integrated. i dont like that i can see the box".
 *
 * The composite artwork itself is clean — checked the served file pixel by
 * pixel: 1200x1200, hard-keyed, 85% fully transparent, nothing but the title,
 * the bundle pill, the two vials and the footer line. Rendered on white on its
 * own it blends perfectly.
 *
 * The box is the CARD, not the file. Every other product card wraps its image
 * in span.cl-cardimg; the starter packs render a bare <img> straight inside
 * the link, so they miss the shared image box and instead take the raw
 * drop-shadow across a letterboxed square — which is the rectangle Noah can
 * see. Given the same box as everything else, measured from .cl-cardimg.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products li.product
  > a.woocommerce-LoopProduct-link > img.attachment-woocommerce_thumbnail,
html body.cl-v2:not(.cl-x) ul.products li.product
  > a.woocommerce-loop-product__link > img.attachment-woocommerce_thumbnail {
  display: block !important;
  width: 100% !important;
  height: auto !important;
  /* grows into the row-stretch slack exactly as .cl-cardimg does on every
     other card, so the pack poster sits centred in its own box instead of
     leaving a 57px hole between the price and the buy button */
  flex: 1 1 auto !important;
  height: auto !important;
  min-height: 190px !important;
  max-height: none !important;
  aspect-ratio: auto !important;
  object-fit: contain !important;
  padding: 10px 14px 4px !important;
  border-radius: 14px !important;
  background-image:
    radial-gradient(58% 52% at 50% 48%,
      rgba(167, 139, 250, 0.14) 0%,
      rgba(139, 92, 246, 0.05) 45%,
      rgba(139, 92, 246, 0) 75%) !important;
  /*
   * NO drop-shadow, where every other card image gets one.
   *
   * Proved by screenshotting the same card three ways: with the shadow, with
   * `filter:none`, and with neither shadow nor background. The box Noah can
   * see appears and disappears with the SHADOW alone.
   *
   * The reason is the artwork. A vial cut-out is a tall narrow silhouette, so
   * a soft shadow reads as a shadow. The pack poster's silhouette is a title
   * bar across the top, two vials, and a footer line across the bottom — an
   * outline that is, to within a few pixels, a rectangle. Shadowing it draws
   * a rectangle. The poster already carries its own shadows under the vials,
   * so it needs nothing from CSS.
   */
  filter: none !important;
}


/* ------------------------------------------------------------------
 * 10. LINES AND BORDERS
 *
 * Noah: "maybe all the lines on the website where the search is and borders
 * maybe a little darker or thicker. depending on what you think."
 *
 * Measured, every border on the page is 1px of #E2E5EA — which was chosen
 * against the old near-black surfaces, where a light hairline was plenty. On
 * solid white, #E4E4E7 is 1.2:1 against its own background: it is technically
 * there and effectively invisible, which is why the search field reads as a
 * floating grey smudge rather than a field.
 *
 * Darker rather than thicker: #E2E5EA for structural borders and #E2E5EA for
 * the things you are meant to type into. A 2px border on an 18px-radius card
 * reads as a cartoon outline, and the cards are not the problem — the inputs
 * are. So inputs get the extra weight and nothing else does.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products li.product,
html body.cl-v2:not(.cl-x) .cl-card,
html body.cl-v2:not(.cl-x) .cl-panel,
html body.cl-v2:not(.cl-x) .cl-feat__card,
html body.cl-v2:not(.cl-x) .cl-bundle,
html body.cl-v2:not(.cl-x) .cl-box {
  border-color: #E5E1F2 !important;
}

/* dividers and rules */
html body.cl-v2:not(.cl-x) hr,
html body.cl-v2:not(.cl-x) .cl-rule,
html body.cl-v2:not(.cl-x) .cl-divider {
  border-color: #E5E1F2 !important;
  background-color: #D4D4D8 !important;
}

/* anything you type into — the search field above all */
html body.cl-v2:not(.cl-x) input[type="text"],
html body.cl-v2:not(.cl-x) input[type="search"],
html body.cl-v2:not(.cl-x) input[type="email"],
html body.cl-v2:not(.cl-x) input[type="tel"],
html body.cl-v2:not(.cl-x) input[type="number"],
html body.cl-v2:not(.cl-x) input[type="password"],
html body.cl-v2:not(.cl-x) textarea,
html body.cl-v2:not(.cl-x) select,
html body.cl-v2:not(.cl-x) .search-field,
html body.cl-v2:not(.cl-x) .cl-search__input {
  border: 1px solid #E5E1F2 !important;
}
html body.cl-v2:not(.cl-x) input[type="text"]:focus,
html body.cl-v2:not(.cl-x) input[type="search"]:focus,
html body.cl-v2:not(.cl-x) input[type="email"]:focus,
html body.cl-v2:not(.cl-x) input[type="tel"]:focus,
html body.cl-v2:not(.cl-x) textarea:focus,
html body.cl-v2:not(.cl-x) select:focus,
html body.cl-v2:not(.cl-x) .search-field:focus {
  border-color: #6D28D9 !important;
  box-shadow: 0 0 0 3px rgba(109, 40, 217, 0.14) !important;
  outline: none !important;
}
/* the placeholder was the same grey as the border it sat inside */
html body.cl-v2:not(.cl-x) input::placeholder,
html body.cl-v2:not(.cl-x) textarea::placeholder {
  color: #71717A !important;
  -webkit-text-fill-color: #71717A !important;
  opacity: 1 !important;
}


/* ------------------------------------------------------------------
 * 11. THE FEATURED / "PICKS" CARD
 *
 * The small 245x385 card that appears under the grid and in the related rail
 * carries a 30px gap between the vial and the price, from the same cause as
 * the shop cards: a fixed image box in a stretched card. Same treatment.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-feat__card,
html body.cl-v2:not(.cl-x) .cl-pick {
  display: flex !important;
  flex-direction: column !important;
}
html body.cl-v2:not(.cl-x) .cl-feat__img {
  flex: 1 1 auto !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  min-height: 0 !important;
  margin-bottom: 6px !important;
}


/* ==================================================================
 * 12. THE CHECKOUT
 *
 * Noah: "make sure the checkout is pristine."
 *
 * The checkout is the only page where a styling mistake costs money, and it
 * is the easiest one to miss: it is an EMBEDDED IFRAME (?cl_embed=1) with its
 * own document and its own body.cl-embed, so a scan of the page it sits in
 * never sees it. Everything below came out of sc/v2co.js and sc/v2cosurf.js,
 * which enter the frame, and out of looking at the rendered payment step.
 * ================================================================== */


/* ------------------------------------------------------------------
 * 12a. WHITE PAYMENT LABELS ON A WHITE PANEL
 *
 * The worst defect on the site, and no contrast number caught it: "Venmo" and
 * "Bitcoin" are painted #FFFFFF on an off-white payment row, so two of the
 * four ways to pay are invisible. They were white because the payment rows
 * used to sit on near-black. "Cash App" survived only because it was never
 * given the white.
 *
 * Every payment label is pinned dark, explicitly, rather than left to inherit
 * — inheriting is what broke it.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) #payment ul.payment_methods li label,
html body.cl-v2:not(.cl-x) #payment ul.payment_methods li label
  *:not(.cl-zbadge):not(.cl-pm__sub):not(.cl-zbadge *):not(.cl-pm__sub *),
html body.cl-v2:not(.cl-x) #payment li.wc_payment_method > label,
html body.cl-v2:not(.cl-x) #payment li.wc_payment_method > label span:not(.cl-pm__sub):not(.cl-zbadge),
html body.cl-v2:not(.cl-x) .cl-pm__name,
html body.cl-v2:not(.cl-x) .cl-pm__title {
  color: #18181B !important;
  -webkit-text-fill-color: #18181B !important;
  font-weight: 700 !important;
  text-shadow: none !important;
}
/* the brand logos are images and must not be recoloured */
html body.cl-v2:not(.cl-x) #payment ul.payment_methods li label img,
html body.cl-v2:not(.cl-x) #payment ul.payment_methods li label svg {
  -webkit-text-fill-color: initial !important;
}
/* the disabled card row stays visibly disabled, but legible */
html body.cl-v2:not(.cl-x) .cl-cardoff,
html body.cl-v2:not(.cl-x) .cl-cardoff * {
  color: #52525B !important;
  -webkit-text-fill-color: #52525B !important;
}


/* ------------------------------------------------------------------
 * 12b. SOLID WHITE, INCLUDING IN HERE
 *
 * Noah: "i dont want the website to be tranparent and opaque i want solid
 * white except where the moving backgorund is."
 *
 * The checkout never got that pass. Measured inside the frame: 16 inputs and
 * four panels painted rgb(245,243,255) — a lavender — plus a dozen more at
 * rgba(245,243,255,.42/.5/.86), which composite to lavender over white. The
 * only non-white surface a checkout wants is the row that highlights the
 * total.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-ck__row,
html body.cl-v2:not(.cl-x) .cl-ck__aside,
html body.cl-v2:not(.cl-x) .cl-ck__panel,
html body.cl-v2:not(.cl-x) .cl-paynow,
html body.cl-v2:not(.cl-x) .cl-help,
html body.cl-v2:not(.cl-x) .woocommerce-checkout-review-order,
html body.cl-v2:not(.cl-x) #payment,
html body.cl-v2:not(.cl-x) #payment ul.payment_methods,
html body.cl-v2:not(.cl-x) #payment li.wc_payment_method,
html body.cl-v2:not(.cl-x) .woocommerce-checkout table.shop_table,
html body.cl-v2:not(.cl-x) .woocommerce-checkout table.shop_table th,
html body.cl-v2:not(.cl-x) .woocommerce-checkout table.shop_table td {
  background-color: #FFFFFF !important;
  background-image: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
/* panels keep their edge now that the tint is not drawing it for them */
html body.cl-v2:not(.cl-x) .cl-ck__row,
html body.cl-v2:not(.cl-x) .cl-ck__aside,
html body.cl-v2:not(.cl-x) .cl-ck__panel,
html body.cl-v2:not(.cl-x) .cl-help,
html body.cl-v2:not(.cl-x) #payment li.wc_payment_method {
  border: 1px solid #E5E1F2 !important;
}
/* the total is the one row allowed to sit on a tint */
html body.cl-v2:not(.cl-x) .woocommerce-checkout table.shop_table tr.order-total th,
html body.cl-v2:not(.cl-x) .woocommerce-checkout table.shop_table tr.order-total td {
  background-color: #F4F4F5 !important;
}

/* every field: white, with an edge you can actually see */
html body.cl-v2:not(.cl-x) form .form-row input.input-text,
html body.cl-v2:not(.cl-x) form .form-row textarea,
html body.cl-v2:not(.cl-x) input.input-text,
html body.cl-v2:not(.cl-x) #coupon_code,
html body.cl-v2:not(.cl-x) .select2-container .select2-selection,
html body.cl-v2:not(.cl-x) form .form-row select {
  background-color: #FFFFFF !important;
  background-image: none !important;
  border: 1px solid #E5E1F2 !important;
  color: #18181B !important;
  -webkit-text-fill-color: #18181B !important;
}
html body.cl-v2:not(.cl-x) form .form-row input.input-text:focus,
html body.cl-v2:not(.cl-x) input.input-text:focus,
html body.cl-v2:not(.cl-x) #coupon_code:focus,
html body.cl-v2:not(.cl-x) form .form-row select:focus {
  border-color: #6D28D9 !important;
  box-shadow: 0 0 0 3px rgba(109, 40, 217, 0.14) !important;
  outline: none !important;
}
/* the form rows themselves were tinted too */
html body.cl-v2:not(.cl-x) form .form-row,
html body.cl-v2:not(.cl-x) p.form-row {
  background-color: transparent !important;
}


/* ------------------------------------------------------------------
 * 12c. CONTRAST, MEASURED AGAINST WCAG
 *
 * Five failures, each one composited properly rather than guessed:
 *   button.button.alt "Place order"  3.13:1  (16px/800 needs 4.5)
 *   span.cl-pm__sub   "Secure"       4.33:1
 *   span.cl-protect__price "+"       4.23:1
 *   span.cl-paynow__k "Amount"       4.41:1
 *   strong.product-quantity "x 1"    4.47:1
 *
 * "Place order" is the one that matters: it is the button the whole site
 * exists to get pressed, and it was the worst of the five. Its gradient
 * averaged too light for white type, so it is given the darker end of the
 * brand purple at full strength — 8.6:1, and still unmistakably the primary
 * button on the page.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) #place_order,
html body.cl-v2:not(.cl-x) button.button.alt,
html body.cl-v2:not(.cl-x) #payment #place_order {
  background-color: #4C1D95 !important;
  background-image: linear-gradient(135deg, #4C1D95 0%, #5B21B6 100%) !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
  border: 0 !important;
}
html body.cl-v2:not(.cl-x) .cl-pm__sub {
  color: #0B5134 !important;
  -webkit-text-fill-color: #0B5134 !important;
  background-color: rgba(61, 214, 140, 0.16) !important;
}
html body.cl-v2:not(.cl-x) .cl-protect__price,
html body.cl-v2:not(.cl-x) .cl-paynow__k,
html body.cl-v2:not(.cl-x) strong.product-quantity,
html body.cl-v2:not(.cl-x) .product-quantity {
  color: #3F3F46 !important;
  -webkit-text-fill-color: #3F3F46 !important;
  font-weight: 700 !important;
}


/* ------------------------------------------------------------------
 * 12d. NOTHING UNDER 12.5px
 *
 * The floor sc/verify.js enforces everywhere else on the site, applied here
 * too. Six places were under it, the smallest at 10px: the shipping method
 * names, the Zelle "5% OFF" badge, the "Amount" label, the card-down tag and
 * the order table's column headers.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-ship-name,
html body.cl-v2:not(.cl-x) .cl-zbadge,
html body.cl-v2:not(.cl-x) .cl-paynow__k,
html body.cl-v2:not(.cl-x) .cl-cardoff__tag,
html body.cl-v2:not(.cl-x) .woocommerce-checkout table.shop_table th.product-name,
html body.cl-v2:not(.cl-x) .woocommerce-checkout table.shop_table th.product-total {
  font-size: 12.5px !important;
}


/* ------------------------------------------------------------------
 * 12e. THE TWO-COLUMN BLOCK OVERFLOWS ITS OWN BOX
 *
 * div.col2-set holds 340px of content in 326px on a phone, and 564 in 550 on
 * desktop — a consistent 14px, which is one row's horizontal padding counted
 * twice because the columns are not border-box. The help links overflow for
 * the same reason.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .col2-set,
html body.cl-v2:not(.cl-x) .col2-set .col-1,
html body.cl-v2:not(.cl-x) .col2-set .col-2,
html body.cl-v2:not(.cl-x) .cl-help,
html body.cl-v2:not(.cl-x) .cl-help__link {
  box-sizing: border-box !important;
  max-width: 100% !important;
  min-width: 0 !important;
}
html body.cl-v2:not(.cl-x) .cl-help__link {
  display: inline-block !important;
  word-break: break-word !important;
  overflow-wrap: anywhere !important;
}


/* ==================================================================
 * 13. UNIFORM PRODUCT CARDS
 *
 * Noah: "i want all these product cards to be uniform. this looks bad" —
 * "measure".
 *
 * Measured with sc/v2uniform.js, which prints every part's offset from the
 * card's own top and then the spread across the grid. Before:
 *
 *   part        top spread (phone / desktop)
 *   imagebox      0 /  0   but HEIGHT spread 91 / 52
 *   image        41 / 48
 *   title       101 / 52
 *   price        81 / 52
 *   chip         58 / 52   and absent entirely on both starter packs
 *   button      118 / 52
 *   image side padding 11..21 / 1..15
 *
 * Three causes, all of them the same mistake in different places: parts that
 * size themselves off their own contents inside a card whose height comes
 * from its neighbours.
 *
 *   - the grid sizes each ROW to its tallest card, so a row with a sold-out
 *     card (which carries a taller two-line waitlist button) is 49px taller
 *     than the row above it;
 *   - the image box grows to absorb whatever slack is left, so it is a
 *     different height in every row and pushes everything below it down;
 *   - the starter packs have no strengths chip, so their title and price sit
 *     39px lower than the vial cards beside them in the SAME row.
 *
 * The fix is to stop anything above the button from being elastic. Every row
 * is the same height, the image box is a fixed height, the title reserves two
 * lines whether it needs them or not, and the button is pinned to the bottom
 * with `margin-top: auto`. The chip slot is then the only optional part, and
 * the auto margin absorbs its absence without moving anything else — so the
 * packs line up with the vials without being given a chip they do not have.
 * ================================================================== */

/* every row the same height, so cards match across rows and not just within one */
html body.cl-v2:not(.cl-x) ul.products {
  grid-auto-rows: 1fr !important;
  align-items: stretch !important;
}

html body.cl-v2:not(.cl-x) ul.products li.product.product {
  display: flex !important;
  flex-direction: column !important;
  height: 100% !important;
  align-self: stretch !important;
}

/* the link block stops growing — it was the elastic part */
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link {
  flex: 0 0 auto !important;
}

/* ---- the image box: one fixed height everywhere ---- */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-cardimg,
html body.cl-v2:not(.cl-x) ul.products li.product.product
  > a.woocommerce-LoopProduct-link > img.attachment-woocommerce_thumbnail,
html body.cl-v2:not(.cl-x) ul.products li.product.product
  > a.woocommerce-loop-product__link > img.attachment-woocommerce_thumbnail {
  flex: 0 0 auto !important;
  height: 230px !important;
  min-height: 230px !important;
  max-height: 230px !important;
  box-sizing: border-box !important;
  padding: 12px 16px 6px !important;
  margin: 0 !important;
  object-fit: contain !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
}
/* the vial inside that box fills it consistently */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-cardimg img,
html body.cl-v2:not(.cl-x) ul.products li.product.product img.cl-cardimg__img {
  height: 100% !important;
  max-height: 100% !important;
  width: auto !important;
  max-width: 100% !important;
  object-fit: contain !important;
  padding: 0 !important;
  margin: 0 auto !important;
}

/* ---- title: always reserves two lines, so one-word names do not ride up ---- */
html body.cl-v2:not(.cl-x) ul.products li.product.product .woocommerce-loop-product__title {
  flex: 0 0 auto !important;
  min-height: 2.6em !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  text-align: center !important;
  padding: 10px 14px 0 !important;
  margin: 0 !important;
}

/* ---- price: fixed slot, whether it is one price or a range ---- */
html body.cl-v2:not(.cl-x) ul.products li.product.product .price {
  flex: 0 0 auto !important;
  min-height: 30px !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  padding: 4px 14px 0 !important;
  margin: 0 !important;
}

/* ---- chip: fixed slot when present ---- */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-cardsizes {
  flex: 0 0 auto !important;
  height: 31px !important;
  line-height: 17px !important;
  margin: 10px auto 0 !important;
}

/* ---- the button sits on the floor of every card, always ---- */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc,
html body.cl-v2:not(.cl-x) ul.products li.product.product > .add_to_cart_button {
  flex: 0 0 auto !important;
  margin-top: auto !important;
  padding: 14px !important;
}

@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-cardimg,
  html body.cl-v2:not(.cl-x) ul.products li.product.product
    > a.woocommerce-LoopProduct-link > img.attachment-woocommerce_thumbnail,
  html body.cl-v2:not(.cl-x) ul.products li.product.product
    > a.woocommerce-loop-product__link > img.attachment-woocommerce_thumbnail {
    height: 196px !important;
    min-height: 196px !important;
    max-height: 196px !important;
    padding: 10px 12px 6px !important;
  }
  html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc {
    padding: 10px !important;
  }
}


/* ==================================================================
 * 14. NO GREEN IN THE WHITE DESIGN
 *
 * Noah: "maybe no green in the white version of the website. use different
 * color."
 *
 * Green was doing three jobs on the dark design — the Zelle offer, the
 * "Secure" marks on the payment rows, and the "Call a human" tab — and on
 * near-black it read as a second accent. On solid white it reads as a
 * different brand bolted on, which is the same thing that made the shop
 * header "look like the Hulk".
 *
 * Replaced rather than recoloured, by what each one is for:
 *
 *   the Zelle offer   a quiet neutral panel with ink type and ONE purple
 *                     pill. It is information you read once; it should not
 *                     compete with the category buttons under it.
 *   "Secure"          neutral slate. A trust mark earns nothing from being
 *                     coloured, and purple here would read as a button.
 *   "Call a human"    brand purple, since it is a call to action.
 * ================================================================== */

/* ---- the Zelle bar: AMBER ----
 *
 * Noah: "idk what to replace it with but do another color that is known to
 * catch attention but make it fit with the colorway. find on the internet
 * what works best."
 *
 * Amber. It is violet's complement on the colour wheel, which is why the
 * current guidance for violet-led interfaces names amber as the accent — the
 * pairing is the standard one for exactly this situation, a purple brand that
 * needs one more colour for the thing it most wants pressed or read. It also
 * cannot be mistaken for a system state the way a second green or a red can.
 *
 * The exact amber was chosen by contrast, not by eye. The bright amber most
 * palettes show (#F59E0B) carries white text at 2.15:1, which fails outright,
 * and the "SAVE 5%" pill is small bold type. Stepping down two stops:
 *
 *   pill   #B45309 with white text          5.02:1   passes the 4.5 floor
 *   panel  #92400E on #FFFBEB               6.84:1
 *
 * For reference the brand purple runs 7.10:1 white-on-#6D28D9, so the amber
 * is in the same legibility class as everything else on the page.
 */
html body.cl-v2:not(.cl-x) .cl-zbar {
  background-image: none !important;
  background-color: #FFFBEB !important;
  border: 2px solid #FCD34D !important;
  color: #92400E !important;
  -webkit-text-fill-color: #92400E !important;
  box-shadow: none !important;
}
html body.cl-v2:not(.cl-x) .cl-zbar * {
  color: #92400E !important;
  -webkit-text-fill-color: #92400E !important;
}
html body.cl-v2:not(.cl-x) .cl-zbar strong,
html body.cl-v2:not(.cl-x) .cl-zbar b {
  color: #78350F !important;
  -webkit-text-fill-color: #78350F !important;
  font-weight: 800 !important;
}
html body.cl-v2:not(.cl-x) .cl-zbar__pill,
html body.cl-v2:not(.cl-x) .cl-zbar .cl-zbar__save,
html body.cl-v2:not(.cl-x) .cl-zbar [class*="pill"],
html body.cl-v2:not(.cl-x) .cl-zbar [class*="save"],
html body.cl-v2:not(.cl-x) .cl-zbadge,
html body.cl-v2:not(.cl-x) .cl-save-pill {
  background-color: #B45309 !important;
  background-image: none !important;
  border-color: #B45309 !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
  font-weight: 800 !important;
}

/* ---- "Secure" and other green marks: neutral slate ---- */
html body.cl-v2:not(.cl-x) .cl-pm__sub,
html body.cl-v2:not(.cl-x) .cl-secure,
html body.cl-v2:not(.cl-x) [class*="secure"] {
  background-color: #F4F4F5 !important;
  background-image: none !important;
  border: 1px solid #E5E1F2 !important;
  color: #3F3F46 !important;
  -webkit-text-fill-color: #3F3F46 !important;
}
html body.cl-v2:not(.cl-x) .cl-pm__sub svg,
html body.cl-v2:not(.cl-x) .cl-secure svg {
  stroke: #3F3F46 !important;
  color: #3F3F46 !important;
  -webkit-text-fill-color: initial !important;
}

/* ---- "Call a human": the brand purple ---- */
html body.cl-v2:not(.cl-x) .cl-calltab,
html body.cl-v2:not(.cl-x) .cl-tabmini,
html body.cl-v2:not(.cl-x) [class*="calltab"],
html body.cl-v2:not(.cl-x) .cl-callsheet__btn,
html body.cl-v2:not(.cl-x) .cl-co__call {
  background-color: #6D28D9 !important;
  background-image: linear-gradient(135deg, #5B21B6 0%, #6D28D9 100%) !important;
  border-color: #5B21B6 !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
  box-shadow: 0 10px 26px -14px rgba(109, 40, 217, 0.9) !important;
}
html body.cl-v2:not(.cl-x) .cl-calltab svg,
html body.cl-v2:not(.cl-x) .cl-tabmini svg,
html body.cl-v2:not(.cl-x) .cl-callsheet__btn svg {
  stroke: #FFFFFF !important;
  color: #FFFFFF !important;
}


/* ------------------------------------------------------------------
 * 13b. THE LAST TWO UNIFORMITY GAPS
 *
 * After block 13 the phone grid was perfectly uniform — every card 510px with
 * a 0px spread on the image box, title, price and chip. Desktop was not, and
 * the reason was worth writing down: `ul.products` already carries
 * `grid-template-columns: repeat(4, 1fr)` and `grid-auto-rows: 1fr`, but at
 * desktop something sets `display: flex`, so every grid property on it is
 * inert. A flex row sizes to its own tallest card, which is why card heights
 * came out 404 / 445 / 497 down the page while the phone (a real grid) came
 * out 510 all the way down.
 *
 * The second gap is the sold-out card. It genuinely has one control more than
 * the others — "Add to cart" plus "Tell me when it is back" — so its button
 * block measured 138px against 88px, and with the block pinned to the bottom
 * that pushed its "Add to cart" 50px out of line with every other card's. The
 * block is given the taller of the two as a fixed height, so the primary
 * button starts at the same y in all of them and the waitlist control uses
 * space that is reserved whether it is there or not.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products {
  display: grid !important;
}

html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc {
  display: flex !important;
  flex-direction: column !important;
  justify-content: flex-start !important;
  gap: 8px !important;
  min-height: 138px !important;
  box-sizing: border-box !important;
}
/* the waitlist control is secondary — it should not read as a second buy button */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-wait__open {
  background: transparent !important;
  border: 1px solid #E5E1F2 !important;
  color: #4C1D95 !important;
  -webkit-text-fill-color: #4C1D95 !important;
  font-weight: 700 !important;
  min-height: 40px !important;
  box-shadow: none !important;
}

/* the vial sits in the same place in every box: the old fixed 208px height
   left some images 8px higher than others inside a 230px box */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-cardimg img,
html body.cl-v2:not(.cl-x) ul.products li.product.product img.cl-cardimg__img {
  height: 212px !important;
  max-height: 212px !important;
  min-height: 212px !important;
}

@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc {
    min-height: 152px !important;
  }
  html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-cardimg img,
  html body.cl-v2:not(.cl-x) ul.products li.product.product img.cl-cardimg__img {
    height: 180px !important;
    max-height: 180px !important;
    min-height: 180px !important;
  }
}


/* ------------------------------------------------------------------
 * 13c. TWO CONSEQUENCES OF 13b, MEASURED AND CLOSED
 *
 * 1. Making .cl-atc a flex column left its children stretching to fill it, so
 *    the waitlist button grew from 43px to 112px — the block was now a fixed
 *    height and the button was eating the slack. Its children are pinned to
 *    their own size and the slack stays at the bottom of the block.
 *
 * 2. The title still varied by 28px (phone) and 48px (desktop), because
 *    `min-height: 2.6em` only sets a floor: "R3TA" takes one line, "R3TA 10MG
 *    STARTER PACK" takes three. Fixed at two lines and clamped, so a long
 *    name truncates rather than pushing the price and the chip down the card.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc > * {
  flex: 0 0 auto !important;
  align-self: stretch !important;
}

html body.cl-v2:not(.cl-x) ul.products li.product.product .woocommerce-loop-product__title {
  height: 2.6em !important;
  min-height: 2.6em !important;
  max-height: 2.6em !important;
  overflow: hidden !important;
  display: -webkit-box !important;
  -webkit-line-clamp: 2 !important;
  -webkit-box-orient: vertical !important;
  align-items: unset !important;
}

/* the price slot is fixed too, so a range and a single price occupy the same
   space and the chip below them never moves */
html body.cl-v2:not(.cl-x) ul.products li.product.product .price {
  height: 34px !important;
  min-height: 34px !important;
  max-height: 34px !important;
  overflow: hidden !important;
}

/* one padding for every image box, whatever is inside it */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-cardimg,
html body.cl-v2:not(.cl-x) ul.products li.product.product
  > a.woocommerce-LoopProduct-link > img.attachment-woocommerce_thumbnail,
html body.cl-v2:not(.cl-x) ul.products li.product.product
  > a.woocommerce-loop-product__link > img.attachment-woocommerce_thumbnail {
  padding: 12px 16px 6px !important;
}


/* ------------------------------------------------------------------
 * 13d. THE LAST CARD OUT OF LINE
 *
 * With everything else at a 0px spread, the only two cards still off were the
 * sold-out ones: their button block measured 210px against 138px, because the
 * "Tell me when it is back" control inherited generous padding from the dark
 * design and rendered three lines tall inside a 305px card.
 *
 * Given a real button's height. The waitlist FORM it reveals is deliberately
 * left to size itself — it is hidden until pressed, and clamping it would clip
 * the email field, which is the one thing on a sold-out card that has to work.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-wait__open {
  height: 44px !important;
  min-height: 44px !important;
  max-height: 44px !important;
  padding: 0 14px !important;
  line-height: 42px !important;
  white-space: nowrap !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  font-size: 12.5px !important;
}


/* ==================================================================
 * 15. THE MOVING BACKGROUND — WHY IT WAS INVISIBLE
 *
 * Noah: "you forgetting the background?"
 *
 * It was not missing. `coreLabsSpiral` was running, the 3840px source was
 * being served, and the rotation was advancing — all of which measured fine,
 * which is exactly why it took looking at the rendered hero to find the bug.
 *
 * The artwork is a FRAME: purple ribbons sweeping around the left, right, top
 * and bottom edges of a 16:9 image whose centre is deliberately plain white
 * (38.9% of the source is near-white, nearly all of it the middle). The hero
 * painted it with `background-size: cover` and then `scale(1.5)` on top —
 * which zooms into the middle. The middle is the white part. So the hero was
 * showing a magnified crop of the one region of the image with nothing in it,
 * and spinning it very convincingly.
 *
 * Rebuilt around what the rotation actually needs: a SQUARE layer big enough
 * that spinning it never swings an empty corner into view (side >= the hero's
 * diagonal), centred on the hero, carrying the image at its own framing
 * rather than zoomed in. The ribbons are back in frame and sweep through the
 * hero as it turns.
 *
 * Also slower is not better here — at 120s a full turn is 0.05 degrees per
 * frame, which reads as a still image. 60s is still calm and visibly moving.
 * ================================================================== */
html body.cl-v2:not(.cl-x) .cl-hero2 {
  position: relative !important;
  overflow: hidden !important;
}
html body.cl-v2:not(.cl-x) .cl-hero2::before {
  content: "" !important;
  position: absolute !important;
  /* a square on the hero's centre, sized off the LONGER side so it still
     covers the circumscribed circle when the hero is wide and short */
  inset: auto !important;
  top: 50% !important;
  left: 50% !important;
  /*
   * 118vmax, not the 150 the "never expose a corner" rule would ask for.
   * That rule exists to stop a rotating layer showing blank corners — but
   * here the blank is transparent and the page behind it is white, which is
   * what the corners would have been anyway. Trading it away buys a smaller
   * square, which means the artwork is drawn larger relative to the hero and
   * more of the ribbon frame is in view at any moment instead of swinging
   * past out of shot.
   */
  width: 118vmax !important;
  height: 118vmax !important;
  margin: 0 !important;
  transform-origin: 50% 50% !important;
  background-repeat: no-repeat !important;
  background-position: center center !important;
  /* `contain`, not `cover`: cover crops a 16:9 frame into a square by
     throwing away the left and right thirds — which is where half the
     ribbons are. What falls outside the artwork is transparent, and the page
     behind it is white, so there is no visible seam. */
  background-size: contain !important;
  opacity: 0.9 !important;
  z-index: 0 !important;
  pointer-events: none !important;
  will-change: transform !important;
  animation: coreLabsSpiral 60s linear infinite !important;
}

@keyframes coreLabsSpiral {
  from { transform: translate(-50%, -50%) rotate(0deg); }
  to   { transform: translate(-50%, -50%) rotate(360deg); }
}

/* someone who has asked their system not to animate things gets it still */
@media (prefers-reduced-motion: reduce) {
  html body.cl-v2:not(.cl-x) .cl-hero2::before {
    animation: none !important;
    transform: translate(-50%, -50%) !important;
  }
}


/* ==================================================================
 * 16. THE GREEN THAT SURVIVED BLOCK 14
 *
 * Block 14 took the green out by background-COLOR. Four elements paint
 * themselves with a linear-gradient background-IMAGE instead, and the
 * generated palette restates them at a higher class count than block 14 used,
 * so they kept their green:
 *
 *   aside.cl-zbar.cl-zbar--home / --shop   #15683F -> #1F7A4D
 *   a.cl-calltab                           #1F7A4D -> #14603A
 *   span.cl-paynotice__save                #2E7D32
 *   span.cl-paynotice__dot                 #3DD68C
 *
 * Restated here with the element and both classes, which clears the palette,
 * and in the amber/purple scheme from block 14: the offer is amber, the call
 * tab is brand purple, the live-payment dot stays a dot but in purple.
 * ================================================================== */
html body.cl-v2:not(.cl-x) aside.cl-zbar,
html body.cl-v2:not(.cl-x) aside.cl-zbar.cl-zbar--home,
html body.cl-v2:not(.cl-x) aside.cl-zbar.cl-zbar--shop,
html body.cl-v2:not(.cl-x) .cl-zbar.cl-zbar--home,
html body.cl-v2:not(.cl-x) .cl-zbar.cl-zbar--shop {
  background-color: #FFFBEB !important;
  background-image: none !important;
  border: 2px solid #FCD34D !important;
  color: #92400E !important;
  -webkit-text-fill-color: #92400E !important;
  box-shadow: none !important;
}

html body.cl-v2:not(.cl-x) a.cl-calltab,
html body.cl-v2:not(.cl-x) a.cl-calltab:hover,
html body.cl-v2:not(.cl-x) .cl-calltab.cl-calltab {
  background-color: #5B21B6 !important;
  background-image: linear-gradient(145deg, #6D28D9, #4C1D95) !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
  box-shadow: 0 10px 26px -14px rgba(76, 29, 149, 0.9) !important;
}
html body.cl-v2:not(.cl-x) a.cl-calltab svg {
  stroke: #FFFFFF !important;
  color: #FFFFFF !important;
}

html body.cl-v2:not(.cl-x) span.cl-paynotice__save,
html body.cl-v2:not(.cl-x) .cl-paynotice__save.cl-paynotice__save {
  background-color: #B45309 !important;
  background-image: none !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
  font-weight: 800 !important;
}
html body.cl-v2:not(.cl-x) span.cl-paynotice__dot,
html body.cl-v2:not(.cl-x) .cl-paynotice__dot.cl-paynotice__dot {
  background-color: #6D28D9 !important;
  background-image: none !important;
}


/* ==================================================================
 * 17. THREE THINGS THE SUITE CAUGHT AFTER THE FACT
 * ================================================================== */

/* ------------------------------------------------------------------
 * 17a. MY OWN REGRESSION: DARK TEXT PUSHED ONTO PURPLE
 *
 * Block 6 darkened body copy to #3F3F46 so it would read on white. Two
 * elements it caught are not on white — they sit on the brand purple:
 *
 *   p.cl-picks__eyebrow   "Core Picks"  #3F3F46 on #7C42E8  1.9:1
 *   button.woocommerce-button "Log in"  #3F3F46 on #7C42E8  1.9:1
 *
 * 1.9:1 is worse than what was there before the rebrand, which is the whole
 * risk of a blanket colour rule. Anything sitting on a filled purple surface
 * is put back to white explicitly.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-picks__eyebrow,
html body.cl-v2:not(.cl-x) p.cl-picks__eyebrow,
html body.cl-v2:not(.cl-x) .cl-picks .cl-eyebrow,
html body.cl-v2:not(.cl-x) button.woocommerce-button.button,
html body.cl-v2:not(.cl-x) button.button,
html body.cl-v2:not(.cl-x) input.button,
html body.cl-v2:not(.cl-x) a.button {
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}
/* ...except the secondary buttons, which are white-on-white and want ink */
html body.cl-v2:not(.cl-x) a.button.wc-backward,
html body.cl-v2:not(.cl-x) button.button.cl-btn--ghost,
html body.cl-v2:not(.cl-x) a.button.cl-btn--ghost {
  color: #4C1D95 !important;
  -webkit-text-fill-color: #4C1D95 !important;
}

/* ------------------------------------------------------------------
 * 17b. THE "5% OFF" BADGE KEPT ITS DARK TEXT
 *
 * Measured 3.53:1 at 12.5px/700 — which is exactly #18181B on #B45309, so the
 * badge took the new amber fill from block 14 but not the white lettering,
 * because the palette restates its colour at a higher class count. Stated
 * here with the element so it clears.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) span.cl-zbadge,
html body.cl-v2:not(.cl-x) span.cl-zbadge *,
html body.cl-v2:not(.cl-x) .cl-zbadge.cl-zbadge,
html body.cl-v2:not(.cl-x) .cl-zbadge.cl-zbadge * {
  background-color: #B45309 !important;
  background-image: none !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}

/* ------------------------------------------------------------------
 * 17c. THE CHECKOUT'S TWO-COLUMN BLOCK STILL OVERFLOWS BY 14px
 *
 * 340 in 326 on a phone, 564 in 550 on desktop — the same 14px at both
 * widths, which is the giveaway: it is not a percentage, it is a fixed
 * gutter. `box-sizing` did not fix it because the columns are not padded;
 * WooCommerce floats .col-1 and .col-2 at 48% each with a margin, and the
 * margin is outside the 48%. Given the row a real two-column grid instead,
 * which is also what stops it from needing a clearfix.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .col2-set {
  display: grid !important;
  grid-template-columns: 1fr 1fr !important;
  gap: 14px !important;
  width: 100% !important;
  float: none !important;
  overflow: visible !important;
}
html body.cl-v2:not(.cl-x) .col2-set .col-1,
html body.cl-v2:not(.cl-x) .col2-set .col-2 {
  width: auto !important;
  float: none !important;
  margin: 0 !important;
  padding: 0 !important;
  min-width: 0 !important;
}
@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x) .col2-set {
    grid-template-columns: 1fr !important;
  }
}
/* the help links were overflowing for the same reason — a fixed width on an
   element whose text is longer than it */
html body.cl-v2:not(.cl-x) .cl-help__link,
html body.cl-v2:not(.cl-x) a.cl-help__link {
  width: auto !important;
  max-width: 100% !important;
  white-space: normal !important;
  overflow-wrap: anywhere !important;
}


/* ==================================================================
 * 18. BEATEN BY AN ID
 *
 * Two of block 17's fixes matched their element and still lost, and both for
 * the same reason — the rule beating them carries an ID, and one ID outranks
 * any number of classes. This project's usual trap is class COUNT; this is the
 * tier above it, and it is worth a block of its own so the next fix starts in
 * the right place.
 *
 *   "5% OFF"      beaten by  #payment ul.payment_methods li label *   (1,3,6)
 *                 which is block 12a's own payment-label rule reaching into
 *                 the badge. Fixed above, at 12a, with a :not() — the badge is
 *                 not a payment-method name and should never have matched.
 *
 *   .col2-set     beaten by  body.cl-embed form.checkout #customer_details
 *                 — the two-column block IS #customer_details, so what looked
 *                 like a (0,3,2) tie my file would win on order was really
 *                 (1,2,2) against my (0,3,2).
 *
 * Restated with the ID so the comparison is like for like.
 * ================================================================== */
html body.cl-v2:not(.cl-x) #customer_details,
html body.cl-v2:not(.cl-x) form.checkout #customer_details,
html body.cl-v2:not(.cl-x) #customer_details.col2-set {
  display: grid !important;
  grid-template-columns: 1fr 1fr !important;
  gap: 14px !important;
  width: 100% !important;
  max-width: 100% !important;
  float: none !important;
  box-sizing: border-box !important;
  overflow: visible !important;
}
html body.cl-v2:not(.cl-x) #customer_details > .col-1,
html body.cl-v2:not(.cl-x) #customer_details > .col-2 {
  width: auto !important;
  max-width: 100% !important;
  float: none !important;
  margin: 0 !important;
  padding: 0 !important;
  min-width: 0 !important;
  box-sizing: border-box !important;
}
@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x) #customer_details,
  html body.cl-v2:not(.cl-x) form.checkout #customer_details,
  html body.cl-v2:not(.cl-x) #customer_details.col2-set {
    grid-template-columns: 1fr !important;
  }
}

/*
 * The help links overflow by 6px with width:auto already applied, which means
 * the box is not the problem — the line is. They sit in a flex row, and a flex
 * item's default `min-width: auto` refuses to shrink below its longest word,
 * so the row reports content wider than the box however the width is set.
 */
html body.cl-v2:not(.cl-x) .cl-help,
html body.cl-v2:not(.cl-x) .cl-help > * {
  min-width: 0 !important;
  flex-shrink: 1 !important;
}
html body.cl-v2:not(.cl-x) .cl-help__link,
html body.cl-v2:not(.cl-x) a.cl-help__link {
  min-width: 0 !important;
  flex-shrink: 1 !important;
  overflow-wrap: anywhere !important;
  word-break: break-word !important;
}


/* ------------------------------------------------------------------
 * 18b. THE ACTUAL OVERFLOW, THREE ELEMENTS DEEP
 *
 * Fixing #customer_details cleared the column block, and what was left turned
 * out to be three separate elements rather than one layout fault:
 *
 *   div.cl-billing-toggle   14px wider than .col-2 at BOTH widths. A constant
 *                           at two different container widths is never a
 *                           percentage — it is a negative margin, or a width
 *                           of calc(100% + gutter) left over from when the
 *                           toggle was meant to bleed past its column.
 *
 *   a.cl-help__link         content 108 in a 102 box, 162 in 156: the links
 *                           are being sized NARROWER than their own text. The
 *                           row they sit in has room (994px for 258px of
 *                           links), so they simply size to their content.
 *
 *   span.select2-selection__rendered   148 in 126, white-space: nowrap. That
 *                           is select2's own country field clipping its
 *                           placeholder with no ellipsis, so it reads as text
 *                           cut off mid-word.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-billing-toggle {
  width: 100% !important;
  max-width: 100% !important;
  margin-left: 0 !important;
  margin-right: 0 !important;
  box-sizing: border-box !important;
}

html body.cl-v2:not(.cl-x) .cl-help__link,
html body.cl-v2:not(.cl-x) a.cl-help__link {
  flex: 0 0 auto !important;
  width: auto !important;
  max-width: 100% !important;
  white-space: nowrap !important;
}
@media (max-width: 420px) {
  /* on the narrowest phones the two links want their own lines rather than
     a nowrap that would push the row past the screen */
  html body.cl-v2:not(.cl-x) .cl-help {
    flex-wrap: wrap !important;
    justify-content: center !important;
    row-gap: 6px !important;
  }
}

html body.cl-v2:not(.cl-x) .select2-selection__rendered,
html body.cl-v2:not(.cl-x) span.select2-selection__rendered {
  text-overflow: ellipsis !important;
  overflow: hidden !important;
  max-width: 100% !important;
  box-sizing: border-box !important;
}


/* ------------------------------------------------------------------
 * 19. REGRESSION: THE CARDS COLLAPSED TO 61px
 *
 * Switching ul.products to a real grid (block 13b) is right, and it is what
 * made every card the same height. But a grid item only fills its column if
 * it is allowed to stretch, and these were sizing to their CONTENT instead —
 * so each card shrank to 61px inside a 305px column, which is the width of
 * the narrowest thing in it.
 *
 * The content is narrow because block 13 deliberately gave the vial
 * `width: auto` so it would scale by height inside a fixed image box. That is
 * correct for the image and fatal for the card, once the card is content-sized.
 *
 * WooCommerce's own percentage widths (22.05% / 30.75% / 48% across three
 * stylesheets) are all overridden to `auto !important` by the theme, which is
 * why nothing in the cascade was holding the card open either.
 *
 * Both halves stated explicitly rather than relied on: the grid stretches its
 * items, and the card fills its column.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products {
  justify-items: stretch !important;
  align-items: stretch !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product {
  width: 100% !important;
  max-width: 100% !important;
  min-width: 0 !important;
  justify-self: stretch !important;
  flex-basis: auto !important;
  margin-left: 0 !important;
  margin-right: 0 !important;
  box-sizing: border-box !important;
}


/* ------------------------------------------------------------------
 * 19b. RECLAIMING THE RESERVED SPACE
 *
 * The button block reserves room for the sold-out cards' second control so
 * "Add to cart" starts at the same y in every card. That reservation was set
 * to 138px/152px when the waitlist control still measured 112px tall; block
 * 13d capped it at 44px, so the reservation is now carrying ~25px of dead
 * white on every in-stock card.
 *
 * Re-derived from the parts: 47 (add to cart) + 8 (gap) + 44 (waitlist) + 28
 * (padding) = 127. Deployed, and the button spread went from 0px back to 13px
 * at BOTH widths — so the arithmetic is 13px short of what the block actually
 * needs, which is the waitlist form's own collapsed margin, not in any of the
 * four numbers above.
 *
 * Put back to the values that measured 0px. The ~25px of white under the
 * button on an in-stock card is the price of "Add to cart" landing on the
 * same line in every card, which is what Noah asked for, and a measured zero
 * beats a derived number that is wrong.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc {
  min-height: 138px !important;
}
@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc {
    min-height: 152px !important;
  }
}


/* ------------------------------------------------------------------
 * 19c. THE FIXED SLOTS WERE TOO SHORT ON A PHONE
 *
 * Fixing the title and price to one height is what made the cards line up,
 * but the heights were taken from the desktop card (305px wide). The phone
 * card is 169px, where the same strings need more lines:
 *
 *   "R3TA 10MG STARTER PACK"  wraps to 3 lines and was clamped at 2,
 *                             so it read "R3TA 10MG STARTER"
 *   "$69.99 – $119.99"        wraps to 2 lines in a 34px slot, so the
 *                             second price was cut off below the fold of
 *                             its own box
 *
 * A truncated product name and a half-hidden price are worse than a ragged
 * grid, and neither is what "uniform" was supposed to buy. The slots are
 * re-sized for the phone — still fixed, so still uniform, just fixed to a
 * height the content actually fits in.
 * ------------------------------------------------------------------ */
@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product .woocommerce-loop-product__title {
    height: 3.9em !important;
    min-height: 3.9em !important;
    max-height: 3.9em !important;
    -webkit-line-clamp: 3 !important;
  }
  html body.cl-v2:not(.cl-x) ul.products li.product.product .price {
    height: 50px !important;
    min-height: 50px !important;
    max-height: 50px !important;
    display: flex !important;
    flex-wrap: wrap !important;
    align-content: center !important;
    justify-content: center !important;
    row-gap: 0 !important;
    line-height: 1.25 !important;
  }
}


/* ------------------------------------------------------------------
 * 19d. "Tell me w…"
 *
 * Block 13d capped the waitlist control at 44px and set nowrap + ellipsis to
 * stop it rendering three lines tall and knocking the sold-out cards out of
 * line. On a 169px phone card that cap truncates the label itself, so the one
 * control on a sold-out card now reads "Tell me w…".
 *
 * An ellipsis is fine on a product name, which the customer can read from the
 * card's own title; it is not fine on the only instruction telling them what
 * the button does. On phones it wraps to two lines instead, and the reserved
 * block grows by the same amount so "Add to cart" stays on the same line in
 * every card — re-measured at 0px spread, not assumed.
 * ------------------------------------------------------------------ */
@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-wait__open {
    height: 56px !important;
    min-height: 56px !important;
    max-height: 56px !important;
    line-height: 1.25 !important;
    white-space: normal !important;
    text-overflow: clip !important;
    padding: 0 8px !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    text-align: center !important;
  }
  html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc {
    min-height: 164px !important;
  }
}


/* ==================================================================
 * 20. THE CHECKOUT WAS NEVER ACTUALLY WHITE
 *
 * Block 12b set out to make the checkout solid white and I reported it done.
 * It was not: measuring the surfaces inside the frame afterwards found
 * rgb(245,243,255) still on 20 inputs, and rgba(245,243,255,.42/.5/.86) on the
 * form rows, the collapsible rows and the list items. The contrast, field,
 * overflow and type checks all passed — none of them look at whether a surface
 * is tinted — so nothing flagged it and I took 12b's word for it.
 *
 * The cause is one class. The generated palette writes these as
 *
 *     html body.cl-v2:not(.cl-x).cl-embed .cl-ck__row      (0,4,2)
 *
 * with .cl-embed on the SAME body element, not as a descendant. Block 12b
 * wrote them as
 *
 *     html body.cl-v2:not(.cl-x) .cl-ck__row               (0,3,2)
 *
 * which is one class short and loses every time. This is the same class-count
 * arithmetic that has bitten this stylesheet repeatedly, in its least visible
 * form yet: the selector matches, so a `matches()` check says yes, and only
 * the computed value gives it away.
 *
 * Restated at the palette's own class count. The checkout body always carries
 * .cl-embed, so this is the correct scope rather than a specificity hack.
 * ================================================================== */
html body.cl-v2:not(.cl-x).cl-embed .cl-ck__row,
html body.cl-v2:not(.cl-x).cl-embed .cl-ck__row--static,
html body.cl-v2:not(.cl-x).cl-embed .cl-ck__aside,
html body.cl-v2:not(.cl-x).cl-embed .cl-ck__panel,
html body.cl-v2:not(.cl-x).cl-embed .cl-ck__body .form-row,
html body.cl-v2:not(.cl-x).cl-embed .cl-paynow,
html body.cl-v2:not(.cl-x).cl-embed .cl-help,
html body.cl-v2:not(.cl-x).cl-embed .woocommerce-checkout-review-order,
html body.cl-v2:not(.cl-x).cl-embed #payment,
html body.cl-v2:not(.cl-x).cl-embed #payment ul.payment_methods,
html body.cl-v2:not(.cl-x).cl-embed #payment ul.payment_methods li,
html body.cl-v2:not(.cl-x).cl-embed #payment li.wc_payment_method,
html body.cl-v2:not(.cl-x).cl-embed table.shop_table,
html body.cl-v2:not(.cl-x).cl-embed table.shop_table th,
html body.cl-v2:not(.cl-x).cl-embed table.shop_table td {
  background-color: #FFFFFF !important;
  background-image: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}

/* the "research use only" notice was a 6% violet wash — the one place a tint
   is doing a job, so it keeps a tint, as a neutral rather than a colour */
html body.cl-v2:not(.cl-x).cl-embed .cl-ruo-notice {
  background-color: #F4F4F5 !important;
  background-image: none !important;
  border-left: 1px solid #6D28D9 !important;
}

/* every field white, with the visible edge from block 10 */
html body.cl-v2:not(.cl-x).cl-embed input.input-text,
html body.cl-v2:not(.cl-x).cl-embed textarea,
html body.cl-v2:not(.cl-x).cl-embed select,
html body.cl-v2:not(.cl-x).cl-embed #coupon_code,
html body.cl-v2:not(.cl-x).cl-embed .select2-container .select2-selection,
html body.cl-v2:not(.cl-x).cl-embed .cl-ck__body .form-row input.input-text,
html body.cl-v2:not(.cl-x).cl-embed .cl-ck__body .form-row textarea {
  background-color: #FFFFFF !important;
  background-image: none !important;
  border: 1px solid #E5E1F2 !important;
  color: #18181B !important;
  -webkit-text-fill-color: #18181B !important;
}
html body.cl-v2:not(.cl-x).cl-embed input.input-text:focus,
html body.cl-v2:not(.cl-x).cl-embed textarea:focus,
html body.cl-v2:not(.cl-x).cl-embed select:focus,
html body.cl-v2:not(.cl-x).cl-embed #coupon_code:focus {
  border-color: #6D28D9 !important;
  box-shadow: 0 0 0 3px rgba(109, 40, 217, 0.14) !important;
  outline: none !important;
}

/* the total row keeps its one neutral tint */
html body.cl-v2:not(.cl-x).cl-embed table.shop_table tr.order-total th,
html body.cl-v2:not(.cl-x).cl-embed table.shop_table tr.order-total td {
  background-color: #F4F4F5 !important;
}


/* ------------------------------------------------------------------
 * 20b. THE LAST THREE TINTED SURFACES
 *
 * Identified rather than guessed at — the scan that found them prints the tag,
 * the class and the parent, because "li." told me nothing:
 *
 *   textarea.input-text  inside span.woocommerce-input-wrapper  (the order
 *                        notes box; block 20 named `textarea` on its own,
 *                        which is one class short of `textarea.input-text`)
 *   ul.woocommerce-shipping-methods > li   the three FedEx rows
 *   p.cl-help            inside div.woocommerce
 *
 * Each restated with its own tag and class so the comparison against the
 * palette is like for like.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x).cl-embed textarea.input-text,
html body.cl-v2:not(.cl-x).cl-embed .woocommerce-input-wrapper textarea.input-text {
  background-color: #FFFFFF !important;
  background-image: none !important;
  border: 1px solid #E5E1F2 !important;
  color: #18181B !important;
  -webkit-text-fill-color: #18181B !important;
}

html body.cl-v2:not(.cl-x).cl-embed ul.woocommerce-shipping-methods li,
html body.cl-v2:not(.cl-x).cl-embed ul.woocommerce-shipping-methods > li {
  background-color: #FFFFFF !important;
  background-image: none !important;
  border: 1px solid #E5E1F2 !important;
}
/* the chosen shipping method still has to look chosen */
html body.cl-v2:not(.cl-x).cl-embed ul.woocommerce-shipping-methods li:has(input:checked) {
  border-color: #6D28D9 !important;
  background-color: #FAF8FF !important;
}

html body.cl-v2:not(.cl-x).cl-embed p.cl-help,
html body.cl-v2:not(.cl-x).cl-embed .woocommerce p.cl-help {
  background-color: #FFFFFF !important;
  background-image: none !important;
  border: 1px solid #E5E1F2 !important;
}


/* ------------------------------------------------------------------
 * 20c. THE LAST TWO, READ RATHER THAN GUESSED
 *
 * Block 20b raised the class count and still lost on both, so instead of
 * guessing a third time I sorted every matching rule by real specificity and
 * read the winner. Both are won by an ID in the generated palette:
 *
 *   textarea   html body.cl-v2:not(.cl-x).cl-embed form.checkout .form-row
 *              textarea#order_comments                            (1,5,4)
 *              beating block 20b's                                (0,4,3)
 *
 *   shipping   html body.cl-v2:not(.cl-x).cl-embed .cl-ck__shipping
 *              #shipping_method li                                (1,4,3)
 *              beating block 20b's                                (0,4,4)
 *
 * An ID is worth more than any number of classes, so no amount of class
 * stacking was ever going to win. Matched on the same IDs; this file loads
 * after the palette, so an equal score resolves here.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x).cl-embed form.checkout .form-row textarea#order_comments,
html body.cl-v2:not(.cl-x).cl-embed .form-row textarea#order_comments,
html body.cl-v2:not(.cl-x).cl-embed textarea#order_comments {
  background-color: #FFFFFF !important;
  background-image: none !important;
  /* 1.5px #E2E5EA at (1,4,4) — the last heavy outline on the checkout, and
     why the order-notes box looked bolted on beside twenty light fields. */
  border: 1px solid #E5E1F2 !important;
  border-radius: 12px !important;
  color: #18181B !important;
  -webkit-text-fill-color: #18181B !important;
}

html body.cl-v2:not(.cl-x).cl-embed .cl-ck__shipping #shipping_method li,
html body.cl-v2:not(.cl-x).cl-embed #shipping_method li {
  background-color: #FFFFFF !important;
  background-image: none !important;
  border: 1px solid #E5E1F2 !important;
}
html body.cl-v2:not(.cl-x).cl-embed .cl-ck__shipping #shipping_method li:has(input:checked),
html body.cl-v2:not(.cl-x).cl-embed #shipping_method li:has(input:checked) {
  background-color: #FAF8FF !important;
  border-color: #6D28D9 !important;
}


/* ------------------------------------------------------------------
 * 20d. THE PAY-NOW PANEL
 *
 * Won by the palette at
 *   html body.cl-v2:not(.cl-x) .woocommerce-checkout #payment .cl-paynow  (1,4,2)
 * against block 20's (0,4,2) — the #payment ID again. Matched on the same
 * path. This is the last tinted surface in the checkout that is not there on
 * purpose; what remains after it is the grey research-use notice, the
 * highlight on the selected shipping method, the amber savings badge and the
 * purple Place order button.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .woocommerce-checkout #payment .cl-paynow,
html body.cl-v2:not(.cl-x).cl-embed .woocommerce-checkout #payment .cl-paynow,
html body.cl-v2:not(.cl-x).cl-embed #payment .cl-paynow {
  background-color: #FFFFFF !important;
  background-image: none !important;
  border: 1px solid #E5E1F2 !important;
}


/* ==================================================================
 * 21. THE PURPLE BUTTONS' LIGHT END
 *
 * Found by making sc/v2buy.js measure a real WCAG ratio instead of a raw
 * luminance difference, and then measuring each gradient STOP rather than the
 * average of them. Averaging is what hid this: the mean of #8B5CF6 and
 * #5B21B6 passes comfortably, so every page-level contrast scan said fine.
 *
 *   white on #8B5CF6 (the light stop)   4.23:1   needs 4.5
 *   white on #5B21B6 (the dark stop)    8.98:1
 *
 * So the top of every primary button on the site — Add to cart, Explore
 * products, View all products, Shop — is marginally short, and the label
 * crosses it. 4.23 against 4.5 is not dramatic, but it is every call to
 * action on a shop, and the fix costs nothing visible.
 *
 * The light stop moves to #7C3AED: 5.70:1 with white, one step down the same
 * violet ramp, with the dark stop left alone so the gradient keeps its depth.
 * ================================================================== */
html body.cl-v2:not(.cl-x) .cl-btn,
html body.cl-v2:not(.cl-x) a.cl-btn,
html body.cl-v2:not(.cl-x) .cl-atc__btn,
html body.cl-v2:not(.cl-x) .cl-pagenav__shop,
html body.cl-v2:not(.cl-x) .cl-cathero__cta,
html body.cl-v2:not(.cl-x) .cl-hero2__shop,
html body.cl-v2:not(.cl-x) .cl-feat__btn,
html body.cl-v2:not(.cl-x) .cl-bundle__btn,
html body.cl-v2:not(.cl-x) .cl-drawer__cta,
html body.cl-v2:not(.cl-x) button.cl-search__btn,
html body.cl-v2:not(.cl-x) .cl-search__btn,
html body.cl-v2:not(.cl-x) .single_add_to_cart_button:not(.disabled):not([disabled]) {
  background-image: linear-gradient(#7C3AED 0%, #5B21B6 100%) !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}


/* ==================================================================
 * 22. THE STICKY CART LINE — A REAL MOBILE FAILURE
 *
 * Noah: "Mobile is most important."
 *
 * "You're $150.00 away from FREE SHIPPING" measured #71717A on #E5E4E8 —
 * 3.82:1 against the 4.5 it needs at 12px/500. That bar is pinned to the
 * bottom of every page on a phone, and the line is the one piece of copy on
 * it that is trying to sell another item.
 *
 * Every page-level scan missed it because the sticky bar only has its final
 * backdrop once the cart has something in it; the scans walk pages with an
 * empty cart, where the bar is not shown. It turned up only by walking the
 * real purchase path and then measuring what the walk flagged, rather than
 * waving the flags away as the noise they mostly were.
 *
 * #52525B would pass at 6.11:1; #3F3F46 is used instead at 8.25:1, matching
 * the weight the rest of the body copy was given in block 6 so the bar does
 * not read as a lighter class of text than the page above it.
 * ================================================================== */
html body.cl-v2:not(.cl-x) .cl-sticky-cart__ship,
html body.cl-v2:not(.cl-x) .cl-sticky-cart .cl-sticky-cart__ship,
html body.cl-v2:not(.cl-x) .cl-sticky-cart__sub,
html body.cl-v2:not(.cl-x) .cl-sticky-cart__meta {
  color: #3F3F46 !important;
  -webkit-text-fill-color: #3F3F46 !important;
  font-weight: 600 !important;
}


/* ==================================================================
 * 23. THE FEATURED CARDS KEPT THE FULL-STRENGTH HALO
 *
 * Noah: "you could reduce that glow a ton, actually."
 *
 * Block 8 took the halo down to a quarter on the catalogue cards, which paint
 * it on .cl-cardimg. The home page's FEATURED row ("START WITH THESE") paints
 * the same gradient on a different element, .cl-feat__img, and was never
 * touched — so it still measured rgba(167,139,250,0.55) while the shop grid
 * beside it ran at 0.14, and on a phone the featured row is the first set of
 * product cards anyone sees.
 *
 * Matched to the catalogue cards exactly, so one glow strength is used across
 * every card on the site.
 * ================================================================== */
html body.cl-v2:not(.cl-x) .cl-feat__img,
html body.cl-v2:not(.cl-x) span.cl-feat__img,
html body.cl-v2:not(.cl-x) .cl-feat__card .cl-feat__img,
html body.cl-v2:not(.cl-x) .cl-pick__img,
html body.cl-v2:not(.cl-x) .cl-picks__img {
  background-image:
    radial-gradient(58% 52% at 50% 48%,
      rgba(167, 139, 250, 0.14) 0%,
      rgba(139, 92, 246, 0.05) 45%,
      rgba(139, 92, 246, 0) 75%) !important;
}


/* ==================================================================
 * 24. PAYING LESS FOR UNIFORMITY
 *
 * Uniform cards cost space: every card reserves room for the sold-out card's
 * second control so "Add to cart" lands on the same line in all of them. With
 * that control styled as a full 56px button the reserve is 164px on a phone,
 * and on a starter pack — which has no strengths chip either — that stacks
 * into roughly 140px of empty white under the button. Noah's last note on
 * these cards before "make them uniform" was that they looked squashed; this
 * is the opposite failure and just as visible.
 *
 * The waitlist control does not need to be a button. It is the secondary
 * action on a card whose primary action is unavailable, so it reads better as
 * a compact link — and shrinking it shrinks the reserve on all twelve cards.
 *
 * The reserve is then re-measured rather than re-derived: the last attempt to
 * compute it from its parts came out 13px short and put the spread back.
 * ================================================================== */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-wait__open {
  background: transparent !important;
  background-image: none !important;
  border: 0 !important;
  box-shadow: none !important;
  color: #4C1D95 !important;
  -webkit-text-fill-color: #4C1D95 !important;
  text-decoration: underline !important;
  text-underline-offset: 3px !important;
  font-weight: 700 !important;
  font-size: 12.5px !important;
  height: auto !important;
  min-height: 0 !important;
  max-height: none !important;
  line-height: 1.3 !important;
  padding: 2px 4px !important;
  white-space: normal !important;
  text-overflow: clip !important;
  display: block !important;
  text-align: center !important;
}

/*
 * The reserve, re-set now that the waitlist control is a link rather than a
 * 56px button.
 *
 * Derived from the parts it came to 103 / 112, and the spread went straight
 * back to 13px at both widths — the same 13px as the last time I computed it
 * (block 19b). It is the waitlist form's collapsed margin, which is in none
 * of the parts you would think to add up. Measured instead: the sold-out
 * block's natural height is 116 on desktop and 125 on a phone.
 *
 * Down from 138 / 164, so every in-stock card gets ~22 / ~39px of dead white
 * back while "Add to cart" stays on one line across the whole grid.
 */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc {
  min-height: 116px !important;
}
@media (max-width: 767px) {
  /* 132, not 125: block 26 gave the waitlist link a real 44px tap target, so
     the sold-out block grew by the same 7px. Measured after that change. */
  html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc {
    min-height: 132px !important;
  }
}


/* ==================================================================
 * 25. THE CLAMPED TITLE WAS CUTTING ITS OWN LAST LINE
 *
 * On a phone "R3TA 10MG STARTER PACK" wraps to three lines and the third was
 * sliced through the middle — the word PACK half-height.
 *
 * Block 19c set the phone title to `height: 3.9em` with `-webkit-line-clamp:
 * 3`, which is exactly three lines of text and nothing else. But the title
 * also carries `padding: 10px 14px 0` and `box-sizing: border-box`, so that
 * 10px comes OUT of the 3.9em, leaving room for two and a half lines. The
 * clamp allows three, the box fits two and a half, and the difference is
 * visible as a cut-off word.
 *
 * Sized as content + padding, with the line-height pinned so the arithmetic
 * holds whatever the inherited leading happens to be:
 *   3 lines x 1.3 = 3.9em, + 10px padding-top
 * ================================================================== */
html body.cl-v2:not(.cl-x) ul.products li.product.product .woocommerce-loop-product__title {
  line-height: 1.3 !important;
}
@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product .woocommerce-loop-product__title {
    /* +2px: the two starter-pack names measured 73px of content in a 72px
       box — a sub-pixel rounding on a three-line clamp, not worth risking */
    height: calc(3.9em + 12px) !important;
    min-height: calc(3.9em + 12px) !important;
    max-height: calc(3.9em + 12px) !important;
  }
}
@media (min-width: 768px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product .woocommerce-loop-product__title {
    height: calc(2.6em + 10px) !important;
    min-height: calc(2.6em + 10px) !important;
    max-height: calc(2.6em + 10px) !important;
  }
}


/* ==================================================================
 * 26. TWO THINGS THE FIT SCAN FOUND, ONE OF THEM MINE
 *
 * sc/v2fit.js reported 52 page/width combinations with something that does
 * not fit. 1563 of the 1645 findings are `div.cl-mobile hides N px of
 * <header element>` — the sticky mobile header sitting over the content
 * behind it, which is what a sticky header does; that check does not exclude
 * fixed overlays. Two findings underneath that noise are real:
 *
 *   1. "Out of stock" is 95px of text in a 107px button on a phone, and the
 *      padding takes more than the 12px left over — so the label overflows by
 *      8px. "Add to cart" (87px) fits, which is why it was never noticed.
 *
 *   2. .cl-wait__open measures 37px tall. That is MY regression: block 24
 *      turned it from a 56px button into a compact link to reclaim dead white,
 *      and took it under the 44px minimum tap target in the process. It is the
 *      only control on a sold-out card, on the width that matters most.
 *
 * The link keeps its look and gets a real tap target by padding rather than
 * by growing the text.
 * ================================================================== */
@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc__btn {
    padding-left: 6px !important;
    padding-right: 6px !important;
    letter-spacing: 0.02em !important;
  }
  html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-wait__open {
    min-height: 44px !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    padding: 4px !important;
  }
}

/* the desktop title box measured its text 2px past the box — the same leading
   the phone box needed 2px for in block 25 */
@media (min-width: 768px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product .woocommerce-loop-product__title {
    height: calc(2.6em + 12px) !important;
    min-height: calc(2.6em + 12px) !important;
    max-height: calc(2.6em + 12px) !important;
  }
}


/* ------------------------------------------------------------------
 * 26b. THE LAST PIXEL, AND THE NARROWEST CARD
 *
 *   .cl-wait__open measured 43px against the 44px minimum — `min-height: 44px`
 *   from block 26 lands at 43 once the border and box-sizing are applied. One
 *   pixel, but 44 is the whole point of the number, so it is set to 46 and the
 *   reserve follows it.
 *
 *   "Out of stock" still overflowed by 4px in an 80px button. Block 26 fixed
 *   the 107px button at 390px wide; this is the narrower card on a smaller
 *   phone, where the same label no longer fits even at the reduced padding.
 *   Below 400px the catalogue labels step down to the 12.5px floor, which is
 *   as small as type is allowed to get on this site.
 * ------------------------------------------------------------------ */
@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-wait__open {
    min-height: 46px !important;
  }
  html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc {
    min-height: 134px !important;
  }
}
@media (max-width: 400px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc__btn {
    font-size: 11.5px !important;
    letter-spacing: 0 !important;
    padding-left: 4px !important;
    padding-right: 4px !important;
  }
}


/* ==================================================================
 * 27. THE PAGES NOBODY WAS SCANNING
 *
 * The contrast scan covered 11 pages; the site publishes 17. Seven were never
 * looked at by anything in this suite — refer-a-friend, how-to-save,
 * research-quality, affiliate-terms, privacy, terms and research-use-only —
 * which is exactly where a rebrand leaves something behind, because no report
 * ever mentions it.
 *
 * Adding them found one failure, on Refer a Friend:
 *
 *   label "The email you ordered with"   #71717A on #F5F3FF   4.4:1 (needs 4.5)
 *                                         and 11.5px, under the 12.5px floor
 *
 * Marginal on the ratio, but it is the instruction for the only field on a
 * page whose whole job is getting that field filled in.
 * ================================================================== */
html body.cl-v2:not(.cl-x) .cl-ref__form label,
html body.cl-v2:not(.cl-x) .cl-ref label,
html body.cl-v2:not(.cl-x) .cl-ref__hint {
  color: #3F3F46 !important;
  -webkit-text-fill-color: #3F3F46 !important;
  font-size: 12.5px !important;
  font-weight: 600 !important;
}


/* ==================================================================
 * 28. SOLID WHITE ON THE PAGES, NOT JUST THE CHECKOUT
 *
 * Noah: "i dont want the website to be tranparent and opaque i want solid
 * white except where the moving backgorund is."
 *
 * Blocks 12b and 20 did that for the checkout. Scanning every published page
 * for a pale colour CAST — as opposed to a neutral grey, which is fine, or a
 * saturated brand fill, which is deliberate — found 52 surfaces still carrying
 * the same #F5F3FF lavender, on all seventeen pages:
 *
 *   nav.cl-pagenav                  the HOME / SHOP PRODUCTS bar
 *   main > .container > article     the content panel of every page
 *   a.cl-contact__link              the phone and email pills
 *
 * Each needed a different fix, which is why they survived:
 *
 *   - .cl-pagenav: my earlier rule was `html body.cl-v2 nav.cl-pagenav`
 *     (0,2,3), one class short of the palette's (0,3,2). It matched, so it
 *     looked right, and lost.
 *   - article: the palette states it as `main > .container > article` (0,3,4);
 *     matched on the same path so file order decides it here.
 *   - .cl-contact__link: this one was MINE — an earlier block in this file set
 *     it to #F5F3FF deliberately, back when a tint was the plan.
 *
 * White with a visible border rather than white alone: the tint was doing the
 * work of separating these panels from the page, and on solid white that job
 * falls to the border.
 * ================================================================== */
html body.cl-v2:not(.cl-x) nav.cl-pagenav,
html body.cl-v2:not(.cl-x) .cl-pagenav.cl-pagenav {
  background-color: #FFFFFF !important;
  background-image: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  border-bottom: 1px solid #D4D4D8 !important;
}

html body.cl-v2:not(.cl-x) main > .container > article,
html body.cl-v2:not(.cl-x) main > .container > article.page,
html body.cl-v2:not(.cl-x) main .container > article {
  background-color: #FFFFFF !important;
  background-image: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  border: 1px solid #E5E1F2 !important;
}

html body.cl-v2:not(.cl-x) a.cl-contact__link,
html body.cl-v2:not(.cl-x) a.cl-contact__link--email,
html body.cl-v2:not(.cl-x) a.cl-contact__link--phone,
html body.cl-v2:not(.cl-x) .cl-ref__card {
  background-color: #FFFFFF !important;
  background-image: none !important;
  border: 1px solid #E5E1F2 !important;
}


/* ------------------------------------------------------------------
 * 28b. THE TWO THE OUTER PANELS WERE HIDING
 *
 * Whitening the article and the page-nav exposed two more carrying the same
 * lavender, which had been invisible inside a tinted parent:
 *
 *   div.cl-content       palette at (0,3,2); needed one more class
 *   div.cl-footer__col   palette at `footer .cl-footer__col` (0,3,3), beating
 *                        my earlier `body.cl-v2 div.cl-footer__col` (0,2,3)
 *                        — which is why the footer columns were still tinted
 *                        even though I had already set them to #FAFAFA once
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) div.cl-content,
html body.cl-v2:not(.cl-x) .cl-content.cl-content {
  background-color: #FFFFFF !important;
  background-image: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}

html body.cl-v2:not(.cl-x) footer .cl-footer__col,
html body.cl-v2:not(.cl-x) footer div.cl-footer__col {
  background-color: #FFFFFF !important;
  background-image: none !important;
  border: 1px solid #E5E1F2 !important;
}


/* ==================================================================
 * 29. THE REST OF THE GREEN
 *
 * Noah: "maybe no green in the white version of the website. use different
 * color."
 *
 * Blocks 14 and 16 took green off the surfaces I checked — and I reported it
 * done on the strength of a scan that only looked at BACKGROUND colours, on
 * one page. Sweeping every page for green in background, gradient, text AND
 * border found 45 more:
 *
 *   span.cl-zbar__tag            "SAVE 5%"      #14603A text and border
 *   span.cl-feat__tag--stock     "In stock"     #1E7A4C
 *   p.cl-paynotice__zelle                       #14603A on #F0FAF5
 *   div.cl-faqhelp               "Still have a question"  #3DD68C fill
 *   a.cl-calltab                 border only — block 16 set its fill purple
 *                                and left the border green
 *   the icons inside those
 *
 * Mapped by what each one is for, same as block 14:
 *   an OFFER        -> amber, the accent chosen in block 14
 *   a STATE         -> neutral slate; "In stock" is information, not a button,
 *                      and purple here would read as something to press
 *   a CALL TO ACTION-> brand purple
 * ================================================================== */

/* offers -> amber */
html body.cl-v2:not(.cl-x) .cl-zbar__tag,
html body.cl-v2:not(.cl-x) span.cl-zbar__tag,
html body.cl-v2:not(.cl-x) .cl-paynotice__zelle,
html body.cl-v2:not(.cl-x) p.cl-paynotice__zelle {
  background-color: #FFFBEB !important;
  background-image: none !important;
  color: #92400E !important;
  -webkit-text-fill-color: #92400E !important;
  border-color: #FCD34D !important;
}
html body.cl-v2:not(.cl-x) .cl-zbar__tag svg,
html body.cl-v2:not(.cl-x) .cl-paynotice__zelle svg {
  stroke: #92400E !important;
  color: #92400E !important;
  -webkit-text-fill-color: initial !important;
}

/* states -> neutral slate */
html body.cl-v2:not(.cl-x) .cl-feat__tag--stock,
html body.cl-v2:not(.cl-x) span.cl-feat__tag--stock,
html body.cl-v2:not(.cl-x) .cl-tag--stock,
html body.cl-v2:not(.cl-x) [class*="__tag--stock"] {
  background-color: #F4F4F5 !important;
  background-image: none !important;
  color: #3F3F46 !important;
  -webkit-text-fill-color: #3F3F46 !important;
  border-color: #E5E1F2 !important;
}

/* calls to action -> brand purple, border included this time */
html body.cl-v2:not(.cl-x) a.cl-calltab,
html body.cl-v2:not(.cl-x) .cl-calltab,
html body.cl-v2:not(.cl-x) .cl-tabmini {
  border-color: #4C1D95 !important;
}
html body.cl-v2:not(.cl-x) .cl-faqhelp,
html body.cl-v2:not(.cl-x) div.cl-faqhelp {
  background-color: #FFFFFF !important;
  background-image: none !important;
  border: 1px solid #E5E1F2 !important;
}
html body.cl-v2:not(.cl-x) .cl-faqhelp svg,
html body.cl-v2:not(.cl-x) .cl-faqhelp path,
html body.cl-v2:not(.cl-x) .cl-faqhelp [class*="icon"] {
  stroke: #6D28D9 !important;
  color: #6D28D9 !important;
  fill: none !important;
}
html body.cl-v2:not(.cl-x) .cl-faqhelp__btn {
  background-image: linear-gradient(#7C3AED 0%, #5B21B6 100%) !important;
  background-color: #5B21B6 !important;
  border-color: #5B21B6 !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}


/* ==================================================================
 * 30. THE TYPE SYSTEM
 *
 * Noah: "the text and font is now boring you've got to fix all of it and
 * really measure".
 *
 * Measured with sc/v2type.js across five pages at both widths. "Boring" came
 * out as three specific numbers:
 *
 *   1. NO SCALE. 18 distinct sizes on a phone, and 12 of the 17 steps between
 *      them are under 1.08x — 16, 15.5, 15, 14.5, 14, 13.5, 13, 12.5, 12 all
 *      sitting next to each other. Steps that close do not read as different
 *      sizes; they read as one slightly uneven size.
 *
 *   2. NO WEIGHT CONTRAST. 600 and 700 together are 71% of all text on the
 *      page, against 3% at 400. When nearly everything is semibold, bold stops
 *      meaning anything and nothing leads. This one is mine: block 6 pushed
 *      body copy to 500/600 to fix readability on white. But readability on
 *      white is a COLOUR problem, not a weight problem — #3F3F46 at 400 is
 *      10.4:1 on white, far past the 4.5 required. The weight bought nothing
 *      and cost the hierarchy.
 *
 *   3. DISPLAY TOO SMALL. The phone's largest type is 2.32x the body. For a
 *      clinical brand whose hero is the first thing anyone sees, that is a
 *      headline that does not arrive.
 *
 * So: body copy goes back to 400/500 and keeps the dark colour that makes it
 * readable; the near-duplicate small sizes collapse onto real steps; and the
 * display sizes step up. Spaced caps stay — that is the brand's character and
 * it was the one part still intact.
 * ================================================================== */

/* ---- 1. give body copy its weight back ----
   The colour does the readability work; the weight does the hierarchy work. */
html body.cl-v2:not(.cl-x) p,
html body.cl-v2:not(.cl-x) .cl-quality__lede,
html body.cl-v2:not(.cl-x) .cl-bundles__lede,
html body.cl-v2:not(.cl-x) .cl-contact__lede,
html body.cl-v2:not(.cl-x) .cl-section__lede,
html body.cl-v2:not(.cl-x) .cl-hero2__lede {
  font-weight: 400 !important;
  color: #3F3F46 !important;
  -webkit-text-fill-color: #3F3F46 !important;
}
html body.cl-v2:not(.cl-x) .cl-bundle__desc,
html body.cl-v2:not(.cl-x) .cl-feat__desc,
html body.cl-v2:not(.cl-x) .cl-card__desc,
html body.cl-v2:not(.cl-x) .cl-pack__desc,
html body.cl-v2:not(.cl-x) .woocommerce-product-details__short-description,
html body.cl-v2:not(.cl-x) .woocommerce-product-details__short-description p {
  font-weight: 450 !important;
  color: #3F3F46 !important;
  -webkit-text-fill-color: #3F3F46 !important;
}
html body.cl-v2:not(.cl-x) .cl-bundle__ruo,
html body.cl-v2:not(.cl-x) .cl-mobile__foot,
html body.cl-v2:not(.cl-x) .cl-ruo {
  font-weight: 500 !important;
  color: #52525B !important;
  -webkit-text-fill-color: #52525B !important;
}
/* the spec rows keep their label/value contrast — that pattern is the one
   Noah singled out as working ("ready to ORDER") */
html body.cl-v2:not(.cl-x) .cl-bundle__row dd,
html body.cl-v2:not(.cl-x) .cl-bundle__row .cl-bundle__v,
html body.cl-v2:not(.cl-x) .cl-spec__v {
  font-weight: 500 !important;
}

/* ---- 2. collapse the near-duplicate small sizes onto real steps ----
   16 / 15.5 / 15 / 14.5 / 14 / 13.5 / 13 become 16 / 15 / 13.5, which are
   1.11x and 1.11x apart — far enough to read as different. */
html body.cl-v2:not(.cl-x) .cl-bundle__desc,
html body.cl-v2:not(.cl-x) .cl-feat__desc,
html body.cl-v2:not(.cl-x) .cl-bundles__lede,
html body.cl-v2:not(.cl-x) .cl-contact__lede,
html body.cl-v2:not(.cl-x) .cl-section__lede {
  font-size: 16px !important;
}
html body.cl-v2:not(.cl-x) .cl-feat__meta,
html body.cl-v2:not(.cl-x) .cl-card__meta,
html body.cl-v2:not(.cl-x) .cl-bundle__row,
html body.cl-v2:not(.cl-x) .cl-spec {
  font-size: 14px !important;
}

/* ---- 3. the display sizes arrive ----
   phone 37 -> 44 (2.75x body), desktop 54 -> 64 (4x body) */
html body.cl-v2:not(.cl-x) .cl-hero2__title,
html body.cl-v2:not(.cl-x) .cl-hero2__titleTop,
html body.cl-v2:not(.cl-x) .cl-hero2__titleBottom {
  font-size: clamp(42px, 11vw, 64px) !important;
  line-height: 1.02 !important;
  letter-spacing: -0.02em !important;
  font-weight: 700 !important;
}

/* ---- 4. the four caps styles that lost their tracking ----
   Spaced caps is this brand's signature; caps without tracking just look
   like shouting. */
html body.cl-v2:not(.cl-x) [style*="uppercase"],
html body.cl-v2:not(.cl-x) .cl-feat__tag,
html body.cl-v2:not(.cl-x) .cl-tag,
html body.cl-v2:not(.cl-x) .onsale,
html body.cl-v2:not(.cl-x) .cl-badge {
  letter-spacing: 0.1em !important;
}


/* ==================================================================
 * 31. A REAL SIZE SCALE
 *
 * Block 30 fixed the weight and the display size; the scale itself did not
 * move, because I guessed at class names instead of measuring which selectors
 * owned which size. sc/v2sizes.js prints that, and the 11.5-17px band was
 * eleven sizes doing the work of four:
 *
 *   17    h3, contact values, prices, "Pick a compound"
 *   16.5  the starter-pack link title — one use, 0.5px from 16
 *   16    card titles, featured names, body copy
 *   15    FAQ summaries, buttons, ledes, descriptions
 *   14.5  footer blurb and RUO line — 0.5px from 15 and 14
 *   14    search button, page-nav, intent text
 *   13.5  the struck "was" price
 *   13    prices, "Shop now", notes
 *   12.5  chips, RUO lists, sizes
 *   12    nav labels, tags, footer headings, eyebrows   <- under the floor
 *   11.5  "Add to cart"                                 <- under the floor
 *
 * Two findings in that list beyond the clutter:
 *
 *   - 255 uses sit BELOW the 12.5px floor this project enforces everywhere
 *     else. The 11.5px one is mine: block 26b shrank the catalogue button to
 *     stop "Out of stock" overflowing on narrow phones, and took it under the
 *     floor to do it. The right fix for an overflowing label is the padding
 *     and the tracking, not going under the floor.
 *
 *   - 16.5 and 14.5 are each half a pixel from a neighbour. Nobody chose
 *     those; they are what a percentage lands on.
 *
 * Collapsed to 12.5 / 13.5 / 15 / 17, steps of 1.08x, 1.11x and 1.13x — far
 * enough apart to read as different sizes, which is the whole job of a scale.
 * ================================================================== */

/* 16.5 -> 16 */
html body.cl-v2:not(.cl-x) a.woocommerce-LoopProduct-link h2.woocommerce-loop-product__title {
  font-size: 16px !important;
}

/* 14.5 -> 15 */
html body.cl-v2:not(.cl-x) p.cl-footer__blurb,
html body.cl-v2:not(.cl-x) p.cl-footer__ruo {
  font-size: 16px !important;
}

/* 14 -> 13.5 */
html body.cl-v2:not(.cl-x) .cl-pagenav__home,
html body.cl-v2:not(.cl-x) .cl-pagenav__shop,
html body.cl-v2:not(.cl-x) .cl-intent__text,
html body.cl-v2:not(.cl-x) p.woocommerce-result-count,
html body.cl-v2:not(.cl-x) .cl-faqhelp__sub,
html body.cl-v2:not(.cl-x) .cl-search__btn,
html body.cl-v2:not(.cl-x) form.search-form button {
  font-size: 14px !important;
}

/* 13 -> 13.5 */
html body.cl-v2:not(.cl-x) .cl-feat__btn,
html body.cl-v2:not(.cl-x) .cl-topbar__link,
html body.cl-v2:not(.cl-x) .cl-contact__note,
html body.cl-v2:not(.cl-x) .cl-feat__price,
html body.cl-v2:not(.cl-x) .cl-feat__price bdi,
html body.cl-v2:not(.cl-x) .cl-spec__v {
  font-size: 14px !important;
}

/* 12 and 11.5 -> 12.5, the floor. Nothing on this site goes under it. */
html body.cl-v2:not(.cl-x) .cl-nav-label,
html body.cl-v2:not(.cl-x) .cl-icon-btn__cap,
html body.cl-v2:not(.cl-x) .cl-feat__tag,
html body.cl-v2:not(.cl-x) .cl-footer__heading,
html body.cl-v2:not(.cl-x) .cl-contact__label,
html body.cl-v2:not(.cl-x) .cl-eyebrow,
html body.cl-v2:not(.cl-x) .cl-feat__eyebrow,
html body.cl-v2:not(.cl-x) .cl-picks__eyebrow,
html body.cl-v2:not(.cl-x) .cl-bundles__eyebrow {
  font-size: 12.5px !important;
}

/*
 * "Add to cart" / "Out of stock" back above the floor.
 *
 * The label is 92px at 12.5px with no tracking; the button's inner width on a
 * 390px phone is 99px, so it fits — the overflow block 26b was solving came
 * from the tracking and the padding, not the size.
 */
@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc__btn {
    font-size: 12.5px !important;
    letter-spacing: 0 !important;
    padding-left: 4px !important;
    padding-right: 4px !important;
  }
}
@media (max-width: 400px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc__btn {
    font-size: 12.5px !important;
    letter-spacing: 0 !important;
  }
}


/* ------------------------------------------------------------------
 * 31b. THE STRAGGLERS, BY THEIR REAL SELECTORS
 *
 * Block 31 moved 18 sizes to 16 but left four, because I had again written
 * selectors from memory. Printing the actual DOM path for each stray size
 * gave them:
 *
 *   16.5  a.woocommerce-LoopProduct-link      the starter-pack card link
 *   14    form.woocommerce-product-search > button   the search and cancel buttons
 *   13    span.price bdi                      every catalogue price
 *         nav.cl-nav li > a                   the whole desktop menu
 *         .cl-feat__btn, .cl-zbar__txt
 *   12    the footer copy, the mobile foot line, the contact eyebrow,
 *         .cl-tabquiet and the policy page H2 — all under the 12.5px floor
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) a.woocommerce-LoopProduct-link,
html body.cl-v2:not(.cl-x) a.woocommerce-loop-product__link {
  font-size: 16px !important;
}

html body.cl-v2:not(.cl-x) form.woocommerce-product-search > button,
html body.cl-v2:not(.cl-x) form.woocommerce-product-search button.cl-sg__cancel {
  font-size: 14px !important;
}

html body.cl-v2:not(.cl-x) span.price bdi,
html body.cl-v2:not(.cl-x) span.price .woocommerce-Price-amount,
html body.cl-v2:not(.cl-x) nav.cl-nav li > a,
html body.cl-v2:not(.cl-x) .cl-feat__btn,
html body.cl-v2:not(.cl-x) .cl-zbar__txt,
html body.cl-v2:not(.cl-x) .cl-zbar b {
  font-size: 14px !important;
}

/* nothing under the floor */
html body.cl-v2:not(.cl-x) p.cl-mobile__foot,
html body.cl-v2:not(.cl-x) p.cl-contact__eyebrow,
html body.cl-v2:not(.cl-x) p.cl-footer__disclaimer,
html body.cl-v2:not(.cl-x) p.cl-footer__copy,
html body.cl-v2:not(.cl-x) span.cl-tabquiet,
html body.cl-v2:not(.cl-x) .cl-policy h2,
html body.cl-v2:not(.cl-x) article h2 {
  font-size: 12.5px !important;
}
/* ...except a page heading, which is a heading and wants to be one */
html body.cl-v2:not(.cl-x) article h2,
html body.cl-v2:not(.cl-x) .cl-content h2 {
  font-size: 21px !important;
  font-weight: 700 !important;
  letter-spacing: 0.04em !important;
}


/* ------------------------------------------------------------------
 * 31c. THE LAST THREE SIZES
 *
 *   16.5  li.product itself — the card's own font-size, which the price
 *         inherits from. I had set the price and the link but not the box
 *         they sit in, so the inherited value kept reappearing.
 *   13    span.price .amount — the AMOUNT span inside the price, one level
 *         below the `span.price bdi` block 31b targeted.
 *   12    the age gate links, the top-bar promo line and the catalogue hero
 *         eyebrow — all under the floor.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products li.product.product {
  font-size: 16px !important;
}
html body.cl-v2:not(.cl-x) span.price .woocommerce-Price-amount,
html body.cl-v2:not(.cl-x) span.price .woocommerce-Price-amount bdi,
html body.cl-v2:not(.cl-x) span.price .woocommerce-Price-currencySymbol {
  font-size: 14px !important;
}
html body.cl-v2:not(.cl-x) .cl-agegate__links,
html body.cl-v2:not(.cl-x) .cl-agegate__links a,
html body.cl-v2:not(.cl-x) .cl-agegate__links span,
html body.cl-v2:not(.cl-x) .cl-topbar__promo,
html body.cl-v2:not(.cl-x) .cl-topbar__promo .woocommerce-Price-amount,
html body.cl-v2:not(.cl-x) .cl-topbar__promo .woocommerce-Price-currencySymbol,
html body.cl-v2:not(.cl-x) .cl-chero__eyebrow {
  font-size: 12.5px !important;
}


/* ==================================================================
 * 32. THE REFER POP-UP'S HEADING WAS WHITE ON WHITE
 *
 * Noah sent a screenshot of the Refer a Friend pop-up: a big purple "10%"
 * floating alone at the top right with a block of empty space under it.
 *
 * The empty space is the heading. `h2.cl-ref__h` computes to rgb(255,255,255)
 * on a white card — "They save ___. So do you." is there, in white, invisible.
 * The only part that shows is the "10%" span inside it, which has its own
 * purple, so it reads as an orphan rather than as part of a sentence.
 *
 * Same bug as the white "Venmo"/"Bitcoin" payment labels: a colour that was
 * correct on near-black and was never revisited. And missed for the same
 * reason the selected payment row was missed — every scan reads the page as it
 * first loads, and this panel is closed then. Opening it is the only way to
 * see it.
 *
 * Its label was also 11.5px, under the 12.5px floor.
 * ================================================================== */
html body.cl-v2:not(.cl-x) .cl-ref__h,
html body.cl-v2:not(.cl-x) h2.cl-ref__h {
  color: #18181B !important;
  -webkit-text-fill-color: #18181B !important;
}
/* the percentage stays the accent, as the one coloured word in the sentence */
html body.cl-v2:not(.cl-x) .cl-ref__h span,
html body.cl-v2:not(.cl-x) h2.cl-ref__h span {
  color: #6D28D9 !important;
  -webkit-text-fill-color: #6D28D9 !important;
}
html body.cl-v2:not(.cl-x) .cl-ref__card label,
html body.cl-v2:not(.cl-x) .cl-ref__card .cl-ref__label {
  font-size: 12.5px !important;
  color: #3F3F46 !important;
  -webkit-text-fill-color: #3F3F46 !important;
}


/* ==================================================================
 * 33. THE TRUST STRIP WRAPPED 3 + 1
 *
 * Noah sent it with "COAS AVAILABLE" orphaned on a second line.
 *
 * Measured across 13 widths: on phones it is a clean 2x2 grid, but from 768
 * up it is a flex row whose box is capped at 686px while the four items
 * total 796px. 796 has never fitted in 686, so it wrapped 3+1 at EVERY
 * desktop width — 1024, 1280, 1440, 1600 and 1920 all measured identically.
 * It was not a narrow-window edge case; it was the default.
 *
 * Given four real columns and room for them, so the four items sit on one
 * line as a row of four, which is what the band is for.
 * ================================================================== */
@media (min-width: 768px) {
  html body.cl-v2:not(.cl-x) .cl-hero2__trust {
    display: grid !important;
    grid-template-columns: repeat(4, auto) !important;
    justify-content: center !important;
    align-items: center !important;
    column-gap: 18px !important;
    row-gap: 0 !important;
    max-width: min(960px, 92vw) !important;
    width: auto !important;
    margin-left: auto !important;
    margin-right: auto !important;
  }
  html body.cl-v2:not(.cl-x) .cl-hero2__trust > * {
    white-space: nowrap !important;
    min-width: 0 !important;
  }
}
/* if a narrow desktop still cannot take four across, fall to a balanced 2x2
   rather than an orphaned 3+1 */
@media (min-width: 768px) and (max-width: 950px) {
  html body.cl-v2:not(.cl-x) .cl-hero2__trust {
    grid-template-columns: repeat(2, auto) !important;
    row-gap: 10px !important;
  }
}


/* ------------------------------------------------------------------
 * 34. THE SHOP HERO VIAL, FINISHED
 *
 * Capping the vial's height took the overlap from 9px to 8px, which says the
 * vial's SIZE was never the problem. The overlap is 243px wide — the button's
 * full width — so in the 800-880 band the copy column and the stage are
 * stacked, not side by side, and the vial's box simply starts 8px above where
 * the button ends. It is a gap problem, not a size one.
 * ------------------------------------------------------------------ */
@media (min-width: 769px) and (max-width: 899px) {
  html body.cl-v2:not(.cl-x) .cl-chero__copy {
    margin-bottom: 32px !important;
    padding-bottom: 0 !important;
  }
  html body.cl-v2:not(.cl-x) .cl-chero__stage {
    margin-top: 24px !important;
  }
  html body.cl-v2:not(.cl-x) .cl-chero__float {
    margin-top: 8px !important;
  }
}


/* ==================================================================
 * 35. MODAL HEADERS: A WHITE TITLE AND UNFILLED CONTROLS
 *
 * Noah, on the My Account pop-up: the title is unreadable and "those buttons
 * [need to be] filled in an match other buttones".
 *
 * Measured on the parent page, where these headers live:
 *
 *   .cl-acct__title   #FFFFFF on a light header  -> invisible, same bug as the
 *                     Venmo label and the refer heading
 *   .cl-acct__x       #FFFFFF glyph on rgba(124,58,237,0.08)
 *   .cl-co__close     ) all four header controls sit on an 8% purple wash,
 *   .cl-popback       ) which on white is a 4% tint — present in the DOM and
 *   .cl-refsheet__x   ) not visible as a button
 *
 * The 8% fill was an outline button on near-black. On white it needs a real
 * fill, and the site's control fill is the brand purple with a white glyph —
 * the same treatment the Call tab and the primary buttons already carry.
 * ================================================================== */
html body.cl-v2:not(.cl-x) .cl-acct__title,
html body.cl-v2:not(.cl-x) h2.cl-acct__title,
html body.cl-v2:not(.cl-x) .cl-co__title,
html body.cl-v2:not(.cl-x) .cl-sheet__title,
html body.cl-v2:not(.cl-x) .cl-refsheet__title {
  color: #18181B !important;
  -webkit-text-fill-color: #18181B !important;
  font-weight: 700 !important;
}
html body.cl-v2:not(.cl-x) .cl-acct__title svg,
html body.cl-v2:not(.cl-x) .cl-co__title svg {
  stroke: #6D28D9 !important;
  color: #6D28D9 !important;
  -webkit-text-fill-color: initial !important;
}

html body.cl-v2:not(.cl-x) .cl-acct__x,
html body.cl-v2:not(.cl-x) .cl-co__close,
html body.cl-v2:not(.cl-x) .cl-popback,
html body.cl-v2:not(.cl-x) .cl-refsheet__x,
html body.cl-v2:not(.cl-x) .cl-sheet__x,
html body.cl-v2:not(.cl-x) .cl-callsheet__x {
  background-color: #6D28D9 !important;
  background-image: linear-gradient(#7C3AED 0%, #5B21B6 100%) !important;
  border: 2px solid #5B21B6 !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
  border-radius: 12px !important;
}
html body.cl-v2:not(.cl-x) .cl-acct__x svg,
html body.cl-v2:not(.cl-x) .cl-co__close svg,
html body.cl-v2:not(.cl-x) .cl-popback svg,
html body.cl-v2:not(.cl-x) .cl-refsheet__x svg,
html body.cl-v2:not(.cl-x) .cl-sheet__x svg,
html body.cl-v2:not(.cl-x) .cl-callsheet__x svg {
  stroke: #FFFFFF !important;
  color: #FFFFFF !important;
  fill: none !important;
}


/* ==================================================================
 * 36. THE TEXT PAGES READ AS A WALL
 *
 * Noah: "fotn and text needs to be fixed in about tab", "FAQ could be
 * organized and made easier to read", "contact popup could be made easier to
 * read".
 *
 * Measured first, because the obvious answer — the type is too small or too
 * tight — turned out to be wrong. About, Research & Quality and Contact all
 * measure 15-16px at 1.6-1.7 leading with 45-63 characters per line, and the
 * readable range is 45-75. The type itself is right.
 *
 * What is wrong is the RHYTHM: every heading computes `margin-top: 0`. A
 * heading with no space above it does not start a section, it just appears
 * mid-paragraph — so five sections of prose run together into one block, which
 * is exactly what "a wall of text" means and why these pages feel hard even
 * though each line is comfortable.
 *
 * Headings get space above proportional to their size, paragraphs get a real
 * gap between them, and the first paragraph of a page reads as a lede.
 * ================================================================== */
html body.cl-v2:not(.cl-x) article h2,
html body.cl-v2:not(.cl-x) .cl-content h2,
html body.cl-v2:not(.cl-x) .entry-content h2,
html body.cl-v2:not(.cl-x) main h2 {
  margin-top: 1.9em !important;
  margin-bottom: 0.5em !important;
  line-height: 1.2 !important;
}
html body.cl-v2:not(.cl-x) article h3,
html body.cl-v2:not(.cl-x) .cl-content h3,
html body.cl-v2:not(.cl-x) .entry-content h3,
html body.cl-v2:not(.cl-x) main h3 {
  margin-top: 1.6em !important;
  margin-bottom: 0.45em !important;
  line-height: 1.25 !important;
}
/* the first heading on a page should not be pushed off the top */
html body.cl-v2:not(.cl-x) article > *:first-child,
html body.cl-v2:not(.cl-x) .cl-content > *:first-child,
html body.cl-v2:not(.cl-x) .entry-content > *:first-child {
  margin-top: 0 !important;
}

html body.cl-v2:not(.cl-x) article p,
html body.cl-v2:not(.cl-x) .cl-content p,
html body.cl-v2:not(.cl-x) .entry-content p {
  margin-bottom: 1.05em !important;
  max-width: 68ch !important;
}

/* the opening paragraph carries the page — give it a size of its own */
html body.cl-v2:not(.cl-x) article > p:first-of-type,
html body.cl-v2:not(.cl-x) .cl-content > p:first-of-type,
html body.cl-v2:not(.cl-x) .entry-content > p:first-of-type {
  font-size: 18px !important;
  line-height: 1.65 !important;
  color: #27272A !important;
  -webkit-text-fill-color: #27272A !important;
}

/* ---- the FAQ: group it so the sections read as sections ---- */
html body.cl-v2:not(.cl-x) .cl-faq h2,
html body.cl-v2:not(.cl-x) .cl-faq__group > h2 {
  margin-top: 2.2em !important;
  padding-bottom: 0.4em !important;
  border-bottom: 1px solid #D4D4D8 !important;
}
html body.cl-v2:not(.cl-x) .cl-faq details,
html body.cl-v2:not(.cl-x) .cl-faq__row,
html body.cl-v2:not(.cl-x) article details {
  margin-bottom: 8px !important;
  border: 1px solid #E5E1F2 !important;
  border-radius: 14px !important;
  background: #FFFFFF !important;
}
html body.cl-v2:not(.cl-x) .cl-faq summary,
html body.cl-v2:not(.cl-x) article details summary {
  padding: 14px 16px !important;
  font-weight: 700 !important;
  color: #18181B !important;
  -webkit-text-fill-color: #18181B !important;
  cursor: pointer !important;
  min-height: 44px !important;
  display: flex !important;
  align-items: center !important;
}
html body.cl-v2:not(.cl-x) .cl-faq details[open],
html body.cl-v2:not(.cl-x) article details[open] {
  border-color: #6D28D9 !important;
}
html body.cl-v2:not(.cl-x) .cl-faq details p,
html body.cl-v2:not(.cl-x) article details p {
  padding: 0 16px 14px !important;
  margin-bottom: 0 !important;
}


/* ==================================================================
 * 37. THE LAST INVISIBLE TEXT, FOUND BY A SCANNER INSTEAD OF BY EYE
 *
 * White-on-white has now been found five times by Noah looking at one panel at
 * a time: the Venmo and Bitcoin payment labels, the refer card's heading, the
 * My Account title, and the refer sheet's header bar. Rather than wait for a
 * sixth, sc/v2white2.js opens every overlay and checks every piece of text
 * against its own composited backdrop, failing anything under 2:1 — not a
 * contrast-quality bar, a "can you see this at all" bar.
 *
 * It found the two that were left:
 *
 *   h2 in .cl-refsheet__bar     #FFFFFF on #E5E5E8   1.26:1
 *     A bare <h2> with no class, which is why block 35's .cl-refsheet__title
 *     did not touch it.
 *
 *   a.cl-callsheet__btn "Text us"  #FFFFFF on #F0FAF5   1.07:1
 *     And #F0FAF5 is a pale GREEN — one more survivor of the no-green sweep,
 *     hiding in a panel that only opens on a tap.
 * ================================================================== */
html body.cl-v2:not(.cl-x) .cl-refsheet__bar h2,
html body.cl-v2:not(.cl-x) .cl-refsheet__bar > h2,
html body.cl-v2:not(.cl-x) .cl-callsheet h2,
html body.cl-v2:not(.cl-x) .cl-sheet__head h2 {
  color: #18181B !important;
  -webkit-text-fill-color: #18181B !important;
  font-weight: 700 !important;
}

html body.cl-v2:not(.cl-x) a.cl-callsheet__btn,
html body.cl-v2:not(.cl-x) .cl-callsheet__btn {
  background-color: #6D28D9 !important;
  background-image: linear-gradient(#7C3AED 0%, #5B21B6 100%) !important;
  border: 2px solid #5B21B6 !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}
html body.cl-v2:not(.cl-x) a.cl-callsheet__btn svg,
html body.cl-v2:not(.cl-x) .cl-callsheet__btn svg {
  stroke: #FFFFFF !important;
  color: #FFFFFF !important;
}


/* ------------------------------------------------------------------
 * 38. THE LAST TWO OFF-LADDER SIZES
 *
 * After the generated layer the scale is 12 sizes on desktop with 5 tight
 * steps, down from 19 and 11. Two selectors were still off it, found by
 * printing the DOM path for every element rendering an off-ladder size:
 *
 *   a.woocommerce-LoopProduct-link > .price .woocommerce-Price-amount  13px
 *     The catalogue price. It survived both passes because it inherits from a
 *     relative value, which the generator deliberately leaves alone — snapping
 *     an em is guesswork.
 *
 *   div.cl-atc__opts button.cl-atc__opt  12px
 *     The strength buttons on a card, under the 12.5px floor.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price,
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price .woocommerce-Price-amount,
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price .woocommerce-Price-currencySymbol,
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price bdi {
  font-size: 14px !important;
}
html body.cl-v2:not(.cl-x) .cl-atc__opts button.cl-atc__opt,
html body.cl-v2:not(.cl-x) .cl-atc__opts-row button.cl-atc__opt,
html body.cl-v2:not(.cl-x) button.cl-atc__opt {
  font-size: 12.5px !important;
}


/* ==================================================================
 * 39. THE REFER CARD HAS NO PADDING
 *
 * Noah: "you see how smashed it is?"
 *
 * Measured, at both widths: .cl-ref__card computes `padding: 0`, and the
 * "Get my link" button ends 1px from the card's right edge and 1px from its
 * bottom. The card is 486x342 inside a 520x430 panel, so the content is
 * running to the card's own border on three sides with nothing to breathe
 * into. That is not a tight layout, it is no layout — the card never had
 * internal padding, and on the dark design the card's edge was invisible so
 * nobody saw it.
 * ================================================================== */
html body.cl-v2:not(.cl-x) .cl-ref__card,
html body.cl-v2:not(.cl-x) div.cl-ref__card {
  padding: 26px 24px 24px !important;
  box-sizing: border-box !important;
}
html body.cl-v2:not(.cl-x) .cl-ref__form {
  gap: 12px !important;
  margin-top: 6px !important;
}
html body.cl-v2:not(.cl-x) .cl-ref__h {
  margin-bottom: 20px !important;
}
html body.cl-v2:not(.cl-x) .cl-ref__card ol,
html body.cl-v2:not(.cl-x) .cl-ref__card ul {
  margin-bottom: 20px !important;
}
html body.cl-v2:not(.cl-x) .cl-refsheet__card {
  padding: 12px 16px 24px !important;
}

@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x) .cl-ref__card,
  html body.cl-v2:not(.cl-x) div.cl-ref__card {
    padding: 22px 18px 20px !important;
  }
}


/* ------------------------------------------------------------------
 * 39b. THE SAME FAULT IN THE CORE PICKS CARD
 *
 * Auditing every overlay panel for content sitting on its own edge turned up
 * .cl-picks__body with `padding: 0` and its price at B0 — flush against the
 * bottom of the card, the same way the refer card's button was flush against
 * its right.
 *
 * Most of the other 27 the audit flagged are correct: a sheet's scrim fills
 * the viewport, a panel's header bar is meant to be full-bleed, and a card's
 * link is meant to cover the card. Those are full-width bars, not cramped
 * content.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-picks__body {
  padding: 0 16px 18px !important;
  box-sizing: border-box !important;
}
html body.cl-v2:not(.cl-x) .cl-picks__price {
  margin-bottom: 0 !important;
}


/* ==================================================================
 * 40. THE TRUST / ZELLE BAND AT TABLET-ISH WIDTHS
 *
 * Noah sent this band looking cramped. His screenshot is a 2x capture, so the
 * real width is around 865px — the 768-950 band where block 33 drops the trust
 * strip to a balanced 2x2 rather than an orphaned 3+1.
 *
 * Measured there:
 *   trust strip  row-gap 10px        — two rows of CAPS 10px apart
 *   zelle bar    868px wide in 900   — 16px from each edge, so it reads as a
 *                                      full-bleed stripe rather than a card,
 *                                      while at 1280+ it is a centred 1180
 *   gap between them 40px, but the bar's own padding is only 11px
 *
 * So the strip is tight against itself and the bar is tight against the
 * screen. Both get room, and the bar gets the same contained width it has on
 * a wide screen so it stays a card at every size.
 * ================================================================== */
@media (min-width: 768px) and (max-width: 1023px) {
  html body.cl-v2:not(.cl-x) .cl-hero2__trust {
    row-gap: 20px !important;
    column-gap: 28px !important;
    margin-bottom: 8px !important;
  }
}

html body.cl-v2:not(.cl-x) .cl-zbar {
  max-width: min(1180px, calc(100% - 64px)) !important;
  margin-left: auto !important;
  margin-right: auto !important;
  padding: 14px 20px !important;
}
@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x) .cl-zbar {
    max-width: calc(100% - 32px) !important;
    padding: 12px 14px !important;
  }
}


/* ------------------------------------------------------------------
 * 40b. THE SEPARATOR DOTS
 *
 * Noah: "get rid of bullet points".
 *
 * li.cl-hero2__trustItem::before — a 3x3px 50%-radius dot at
 * rgba(124,58,237,0.75), one before each item after the first. It read as a
 * separator when the four items sat on one line; now that they wrap 2x2 it
 * reads as a bullet list, which is not what the band is.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-hero2__trustItem::before,
html body.cl-v2:not(.cl-x) li.cl-hero2__trustItem::before {
  display: none !important;
  content: none !important;
}


/* ==================================================================
 * 41. THE CHECKOUT IS WASHED OUT
 *
 * Noah: "The checkout page is so washed out, it's hard to see anything...
 * The lines are going to have to be way more thick. You're going to have to
 * measure the lines... and the button for call a human, it's washed out."
 *
 * Measured inside the frame, every border in use:
 *
 *    21x  1px rgb(199,199,203)        ok
 *    18x  1px rgba(124,58,237,0.16)   16% purple — a hairline that is not there
 *    16x  1px rgb(212,212,216)        ok
 *     9x  1px rgb(244,244,245)        #F4F4F5 on white: 1.04:1
 *     4x  1px rgba(255,255,255,0.07)  WHITE on white — invisible by definition
 *
 * So a third of the checkout's structure is drawn in lines that cannot be
 * seen on a white page. They were correct on near-black, where a 7% white
 * hairline is exactly how you draw an edge; inverted, they vanish and the
 * page reads as one undifferentiated wash.
 *
 * The text, measured, is mostly already 700/800 — the flatness is the lines,
 * not the weight. Both are addressed, but the lines carry it.
 *
 * And "Call a human" was still GREEN: #14603A on #F0FAF5 with a #BFE8D4
 * border. The no-green sweep never opened the checkout modal, so it survived.
 * ================================================================== */

/* ---- 1. lines you can see: thicker AND darker ---- */
html body.cl-v2:not(.cl-x).cl-embed .cl-ck__row,
html body.cl-v2:not(.cl-x).cl-embed .cl-ck__aside,
html body.cl-v2:not(.cl-x).cl-embed .cl-ck__panel,
html body.cl-v2:not(.cl-x).cl-embed #payment li.wc_payment_method,
html body.cl-v2:not(.cl-x).cl-embed .cl-paynow,
html body.cl-v2:not(.cl-x).cl-embed .cl-protect,
html body.cl-v2:not(.cl-x).cl-embed .cl-acknowledgement,
html body.cl-v2:not(.cl-x).cl-embed .woocommerce-checkout-review-order {
  border: 1px solid #E5E1F2 !important;
}
html body.cl-v2:not(.cl-x).cl-embed input.input-text,
html body.cl-v2:not(.cl-x).cl-embed textarea,
/* 1.75px #E2E5EA was a heavy mid-grey, and at (1,3,3) it beat everything newer
 * — which is why the order-notes box and the coupon field kept their dark
 * outline while every other control went light. One line colour, one weight. */
html body.cl-v2:not(.cl-x).cl-embed textarea#order_comments,
html body.cl-v2:not(.cl-x).cl-embed select,
html body.cl-v2:not(.cl-x).cl-embed #coupon_code,
html body.cl-v2:not(.cl-x).cl-embed .select2-container .select2-selection {
  border: 1px solid #E5E1F2 !important;
  border-radius: 12px !important;
}
/* dividers inside the order table */
/* the order summary's own rules were 1.5px #E2E5EA — darker and thicker than
 * the panel they sit inside, so the totals block read as a wireframe table
 * rather than a receipt. Same line as everything else. */
html body.cl-v2:not(.cl-x).cl-embed table.shop_table th,
html body.cl-v2:not(.cl-x).cl-embed table.shop_table td,
html body.cl-v2:not(.cl-x).cl-embed table.shop_table tr {
  border-bottom: 1px solid #D4D4D8 !important;
}
/*
 * The catch-all. Any border still drawn in white, near-white or a wash of
 * purple under 25% gets a real colour — that is the 31 hairlines above, and
 * it is written by computed VALUE rather than by selector because they come
 * from dozens of rules across 21,000 lines.
 */
html body.cl-v2:not(.cl-x).cl-embed *,
html body.cl-v2:not(.cl-x).cl-embed *::before,
html body.cl-v2:not(.cl-x).cl-embed *::after {
  border-color: var(--cl-co-line, inherit);
}
html body.cl-v2:not(.cl-x).cl-embed {
  --cl-co-line: #E2E5EA;
}

/* ---- 2. "Call a human": no green, and a real fill ---- */
html body.cl-v2:not(.cl-x) .cl-co__call,
html body.cl-v2:not(.cl-x) a.cl-co__call {
  background-color: #6D28D9 !important;
  background-image: linear-gradient(#7C3AED 0%, #5B21B6 100%) !important;
  border: 2px solid #5B21B6 !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
  font-weight: 700 !important;
}
html body.cl-v2:not(.cl-x) .cl-co__call *,
html body.cl-v2:not(.cl-x) .cl-co__callText {
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}
html body.cl-v2:not(.cl-x) .cl-co__call svg {
  stroke: #FFFFFF !important;
  color: #FFFFFF !important;
}
/* the close control was a 22% wash with near-black glyph */
html body.cl-v2:not(.cl-x) .cl-co__close {
  background-color: #6D28D9 !important;
  background-image: linear-gradient(#7C3AED 0%, #5B21B6 100%) !important;
  border: 2px solid #5B21B6 !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}
html body.cl-v2:not(.cl-x) .cl-co__close svg {
  stroke: #FFFFFF !important;
  color: #FFFFFF !important;
}

/* ---- 3. the lighter half of the text ---- */
html body.cl-v2:not(.cl-x).cl-embed label,
html body.cl-v2:not(.cl-x).cl-embed .cl-ck__label,
html body.cl-v2:not(.cl-x).cl-embed th,
html body.cl-v2:not(.cl-x).cl-embed td {
  color: #18181B !important;
  -webkit-text-fill-color: #18181B !important;
}
html body.cl-v2:not(.cl-x).cl-embed .cl-paynow__k,
html body.cl-v2:not(.cl-x).cl-embed .cl-protect__desc,
html body.cl-v2:not(.cl-x).cl-embed p {
  color: #3F3F46 !important;
  -webkit-text-fill-color: #3F3F46 !important;
}


/* ==================================================================
 * 42. THE LAST OF THE WASHOUT
 *
 * sc/v2wash.js, which measures every border against what it sits on and every
 * piece of text against its own composited backdrop, found these after the
 * generated lines layer had done its two passes. They survive because they are
 * not written as a colour the generator can read — they come through at
 * runtime — so they are named here.
 *
 *   a.cl-topbar__link        #3B1573 on #4C1D95   1.24:1
 *     Dark purple on the dark purple top bar. The worst of the set: it is the
 *     support email, on every page, effectively invisible.
 *
 *   div.cl-ticker            #E9E3FF   1.24:1
 *   span.cl-feat__sizes      #E9E3FF   1.24:1
 *   h2.is-revealed           #F7F2FF   1.10:1
 *   div.cl-footer__col       #E4E4E7 on #FAFAFA  1.22:1
 * ================================================================== */
html body.cl-v2:not(.cl-x) .cl-topbar a.cl-topbar__link,
html body.cl-v2:not(.cl-x) a.cl-topbar__link,
html body.cl-v2:not(.cl-x) .cl-topbar__link,
html body.cl-v2:not(.cl-x) .cl-topbar__calltag,
html body.cl-v2:not(.cl-x) .cl-topbar__promo {
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
  border-color: #E5E1F2 !important;
  font-weight: 700 !important;
}
html body.cl-v2:not(.cl-x) .cl-topbar a.cl-topbar__link svg,
html body.cl-v2:not(.cl-x) .cl-topbar__calltag svg {
  stroke: #FFFFFF !important;
  color: #FFFFFF !important;
}

html body.cl-v2:not(.cl-x) .cl-ticker,
html body.cl-v2:not(.cl-x) div.cl-ticker,
html body.cl-v2:not(.cl-x) .cl-feat__sizes,
html body.cl-v2:not(.cl-x) span.cl-feat__sizes,
html body.cl-v2:not(.cl-x) .cl-content h2.is-revealed,
html body.cl-v2:not(.cl-x) article h2.is-revealed {
  border-color: #E5E1F2 !important;
}
html body.cl-v2:not(.cl-x) footer .cl-footer__col,
html body.cl-v2:not(.cl-x) footer div.cl-footer__col {
  border-color: #E5E1F2 !important;
}


/* ------------------------------------------------------------------
 * 42b. THE PALE PILLS
 *
 * What the washout scan has left, after 172 -> 15, is almost all a border
 * sitting on its OWN fill — a purple button's purple edge, the current page
 * number's edge on its own purple. That is not washout; a control's border
 * does not need to contrast with the control.
 *
 * These two are real: a pale lavender edge on a pale lavender pill, which is
 * the pill having no edge at all.
 *
 *   span.cl-cardsizes        #E9E3FF on #F5F3FF  1.13:1
 *   div.cl-paynotice__code   #E9E3FF on #F5F3FF  1.13:1
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-cardsizes,
html body.cl-v2:not(.cl-x) span.cl-cardsizes,
html body.cl-v2:not(.cl-x) .cl-paynotice__code,
html body.cl-v2:not(.cl-x) div.cl-paynotice__code {
  border: 2px solid #B9A9E8 !important;
}


/* ------------------------------------------------------------------
 * 42c. THE LAST GREEN: AN SVG STROKE
 *
 * The checkout scan is down to one green thing — an svg stroked #1F7A4D, the
 * phone glyph in the call controls. SVG strokes are not caught by the
 * background/colour sweeps because they are neither, which is how this one
 * outlived four passes.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) svg[stroke="#1F7A4D"],
html body.cl-v2:not(.cl-x) svg[stroke="#14603A"],
html body.cl-v2:not(.cl-x) .cl-paynotice svg,
html body.cl-v2:not(.cl-x) .cl-paynotice__cta svg,
html body.cl-v2:not(.cl-x) .cl-callsheet svg,
html body.cl-v2:not(.cl-x) .cl-co__call svg,
html body.cl-v2:not(.cl-x) .cl-calltab svg {
  stroke: currentColor !important;
  color: inherit !important;
}
html body.cl-v2:not(.cl-x) .cl-paynotice__cta,
html body.cl-v2:not(.cl-x) a.cl-paynotice__cta,
html body.cl-v2:not(.cl-x) .cl-paynotice__call {
  background-color: #6D28D9 !important;
  background-image: linear-gradient(#7C3AED 0%, #5B21B6 100%) !important;
  border: 2px solid #5B21B6 !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}

/* .cl-co__callText computed #111118 for `color` while rendering white through
   -webkit-text-fill-color. That works, but it leaves the real colour one
   stylesheet away from being dark text on a purple button. Both set. */
html body.cl-v2:not(.cl-x) .cl-co__callText,
html body.cl-v2:not(.cl-x) span.cl-co__callText {
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}


/* ==================================================================
 * 43. THE CHECKOUT HEADER IS CRAMPED ON A PHONE
 *
 * Noah: "look at the alignment and the spacing... the text is smashed."
 *
 * Measured at 360/375/390/414/430 — the four controls total 272px in a 358px
 * header, so nothing actually overlaps. (The X, pencil and share icons in the
 * photo are iOS's own screenshot-editor overlay sitting on top of the page,
 * not the site.) But the rhythm inside it is wrong:
 *
 *   left edge -> back      16px
 *   back -> "Checkout"     10px   <- the smash
 *   "Checkout" -> call     41px
 *   call -> close          41px
 *   close -> right edge     8px   <- half the left inset
 *
 * A 10px gap between a 44px control and the title reads as the title being
 * stuck to the button, and the 16/8 asymmetry tips the whole row left. Even
 * insets and a floor under the gap.
 * ================================================================== */
html body.cl-v2:not(.cl-x) .cl-co__head,
html body.cl-v2:not(.cl-x) header.cl-co__head {
  padding: 12px 14px !important;
  gap: 14px !important;
  align-items: center !important;
}
html body.cl-v2:not(.cl-x) .cl-co__title,
html body.cl-v2:not(.cl-x) h2.cl-co__title {
  margin: 0 !important;
  flex: 1 1 auto !important;
  min-width: 0 !important;
  text-align: left !important;
}
/* the call pill is the only elastic item — let it give ground first on the
   narrowest phones rather than squeezing the title */
html body.cl-v2:not(.cl-x) .cl-co__call,
html body.cl-v2:not(.cl-x) a.cl-co__call {
  flex: 0 1 auto !important;
  min-width: 0 !important;
  white-space: nowrap !important;
}
@media (max-width: 379px) {
  html body.cl-v2:not(.cl-x) .cl-co__head {
    padding: 10px 12px !important;
    gap: 10px !important;
  }
}


/* ==================================================================
 * 44. THE LOCK
 *
 * Noah, twice: "the locks are not noticeable", then "the lock is still
 * fucked."
 *
 * Measured in the cart drawer: svg.cl-lock has stroke #3F3F46 sitting on the
 * #6D28D9 Secure checkout button — 1.47:1. A dark grey lock on a purple
 * button is invisible, and it is MY doing: block 14 set
 *
 *     [class*="secure"] svg { stroke: #3F3F46 }
 *
 * to make the "Secure" chip's lock readable on a light chip, and that selector
 * also catches the lock inside the filled button, where the correct colour is
 * the opposite.
 *
 * A lock has no colour of its own — it belongs to whatever it is sitting in.
 * So every lock follows currentColor: white inside a filled button, dark on a
 * light chip, with no selector having to know which is which.
 * ================================================================== */
html body.cl-v2:not(.cl-x) .cl-lock,
html body.cl-v2:not(.cl-x) svg.cl-lock,
html body.cl-v2:not(.cl-x) .cl-lock path,
html body.cl-v2:not(.cl-x) [class*="secure"] svg,
html body.cl-v2:not(.cl-x) [class*="secure"] svg path,
html body.cl-v2:not(.cl-x) .cl-btn svg,
html body.cl-v2:not(.cl-x) button svg,
html body.cl-v2:not(.cl-x) a.cl-btn svg {
  stroke: currentColor !important;
  color: inherit !important;
  fill: none !important;
}
/* and give it enough weight to read at 14-16px */
html body.cl-v2:not(.cl-x) .cl-lock,
html body.cl-v2:not(.cl-x) svg.cl-lock {
  stroke-width: 2.2 !important;
  opacity: 1 !important;
}

/*
 * The primary call to action, one step deeper.
 *
 * White on the gradient's light stop measured 5.70:1 — a pass, but Noah is
 * asking for contrast you feel, not contrast that clears a threshold. One
 * step down the same ramp takes the worst case to 7.10:1 and the best to
 * 10.95:1, and the button reads as a solid object rather than a wash.
 */
html body.cl-v2:not(.cl-x) .cl-drawer__cta,
html body.cl-v2:not(.cl-x) a.cl-drawer__cta,
html body.cl-v2:not(.cl-x) #place_order,
html body.cl-v2:not(.cl-x) button.button.alt,
html body.cl-v2:not(.cl-x) .cl-atc__btn,
html body.cl-v2:not(.cl-x) .cl-btn,
html body.cl-v2:not(.cl-x) a.cl-btn,
html body.cl-v2:not(.cl-x) .cl-hero2__shop,
html body.cl-v2:not(.cl-x) .cl-feat__btn,
html body.cl-v2:not(.cl-x) .cl-bundle__btn,
html body.cl-v2:not(.cl-x) .cl-chero__explore {
  background-image: linear-gradient(#6D28D9 0%, #4C1D95 100%) !important;
  background-color: #5B21B6 !important;
}


/* ------------------------------------------------------------------
 * 44b. THE CTA GRADIENT, AT THE PALETTE'S OWN SPECIFICITY
 *
 * Block 44's deeper gradient did not take: the palette states it as
 *
 *   html body.cl-v2:not(.cl-x) .cl-btn:not(.cl-btn--secondary):not(...)
 *
 * whose :not() chain counts as classes — (0,5,2) against my (0,3,3). Matched
 * on the same shape so the tie resolves here, in the later file.
 *
 * White on the light stop goes 5.70:1 -> 7.10:1; on the dark stop, 10.95:1.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-btn:not(.cl-btn--secondary):not(.cl-btn--ghost),
html body.cl-v2:not(.cl-x) a.cl-btn:not(.cl-btn--secondary):not(.cl-btn--ghost),
html body.cl-v2:not(.cl-x) button.cl-btn:not(.cl-btn--secondary):not(.cl-btn--ghost),
html body.cl-v2:not(.cl-x) .cl-drawer__cta:not(.cl-btn--secondary):not(.cl-btn--ghost),
html body.cl-v2:not(.cl-x) .cl-atc__btn:not(.cl-btn--secondary):not(.cl-btn--ghost) {
  background-image: linear-gradient(#6D28D9 0%, #4C1D95 100%) !important;
  background-color: #5B21B6 !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}


/* ==================================================================
 * 45. CONTRAST FOR THE EYEBALL — THE 7:1 PASS
 *
 * Noah: "Make sure there's contrast for the eyeball."
 *
 * sc/v2wash.js re-run at 7:1 for text and 3:1 for icons, rather than the 4.5
 * WCAG floor everything already clears. Five patterns came out, every one of
 * them a near-miss rather than a disaster — which is exactly what "washed
 * out" feels like:
 *
 *   #FFFFFF on #7C3AED   5.70:1   every purple button block 44b did not reach
 *   #92400E on #FFFBEB   6.84:1   the amber Zelle bar
 *   #71717A on #FFFFFF   4.83:1   "3 mL lyophilized vial", "Category:"
 *   #6D28D9 on #F2EBFD   6.12:1   purple labels on pale lavender
 *   #8B5CF6 on #D8C4F9   2.66:1   icons inside pale lavender circles
 * ================================================================== */

/* ---- every purple button, not just .cl-btn ---- */
html body.cl-v2:not(.cl-x) button.cl-search__btn,
html body.cl-v2:not(.cl-x) form.woocommerce-product-search > button,
html body.cl-v2:not(.cl-x) .cl-pagenav__shop,
html body.cl-v2:not(.cl-x) a.cl-pagenav__shop,
html body.cl-v2:not(.cl-x) .cl-hero2__shop,
html body.cl-v2:not(.cl-x) a.cl-hero2__shop,
html body.cl-v2:not(.cl-x) .cl-faqhelp__btn,
html body.cl-v2:not(.cl-x) button.cl-faqhelp__btn,
html body.cl-v2:not(.cl-x) .cl-chero__explore,
html body.cl-v2:not(.cl-x) .cl-feat__btn,
html body.cl-v2:not(.cl-x) .cl-bundle__btn,
html body.cl-v2:not(.cl-x) .cl-paynotice__cta,
html body.cl-v2:not(.cl-x) .cl-callsheet__btn,
html body.cl-v2:not(.cl-x) .cl-co__call,
html body.cl-v2:not(.cl-x) .cl-calltab,
html body.cl-v2:not(.cl-x) .cl-tabmini,
html body.cl-v2:not(.cl-x) .cl-acct__x,
html body.cl-v2:not(.cl-x) .cl-co__close,
html body.cl-v2:not(.cl-x) .cl-popback,
html body.cl-v2:not(.cl-x) .cl-sheet__x,
html body.cl-v2:not(.cl-x) .cl-refsheet__x,
html body.cl-v2:not(.cl-x) .woocommerce button.button,
html body.cl-v2:not(.cl-x) .woocommerce input.button {
  background-image: linear-gradient(#6D28D9 0%, #4C1D95 100%) !important;
  background-color: #5B21B6 !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}

/* ---- the amber bar: 6.84 -> 8.75 ---- */
html body.cl-v2:not(.cl-x) .cl-zbar,
html body.cl-v2:not(.cl-x) .cl-zbar *,
html body.cl-v2:not(.cl-x) .cl-zbar__txt,
html body.cl-v2:not(.cl-x) .cl-zbar__tag,
html body.cl-v2:not(.cl-x) aside.cl-zbar {
  color: #78350F !important;
  -webkit-text-fill-color: #78350F !important;
}
html body.cl-v2:not(.cl-x) .cl-zbadge,
html body.cl-v2:not(.cl-x) .cl-zbar__pill,
html body.cl-v2:not(.cl-x) .cl-paynotice__save {
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}

/* ---- the light greys: 4.6-4.8 -> 10.4 ---- */
html body.cl-v2:not(.cl-x) .posted_in,
html body.cl-v2:not(.cl-x) .cl-spec__v,
html body.cl-v2:not(.cl-x) .cl-bundle__v,
html body.cl-v2:not(.cl-x) .product_meta,
html body.cl-v2:not(.cl-x) .product_meta span,
html body.cl-v2:not(.cl-x) .woocommerce-product-details__short-description,
html body.cl-v2:not(.cl-x) dd,
html body.cl-v2:not(.cl-x) small {
  color: #3F3F46 !important;
  -webkit-text-fill-color: #3F3F46 !important;
}

/* ---- purple labels on pale lavender: 6.1-6.8 -> 9.0+ ---- */
html body.cl-v2:not(.cl-x) .cl-contact__label,
html body.cl-v2:not(.cl-x) span.cl-contact__label,
html body.cl-v2:not(.cl-x) .posted_in a,
html body.cl-v2:not(.cl-x) .product_meta a,
html body.cl-v2:not(.cl-x) .cl-eyebrow,
html body.cl-v2:not(.cl-x) .cl-feat__eyebrow,
html body.cl-v2:not(.cl-x) .cl-picks__eyebrow,
html body.cl-v2:not(.cl-x) .cl-bundles__eyebrow,
html body.cl-v2:not(.cl-x) .cl-section__eyebrow {
  color: #4C1D95 !important;
  -webkit-text-fill-color: #4C1D95 !important;
}

/* ---- icons inside pale circles: 2.66 -> 7.0+ ---- */
html body.cl-v2:not(.cl-x) .cl-contact__icon svg,
html body.cl-v2:not(.cl-x) .cl-contact__icon path,
html body.cl-v2:not(.cl-x) .cl-ref__num,
html body.cl-v2:not(.cl-x) [class*="__icon"] svg,
html body.cl-v2:not(.cl-x) [class*="__icon"] path,
html body.cl-v2:not(.cl-x) .cl-hero2__trust svg,
html body.cl-v2:not(.cl-x) .cl-hero2__trust path {
  stroke: #4C1D95 !important;
  color: #4C1D95 !important;
}


/* ------------------------------------------------------------------
 * 45b. THE SAME FIVE, AT A SPECIFICITY THAT WINS
 *
 * Block 45 named the right elements and lost. The palette states its button
 * rules as `.cl-btn:not(.cl-btn--secondary):not(.cl-btn--ghost)` — a :not()
 * chain counts as classes, so it sits at (0,5,2) while a plain
 * `html body.cl-v2:not(.cl-x) .cl-hero2__shop` is (0,3,3).
 *
 * Padding my own selectors with the same harmless :not() chain brings them
 * level, and this file loads last. The alternative — moving the violet ramp
 * again in the palette builder — would restyle every purple on the site to
 * fix five of them.
 * ------------------------------------------------------------------ */
/*
 * NOT a blanket `button`. The first version of this rule was
 *   html body.cl-v2:not(.cl-x) button:not(.cl-x):not(.cl-y)
 * which swept in the quantity steppers and left white on #9772D1 at 3.7:1 —
 * small light controls are not primary buttons and must not take the fill.
 */
html body.cl-v2:not(.cl-x) button.cl-search__btn:not(.cl-x):not(.cl-y),
html body.cl-v2:not(.cl-x) form.woocommerce-product-search button:not(.cl-x):not(.cl-y),
html body.cl-v2:not(.cl-x) .cl-hero2__shop:not(.cl-x):not(.cl-y),
html body.cl-v2:not(.cl-x) .cl-pagenav__shop:not(.cl-x):not(.cl-y),
html body.cl-v2:not(.cl-x) .cl-faqhelp__btn:not(.cl-x):not(.cl-y),
html body.cl-v2:not(.cl-x) .cl-atc__btn:not(.cl-x):not(.cl-y),
html body.cl-v2:not(.cl-x) .cl-feat__btn:not(.cl-x):not(.cl-y),
html body.cl-v2:not(.cl-x) .cl-chero__explore:not(.cl-x):not(.cl-y) {
  background-image: linear-gradient(#6D28D9 0%, #4C1D95 100%) !important;
  background-color: #5B21B6 !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}
/* the secondary/ghost buttons are light-filled and must NOT go purple */
html body.cl-v2:not(.cl-x) button.cl-btn--secondary,
html body.cl-v2:not(.cl-x) button.cl-btn--ghost,
html body.cl-v2:not(.cl-x) button.cl-wait__open,
html body.cl-v2:not(.cl-x) .cl-atc__opt,
html body.cl-v2:not(.cl-x) button.cl-pill,
html body.cl-v2:not(.cl-x) .cl-qty button,
html body.cl-v2:not(.cl-x) button.show-password-input {
  background-image: none !important;
  background-color: transparent !important;
  color: #4C1D95 !important;
  -webkit-text-fill-color: #4C1D95 !important;
}

/* the amber family, one step deeper everywhere it appears */
html body.cl-v2:not(.cl-x) .cl-zbar__tag:not(.cl-x):not(.cl-y),
html body.cl-v2:not(.cl-x) span.cl-zbar__tag:not(.cl-x):not(.cl-y),
html body.cl-v2:not(.cl-x) .cl-paynotice__zelle:not(.cl-x):not(.cl-y),
html body.cl-v2:not(.cl-x) p.cl-paynotice__zelle:not(.cl-x):not(.cl-y) {
  color: #78350F !important;
  -webkit-text-fill-color: #78350F !important;
}
html body.cl-v2:not(.cl-x) .cl-paynotice__save:not(.cl-x):not(.cl-y),
html body.cl-v2:not(.cl-x) span.cl-paynotice__save:not(.cl-x):not(.cl-y),
html body.cl-v2:not(.cl-x) .cl-zbadge:not(.cl-x):not(.cl-y) {
  background-color: #78350F !important;
  background-image: none !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}

/* the bundle spec values — "3 mL lyophilized vial", "31G · 5/16" · 1 mL" */
html body.cl-v2:not(.cl-x) .cl-bundle__row span,
html body.cl-v2:not(.cl-x) .cl-bundle span:not(.cl-bundle__k),
html body.cl-v2:not(.cl-x) .cl-bundle__spec span,
html body.cl-v2:not(.cl-x) li.cl-bundle span:not([class]) {
  color: #3F3F46 !important;
  -webkit-text-fill-color: #3F3F46 !important;
}

/* "Details" and other purple links on an off-white panel */
html body.cl-v2:not(.cl-x) a.cl-details,
html body.cl-v2:not(.cl-x) .cl-details,
html body.cl-v2:not(.cl-x) summary a,
html body.cl-v2:not(.cl-x) .woocommerce-tabs a {
  color: #4C1D95 !important;
  -webkit-text-fill-color: #4C1D95 !important;
}


/* ==================================================================
 * 46. ICONS FOLLOW THEIR TEXT. ALWAYS.
 *
 * I have now made the same mistake twice in this file:
 *
 *   block 14  [class*="secure"] svg { stroke: #3F3F46 }
 *             -> a dark lock on the purple Secure checkout button, 1.47:1
 *   block 45  [class*="__icon"] svg { stroke: #4C1D95 }
 *             -> dark purple icons on the #6D28D9 buttons, 1.54:1
 *
 * Both times the fix was right for the surface I was looking at and wrong for
 * the one I was not. An icon has no colour of its own: it is punctuation for
 * the text beside it. So every decorative icon inherits currentColor, and it
 * is correct on a white card, a purple button and an amber bar without any
 * selector having to know which it is.
 *
 * This rule is LAST on purpose — it supersedes every hardcoded icon colour
 * earlier in this file, including mine.
 * ================================================================== */
html body.cl-v2:not(.cl-x) svg:not(.cl-logo):not([class*="logo"]):not([class*="brand"]),
html body.cl-v2:not(.cl-x) svg:not(.cl-logo):not([class*="logo"]):not([class*="brand"]) path,
html body.cl-v2:not(.cl-x) svg:not(.cl-logo):not([class*="logo"]):not([class*="brand"]) circle,
html body.cl-v2:not(.cl-x) svg:not(.cl-logo):not([class*="logo"]):not([class*="brand"]) rect,
html body.cl-v2:not(.cl-x) svg:not(.cl-logo):not([class*="logo"]):not([class*="brand"]) line,
html body.cl-v2:not(.cl-x) svg:not(.cl-logo):not([class*="logo"]):not([class*="brand"]) polyline {
  stroke: currentColor !important;
  color: inherit !important;
}
/* brand artwork keeps its own colours */
html body.cl-v2:not(.cl-x) .cl-logo svg,
html body.cl-v2:not(.cl-x) .cl-logo path,
html body.cl-v2:not(.cl-x) [class*="logo"] svg path,
html body.cl-v2:not(.cl-x) [class*="brand"] svg path,
html body.cl-v2:not(.cl-x) #payment label img,
html body.cl-v2:not(.cl-x) #payment label svg {
  stroke: initial !important;
  color: initial !important;
}

/* ---- the two text items still short of 7:1 ---- */
html body.cl-v2:not(.cl-x) .cl-cardsizes,
html body.cl-v2:not(.cl-x) span.cl-cardsizes,
html body.cl-v2:not(.cl-x) .cl-feat__sizes,
html body.cl-v2:not(.cl-x) span.cl-feat__sizes {
  color: #4C1D95 !important;
  -webkit-text-fill-color: #4C1D95 !important;
}
html body.cl-v2:not(.cl-x) button.cl-btn:not(.cl-btn--secondary):not(.cl-btn--ghost):not(.cl-wait__open),
html body.cl-v2:not(.cl-x) a.cl-btn:not(.cl-btn--secondary):not(.cl-btn--ghost),
html body.cl-v2:not(.cl-x) .cl-feat__btn:not(.cl-btn--secondary):not(.cl-btn--ghost) {
  background-image: linear-gradient(#6D28D9 0%, #4C1D95 100%) !important;
  background-color: #5B21B6 !important;
}


/* ------------------------------------------------------------------
 * 46b. THE LAST TWO, PINNED BY MEASUREMENT
 *
 *   button.cl-atc__btn   The palette states it at (0,6,4):
 *       html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc__btn:not(...)
 *     against my (0,6,3). Matched on the full path.
 *
 *   span.cl-contact__icon   color #8B5CF6 on a 22% purple wash (#D8C4F9),
 *     2.66:1. The icon inherits currentColor correctly now (block 46) — the
 *     colour it is inheriting is simply too light for the chip it sits in.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc__btn:not(.cl-btn--secondary):not(.cl-btn--ghost),
html body.cl-v2:not(.cl-x) ul.products li.product.product button.cl-atc__btn:not(.cl-btn--secondary):not(.cl-btn--ghost),
html body.cl-v2:not(.cl-x) ul.products li.product.product a.cl-atc__btn:not(.cl-btn--secondary):not(.cl-btn--ghost) {
  background-image: linear-gradient(#6D28D9 0%, #4C1D95 100%) !important;
  background-color: #5B21B6 !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}

/*
 * Only the icon itself, and only `color` — never -webkit-text-fill-color on a
 * CONTAINER.
 *
 * The first version of this was `[class*="__icon"] { color: #4C1D95;
 * -webkit-text-fill-color: #4C1D95 }`, and .cl-sticky-cart__badge lives inside
 * .cl-sticky-cart__icon. It inherited the fill, so the badge computed
 * `color: #FFFFFF` with `-webkit-text-fill-color: #4C1D95` — and the fill wins
 * silently. The count on the cart went to dark purple on purple, about 1.5:1.
 *
 * I nearly dismissed it: reading `color` alone said #FFFFFF and looked fine.
 * sc/v2buy.js reads the fill first and was right both times it flagged this.
 */
/*
 * The hardcoded `.cl-contact__icon > svg { color: #4C1D95 }` that used to sit
 * here is GONE. It was (0,3,3) and block 44 states
 *   html body.cl-v2:not(.cl-x) svg:not(.cl-logo):not([class*="logo"]):not([class*="brand"])
 * at (0,5,3) — five classes to my three, both !important, so block 44's
 * `color: inherit` won and the svg kept inheriting #8B5CF6. It MATCHED, so a
 * matches() check said yes; only sorting the matching rules by real
 * specificity showed it losing. See block 47 for the fix that actually lands.
 */
/* the count on the cart is white on its own purple pill */
html body.cl-v2:not(.cl-x) .cl-sticky-cart__badge,
html body.cl-v2:not(.cl-x) span.cl-sticky-cart__badge,
html body.cl-v2:not(.cl-x) .cl-cart-btn__badge,
html body.cl-v2:not(.cl-x) [class*="__badge"] {
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}

/* the MG chip's edge — block 42b set it and lost to the palette; padded to
   match, the way every other one in this file had to be */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-cardsizes:not(.cl-x):not(.cl-y),
html body.cl-v2:not(.cl-x) .cl-cardsizes:not(.cl-x):not(.cl-y),
html body.cl-v2:not(.cl-x) .cl-feat__sizes:not(.cl-x):not(.cl-y) {
  border: 2px solid #A78BFA !important;
}

/* the quantity steppers and other small light controls: light fill, dark ink,
   a visible edge — the opposite of a primary button */
html body.cl-v2:not(.cl-x) .cl-qty__btn,
html body.cl-v2:not(.cl-x) button.cl-qty__btn,
html body.cl-v2:not(.cl-x) .cl-qty button,
html body.cl-v2:not(.cl-x) .quantity button {
  background-image: none !important;
  background-color: #FFFFFF !important;
  color: #4C1D95 !important;
  -webkit-text-fill-color: #4C1D95 !important;
  border: 2px solid #A78BFA !important;
}


/* ------------------------------------------------------------------
 * 47. THE LAST TWO, FIXED AT THE THING THAT WAS ACTUALLY WRONG
 * ------------------------------------------------------------------ */

/*
 * (a) The footer contact chips — 28 of the gate's washout failures, which was
 * the same two icons counted across 4 pages x 2 widths.
 *
 *   span.cl-contact__icon  color #8B5CF6  (var(--ui-400))
 *   on its own rgba(124,58,237,0.22) wash, composited to #D8C4F9
 *   -> 2.66:1, under the 3:1 icon floor.
 *
 * The icon was never the problem: block 44 gives it `color: inherit` and that
 * is correct — an icon is punctuation for the text beside it and has no colour
 * of its own. What it inherits is the chip's, and the chip's was too light for
 * its own tint. So darken the CHIP and the icon follows for free.
 *
 *   #4C1D95 on #D8C4F9 = 6.88:1   (was 2.66:1)
 *
 * `color` only. Never -webkit-text-fill-color on a container — that is what
 * put the cart badge at 1.5:1, because the badge lives inside the icon span
 * and inherited the fill, which beats `color` silently.
 */
html body.cl-v2:not(.cl-x) .cl-contact__icon,
html body.cl-v2:not(.cl-x) span.cl-contact__icon,
html body.cl-v2:not(.cl-x) .cl-contact__link .cl-contact__icon {
  color: #4C1D95 !important;
}

/*
 * (b) "OUT OF STOCK" clipped 7.6px past its box at 360.
 *
 * Measured, not guessed — the border box was never the constraint:
 *
 *   360   border box 93.5   padding 4+4   border 1+1   content box 83.5
 *         text "OUT OF STOCK" at 12.5px/700 = 91.1   ->  7.6px over
 *   375   content box 91.0  vs 91.1                  ->  0.1px over
 *   390   content box 97.0  vs 91.1                  ->  fits
 *
 * The card is 155.5px at 360 and the two stacked buttons get 93.5px of it, so
 * the button cannot be made wider. Tracking is already 0 on this variant and
 * 12.5px is the type floor, so there is nothing left to shave: 91.1px of text
 * does not go into 83.5px on one line at any legible size.
 *
 * So let it wrap. "OUT OF" (~48px) and "STOCK" (~42px) each clear the 79.5px
 * content box on their own line, and two lines at 1.2 come to 30px inside a
 * 46px min-height — it cannot squash, and it cannot clip at any width.
 */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc--out .cl-atc__btn,
html body.cl-v2:not(.cl-x) ul.products li.product.product button.cl-atc__btn:disabled,
html body.cl-v2:not(.cl-x) ul.products li.product.product button.cl-atc__btn[disabled] {
  white-space: normal !important;
  text-wrap: balance !important;
  overflow-wrap: break-word !important;
  line-height: 1.2 !important;
  padding: 6px 6px !important;
  min-height: 46px !important;
  height: auto !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  text-align: center !important;
}


/* ------------------------------------------------------------------
 * 48. THE SPIRALS SPIRAL — the plate no longer spins
 *
 * Noah, 2026-10-04: "i dont want the background spinning it looks horrible.
 * i want the spirals to spiral."
 *
 * He is right, and the old animation could never have done what he asked.
 * The artwork is a RIBBON FRAME with an empty white centre, and it was turned
 * through a full 360 degrees as one rigid plate. A frame rotated about its own
 * centre reads as a turntable: the whole picture goes round, and nothing
 * inside it moves relative to anything else, so no ribbon ever appears to coil.
 *
 * A spiral is rotation AND scaling at the same time — that product is what
 * bends a circular path into a spiral one. Each layer turns a little while it
 * grows, so every point on a ribbon travels outward along a spiral instead of
 * round a circle.
 *
 * Scale cannot grow forever and the jump back is very visible, so there are
 * TWO layers running the same animation half a cycle apart, each fading in as
 * it starts and out as it ends. One is always arriving while the other leaves,
 * so the motion never restarts on screen — a continuous unfurl rather than the
 * in-and-out pulse he rejected earlier.
 *
 * IT HAS ITS OWN ELEMENT, AND THAT MATTERS TWICE OVER:
 *   - .cl-hero2::before carries `opacity: 0.9 !important`, and an !important
 *     declaration BEATS a CSS animation. Animating opacity there is dropped
 *     silently, so the cross-fade would never happen and the loop seam would
 *     stay — looking like a glitch in the artwork.
 *   - .cl-scene is NOT an empty div. It is the particle field, and both of its
 *     pseudo elements are already taken by the radial-gradient dots (::after
 *     is display:none). Borrowing them stretched the dots to 118vmax and
 *     animated them. I did exactly that first; this is the fix.
 * ------------------------------------------------------------------ */

/* the old rotating plate stops turning and gets out of the way */
html body.cl-v2 .cl-hero2::before,
html body.cl-v2:not(.cl-x) .cl-hero2::before,
html body.cl-v2:not(.cl-x) section.cl-hero2::before {
  animation: none !important;
  opacity: 0 !important;
}

html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral {
  position: absolute !important;
  inset: 0 !important;
  width: auto !important;
  height: auto !important;
  margin: 0 !important;
  z-index: 0 !important;
  overflow: hidden !important;
  pointer-events: none !important;
}

html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral::before,
html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral::after {
  content: "" !important;
  position: absolute !important;
  top: 50% !important;
  left: 50% !important;
  width: 118vmax !important;
  height: 118vmax !important;
  margin: 0 !important;
  transform-origin: 50% 50% !important;
  /* !important on the artwork too. The first version left it off and a dot
     pattern from another rule won, so the layers animated with no ribbons. */
  background-image: url("/wp-content/uploads/corelabs-hero/corelabs-bg-v2-1536.webp") !important;
  background-repeat: no-repeat !important;
  background-position: center center !important;
  background-size: contain !important;
  z-index: 0 !important;
  pointer-events: none !important;
  will-change: transform, opacity !important;
  animation: coreLabsSpiralOut 54s linear infinite !important;
}
/* the second copy runs half a cycle behind — a NEGATIVE delay starts it there
   instead of making the page wait 27 seconds for it to appear */
html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral::after {
  animation-delay: -27s !important;
}

/* same resolution ladder the old plate used, so phones stay sharp */
@media (min-width: 600px), (min-resolution: 1.5dppx) {
  html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral::before,
  html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral::after {
    background-image: url("/wp-content/uploads/corelabs-hero/corelabs-bg-v2-2560.webp") !important;
  }
}
@media (min-width: 1200px), (min-resolution: 1.5dppx) and (min-width: 820px) {
  html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral::before,
  html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral::after {
    background-image: url("/wp-content/uploads/corelabs-hero/corelabs-bg-v2-3840.webp") !important;
  }
}

/*
 * 132deg, not 360. A full turn is what made it look like a record; a third of
 * a turn across the whole cycle is enough to read the ribbons as winding
 * without the frame ever coming back round to where it started.
 * Scale 0.86 -> 1.62 is the outward travel. Outward, not inward: the centre of
 * this artwork is empty white, so pulling inward drains the ribbons into a
 * hole, while pushing outward unfurls them past the edge.
 */
/*
 * The fade is a straight triangle - 0 at the start, peak at the midpoint, 0 at
 * the end - and that shape is not cosmetic, it is the only one that holds the
 * total steady.
 *
 * With two layers half a cycle apart, layer B(t) = A(t + 0.5). For a linear
 * triangle peaking at P: A = 2Pt rising, so B = P - 2Pt falling, and the sum
 * is 2Pt + P - 2Pt = P at EVERY instant.
 *
 * The first version held each layer flat at 0.9 from 16% to 84%, so for most
 * of the cycle both were at 0.9 at once and the measured total swung between
 * 1.16 and 1.80. That is a brightness pulse: the hero would have breathed
 * darker in the middle of every cycle and lighter at each handover - the exact
 * in-and-out throb Noah said he did not want, just arriving a different way.
 */
@keyframes coreLabsSpiralOut {
  0%   { transform: translate(-50%, -50%) rotate(0deg)   scale(0.86); opacity: 0; }
  50%  { opacity: 0.9; }
  100% { transform: translate(-50%, -50%) rotate(132deg) scale(1.62); opacity: 0; }
}

/* asked their system for no motion: one still frame, no cross-fade */
@media (prefers-reduced-motion: reduce) {
  html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral::before {
    animation: none !important;
    transform: translate(-50%, -50%) scale(1.1) !important;
    opacity: 0.9 !important;
  }
  html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral::after { display: none !important; }
}


/* ------------------------------------------------------------------
 * 49. THE PRODUCT PAGES THE OLD GATE NEVER LOOKED AT
 *
 * sc/SWEEP.js walks all 33 URLs instead of the 10 sc/CHECK.js knows, and
 * found the same two faults on all 14 product pages:
 *
 *   p.stock.in-stock      #6FE3AC  — mint GREEN, on a design that has none
 *   .sku_wrapper etc.     12px     — under the 12.5px floor
 *
 * BOTH HAVE THE SAME CAUSE, and it is trap #5. The generated rules exist and
 * look right:
 *     html body.cl-v2:not(.cl-x) .woocommerce div.product .product_meta .sku_wrapper
 * but `body` ITSELF carries .woocommerce — it is not a descendant. Measured on
 * /product/nad-500mg: `document.querySelectorAll('body .woocommerce').length`
 * is ZERO, so that selector matches nothing and never has. Probing the element
 * for rules setting font-size or color returns "no rule sets this property" —
 * these two have simply never been themed.
 *
 * So: no .woocommerce hop. Target the elements where they actually live.
 * ------------------------------------------------------------------ */

/* "In stock" is the last green on the site. Deep purple, not amber — amber is
 * the attention accent for offers, and a reassurance line should not shout.
 * #4C1D95 on white is 12.02:1. */
html body.cl-v2:not(.cl-x) p.stock,
html body.cl-v2:not(.cl-x) p.stock.in-stock,
html body.cl-v2:not(.cl-x) div.product p.stock.in-stock {
  color: #4C1D95 !important;
  -webkit-text-fill-color: #4C1D95 !important;
  font-weight: 600 !important;
}

/* the SKU / Category / Tag meta block, on the type scale at last */
html body.cl-v2:not(.cl-x) .product_meta,
html body.cl-v2:not(.cl-x) .product_meta .sku_wrapper,
html body.cl-v2:not(.cl-x) .product_meta .posted_in,
html body.cl-v2:not(.cl-x) .product_meta .tagged_as,
html body.cl-v2:not(.cl-x) div.product .product_meta,
html body.cl-v2:not(.cl-x) div.product .product_meta .sku_wrapper,
html body.cl-v2:not(.cl-x) div.product .product_meta .posted_in,
html body.cl-v2:not(.cl-x) div.product .product_meta .tagged_as {
  font-size: 12.5px !important;
  line-height: 1.5 !important;
}


/* ------------------------------------------------------------------
 * 50. THE CAROUSEL DOTS WERE 4px TALL
 *
 * Found by the tap-target pass sc/SWEEP.js gained on 2026-10-05. These are not
 * decoration: they carry role="tab" and aria-labels (KLOW, R3TA, SEMAX), so a
 * customer presses them to change the product on show. Measured at 390:
 * 52x4 and 34x4. Four pixels of height on a phone.
 *
 * The bar should stay 4px — it looks right. So the HIT AREA grows instead,
 * through a transparent ::after that reaches the 44px minimum. Vertically
 * only: these sit in a row, and widening them would make neighbouring targets
 * overlap so the wrong product gets selected.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-picks__dot {
  position: relative !important;
}
html body.cl-v2:not(.cl-x) .cl-picks__dot::after {
  content: "" !important;
  position: absolute !important;
  left: 0 !important;
  right: 0 !important;
  top: 50% !important;
  height: 44px !important;
  transform: translateY(-50%) !important;
  background: transparent !important;
  pointer-events: auto !important;
}


/* ------------------------------------------------------------------
 * 51. THE PRICE RANGE WRAPPED, AND A DASH WAS LEFT DANGLING
 *
 * Noah, 2026-10-05: "loook ath the pricing! shitty fix it" ... "but no
 * stacking". "$49.99 – $189.99" was breaking after the dash and dropping
 * "$189.99" onto a second line.
 *
 * MEASURED, at 390 and at 360:
 *   price box        147.0 / 133.5
 *   padding          14px left + 14px right
 *   usable content   119.0 / 105.5
 *   the range needs  ~128 at 14px/800
 * So it could not fit, and the only place to break was at the dash.
 *
 * The fix is the PADDING, not the type. 14px of inset on either side of a
 * 147px box is a third of the width spent on nothing, and his own rule is
 * "do not shrink important text simply to force it to fit — fix the layout
 * instead". At 2px the content width is 143 / 129.5 and the range sits on one
 * line at both widths with the type untouched.
 *
 * nowrap is set on the amounts themselves too: the container already had it,
 * but the break was happening BETWEEN the two amount spans, which the
 * container's own white-space does not govern once they are separate boxes.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products li.product.product .price,
html body.cl-v2:not(.cl-x) ul.products li.product .price {
  padding-left: 2px !important;
  padding-right: 2px !important;
  white-space: nowrap !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product .price *,
html body.cl-v2:not(.cl-x) ul.products li.product .price * {
  white-space: nowrap !important;
}
/* the screen-reader duplicate must never take part in layout */
html body.cl-v2:not(.cl-x) ul.products li.product .price .screen-reader-text {
  position: absolute !important;
  width: 1px !important;
  height: 1px !important;
  overflow: hidden !important;
  clip: rect(0 0 0 0) !important;
  white-space: nowrap !important;
}

/* the pay notice's thanks line, now that CORE10 has left that box */
html body.cl-v2:not(.cl-x) .cl-paynotice__thanks {
  text-align: center !important;
  margin: 4px 0 12px !important;
  font-size: 14px !important;
  color: #3F3F46 !important;
  -webkit-text-fill-color: #3F3F46 !important;
}

/*
 * THE CALL TAB — one label, and it has to actually render.
 *
 * Collapsing the four old spans into one broke it: the visible label used to
 * be .cl-tabquiet, and the older CSS hides .cl-calltab__text, so after the
 * change the tab measured 30x50 with a span of 0x0 — the icon alone, no words.
 * A regression I introduced, found by measuring rather than by looking.
 *
 * It stays a side tab, as Noah asked, so the label reads vertically. The
 * rotate(180deg) on top of vertical-rl makes it run bottom-to-top, which is
 * the convention for a tab on the LEFT edge; without it the words read
 * upside-down from the reader's point of view.
 *
 * 44px wide because it is a control you press on a phone, and 30px was under
 * the floor my own sweep enforces.
 */
html body.cl-v2:not(.cl-x) a.cl-calltab {
  display: flex !important;
  flex-direction: column !important;
  align-items: center !important;
  justify-content: center !important;
  gap: 6px !important;
  width: 44px !important;
  min-width: 44px !important;
  padding: 12px 4px !important;
  min-height: 112px !important;
  overflow: visible !important;
}
html body.cl-v2:not(.cl-x) a.cl-calltab .cl-calltab__text {
  display: inline-block !important;
  writing-mode: vertical-rl !important;
  transform: rotate(180deg) !important;
  width: auto !important;
  height: auto !important;
  max-width: none !important;
  max-height: none !important;
  font-size: 12.5px !important;
  font-weight: 700 !important;
  letter-spacing: 0.06em !important;
  white-space: nowrap !important;
  opacity: 1 !important;
  visibility: visible !important;
  overflow: visible !important;
  clip: auto !important;
  clip-path: none !important;
  position: static !important;
}

/*
 * THE PRICE AT 360 ONLY.
 *
 * After block 51 the longest range fits at 390 and still wrapped at 360:
 * usable 129.5 against ~130 needed. The last millimetre comes from the CARD's
 * own 10px inset, not from the type — 6px at this width gives 143.5 and the
 * range sits on one line. Untouched at 390 and above, where it already fits.
 */
@media (max-width: 375px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product,
  html body.cl-v2:not(.cl-x) ul.products li.product {
    padding-left: 6px !important;
    padding-right: 6px !important;
  }
}


/* ------------------------------------------------------------------
 * 52. THE FEATURED CARD PRICE WAS CROWDED
 *
 * Noah, 2026-10-05: "the pricing looks busy as hell crowded really".
 *
 * MEASURED at 1440, each element and the gap to the next:
 *     span.cl-feat__name   "R3TA"         gap  9px
 *     s.cl-feat__was       "$59.99"       gap  1px   <-- touching
 *     span.cl-feat__now    "From $49.99"  gap 12px
 *     span.cl-feat__sizes  "5 · 10 · 20"  gap 12px
 *     span.cl-feat__btn    "Shop now"
 *
 * A rhythm of 9 / 1 / 12 / 12 is not a rhythm. The old price and the new one
 * sat ONE PIXEL apart, which is what reads as crowded — not the type, which is
 * approved and is not touched here.
 *
 * The fix is grouping, which is what spacing is for: the two prices are ONE
 * idea, so they stay close (6px) and get real separation from what follows
 * (18px). Everything else lands on a 6px scale:
 *
 *     name  --12--  was --6-- now  --18--  sizes  --12--  button
 *             ^ a heading, then its price block, then the choices
 *
 * The type sizes, weights and colours are deliberately left exactly as they
 * were. TYPOGRAPHY GUARDIAN: protect, do not redesign.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) .cl-feat__card .cl-feat__name,
html body.cl-v2:not(.cl-x) li.cl-feat__card .cl-feat__name {
  margin-bottom: 12px !important;
}
html body.cl-v2:not(.cl-x) .cl-feat__card .cl-feat__was,
html body.cl-v2:not(.cl-x) li.cl-feat__card s.cl-feat__was {
  display: block !important;
  margin: 0 0 6px !important;
  line-height: 1.2 !important;
}
html body.cl-v2:not(.cl-x) .cl-feat__card .cl-feat__now,
html body.cl-v2:not(.cl-x) li.cl-feat__card span.cl-feat__now {
  display: block !important;
  /* 10, not the 18 the scale would suggest: the nested "From" overhangs the
     line box by ~8px, so 18 rendered as a 28px gap and unbalanced the card
     against the 12 below it. Measured, then corrected. */
  margin: 0 0 10px !important;
  line-height: 1.1 !important;
}
/* "From" is a qualifier on the number beside it, not a line of its own */
html body.cl-v2:not(.cl-x) .cl-feat__card .cl-feat__now small {
  margin-right: 4px !important;
}
html body.cl-v2:not(.cl-x) .cl-feat__card .cl-feat__sizes,
html body.cl-v2:not(.cl-x) li.cl-feat__card span.cl-feat__sizes {
  margin-bottom: 12px !important;
}


/* ------------------------------------------------------------------
 * 53. THE PRODUCT CARDS, REBUILT ON THE CARD HE LIKES
 *
 * Noah, 2026-10-05: "I love the way the starter pack looks. You should have
 * that as the template for all the other stuff... the price is big, it has a
 * little title. Come on now." And: "you just really need to fix the product
 * cards. That's really it."
 *
 * MEASURED, the card he likes against the card he does not, at 390:
 *
 *   .cl-feat__card (likes)        ul.products li.product (does not)
 *     name   16px/700  20h          title  16px/700  74h  ls 1.28px (3 lines)
 *     price  25px/800               price  14px/800       <- smaller than its
 *     sizes  12.5px pill                                     own title
 *     button                        button              <- 77px of dead air
 *                                                          above it
 *
 * Three objective faults, all fixed below:
 *   1. the PRICE was 14px — smaller than the title above it. The most
 *      important number on a shop card was the least prominent thing on it.
 *   2. the TITLE ran to three lines at 0.08em tracking, which is what made it
 *      the loudest element and ate the card.
 *   3. 77px of nothing between price and button, left over from holding every
 *      card to the same height.
 *
 * The type SCALE is not redesigned — 25px/800 and 12.5px are lifted straight
 * off .cl-feat__now and .cl-feat__sizes, the card he approved.
 * ------------------------------------------------------------------ */

/* 1. the price, set like the one he likes */
html body.cl-v2:not(.cl-x) ul.products li.product.product .price,
html body.cl-v2:not(.cl-x) ul.products li.product .price {
  font-size: 22px !important;
  font-weight: 800 !important;
  line-height: 1.15 !important;
  letter-spacing: -0.01em !important;
  margin: 0 0 12px !important;
  padding: 0 2px !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product .price .amount,
html body.cl-v2:not(.cl-x) ul.products li.product .price bdi,
html body.cl-v2:not(.cl-x) ul.products li.product .price .woocommerce-Price-currencySymbol {
  font-size: inherit !important;
  font-weight: 800 !important;
}
/* "From" is a qualifier, not a number — it must not compete with one */
html body.cl-v2:not(.cl-x) ul.products li.product .price .cl-price__from,
html body.cl-v2:not(.cl-x) ul.products li.product .price small {
  font-size: 12.5px !important;
  font-weight: 700 !important;
  letter-spacing: 0.02em !important;
  margin-right: 3px !important;
  opacity: 0.75 !important;
}
/* a struck-through old price stays small and quiet beside it */
html body.cl-v2:not(.cl-x) ul.products li.product .price del,
html body.cl-v2:not(.cl-x) ul.products li.product .price del .amount {
  font-size: 14px !important;
  font-weight: 600 !important;
}

/* 2. the title: a LITTLE title, as he put it */
html body.cl-v2:not(.cl-x) ul.products li.product.product .woocommerce-loop-product__title,
html body.cl-v2:not(.cl-x) ul.products li.product h2.woocommerce-loop-product__title {
  font-size: 16px !important;
  font-weight: 700 !important;
  /* 0.04em, down from 0.08em. Tracking is what pushed these to three lines:
     it adds ~1.3px per character, and "R3TA 10MG STARTER PACK" is 22 of them. */
  letter-spacing: 0.04em !important;
  line-height: 1.25 !important;
  margin: 0 0 8px !important;
  padding: 8px 2px 0 !important;
}

/* 3. close the dead air, and let the button sit under the price */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc,
html body.cl-v2:not(.cl-x) ul.products li.product .cl-atc {
  margin-top: 10px !important;
}

@media (min-width: 900px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product .price,
  html body.cl-v2:not(.cl-x) ul.products li.product .price {
    font-size: 25px !important;
  }
}


/* ------------------------------------------------------------------
 * 54. THE PRICE ROW, LEARNED FROM THE CARD HE SHOWED ME
 *
 * Noah, 2026-10-05, holding up a competitor's grid: "look how easy they seem
 * to read and mine look like shit compared. So fix that and use the elements.
 * And learn from this."
 *
 * What makes theirs legible, read off the picture:
 *   - the name is NOT letter-spaced caps, so it reads as a word not a pattern
 *   - old and new price sit on ONE line, old small and grey, new large
 *   - nothing between the price and the buttons
 *
 * Ours had the opposite of each: 0.08em tracking over three lines, a 14px
 * price under a 16px title, and 77px of dead air.
 *
 * The brand's spaced caps are kept for SECTION titles — that is the CORE LABS
 * identity and it is approved. It is dropped only on the product name inside a
 * card, where it was costing a whole extra line and most of the readability.
 * ------------------------------------------------------------------ */

/* old and new price on ONE line, the new one carrying the weight */
html body.cl-v2:not(.cl-x) ul.products li.product .price {
  display: flex !important;
  flex-wrap: nowrap !important;
  align-items: baseline !important;
  justify-content: center !important;
  gap: 8px !important;
  white-space: nowrap !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product .price del {
  order: 0 !important;
  opacity: 0.55 !important;
  font-size: 13px !important;
  font-weight: 600 !important;
  margin: 0 !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product .price ins,
html body.cl-v2:not(.cl-x) ul.products li.product .price > .amount,
html body.cl-v2:not(.cl-x) ul.products li.product .price > .cl-price {
  order: 1 !important;
  text-decoration: none !important;
}

/* the name reads as a word, not as spaced-out letters */
html body.cl-v2:not(.cl-x) ul.products li.product.product .woocommerce-loop-product__title,
html body.cl-v2:not(.cl-x) ul.products li.product h2.woocommerce-loop-product__title {
  letter-spacing: 0.01em !important;
  line-height: 1.3 !important;
}


/* ------------------------------------------------------------------
 * 55. LEFT-ALIGNED CARDS, AND THE DETAILS + ADD PAIR
 *
 * Noah chose both on 2026-10-05, after showing a competitor's grid.
 *
 * LEFT-ALIGN REVERSES AN EARLIER INSTRUCTION of his — "center titles,
 * 'Details', labels, buttons on phones" — so it was put to him explicitly
 * rather than changed quietly. His answer: left-align, like the reference.
 * That is why it reads so fast: name, price and buttons all start on the same
 * vertical line and the eye follows one edge down the card instead of
 * re-centring on every row.
 *
 * The pair is outlined Details + filled Add, side by side, equal height. Add
 * takes the larger share because it is the action the shop wants; Details is
 * a real link so it can be opened in a new tab and tabbed to.
 * ------------------------------------------------------------------ */

html body.cl-v2:not(.cl-x) ul.products li.product.product,
html body.cl-v2:not(.cl-x) ul.products li.product {
  text-align: left !important;
  align-items: stretch !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product .woocommerce-loop-product__title,
html body.cl-v2:not(.cl-x) ul.products li.product h2.woocommerce-loop-product__title,
html body.cl-v2:not(.cl-x) ul.products li.product .cl-cardsizes {
  text-align: left !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product .price {
  justify-content: flex-start !important;
  text-align: left !important;
}

/* the pair */
html body.cl-v2:not(.cl-x) ul.products li.product .cl-atc {
  display: flex !important;
  flex-direction: row !important;
  align-items: stretch !important;
  gap: 8px !important;
  flex-wrap: nowrap !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product .cl-atc__details {
  flex: 0 1 auto !important;
  min-width: 0 !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  min-height: 46px !important;
  padding: 0 12px !important;
  font-size: 12.5px !important;
  font-weight: 700 !important;
  letter-spacing: 0.04em !important;
  white-space: nowrap !important;
  text-decoration: none !important;
  background: #FFFFFF !important;
  background-image: none !important;
  color: #27272A !important;
  -webkit-text-fill-color: #27272A !important;
  border: 1px solid #E5E1F2 !important;
  border-radius: 999px !important;
  box-shadow: none !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product .cl-atc .cl-atc__btn {
  flex: 1 1 auto !important;
  min-width: 0 !important;
  white-space: nowrap !important;
}
/* the strength picker still has to drop below the pair, full width */
html body.cl-v2:not(.cl-x) ul.products li.product .cl-atc .cl-atc__opts {
  flex: 1 0 100% !important;
  order: 9 !important;
}


/* ------------------------------------------------------------------
 * 56. THE SAME CARD RULES, AT A SPECIFICITY THAT ACTUALLY WINS
 *
 * Blocks 53-55 were correct and did nothing, because of trap #1 — and this
 * time the extra class was .woocommerce. theme-v2-type.css states:
 *
 *   html body.cl-v2:not(.cl-x) .woocommerce ul.products li.product .price
 *       classes: cl-v2, cl-x, woocommerce, products, product, price = 6
 *       elements: html, body, ul, li = 4                      -> (0,6,4)
 *
 * against mine, which left .woocommerce out:
 *
 *   html body.cl-v2:not(.cl-x) ul.products li.product .price  -> (0,5,4)
 *
 * One class short, both !important, so 14px kept winning and the price never
 * moved. The element MATCHED my selector the whole time, which is exactly why
 * a matches() check proves nothing.
 *
 * Two forms of every selector below, on purpose:
 *   - one WITH .woocommerce, for pages that have such a descendant (shop)
 *   - one with a doubled class instead, for pages that do NOT. `body` itself
 *     carries .woocommerce (trap #5), so on a product page there is no
 *     .woocommerce DESCENDANT and the first form matches nothing.
 * ------------------------------------------------------------------ */

/* ---- the price, big, as on the card he likes ---- */
html body.cl-v2:not(.cl-x) .woocommerce ul.products li.product.product .price,
html body.cl-v2:not(.cl-x) ul.products li.product.product .price:not(.cl-x) {
  font-size: 22px !important;
  font-weight: 800 !important;
  line-height: 1.15 !important;
  letter-spacing: -0.01em !important;
  display: flex !important;
  flex-wrap: nowrap !important;
  align-items: baseline !important;
  justify-content: flex-start !important;
  gap: 8px !important;
  margin: 0 0 12px !important;
  padding: 0 !important;
  white-space: nowrap !important;
}
html body.cl-v2:not(.cl-x) .woocommerce ul.products li.product.product .price .amount,
html body.cl-v2:not(.cl-x) .woocommerce ul.products li.product.product .price bdi,
html body.cl-v2:not(.cl-x) ul.products li.product.product .price .amount:not(.cl-x),
html body.cl-v2:not(.cl-x) ul.products li.product.product .price bdi:not(.cl-x) {
  font-size: inherit !important;
  font-weight: 800 !important;
}
html body.cl-v2:not(.cl-x) .woocommerce ul.products li.product.product .price small,
html body.cl-v2:not(.cl-x) ul.products li.product.product .price small:not(.cl-x) {
  font-size: 12.5px !important;
  font-weight: 700 !important;
  opacity: 0.7 !important;
}
html body.cl-v2:not(.cl-x) .woocommerce ul.products li.product.product .price del,
html body.cl-v2:not(.cl-x) ul.products li.product.product .price del:not(.cl-x) {
  font-size: 13px !important;
  font-weight: 600 !important;
  opacity: 0.55 !important;
  order: 0 !important;
}

/* ---- left-aligned, as he chose ---- */
html body.cl-v2:not(.cl-x) .woocommerce ul.products li.product.product,
html body.cl-v2:not(.cl-x) ul.products li.product.product:not(.cl-x) {
  text-align: left !important;
}
html body.cl-v2:not(.cl-x) .woocommerce ul.products li.product.product .woocommerce-loop-product__title,
html body.cl-v2:not(.cl-x) ul.products li.product.product h2.woocommerce-loop-product__title:not(.cl-x) {
  text-align: left !important;
  letter-spacing: 0.01em !important;
  line-height: 1.22 !important;
  font-size: 20px !important;   /* was 16 — the compound name was SMALLER than its own price (16 vs 25) */
  margin: 0 0 8px !important;
}

/* ---- Details + Add, side by side ---- */
html body.cl-v2:not(.cl-x) .woocommerce ul.products li.product.product .cl-atc,
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc:not(.cl-x) {
  display: flex !important;
  flex-direction: row !important;
  flex-wrap: wrap !important;
  align-items: stretch !important;
  justify-content: flex-start !important;
  gap: 8px !important;
  margin: 10px 0 0 !important;
  width: 100% !important;
}
html body.cl-v2:not(.cl-x) .woocommerce ul.products li.product.product .cl-atc .cl-atc__btn,
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc .cl-atc__btn:not(.cl-x) {
  flex: 1 1 auto !important;
  width: auto !important;
  min-width: 0 !important;
  white-space: nowrap !important;
  padding: 12px 10px !important;
}
html body.cl-v2:not(.cl-x) .woocommerce ul.products li.product.product .cl-atc .cl-atc__details,
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc .cl-atc__details:not(.cl-x) {
  flex: 0 0 auto !important;
  width: auto !important;
}
/* the strength picker drops below the pair and spans it */
html body.cl-v2:not(.cl-x) .woocommerce ul.products li.product.product .cl-atc .cl-atc__opts,
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc .cl-atc__opts:not(.cl-x) {
  flex: 1 0 100% !important;
  order: 9 !important;
}


/* ------------------------------------------------------------------
 * 57. THE SELECTOR THAT ACTUALLY REACHES THE PRICE
 *
 * Blocks 53, 54, 55 and 56 all failed, and I blamed the wrong rule twice.
 *
 * I assumed the winner was theme-v2-type.css's
 *     html body.cl-v2:not(.cl-x) .woocommerce ul.products li.product .price
 * It is not. It MATCHES NOTHING — trap #5 again. `body` itself carries
 * .woocommerce, so ".woocommerce ul.products" needs a .woocommerce DESCENDANT,
 * and the shop page has none. The real chain is:
 *
 *     span.price < a.woocommerce-LoopProduct-link < li.product < ul.products
 *
 * The rule that was really winning goes THROUGH that anchor, which buys it two
 * extra element terms:
 *     ...li.product.product a.woocommerce-LoopProduct-link span.price  (0,7,6)
 * against my best effort                                              (0,7,4).
 *
 * Specificity compares classes BEFORE elements, so I kept adding classes and
 * kept losing on a tie-break I had not looked at. The empirical probe — a rule
 * with a marker property nobody else sets — is what finally settled it: the
 * rule was parsed, present and simply not matching.
 *
 * Everything below therefore names the anchor explicitly.
 * ------------------------------------------------------------------ */

html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price:not(.cl-x),
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link p.price:not(.cl-x) {
  font-size: 22px !important;
  font-weight: 800 !important;
  line-height: 1.15 !important;
  letter-spacing: -0.01em !important;
  display: flex !important;
  flex-wrap: nowrap !important;
  align-items: baseline !important;
  justify-content: flex-start !important;
  gap: 8px !important;
  margin: 0 0 12px !important;
  padding: 0 !important;
  white-space: nowrap !important;
  text-align: left !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price .amount:not(.cl-x),
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price bdi:not(.cl-x) {
  font-size: inherit !important;
  font-weight: 800 !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price small:not(.cl-x) {
  font-size: 12.5px !important;
  font-weight: 700 !important;
  opacity: 0.7 !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price del:not(.cl-x) {
  font-size: 13px !important;
  font-weight: 600 !important;
  opacity: 0.55 !important;
  order: 0 !important;
}
/* the title sits in that same anchor */
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link h2.woocommerce-loop-product__title:not(.cl-x) {
  text-align: left !important;
  letter-spacing: 0.01em !important;
  line-height: 1.22 !important;
  font-size: 20px !important;   /* was 16 — the compound name was SMALLER than its own price (16 vs 25) */
  margin: 0 0 8px !important;
  padding: 8px 0 0 !important;
}

@media (min-width: 900px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price:not(.cl-x) {
    font-size: 25px !important;
  }
}


/* ------------------------------------------------------------------
 * 58. THE CURRENCY SYMBOL AND THE BUTTON ROW
 *
 * After block 57 the number went to 22px and the "$" stayed at 14 — it is its
 * own span with its own rule, so "font-size: inherit" on .amount never reached
 * it. A $ set 8px smaller than the figure beside it is the kind of detail that
 * reads as sloppy without anyone being able to say why.
 *
 * .cl-atc is a SIBLING of a.woocommerce-LoopProduct-link, not inside it, so it
 * needs its own chain. Its margin-top:auto comes from the card-uniformity
 * block: that is what holds every card to the same height, and it is also what
 * leaves ~69px of nothing above the buttons on a short card. Uniformity is
 * kept — the row is simply pulled back up to a fixed distance from the price.
 * ------------------------------------------------------------------ */

html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price .woocommerce-Price-currencySymbol:not(.cl-x),
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price span:not(.cl-x):not(small) {
  font-size: inherit !important;
  font-weight: inherit !important;
}

html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc:not(.cl-x):not(.cl-y) {
  display: flex !important;
  flex-direction: row !important;
  flex-wrap: wrap !important;
  align-items: stretch !important;
  justify-content: flex-start !important;
  gap: 8px !important;
  width: 100% !important;
  margin: 0 !important;
  padding: 0 !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc:not(.cl-x) button.cl-atc__btn:not(.cl-y) {
  flex: 1 1 auto !important;
  width: auto !important;
  min-width: 0 !important;
  margin: 0 !important;
  white-space: nowrap !important;
  padding: 12px 10px !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc:not(.cl-x) a.cl-atc__details:not(.cl-y) {
  flex: 0 0 auto !important;
  width: auto !important;
  margin: 0 !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc:not(.cl-x) div.cl-atc__opts:not(.cl-y) {
  flex: 1 0 100% !important;
  order: 9 !important;
}


/* ------------------------------------------------------------------
 * 59. STOP THE BUTTONS STRETCHING INTO THE LEFTOVER SPACE
 *
 * With the pair finally on one row they measured 134px TALL. align-items:
 * stretch plus a row that is allowed to grow means the buttons absorb whatever
 * height the card-uniformity rule left over — the dead space did not go away,
 * it got poured into the controls.
 *
 * So the row is pinned: it does not grow, and the buttons are a fixed 48.
 * Uniformity still holds the cards to one height; the slack now sits where it
 * belongs, as quiet space, instead of inflating a button to three times its
 * size.
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc:not(.cl-x):not(.cl-y) {
  align-items: center !important;
  flex: 0 0 auto !important;
  align-self: stretch !important;
  margin-top: auto !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc:not(.cl-x) button.cl-atc__btn:not(.cl-y),
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc:not(.cl-x) a.cl-atc__details:not(.cl-y) {
  height: 48px !important;
  min-height: 48px !important;
  max-height: 48px !important;
  align-self: center !important;
}


/* ------------------------------------------------------------------
 * 60. BACK TO THE SINGLE BUTTON, ALIGNMENT KEPT
 *
 * Noah, 2026-10-05: "go back to the buttons we had... where you could just
 * pick it right into the cart. But just make the alignment better." And: "I
 * love the measurements, but I need you to go back to our button."
 *
 * So the Details link is gone from the markup and the row goes back to one
 * full-width control with the strength picker under it — the thing that keeps
 * the whole purchase on the card.
 *
 * KEPT from the pair experiment, because those were the real wins:
 *   price   14px -> 22px (25px at 900+), with the $ finally the same size
 *   name    0.08em tracking -> 0.01em, so it reads as a word not a pattern
 *   align   left, which he chose over the earlier centre-on-mobile rule
 *   space   one even rhythm instead of 9 / 1 / 12 / 12
 * ------------------------------------------------------------------ */
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc:not(.cl-x):not(.cl-y) {
  display: flex !important;
  flex-direction: column !important;
  align-items: stretch !important;
  gap: 8px !important;
  width: 100% !important;
  margin-top: auto !important;
  padding: 0 !important;
  flex: 0 0 auto !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc:not(.cl-x) button.cl-atc__btn:not(.cl-y) {
  flex: 0 0 auto !important;
  width: 100% !important;
  height: 48px !important;
  min-height: 48px !important;
  max-height: 48px !important;
  margin: 0 !important;
  padding: 12px 14px !important;
  white-space: nowrap !important;
}
/* the picker opens under the button, full width, as it did before */
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc:not(.cl-x) div.cl-atc__opts:not(.cl-y) {
  width: 100% !important;
  order: 2 !important;
  flex: 0 0 auto !important;
}


/* ------------------------------------------------------------------
 * 61. MATTE. NO GLOW, NO STRAY GREEN, PURPLE ONLY ON THE PRIMARY BUTTON
 *
 * Noah, 2026-10-05, comparing against a competitor: "what is making theirs
 * look more professional... is mine just too glowy? Is it the matte?" Then:
 * "kill the glow... pull purple back to the primary but nothing else
 * structural."
 *
 * MEASURED on the live page, the glows that were actually there:
 *   svg                     filter: drop-shadow(rgba(167,139,250,.9) 0 0 3px)
 *   span.onsale             box-shadow rgba(109,40,217,.9)
 *   .cl-feat__btn/__all     box-shadow rgba(109,40,217,.5)
 *   .cl-eyebrow             text-shadow rgba(109,40,217,.3) 0 0 16px
 *   .cl-footer__heading     text-shadow rgba(109,40,217,.3) 0 0 16px
 *   .page-numbers.current   box-shadow rgba(109,40,217,.85)
 *   a.cl-calltab            box-shadow rgba(76,29,149,.9)
 *   "Add TIRZ Bundle"       box-shadow rgba(109,40,217,.62)
 *
 * AND TWO GREENS on a design that is supposed to have none:
 *   "Call now"  box-shadow: rgba(31, 122, 77, 0.5)   <- a GREEN glow
 *   "Text us"   svg background-color: rgb(240, 250, 245)  <- the pale green
 *               square Noah saw as a blank box where an icon should be
 * The green scanner never caught these because it reads text and background
 * colour, and a SHADOW is neither.
 *
 * A glow is light. Light says "screen". A flat fill with one honest shadow
 * says "object", and that is the whole difference he is pointing at.
 * ------------------------------------------------------------------ */

/* 1. no coloured light anywhere */
html body.cl-v2:not(.cl-x) *,
html body.cl-v2:not(.cl-x) *::before,
html body.cl-v2:not(.cl-x) *::after {
  text-shadow: none !important;
}
html body.cl-v2:not(.cl-x) svg,
html body.cl-v2:not(.cl-x) svg * ,
html body.cl-v2:not(.cl-x) img {
  filter: none !important;
}

/* 2. one honest shadow on the things that are surfaces, none on the rest */
html body.cl-v2:not(.cl-x) button,
html body.cl-v2:not(.cl-x) a.cl-btn,
html body.cl-v2:not(.cl-x) .cl-btn,
html body.cl-v2:not(.cl-x) .cl-feat__btn,
html body.cl-v2:not(.cl-x) .cl-feat__all,
html body.cl-v2:not(.cl-x) span.onsale,
html body.cl-v2:not(.cl-x) .page-numbers,
html body.cl-v2:not(.cl-x) a.cl-calltab,
html body.cl-v2:not(.cl-x) .cl-callsheet a,
html body.cl-v2:not(.cl-x) .cl-callsheet button {
  box-shadow: none !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product,
html body.cl-v2:not(.cl-x) li.cl-feat__card,
html body.cl-v2:not(.cl-x) .cl-bundle {
  box-shadow: 0 1px 2px rgba(17, 17, 24, 0.04), 0 6px 16px -10px rgba(17, 17, 24, 0.10) !important;
}

/* 3. the two greens, killed at the source */
html body.cl-v2:not(.cl-x) .cl-callsheet svg,
html body.cl-v2:not(.cl-x) .cl-callsheet svg * {
  background: transparent !important;
  background-color: transparent !important;
}

/* 4. purple earns its place on the PRIMARY action and nowhere structural.
 *    Secondary controls go neutral: white face, grey hairline, near-black
 *    label. That is what makes the one purple button read as the thing to
 *    press. */
html body.cl-v2:not(.cl-x) .cl-btn--secondary,
html body.cl-v2:not(.cl-x) a.cl-btn--secondary,
html body.cl-v2:not(.cl-x) button.cl-btn--secondary {
  background: #FFFFFF !important;
  background-image: none !important;
  color: #27272A !important;
  -webkit-text-fill-color: #27272A !important;
  border: 1px solid #E5E1F2 !important;
}


/* ------------------------------------------------------------------
 * 62. THE PRICE CLIPPED BY 3px AT 360 — MY REGRESSION, FIXED AT THE GAP
 *
 * Raising the price to 22px (block 57) pushed "From $34.99" 3px past its box
 * on 26 page/width combinations. sc/SWEEP.js caught it; nobody had to notice
 * it by eye.
 *
 * TYPOGRAPHY GUARDIAN says do not shrink text to make it fit — fix the layout.
 * The layout here has 8px of gap between "From" and the figure, and 3px is
 * less than half of it. Taking the gap to 4px on phones returns 4px, which
 * clears the overflow with a pixel to spare and leaves the type alone.
 * ------------------------------------------------------------------ */
@media (max-width: 375px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price:not(.cl-x) {
    gap: 4px !important;
  }
  html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price small:not(.cl-x) {
    margin-right: 0 !important;
  }
}


/* ------------------------------------------------------------------
 * 63. BACK TO THE ORIGINAL CARD. CENTRED. SPACING FIXED.
 *
 * Noah, 2026-10-05, with a picture of the card he wants: "I love the original
 * product cards. Do the original product cards. I like that. But the spacing
 * was bad... you just needed to fix the spacing just a smidge."
 *
 * So the left-alignment from block 55/56 is REVERSED. He chose left-align
 * earlier from a competitor's screenshot, then saw it on his own cards and
 * preferred what he already had. His call, and the centred version is what
 * ships.
 *
 * WHAT STAYS from that work, because it is what he keeps pointing at as right:
 *   - the price large (22px, 25px at 900+) instead of 14px
 *   - "From $34.99" — small qualifier, big figure — instead of a full range
 *   - the name no longer at 0.08em tracking
 *
 * WHAT CHANGES is only the rhythm. Measured before: name gap 0, price gap 5,
 * then SEVENTY-FIVE pixels of nothing before the button. That is the "bad
 * spacing" — not the design.
 *
 *   image  --16--  name  --14--  price  --16--  sizes  --16--  button
 *
 * One scale, no gap smaller than 14 and none larger than 16, so nothing reads
 * as an accident.
 * ------------------------------------------------------------------ */

html body.cl-v2:not(.cl-x) .woocommerce ul.products li.product.product,
html body.cl-v2:not(.cl-x) ul.products li.product.product:not(.cl-x) {
  text-align: center !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link h2.woocommerce-loop-product__title:not(.cl-x) {
  text-align: center !important;
  margin: 16px 0 14px !important;
  padding: 0 2px !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price:not(.cl-x),
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link p.price:not(.cl-x) {
  justify-content: center !important;
  text-align: center !important;
  margin: 0 0 16px !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-cardsizes:not(.cl-x) {
  text-align: center !important;
  margin: 0 auto 16px !important;
  display: block !important;
}
/* the button row sits right under the pill, not pushed to the floor of the
   card — the 75px of dead air was margin-top:auto doing what it was told */
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc:not(.cl-x):not(.cl-y) {
  margin-top: 0 !important;
  margin-bottom: 0 !important;
}


/* ------------------------------------------------------------------
 * 64. THE PRODUCT FILLS THE CARD, SO THERE IS NO VOID TO LOOK AT
 *
 * Looking at a single card rendered at 390 instead of reading numbers: the
 * vial sat small in the top third and roughly 180px of empty white sat under
 * the button. Noah has been saying "the cards look like shit" through several
 * passes and THIS is what he was looking at.
 *
 * The cause is card uniformity. Every card is stretched to the height of the
 * tallest in its row, and a card with a short title has slack left over. Block
 * 63 took margin-top:auto off the button row, which only moved that slack from
 * above the button to below it — the void stayed, it just changed ends.
 *
 * So the IMAGE absorbs it. The image box grows to take whatever is spare, the
 * vial scales up inside it, and the card is full of product instead of full of
 * nothing. Uniformity is untouched — every card still ends at the same height,
 * which is the thing he asked for earlier and has not withdrawn.
 *
 * The vial itself is not altered: object-fit stays `contain`, so the label is
 * never cropped and the artwork is never stretched. It is only ever shown
 * larger within a larger box.
 * ------------------------------------------------------------------ */

html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link:not(.cl-x) {
  display: flex !important;
  flex-direction: column !important;
  flex: 1 1 auto !important;
  min-height: 0 !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-cardimg:not(.cl-x) {
  flex: 1 1 auto !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  min-height: 196px !important;
  height: auto !important;
  max-height: none !important;
  padding: 10px 10px 0 !important;
  overflow: hidden !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-cardimg img:not(.cl-x),
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-cardimg .cl-cardimg__img:not(.cl-x) {
  width: auto !important;
  max-width: 100% !important;
  height: 100% !important;
  max-height: 100% !important;
  object-fit: contain !important;
  margin: 0 auto !important;
}
@media (min-width: 900px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-cardimg:not(.cl-x) {
    flex-basis: 240px !important;
  }
}


/* ------------------------------------------------------------------
 * 65. THE CARD'S TWO VOIDS
 *
 * (Correction: an earlier note here claimed `.cl-cardimg` does not exist. It
 * does — see block 66, which measures it. Block 64 failed on SPECIFICITY, the
 * usual reason, not on a missing element.)
 *
 * Reading the DOM instead of assuming it:
 *
 *   li.product                      169 x 571   flex column
 *     a.woocommerce-LoopProduct-link  147 x 413   flex column, flex: 1 1 auto
 *       img.attachment-...            147 x 196   flex: 0 0 auto, height: 196px
 *       h2.woocommerce-loop-...title  147 x  74
 *       span.price                    147 x  50
 *     div.cl-atc                      147 x 134   <- holding a 48px button
 *
 * Two voids, which together are the empty card Noah keeps pointing at:
 *   - the image is PINNED at 196px, so the anchor's spare ~93px sits as
 *     white space instead of showing more product
 *   - .cl-atc is 134px tall around a 48px button: 86px of nothing
 *
 * Fix both at the elements that actually exist. The image grows to take the
 * slack; the button row shrinks to its button. object-fit stays `contain`, so
 * the vial is only ever shown LARGER, never cropped or stretched.
 * ------------------------------------------------------------------ */

html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link img:not(.cl-x) {
  flex: 1 1 auto !important;
  height: auto !important;
  min-height: 196px !important;
  max-height: none !important;
  width: 100% !important;
  object-fit: contain !important;
  object-position: center !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc:not(.cl-x):not(.cl-y) {
  flex: 0 0 auto !important;
  height: auto !important;
  min-height: 0 !important;
  align-self: stretch !important;
  padding: 0 !important;
}
@media (min-width: 900px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link img:not(.cl-x) {
    flex-basis: 240px !important;
  }
}


/* ------------------------------------------------------------------
 * 66. THE CARD IS MOSTLY AIR — give the vial the room back
 *
 * Noah, repeatedly: "the product cards look like shit", "the spacing was
 * bad", "make the product image a flat color panel filling the card top edge
 * to edge". Block 65 removed the void UNDER the button. This removes the much
 * larger one spread through the rest of the card.
 *
 * Measured on the live card at 390 (sc/cardink.js reads PAINTED pixels, not
 * boxes — a box tells you nothing when its content is centred in it):
 *
 *     band            ink     empty space above it
 *     vial art        133px   61px
 *     name            12px    70px
 *     price           20px    76px
 *     size chip       31px    44px
 *     ADD TO CART     48px    16px
 *     ------------------------------------------- card 549px tall
 *
 * Three separate causes, each fixed at its own element:
 *
 * 1. THE IMAGE IS NOT FULL BLEED. li.product is 169 wide with a 1px border
 *    and 10px padding (6px at <=375), so the image box is 147 and the vial
 *    paints 127 of it. The panel is pulled out over that padding with negative
 *    margins, so the art renders at the full card width — about a third
 *    larger — for no extra height. li already has overflow:hidden and an 18px
 *    radius, so the panel's top corners are clipped to the card for free.
 *    object-fit stays `contain`: the vial is only ever shown LARGER, never
 *    cropped or stretched. The panel gets a flat #F5F3FF — the same tint the
 *    size chip already uses — so it reads as a panel, not as a glow.
 *
 * 2. THE NAME RESERVES THREE LINES IT NEVER USES. min-height was
 *    calc(3.9em + 12px) = 74.4px with -webkit-line-clamp: 3. Measuring the
 *    glyph rects of all 12 shop titles (sc/titleink.js): the LONGEST,
 *    "R3TA 10MG STARTER PACK", uses 44px = 2 lines. Every other title uses
 *    23px = 1 line. So 30px of every card is reserved for a line no product
 *    has. Two lines is the honest number. The clamp stays at 3 as a bound, so
 *    a future long name wraps instead of overflowing — it would make that one
 *    card ~22px taller than its neighbour, which is the correct trade against
 *    30px of dead space on all 12 today.
 *
 * 3. THE RHYTHM IS DOUBLE-SPACED. 16/14 + 16 + 16 of margin between four
 *    blocks that are already generously padded. Halved, not removed.
 *
 * The type itself is untouched — same faces, same sizes, same weights, same
 * spaced caps. TYPOGRAPHY-GUARDIAN: fix the layout, never the type.
 * ------------------------------------------------------------------ */

/* 1 — the image panel, edge to edge */
html body.cl-v2:not(.cl-x) ul.products li.product.product span.cl-cardimg:not(.cl-x):not(.cl-y) {
  display: block !important;
  margin: -10px -10px 0 !important;
  width: auto !important;
  /* .cl-cardimg carries flex-grow:1 at (0,7,4) and keeps it: slack is
   * absorbed here, and now that the panel is a flat colour that slack reads
   * as panel, not as a white void.
   *
   * But `height: auto` with `height: 100%` on the img inside resolves to the
   * IMAGE'S OWN natural height at that width, so every panel was a different
   * height and the tallest one — through grid-auto-rows: 1fr — set the height
   * of all twelve cards. A definite flex-basis makes the row's max-content a
   * number this stylesheet chooses instead of one the artwork chooses. */
  flex: 1 1 200px !important;
  height: auto !important;
  min-height: 0 !important;
  max-height: none !important;
  padding: 0 !important;
  background: #F5F3FF !important;
  border-radius: 0 !important;
  overflow: hidden !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product span.cl-cardimg img:not(.cl-x):not(.cl-y),
html body.cl-v2:not(.cl-x) ul.products li.product.product img.cl-cardimg__img:not(.cl-x):not(.cl-y) {
  display: block !important;
  width: 100% !important;
  height: 100% !important;
  min-height: 0 !important;
  max-height: none !important;
  padding: 0 !important;
  margin: 0 !important;
  object-fit: contain !important;
  object-position: center !important;
}

/* the starter packs render a bare <img> straight inside the anchor, with no
 * .cl-cardimg wrapper. Block 65 already sized that one; it only needs the
 * same height so the two kinds of card agree. */
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link > img:not(.cl-x):not(.cl-y) {
  flex: 1 1 200px !important;
  height: auto !important;
  min-height: 0 !important;
  margin: -10px -10px 0 !important;
  /* an <img> is a REPLACED element: `width: auto` means its intrinsic width,
   * not "fill the box", so the negative side margins alone left it at 147
   * while the wrapped cards reached 167. Say the width out loud. */
  width: calc(100% + 20px) !important;
  align-self: stretch !important;
  /* WHITE here, not the lilac the wrapped cards get.
   *
   * This selector only ever matches the starter packs: every other product
   * renders <a><span.cl-cardimg><img>, so `a > img` is exactly the cards whose
   * artwork is a 1200x1200 composite with a WHITE BACKGROUND BAKED IN, not a
   * transparent cut-out. On lilac that painted a white box inside a lilac box.
   * Matching the panel to the art it actually holds removes the seam.
   *
   * CORRECTION, 2026-10-06 — the note above was WRONG and it cost weeks of
   * "the cards aren't uniform". I downloaded the live file and measured it:
   *
   *   core-labs-r3ta-starter-pack-v2.webp   1200x1200
   *   corner pixels (255,255,255,0)  ->  alpha ZERO
   *   84.5% of the image is transparent
   *
   * The pack art was ALREADY a transparent cut-out, exactly like the vials.
   * This white background was painted behind a transparent PNG to hide a seam
   * that did not exist, and THAT is what made the two pack cards read as white
   * boxes beside twelve lilac ones. No artwork needed changing at any point.
   *
   * Lesson: verify the asset before writing CSS to work around it. One curl and
   * four corner pixels would have settled it.
   *
   * With every image now a true cut-out, the panel tint goes on the IMAGE
   * element itself rather than on some wrapper only the single-product cards
   * happen to have. That is what finally makes all fourteen cards identical:
   * one declaration, one specificity, no card left out.
   *
   * SUPERSEDED 2026-10-06: the real fault was markup, not paint. The packs had
   * no <span class="cl-cardimg"> at all, because corelabs_hero_cutout() returns
   * nothing for them and shop-buttons.php fell back to a bare WooCommerce
   * thumbnail. That fallback is now wrapped too, so the panel comes from the
   * same element on every card and the image goes back to transparent. */
  background: transparent !important;
  object-fit: contain !important;
}

/* 2 — the name stops reserving a third line */
/* must go through a.woocommerce-LoopProduct-link: block 63 owns these
 * margins at (0,8,6) and a rule without the anchor is (0,8,5) — same
 * class count, fewer elements, loses in silence. */
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link h2.woocommerce-loop-product__title:not(.cl-x):not(.cl-y) {
  min-height: 49px !important;   /* 2 lines x 24.4px. Was 44px = one line, which
                                   * let a wrapping title (the starter packs) push
                                   * its price and button below its neighbours. This
                                   * rule is (0,9,6) and quietly beat the 49px set in
                                   * block 117e at (0,7,5), so it is changed HERE
                                   * rather than by stacking a tenth class on top. */
  height: auto !important;
  margin: 12px 0 8px !important;
}

/* 3 — halve the rhythm */
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price:not(.cl-x):not(.cl-y) {
  min-height: 0 !important;
  height: auto !important;
  margin: 0 0 10px !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product span.cl-cardsizes:not(.cl-x):not(.cl-y) {
  margin: 0 auto 12px !important;
}

/* <=375 the card padding is 6px, not 10px, so the bleed has to match it or
 * the panel either falls short of the edge or pokes through the border. */
@media (max-width: 375px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product span.cl-cardimg:not(.cl-x):not(.cl-y),
  html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link > img:not(.cl-x):not(.cl-y) {
    margin: -10px -6px 0 !important;
  }
}

/* desktop has room for a taller panel; everything else is the same */
@media (min-width: 900px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product span.cl-cardimg:not(.cl-x):not(.cl-y),
  html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link > img:not(.cl-x):not(.cl-y) {
    flex-basis: 240px !important;
  }
}

/* 66b — a row sizes to ITS OWN content.
 *
 * `grid-auto-rows: 1fr` makes every row as tall as the tallest row in the
 * whole grid, so the two cards that carry a size picker (GLOW, SELANK — their
 * .cl-atc is 102px, not 48px) were adding ~54px of white to all twelve. Cards
 * within a row still stretch, so buttons stay aligned across a row, which is
 * the alignment that actually matters. */
html body.cl-v2:not(.cl-x) ul.products:not(.cl-x):not(.cl-y) {
  /* REVERTED to 1fr on 2026-10-05 after sc/CHECK.js `uniform` measured a 124px
   * button spread and an 81px title spread: with `auto`, a row that carries a
   * size picker is taller than one that does not, and the starter packs (which
   * have no size chip at all) stopped lining up with everything else.
   *
   * 1fr costs nothing now. The reason it was wasteful before was that the
   * slack landed as WHITE SPACE; .cl-cardimg carries flex-grow with a 200px
   * basis, so the slack is absorbed by the flat image panel instead. Cards are
   * 458px with every element aligned, against 500px and aligned before this
   * session's work started. */
  /* `auto`, not `1fr`.
   *
   * 1fr makes EVERY row as tall as the tallest row in the grid, and with the
   * buy controls pinned to the card bottom that surfaced as ~140px of white
   * between the price and ADD TO CART on the starter packs — the exact void
   * this session set out to remove.
   *
   * It is safe now in a way it was not earlier: back then the image panel
   * carried flex-grow, so rows of different heights gave their cards
   * different panel heights and knocked the names and prices out of line.
   * Block 74 pinned the panel to a fixed height, so a row sizes to its own
   * content while every card inside it still lines up. Verified per row with
   * sc/v2uniform.js. */
  grid-auto-rows: auto !important;
}

@media (max-width: 375px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link > img:not(.cl-x):not(.cl-y) {
    width: calc(100% + 12px) !important;
  }
}

/* ------------------------------------------------------------------
 * 67. CARD TYPE — the weight hierarchy was inverted
 *
 * Noah: "Better font bolding and text."
 *
 * Measured on the live card (sc/cardtype.js):
 *
 *     name     16px   w700   tracking 0.01em   #111118
 *     price    22px   w800   tracking -0.01em  #111118
 *     From     12.5px w700   grey
 *     button   12.5px w700   white
 *
 * Two things are wrong with that, and neither is a size:
 *
 * 1. THE PRICE IS THE HEAVIEST TEXT ON THE CARD. It is bigger AND bolder than
 *    the product name, in the same colour, so the eye lands on "$100.00"
 *    before it lands on what is being sold. The name should win on weight and
 *    the price on size — then both read, in the right order.
 *
 * 2. THE NAME IS SET IN CAPS WITH NO TRACKING. 0.01em is not spaced; caps need
 *    air between the letters or they read as a block. The site's own treatment
 *    for names, titles and buttons is spaced caps, and this one was not
 *    getting it.
 *
 * SIZES ARE UNTOUCHED — 16 / 22 / 12.5 are the approved scale and nothing here
 * shrinks text (TYPOGRAPHY-GUARDIAN). This changes weight and tracking only.
 * ------------------------------------------------------------------ */

/* the name leads */
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link h2.woocommerce-loop-product__title:not(.cl-x):not(.cl-y) {
  font-weight: 800 !important;
  letter-spacing: 0.06em !important;
}

/* the price is big, not loud — 800 -> 700 */
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price:not(.cl-x):not(.cl-y),
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price span:not(.cl-x):not(.cl-y) {
  font-weight: 700 !important;
  /* Tracking neutral, added 2026-10-09. The product NAME directly above is
   * spaced caps at +1.2px and the price was at -0.22px — one opening up and
   * one tightening, 8px apart. That opposition is what Noah was seeing when
   * he said the card "looks like you just guessed and threw shit in there";
   * it reads as two unrelated type systems stacked.
   *
   * A price is read as a figure, not as display lettering, so it sits at 0
   * rather than borrowing the name's +1.2px. The 700 weight above is a
   * deliberate earlier call ("big, not loud") and is left alone. */
  letter-spacing: 0 !important;
}

/* "From" is a label, not a shout */
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price small.cl-price__from:not(.cl-x):not(.cl-y) {
  font-weight: 600 !important;
  letter-spacing: 0.08em !important;
}

/* the primary action is the most confident text in the card */
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc button.cl-atc__btn:not(.cl-x):not(.cl-y),
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc a.cl-atc__btn:not(.cl-x):not(.cl-y) {
  font-weight: 800 !important;
  letter-spacing: 0.08em !important;
}

/* ------------------------------------------------------------------
 * 68. A PRICE MUST NEVER BE CUT
 *
 * SWEEP flagged span.price on 26 page/width combinations. Two different
 * things were hiding behind one message, and only one of them was real:
 *
 * 1. "3px past" on EVERY price — scrollHeight 28 vs clientHeight 25. Poppins
 *    at 22px has a glyph box taller than the 25.3px line-height it is set on.
 *    Nothing is actually cut, because digits and "$" have no descenders below
 *    the clip line. (It is NOT the .screen-reader-text inside .price — the
 *    obvious suspect. Removing those spans left the numbers identical.)
 *
 * 2. "18px past" on SELANK — scrollWidth 159 vs clientWidth 142, and this one
 *    IS visibly cut. SELANK is a VARIABLE product that is entirely sold out
 *    (both variations, 0 stock), so inc/instock-price-range.php correctly
 *    falls through to WooCommerce's own markup and prints the full range,
 *    "$44.99 - $59.99" — 159px of type in a 142px box. Sold-out items stay on
 *    the shop on purpose, to collect waitlist emails, so this will recur for
 *    any sold-out variable product and for any long price.
 *
 * The fix is the same for both and is a layout fix, not a type fix: stop
 * clipping, and let a price that does not fit WRAP instead. Nothing is
 * shrunk — TYPOGRAPHY-GUARDIAN — and nothing can be silently cut again.
 * ------------------------------------------------------------------ */

html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link span.price:not(.cl-x):not(.cl-z) {
  overflow: visible !important;
  white-space: normal !important;
  flex-wrap: wrap !important;
  row-gap: 2px !important;
}

/* ------------------------------------------------------------------
 * 69. THE SECONDARY BUTTON'S LABEL WAS UNREADABLE — 2.10:1
 *
 * "LEARN ABOUT OUR STANDARDS" (home) and "VIEW / DOWNLOAD COA" (COA portal)
 * were painting #27272a on #6D28D9: 2.10:1, against a 4.5:1 floor.
 *
 * How it happened is worth keeping, because the comment on the rule that
 * caused it says the opposite in good faith. A cleanup block replaced a
 * leftover 5-14% purple tint sitting in background-COLOR underneath a gradient
 * in background-IMAGE, reasoning "nothing shows through" — true for every
 * button that has the gradient. `.cl-btn--secondary` is designed as a LIGHT
 * button: it sets its own white background and dark ink. Listing it with the
 * others replaced its white with solid purple at (0,4,3) while its ink stayed
 * dark at (0,3,3), so the one button whose background actually shows is the
 * one that got repainted.
 *
 * The button itself looks right and is left alone — only the ink is wrong.
 * White on this purple is 5.70:1 against the lighter end of the gradient and
 * 8.21:1 against the darker, so it passes AA across the whole sweep.
 * ------------------------------------------------------------------ */

html body.cl-v2:not(.cl-x) a.cl-btn.cl-btn--secondary:not(.cl-z),
html body.cl-v2:not(.cl-x) button.cl-btn.cl-btn--secondary:not(.cl-z),
html body.cl-v2:not(.cl-x) span.cl-btn.cl-btn--secondary:not(.cl-z) {
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}

/* ==================================================================
 * 70. DESIGN SYSTEM PASS — TYPE SCALE
 *
 * Measured against the brief with sc/dsaudit.js + sc/typegaps.js, at
 * 360/390/430/768/1024/1440. Only the numbers that FAILED are changed; the
 * faces (Poppins + DM Sans), the spaced caps and the colours are untouched.
 *
 *   rule                     was                         now
 *   H1 mobile  30-38px       42.9 home / 28 elsewhere    34
 *   H1 desktop 44-60px       64 home / 36 elsewhere      52
 *   H1 line-height 1.1-1.25  1.02 on the hero           1.15 / 1.12
 *   body 16-18px             14 on several real paras   16
 *   metadata 13-14px         12.5 on four blocks        14
 *
 * The hero H1 was the only one in range for SIZE on desktop and it was the
 * one breaking line-height; the rest of the site was UNDER the mobile floor.
 * One scale now covers every page, which is the point of a scale.
 * ================================================================== */

/* ---- H1: one scale for every page ---- */
html body.cl-v2:not(.cl-x) h1:not(.cl-x),
html body.cl-v2:not(.cl-x) h1.cl-hero2__title:not(.cl-x),
html body.cl-v2:not(.cl-x) h1.product_title:not(.cl-x) {
  font-size: 34px !important;
  line-height: 1.15 !important;
}
@media (min-width: 768px) {
  html body.cl-v2:not(.cl-x) h1:not(.cl-x),
  html body.cl-v2:not(.cl-x) h1.cl-hero2__title:not(.cl-x),
  html body.cl-v2:not(.cl-x) h1.product_title:not(.cl-x) {
    font-size: 52px !important;
    line-height: 1.12 !important;
  }
}

/* ---- body copy that was set at 14px ---- */
html body.cl-v2:not(.cl-x) p.cl-quality__lede:not(.cl-x),
html body.cl-v2:not(.cl-x) p.cl-contact__lede:not(.cl-x),
html body.cl-v2:not(.cl-x) section.cl-quality p:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-quality__item p:not(.cl-x) {
  font-size: 16px !important;
  line-height: 1.6 !important;
}

/* ---- essential small text was below the 13-14px floor ----
 * .cl-ruo-notice is "Research use only. Not for human consumption" — that is
 * the single most important sentence on a product page and it was the
 * smallest type on it. The footer disclaimer is the same argument. */
html body.cl-v2:not(.cl-x) p.cl-ruo-notice:not(.cl-x),
html body.cl-v2:not(.cl-x) p.cl-contact__note:not(.cl-x),
html body.cl-v2:not(.cl-x) p.cl-footer__disclaimer:not(.cl-x) {
  font-size: 14px !important;
  line-height: 1.55 !important;
}

/* ---- FAQ group labels ----
 * These are eyebrow labels ("TESTING & COAS", "SHIPPING"), not failed
 * headings, so they keep the purple spaced-caps treatment and only come off
 * the 12.5px floor. They are how a reader finds a section. */
html body.cl-v2:not(.cl-x) .cl-faq h2:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-faq__group h2:not(.cl-x),
html body.cl-v2:not(.cl-x) h2.cl-faq__grouptitle:not(.cl-x) {
  font-size: 14px !important;
  line-height: 1.4 !important;
}

/* 70b — the four "pillar" paragraphs on the home page.
 * Found by walking the ancestor chain (sc/findp.js) instead of guessing a
 * container name: section.cl-section--alt > .container > .cl-pillars >
 * .cl-pillar > p. These are real body copy — how identity, purity, lot
 * numbers and outside testing work — and they were the smallest readable
 * text in the middle of the page. */
html body.cl-v2:not(.cl-x) div.cl-pillar p:not(.cl-x),
html body.cl-v2:not(.cl-x) div.cl-pillars div.cl-pillar p:not(.cl-x) {
  font-size: 16px !important;
  line-height: 1.6 !important;
}

/* 70c — section headings that sat under the H2 floor.
 * The WooCommerce "Description" heading on a product page was 21px against a
 * 24px mobile floor. Scoped to the product summary so it cannot reach the FAQ
 * eyebrow labels, which are a different thing and stay small on purpose. */
html body.cl-v2:not(.cl-x) div.woocommerce-Tabs-panel h2:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-product-details__short-description h2:not(.cl-x),
html body.cl-v2:not(.cl-x) section.related h2:not(.cl-x),
html body.cl-v2:not(.cl-x) div.product div.summary h2:not(.cl-x) {
  font-size: 24px !important;
  line-height: 1.2 !important;
}

/* 70d — the FAQ group labels live in div.cl-content, not a .cl-faq wrapper.
 * (The guessed selector in 70 matched nothing; the chain is
 *  main > .container > article > div.cl-content > h2.) They stay purple
 * spaced caps — they are eyebrow labels, not headings to be scaled up — and
 * only come off the 12.5px floor to the 14px metadata minimum. */
html body.cl-v2:not(.cl-x) div.cl-content > h2:not(.cl-x) {
  font-size: 14px !important;
  line-height: 1.4 !important;
}

/* ==================================================================
 * 71. THE BACKGROUND DRIFTS LIKE MIST — IT NO LONGER TURNS
 *
 * Noah: "i dont want the back ground spinning it looks horibble", and the
 * brief: "slow mist or smoke... gentle drifting and subtle deformation. No
 * rotation of the entire image. No spinning, bouncing, rapid zooming, or
 * obvious repetitive swinging. No abrupt loop resets or hard rectangular
 * image edges."
 *
 * What was there (block 69's spiral) rotated the plate 132deg and scaled it
 * 0.86 -> 1.62 on a 54s linear loop. That is a rotation and a zoom, which is
 * exactly the two things the brief rules out, and linear timing is what makes
 * motion read as mechanical.
 *
 * How this one satisfies each constraint, deliberately:
 *
 *   no rotation          there is no rotate() anywhere below. Only translate
 *                        and a 6% scale breath.
 *   no loop reset        `alternate` plays the keyframes forwards then
 *                        BACKWARDS, so the end state IS the next start state.
 *                        A seam is impossible. This is why the old version
 *                        needed a cross-fade and this one does not.
 *   no hard edges        each layer is 128% of the box, offset -14%, and only
 *                        ever scales UP. The artwork's rectangle is always
 *                        outside the frame, at every point in the cycle.
 *   no swinging          two layers on 53s and 71s. Those are coprime enough
 *                        that the pair does not visibly re-sync; a reader
 *                        never sees the same relative arrangement twice in a
 *                        sitting, which is what kills the "repetitive" read.
 *   deformation          comes from the two layers sliding ACROSS each other,
 *                        not from any filter. No blur, no opacity crush, so
 *                        the artwork keeps its detail.
 *   not clickable        pointer-events: none on the layer and both copies.
 *
 * Timing is ease-in-out, so the motion is slowest at the extremes — the way
 * smoke actually settles, and the opposite of linear's constant march.
 * ================================================================== */

/* 2026-10-09 — amplitude raised so the roll is actually VISIBLE.
 *
 * These were +/-1.6% and +/-1.1% over 53 and 71 seconds. That is about one
 * pixel every two seconds on a phone — present in the computed style, and
 * invisible to a human. It is why Noah kept saying there was no moving
 * background when there demonstrably was one.
 *
 * Now +/-4.5% and +/-3% with a deeper scale, over 38s and 52s. The two layers
 * still travel in OPPOSITE directions at different speeds, which is what
 * makes the ribbon read as rolling rather than sliding.
 *
 * The amplitude is bounded by the plate's own margin: the layers are 128%
 * wide at -14%, so a 4.5% translate plus 6% of scale overflow is 10.5% and
 * stays inside 14% — the artwork's edges can never enter the frame. Raise
 * these further and you will see the plate's edge; check that margin first.
 *
 * Translate and scale only. No rotation — Noah: "I don't want it to rotate."
 */
@keyframes clMistA {
  from { transform: translate3d(-4.5%, -3.0%, 0) scale(1.00); }
  to   { transform: translate3d( 4.5%,  3.0%, 0) scale(1.12); }
}
@keyframes clMistB {
  from { transform: translate3d( 4.0%,  2.6%, 0) scale(1.10); }
  to   { transform: translate3d(-4.0%, -2.6%, 0) scale(1.00); }
}

html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral:not(.cl-x) {
  position: absolute !important;
  inset: 0 !important;
  overflow: hidden !important;
  pointer-events: none !important;
  z-index: 0 !important;
}

html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral:not(.cl-x)::before,
html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral:not(.cl-x)::after {
  content: "" !important;
  position: absolute !important;
  /* 128% offset -14% — the plate's own edges never enter the frame */
  top: -14% !important;
  left: -14% !important;
  width: 128% !important;
  height: 128% !important;
  margin: 0 !important;
  transform-origin: 50% 50% !important;
  background-image: url("/wp-content/uploads/corelabs-hero/corelabs-bg-v2-1536.webp") !important;
  background-repeat: no-repeat !important;
  background-position: center center !important;
  background-size: cover !important;
  pointer-events: none !important;
  will-change: transform !important;
  /* only the transform is promoted; no filter, no opacity animation */
  animation: clMistA 38s ease-in-out infinite alternate !important;
}

html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral:not(.cl-x)::after {
  opacity: 0.55 !important;
  animation: clMistB 52s ease-in-out infinite alternate !important;
  animation-delay: -18s !important;   /* start mid-phase, don't make the page wait */
}

/* resolution ladder — never upscale a small plate into a big viewport */
@media (min-width: 600px), (min-resolution: 1.5dppx) {
  html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral:not(.cl-x)::before,
  html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral:not(.cl-x)::after {
    background-image: url("/wp-content/uploads/corelabs-hero/corelabs-bg-v2-2560.webp") !important;
  }
}
@media (min-width: 1200px), (min-resolution: 1.5dppx) and (min-width: 820px) {
  html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral:not(.cl-x)::before,
  html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral:not(.cl-x)::after {
    background-image: url("/wp-content/uploads/corelabs-hero/corelabs-bg-v2-3840.webp") !important;
  }
}

/* A phone paints the second layer for no visible gain and real battery cost.
 * One drifting layer still reads as mist; two is a desktop refinement. */
@media (max-width: 600px) {
  html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral:not(.cl-x)::after {
    display: none !important;
  }
}

/* the page is hidden — stop painting (class set in site-background.php).
 * This needs !important AND more classes than the rule that starts the
 * animation: that one is (0,5,2) !important, so a plain (0,4,2) pause rule
 * lands the class and changes nothing. Verified with sc/mistaccess.js, which
 * is how the first version was caught reporting play=running under a body
 * that already carried .cl-bg-paused. */
html body.cl-v2.cl-bg-paused:not(.cl-x) .cl-hero2 .cl-spiral:not(.cl-x)::before,
html body.cl-v2.cl-bg-paused:not(.cl-x) .cl-hero2 .cl-spiral:not(.cl-x)::after {
  animation-play-state: paused !important;
}

/* someone asked their system for less motion: show the artwork, still */
@media (prefers-reduced-motion: reduce) {
  html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral:not(.cl-x)::before,
  html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral:not(.cl-x)::after {
    animation: none !important;
    transform: none !important;
  }
  html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral:not(.cl-x)::after {
    display: none !important;
  }
}

/* ==================================================================
 * 72. CONTROLS — TEXT SIZE AND HEIGHT TO THE BRIEF
 *
 * Audited with sc/controls.js across /, /shop/, /product/, /cart/, /checkout/
 * at 390 and 1440. Brief: button text 15-16px weight 600+, standard height
 * 48px, never under a 44px tap target; inputs 48px with >=16px text.
 *
 * What actually failed (icon-only buttons are excluded — their font-size
 * styles nothing, and the audit flagged them only because it read font-size
 * on every control):
 *
 *   a.cl-btn, .cl-btn--secondary, .cl-feat__all, .cl-chero__explore   14px
 *   button.single_add_to_cart_button                                  14px
 *   button.cl-scrollcue                                               14px
 *   button.cl-btn.cl-atc__btn        12.5px   <- the main buy button
 *   button.cl-wait__open             12.5px and 20px TALL at desktop
 *   select.orderby                   14px text in a 44px box
 *   input.search-field               52px tall
 *
 * RADIUS IS DELIBERATELY NOT CHANGED. The brief asks for 8px; these are pills
 * (999px) and the pill is CORE LABS' button, approved and reverted back to
 * once already. The brief's own rule covers this: preserve the identity of a
 * branded component and make the smallest necessary adjustment. Size and
 * height are the readability problem; the shape is not.
 * ================================================================== */

/* text buttons reach the 15px floor, keeping their weight and spaced caps */
html body.cl-v2:not(.cl-x) a.cl-btn:not(.cl-q),
html body.cl-v2:not(.cl-x) button.cl-btn:not(.cl-q),
html body.cl-v2:not(.cl-x) a.cl-btn.cl-btn--secondary:not(.cl-q),
html body.cl-v2:not(.cl-x) a.cl-btn.cl-feat__all:not(.cl-q),
html body.cl-v2:not(.cl-x) a.cl-btn.cl-chero__explore:not(.cl-q),
html body.cl-v2:not(.cl-x) button.cl-scrollcue:not(.cl-q),
html body.cl-v2:not(.cl-x) button.single_add_to_cart_button:not(.cl-q) {
  font-size: 15px !important;
  font-weight: 700 !important;
  min-height: 48px !important;
}

/* the product-card buy button: 12.5 -> 15px.
 * It is the single most important control in the shop and it was the smallest
 * text on the card. Same face, same caps, same purple — only the size moves.
 * Tracking eases 0.08em -> 0.04em so "ADD TO CART" still fits a 147px card
 * button at 15px; measured after deploy with sc/controls.js, not assumed. */
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc button.cl-atc__btn:not(.cl-q),
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc a.cl-atc__btn:not(.cl-q) {
  font-size: 15px !important;
  letter-spacing: 0.04em !important;
  min-height: 48px !important;
}

/* the back-in-stock button was 20px tall at desktop with 12.5px text.
 * Sold-out products stay on the shop to collect waitlist emails, so this is a
 * real conversion control, not decoration. */
html body.cl-v2:not(.cl-x) button.cl-wait__open:not(.cl-q) {
  font-size: 15px !important;
  font-weight: 600 !important;
  min-height: 48px !important;
  padding: 10px 20px !important;
  line-height: 1.3 !important;
  white-space: normal !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
}

/* inputs: 48px tall, never under 16px text (under 16 makes iOS zoom the page) */
html body.cl-v2:not(.cl-x) input.search-field:not(.cl-q),
html body.cl-v2:not(.cl-x) select.orderby:not(.cl-q),
html body.cl-v2:not(.cl-x) input[type="text"]:not(.cl-q),
html body.cl-v2:not(.cl-x) input[type="email"]:not(.cl-q),
html body.cl-v2:not(.cl-x) input[type="tel"]:not(.cl-q),
html body.cl-v2:not(.cl-x) input[type="search"]:not(.cl-q),
html body.cl-v2:not(.cl-x) input[type="number"]:not(.cl-q),
html body.cl-v2:not(.cl-x) select:not(.cl-q),
html body.cl-v2:not(.cl-x) textarea:not(.cl-q) {
  min-height: 48px !important;
  height: 48px !important;
  font-size: 16px !important;
}
html body.cl-v2:not(.cl-x) textarea:not(.cl-q) {
  height: auto !important;
  min-height: 96px !important;
}

/* 72b — the three controls that 72 missed, and why.
 *
 * .cl-wait__open      72's rule was (0,4,3); the theme owns this button at
 *                     (0,5,4) through `ul.products li.product.product`, so
 *                     72 matched and lost in silence. Routed the same way
 *                     here, plus a standalone copy for the product page where
 *                     there is no ul.products ancestor.
 * "Search" button     a BARE <button> with no class, so nothing in 72
 *                     selected it. 12.5px on a 52px control.
 * nav labels          13.3px against the brief's 14-16px for navigation. */

html body.cl-v2:not(.cl-x) ul.products li.product.product button.cl-wait__open:not(.cl-q):not(.cl-r),
html body.cl-v2:not(.cl-x) div.product button.cl-wait__open:not(.cl-q):not(.cl-r),
html body.cl-v2:not(.cl-x) body button.cl-wait__open:not(.cl-q):not(.cl-r) {
  font-size: 15px !important;
  font-weight: 600 !important;
  min-height: 48px !important;
  line-height: 1.3 !important;
  white-space: normal !important;
}

html body.cl-v2:not(.cl-x) form.cl-search button:not(.cl-q),
html body.cl-v2:not(.cl-x) form[role="search"] button:not(.cl-q),
html body.cl-v2:not(.cl-x) form.search-form button:not(.cl-q) {
  font-size: 15px !important;
  font-weight: 700 !important;
  min-height: 48px !important;
}

/* navigation labels — 14px is the brief's floor for a control label */
html body.cl-v2:not(.cl-x) button.cl-icon-btn:not(.cl-q),
html body.cl-v2:not(.cl-x) a.cl-icon-btn:not(.cl-q),
html body.cl-v2:not(.cl-x) .cl-nav a:not(.cl-q),
html body.cl-v2:not(.cl-x) .cl-nav button:not(.cl-q) {
  font-size: 14px !important;
}

/* ==================================================================
 * 73. THE CALL TAB WAS SITTING ON THE TEXT COLUMN
 *
 * Measured (sc/overlap.js, sc/calltab.js): .cl-calltab is fixed at left 0 and
 * 44px wide, while page content starts at 18px. It covered 9x20px of
 * "Research-Use Policy" on /faq/ at 360 AND 390, and 2x17px of the shop lede
 * at 360. Because the tab is FIXED, this is not about those two elements —
 * whatever the reader scrolls past ends up under it.
 *
 * So the visible strip has to fit inside the 18px gutter. It is narrowed to
 * 18px and the 44px tap target is kept with a transparent ::after reaching
 * right — the same trick block 50 used for the 4px carousel dots, which is
 * already proven on this site.
 *
 * Mobile only: at >=431 the gutter is wide enough that the full tab clears
 * the text column on its own.
 * ================================================================== */

@media (max-width: 430px) {
  html body.cl-v2:not(.cl-x) a.cl-calltab:not(.cl-x) {
    width: 18px !important;
    min-width: 0 !important;
    max-width: 18px !important;
    padding-left: 1px !important;
    padding-right: 1px !important;
    overflow: visible !important;
    position: fixed !important;
  }
  /* the tap target stays 44px — it just reaches right, transparently, over
     the gutter rather than painting on top of the words */
  html body.cl-v2:not(.cl-x) a.cl-calltab:not(.cl-x)::after {
    content: "" !important;
    position: absolute !important;
    top: 0 !important;
    bottom: 0 !important;
    left: 0 !important;
    width: 44px !important;
    background: transparent !important;
    pointer-events: auto !important;
  }
}

/* ==================================================================
 * 74. CARDS BESIDE EACH OTHER MUST LINE UP
 *
 * With the row-wise measurement fixed, sc/v2uniform.js shows real
 * misalignment between cards IN THE SAME ROW:
 *
 *   390   GLOW vs KLOW          title/price/chip/button all 56px apart
 *   390   NAD vs SELANK         title/price 81px apart
 *   1440  starter packs vs TIRZ title/price 53px apart
 *
 * Cause: the image panel carries flex-grow, so it soaks up whatever slack the
 * card has. Cards whose CONTROLS differ in height — GLOW carries an expanded
 * size picker where KLOW has a plain button, SELANK is sold out and shows the
 * waitlist button — get different panel heights, which pushes the name, price
 * and chip to different places. The panel was absorbing a difference that
 * belongs at the bottom of the card.
 *
 * So the panel stops growing and becomes a FIXED height, and the control block
 * is pushed to the bottom instead. Result:
 *   - panel, name, price and chip start at the same y in every card
 *   - buttons sit on the card's bottom edge, so they line up too
 *   - the slack from a taller neighbour lands in ONE place, between the chip
 *     and the button, instead of being spread through the whole card
 * ================================================================== */

html body.cl-v2:not(.cl-x) ul.products li.product.product span.cl-cardimg:not(.cl-x):not(.cl-z),
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link > img:not(.cl-x):not(.cl-z) {
  flex: 0 0 200px !important;
  height: 200px !important;
  min-height: 200px !important;
  max-height: 200px !important;
}
@media (min-width: 900px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product span.cl-cardimg:not(.cl-x):not(.cl-z),
  html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link > img:not(.cl-x):not(.cl-z) {
    flex: 0 0 240px !important;
    height: 240px !important;
    min-height: 240px !important;
    max-height: 240px !important;
  }
}

/* the anchor stops stretching, so it cannot reintroduce the slack it just lost */
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link:not(.cl-x):not(.cl-z) {
  flex: 0 0 auto !important;
}

/* the buy controls sit on the bottom edge — this is what aligns the buttons */
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc:not(.cl-x):not(.cl-z) {
  margin-top: auto !important;
}

/* 74b — WHY SOLD-OUT CARDS ARE 56px TALLER, AND WHY THAT IS CORRECT
 *
 * I first blamed block 72 for this, assuming the 15px waitlist button had
 * wrapped to two lines, and forced it onto one line. That changed nothing,
 * because it was never the cause. Reading the element instead of guessing at
 * it (sc/outblock.js), a sold-out .cl-atc--out contains TWO stacked controls:
 *
 *     button.cl-btn          147x48   "Out of stock"
 *     button.cl-wait__open   147x48   "Tell me when it is back"
 *     + 8px column gap                = 104px, against 48px in stock
 *
 * 48 + 8 = the exact 56px the uniformity scan reports. A sold-out product
 * genuinely offers one more control than an in-stock one — it stays on the
 * shop on purpose, to collect waitlist emails — so this is the layout being
 * right, not wrong. The nowrap/13.5px override is removed: it fixed nothing,
 * and it dropped the button under the brief's 15px floor and pushed it 4px
 * wider than its card.
 *
 * Everything that CAN align does: image, name, price and chip are 0px spread
 * within every row, and buttons are 0px in every row where both cards have
 * the same controls. */

/* 75 — nav labels at weight 500. Size was already 14px after block 72b; the
 * brief asks for 500-600 on control labels and these were still 400. */
html body.cl-v2:not(.cl-x) button.cl-icon-btn:not(.cl-q),
html body.cl-v2:not(.cl-x) a.cl-icon-btn:not(.cl-q),
html body.cl-v2:not(.cl-x) .cl-nav a:not(.cl-q),
html body.cl-v2:not(.cl-x) .cl-nav button:not(.cl-q) {
  font-weight: 500 !important;
}

/* 76 — the checkout "Continue" button was 12.5px.
 * It is the control that moves a customer from the notice into paying, so it
 * is the last place on the site that should be set in the smallest type. */
html body.cl-v2:not(.cl-x) button.cl-paynotice__cta:not(.cl-q),
html body.cl-v2:not(.cl-x) a.cl-paynotice__cta:not(.cl-q) {
  font-size: 15px !important;
  font-weight: 700 !important;
  min-height: 48px !important;
}

/* 77 — desktop H1 on the pages that are not the home hero.
 *
 * Block 70 set 52px at >=768 through `h1:not(.cl-x)` = (0,3,4 after the :not).
 * theme-v2-type.css — a GENERATED layer — already owns the same property at
 * `main h1:not(.cl-hero2__title)`, which carries one more element and wins, so
 * /shop/ and /faq/ stayed at 36px against the brief's 44-60px while the home
 * and product H1s moved to 52. (Their line-height DID change, which is the
 * tell: same rule winning one property and losing the other.)
 *
 * Matching the generated selector's shape makes this land, because
 * theme-v2.css is enqueued after theme-v2-type.css and source order decides a
 * tie. Mobile is already correct at 34px and is left alone. */
@media (min-width: 768px) {
  html body.cl-v2:not(.cl-x) main h1:not(.cl-x),
  html body.cl-v2:not(.cl-x) main h1.cl-chero__title:not(.cl-x),
  /* the generated layer reaches a page title through
   * `main .container > article > h1` at (0,3,5), one element deeper again —
   * /faq/ and the other article pages stayed at 36px until this matched it. */
  html body.cl-v2:not(.cl-x) main .container > article > h1:not(.cl-x) {
    font-size: 52px !important;
    line-height: 1.12 !important;
  }
}

/* ==================================================================
 * 78. THE ACTIVE NAV ITEM'S ICON WAS INVISIBLE — 1.26:1
 *
 * Found by the desktop sweep on /coa-portal at 1440. The nav item for the
 * page you are ON (li.current-menu-item > a[aria-current="page"]) is given a
 * solid purple pill, #6D28D9, but keeps dark purple ink, #5B21B6. Icon and
 * label both land at 1.26:1 — effectively invisible, and it is the item
 * telling the reader where they are.
 *
 * Same mistake as block 69 on the secondary button: a background was changed
 * and the ink that sits on it was not.
 *
 * Fixed at the ANCHOR, not the icon. The icon carries stroke: currentColor by
 * design, so it inherits whatever the link is set to — darkening or lightening
 * an icon directly is how you end up with a hardcoded colour that drifts out
 * of step with its text. White on #6D28D9 is 5.70:1.
 * ================================================================== */

html body.cl-v2:not(.cl-x) nav.cl-nav li.current-menu-item:not(.cl-x) > a[aria-current="page"]:not(.cl-y),
html body.cl-v2:not(.cl-x) nav.cl-nav li.current_page_item:not(.cl-x) > a[aria-current="page"]:not(.cl-y) {
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}
html body.cl-v2:not(.cl-x) nav.cl-nav li.current-menu-item:not(.cl-x) > a[aria-current="page"] svg:not(.cl-y),
html body.cl-v2:not(.cl-x) nav.cl-nav li.current_page_item:not(.cl-x) > a[aria-current="page"] svg:not(.cl-y) {
  color: #FFFFFF !important;
  stroke: currentColor !important;
}

/* 78b — the hero vial pill was 12px, under the site's 12.5px floor. */
html body.cl-v2:not(.cl-x) span.cl-vial__pill:not(.cl-x):not(.cl-y) {
  font-size: 12.5px !important;
}

/* ==================================================================
 * 79. CHECKOUT — THREE BORDERS AROUND ONE TEXT FIELD
 *
 * Noah: "chekout needs a revamp."
 *
 * Measured on the live embedded checkout (sc/codbg.js at 390), the nesting
 * around a single "First name" box:
 *
 *   input.input-text                     156x54   1px #E2E5EA  radius 12
 *   p.form-row                           158x81   1px #E2E5EA  radius 12   <-
 *   div.woocommerce-shipping-fields      328x866  1px purple   radius 14
 *
 * Three rounded outlines stacked around one input. The middle one adds no
 * information — it wraps the label and the field that already has its own
 * border — and it is what makes the form read as cluttered and run to 3156px.
 *
 * Also measured and wrong against the brief:
 *   labels 12.5px   — control labels are meant to be 14-16px, and these are
 *                     the instructions for where a customer's order goes
 *   inputs 54px     — the brief says 48px; block 72 set it but .input-text
 *                     carries its own height here and won
 *
 * What is NOT changed: the "SHIP TO" card keeps its purple outline (it groups
 * a real section), the inputs keep their own border and 12px radius, and the
 * labels stay CENTRED — that is Noah's standing call for phones, not an
 * accident. This removes a redundant layer; it does not restyle the checkout.
 *
 * The checkout is the money path, so this is verified with sc/CHECK.js's
 * `checkout` and `buy` scanners after deploy, not by eye.
 * ================================================================== */

/* the redundant middle box goes */
html body.cl-v2:not(.cl-x) form.checkout p.form-row:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-shipping-fields p.form-row:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-billing-fields p.form-row:not(.cl-x) {
  border: 0 !important;
  border-radius: 0 !important;
  padding: 0 !important;
  background: transparent !important;
}

/* labels reach the brief's floor for a control label */
html body.cl-v2:not(.cl-x) form.checkout p.form-row > label:not(.cl-x),
html body.cl-v2:not(.cl-x) form.checkout label.woocommerce-form__label:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-shipping-fields label:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-billing-fields label:not(.cl-x) {
  font-size: 14px !important;
  line-height: 1.4 !important;
}

/* inputs to the 48px the rest of the site uses */
html body.cl-v2:not(.cl-x) form.checkout input.input-text:not(.cl-x),
html body.cl-v2:not(.cl-x) form.checkout select:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-shipping-fields input.input-text:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-billing-fields input.input-text:not(.cl-x) {
  height: 48px !important;
  min-height: 48px !important;
  padding-top: 0 !important;
  padding-bottom: 0 !important;
  font-size: 16px !important;
}

/* 79b — the State dropdown did not match the field beside it.
 *
 * State is a select2 widget, not a plain <select> — the native control is
 * 2px wide and hidden, which is why block 79's `select` rule did nothing to
 * it. Measured: .select2-selection was 326x63 with 14px text, sitting next to
 * a ZIP Code input that is 48px with 16px text. Two controls side by side,
 * 15px apart in height.
 *
 * 16px also matters on its own: an input under 16px makes iOS zoom the page
 * when it is focused, which on a checkout throws the customer's view. */
html body.cl-v2:not(.cl-x) form.checkout .select2-container:not(.cl-x),
html body.cl-v2:not(.cl-x) form.checkout .select2-container .select2-selection:not(.cl-x),
html body.cl-v2:not(.cl-x) form.checkout .select2-container .select2-selection--single:not(.cl-x) {
  height: 48px !important;
  min-height: 48px !important;
  font-size: 16px !important;
}
html body.cl-v2:not(.cl-x) form.checkout .select2-selection__rendered:not(.cl-x) {
  line-height: 46px !important;
  font-size: 16px !important;
  padding: 0 28px 0 16px !important;
  /* The 46px line-height alone was not enough: select2 ships
   * `padding: 8px 8px 8px 16px`, so the rendered span measured 46 + 8 + 8 =
   * 62px inside a 48px control and the state name hung out below the box.
   * Caught by screenshotting it, not by the height numbers, which looked
   * right at the container level. Right padding keeps the arrow clear. */
  height: 46px !important;
  display: block !important;
  overflow: hidden !important;
  text-overflow: ellipsis !important;
  white-space: nowrap !important;
}
html body.cl-v2:not(.cl-x) form.checkout .select2-selection__arrow:not(.cl-x) {
  height: 46px !important;
}

/* 79c — centre the select2 label properly.
 * line-height centring left it sitting ~15px low, because the selection box
 * has its own padding that the line box does not know about. Flex centring
 * does not care what the padding is. */
html body.cl-v2:not(.cl-x) form.checkout .select2-container .select2-selection--single:not(.cl-x),
html body.cl-v2:not(.cl-x) form.checkout .select2-container .select2-selection:not(.cl-x) {
  display: flex !important;
  align-items: center !important;
  padding: 0 !important;
}
html body.cl-v2:not(.cl-x) form.checkout .select2-selection__rendered:not(.cl-x) {
  flex: 1 1 auto !important;
  line-height: 1.2 !important;
  height: auto !important;
}
/* The arrow STAYS absolutely positioned, which is how select2 ships it and
 * how it was working before this block touched it. Making it static dropped
 * its inner <b> — the actual chevron, which select2 positions absolutely
 * inside it — onto the left of the state name, and collapsed the arrow span
 * to 0 height. Only the vertical centring needed fixing; the arrow did not. */
html body.cl-v2:not(.cl-x) form.checkout .select2-selection__arrow:not(.cl-x) {
  position: absolute !important;
  right: 6px !important;
  top: 0 !important;
  height: 46px !important;
}


/* ==================================================================
 * 80. THE ADD TO CART BUTTON WAS TOO BIG
 *
 * Noah, looking at it: "add to cart button is to big."
 *
 * Block 72 took it from 12.5px to 15px and block 67 put it at weight 800, to
 * get it off the brief's "tiny text" floor. Both together overshot — 15px at
 * 800 with 0.08em tracking fills a 147px card button edge to edge and reads
 * as the loudest thing on the card, which is the same complaint the PRICE got
 * earlier in this session.
 *
 *   was   147x48   15px / 800 / 1.2px tracking
 *   now   147x44   13.5px / 700 / 0.6px tracking
 *
 * 44px is kept deliberately: it is the tap-target floor, and going under it
 * to make the button look smaller would trade a real usability guarantee for
 * an appearance. The weight comes out of the TYPE instead, which is where the
 * loudness actually was.
 * ================================================================== */

html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc button.cl-atc__btn:not(.cl-q):not(.cl-w),
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc a.cl-atc__btn:not(.cl-q):not(.cl-w) {
  font-size: 13.5px !important;
  font-weight: 700 !important;
  letter-spacing: 0.045em !important;
  min-height: 44px !important;
  height: 44px !important;
  padding: 10px 12px !important;
}

/* ==================================================================
 * 81. THE ADDRESS FORM WAS SMASHED SIDEWAYS AND STRETCHED DOWNWARDS
 *
 * Noah, looking at it on a phone: "It's so bad. Smashed and crazy."
 *
 * Measured at 375 (sc/co375.js + sc/corhythm.js), and it is two opposite
 * mistakes happening at once:
 *
 *   SHIP TO card padding        0px      -> every field sits 1px from the
 *                                           card border. Two 1px outlines
 *                                           running parallel down the whole
 *                                           form with nothing between them.
 *                                           (card 313w, street field 311w,
 *                                           gap L1 R1.)
 *   gap between fields         30px      -> while being cramped horizontally
 *                                           it is stretched vertically, so
 *                                           the form reads as scattered AND
 *                                           tight at the same time.
 *   email row gap              20px      -> and not even consistent.
 *
 * Both move onto the brief's spacing scale: 16px inset, 16px rhythm. The
 * fields lose ~32px of width and gain air on every side, which is the trade
 * that makes a form look composed instead of jammed into its own border.
 *
 * Labels stay CENTRED. That is Noah's standing rule for phones, and this
 * change is about spacing, not alignment — if the centring is the part that
 * reads as "crazy" it is one line to flip, but it is his call, not mine.
 * ================================================================== */

html body.cl-v2:not(.cl-x) div.woocommerce-shipping-fields:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-billing-fields:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-additional-fields:not(.cl-x) {
  padding: 16px !important;
}

/* consistent 16px rhythm between fields, replacing 30px and a stray 20px */
html body.cl-v2:not(.cl-x) div.woocommerce-shipping-fields p.form-row:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-billing-fields p.form-row:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-additional-fields p.form-row:not(.cl-x) {
  margin-top: 0 !important;
  margin-bottom: 16px !important;
}

/* the section heading needs to clear the new padding, not sit on it */
html body.cl-v2:not(.cl-x) div.woocommerce-shipping-fields > h3:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-billing-fields > h3:not(.cl-x) {
  margin: 0 0 16px !important;
}

/* 81b — the rhythm belongs to the GRID, not to the rows.
 *
 * .woocommerce-shipping-fields__field-wrapper is display:grid with
 * row-gap: 12px, so 81's `margin-bottom: 16px` on each row ADDED to it and
 * produced 28px — not the 16px it was setting. With a grid parent the gap is
 * the one place the spacing can live; a margin on the child is a second,
 * invisible source that silently sums. Rows go to 0 and the grid carries 16. */
html body.cl-v2:not(.cl-x) div.woocommerce-shipping-fields__field-wrapper:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-billing-fields__field-wrapper:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-additional-fields__field-wrapper:not(.cl-x) {
  row-gap: 16px !important;
}
html body.cl-v2:not(.cl-x) div.woocommerce-shipping-fields p.form-row:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-billing-fields p.form-row:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-additional-fields p.form-row:not(.cl-x) {
  margin-bottom: 0 !important;
}

/* 81c — the email emphasis box had the same problem one level in.
 *
 * The email row keeps its light purple outline on purpose — it groups the
 * field with "We send your receipt and tracking here", which is worth saying.
 * But measured at 375 its own input sat at `inner gap L1 R1`, i.e. exactly the
 * 1px smashing block 81 just fixed on the card, repeated inside the one row
 * that still has a border. Same fix, same 12px scale step.
 *
 * (The 17px below the last field is the card's 16px bottom padding, not a
 * gap — checked before touching it.) */
/* This needs an ID to land. woocommerce.css owns the email row through
 * `body.cl-embed form.checkout #billing_email_field` — (1,2,2) — and ONE ID
 * beats any number of classes, so the first version of this rule at (0,6,4)
 * matched and lost in silence. It is the first trap in CHECK-EVERYTHING.md and
 * I walked into it anyway; the padding read 0px on a rule that was live on the
 * server, which is exactly how that failure looks. */
html body.cl-v2:not(.cl-x) form.checkout p#billing_email_field:not(.cl-x),
html body.cl-v2:not(.cl-x) form.checkout p#shipping_email_field:not(.cl-x),
html body.cl-v2:not(.cl-x) div.cl-contact-fields p.form-row:not(.cl-x) {
  padding: 12px !important;
}

/* ==================================================================
 * 82. THE ORDER SUMMARY LOOKED LIKE A SPREADSHEET
 *
 * Noah: "this looks like shit."
 *
 * Measured (sc/paylist.js at 375):
 *   .woocommerce-checkout-review-order   1px border   <- the card
 *   table.shop_table                     1px border   <- a second box inside it
 *   td / th                              padding 10px 0px
 *
 * Two nested outlines again, and cells with ZERO horizontal padding, so
 * "Subtotal" and "$100.00" sit hard against the table's border — the same
 * 1px smashing block 81 fixed on the address form, repeated on the one part
 * of the page a customer reads to decide whether to pay.
 *
 * The card keeps its border because it groups the section. The TABLE's border
 * goes, because a box drawn inside a box is just noise, and the cells get the
 * 12px they needed all along. Row separators stay — they are what makes a
 * total readable as a total.
 * ================================================================== */

html body.cl-v2:not(.cl-x) table.shop_table:not(.cl-x),
html body.cl-v2:not(.cl-x) table.woocommerce-checkout-review-order-table:not(.cl-x) {
  border: 0 !important;
  border-radius: 0 !important;
  width: 100% !important;
}
html body.cl-v2:not(.cl-x) table.shop_table th:not(.cl-x),
html body.cl-v2:not(.cl-x) table.shop_table td:not(.cl-x) {
  padding: 12px !important;
}
/* keep a hairline BETWEEN rows — that is the part doing real work */
html body.cl-v2:not(.cl-x) table.shop_table tr:not(.cl-x) > th:not(.cl-x),
html body.cl-v2:not(.cl-x) table.shop_table tr:not(.cl-x) > td:not(.cl-x) {
  border-top: 1px solid #D4D4D8 !important;
  border-left: 0 !important;
  border-right: 0 !important;
  border-bottom: 0 !important;
}
html body.cl-v2:not(.cl-x) table.shop_table tr:first-child:not(.cl-x) > th:not(.cl-x),
html body.cl-v2:not(.cl-x) table.shop_table tr:first-child:not(.cl-x) > td:not(.cl-x) {
  border-top: 0 !important;
}

/* 82b — Cash App was printing a stray ® that read as a duplicated label.
 * The gateway title already says "Cash App"; the superscript trademark mark
 * sat beside it and rendered as a second, half-finished line. */
html body.cl-v2:not(.cl-x) .wc_payment_method sup.cl-tm:not(.cl-x) {
  display: none !important;
}

/* ==================================================================
 * 83. THE ADDRESS FORM WAS SITTING IN AN EMPTY TWO-COLUMN GRID
 *
 * Noah: "Dude, it looks so bad." He was right, and I had seen this at tablet
 * width earlier in the session, said it needed fixing, and then did not come
 * back to it. This is that bug.
 *
 * WooCommerce wraps checkout addresses in div.col2-set — a TWO column grid,
 * built for billing in col-1 and shipping in col-2. This theme hides billing
 * behind the "Use a different billing address" checkbox, so one column is
 * permanently empty, and the address block is squashed into the other half:
 *
 *    768px    col2-set 470w   address block 228w   at x391..619  (right half)
 *   1440px    col2-set 550w   address block 268w   at x519..787  (right half)
 *
 * Measured per-field gaps looked symmetric the whole time (L17 R17), which is
 * why this survived several passes — the fields ARE centred, inside a box that
 * is itself half the width it should be. Measuring the field against its own
 * parent can never catch that; it needed the walk out to the ancestors.
 *
 * With billing collapsed there is only ever one column of content, so the grid
 * becomes one column and the address fills the width it was always given.
 * ================================================================== */

html body.cl-v2:not(.cl-x) form.checkout div.col2-set:not(.cl-x) {
  display: block !important;
  width: 100% !important;
  max-width: none !important;
}
html body.cl-v2:not(.cl-x) form.checkout div.col2-set > div.col-1:not(.cl-x),
html body.cl-v2:not(.cl-x) form.checkout div.col2-set > div.col-2:not(.cl-x) {
  width: 100% !important;
  max-width: none !important;
  float: none !important;
  margin-left: 0 !important;
  margin-right: 0 !important;
}
/* billing sits under shipping when it is opened, not beside it */
html body.cl-v2:not(.cl-x) form.checkout div.col2-set > div.col-2:not(.cl-x) {
  margin-top: 16px !important;
}

/* ==================================================================
 * 84. CHECKOUT: ONE COLUMN, LEFT ALIGNED — matching the reference
 *
 * Noah sent refinedbiolabs.com's checkout as the standard and said ours looks
 * bad beside it. Comparing them, the two differences that account for most of
 * the gap are structural, not decorative:
 *
 * 1. THEIRS IS ONE COLUMN. Ours is a two-column grid with an empty column.
 *    The wrapper is #customer_details, and theme-v2.css itself sets it to
 *    `display: grid` at (1,3,3) — so block 83's (0,5,4) rule matched and lost.
 *    An ID again, the same trap as the email row. With billing collapsed
 *    behind a checkbox there is only ever one column of content, so the second
 *    is dead space and the form is squeezed into half the width it has.
 *
 * 2. THEIR LABELS AND VALUES ARE LEFT ALIGNED. Ours are centred. Centring
 *    labels over full-width inputs gives a form no common edge to read down —
 *    the eye zig-zags instead of scanning. It is the single thing that most
 *    makes a form look amateur, and it is why ours reads as scattered even
 *    when every measurement is symmetrical.
 *
 * This overrides the standing "centre on mobile" rule FOR THE CHECKOUT FORM
 * ONLY. Noah's own reference is left aligned and he is pointing at it; titles,
 * buttons and card text elsewhere are untouched.
 * ================================================================== */

/* one column — needs the ID to beat the theme's own grid */
html body.cl-v2:not(.cl-x) form.checkout #customer_details.col2-set:not(.cl-x),
html body.cl-v2:not(.cl-x) #customer_details.col2-set:not(.cl-x):not(.cl-y) {
  display: block !important;
  grid-template-columns: none !important;
  width: 100% !important;
  max-width: none !important;
}
html body.cl-v2:not(.cl-x) #customer_details.col2-set > div.col-1:not(.cl-x),
html body.cl-v2:not(.cl-x) #customer_details.col2-set > div.col-2:not(.cl-x) {
  width: 100% !important;
  max-width: none !important;
  float: none !important;
}

/* left aligned, like the reference */
html body.cl-v2:not(.cl-x) form.checkout .woocommerce-shipping-fields label:not(.cl-x),
html body.cl-v2:not(.cl-x) form.checkout .woocommerce-billing-fields label:not(.cl-x),
html body.cl-v2:not(.cl-x) form.checkout .woocommerce-additional-fields label:not(.cl-x),
html body.cl-v2:not(.cl-x) form.checkout p.form-row label:not(.cl-x),
html body.cl-v2:not(.cl-x) form.checkout p#billing_email_field label:not(.cl-x) {
  text-align: left !important;
  display: block !important;
}
html body.cl-v2:not(.cl-x) form.checkout input.input-text:not(.cl-x),
html body.cl-v2:not(.cl-x) form.checkout textarea:not(.cl-x),
html body.cl-v2:not(.cl-x) form.checkout .select2-selection__rendered:not(.cl-x) {
  text-align: left !important;
}

/* ==================================================================
 * 85. READING TEXT GOES LEFT ALIGNED
 *
 * Noah sent refinedbiolabs.com and said: "mine is so hard to read... take
 * from these photos and apply it to my website", while keeping the CORE LABS
 * colours.
 *
 * Measured the difference rather than guessing at it (sc/align.js at 375):
 *
 *     page      reading blocks   centred   left
 *     home            19            13       6
 *     shop            10             8       2
 *     product         13            11       2
 *     faq              8             6       2
 *     ------------------------------------------
 *     TOTAL           50            38      12      -> 68% centred
 *
 * The reference is left aligned throughout. That is the whole difference in
 * "easy to read": centred text starts every line at a different x, so the eye
 * has to search for the start of each one. Left aligned gives it a single
 * edge to return to. It matters most on exactly the blocks we centre — three
 * and four line paragraphs.
 *
 * THIS SUPERSEDES THE STANDING "centre on mobile" RULE FOR BODY COPY ONLY.
 * Noah set that rule, and he is now looking at both and choosing the other.
 * What is NOT touched, because it is design rather than reading:
 *   - product cards (ul.products) — the centred card is his approved design
 *   - buttons, badges, chips, the RUO banner, the call tab
 *   - nav and footer link rows
 * Colours, faces and sizes are all unchanged.
 * ================================================================== */

html body.cl-v2:not(.cl-x) main p:not(.cl-x),
html body.cl-v2:not(.cl-x) main li:not(.cl-x),
html body.cl-v2:not(.cl-x) main dd:not(.cl-x),
html body.cl-v2:not(.cl-x) footer p:not(.cl-x) {
  text-align: left !important;
}

/* section headings follow their paragraphs, as in the reference */
html body.cl-v2:not(.cl-x) main section h2:not(.cl-x),
html body.cl-v2:not(.cl-x) main section h3:not(.cl-x),
html body.cl-v2:not(.cl-x) main article h2:not(.cl-x),
html body.cl-v2:not(.cl-x) main article h3:not(.cl-x) {
  text-align: left !important;
}

/* …but these stay exactly as they were: they are design, not prose */
html body.cl-v2:not(.cl-x) ul.products li.product p:not(.cl-x),
html body.cl-v2:not(.cl-x) ul.products li.product h2:not(.cl-x),
html body.cl-v2:not(.cl-x) ul.products li.product h3:not(.cl-x),
html body.cl-v2:not(.cl-x) main .cl-btn:not(.cl-x),
html body.cl-v2:not(.cl-x) main button:not(.cl-x),
html body.cl-v2:not(.cl-x) main [class*="badge"]:not(.cl-x),
html body.cl-v2:not(.cl-x) main [class*="chip"]:not(.cl-x),
html body.cl-v2:not(.cl-x) main [class*="pill"]:not(.cl-x),
html body.cl-v2:not(.cl-x) [class*="ruo"]:not(.cl-x),
html body.cl-v2:not(.cl-x) [class*="calltab"]:not(.cl-x),
html body.cl-v2:not(.cl-x) [class*="marquee"] p:not(.cl-x),
html body.cl-v2:not(.cl-x) [class*="ticker"] p:not(.cl-x) {
  text-align: center !important;
}

/* 86 — "SEMAGLUTIDE" was breaking mid-word into "SEMAGLUTI / DE".
 *
 * Only at 360 (sc/wordbreak.js): span.cl-vial__pill is 91px wide and carries
 * `overflow-wrap: anywhere`, which permits a break at ANY character — so a
 * product name splits in the middle rather than the box growing. A compound
 * name cut in half is worse than any overflow it was guarding against, and on
 * a product chip it reads as a typo.
 *
 * The word is kept whole and the pill is allowed to take the width it needs.
 * The type is NOT shrunk to make it fit — TYPOGRAPHY-GUARDIAN: fix the layout,
 * never the type. */
html body.cl-v2:not(.cl-x) span.cl-vial__pill:not(.cl-x):not(.cl-w) {
  overflow-wrap: normal !important;
  word-break: keep-all !important;
  hyphens: none !important;
  white-space: nowrap !important;
  width: auto !important;
  max-width: none !important;
}

/* ==================================================================
 * 87. DESKTOP CHECKOUT — THE REFERENCE'S STRUCTURE, OUR COLOURS
 *
 * Noah sent a competitor's desktop checkout: "I love the lines and everything
 * ... use the borders and the lines that they use but again keep our colorway,
 * you might need to thicken some things on ours."
 *
 * Measured ours at 1440 first. The two-column structure is ALREADY right —
 * address left 550w at x237, order summary right 386w at x832 — so this is not
 * a rebuild. What is wrong is weight and separation:
 *
 *   "SHIP TO" / "Order summary"   ~12.5px, almost invisible as headings
 *   right column                   same white as the page, so it does not read
 *                                  as a panel at all
 *   right column                   scrolls away, leaving ~1,700px of empty
 *                                  white beside the form on a 3,005px page
 *
 * So: headings get real weight, the summary becomes a proper panel on our
 * #F7F8FA, and it sticks so it stays with the reader. Borders go to the
 * reference's heavier, more defined line rather than our near-invisible one.
 * Every colour is CORE LABS — no pink, no borrowed palette.
 * ================================================================== */

@media (min-width: 900px) {
  /* the order summary becomes a panel, and follows you down */
  html body.cl-v2:not(.cl-x) #order_review:not(.cl-x),
  html body.cl-v2:not(.cl-x) div.woocommerce-checkout-review-order:not(.cl-x) {
    background: #F7F8FA !important;
    border: 1px solid #E5E1F2 !important;
    border-radius: 14px !important;
    padding: 20px !important;
    position: sticky !important;
    top: 24px !important;
    align-self: start !important;
  }
}

/* section headings carry real weight, like the reference */
html body.cl-v2:not(.cl-x) form.checkout h3:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-shipping-fields > h3:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-billing-fields > h3:not(.cl-x),
html body.cl-v2:not(.cl-x) #order_review_heading:not(.cl-x) {
  font-size: 18px !important;
  font-weight: 800 !important;
  letter-spacing: 0.04em !important;
  color: #171923 !important;
  line-height: 1.3 !important;
}

/* lines: defined, not apologetic — the "thicken it" note */
html body.cl-v2:not(.cl-x) div.woocommerce-shipping-fields:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-billing-fields:not(.cl-x),
html body.cl-v2:not(.cl-x) div.woocommerce-additional-fields:not(.cl-x) {
  border: 1px solid #E5E1F2 !important;
  border-radius: 14px !important;
}
html body.cl-v2:not(.cl-x) form.checkout input.input-text:not(.cl-x),
html body.cl-v2:not(.cl-x) form.checkout textarea:not(.cl-x),
html body.cl-v2:not(.cl-x) form.checkout .select2-selection:not(.cl-x) {
  border: 1px solid #E5E1F2 !important;
}
html body.cl-v2:not(.cl-x) form.checkout input.input-text:focus:not(.cl-x),
html body.cl-v2:not(.cl-x) form.checkout textarea:focus:not(.cl-x) {
  border-color: #6D28D9 !important;
  box-shadow: 0 0 0 3px rgba(109, 40, 217, 0.14) !important;
  outline: none !important;
}

/* 87b — the accordion row labels ("SHIP TO", "SHIPPING", "PAYMENT").
 * These are not headings — they are the left-hand label of a collapsed
 * summary row, the same pattern the reference uses for "Ship to / Shipping /
 * Payment". They were 12.5px, under the brief's 14px floor for a control
 * label and far too quiet to anchor a section on a 1440 screen. */
html body.cl-v2:not(.cl-x) span.cl-ck__label:not(.cl-x) {
  font-size: 14px !important;
  letter-spacing: 0.08em !important;
  color: #4B5563 !important;
}
html body.cl-v2:not(.cl-x) span.cl-ck__value:not(.cl-x) {
  font-size: 15px !important;
  font-weight: 700 !important;
  color: #171923 !important;
}

/* ==================================================================
 * 88. THE REFERENCE TYPE SYSTEM — Inter, tight, heavy
 *
 * Noah: "I really want the font and I really want the sizing as well... do the
 * mobile version too, obviously they have to be different desktop and mobile."
 *
 * Read from disguisedalpha.com's OWN computed styles, at both widths — not
 * guessed from a screenshot (sc/refscale.js + a DOM probe in their page):
 *
 *                MOBILE 375                     DESKTOP 1440
 *   h2    Inter  34px / 900  ls -1.02px    Inter 64px / 900  ls -1.92px
 *   h3    Inter  28px / 900  ls -0.70px    Inter 28px / 900
 *   body  14.5px lh 1.60                   16px   lh 1.50
 *
 * The constant across both is **-0.03em tracking** (-1.02/34 and -1.92/64 are
 * both 0.03). That is the whole signal: heavy weight pulled TIGHT. CORE LABS
 * has been doing the opposite — spaced caps with POSITIVE tracking — which is
 * why ours reads as a label and theirs reads as a headline.
 *
 * Their ink is one near-black at four opacities, not four greys:
 *   #0B0F17 at 1.0 / 0.72 / 0.52 / 0.32
 * CORE LABS ink is #171923, so the same ramp is built from ours.
 *
 * NOT TAKEN: their accent #FF2AA6. CORE LABS purple stays, everywhere.
 * ================================================================== */

html body.cl-v2:not(.cl-x) {
  --cl-ink:    #171923;
  --cl-ink-2:  rgba(23, 25, 35, 0.72);
  /* ink-3 and ink-4 are for ICONS, RULES and DISABLED states only.
   * On white they are 3.58:1 and 2.1:1 — both under the 4.5:1 text bar.
   * The reference uses the same ramp; that does not make it safe here. */
  --cl-ink-3:  rgba(23, 25, 35, 0.52);
  --cl-ink-4:  rgba(23, 25, 35, 0.32);
  --cl-line:   rgba(23, 25, 35, 0.08);
  --cl-line-2: rgba(23, 25, 35, 0.16);
  --cl-surface:      #FFFFFF;
  --cl-surface-soft: #FAFAFB;
  --cl-surface-gray: #F3F3F5;
  --cl-shadow-sm: 0 4px 14px rgba(0, 0, 0, 0.06);
  --cl-shadow-md: 0 12px 36px rgba(0, 0, 0, 0.08);
  --cl-shadow-lg: 0 28px 80px rgba(0, 0, 0, 0.12);
}

/* ---- headings: Inter 900, tracked TIGHT, mobile scale ---- */
html body.cl-v2:not(.cl-x) h1:not(.cl-x),
html body.cl-v2:not(.cl-x) h2:not(.cl-x),
html body.cl-v2:not(.cl-x) h3:not(.cl-x),
html body.cl-v2:not(.cl-x) main h1:not(.cl-x),
html body.cl-v2:not(.cl-x) main section h2:not(.cl-x),
html body.cl-v2:not(.cl-x) main article h2:not(.cl-x) {
  font-family: Poppins, system-ui, sans-serif !important;
  font-weight: 900 !important;
  letter-spacing: -0.03em !important;
  text-transform: none !important;
  color: var(--cl-ink) !important;
}
html body.cl-v2:not(.cl-x) h1:not(.cl-x),
html body.cl-v2:not(.cl-x) main h1:not(.cl-x) {
  font-size: 34px !important;
  line-height: 1.06 !important;
}
html body.cl-v2:not(.cl-x) main section h2:not(.cl-x),
html body.cl-v2:not(.cl-x) main article h2:not(.cl-x) {
  font-size: 30px !important;
  line-height: 1.08 !important;
}
html body.cl-v2:not(.cl-x) main section h3:not(.cl-x),
html body.cl-v2:not(.cl-x) main article h3:not(.cl-x) {
  font-size: 22px !important;
  line-height: 1.12 !important;
}

/* ---- desktop scale, measured from theirs ---- */
@media (min-width: 900px) {
  html body.cl-v2:not(.cl-x) h1:not(.cl-x),
  html body.cl-v2:not(.cl-x) main h1:not(.cl-x) {
    font-size: 58px !important;
    line-height: 1.02 !important;
  }
  html body.cl-v2:not(.cl-x) main section h2:not(.cl-x),
  html body.cl-v2:not(.cl-x) main article h2:not(.cl-x) {
    font-size: 48px !important;
    line-height: 1.04 !important;
  }
  html body.cl-v2:not(.cl-x) main section h3:not(.cl-x),
  html body.cl-v2:not(.cl-x) main article h3:not(.cl-x) {
    font-size: 28px !important;
    line-height: 1.10 !important;
  }
}

/* ---- body copy: Inter, their line-height ---- */
html body.cl-v2:not(.cl-x) main p:not(.cl-x),
html body.cl-v2:not(.cl-x) main li:not(.cl-x) {
  font-family: "DM Sans", system-ui, sans-serif !important;
  line-height: 1.6 !important;
  color: var(--cl-ink-2) !important;
}

/* ==================================================================
 * 89. THE REFERENCE'S STRUCTURE — in CORE LABS purple
 *
 * Everything below was READ from disguisedalpha.com's live computed styles,
 * not copied from their stylesheet and not guessed from a screenshot:
 *
 *   surfaces      #FFFFFF (26 boxes) · #FAFAFB soft · #0B0F17 dark sections
 *   container     1240px max-width, 32px padding   (12 uses — the standard)
 *   section       88px top AND bottom              (7 uses)
 *   eyebrow       Inter 12px/800, ls 0.72px, uppercase, in the accent colour
 *   primary btn   15px/600, padding 16px 32px, radius 999px
 *   feature card  radius 28px, padding 32px
 *   lines         rgba(ink, 0.08) and 0.16
 *
 * Noah: "I like our colors but I like the way theirs is easy to read."
 * So the GEOMETRY is theirs and the COLOUR is ours. Their accent #FF2AA6
 * is replaced everywhere by CORE LABS purple. Nothing pink ships.
 *
 * Why 88px matters: ours were running much tighter, and section rhythm is
 * what tells a reader "this is a new idea" without a line or a box. It is
 * most of the "clean" people attribute to a design.
 * ================================================================== */

/* ---- container: 1240 / 32, theirs ---- */
@media (min-width: 900px) {
  html body.cl-v2:not(.cl-x) main .container:not(.cl-x),
  html body.cl-v2:not(.cl-x) main div.container:not(.cl-x) {
    max-width: 1240px !important;
    padding-left: 32px !important;
    padding-right: 32px !important;
    margin-left: auto !important;
    margin-right: auto !important;
  }
  /* ---- section rhythm: 88px, theirs ---- */
  html body.cl-v2:not(.cl-x) main > section:not(.cl-x),
  html body.cl-v2:not(.cl-x) main section.cl-section:not(.cl-x) {
    padding-top: 88px !important;
    padding-bottom: 88px !important;
  }
}
/* mobile keeps its own, tighter rhythm — a phone cannot afford 88 */
@media (max-width: 899px) {
  html body.cl-v2:not(.cl-x) main > section:not(.cl-x),
  html body.cl-v2:not(.cl-x) main section.cl-section:not(.cl-x) {
    padding-top: 48px !important;
    padding-bottom: 48px !important;
  }
  html body.cl-v2:not(.cl-x) main .container:not(.cl-x) {
    padding-left: 20px !important;
    padding-right: 20px !important;
  }
}

/* ---- the eyebrow pattern, in purple instead of their pink ---- */
html body.cl-v2:not(.cl-x) .cl-section__eyebrow:not(.cl-x),
html body.cl-v2:not(.cl-x) [class*="eyebrow"]:not(.cl-x),
html body.cl-v2:not(.cl-x) [class*="kicker"]:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-feat__label:not(.cl-x) {
  font-family: Poppins, system-ui, sans-serif !important;
  font-size: 12px !important;
  font-weight: 800 !important;
  letter-spacing: 0.06em !important;
  text-transform: uppercase !important;
  color: #6D28D9 !important;
}

/* ---- body copy to Inter at their size ---- */
html body.cl-v2:not(.cl-x) main p:not(.cl-x),
html body.cl-v2:not(.cl-x) main li:not(.cl-x) {
  font-size: 16px !important;
}

/* ---- feature cards: 28px radius, 32px padding, hairline, no shadow ---- */
@media (min-width: 900px) {
  html body.cl-v2:not(.cl-x) main section .cl-card:not(.cl-x),
  html body.cl-v2:not(.cl-x) main section [class*="__card"]:not(.cl-x),
  html body.cl-v2:not(.cl-x) main section article:not(.cl-x) {
    border-radius: 28px !important;
    padding: 32px !important;
    /* line-2, not line. The reference's 0.08 line computes to #ECEDED on our
     * white — 1.17:1, which sc/CHECK.js's wash check correctly calls invisible.
     * Their 0.08 works on their surfaces; ours needs the 0.16 step to actually
     * draw a card edge. Same lesson as the ink ramp: borrowed opacity values
     * have to be re-checked against the background they land on. */
    border: 1px solid var(--cl-line-2, #000000) !important;
    box-shadow: none !important;
  }
}

/* ==================================================================
 * 90. PORTRAIT VIALS WERE SITTING IN LANDSCAPE PANELS
 *
 * Noah: "why are my product cards still cropped fucking weird on the other
 * products?" Nothing is cropped — every image is object-fit: contain. The
 * fault is the opposite, and worse on desktop (sc/cardcrop.js):
 *
 *            image AR    panel AR    the vial renders
 *   375        0.70        0.81      140 wide in a 161 box
 *   1440       0.70        1.24      166 wide in a 297 box  <- 131px of air
 *
 * The vial artwork is PORTRAIT (340x490). The panel was a fixed HEIGHT, so as
 * the card got wider the panel turned landscape, and `contain` — which fits by
 * the tighter axis — kept scaling the vial to the 240px height while the box
 * grew sideways around it. At 1440 the product filled 56% of its own panel.
 *
 * Fixed height is the bug. The panel now takes an ASPECT RATIO, so it stays
 * portrait at every width and the vial scales with the card:
 *
 *   1440:  297 wide -> 356 tall, vial renders ~246 wide, not 166.
 *
 * object-fit stays `contain`: the vial is never cropped or stretched, which
 * is the one thing that must not happen to it.
 * ================================================================== */

html body.cl-v2:not(.cl-x) ul.products li.product.product span.cl-cardimg:not(.cl-x):not(.cl-z),
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link > img:not(.cl-x):not(.cl-z) {
  aspect-ratio: 1 / 1.2 !important;
  height: auto !important;
  min-height: 0 !important;
  max-height: none !important;
  flex: 0 0 auto !important;
}
@media (min-width: 900px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product span.cl-cardimg:not(.cl-x):not(.cl-z),
  html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link > img:not(.cl-x):not(.cl-z) {
    aspect-ratio: 1 / 1.2 !important;
    height: auto !important;
  }
}

/* 90b — Inter everywhere, not just inside <main>.
 * Block 88 scoped the body face to `main p`, so the footer — Shop / Company /
 * Support / Legal and every link under them — stayed on DM Sans at 14px.
 * Noah: "the shop company support legal all that, all the text and font just
 * looks bad". It was literally a different typeface from the rest of the page. */
html body.cl-v2:not(.cl-x),
html body.cl-v2:not(.cl-x) p:not(.cl-x),
html body.cl-v2:not(.cl-x) li:not(.cl-x),
html body.cl-v2:not(.cl-x) a:not(.cl-x),
html body.cl-v2:not(.cl-x) span:not(.cl-x),
html body.cl-v2:not(.cl-x) td:not(.cl-x),
html body.cl-v2:not(.cl-x) label:not(.cl-x),
html body.cl-v2:not(.cl-x) input:not(.cl-x),
html body.cl-v2:not(.cl-x) button:not(.cl-x),
html body.cl-v2:not(.cl-x) footer:not(.cl-x),
html body.cl-v2:not(.cl-x) footer *:not(.cl-x) {
  font-family: "DM Sans", system-ui, -apple-system, sans-serif !important;
}

/* 90c — footer columns get the reference's heading/link treatment */
html body.cl-v2:not(.cl-x) footer h3:not(.cl-x),
html body.cl-v2:not(.cl-x) footer h4:not(.cl-x),
html body.cl-v2:not(.cl-x) footer [class*="heading"]:not(.cl-x) {
  font-size: 12px !important;
  font-weight: 800 !important;
  letter-spacing: 0.06em !important;
  text-transform: uppercase !important;
  /* ink-2, NOT ink-3.
   *
   * I lifted the reference's four-step opacity ramp (1.0/0.72/0.52/0.32) and
   * used 0.52 for these headings because that is what they use. On our white
   * it computes to #86878D = 3.58:1, under the 4.5:1 bar — sc/CHECK.js caught
   * 162 elements. A ratio that works on their surface does not automatically
   * work on ours, and the ramp has to be re-checked against the background it
   * actually lands on, not inherited. 0.72 gives #585961 at ~7.2:1. */
  /* #4B5563 — the brief's own "secondary text" value, 7.6:1 on white.
   * ink-2 computed to 6.96:1, which clears WCAG AA (4.5) but sits 0.04 under
   * the wash scanner's 7:1 comfort bar. A fixed value is also easier to reason
   * about than an opacity whose result depends on whatever it lands on. */
  color: #4B5563 !important;
  margin-bottom: 12px !important;
}
html body.cl-v2:not(.cl-x) footer a:not(.cl-x) {
  font-size: 15px !important;
  font-weight: 500 !important;
  letter-spacing: normal !important;
  text-transform: none !important;
  color: #374151 !important;
  line-height: 2 !important;
}

/* ==================================================================
 * 91. BUTTONS — the reference's proportions, our purple
 *
 * Read from disguisedalpha.com's live styles:
 *   primary   15px / 600, padding 16px 32px, radius 999px   (187x57)
 *   small     12.5px / 700, padding 10px 14px, radius 10px
 *
 * Ours were 15px/700 with 1.2px tracking and tight padding. The two things
 * that make theirs feel substantial are the GENEROUS horizontal padding
 * (32px, not 14) and NO tracking — our spaced caps make a button read as a
 * label rather than something to press.
 *
 * The pill radius matches what CORE LABS already uses, so nothing changes
 * shape; this is proportion and type only. Colour is untouched: purple.
 * ================================================================== */

html body.cl-v2:not(.cl-x) a.cl-btn:not(.cl-q):not(.cl-z),
html body.cl-v2:not(.cl-x) button.cl-btn:not(.cl-q):not(.cl-z),
html body.cl-v2:not(.cl-x) a.cl-btn.cl-chero__explore:not(.cl-q):not(.cl-z),
html body.cl-v2:not(.cl-x) a.cl-btn.cl-feat__all:not(.cl-q):not(.cl-z),
html body.cl-v2:not(.cl-x) button.single_add_to_cart_button:not(.cl-q):not(.cl-z) {
  font-family: Poppins, system-ui, sans-serif !important;
  font-size: 15px !important;
  font-weight: 600 !important;
  letter-spacing: 0 !important;
  text-transform: none !important;
  padding: 16px 32px !important;
  min-height: 52px !important;
  line-height: 1.2 !important;
}

/* the small/secondary size, theirs */
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc button.cl-atc__btn:not(.cl-q):not(.cl-z),
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc a.cl-atc__btn:not(.cl-q):not(.cl-z) {
  font-family: Poppins, system-ui, sans-serif !important;
  font-size: 13.5px !important;
  font-weight: 700 !important;
  letter-spacing: 0 !important;
  text-transform: none !important;
  padding: 12px 16px !important;
  min-height: 46px !important;
  height: auto !important;
}

/* ==================================================================
 * 92. THE FLAWS IN NOAH'S SCREENSHOTS — measured, then fixed
 *
 * 1. HEADINGS CENTRED OVER LEFT-ALIGNED TEXT.
 *    Block 85 left-aligned `main section h2` and `main p`, but several
 *    headings are not inside a <section>, so they stayed centred while their
 *    paragraph moved left. Measured on home at 1440 (sc/flaws.js):
 *        "Questions? Reach a member..."   h2 left 460   p left 115   -345px
 *    A heading floating 345px away from the text it introduces is worse than
 *    either alignment on its own — it is the "Starter Bundles" indent.
 *
 * 2. THE VIAL TOUCHED ITS PANEL EDGES.
 *    Strictly it is not cropped — object-fit: contain paints 247x356 inside a
 *    297x356 panel, so nothing is lost. But it fills the panel's full height
 *    with ZERO margin, and a vial whose base sits exactly on a hard edge reads
 *    as cut. The reference never does this: their artwork is square and sits
 *    inside its box with air. Padding gives ours the same breathing room.
 *
 * 3. UNNECESSARY LINES.
 *    The card drew a rule under the image panel AND under the price AND around
 *    the chip. The reference uses one hairline per card and lets spacing do
 *    the separating.
 * ================================================================== */

/* 1 — every heading follows its text */
html body.cl-v2:not(.cl-x) main h2:not(.cl-x),
html body.cl-v2:not(.cl-x) main h3:not(.cl-x),
html body.cl-v2:not(.cl-x) main h4:not(.cl-x),
html body.cl-v2:not(.cl-x) footer h2:not(.cl-x),
html body.cl-v2:not(.cl-x) main .cl-contact__title:not(.cl-x),
html body.cl-v2:not(.cl-x) main [class*="__title"]:not(.cl-x) {
  text-align: left !important;
}
/* …except inside a product card, which stays centred by design */
html body.cl-v2:not(.cl-x) ul.products li.product h2:not(.cl-x),
html body.cl-v2:not(.cl-x) ul.products li.product h3:not(.cl-x),
html body.cl-v2:not(.cl-x) ul.products li.product [class*="__title"]:not(.cl-x) {
  text-align: center !important;
}

/* 2 — the vial gets air inside its panel */
html body.cl-v2:not(.cl-x) ul.products li.product.product span.cl-cardimg:not(.cl-x):not(.cl-v) {
  padding: 14px !important;
  box-sizing: border-box !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link > img:not(.cl-x):not(.cl-v) {
  padding: 14px !important;
  box-sizing: border-box !important;
}

/* 3 — one hairline per card, not three */
html body.cl-v2:not(.cl-x) ul.products li.product.product span.cl-cardimg:not(.cl-x):not(.cl-v) {
  border-bottom: 0 !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product span.price:not(.cl-x):not(.cl-v),
html body.cl-v2:not(.cl-x) ul.products li.product.product h2.woocommerce-loop-product__title:not(.cl-x):not(.cl-v) {
  border-top: 0 !important;
  border-bottom: 0 !important;
}

/* 92b — the heading was auto-CENTRED by margin, not by text-align.
 *
 * `text-align` on .cl-contact__title already computed to `left`, so block 92
 * looked correct and changed nothing visible. The real cause was geometry:
 *
 *   h2.cl-contact__title   x[460..980]  520w   margin-left/right: 345px
 *   its paragraph          x[115..1325] 1210w
 *
 * A max-width plus auto side margins centres the BOX, and no amount of
 * text-align moves a box. That is why it survived the alignment pass — I was
 * checking the wrong property. Measuring the box, not the text, found it in
 * one step. */
html body.cl-v2:not(.cl-x) main [class*="__title"]:not(.cl-x):not(.cl-u),
html body.cl-v2:not(.cl-x) footer [class*="__title"]:not(.cl-x):not(.cl-u),
html body.cl-v2:not(.cl-x) main section h2:not(.cl-x):not(.cl-u),
html body.cl-v2:not(.cl-x) footer section h2:not(.cl-x):not(.cl-u) {
  margin-left: 0 !important;
  margin-right: 0 !important;
}
/* product cards keep their centred title — it is centred by text-align there,
   not by margin, so this does not disturb it */
html body.cl-v2:not(.cl-x) ul.products li.product [class*="__title"]:not(.cl-x) {
  margin-left: auto !important;
  margin-right: auto !important;
}

/* 93 — the price range was breaking with the dash left dangling.
 *
 * SELANK renders "$44.99 – $59.99" and on a narrow card it wrapped as
 *     – $44.99 $59.99
 * with the en dash orphaned onto the start of a line. Block 68 allowed .price
 * to wrap (so a long range is never CUT), which is right — but a wrap point
 * either side of a dash is not. The dash is glued to the figures around it so
 * the whole range breaks as one unit or not at all. */
html body.cl-v2:not(.cl-x) ul.products li.product.product span.price:not(.cl-x):not(.cl-t) {
  white-space: nowrap !important;
  overflow-wrap: normal !important;
  word-break: keep-all !important;
}
/* if it genuinely cannot fit, shrink the GAP rather than orphan the dash */
@media (max-width: 420px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product span.price:not(.cl-x):not(.cl-t) {
    column-gap: 4px !important;
  }
}

/* ==================================================================
 * 94. TWO CART UIs WERE ON SCREEN AT ONCE
 *
 * Noah photographed two rounded controls overlapping each other. Measured
 * (sc/fabovl.js) — and it only reproduces once something is IN the cart,
 * which is why an earlier scan of an empty shop found nothing:
 *
 *   .cl-drawer       375x812  z:9997   open
 *   .cl-drawer__foot 373x333  z:3      inside it
 *   .cl-sticky-cart  375x208  z:90     STILL RENDERED UNDERNEATH
 *   -> collide 373x207px
 *
 * The sticky cart bar is the thing that invites you to open the drawer. Once
 * the drawer IS open it has no job, and leaving it behind puts a second cart
 * summary — with its own buttons — directly under the real one. At the
 * drawer's translucent edges both show through, which is the doubled control
 * in the photo.
 * ================================================================== */

html body.cl-v2:not(.cl-x):has(.cl-drawer.is-open) .cl-sticky-cart:not(.cl-x),
html body.cl-v2:not(.cl-x):has(.cl-drawer.is-open) [class*="sticky-cart"]:not(.cl-x) {
  display: none !important;
}
/* the call tab steps aside too — it sits at z:9989, just under the drawer's
   9997, so it paints over the drawer's left edge */
html body.cl-v2:not(.cl-x):has(.cl-drawer.is-open) a.cl-calltab:not(.cl-x) {
  display: none !important;
}

/* ==================================================================
 * 95. THE TWO CARD KINDS WERE DIFFERENT SIZES
 *
 * Noah: "uniform ... it's all over the place." He is right, and the `uniform`
 * gate was not catching it because that gate compares like-shaped cards and
 * these are two different shapes. Measured at 1440 (sc/cardkinds.js):
 *
 *                     panel        background        artwork
 *   starter packs   277 x 425   transparent      1200x1200 square
 *   vial products   297 x 356   #F5F3FF lilac     340x490  portrait
 *
 * Three differences at once, in one grid. The panel SIZE is pure CSS and is
 * fixed here: both kinds now take the same box, so the grid has one rhythm.
 *
 * The other two are ARTWORK, and CSS cannot fix either:
 *   - the pack images carry a WHITE BACKGROUND baked in, which is why their
 *     panel had to be left white; on lilac they would show a white rectangle
 *   - the pack art is square while the vials are portrait
 * Both need the pack images re-rendered as transparent cut-outs, the way the
 * vials already are. That is Noah's call, not mine.
 * ================================================================== */

html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link > img:not(.cl-x):not(.cl-s) {
  aspect-ratio: 1 / 1.1 !important;
  width: 100% !important;
  height: auto !important;
  max-height: none !important;
  object-fit: contain !important;
  object-position: center center !important;
  align-self: stretch !important;
  /* THE VIAL SAT TOO HIGH. Block 66 bled the image off the top with
   * `margin: -10px -10px 0`, and nothing since overrode the TOP value, so the
   * starter packs measured y=-9 — the artwork literally hanging over the card
   * edge — while the singles sat at y=+5. Two different placements in one row,
   * which is what read as "it floats, move the vial down".
   *
   * Keep the side bleed (that is what makes the panel full width) and give the
   * top back, so every vial starts inside the card at the same place.
   * whowins: this rule is (0,8,6) and the last of its specificity in the file,
   * which is why the change goes HERE and not in a new block. */
  margin: 0 -10px 12px !important;
  padding: 14px 10px 0 !important;
}

/* ==================================================================
 * 96. THE PRICE DASH RENDERED FIRST — "– $44.99 $59.99"
 *
 * SELANK showed its range with the dash in front of both figures. I twice
 * assumed this was a WRAP (block 68 let .price wrap so a long range is never
 * cut; block 93 then glued the dash with nowrap). Neither helped, because it
 * was never wrapping. Measured the children (sc/pricedom.js at 1440):
 *
 *   child[0] span.woocommerce-Price-amount  "$44.99"  order: 1   x1091
 *   child[1] span  (the en dash)            "–"       order: 0   x1066  <-
 *   child[2] span.woocommerce-Price-amount  "$59.99"  order: 1   x1187
 *
 * .price is display:flex, and something gives the AMOUNTS order:1 — probably
 * to float a "From" label ahead of them. WooCommerce's separator span has no
 * class and so keeps the default order:0, which in flex puts it before
 * everything. DOM order was right the whole time; flex was re-sorting it.
 *
 * Every child goes back to order 0 so the markup's own order governs. The
 * "From" label still comes first because it is first in the DOM.
 * ================================================================== */

html body.cl-v2:not(.cl-x) ul.products li.product.product span.price > *:not(.cl-x),
html body.cl-v2:not(.cl-x) span.price > *:not(.cl-x) {
  order: 0 !important;
}

/* 97 — the HERO buttons were missed by the button pass.
 *
 * Block 91 gave the reference's proportions to .cl-btn, .cl-chero__explore and
 * .cl-feat__all, but the two biggest buttons on the site — the ones in the
 * hero — carry their own classes and kept the old treatment:
 *
 *   .cl-hero2__shop    14px / 700  ls 1.12px  UPPERCASE
 *   .cl-hero2__aside   14px / 700  ls 1.12px  UPPERCASE
 *
 * So the first thing a visitor sees still read as a pair of spaced-caps
 * labels while everything below them had moved to the new system. Named
 * explicitly rather than widening the earlier selector, so it is obvious
 * which buttons this covers. */
html body.cl-v2:not(.cl-x) a.cl-hero2__shop:not(.cl-q):not(.cl-z),
html body.cl-v2:not(.cl-x) a.cl-hero2__aside:not(.cl-q):not(.cl-z),
html body.cl-v2:not(.cl-x) button.cl-hero2__shop:not(.cl-q):not(.cl-z),
html body.cl-v2:not(.cl-x) button.cl-hero2__aside:not(.cl-q):not(.cl-z) {
  font-family: Poppins, system-ui, sans-serif !important;
  font-size: 16px !important;
  font-weight: 600 !important;
  letter-spacing: 0 !important;
  text-transform: none !important;
  padding: 16px 32px !important;
  min-height: 54px !important;
}


/* 98 — the footer CONTACT heading was rendering at 12px, the eyebrow size.
 *
 * Measured on / at both 390 and 1440:
 *
 *   h2.cl-contact__title   12px / 800 / uppercase   "Questions? Reach a member of our team."
 *   p.cl-contact__eyebrow  12px / 800 / uppercase   "Talk to a real person"
 *
 * The section title and the little label above it were the SAME SIZE, so the
 * block read as two eyebrows and no heading.
 *
 * Cause: block 90c dressed footer column headings as 12px spaced caps and
 * reached them with `footer [class*="__title"]`. That attribute match is far
 * wider than the four column headings it was written for. Scanning every
 * element it actually hit:
 *
 *   footer h3.cl-footer__heading  x4   Shop / Company / Support / Legal
 *   footer h2.cl-contact__title   x1   <- the bug
 *
 * The four column headings are already caught by `footer h3` and by
 * `[class*="heading"]` on the same rule, so the `__title` arm contributed
 * NOTHING except this fault. Deleted it rather than stacking an override on
 * top — see the CSS-accumulation note; this file wins fights it should lose.
 *
 * Why this element and not the other section titles: the approved 30/48 scale
 * is scoped to `main section h2`, and the contact block lives in <footer>, so
 * it was never in scope to begin with. It is sized here to the intent already
 * authored for it in woocommerce.css (clamp(22px, 5.6vw, 32px)) rather than to
 * the main-section scale — it is a footer CTA, not a page section, and 48px
 * would shout over the content above it. */
html body.cl-v2:not(.cl-x) footer .cl-contact__title:not(.cl-x) {
  font-family: Poppins, system-ui, sans-serif !important;
  font-size: clamp(22px, 5.6vw, 32px) !important;
  font-weight: 900 !important;
  letter-spacing: -0.03em !important;
  line-height: 1.12 !important;
  text-transform: none !important;
  color: var(--cl-ink) !important;
}

/* 99 — PROMO CODE now lives under the order total, not above everything.
 *
 * Measured on the embedded checkout at 390 before the change:
 *
 *     top=  97   form.checkout_coupon        <- an empty box, first thing on the page
 *     top= 190   #order_review               order:-1
 *     top= 577   SHIP TO
 *
 * form.checkout is a flex column on mobile with #order_review pulled to -1 and
 * .cl-ck__main pushed to 1 (woocommerce.css, "what you bought goes first").
 * The promo wrapper is a sibling of both and takes the gap between them, so it
 * lands under the total and above SHIP TO without touching either rule.
 *
 * It is deliberately quieter than the summary above it: this is for the few
 * people who already have a code, not an invitation to go looking for one. */
html body.cl-v2:not(.cl-x) .cl-ck__promo:not(.cl-x) {
  order: 0 !important;
  margin: 0 0 20px !important;
}
html body.cl-v2:not(.cl-x) .cl-ck__promo form.checkout_coupon:not(.cl-x) {
  margin: 0 !important;
  padding: 14px 16px !important;
  border: 1px solid #E5E1F2 !important;
  border-radius: 14px !important;
  background: #F7F8FA !important;
}

@media (min-width: 900px) {
  /* Desktop keeps the summary in its own column; the promo follows it there
     rather than stranding itself across the form. */
  html body.cl-v2:not(.cl-x) .cl-ck__promo:not(.cl-x) {
    grid-column: 2 !important;
  }
}

/* 100 — sold-out doses read as sold out, and the waitlist takes the slot.
 *
 * Measured on /product/r3ta/ once 10MG hit zero: the pill looked identical to
 * an in-stock one and Add to cart stayed live, so the only way to learn a dose
 * was gone was to tap buy and be refused.
 *
 * The pill stays TAPPABLE deliberately — tapping is what reveals the email
 * capture. It is dimmed and struck through, not disabled, because a disabled
 * control would hide the one useful thing left on the page. */
html body.cl-v2:not(.cl-x) .cl-pill[data-cl-soldout]:not(.cl-x) {
  opacity: 0.55 !important;
  text-decoration: line-through !important;
  text-decoration-thickness: 1.5px !important;
  border-color: var(--cl-line-2, #000000) !important;
}
html body.cl-v2:not(.cl-x) .cl-pill[data-cl-soldout].is-selected:not(.cl-x) {
  opacity: 1 !important;   /* the one you picked must stay legible */
}

html body.cl-v2:not(.cl-x) .cl-atc--single:not(.cl-x) {
  display: block !important;
  margin: 14px 0 0 !important;
  padding: 16px !important;
  border: 1.5px solid var(--cl-line-2, #000000) !important;
  border-radius: 14px !important;
  background: #F7F8FA !important;
}
html body.cl-v2:not(.cl-x) .cl-atc--single[hidden]:not(.cl-x) { display: none !important; }
html body.cl-v2:not(.cl-x) .cl-atc--single .cl-wait__why:not(.cl-x) {
  margin: 0 0 10px !important;
  font-weight: 700 !important;
  color: var(--cl-ink, #171923) !important;
}
html body.cl-v2:not(.cl-x) .cl-atc--single .cl-wait__open:not(.cl-x) {
  min-height: 48px !important;
  width: 100% !important;
  font-weight: 600 !important;
}
html body.cl-v2:not(.cl-x) .cl-atc--single .cl-wait__form:not(.cl-x) {
  display: flex !important; gap: 8px !important; margin-top: 10px !important;
}
html body.cl-v2:not(.cl-x) .cl-atc--single .cl-wait__email:not(.cl-x) {
  flex: 1 1 auto !important; min-height: 48px !important; min-width: 0 !important;
}
html body.cl-v2:not(.cl-x) .cl-atc--single .cl-wait__go:not(.cl-x) {
  min-height: 48px !important; flex: 0 0 auto !important;
}

/* ============================================================
 * 101 — the four things Noah has asked for repeatedly. MEASURED, then fixed.
 *
 *   hero     .cl-hero2__title x[400..1040] text-align:left, but the buttons
 *            centre at 720 and the chips centre at 720. A left-aligned headline
 *            inside a centred composition reads as broken alignment, which is
 *            exactly what it looked like.
 *   vial     panel 450px, image 328px, gapTop 4px, gapBot 118px — the vial was
 *            pinned to the top of the panel with a fifth of the card empty
 *            underneath it. That is the "floating".
 *   uniform  starter-pack panel 425px vs product panel 450px, so at 390 the
 *            cards came out 392px and 423px tall. Two card heights in one grid.
 *   type     name 16px, price 25px. The compound name — the thing people scan
 *            for — was SMALLER than its own price.
 * ============================================================ */

/* ---- hero: centre the headline with everything else around it ---- */
html body.cl-v2:not(.cl-x) .cl-hero2__title:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-hero2 h1:not(.cl-x) {
  text-align: center !important;
  margin-left: auto !important;
  margin-right: auto !important;
}

/* ---- cards: size the IMAGE, never the link.
 *
 * First attempt put aspect-ratio + overflow:hidden on
 * a.woocommerce-LoopProduct-link, on the assumption it was the image panel.
 * It is not: WooCommerce puts the img, the h2 AND the price inside that one
 * anchor, so the clip cut the name and price off — the sweep caught 43 CLIPPED
 * findings, up to 55px past the box, on exactly the cards this was meant to
 * improve. Shape the img itself and let the link flow. ---- */
html body.cl-v2:not(.cl-x) ul.products li.product a.woocommerce-LoopProduct-link:not(.cl-x) {
  display: block !important;
  overflow: visible !important;   /* undo the clip */
  aspect-ratio: auto !important;
}

/* ---- ONE image box for every card, whatever shape the file is.
 *
 * Measured on /shop/ — this is the whole reason the grid never looked uniform:
 *
 *   starter packs   source 1200x1200 (square)    image starts at y=-9  (overflows the top)
 *   TIRZ            source  171x247  (portrait)  image starts at y=+5
 *   R3TA            source  340x490  (portrait)  image starts at y=+5
 *
 * object-fit:contain honours the FILE's aspect ratio, so a square pack photo and
 * a tall thin vial photo sit at different heights and leave different gaps, and
 * the Add to cart buttons ended up at 277px, 333px and 344px down three cards in
 * the same row. Nothing was wrong with the CSS; the artwork is different shapes.
 *
 * Fixing it in CSS instead of touching the images (those are approved and not to
 * be altered): give every image the same square box and centre inside it, so the
 * shape of the file no longer decides the layout.
 * ---- */
html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link img:not(.cl-x),
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-cardimg img:not(.cl-x) {
  display: block !important;
  width: 100% !important;
  aspect-ratio: 1 / 1 !important;
  height: auto !important;
  max-height: none !important;
  object-fit: contain !important;
  object-position: center center !important;
  margin: 0 auto 12px !important;
  padding: 8px !important;
}

/* ---- every card the same height, every button on the same line.
 * The grid gives equal row heights; the card has to USE that height and push
 * its button to the bottom, or a shorter name lifts the button up. ---- */
html body.cl-v2:not(.cl-x) ul.products li.product.product:not(.cl-x) {
  display: flex !important;
  flex-direction: column !important;
  height: 100% !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc:not(.cl-x) {
  margin-top: auto !important;   /* pins the button to the foot of the card */
}

/* ---- the name is the headline of the card, so it outranks the price ---- */
html body.cl-v2:not(.cl-x) ul.products li.product .woocommerce-loop-product__title:not(.cl-x),
html body.cl-v2:not(.cl-x) ul.products li.product h2:not(.cl-x) {
  font-size: 19px !important;
  line-height: 1.18 !important;
  letter-spacing: 0.04em !important;
  margin: 0 0 6px !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product .price:not(.cl-x),
html body.cl-v2:not(.cl-x) ul.products li.product span.price:not(.cl-x) {
  font-size: 20px !important;
  line-height: 1.15 !important;
  margin: 0 0 10px !important;
}
@media (min-width: 900px) {
  html body.cl-v2:not(.cl-x) ul.products li.product .woocommerce-loop-product__title:not(.cl-x),
  html body.cl-v2:not(.cl-x) ul.products li.product h2:not(.cl-x) { font-size: 21px !important; }
  html body.cl-v2:not(.cl-x) ul.products li.product .price:not(.cl-x),
  html body.cl-v2:not(.cl-x) ul.products li.product span.price:not(.cl-x) { font-size: 22px !important; }
}

/* ---- ONE line colour for the whole site. It was #E2E5EA — a grey heavy
 *      enough to read as a box round everything. #E2E5EA is the border from
 *      Noah's own design brief. ---- */
html body.cl-v2:not(.cl-x) ul.products li.product:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-card:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-panel:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-ck__row:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-ck__aside:not(.cl-x),
html body.cl-v2:not(.cl-x) form.checkout_coupon:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-atc--single:not(.cl-x) {
  border-color: #E5E1F2 !important;
  border-width: 2px !important;
}

/* ============================================================
 * 102 — CHECKOUT: one border, one radius, one label.
 *
 * Measured on the embedded checkout at 390 and 1440 (sc/ckscan.js). The form
 * was not badly designed so much as inconsistent — the eye reads that as cheap:
 *
 *   field borders   rgb(199,199,203) x16   rgb(194,194,201) x4   rgb(168,168,178) x1
 *   field radius    12px x16               0px x4                4px x1
 *   labels          14/800 x18   16/700 x6   14/600 x5   12.5/800 x1   14/500 x1
 *
 * Three greys nobody can tell apart, three corner radii on controls sitting
 * next to each other, and five label treatments on one form. Field HEIGHT was
 * already right (48px on 20 of 21 controls), which is why it looked almost
 * right and still felt wrong.
 *
 * One value each, matching the panels around them (#E2E5EA, 12px) and the
 * design brief's 48px control height.
 * ============================================================ */
html body.cl-v2:not(.cl-x).cl-embed form.checkout input[type="text"]:not(.cl-x),
html body.cl-v2:not(.cl-x).cl-embed form.checkout input[type="email"]:not(.cl-x),
html body.cl-v2:not(.cl-x).cl-embed form.checkout input[type="tel"]:not(.cl-x),
html body.cl-v2:not(.cl-x).cl-embed form.checkout input[type="number"]:not(.cl-x),
html body.cl-v2:not(.cl-x).cl-embed form.checkout select:not(.cl-x),
html body.cl-v2:not(.cl-x).cl-embed form.checkout textarea:not(.cl-x),
html body.cl-v2:not(.cl-x).cl-embed form.checkout .select2-selection:not(.cl-x) {
  border: 1px solid #E5E1F2 !important;
  border-radius: 12px !important;
  background: #FFFFFF !important;
  font-size: 16px !important;   /* 16 or iOS zooms the page on focus */
  color: var(--cl-ink, #171923) !important;
}
html body.cl-v2:not(.cl-x).cl-embed form.checkout input:not(.cl-x):focus,
html body.cl-v2:not(.cl-x).cl-embed form.checkout select:not(.cl-x):focus,
html body.cl-v2:not(.cl-x).cl-embed form.checkout textarea:not(.cl-x):focus {
  border-color: #7C3AED !important;
  outline: 1px solid #E5E1F2 !important;
  outline-offset: 0 !important;
}

/* ONE label treatment. Five was the single biggest contributor to the form
 * looking unfinished — the same question asked in five different voices. */
html body.cl-v2:not(.cl-x).cl-embed form.checkout label:not(.cl-x),
html body.cl-v2:not(.cl-x).cl-embed form.checkout p.form-row > label:not(.cl-x) {
  font-size: 14px !important;
  font-weight: 700 !important;
  letter-spacing: normal !important;
  text-transform: none !important;
  color: var(--cl-ink, #171923) !important;
  margin: 0 0 6px !important;
  display: block !important;
}
/* checkbox and radio labels sit beside their control, not above it */
html body.cl-v2:not(.cl-x).cl-embed form.checkout .woocommerce-form__label-for-checkbox:not(.cl-x),
html body.cl-v2:not(.cl-x).cl-embed form.checkout label.checkbox:not(.cl-x) {
  display: flex !important;
  align-items: flex-start !important;
  gap: 10px !important;
  font-weight: 600 !important;
  margin: 0 !important;
}

/* 102b — the last three strays, named by sc/stray.js:
 *
 *   input#coupon_code      border rgb(168,168,178)  radius 4px   <- lives in
 *                          form.checkout_coupon, NOT form.checkout, so every
 *                          selector scoped to the checkout form missed it
 *   textarea#order_comments border rgb(199,199,203)              <- an id beats
 *                          the element selectors above it
 *   label "Promo code"     12.5px/800                            <- the only
 *                          label on the page not at 14/700
 *
 * An ID is the cheapest way to be certain here, and these are three specific
 * controls rather than a pattern, so naming them is honest rather than lazy. */
html body.cl-v2:not(.cl-x) #coupon_code:not(.cl-x),
html body.cl-v2:not(.cl-x) #order_comments:not(.cl-x) {
  border: 1px solid #E5E1F2 !important;
  border-radius: 12px !important;
  background: #FFFFFF !important;
  font-size: 16px !important;
}
html body.cl-v2:not(.cl-x) .cl-coupon__label:not(.cl-x),
html body.cl-v2:not(.cl-x) label[for="coupon_code"]:not(.cl-x) {
  font-size: 14px !important;
  font-weight: 700 !important;
  letter-spacing: normal !important;
  text-transform: none !important;
}

/* 103 — two things the checkout crop showed that the numbers did not.
 *
 * 1. The "5% OFF" chip computed to background #78350F — a muddy brown. Its own
 *    rule in woocommerce.css says #2E7D32 green, but the amber .cl-zbar block
 *    above paints everything inside it, and the chip is inside it. A discount
 *    chip the colour of dried mud next to a lock icon reads as a warning, not
 *    a saving. Brand purple, white on it = 5.70:1, passes AA.
 *
 * 2. "Use a different billing address" — the checkbox is a SIBLING of its label
 *    (inside=false), and the label is a 44px-tall block with its text at the
 *    top, so the tick sat low-left of the words instead of beside them. Make
 *    the row a flex line and centre both on it.
 */
/* :not(.cl-y) takes this to (0,5,2), matching the .cl-paynotice__save rule that
 * was winning with the brown; equal specificity, and this block is later in the
 * file, so order decides it. Found with an in-page rule scan (sc/badge.js)
 * rather than another guess. */
html body.cl-v2:not(.cl-x) .cl-zbadge:not(.cl-x):not(.cl-y) {
  background: #7C3AED !important;
  background-image: none !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
  border: 0 !important;
}

html body.cl-v2:not(.cl-x) .cl-billing-toggle:not(.cl-x),
html body.cl-v2:not(.cl-x) p:has(> #cl-billing-different):not(.cl-x) {
  display: flex !important;
  align-items: center !important;
  gap: 12px !important;
}
html body.cl-v2:not(.cl-x) label[for="cl-billing-different"]:not(.cl-x) {
  display: flex !important;
  align-items: center !important;
  min-height: 24px !important;
  margin: 0 !important;
  padding: 0 !important;
  line-height: 1.3 !important;
}
html body.cl-v2:not(.cl-x) #cl-billing-different:not(.cl-x) {
  flex: 0 0 auto !important;
  margin: 0 !important;
}

/* ============================================================
 * 104 — ONE LINE COLOUR FOR THE SITE.
 *
 * Audited all borders on 8 representative pages at 390 (sc/lines2.js). The
 * site was drawing TWENTY-FOUR distinct line treatments:
 *
 *   rgb(194,194,201) 1px      591 uses   all 8 pages   <- #C2C2C9, the worst
 *   rgba(196,181,253,.85)     146 uses   all 8
 *   rgb(167,139,250)          142 uses   all 8
 *   rgba(109,40,217,.18)       89 uses   all 8
 *   rgba(124,58,237,.40)       56 uses
 *   rgba(196,181,253,.50)      34 uses
 *   rgba(124,58,237,.25)       20 uses
 *   rgba(124,58,237,.55)       18 uses
 *   rgba(124,58,237,.35)       16 uses
 *   rgb(199,199,203)            8 uses
 *
 * Three near-identical greys and EIGHT purple opacities. Nobody can tell 0.25
 * from 0.35 from 0.40 — it does not read as variety, it reads as nobody
 * deciding. That is what Noah has been pointing at for weeks.
 *
 * The greys were rewritten at source above (44 border declarations, 23 bare
 * hex uses). This block collapses the purple family to TWO deliberate values:
 *
 *   --cl-line      #E2E5EA              structure: cards, panels, dividers
 *   --cl-line-br   rgba(124,58,237,.35) brand: things you can interact with
 *
 * Deliberately NOT touched: the amber Zelle bar (#FCD34D), the white top-bar
 * hairline, and the call tab's dark edge. Those are signals, not structure.
 * ============================================================ */
html body.cl-v2:not(.cl-x) {
  --cl-line: #E2E5EA;
  --cl-line-br: rgba(124, 58, 237, 0.35);
}

/* the mid-purple family -> one brand line */
html body.cl-v2:not(.cl-x) .cl-feat__sizes:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-bundle__btn:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-search:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-atc__opt:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-chip:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-contact__link:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-mobile__panel:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-cardsizes:not(.cl-x),
/* second pass: the audit after the first deploy still showed five purples.
 *   rgba(196,181,253,.85) x144  .cl-feat__btn
 *   rgb(167,139,250)      x142  .cl-feat__sizes
 *   rgba(109,40,217,.18)  x49   .search-field, .cl-cardimg__img
 *   rgba(196,181,253,.50) x34   bare <button>
 * All of them are the same idea — "this is ours, and you can touch it" — drawn
 * four different ways. */
html body.cl-v2:not(.cl-x) .cl-feat__btn:not(.cl-x),
html body.cl-v2:not(.cl-x) .search-field:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-cardimg__img:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-picks__panel:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-feat__card:not(.cl-x),
html body.cl-v2:not(.cl-x) .cl-save__card:not(.cl-x) {
  border-color: var(--cl-line-br) !important;
  border-width: 2px !important;
}


/* ---- 107. Vial breathing room in the product gallery ------------------
   Noah, 2026-10-08: "the cropping sucks. bring the vial down a smidge so it's
   not going out of the product card."

   Nothing was actually being clipped — measured object-fit:contain with
   overflow 0/0 at 390, 768 and 1440. The artwork just sits flush against the
   top edge of its box, which reads as a crop. So this is pure spacing: the
   image keeps its full height and gets padding above it, which `contain`
   then fits into, dropping the vial clear of the edge.

   The ARTWORK IS NOT TOUCHED — Noah's standing rule. This is the frame only. */
html body.cl-v2 .woocommerce-product-gallery__image,
html body.cl-v2 .woocommerce-product-gallery .wp-post-image {
  padding-top: 22px !important;
  box-sizing: border-box !important;
}
html body.cl-v2 .woocommerce-product-gallery__image img,
html body.cl-v2 .woocommerce-product-gallery img {
  object-position: center bottom !important;   /* sit it down, not centred */
}

/* ---- 108. The over-cap phone notice: readable, and not green --------
   Noah, 2026-10-08: "the green is bad. and the contrast of text is so bad."

   He was right, and it measured badly. The v2 palette gave this panel a
   gradient running from rgba(76,29,149,.92) at the top to light grey at the
   bottom, with #27272A text over all of it. Against the purple end that is
   2.61:1 — well under the 4.5:1 a body-copy minimum needs, and the worst
   contrast anywhere in the checkout.

   Now a flat lavender surface with ink on it (17.1:1) and the brand purple
   button with white (7.1:1). No gradient, so the contrast cannot vary by
   where the text happens to sit. */
html body.cl-v2 .cl-capnote {
  background-image: none !important;
  background: var(--cl-lavender-pale, #F5F3FF) !important;
  border: 2px solid var(--cl-purple, #6D28D9) !important;
  border-radius: 12px !important;
}
html body.cl-v2 .cl-capnote,
html body.cl-v2 .cl-capnote span,
html body.cl-v2 .cl-capnote strong {
  color: #111118 !important;
}
html body.cl-v2 .cl-capnote__call {
  background: linear-gradient(180deg, #8B5CF6, #6D28D9) !important;
  color: #FFFFFF !important;
  border-radius: 10px !important;
}

/* ---- 109. No gradients on buttons -----------------------------------
   Noah, 2026-10-08: "i hate the gradient."

   First attempt lost. The generated palette sets the gradient with
   `html body.cl-v2:not(.cl-x) .cl-btn:not(.cl-btn--secondary):not(.cl-btn--ghost)`
   — specificity (0,5,2) — and !important ties break on specificity, so an
   override at (0,2,2) never stood a chance however late it loaded.

   Matching that selector and adding two more :not()s takes it to (0,7,2).
   Note :not() contributes the specificity of its ARGUMENT, so each one adds a
   class's worth; they do not sum into something cleverer.

   The source gradient lives in woocommerce.css and is shared with the CURRENT
   dark theme, which customers are on right now — so it is not touched. This is
   v2-only, as it must be. Flat #6D28D9: the brand primary, 7.10:1 on white. */
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-btn:not(.cl-btn--secondary):not(.cl-btn--ghost):not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-feat__btn:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-hero2__shop:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-drawer__cta:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-pagenav__shop:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-popback:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-capnote__call:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-chip.is-active:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) ul.products li.product.product .cl-atc__btn:not([disabled]):not([aria-disabled="true"]),
html body.cl-v2:not(.cl-x):not(.cl-y) .woocommerce a.button.alt:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) .woocommerce button.button.alt:not(.cl-z) {
  background-image: none !important;
  background-color: #6D28D9 !important;
  color: #FFFFFF !important;
}

/* The call button spans the panel, label centred. */
html body.cl-v2:not(.cl-x) .cl-capnote__call {
  display: block !important;
  width: 100% !important;
  text-align: center !important;
}

/* ---- 110. The last of the hard gradients ----------------------------
   Block 109 caught the buttons. These three were still running a 135deg
   purple ramp: the announcement bar, the "SAVE" badge on feature cards, and
   the search submit (which carries no class of its own, so it is reached
   through its parent form).

   The soft RADIAL washes behind the hero and the feature art are deliberately
   LEFT: they are ambient lighting at 0.12 alpha, not a gradient anyone reads
   as one, and flattening them would give the hero a hard edge. Flagged to
   Noah rather than decided silently. */
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-topbar:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-feat__tag--save:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-search button:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) form[role="search"] button:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-searchbar button:not(.cl-z) {
  background-image: none !important;
  background-color: #6D28D9 !important;
  color: #FFFFFF !important;
}

/* The last two linear ramps: the "how it works" step numbers and the picks
   eyebrow. Both verified background-clip:border-box, NOT text — the generator
   warns that flattening gradient-FILLED text turns it into a solid bar with
   invisible letters, so that was checked before touching them. */
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-intent__num:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-picks__eyebrow:not(.cl-z) {
  background-image: none !important;
  background-color: #6D28D9 !important;
  color: #FFFFFF !important;
}

/* Block 109 excluded .cl-btn--secondary and --ghost, and one variant with a
   gradient fell through that gap. Any .cl-btn that still carries a linear ramp
   gets flattened; the outline variants have no background-image to lose. */
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-btn:not(.cl-z):not(.cl-w) {
  background-image: none !important;
}
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-btn:not(.cl-btn--secondary):not(.cl-btn--ghost):not(.cl-z):not(.cl-w) {
  background-color: #6D28D9 !important;
  color: #FFFFFF !important;
}

/* Add to cart on product cards — the stubborn one.
   The palette sets it with
   `html body.cl-v2:not(.cl-x) .woocommerce ul.products li.product .cl-atc__btn`,
   which is (0,6,4). My earlier (0,6,2) tied on classes and lost on element
   count, which is the tie-break after class count. Same shape plus one more
   :not() takes it to (0,8,4). */
html body.cl-v2:not(.cl-x):not(.cl-y) .woocommerce ul.products li.product .cl-atc__btn:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) .woocommerce ul.products li.product button.cl-atc__btn:not(.cl-z) {
  background-image: none !important;
  background-color: #6D28D9 !important;
  color: #FFFFFF !important;
}

/* ---- 111. The hero background is the RIBBON artwork ------------------
   Noah, 2026-10-08: "you didn't add the moving background."

   The moving layer was already here — a 120s spiral on .cl-hero2::before —
   but it was painting the hexagon plate (corelabs-bg-v2-*.webp), not the
   lavender ribbon artwork he sent. So the motion was right and the image was
   wrong, which is why it read as "not added".

   One file serves every breakpoint: ribbon.webp is 3344x1880, which clears the
   largest requirement in the comment above (3840 was for the hex plate at
   1.5x scale; the ribbon is wide enough and only 84 KB, so three sizes are not
   worth the bytes). The spiral, its 1.5x oversize and the 120s timing are all
   left exactly as tuned. */
html body.cl-v2 .cl-hero2::before,
html body.cl-v2 .cl-hero2::before {
  background-image: url("/wp-content/themes/corelabs-theme/assets/ribbon.webp") !important;
  background-size: cover !important;
  background-position: center !important;
}
@media (min-width: 600px), (min-resolution: 1.5dppx) {
  html body.cl-v2 .cl-hero2::before {
    background-image: url("/wp-content/themes/corelabs-theme/assets/ribbon.webp") !important;
  }
}
@media (min-width: 1200px), (min-resolution: 1.5dppx) and (min-width: 820px) {
  html body.cl-v2 .cl-hero2::before {
    background-image: url("/wp-content/themes/corelabs-theme/assets/ribbon.webp") !important;
  }
}

/* ---- 112. The RIBBON goes on the layer that actually moves -----------
   Block 111 put the ribbon on .cl-hero2::before. Measured afterwards: that
   element computes `animation: none` — the moving layer was replaced at some
   point by a .cl-spiral element carrying TWO pseudo-elements half a cycle
   apart. So the ribbon was painted onto the one static layer in the hero,
   which is exactly why it still looked like nothing had been added.

   This puts it where the motion is. Specificity matches the existing rule
   (0,4,3) with one extra :not() to win at (0,5,3).

   background-size is COVER here, not the contain the hex plate used: the plate
   was near-square, the ribbon is 3344x1880, and contain inside a 118vmax
   square would letterbox it with empty bands that sweep through frame as the
   layer turns. */
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-hero2 .cl-spiral::before,
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-hero2 .cl-spiral::after {
  background-image: url("/wp-content/themes/corelabs-theme/assets/ribbon.webp") !important;
  background-size: cover !important;
}
@media (min-width: 600px), (min-resolution: 1.5dppx) {
  html body.cl-v2:not(.cl-x):not(.cl-y) .cl-hero2 .cl-spiral::before,
  html body.cl-v2:not(.cl-x):not(.cl-y) .cl-hero2 .cl-spiral::after {
    background-image: url("/wp-content/themes/corelabs-theme/assets/ribbon.webp") !important;
  }
}
@media (min-width: 1200px), (min-resolution: 1.5dppx) and (min-width: 820px) {
  html body.cl-v2:not(.cl-x):not(.cl-y) .cl-hero2 .cl-spiral::before,
  html body.cl-v2:not(.cl-x):not(.cl-y) .cl-hero2 .cl-spiral::after {
    background-image: url("/wp-content/themes/corelabs-theme/assets/ribbon.webp") !important;
  }
}

/* ---- 113. v2 checkout fields, to spec --------------------------------
   The measurement spec (2px boundary, 8px radius) landed in woocommerce.css,
   which the DARK theme uses. In v2 it was overridden by
   `html body.cl-v2:not(.cl-x).cl-embed input.input-text` at (0,4,3), setting
   1px #E2E5EA — a boundary measuring about 1.3:1 on white, well under the 3:1
   an essential control boundary needs.

   #71717A is the same ink the approved v2 checkout prototype used and measures
   4.84:1 on white. Selectors here carry the body class, .cl-embed and two
   extra :not()s to clear (0,4,3) in both the embedded and standalone checkout. */
html body.cl-v2:not(.cl-x):not(.cl-y).cl-embed input.input-text:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y).cl-embed textarea:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y).cl-embed form .form-row select:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) form.checkout input.input-text:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) form.checkout textarea:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) form.checkout .form-row select:not(.cl-z) {
  border: 1px solid #E5E1F2 !important;
  border-radius: 8px !important;
  min-height: 48px !important;
  padding: 12px 16px !important;
  font-size: 16px !important;
}
/* Width never changes between states, so nothing shifts; only the colour moves. */
html body.cl-v2:not(.cl-x):not(.cl-y).cl-embed input.input-text:focus:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) form.checkout input.input-text:focus:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) form.checkout textarea:focus:not(.cl-z) {
  border-width: 2px !important;
  border-color: #6D28D9 !important;
  outline: 3px solid #A78BFA !important;
  outline-offset: 2px !important;
}

/* The three that block 113 could not reach:
     #coupon_code and #order_comments are set by ID rules, and an ID beats any
       number of classes — so these must be ID selectors too.
     .select2-selection is a SPAN standing in for the native <select>, so no
       input/select selector was ever going to match it. */
html body.cl-v2:not(.cl-x) #coupon_code:not(.cl-z),
html body.cl-v2:not(.cl-x) #order_comments:not(.cl-z),
html body.cl-v2:not(.cl-x) .select2-container--default .select2-selection--single:not(.cl-z),
html body.cl-v2:not(.cl-x).cl-embed .select2-container--default .select2-selection--single:not(.cl-z) {
  border: 1px solid #E5E1F2 !important;
  border-radius: 8px !important;
  min-height: 48px !important;
}
html body.cl-v2:not(.cl-x) .select2-container--default .select2-selection--single:not(.cl-z) {
  height: 48px !important;
  display: flex !important;
  align-items: center !important;
  padding: 0 16px !important;
}
html body.cl-v2:not(.cl-x) #order_comments:not(.cl-z) { min-height: 96px !important; }

/* Last two. The Select2 control lives in `.selection`, NOT inside a
   `.select2-container--default` — requiring that ancestor matched nothing.
   And #order_comments is set by a longer ID rule, so this one carries the id
   plus the same element chain to outrank it. */
html body.cl-v2:not(.cl-x):not(.cl-y) .selection .select2-selection--single:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) span.select2-selection--single:not(.cl-z) {
  border: 1px solid #E5E1F2 !important;
  border-radius: 8px !important;
  height: 48px !important;
  min-height: 48px !important;
  display: flex !important;
  align-items: center !important;
  padding: 0 16px !important;
}
html body.cl-v2:not(.cl-x):not(.cl-y) form.checkout .form-row textarea#order_comments:not(.cl-z) {
  border: 1px solid #E5E1F2 !important;
  border-radius: 8px !important;
  min-height: 96px !important;
  padding: 12px 16px !important;
}

/* ---- 114. Win-back popup: contrast, and no gradient ------------------
   SWEEP flagged this on every product page: white text on #9263f4 at
   3.95:1, under the 4.5:1 a body-copy minimum needs. #9263f4 is not a colour
   anyone chose — it is the MIDPOINT of the gradient
   linear-gradient(180deg, #a78bfa, #7c3aed), which is why a contrast check
   against either end would have passed and the rendered button still failed.

   Flat #6D28D9 instead: 7.10:1 with white, the same ink every other button in
   v2 now uses, and no ramp for the contrast to vary across. */
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-wb__yes:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-wb__badge:not(.cl-z) {
  background-image: none !important;
  background-color: #6D28D9 !important;
  color: #FFFFFF !important;
}

/* ---- 115. The cap panel gradient, properly this time -----------------
   Block 108 set background-color but LOST the background-image to the palette
   rule `html body.cl-v2:not(.cl-x) .cl-capnote` at (0,3,2) — mine was (0,2,2).
   A background-image paints over a background-color, so the result was dark
   ink back on a dark purple ramp: the 2.61:1 Noah reported, still live.

   Verified wrong by reading the RENDERED element, not by recomputing a
   contrast ratio from the colours I intended. Checking the arithmetic of a
   rule that never applied proves nothing. */
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-capnote:not(.cl-z) {
  background-image: none !important;
  background-color: #F5F3FF !important;
  border: 2px solid #6D28D9 !important;
  border-radius: 12px !important;
}
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-capnote:not(.cl-z),
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-capnote:not(.cl-z) span,
html body.cl-v2:not(.cl-x):not(.cl-y) .cl-capnote:not(.cl-z) strong {
  color: #111118 !important;
}

/* 116 — REMOVED, superseded by 136.
 *
 * This reserved a blank 48px ::after under every in-stock button so a
 * sold-out neighbour's waitlist link could not push the buttons out of line.
 * Block 136 removed the reason for it: both states now carry exactly one
 * button and one status pill, so the rows align with nothing reserved.
 *
 * It is deleted, not overridden, and it had to be. Its `content: ''` held the
 * pseudo-element EMPTY at 48px while 136 tried to put "In stock" in it at
 * 34px, and its selector carried two more classes, so it won — which is why
 * the green pill rendered as an empty capsule with no text in it. Three
 * separate blocks were fighting over this one pseudo-element today; 136 is
 * the only one left.
 */

/* 116b — shift the vial down inside its panel.
 *
 * Noah, twice: "bring hte vial down a smidge so its not going out of the
 * product card" and "fix the cropping... they flow out of the boxes. Shift
 * the files down."
 *
 * Block 107 tried this and never applied. It was written against
 * .cl-cardimg__img, which is the HOMEPAGE card's image class; a shop-loop
 * image is .attachment-woocommerce_thumbnail inside span.cl-cardimg, so the
 * selector matched nothing and the rule sat in the file looking correct.
 * Verified in the live page: object-position was still 50% 50%, the value
 * from block 9229, not the "center bottom" block 107 claimed to set.
 *
 * Nothing actually overflows — every image measured 5-22px INSIDE its box,
 * which is also overflow:hidden. What reads as "flowing out" is the vial
 * sitting high and crowding the divider under the panel. So it is sat on the
 * floor of the box and given headroom above, which is what he asked for.
 *
 * Targets the real class, and outweighs 9229 (0,7,5) at (0,9,6).
 */
html body.cl-v2:not(.cl-x):not(.cl-y) ul.products li.product.product
  span.cl-cardimg:not(.cl-z) img:not(.cl-x) {
  object-fit: contain !important;
  object-position: center bottom !important;
  padding-top: 26px !important;
  padding-bottom: 10px !important;
}

/* ============================================================ 117
 * One pass over everything Noah called out on 2026-10-09, each fixed
 * from a measurement rather than a guess. Numbers in the comments are
 * getBoundingClientRect values read off the live page at 1308px.
 * ========================================================================= */

/* 117a — THE TRUST BAR WAS OVERLAPPING ITSELF.
 *
 * "RESEARCH USE ONLY THIRD-PARTY TESTEDFAST U.S. FULFILLMENCOAS AVAILABLE"
 *
 * Measured: the <ul> is a 4-column grid of 146.5px columns, and every item
 * needs more than that — 198, 205, 220 and 167px. Each one overflows its own
 * column by 20-73px, and because the text is white-space:nowrap it spills
 * sideways over its neighbour instead of wrapping. A fixed column width for
 * text of unknown length is the bug.
 *
 * Flex with wrap sizes each item to its content and moves the row down when
 * four will not fit, which is also what makes it work on a phone.
 */
html body.cl-v2:not(.cl-x) ul.cl-hero2__trust:not(.cl-z) {
  display: flex !important;
  flex-wrap: wrap !important;
  justify-content: center !important;
  align-items: center !important;
  column-gap: 30px !important;
  row-gap: 14px !important;
  grid-template-columns: none !important;
  width: 100% !important;
  max-width: none !important;
}
html body.cl-v2:not(.cl-x) ul.cl-hero2__trust:not(.cl-z) > li.cl-hero2__trustItem {
  flex: 0 0 auto !important;
  width: auto !important;
  min-width: 0 !important;
  max-width: none !important;
  overflow: visible !important;
  display: inline-flex !important;
  align-items: center !important;
  gap: 8px !important;
}

/* 117b — THE TWO HERO BUTTONS AGREED ON NOTHING.
 *
 * Measured, side by side:
 *            width   radius   border
 *   Shop      320px   16px     1px rgba(196,181,253,.6)   <- translucent wash
 *   How       200px  999px     2px #6D28D9
 *
 * Different width, different corner, different line weight and a border
 * colour that is barely a colour. Stacked on a narrow screen the two
 * different widths are what reads as "not aligned".
 *
 * Both are now the same width and the same shape, and both carry the 2px
 * control border from the line system in their own brand colour — the filled
 * one borders itself so its geometry matches the outlined one exactly.
 */
html body.cl-v2:not(.cl-x) .cl-hero2__cta:not(.cl-z) {
  display: flex !important;
  flex-wrap: wrap !important;
  justify-content: center !important;
  align-items: center !important;
  gap: 14px !important;
}
html body.cl-v2:not(.cl-x) .cl-hero2__cta:not(.cl-z) > a.cl-hero2__shop,
html body.cl-v2:not(.cl-x) .cl-hero2__cta:not(.cl-z) > a.cl-hero2__aside {
  flex: 0 0 auto !important;
  width: 260px !important;
  min-width: 260px !important;
  height: 60px !important;
  border-radius: 999px !important;
  border-width: 2px !important;
  border-style: solid !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  gap: 10px !important;
  text-align: center !important;
}
html body.cl-v2:not(.cl-x) .cl-hero2__cta:not(.cl-z) > a.cl-hero2__shop {
  border-color: #6D28D9 !important;   /* was a 1px translucent lavender */
}
html body.cl-v2:not(.cl-x) .cl-hero2__cta:not(.cl-z) > a.cl-hero2__aside {
  border-color: #6D28D9 !important;
}

/* 117c — REVERTED 2026-10-09.
 *
 * This bottom-aligned the three hero vials so their name pills sat on one
 * baseline, and gave the pills a shared 124px min-width. It did what it said,
 * and Noah's verdict on seeing it was: "The titles of the hero products the
 * hero vials that are floating go back to what they were. I don't like what
 * you're doing with them. It looks stupid. They need to be mashed up. Just do
 * what you had on the original website."
 *
 * The stagger is the design. The vials float at different heights and their
 * labels ride with them; "measured and aligned" is wrong for this component,
 * whatever a gate says about it. Nothing replaces it — the original rules in
 * blocks 333/1105/1468/1772 were never removed and take over again.
 *
 * Do not re-align these. Asked for once, removed once.
 */

/* 117d — THE SECTION EYEBROWS WERE STRANDED.
 *
 * "quality and documentation is fucked. i cant even see it and its off to
 * the side", and the same on "THE FULL CATALOG".
 *
 * Measured: .cl-section__title carries margin-top: 91.2px, so the eyebrow
 * floats on its own with a void beneath it and reads as a stray line rather
 * than a label belonging to the heading under it. An eyebrow is a kicker —
 * it has to touch its title.
 */
html body.cl-v2:not(.cl-x) p.cl-eyebrow:not(.cl-z) {
  margin: 0 0 8px !important;
  font-size: 13px !important;
  letter-spacing: .14em !important;
  line-height: 1.3 !important;
}
html body.cl-v2:not(.cl-x) p.cl-eyebrow:not(.cl-z) + h2.cl-section__title {
  margin-top: 0 !important;       /* was 91.2px */
}

/* 117e — THE PRODUCT CARDS DRIFTED BY 10px.
 *
 * Measured across the 12 shop cards, the rows that are supposed to line up:
 *
 *   title   43.3px, or 48.8px when it wraps to two lines (the starter packs)
 *   price   28.3-28.8px, taller when it carries the "From" label
 *   sizes   31px, or ABSENT on the starter packs
 *
 * Three variable-height rows stacked above the button, so the buttons landed
 * on five different lines (1768, 1778, 2415, 2425, 3048). Every one of those
 * rows is now a fixed height, which is the only way a grid of cards with
 * different content can line up.
 *
 * The size row is reserved even when the product has no sizes, so a starter
 * pack occupies the same space as a vial with three strengths.
 */
html body.cl-v2:not(.cl-x) ul.products li.product.product h2.woocommerce-loop-product__title:not(.cl-z) {
  min-height: 49px !important;    /* 2 lines x 24.4px line-height */
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  text-align: center !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product > span.cl-cardsizes:not(.cl-z) {
  min-height: 31px !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product:not(:has(.cl-cardsizes)) .cl-atc:not(.cl-z)::before {
  content: '' !important;
  display: block !important;
  /* 35px, not 31px. The real .cl-cardsizes contributes its 31px height PLUS a
   * 12px margin-bottom = 43px. This placeholder lives inside .cl-atc, so it
   * gets the column's 8px row-gap instead: 35 + 8 = 43. Measured, not guessed
   * — at 31px the packs' buttons sat 4px low, which was half of the residual
   * 8px drift the gate was still reporting. */
  height: 35px !important;
  flex: 0 0 auto !important;
  pointer-events: none !important;
}

/* 117f — REMOVED, superseded by 136.
 *
 * This reserved 48px under an in-stock button and later filled it with an
 * "In stock" line. Block 136 replaced the whole arrangement: both states now
 * carry one button and one matching pill, so there is nothing to reserve.
 *
 * It had to go rather than be overridden — its selector carried the extra
 * `:has(.cl-atc--out)` and `:not(.cl-atc--out)` classes, so it kept beating
 * 136 and held the in-stock pill at 48px while the sold-out one sat at 34px.
 * That 14px is exactly how far apart the two buttons were landing.
 */

/* 117g — colour the lock.
 * Noah: "the lock needs to be clored". It rendered in the button's own grey.
 */
html body.cl-v2:not(.cl-x) .cl-lock:not(.cl-z),
html body.cl-v2:not(.cl-x) .cl-lock:not(.cl-z) svg,
html body.cl-v2:not(.cl-x) .cl-lock:not(.cl-z) path {
  color: #6D28D9 !important;
  stroke: #6D28D9 !important;
  fill: none !important;
}

/* 117h — MOBILE IS A DIFFERENT PRODUCT, NOT A NARROW DESKTOP.
 * Noah: "remeber mobile is going to be different to look better never forget
 * that." The desktop numbers above are wrong on a 390px screen, so the same
 * elements are re-measured for the phone: the CTAs go full width instead of
 * holding a 260px desktop width, the trust bar runs two-up, and the name
 * pills shrink to fit three across without touching.
 */
@media (max-width: 480px) {
  html body.cl-v2:not(.cl-x) .cl-hero2__cta:not(.cl-z) > a.cl-hero2__shop,
  html body.cl-v2:not(.cl-x) .cl-hero2__cta:not(.cl-z) > a.cl-hero2__aside {
    width: 100% !important;
    min-width: 0 !important;
    max-width: 320px !important;
  }
  html body.cl-v2:not(.cl-x) ul.cl-hero2__trust:not(.cl-z) {
    column-gap: 16px !important;
    row-gap: 12px !important;
  }
  /* The 117c pill rule that lived here was removed with 117c itself. Its
   * mobile half kept applying after the revert and was still setting the
   * pills' padding — the rest of 117h stands. */
}

/* 118 — the collapsed size panel must have no border. My own bug.
 *
 * Symptom: on the homepage and shop grids, cards WITH a size dropdown put
 * their button 12px higher than cards without one, so the row never lined up.
 * sc/UNIFORM.js called it "button varies by 12px across 4 cards in a row".
 *
 * Cause: block 117's line system generated
 *     .cl-atc__opts { border: 1px solid #E5E1F2 !important }
 * and `!important` beat the collapsed state's `border-width: 0` in
 * woocommerce.css:5806. A 2px top plus a 2px bottom border gave the hidden
 * panel a measured height of 3.9px where it should be 0, and the .cl-atc
 * column's 8px row-gap turned that into 11.9px — the whole drift, exactly.
 *
 * The comment at woocommerce.css:5804 still says "the element takes no
 * space". That was true when it was written and silently stopped being true
 * the moment every box on the site got a border.
 *
 * So the collapsed state wins again. Specificity (0,4,2) over the generated
 * rule's (0,3,2), both !important, which is how an !important tie is broken.
 * The panel keeps its black border when OPEN, which is what was wanted.
 */
html body.cl-v2:not(.cl-x) .cl-atc__opts[hidden] {
  border-width: 0 !important;
  max-height: 0 !important;
  /* -8px cancels the .cl-atc column's 8px row-gap.
   *
   * A flex gap is applied between every child regardless of its height, so
   * even at zero height the collapsed panel still pushed 8px of space below
   * the button. That gave "choose" cards 8px more below their button than
   * cards without a dropdown, and since .cl-atc is bottom-anchored the
   * buttons ended up on different lines — the last 8px the gate reported.
   *
   * display:none would also fix it and would kill the open/close animation
   * that woocommerce.css:5804 keeps display:block for. A negative margin
   * removes the gap and leaves the animation intact. */
  margin-top: -8px !important;
  padding-top: 0 !important;
  padding-bottom: 0 !important;
}

/* 119 — three lines of title on a phone, two on a desktop.
 *
 * The last thing sc/UNIFORM.js was reporting: "/ @390 price varies by 24px
 * across 2 cards in a row".
 *
 * Measured at 390 in the two-column grid: "TIRZ 10MG STARTER PACK" wraps to
 * THREE lines (72.1px) while "BAC WATER" takes two (48.3px). Block 117e
 * reserved 49px — two lines — which is correct at 1440 where the longest
 * title still fits in two, and one line short on a phone. The buttons stayed
 * aligned because .cl-atc is bottom-anchored; it was the price that dropped.
 *
 * So the phone reserves three lines and the desktop keeps two. This is the
 * mobile-is-a-different-product rule doing real work rather than being
 * recited: the same 49px at both widths is what caused the bug.
 *
 * Not solved by clamping the title to two lines — "TIRZ 10MG STARTER PACK"
 * truncated to "TIRZ 10MG STARTER..." hides what the product is, and
 * TYPOGRAPHY-GUARDIAN.md forbids shrinking the type to make it fit.
 *
 * Selector matches theme-v2.css:7207 exactly so the two tie on specificity
 * and this one wins by coming later. Do not "simplify" it.
 */
@media (max-width: 480px) {
  html body.cl-v2:not(.cl-x) ul.products li.product.product a.woocommerce-LoopProduct-link h2.woocommerce-loop-product__title:not(.cl-x):not(.cl-y) {
    min-height: 73px !important;   /* 3 lines x 24.4px */
  }
}

/* 120 — the last green on the site.
 *
 * Noah: "no green still". sc/green.js walks all 41 pages at 390 and 1440 and
 * reports every element that RENDERS a green colour — not every green in the
 * stylesheets, which is a different and much longer list that mostly never
 * paints. Exactly one class came back:
 *
 *   p.stock.in-stock   background rgba(61,214,140,.08)
 *                      border     rgba(61,214,140,.35)
 *
 * the "In stock" badge on the three simple product pages. The line generator
 * recolours green BORDERS but has no business touching a background, so it
 * left the pill a green tint with a green edge.
 *
 * It keeps its job — telling you the thing is in stock — in the brand violet.
 * The meaning was never carried by the hue here; the word "In stock" is right
 * there in the badge.
 */
html body.cl-v2:not(.cl-x) p.stock.in-stock:not(.cl-z) {
  background-color: rgba(109, 40, 217, .08) !important;
  background-image: none !important;
  border-color: rgba(109, 40, 217, .35) !important;
  color: #4C1D95 !important;
}

/* 121 — floating controls are not boxes. Keep the black for structure.
 *
 * Noah, on a phone screenshot of the hero and the cart bubble: "what the hell
 * is htis". Measured at 390, and he is right:
 *
 *   .cl-cart-fab     58x58 circle wearing a 2px SOLID BLACK ring
 *   .cl-vial__pill   2px black, and at 16px side padding the long names
 *                    ("SEMAGLUTIDE", "MOTS-C - 10MG") grow until neighbouring
 *                    pills touch and their black borders merge into one blob
 *
 * The two-tier system was meant to separate a BOX from a DIVIDER. It missed a
 * third thing: a floating control — a bubble, a badge, a label riding under a
 * vial. Those are chrome, not structure. Ringing them in heavy black is what
 * made the site read as a wireframe, which is the thing he objected to when
 * he asked for the balance back.
 *
 * So the rule is now explicit, and it is the one to extend if another
 * floating control appears:
 *
 *   BOX      2px #000000   cards, panels, inputs — the definitive line
 *   DIVIDER  1px #D4D4D8   a single edge inside something
 *   CHROME   1px, its own colour — floating bubbles, badges, vial labels
 *
 * The pills also lose 4px of side padding on the phone, which is what buys
 * the room between them. NOT a smaller font — TYPOGRAPHY-GUARDIAN.md, and
 * the 11px version of exactly this rule was caught by the sweep earlier today.
 */
html body.cl-v2:not(.cl-x) .cl-cart-fab:not(.cl-z) {
  border: 2px solid #4C1D95 !important;   /* was 1px solid #E5E1F2 */
}
html body.cl-v2:not(.cl-x) .cl-cart-fab:not(.cl-z) .cl-cart-count,
html body.cl-v2:not(.cl-x) .cl-cart-count:not(.cl-z) {
  border-color: #4C1D95 !important;
}
html body.cl-v2:not(.cl-x) span.cl-vial__pill:not(.cl-z) {
  border-width: 1px !important;
  border-color: #D4D4D8 !important;
}
@media (max-width: 480px) {
  html body.cl-v2:not(.cl-x) span.cl-vial__pill:not(.cl-z) {
    padding-left: 12px !important;
    padding-right: 12px !important;
  }
}

/* 121b — stop the long vial names from colliding on a phone.
 *
 * Measured at 390 after 121: the gap between the second and third pill is
 * MINUS 8px — "LIPO-C - 10 mL" and "MOTS-C - 10MG" overlap. Each pill is
 * centred under its vial, so it gets a third of the width (130px), and a
 * nowrap label longer than that grows into its neighbour. Short names
 * (KLOW, TIRZ) never showed it; the hero rotates products, so which pair
 * collides changes on every load. That is why it looked intermittent.
 *
 * The label wraps to a second line instead of growing sideways. The pill gets
 * taller, which it has room for, and the type stays at 12.5px — the fix is in
 * the layout, per TYPOGRAPHY-GUARDIAN.md, not in the font size.
 */
@media (max-width: 480px) {
  /* The long selector is doing real work. An older rule
   *   html body.cl-v2:not(.cl-x) span.cl-vial__pill:not(.cl-x):not(.cl-w)
   * sets `white-space: nowrap; max-width: none` at (0,5,3) and silently beat
   * the (0,4,3) version of this block — the pills kept overlapping and the
   * computed style still read "nowrap" after two deploys. This matches it
   * class-for-class and adds one, so it wins at (0,6,3).
   * corelabs-prove-it: check what WINS, not what you wrote. */
  html body.cl-v2:not(.cl-x) span.cl-vial__pill:not(.cl-x):not(.cl-w):not(.cl-z) {
    /* NEVER break inside a word. Letting it wrap stopped the pills touching
     * but split "SEMAGLUTIDE" into "SEMAGLUTID / E", which is worse than the
     * problem it solved — Noah's whole complaint is jumbled text.
     *
     * One line, and the room comes from PADDING instead. Measured at 390:
     * the widest label is SEMAGLUTIDE at ~95px of glyphs; 8px of side padding
     * and a 1px border put the pill at ~113px inside a 130px slot. The
     * typeface is untouched. */
    /* Wrap at SPACES, never inside a word.
     *
     * nowrap alone still failed: measured across 24 loads at 360, "NAD -
     * 500MG" and "SEMAGLUTIDE" overlapped by 6px, because at 360 each vial
     * gets a 120px slot and SEMAGLUTIDE is ~113px of unbreakable glyphs.
     *
     * word-break:keep-all with overflow-wrap:normal means a multi-word label
     * ("NAD - 500MG", "MOTS-C - 10MG", "LIPO-C - 10 mL") folds onto two short
     * lines and takes half the width, while a single long word stays whole on
     * one line. That buys the clearance from the labels that CAN give it,
     * and never produces "SEMAGLUTID / E". */
    white-space: normal !important;
    max-width: none !important;
    word-break: keep-all !important;
    overflow-wrap: normal !important;
    line-height: 1.25 !important;
    text-align: center !important;
    /* 6px, and the tracking relaxed. After wrapping at spaces the tightest
     * measured gap was +2px (MOTS-C - 10MG beside SEMAGLUTIDE at 360) — not
     * overlapping any more, but close enough to read as touching. These two
     * give back ~10px on an 11-character word.
     *
     * The spaced-caps treatment is the brand's (corelabs-typography) and it
     * is kept everywhere else; this relaxes it only on these three small
     * floating labels, at the phone widths where the slot is 120px. The FONT
     * SIZE is untouched — TYPOGRAPHY-GUARDIAN.md. */
    padding-left: 6px !important;
    padding-right: 6px !important;
    letter-spacing: .01em !important;
  }
}

/* 122 — BLACK IS OPT-IN. The named list lives here.
 *
 * Noah: "Check out looks cleaner. I kind of like the black bars. But yeah,
 * there's too many double lines and stuff."
 *
 * He likes the black edge. What he does not like is seeing it twice. A census
 * of the live homepage found black borders on 18 classes, and boxes nest — so
 * .cl-bundle drew one and .cl-bundle__media drew another 6px inside it, and
 * on the checkout two panels nested the same way and produced the "two black
 * lines on each side" he described.
 *
 * The generator no longer emits black at all (see build-v2-lines.py), and
 * every 2px black in this file became a quiet 1px #E5E1F2. Black is now
 * applied ONLY to the outermost card of a component, by name, below.
 *
 * TO ADD A BLACK EDGE: put the OUTER element in the first list, and make sure
 * nothing inside it is in there too. That second part is the whole point.
 */
html body.cl-v2:not(.cl-x) ul.products li.product.product,
html body.cl-v2:not(.cl-x) .cl-bundle:not(.cl-z),
html body.cl-v2:not(.cl-x) .cl-feat__link:not(.cl-z),
html body.cl-v2:not(.cl-x) .cl-pillar:not(.cl-z),
html body.cl-v2:not(.cl-x) .cl-intent__step:not(.cl-z) {
  border: 2px solid #000000 !important;
}

/* …and explicitly NOT on anything living inside one of those. These are the
 * exact classes the census caught drawing the second line. */
html body.cl-v2:not(.cl-x) .cl-bundle .cl-bundle__media,
html body.cl-v2:not(.cl-x) li.product .cl-cardimg,
html body.cl-v2:not(.cl-x) .cl-picks__art:not(.cl-z),
html body.cl-v2:not(.cl-x) .cl-picks__dot:not(.cl-z),
html body.cl-v2:not(.cl-x) .cl-footer__col:not(.cl-z),
html body.cl-v2:not(.cl-x) .cl-ticker:not(.cl-z),
html body.cl-v2:not(.cl-x) .cl-topbar__link:not(.cl-z),
html body.cl-v2:not(.cl-x) .cl-topbar__calltag:not(.cl-z),
html body.cl-v2:not(.cl-x) .cl-feat__tag:not(.cl-z),
html body.cl-v2:not(.cl-x) .cl-intent:not(.cl-z) {
  border-color: transparent !important;
  border-width: 0 !important;
}

/* 122b — a button is never black-edged.
 *
 * Measured: the "Secure checkout" CTA was a filled #6D28D9 button wearing a
 * 2px BLACK ring, which is what made it read as cheap. Giving every button a
 * border in its OWN purple fixes both kinds at once — on a filled button the
 * border disappears into the fill, and an outline button keeps the violet
 * edge it is supposed to have. No per-button list to maintain.
 */
html body.cl-v2:not(.cl-x) .cl-btn:not(.cl-z),
html body.cl-v2:not(.cl-x) button.cl-atc__btn:not(.cl-z),
html body.cl-v2:not(.cl-x) .cl-secure:not(.cl-z),
html body.cl-v2:not(.cl-x) #place_order {
  border-color: #6D28D9 !important;
}

/* 122c — the Talk to someone tab is too fat.
 * Noah: "The talk to someone button is too fat." Its label was 16px, the
 * largest type in any piece of chrome on the site, which is what sets the
 * tab's width since the text runs vertically. 13px is still well clear of the
 * 12px floor and takes roughly a quarter off the width.
 */
html body.cl-v2:not(.cl-x) .cl-calltab:not(.cl-z) {
  font-size: 13px !important;
  padding: 10px 2px !important;
  letter-spacing: .02em !important;
}

/* 123 — the checkout polish Noah listed, plus the header alignment.
 *
 * "the X in the corner, top corner of the right is... I don't like that at
 *  all. It's just black X. Maybe it needs to be white um, in the purple."
 *
 * The X is an SVG <path stroke="currentColor">. A presentation attribute ON
 * an element beats a value INHERITED from its parent, so the existing
 * `.cl-co__close svg { stroke: #FFFFFF }` never reached the path — the path
 * resolved currentColor against whatever `color` won on the button. Setting
 * the stroke on the PATH itself is what actually paints it.
 */
/* The extra :not()s are load-bearing. theme-v2.css:5734 says
 *   html body.cl-v2:not(.cl-x) svg:not(.cl-logo):not([class*="logo"]):not([class*="brand"]) path
 *     { stroke: currentcolor !important }
 * which is (0,5,4) — five classes/attribute selectors. The first version of
 * this block was (0,4,4) and lost by ONE class, so the X kept resolving
 * currentColor against the button's near-black #111118 and stayed black on
 * the purple, exactly as Noah described. This is (0,6,4).
 * corelabs-v2-rebrand: class count beats element count, which is why
 * overrides here silently lose. Count before you write. */
html body.cl-v2:not(.cl-x) .cl-co__close:not(.cl-z):not(.cl-y) svg path:not(.cl-w),
html body.cl-v2:not(.cl-x) .cl-popback:not(.cl-z):not(.cl-y) svg path:not(.cl-w),
html body.cl-v2:not(.cl-x) .cl-sheet__x:not(.cl-z):not(.cl-y) svg path:not(.cl-w),
html body.cl-v2:not(.cl-x) .cl-callsheet__x:not(.cl-z):not(.cl-y) svg path:not(.cl-w),
html body.cl-v2:not(.cl-x) .cl-refsheet__x:not(.cl-z):not(.cl-y) svg path:not(.cl-w),
html body.cl-v2:not(.cl-x) .cl-acct__x:not(.cl-z):not(.cl-y) svg path:not(.cl-w) {
  stroke: #FFFFFF !important;
  fill: none !important;
}
/* and the button's own colour, so currentColor is white even where a path
 * rule does not reach */
html body.cl-v2:not(.cl-x) .cl-co__close:not(.cl-z):not(.cl-y):not(.cl-w),
html body.cl-v2:not(.cl-x) .cl-popback:not(.cl-z):not(.cl-y):not(.cl-w),
html body.cl-v2:not(.cl-x) .cl-sheet__x:not(.cl-z):not(.cl-y):not(.cl-w),
html body.cl-v2:not(.cl-x) .cl-callsheet__x:not(.cl-z):not(.cl-y):not(.cl-w) {
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}

/* "the continue to but payment button could be fixed up a little bit... it
 *  just looks a little too dark of purple."
 * That is PLACE ORDER. It was running the darkest end of the ramp
 * (#4C1D95/#5B21B6), which on a phone screen reads as near-black rather than
 * as the brand. Moved up to the mid ramp so it matches "Shop the catalog"
 * and the Add to cart buttons — one purple for one kind of action.
 */
html body.cl-v2:not(.cl-x) #place_order:not(.cl-z) {
  background-color: #6D28D9 !important;
  background-image: linear-gradient(180deg, #7C3AED 0%, #6D28D9 100%) !important;
  border-color: #6D28D9 !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
}

/* 123b — REMOVED, superseded by 136.
 *
 * It restyled the "In stock" line as quiet grey sentence text. Noah later
 * asked for the green pill back, which 136 provides for both states.
 */

/* 123c — a section header should agree with itself.
 *
 * On the shop at 390 the eyebrow "CORE LABS" sat LEFT while the title "FULL
 * CATALOG" under it sat CENTRE, which is what reads as "off-center". Noah:
 * "the starter bundles, title, and start here, all that's... off-center and
 * stuff on my mobile."
 *
 * Eyebrow and title now both centre on the phone, per corelabs-mobile-center.
 * Body prose stays LEFT, per corelabs-left-align, which supersedes centring
 * for reading text — those two notes do not conflict, they cover different
 * things, and the bug was applying neither consistently.
 */
@media (max-width: 480px) {
  html body.cl-v2:not(.cl-x) p.cl-eyebrow:not(.cl-z) {
    text-align: center !important;
  }
}

/* 124 — the Talk to someone tab, slimmer, and deterministic.
 *
 * Noah, twice: "too fat", then "too thick. Make it a little less protruding."
 *
 * Shrinking the font was not enough, and the reason is the ICON: the phone
 * svg inside the tab is a fixed 16px wide, so with any padding at all the tab
 * could never go below ~20px however small the label got. The width is now
 * SET, not inferred — 20px on a phone, with the icon scaled to match — so it
 * is the same on every device instead of depending on font metrics.
 *
 * The label stays in the DOM and keeps its size for screen readers; only the
 * drawn box shrinks. Still one button with one name, per
 * "just pick one and stick with it".
 */
@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x) .cl-calltab:not(.cl-z) {
    width: 20px !important;
    min-width: 0 !important;
    padding: 10px 0 !important;
    font-size: 12px !important;      /* the floor, not below it */
    letter-spacing: 0 !important;
    border-radius: 0 8px 8px 0 !important;
  }
  html body.cl-v2:not(.cl-x) .cl-calltab:not(.cl-z) svg {
    width: 11px !important;
    height: 11px !important;
  }
}

/* 124b — the trust row was four ragged lines.
 *
 * Measured at 390: the four items stack ONE PER ROW, each centred on its own
 * width, so their left edges land at 109, 106, 98 and 124 — four different
 * starting points down the page. That is the "text is off to the left, text
 * is off to the right, things are not lined up" Noah is pointing at.
 *
 * A centred flex row cannot line up items of different widths; only a grid
 * can. Two columns, each item left-aligned inside its cell, so all four share
 * exactly two left edges instead of four.
 */
@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x) ul.cl-hero2__trust:not(.cl-z) {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    column-gap: 10px !important;
    row-gap: 14px !important;
    justify-items: start !important;
    align-items: center !important;
    max-width: 340px !important;
    margin-left: auto !important;
    margin-right: auto !important;
  }
  html body.cl-v2:not(.cl-x) ul.cl-hero2__trust:not(.cl-z) > li.cl-hero2__trustItem {
    width: 100% !important;
    min-width: 0 !important;
    justify-content: flex-start !important;
    text-align: left !important;
    align-items: center !important;
  }
  /* The label wraps inside its cell.
   *
   * sc/UNIFORM.js caught this the moment the grid went in: at 390 two columns
   * give each cell 165px and "Fast U.S. fulfillment" needs 176, so the span
   * escaped its box by 11px. Widening the columns only moves the problem to
   * 360. Letting the longest label take two lines fixes it at every width,
   * and the four cells still share two left edges, which was the point. */
  html body.cl-v2:not(.cl-x) ul.cl-hero2__trust:not(.cl-z) .cl-hero2__trustText {
    white-space: normal !important;
    overflow-wrap: normal !important;
    word-break: keep-all !important;
    line-height: 1.25 !important;
    min-width: 0 !important;
  }
}

/* 125 — the age gate's "No" button was INVISIBLE. White on white, 1.00:1.
 *
 * Noah sent a photo of the age gate with an empty white pill where "No"
 * should be. Every first-time visitor sees that screen.
 *
 * Cause, and it is worth understanding because it is the whole shape of the
 * problem he is describing ("the website's slowly breaking... it shouldn't
 * fuck up all the text"):
 *
 * theme-v2.css:7395 sets white ink on .cl-btn--secondary. Its comment says
 * why, and the reasoning was correct AT THE TIME — another rule had repainted
 * the secondary button solid purple, so white ink was the fix. Later work
 * restored the button's white background. The ink rule did not move, because
 * nothing connected the two. One rule owned the background, a different rule
 * owned the text, and when the first changed the second silently became
 * wrong.
 *
 * So they are pinned together here, in ONE rule. A secondary button is white
 * with violet ink and a violet edge, and that cannot half-change again.
 * #4C1D95 on #FFFFFF is 10.9:1.
 *
 * (0,6,3) to beat 7395's (0,5,3).
 */
html body.cl-v2:not(.cl-x) a.cl-btn.cl-btn--secondary:not(.cl-z):not(.cl-y),
html body.cl-v2:not(.cl-x) button.cl-btn.cl-btn--secondary:not(.cl-z):not(.cl-y),
html body.cl-v2:not(.cl-x) span.cl-btn.cl-btn--secondary:not(.cl-z):not(.cl-y) {
  background-color: #FFFFFF !important;
  background-image: none !important;
  color: #4C1D95 !important;
  -webkit-text-fill-color: #4C1D95 !important;
  border: 2px solid #6D28D9 !important;
}

/* 126 — one type system on the product card.
 *
 * Noah: "the pricing, it's just like there's just jumbled words. It looks like
 * you just guessed and threw shit in there."
 *
 * Measured on one card before this block:
 *
 *   name    Poppins  20px / 800 / +1.2px tracking
 *   price   Poppins  25px / 700 / -0.25px tracking
 *   pill    DM Sans  12.5px / 600 / +0.25px
 *   button  INTER    13.5px / 700 / normal
 *
 * Three typefaces in 100px of card, and the name and the price tracked in
 * OPPOSITE directions — one opening up, one tightening. Nothing there was
 * decided; four rules were written at four different times.
 *
 * Against corelabs-typography, which is the approved system:
 *   - prices are Poppins 800, not 700
 *   - buttons are Poppins 14-17px, not 13.5px of Inter
 *   - product names are spaced caps, which is why the name keeps its +1.2px
 *
 * The price drops to neutral tracking rather than negative: a price is read as
 * a figure, not as display lettering, and -0.25px was fighting the +1.2px
 * directly above it. Sizes are left alone — price larger than name is correct
 * on a shop card and is what the approved spec already says.
 */
/* REVISED. The first version of this block set the price to 800 and the
 * button to 14px, citing the approved spec. Both were already decided
 * deliberately elsewhere and LATER — theme-v2.css:7323 "the price is big, not
 * loud - 800 -> 700" and :8816 "the small/secondary size, theirs" — at a
 * specificity of (12,6) that beat this block's (9,4) anyway.
 *
 * Quoting the spec at a considered later decision is how a stylesheet ends up
 * with two rules fighting and neither winning cleanly. The tracking conflict
 * was the actual defect Noah could see, and it is fixed at the winning rule
 * itself (search "Tracking neutral"). Nothing about weight or size belongs
 * here. */
html body.cl-v2:not(.cl-x) ul.products li.product.product .price:not(.cl-z) {
  font-family: Poppins, system-ui, sans-serif !important;
}

/* 126b — the 10% popup badge was clipping its own text.
 *
 * .cl-wb__badge computed `padding: 0` with `letter-spacing: 2px` inside a
 * `border-radius: 999px` pill. Zero padding puts the glyphs flush against the
 * purple edge, and the trailing letter-space — which is added AFTER the last
 * character — pushes it past the curve. That is the cut-off "10% OFF" in
 * Noah's screenshot, and it is why it looked cropped rather than small.
 */
html body.cl-v2:not(.cl-x) .cl-wb__badge:not(.cl-z) {
  font-family: Poppins, system-ui, sans-serif !important;
  padding: 5px 14px 5px 16px !important;   /* +2px left: tracking pads the right */
  display: inline-block !important;
  line-height: 1.2 !important;
}

/* 126c — the search field had no accessible name.
 * WCAG 4.1.2. It is the one unlabelled control on the page; a screen reader
 * announces it as "edit text, blank". The visible placeholder is not a label.
 */
html body.cl-v2:not(.cl-x) .search-field:not(.cl-z) {
  font-family: "DM Sans", system-ui, sans-serif !important;
}

/* 127 — tap targets that were too small to hit.
 *
 * From /impeccable audit, measured at 390:
 *   .cl-agegate__links a   17px tall  ("Research Use Only Policy", "Terms")
 *   .cl-topbar__link       40px tall  (the phone number)
 *
 * 17px fails even WCAG 2.5.8 AA, which asks for 24px; 44px is the AAA target
 * and what a thumb actually needs. The age-gate links matter more than their
 * size suggests — they are the only way to read the policy before agreeing to
 * it, and they sit on the first screen every visitor meets.
 *
 * Padding, not font-size: the type is approved and TYPOGRAPHY-GUARDIAN.md
 * says the layout gives way, not the type. inline-block so the padding
 * actually forms a box on an inline link.
 *
 * Deliberately NOT changed, having been measured and considered:
 *   .cl-skip-link  26px — only rendered when focused, never pointed at
 *   .cl-logo       26px — a wordmark; the whole header row is the target
 *   .cl-calltab    18px wide — Noah asked for it slim, twice
 */
html body.cl-v2:not(.cl-x) .cl-agegate__links:not(.cl-z) a {
  display: inline-block !important;
  padding: 7px 10px !important;
  min-height: 24px !important;
  line-height: 1.5 !important;
}
html body.cl-v2:not(.cl-x) a.cl-topbar__link:not(.cl-z) {
  min-height: 44px !important;
  display: inline-flex !important;
  align-items: center !important;
}

/* 128 — section headings centre on the phone. All of them.
 *
 * Noah: "I also wanted those headings centered on the mobile. I don't like how
 * they're off centered. I want them centered because you're scrolling."
 *
 * Measured at 390, the site could not make up its mind. CENTRED: the hero
 * title, .cl-eyebrow ("Featured"), the product-card titles. LEFT:
 * .cl-bundles__title ("Starter Bundles"), .cl-bundles__eyebrow ("Start
 * here"), .cl-feat__title ("Start with these"), .cl-section__title ("How It
 * Works"), .cl-picks__eyebrow, .cl-contact__title. Scrolling past that reads
 * as drift, which is exactly what he is describing — the axis moves under you
 * section by section.
 *
 * This reconciles two memories that look like they conflict and do not:
 *   corelabs-mobile-center  — centre titles and labels on phones
 *   corelabs-left-align     — Noah chose LEFT for reading text, which
 *                             supersedes centring *for prose*
 * They cover different things. A heading is a signpost and centres; a
 * paragraph is read and stays left. Body copy is deliberately NOT in this
 * block, and must not be added to it.
 *
 * Also left alone, deliberately:
 *   .cl-footer__heading  — its link list underneath is left, and a centred
 *                          heading over a left list is worse than either
 *   .cl-bundle__name     — a title INSIDE the starter-pack card Noah asked to
 *                          keep as it is
 *   .cl-picks__name, .cl-contact__label — labels inside components, not
 *                          section headers
 */
@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x) h1.cl-hero2__title:not(.cl-z),
  html body.cl-v2:not(.cl-x) h2.cl-bundles__title:not(.cl-z),
  html body.cl-v2:not(.cl-x) p.cl-bundles__eyebrow:not(.cl-z),
  html body.cl-v2:not(.cl-x) h2.cl-feat__title:not(.cl-z),
  html body.cl-v2:not(.cl-x) h2.cl-section__title:not(.cl-z),
  html body.cl-v2:not(.cl-x) p.cl-picks__eyebrow:not(.cl-z),
  html body.cl-v2:not(.cl-x) h2.cl-contact__title:not(.cl-z),
  html body.cl-v2:not(.cl-x) p.cl-contact__eyebrow:not(.cl-z),
  html body.cl-v2:not(.cl-x) h1.cl-chero__title:not(.cl-z),
  html body.cl-v2:not(.cl-x) p.cl-chero__eyebrow:not(.cl-z),
  html body.cl-v2:not(.cl-x) p.cl-eyebrow:not(.cl-z) {
    text-align: center !important;
    margin-left: auto !important;
    margin-right: auto !important;
  }
}

/* 129 — the topbar did not fit the phone, and lost text off BOTH edges.
 *
 * Noah: "This doesn't fit."
 *
 * Measured at 390: the bar's content is 463px wide in a 390px box. The
 * "Talk to someone" label starts at left:-73 and the email pill ends at
 * right:463 — 73px past the screen. overflow is visible and the row does not
 * wrap, so it simply clips at both ends: "D SOMEONE" on the left and
 * "corelabsllc@gmail." on the right. corelabs-mobile-center is explicit that
 * no text goes off the edge.
 *
 * It did not show up in sc/UNIFORM.js because the page itself does not scroll
 * sideways — the overflow is clipped, not scrollable, so the BLEED check
 * (which keys on documentElement.scrollWidth, deliberately) never sees it.
 * That gap is now covered by sc/fitcheck.js.
 *
 * On a phone the bar keeps the ONE thing it is for: tap to call. The label is
 * decoration — the pill already carries a phone icon and the number — and the
 * email is still one tap away in the footer and on the contact section, which
 * is where people look for it. 165px of phone pill fits 390 and 360 with room.
 */
@media (max-width: 767px) {
  html body.cl-v2:not(.cl-x) .cl-topbar__inner:not(.cl-z) {
    justify-content: center !important;
    flex-wrap: nowrap !important;
    gap: 0 !important;
  }
  html body.cl-v2:not(.cl-x) .cl-topbar__calltag:not(.cl-z) {
    display: none !important;
  }
  html body.cl-v2:not(.cl-x) .cl-topbar__link--mail:not(.cl-z),
  html body.cl-v2:not(.cl-x) a.cl-topbar__link[href^="mailto"]:not(.cl-z) {
    display: none !important;
  }
}

/* 130 — REVERTED. A procedural WebGL smoke shader lived here.
 *
 * It worked — fBm with domain warping, 6KB, real rolling smoke — and Noah's
 * verdict on seeing it was: "that background is shit. Like, what the fuck is
 * that? I was just wanting it to pull up that image of that smoke I had...
 * the PNG, that's transparent background. And then just make it kind of roll
 * like smoke. Just make it move. That's all."
 *
 * Which is the whole lesson: he did not want smoke invented, he wanted HIS
 * artwork to move. The art was already there and already drifting; the drift
 * was simply too small to see (see the clMistA/clMistB note). Removing the
 * shader and raising the amplitude is the entire fix.
 *
 * assets/mist.js is left on disk but is no longer enqueued. Do not re-add it.
 */

}

/* 131 — the warped-ribbon canvas.
 *
 * It sits ON TOP of the two CSS ribbon layers and replaces what you see,
 * which is why those layers keep their own animation: they are the fallback,
 * not dead weight. If the canvas never appears the hero is unchanged.
 *
 * Noah wanted the ribbon to move "like mist" rather than slide. The canvas
 * samples the same artwork and displaces where each pixel is read from, so
 * the shape curls in place instead of travelling as a rigid plate.
 */
html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral canvas.cl-mistgl {
  position: absolute !important;
  inset: 0 !important;
  width: 100% !important;
  height: 100% !important;
  display: block !important;
  z-index: 2 !important;
  pointer-events: none !important;
}
/* with the canvas up, the plain CSS layers underneath would double the
   artwork — hide them, but ONLY when the canvas actually exists */
/* .is-mist-painted, not :has(canvas).
 *
 * Keying on the canvas EXISTING meant the fallback was dismissed the moment
 * the element was inserted — before it had drawn anything. A canvas that is
 * present and blank then produced a blank hero. mist.js adds this class only
 * after a frame has actually landed, so the CSS ribbon stays up until there
 * is something real to replace it with. */
html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral.is-mist-painted::before,
html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral.is-mist-painted::after {
  opacity: 0 !important;
}
@media (prefers-reduced-motion: reduce) {
  html body.cl-v2:not(.cl-x) .cl-hero2 .cl-spiral canvas.cl-mistgl { display: none !important; }
}

/* 132 — the Zelle bar was the only amber thing on a violet site.
 *
 * Noah: "make this better. its clashing."
 *
 * Measured: background #FFFBEB, border 2px #FCD34D, text #92400E. Cream,
 * amber and brown — a complete second palette, sitting directly beneath the
 * violet hero. It reads as a warning strip from another website rather than
 * as an offer from this one.
 *
 * It keeps every bit of its prominence: full-width, bordered, its own
 * surface. It just makes that noise in the brand's own colour. #4C1D95 on
 * #F5F3FF is 10.9:1, so the saving is easier to read than it was at
 * #92400E on #FFFBEB.
 *
 * Amber is NOT banished from the site — it still carries genuine warnings
 * (corelabs-typography keeps #FCD34D / #B45309 for status). A 5% discount is
 * not a warning.
 */
/* `aside.` and the extra :not() are load-bearing. The bar is an <aside>, and
 * the amber rule qualifies the tag: `html body.cl-v2:not(.cl-x) aside.cl-zbar`
 * is (0,4,3). The first version of this block was `.cl-zbar:not(.cl-z)` at
 * (0,4,2) — the SAME four classes, one fewer element — so it lost on the
 * element tie-break and the bar stayed amber through a deploy.
 * This is (0,5,3). corelabs-v2-rebrand: count before you write. */
html body.cl-v2:not(.cl-x) aside.cl-zbar:not(.cl-z):not(.cl-y) {
  background-color: #F5F3FF !important;
  background-image: none !important;
  border-color: #C4B5FD !important;
  color: #4C1D95 !important;
}
html body.cl-v2:not(.cl-x) aside.cl-zbar:not(.cl-z):not(.cl-y) .cl-zbar__tag {
  background-color: transparent !important;
  color: #6D28D9 !important;
}
html body.cl-v2:not(.cl-x) aside.cl-zbar:not(.cl-z):not(.cl-y) strong,
html body.cl-v2:not(.cl-x) aside.cl-zbar:not(.cl-z):not(.cl-y) b {
  color: #4C1D95 !important;
}

/* 132b — a section's intro paragraph belongs under its own heading.
 *
 * Noah: "move the small text to fit this and make more sense."
 *
 * Measured at 1440: .cl-bundles__title starts at x=132. .cl-bundles__lede
 * starts at x=424 — 292px to its right — because the lede carries
 * `margin: 0 auto` with a 592px max-width, so it centres itself inside a
 * container whose heading is left-aligned. The heading and its own sentence
 * end up on two different axes, which is what makes it read as floating
 * loose rather than belonging to the heading above it.
 *
 * The max-width stays: 592px is about 70 characters, which is the measure
 * you want for reading. Only the centring goes, and only on desktop — on a
 * phone the heading itself is centred (block 128), so a centred block of
 * left-aligned prose under it is correct there.
 */
@media (min-width: 768px) {
  html body.cl-v2:not(.cl-x) .cl-bundles__lede:not(.cl-z),
  html body.cl-v2:not(.cl-x) .cl-feat__lede:not(.cl-z),
  html body.cl-v2:not(.cl-x) .cl-section__lede:not(.cl-z) {
    margin-left: 0 !important;
    margin-right: 0 !important;
  }
}

/* 133 — the trust panel had no hierarchy, so it read as a block of shouting.
 *
 * Noah: "Hate the way the text is on the first." And on the same pattern
 * elsewhere: "move the small text to fit this and make more sense."
 *
 * Measured at 1440. Four things, all of them structural rather than taste:
 *
 *   1. The icon sat 118px to the RIGHT of its own text — iconL 271, textL 153
 *      — because the item is a flex COLUMN with align-items:center while the
 *      text inside is left-aligned. The icon centres, the words do not.
 *   2. The <strong> label and the <span> sentence under it were typographically
 *      IDENTICAL: both 12.5px, both 1.75px tracking. A title that looks exactly
 *      like its own description is not a title.
 *   3. That 1.75px of tracking was applied to the SENTENCE too. Spaced caps are
 *      the brand's voice for labels (corelabs-typography) and are wrong for
 *      running text — it is what made "Ships From Tennessee" and "Batch
 *      Documentation" wrap in a 284px cell.
 *   4. Each item carried a 1px violet left border — the accent-bar tell, and
 *      more lines on a site where Noah has asked twice for fewer.
 *
 * So: one left edge for everything, the icon inline beside its label, the
 * label keeping its spaced caps at a tracking that fits, and the sentence
 * reading as a sentence. No type gets smaller — TYPOGRAPHY-GUARDIAN.md.
 */
html body.cl-v2:not(.cl-x) ul.cl-trustbar:not(.cl-z) > li.cl-trustbar__item {
  display: grid !important;
  grid-template-columns: auto 1fr !important;
  grid-template-areas: "icon label" "icon copy" !important;
  column-gap: 11px !important;
  row-gap: 2px !important;
  align-items: start !important;
  justify-items: start !important;
  text-align: left !important;
  border-left: 0 !important;      /* the accent bar goes */
  padding: 4px 22px 4px 0 !important;
}
html body.cl-v2:not(.cl-x) ul.cl-trustbar:not(.cl-z) > li.cl-trustbar__item > .cl-trustbar__icon {
  grid-area: icon !important;
  align-self: start !important;
  margin-top: 1px !important;
  color: #6D28D9 !important;
}
html body.cl-v2:not(.cl-x) ul.cl-trustbar:not(.cl-z) > li.cl-trustbar__item > .cl-trustbar__text {
  display: contents !important;   /* let the label and copy land in their own cells */
}
/* the label keeps the brand's spaced caps, at a tracking that fits 284px */
html body.cl-v2:not(.cl-x) ul.cl-trustbar:not(.cl-z) .cl-trustbar__text > strong {
  grid-area: label !important;
  letter-spacing: .085em !important;   /* was 1.75px / .14em */
  font-weight: 700 !important;
  color: #111118 !important;
  line-height: 1.35 !important;
}
/* the sentence reads as a sentence: no caps tracking, quieter ink */
html body.cl-v2:not(.cl-x) ul.cl-trustbar:not(.cl-z) .cl-trustbar__text > span {
  grid-area: copy !important;
  letter-spacing: 0 !important;
  text-transform: none !important;
  font-weight: 400 !important;
  color: #6B6B76 !important;
  line-height: 1.45 !important;
}

/* 134 — the hero's buttons sat on a different axis from its own headline.
 *
 * Noah: "the alignment and spacing could be better."
 *
 * Block 117b centred .cl-hero2__cta, which is right on a phone — block 128
 * centres the headline there, so the buttons belong under its middle. On a
 * DESKTOP the headline is left-aligned and starts at the container's edge,
 * while the buttons stayed centred in the column. Headline on one axis,
 * call to action on another, with a few hundred pixels between them.
 *
 * So the rule follows the headline instead of being fixed: centred where the
 * headline is centred, left where the headline is left.
 */
@media (min-width: 768px) {
  html body.cl-v2:not(.cl-x) .cl-hero2__cta:not(.cl-z) {
    justify-content: flex-start !important;
  }
}

/* 135 — REMOVED, superseded by 136 below.
 *
 * It styled the in-stock pill at 36px, restyled the dead "Out of stock"
 * button red, and made the waitlist a 44px outline button. Block 136 then
 * removed the dead button entirely and gave both states one shared pill, so
 * 135's rules only survived to fight it: the in-stock pill came out 36px
 * against 34, and the buttons landed 1px apart because 135's selector carried
 * one more class.
 *
 * Deleted rather than overridden. corelabs-css-accumulation — this stylesheet
 * is 10,000 lines because superseded blocks were left in place and beaten
 * with new ones. The green and red it introduced live on in 136.
 */

/* 136 — one button per card, and the two stock pills match.
 *
 * Noah: "out of stock shoudk look like the in stock" and "the tell me when
 * its back could jsut replace the add to cart butotn when its out of stock."
 *
 * Both right, and together they undo a tangle this card has had all day. A
 * sold-out card was carrying TWO controls — a dead "Out of stock" button
 * nobody can press, plus a separate waitlist link — while an in-stock card
 * carried one. That mismatch is what forced the 48px reserve slot, which then
 * looked bare, which was then filled with a status line. Every fix was
 * patching the shape instead of correcting it.
 *
 * The shape now matches, state for state:
 *
 *     in stock      [ Add to cart              ]   ( In stock )
 *     out of stock  [ Tell me when it is back  ]   ( Out of stock )
 *
 * One button, one pill, same geometry, so the rows line up with no reserve to
 * engineer and nothing blank to fill. The dead button is gone rather than
 * restyled: a control that cannot be pressed should not occupy the place
 * where the pressable one lives.
 */

/* the status pill, both states, identical geometry */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc:not(.cl-z)::after {
  content: 'In stock' !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  width: fit-content !important;
  height: 34px !important;
  margin: 8px auto 0 !important;
  padding: 0 16px !important;
  border-radius: 999px !important;
  font-family: "DM Sans", system-ui, sans-serif !important;
  font-size: 12.5px !important;
  font-weight: 600 !important;
  letter-spacing: 0 !important;
  text-transform: none !important;
  opacity: 1 !important;
  background-color: #EAFBF1 !important;
  border: 1px solid rgba(61, 214, 140, .45) !important;
  color: #0F6B3F !important;
  pointer-events: none !important;
}
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc.cl-atc--out:not(.cl-z)::after {
  content: 'Out of stock' !important;
  background-color: #FEF2F2 !important;
  border-color: rgba(220, 38, 38, .40) !important;
  color: #9B1C1C !important;
}

/* the dead button goes; nothing should sit where a live control belongs */
html body.cl-v2:not(.cl-x) ul.products li.product.product div.cl-atc.cl-atc--out
  button.cl-atc__btn:not(.cl-q):not(.cl-z) {
  display: none !important;
}

/* and the waitlist takes its place, as the card's one real action */
/* Every value here is copied from the live "Add to cart" button, not chosen.
 * Noah: "the buttons need to match." Measured side by side, they differed in
 * five ways at once — 999px radius against 10px, 44px tall against 46, a 2px
 * violet border against a 1px lavender one, a gradient against a flat fill,
 * and 0.54px of tracking against none. Each looked reasonable alone; together
 * they made the sold-out card look like it came from a different site.
 * If Add to cart changes, change this with it. */
html body.cl-v2:not(.cl-x) ul.products li.product.product .cl-atc--out
  button.cl-wait__open:not(.cl-z) {
  order: -1 !important;
  display: flex !important;
  align-items: center !important;
  justify-content: center !important;
  width: 100% !important;
  height: 46px !important;
  min-height: 46px !important;
  background-color: #6D28D9 !important;
  background-image: none !important;
  border: 1px solid rgba(196, 181, 253, .85) !important;
  border-radius: 10px !important;
  color: #FFFFFF !important;
  -webkit-text-fill-color: #FFFFFF !important;
  font-family: Poppins, system-ui, sans-serif !important;
  font-size: 13.5px !important;
  font-weight: 700 !important;
  letter-spacing: normal !important;
  text-transform: none !important;
  text-decoration: none !important;
  box-shadow: none !important;
  margin: 0 !important;
  padding: 0 14px !important;
}

/* the reserve slot engineered in block 116 is no longer needed: both states
   now have the same number of children and the same heights */
html body.cl-v2:not(.cl-x) ul.products:has(.cl-atc--out) li.product.product
  .cl-atc:not(.cl-atc--out):not(.cl-z)::before {
  content: none !important;
}

/* ===========================================================================
   137. Quick-view modal: foregrounds the generated palette missed
   build-v2-palette.py rewrote the BACKGROUNDS of .cl-qv__size (#f5f3ff),
   .cl-qv__more (#f5f3ff) and .cl-qv__x (rgba(245,243,255,.9)) for v2 but left
   every one of them on the dark theme's `color: #fff` from woocommerce.css.
   White on near-white: the strength buttons, "Details" and the close X all
   rendered invisible. Pin the foreground in the same rule as the surface, so
   a future palette pass cannot separate them again.
   Specificity matches the palette at (0,3,2); theme-v2.css loads last.
   ======================================================================== */

/* strength buttons — 10MG / 30MG was #fff on #f5f3ff = 1.06:1 */
html body.cl-v2:not(.cl-x) .cl-qv__size,
html body.cl-v2:not(.cl-x) .cl-qv__size b {
  color: #18181B !important;            /* 15.3:1 on #f5f3ff */
  -webkit-text-fill-color: #18181B !important;
}
html body.cl-v2:not(.cl-x) .cl-qv__size:disabled,
html body.cl-v2:not(.cl-x) .cl-qv__size:disabled b {
  /* #71717A measured 4.41:1 here — it clears AA on white (4.83) but NOT on
     this lavender panel. #52525B is the palette's own light-theme muted ink
     and measures 7.04:1, still clearly secondary next to #18181B. */
  color: #52525B !important;
  -webkit-text-fill-color: #52525B !important;
}
html body.cl-v2:not(.cl-x) .cl-qv__size.is-on,
html body.cl-v2:not(.cl-x) .cl-qv__size.is-on b,
html body.cl-v2:not(.cl-x) .cl-qv__size.is-adding,
html body.cl-v2:not(.cl-x) .cl-qv__size.is-adding b {
  color: #2E1065 !important;            /* on the rgba(124,58,237,.22) fill */
  -webkit-text-fill-color: #2E1065 !important;
}

/* "Details" summary — was #fff on #f5f3ff */
html body.cl-v2:not(.cl-x) .cl-qv__more > summary {
  color: #18181B !important;
  -webkit-text-fill-color: #18181B !important;
}

/* close X — was #fff on rgba(245,243,255,.9) */
html body.cl-v2:not(.cl-x) .cl-qv__x {
  color: #6D28D9 !important;            /* 6.9:1 on the lavender chip */
  -webkit-text-fill-color: #6D28D9 !important;
}
html body.cl-v2:not(.cl-x) .cl-qv__x svg,
html body.cl-v2:not(.cl-x) .cl-qv__x svg path {
  stroke: #6D28D9 !important;
  fill: none !important;
}

/* product title — palette never covered it; still #fff !important */
html body.cl-v2:not(.cl-x) .cl-qv__title {
  color: #18181B !important;
  -webkit-text-fill-color: #18181B !important;
}


/* ===========================================================================
   138. #71717A is 0.09 short of AA on the lavender panels
   Measured in the quick-view with sc/qvink.js: the pack spec lines render
   #71717A on #F5F3FF = 4.41:1, needing 4.5. The same ink on plain white is
   4.83:1, which is why this never showed up on a product page and only
   surfaces inside a modal whose panel is lavender. Rather than move
   --mist-400 (21 call sites, approved and fine on white), darken the one
   component that sits on the tinted surface. #52525B = 7.04:1 on #F5F3FF
   and 7.46:1 on #FFFFFF, so it is correct on both.
   ======================================================================== */
html body.cl-v2:not(.cl-x) .cl-pack__detail,
html body.cl-v2:not(.cl-x) .cl-qv__card .cl-pack__detail {
  color: #52525B !important;
  -webkit-text-fill-color: #52525B !important;
}
