/* ============================================================
   DICE PEPTIDES — BASE STYLESHEET (loaded site-wide)
   Design System v1.0. Tokens + global primitives +
   every SHARED component (navbar, buttons, badges, fields,
   product grid/card, tabs, COA card, accordion, trust strip,
   CTA band, footer). Page-specific styles live in home.css /
   shop.css / product.css etc. and are enqueued conditionally.
   No token is added, removed, or altered from v1.0.
   ============================================================ */

/* ---- DESIGN TOKENS (Dice Peptides v1.0) ------------------ */
:root {
  /* Colors — Dice light clinical palette (cobalt accent) */
  --bg-base:       #F5F7FB;
  --bg-surface:    #FFFFFF;
  --bg-elevated:   #FFFFFF;
  --bg-overlay:    #EEF2FA;
  --bg-panel:      #F0F3FA;
  --border-subtle: #E7ECF4;
  --border-default:#D6DEEB;
  --text-primary:  #0F1A33;
  --text-secondary:#525C72;
  --text-muted:    #8A93A8;
  --accent:        #1E48C4;
  --accent-strong: #173BA8;
  --accent-light:  #3A63DA;
  --accent-dim:    rgba(30,72,196,0.08);
  --accent-soft:   rgba(30,72,196,0.12);
  --accent-glow:   rgba(30,72,196,0.22);
  --success:       #12A150;
  --warning:       #E0821A;
  --danger:        #DC3545;

  /* Product studio well — matched to the neutral-gray studio photography */
  --stage: radial-gradient(72% 66% at 50% 44%, #EDECEC 0%, #E0DEDF 50%, #CBC9CA 100%);

  /* Typography — single source of truth for the brand font stack, so every
     surface (incl. WooCommerce) can reference the same family token. */
  --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

  /* Radius */
  --radius-sm:  8px;
  --radius-md:  10px;
  --radius-lg:  12px;
  --radius-xl:  16px;
  --radius-full:9999px;

  /* Shadows — tuned for a light surface (soft, ink-based) */
  --shadow-card:  0 1px 2px rgba(15,26,51,0.05), 0 6px 20px rgba(15,26,51,0.06);
  --shadow-hover: 0 10px 34px rgba(15,26,51,0.12);
  --shadow-glow:  0 6px 18px var(--accent-glow);

  /* Animation */
  --ease-out: cubic-bezier(0.16,1,0.3,1);
  --dur-fast: 200ms;
  --dur-base: 250ms;
  --dur-slow: 400ms;

  /* Spacing — 8px base scale */
  --sp-1: 4px;  --sp-2: 8px;   --sp-3: 12px;  --sp-4: 16px;
  --sp-5: 20px; --sp-6: 24px;  --sp-8: 32px;  --sp-10:40px;
  --sp-12:48px; --sp-16:64px;  --sp-20:80px;  --sp-24:96px;

  /* Layout */
  --container: 1200px;
  --gutter: var(--sp-10);          /* 40px desktop */
  --section-gap: var(--sp-24);     /* 96px desktop */
  --nav-h: 64px;
  --z-nav: 50; --z-drawer: 60; --z-cart-overlay: 80; --z-cart: 90; --z-skip: 100;
  --cart-w: 440px;
}

/* ---- RESET & BASE --------------------------------------- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* overflow-x: clip stops the off-canvas cart drawer (position:fixed, translated
   off-screen right) and any minor bleed from creating a left/right scroll on
   mobile. `clip` (not `hidden`) avoids making the root a scroll container, so the
   sticky header keeps working. No visual change on desktop — nothing overflows there.

   overflow-y: auto is REQUIRED alongside it: on narrow viewports Chromium's
   `overflow-x: clip` on the root silently disables *vertical* scrolling whenever
   there is any clipped horizontal overflow (here the off-canvas cart drawer). That
   left the whole page — most critically the checkout, whose "Place Order" button
   sits far below the fold — unscrollable on mobile. Pairing an explicit vertical
   scroll value keeps the root a vertical scroll container so the page always
   scrolls; the sticky header still works (verified) and short pages show no bar. */
html { scroll-behavior: smooth; overflow-x: clip; overflow-y: auto; }

body {
  font-family: var(--font-sans);
  background: var(--bg-base);
  color: var(--text-primary);
  line-height: 1.6;
  font-size: 15px;                 /* v1.0 base */
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg, video { display: block; max-width: 100%; height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; cursor: pointer; }
/* Form controls don't inherit the document font by default — make them, so the
   brand family carries into every input/select/textarea site-wide. */
input, select, textarea, optgroup { font-family: inherit; }
ul { list-style: none; }
:where(h1, h2, h3, h4) { line-height: 1.15; font-weight: 700; }

/* ---- TYPE SCALE (v1.0) ---------------------------------- */
.t-display { font-size: clamp(40px, 8vw, 72px); font-weight: 800; letter-spacing: -0.04em; line-height: 1; }
.t-h1      { font-size: clamp(32px, 6vw, 48px); font-weight: 800; letter-spacing: -0.03em; line-height: 1.1; }
.t-h2      { font-size: clamp(28px, 5vw, 36px); font-weight: 700; letter-spacing: -0.025em; line-height: 1.15; }
.t-h3      { font-size: 24px; font-weight: 600; letter-spacing: -0.015em; line-height: 1.3; }
.t-h4      { font-size: 20px; font-weight: 600; letter-spacing: -0.01em; line-height: 1.4; }
.t-body-lg { font-size: 17px; line-height: 1.7; color: var(--text-secondary); }
.t-body    { font-size: 15px; line-height: 1.6; color: var(--text-secondary); }
.t-body-sm { font-size: 13px; line-height: 1.5; color: var(--text-secondary); }
.t-label   { font-size: 11px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); }

/* ---- ACCESSIBILITY UTILITIES ---------------------------- */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: var(--sp-4); top: -100px; z-index: var(--z-skip);
  background: var(--accent-strong); color: #fff; padding: 10px 16px;
  border-radius: var(--radius-md); transition: top var(--dur-fast);
}
.skip-link:focus { top: var(--sp-4); }

a:focus-visible, button:focus-visible, [tabindex]:focus-visible,
input:focus-visible, select:focus-visible, summary:focus-visible {
  outline: 2px solid var(--accent-light); outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  .reveal { opacity: 1 !important; transform: none !important; }
}

/* ---- LAYOUT PRIMITIVES ---------------------------------- */
.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.section { padding-block: var(--section-gap); }
.section--surface { background: var(--bg-surface); }

/* Scroll-reveal (progressively enhanced; visible by default if no JS) */
.reveal { opacity: 0; transform: translateY(16px); transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out); }
.reveal.is-visible { opacity: 1; transform: none; }
.no-js .reveal { opacity: 1; transform: none; }

/* Reusable section header (kicker + h2 + intro) */
.section-header { max-width: 640px; margin-bottom: var(--sp-10); }
.section-header__kicker { display: block; margin-bottom: var(--sp-3); }
.section-header__title { color: var(--text-primary); }
.section-header__intro { margin-top: var(--sp-4); }
.section-header--center { margin-inline: auto; text-align: center; }

/* Progressive-enhancement visibility helpers (reuse the no-js→js swap) */
.js [data-nojs-only]   { display: none !important; }
.no-js [data-js-only]  { display: none !important; }

/* ---- BUTTONS (v1.0) ------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  padding: 12px 24px; border-radius: var(--radius-md); border: none;
  font-size: 14px; font-weight: 600; letter-spacing: 0.01em; white-space: nowrap;
  transition: background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out);
}
.btn-primary   { background: var(--accent-strong); color: #fff; }
.btn-primary:hover { transform: translateY(-1px); box-shadow: var(--shadow-glow); }
.btn-secondary { background: var(--bg-elevated); color: var(--text-primary); border: 1px solid var(--border-default); }
.btn-secondary:hover { border-color: var(--accent); color: var(--accent); transform: translateY(-1px); }
.btn-ghost     { background: transparent; color: var(--text-secondary); border: 1px solid var(--border-subtle); }
.btn-ghost:hover { color: var(--text-primary); border-color: var(--border-default); }
.btn-link      { background: none; padding: 0; color: var(--accent); font-weight: 600; }
.btn-link:hover { color: var(--accent-light); }
.btn-sm  { padding: 8px 16px; font-size: 13px; }
.btn-lg  { padding: 16px 32px; font-size: 15px; }
.btn-full { width: 100%; }

/* ---- BADGES (v1.0, tinted, borderless) ------------------ */
.badge { display: inline-flex; align-items: center; gap: 5px; padding: 3px 10px;
  border-radius: var(--radius-full); font-size: 11px; font-weight: 600; letter-spacing: 0.04em; }
.badge-success { background: rgba(34,197,94,0.12); color: var(--success); }
.badge-blue    { background: var(--accent-soft); color: var(--accent); }
.badge-warning { background: rgba(245,158,11,0.12); color: var(--warning); }
.badge-muted   { background: var(--bg-overlay); color: var(--text-secondary); }
.badge-dot { width: 5px; height: 5px; border-radius: 50%; background: currentColor; }

/* ---- FORM CONTROLS (search / newsletter inputs) --------- */
.field-label { display: block; font-size: 12px; font-weight: 500; color: var(--text-secondary); margin-bottom: 6px; }
.field {
  width: 100%; padding: 12px 16px; background: var(--bg-elevated);
  border: 1px solid var(--border-default); border-radius: var(--radius-md);
  color: var(--text-primary); font-size: 14px; font-family: inherit; outline: none;
  transition: border-color var(--dur-fast);
}
.field::placeholder { color: var(--text-muted); }
.field:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-dim); }

/* Reusable feature-image blend utility (hero/calc/product treatments).
   Light theme: a soft radial mask feathers the photo's gray studio edge into
   the page, with a grounded drop-shadow. No blend mode (that is a dark-bg trick). */
/* Optional feathering utility (not applied to the calculator image, which is shown unedited). */
.media-blend { -webkit-mask-image: radial-gradient(120% 120% at 50% 48%, #000 62%, transparent 100%); mask-image: radial-gradient(120% 120% at 50% 48%, #000 62%, transparent 100%); filter: drop-shadow(0 18px 30px rgba(15,26,51,0.14)); }

/* ============================================================
   COMPONENT: Site header / navbar
   ============================================================ */
.site-header {
  position: sticky; top: 0; z-index: var(--z-nav);
  border-bottom: 1px solid transparent;
  transition: background-color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
}
.site-header.is-scrolled {
  background: rgba(255,255,255,0.85);
  -webkit-backdrop-filter: blur(20px) saturate(1.4); backdrop-filter: blur(20px) saturate(1.4);
  border-bottom-color: var(--border-subtle);
  box-shadow: 0 1px 0 rgba(15,26,51,0.03);
}
.nav { display: flex; align-items: center; gap: var(--sp-10); height: var(--nav-h); }
.nav__logo { display: inline-flex; align-items: center; gap: var(--sp-2); font-size: 16px; font-weight: 800; letter-spacing: -0.02em; color: var(--text-primary); white-space: nowrap; }
.nav__logo span { color: var(--accent); }
/* Scoped under .nav__logo (0,2,0) so WooCommerce's `.woocommerce-page img`
   (0,1,1) can't override the height on cart/checkout/account/shop pages. */
.nav__logo .nav__logo-mark, .nav__logo .custom-logo { height: 30px; width: auto; object-fit: contain; }
.nav__menu { display: flex; gap: var(--sp-8); flex: 1; }

/* Dropdown submenus. The primary menu can contain parent items with children
   (e.g. a "Categories" item); render the children as a hover/focus dropdown in
   the theme's surface style instead of spilling inline into the header bar.
   On mobile (<=600px) they collapse into the off-canvas panel as an indented
   list — see the responsive block below. */
.nav__menu .menu-item-has-children { position: relative; }
.nav__menu .sub-menu {
  position: absolute; top: 100%; left: 0; margin: 0; padding: var(--sp-2);
  min-width: 200px; list-style: none;
  display: flex; flex-direction: column; gap: 2px;
  background: var(--bg-surface); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md); box-shadow: var(--shadow-card);
  opacity: 0; visibility: hidden; transform: translateY(6px);
  transition: opacity var(--dur-fast), transform var(--dur-fast), visibility var(--dur-fast);
  z-index: var(--z-cart);
}
.nav__menu .menu-item-has-children:hover > .sub-menu,
.nav__menu .menu-item-has-children:focus-within > .sub-menu {
  opacity: 1; visibility: visible; transform: translateY(0);
}
.nav__menu .sub-menu a {
  display: block; padding: var(--sp-2) var(--sp-3); border-radius: var(--radius-sm);
  font-size: 14px; color: var(--text-secondary); white-space: nowrap;
  transition: color var(--dur-fast), background-color var(--dur-fast);
}
.nav__menu .sub-menu a:hover { color: var(--text-primary); background: var(--bg-overlay); }
.nav__link {
  position: relative; font-size: 13px; font-weight: 500; color: var(--text-secondary);
  padding-block: 2px; transition: color var(--dur-fast);
}
.nav__link::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -2px; height: 1px;
  background: var(--accent); transform: scaleX(0); transform-origin: left;
  transition: transform var(--dur-base) var(--ease-out);
}
.nav__link:hover, .nav__link[aria-current="page"] { color: var(--text-primary); }
.nav__link:hover::after, .nav__link[aria-current="page"]::after { transform: scaleX(1); }
.nav__actions { display: flex; align-items: center; gap: var(--sp-2); }
.nav__icon {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: var(--radius-sm);
  background: var(--bg-elevated); border: 1px solid var(--border-subtle);
  color: var(--text-secondary); transition: border-color var(--dur-fast), color var(--dur-fast);
}
.nav__icon:hover { border-color: var(--accent); color: var(--accent); }
.nav__icon svg { width: 18px; height: 18px; }
.nav__cart-count {
  position: absolute; top: -4px; right: -4px; min-width: 16px; height: 16px; padding: 0 4px;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent-strong); color: #fff; font-size: 9px; font-weight: 700; border-radius: var(--radius-full);
}
.nav__toggle { display: none; width: 40px; height: 40px; align-items: center; justify-content: center;
  background: var(--bg-elevated); border: 1px solid var(--border-subtle); border-radius: var(--radius-sm); color: var(--text-primary); }
.nav__toggle svg { width: 20px; height: 20px; }
.nav__search { display: flex; gap: var(--sp-2); padding-bottom: var(--sp-4); }
.nav__search[hidden] { display: none; }

/* ============================================================
   PAGE-BUILDER DEFENSE
   The site's Elementor global kit injects
   `.elementor-kit-39 button { padding: 1em 3em }` (specificity 0,1,1) onto
   EVERY <button>, which out-weighs the theme's single-class button rules (0,1,0)
   and inflates icon/utility buttons — the header search/menu icons blew out to
   98px, breaking the mobile header (horizontal overflow). Multi-class buttons
   like `.btn.btn-primary` (0,2,0) already win; re-assert the intended padding on
   the single-class buttons with a parent scope so they hold their size no matter
   what the page builder sets globally.
   ============================================================ */
.nav__actions .nav__icon,
.nav__actions .nav__toggle,
.cart .cart__close,
.gallery__thumbs .gallery__thumb,
#cart .qty button,
.buy-box__buy .qty button,
#cart .cart-applied__remove { padding: 0; }

/* The same kit also sets link COLOUR / SIZE / WEIGHT on every `a` and a
   primary-colour BACKGROUND on every `button` (this is the "blue overlay" behind
   the header search/icon buttons — not an overlay or pseudo-element, just
   Elementor's button background), plus a lighter body weight. On Elementor-
   templated pages (Cart / Checkout / Account / Order-Received) these bleed onto
   the ONE shared site header — turning the wordmark blue/thin and the nav links
   blue/larger. Re-assert the header component's own tokens at a higher
   specificity (scoped under .site-header, 0,2–3,x) so the header is identical on
   every page. Same tokens as the rules above — no duplicated values, no
   !important, no second header. */
.site-header .nav__logo { color: var(--text-primary); font-size: 16px; font-weight: 800; }
.site-header .nav__logo span { color: var(--accent); }
.site-header .nav__link { color: var(--text-secondary); font-size: 13px; font-weight: 500; }
.site-header .nav__link:hover,
.site-header .nav__link[aria-current="page"] { color: var(--text-primary); }
.site-header .nav__actions .nav__icon { background: var(--bg-elevated); border-color: var(--border-subtle); color: var(--text-secondary); }
.site-header .nav__actions .nav__icon:hover { background: var(--bg-elevated); border-color: var(--accent); color: var(--accent); }
.site-header .nav__toggle { background: var(--bg-elevated); border-color: var(--border-subtle); color: var(--text-primary); }

.tabs .tab { padding: 8px 16px; }

#cart .cart-item__remove { padding: 8px; }

/* --- Cart drawer isolation ---
   The drawer markup is printed in the footer of EVERY page, so on the
   Elementor-templated pages (Cart / Checkout / Account / Order-Received) the
   kit's ELEMENT-level rules — `.elementor-kit-39 button|a|h1..h6|input|label`
   (0,1,1) — outrank the drawer's own single-class rules (0,1,0) and repaint it:
   the heading went 17px -> 50px (wrapping the header onto two lines), all 15
   classed buttons took the kit's #0B4E97 primary background with 16px/500
   Oswald type, and the promo field lost its border + radius. The markup is
   byte-identical on every page — this is purely a specificity loss.

   Fixed by re-asserting the drawer's OWN values under the `#cart` id, which
   outranks the kit without !important, in the two tiers the drawer's cascade
   already uses:
     1. element-level reset (1,0,1) — undoes the kit's blanket declarations and
        lets inherited typography flow from the drawer again;
     2. component re-assertion (1,1,0+) — restores each component, same tokens
        and values as its rule further down this file.
   Both tiers are no-ops where the kit isn't loaded, so the homepage / shop /
   product drawers are unchanged. Padding for the close, qty and remove buttons
   is already handled by the rules above; it is not repeated here. */

/* 1 · element-level reset */
/* The kit's own `.elementor-kit-39 {…}` rule (0,1,0) sits on <body> and beats the
   theme's `body` (0,0,1), so the drawer INHERITED the kit's 16px / #404040 /
   1.5em instead of the theme's 15px / --text-primary / 1.6. Because 1.5em
   computes to a fixed 24px on body, every descendant inherited that same 24px
   regardless of its own font-size. Re-assert the theme's body baseline on the
   panel itself (1,0,0) so the whole subtree inherits theme values again — the
   #cart rule further down doesn't declare these three, so nothing is shadowed. */
#cart { font-size: 15px; line-height: 1.6; color: var(--text-primary); }
#cart :is(h1, h2, h3, h4, h5, h6, button, a, input, select, textarea, label) {
  font-family: inherit; letter-spacing: inherit; text-transform: inherit;
}
/* Form controls take `normal` from the UA, not the inherited line-height. */
#cart :is(input, select, textarea) { line-height: normal; }
/* `… label` (0,1,1) also carries its own size/colour, which beat `.sr-only`
   (0,1,0). No visual effect while the label stays clipped, but left alone the
   drawer isn't fully isolated — and any future visible label would inherit it. */
#cart label { font-size: inherit; line-height: inherit; color: inherit; }
#cart button {
  padding: 0; border-radius: 0; background-color: transparent; background-image: none;
  font-size: inherit; font-weight: inherit; line-height: inherit;
}
#cart a { color: inherit; font-size: inherit; font-weight: inherit; line-height: inherit; }

/* 2 · component re-assertion */
#cart .cart__title { font-size: 17px; font-weight: 600; line-height: 1.15; letter-spacing: -0.01em; }
#cart .cart__empty h3 { font-size: 18px; font-weight: 600; line-height: 1.15; }
#cart .cart__close { border-radius: var(--radius-sm); background: var(--bg-elevated); }
#cart .cart-item__remove { border-radius: var(--radius-sm); font-size: 12px; font-weight: 500; }
#cart .cart-applied__remove { font-size: 12px; }
#cart .field {
  padding: 12px 16px; border: 1px solid var(--border-default); border-radius: var(--radius-md);
  font-size: 14px; color: var(--text-primary);
}
#cart .btn { padding: 12px 24px; border-radius: var(--radius-md); font-size: 14px; font-weight: 600; letter-spacing: 0.01em; }
#cart .btn-lg { padding: 16px 32px; font-size: 15px; }
#cart .cart-checkout .btn { padding: 14px 32px; font-size: 16px; }
#cart .btn-primary { background: var(--accent-strong); color: #fff; }
#cart .btn-secondary { background: var(--bg-elevated); color: var(--text-primary); border: 1px solid var(--border-default); }

/* The kit also restyles :hover/:focus (`… button:hover` 0,1,2 sets its accent
   colour and `border-style:none`). Re-assert only on the components that
   actually carry a border — forcing a style onto the border-less qty steppers
   would give them a 3px medium border on hover. */
#cart .cart__close:hover, #cart .cart__close:focus { border-style: solid; border-color: var(--accent); color: var(--accent); }
#cart .btn-secondary:hover { border-style: solid; border-color: var(--accent); color: var(--accent); }
#cart .cart-item__remove:hover { color: var(--danger); }
#cart .cart-applied__remove:hover { color: var(--text-primary); }

@media (max-width: 520px) {
  #cart .cart__title { font-size: 16px; }
}

/* --- Typography ---
   On cart/checkout/search the Elementor kit stylesheet loads and applies
   `.elementor-kit-39 h1..h6` (0,1,1) with its own global font sizes, overriding
   the theme's heading utilities and WooCommerce block headings — footer column
   titles and the cart's block headings ballooned to 50px. Re-assert the theme
   scale with selectors that outrank the kit: the doubled-class trick (0,2,0) for
   utilities and the `#content` id scope (1,0,x) for WooCommerce content. */
.footer__col-title.footer__col-title { font-size: 11px; }
.t-h1.t-h1 { font-size: clamp(32px, 6vw, 48px); }
.t-h2.t-h2 { font-size: clamp(28px, 5vw, 36px); }
.t-h3.t-h3 { font-size: 24px; }
#content .wp-block-heading { font-size: clamp(24px, 4vw, 32px); }
#content .cart_totals h2,
#content #order_review_heading,
#content .woocommerce-checkout-review-order h3 { font-size: 20px; }

/* --- WooCommerce block buttons ---
   The Cart/Checkout pages use WooCommerce Blocks, and the theme's woocommerce.css
   doesn't load there (those pages aren't registered as WC cart/checkout, so
   is_cart()/is_checkout() are false). This lives in base.css so it always applies.
   The cart "Proceed to Checkout" and cross-sell "Add to cart" buttons render as
   <a> with `.wp-element-button`, so Elementor's `.elementor-kit-39 a` paints their
   text blue over the white and they fall back to core's dark default background
   (`:root :where(.wp-element-button){background:#32373c}`). Re-assert the theme's
   primary-button look; specificity 0,2,0 outranks both. */
.wc-block-cart__submit-button.wp-element-button,
.wc-block-components-product-button__button.wp-element-button {
  background-color: var(--accent);
  color: #fff;
}
.wc-block-cart__submit-button.wp-element-button:hover,
.wc-block-components-product-button__button.wp-element-button:hover {
  background-color: var(--accent-strong);
  color: #fff;
}

/* The block cart/checkout render full-bleed while the rest of the site sits in a
   max-width container; align them to the same content width + gutters so the
   layout lines up with the header and footer. */
.wp-block-woocommerce-cart,
.wp-block-woocommerce-checkout {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* --- Login-With-Phone scroll-lock (mobile checkout dead-button fix) ---
   The "Login With Phone Number" plugin bundles intl-tel-input, whose
   intlTelInput.min.css ships `body.iti-mobile { position: fixed !important;
   overflow: hidden !important; width:100% !important; height:100% !important }`.
   That lock is only meant to hold while the phone-field country picker's
   fullscreen popup is open, but the library stamps `.iti-mobile` on <body>
   PERMANENTLY the moment it initialises on a mobile viewport (it inits on the
   checkout billing-phone field). Result: the entire mobile checkout was frozen —
   the page couldn't scroll, so the "Place Order" button below the fold was
   unreachable. Re-assert normal document flow (specificity beats the plugin's
   0,1,1; both !important) and yield while the theme's own cart drawer is
   intentionally locking scroll (.dice-cart-open).

   Applied wherever the class appears (the only exception is while the theme's own
   cart drawer is intentionally locking scroll, .dice-cart-open). The lock has NO
   legitimate purpose here — the library stamps .iti-mobile on <body> permanently,
   not just while the country picker is open — and it silently breaks every
   scroll-dependent mobile flow:
     · checkout — the "Place Order" button sits far below the fold;
     · the /welcome/ Instagram phone-signup landing page;
     · and, most importantly, the phone-LOGIN / OTP verification itself: after you
       submit your number the reCAPTCHA + code-entry step appears below the fold,
       and the frozen page can't scroll to it — so phone verification "only works
       on a computer" (desktop has no .iti-mobile lock). Unlocking scroll does not
       disable or alter the phone login; it only lets the page scroll so the code
       step is reachable. Worst case is the rarely-used fullscreen country picker
       letting the background scroll behind it — a cosmetic trade we accept to keep
       mobile checkout AND mobile login actually usable. */
body.iti-mobile:not(.dice-cart-open) {
  position: static !important;
  top: auto !important;
  left: auto !important;
  width: auto !important;
  height: auto !important;
  overflow: visible !important;
}

/* ============================================================
   COMPONENT: Announcement bar (admin-editable via Theme Settings)
   ============================================================ */
.announcement-bar { background: var(--bg-surface); border-bottom: 1px solid var(--border-subtle); }
.announcement-bar__inner { display: flex; align-items: center; justify-content: center; gap: var(--sp-2); padding-block: var(--sp-2); text-align: center; }
.announcement-bar__text { font-size: 12px; font-weight: 500; letter-spacing: 0.02em; color: var(--text-secondary); }
.announcement-bar__text a { color: var(--accent); font-weight: 600; }

/* ============================================================
   COMPONENT: Promo banner — the cobalt announcement band.
   Site-wide (hence base.css, not home.css): the homepage renders the sale
   offer + the research-use notice beneath it; every other page renders the
   `--notice` variant carrying the notice alone. One component, one gradient.
   Full-bleed band; content constrained by .container.
   ============================================================ */
.promo-banner {
  background: linear-gradient(120deg, var(--accent-strong) 0%, var(--accent) 52%, var(--accent-light) 100%);
  color: #fff;
  overflow: hidden;
}
/* --- Marquee (homepage sale strip) -------------------------------------
   Slim full-bleed band whose track holds SIX identical copies of the offer.
   The animation translates the track by exactly one copy — calc(-100% / 6),
   where 100% is the track's own width — so copy 2 lands precisely where copy 1
   began and the loop is seamless with no jump or gap. Six copies also
   guarantee the strip spans very wide viewports at all times.
   If you change the repeat count in front-page.php, change the 6 here too. */
.promo-marquee {
  height: 38px;
  display: flex; align-items: center;
  overflow: hidden;
}
.promo-marquee__track {
  display: flex; align-items: center;
  width: max-content;
  will-change: transform;
  animation: promo-marquee-scroll 22s linear infinite;
}
/* NOTE: deliberately a block, not a flex container. As a flex parent it would
   treat the <b>SUMMER30</b> as a flex item and drop the whitespace either side
   of it ("USE CODESUMMER30"). Block layout keeps the line as normal inline text
   so the spaces survive; the track's align-items centres it vertically. */
.promo-marquee__group {
  display: block; flex: 0 0 auto;
  white-space: nowrap;                 /* one unbroken line — never wraps mid-scroll */
  padding-inline-end: var(--sp-6);     /* gap between repeats; part of the copy width */
  font-size: 12.5px; font-weight: 600; line-height: 1;
  letter-spacing: 0.07em; text-transform: uppercase;
}
.promo-marquee__hl { color: #FFD25A; font-weight: 800; letter-spacing: 0.09em; }
@keyframes promo-marquee-scroll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(calc(-100% / 6), 0, 0); }
}
/* Pause while hovered or held — pointer devices only, so a tap on a phone
   never freezes the strip. */
@media (hover: hover) and (pointer: fine) {
  .promo-marquee:hover  .promo-marquee__track,
  .promo-marquee:active .promo-marquee__track { animation-play-state: paused; }
}
/* The band now holds only the marquee — the compliance notice moved out to its
   own neutral strip below (.research-notice). */
/* ============================================================
   COMPONENT: Research-use compliance notice
   Sits on the page background with no band or box, so it reads as fine print
   rather than a second promotion — but stays legible (AA on --bg-base) because
   it is a payment-processor requirement. Hairline rule separates it from the
   content below. Static: never animated.
   ============================================================ */
.research-notice { border-bottom: 1px solid var(--border-subtle); }
/* The partial always prints both wordings and exactly one is ever displayed, so
   screen readers announce a single notice — never both.
   The CONDENSED one-row variant ("Research Use Only • Not for human or animal
   consumption.") is the site-wide default, on every template and every width:
   the full sentence pair wrapped to two rows on phones, and one slim centred
   row reclaims that height everywhere without weakening the notice — the
   operative sentence is carried verbatim and only the leading clause is
   shortened (see dice_research_notice_short() in inc/helpers.php). */
.research-notice__full { display: none; }
.research-notice__compact { display: inline; }
.research-notice__text {
  margin: 0;
  padding-block: 7px;
  text-align: center;
  font-size: 13px; line-height: 1.45;
  font-weight: 500; letter-spacing: 0.01em;
  color: var(--text-secondary);
  text-wrap: balance;
}
/* Phones: a slightly shorter strip and tighter type, so the band stays slim
   without crowding the copy. Same colours and content as desktop. */
@media (max-width: 600px) {
  .promo-marquee { height: 34px; }
  .promo-marquee__group {
    font-size: 11.5px; letter-spacing: 0.06em;
    padding-inline-end: var(--sp-5);
  }
  /* The condensed line still needs ~355px at 12.5px but only ~335px is
     available at 390px, so it wrapped anyway. Reclaim this band's side gutters
     (this container only, never the page's) and scale the type with the
     viewport, floored at 10px so it stays legible on the narrowest phone. The
     component's 0.01em tracking costs ~5.5px across this 55-character line —
     more than the 3.6px it overflowed by at 320px — so it is dropped here.
     MEASURED: one line from 320px up. Wrapping is still deliberately allowed
     (a longer translation should wrap, never overflow or truncate). */
  .research-notice .container { padding-inline: 8px; }
  .research-notice__text {
    padding-block: 6px;
    font-size: clamp(10px, 3.1vw, 12.5px);
    letter-spacing: normal;
  }
}
/* Reduced motion: stop the scroll entirely and show ONE static, centred copy.
   Height is released and the line is allowed to wrap so the full message stays
   readable — and unclipped — even on a narrow phone. */
@media (prefers-reduced-motion: reduce) {
  .promo-marquee { height: auto; min-height: 38px; }
  .promo-marquee__track { animation: none; width: 100%; justify-content: center; }
  .promo-marquee__group:not(:first-child) { display: none; }
  .promo-marquee__group {
    /* Undo the scrolling flex sizing: the copy MUST be allowed to shrink here,
       otherwise flex: 0 0 auto pins it to its max-content width and the line
       runs off a narrow screen instead of wrapping. */
    flex: 1 1 auto; min-width: 0;
    white-space: normal; text-align: center;
    padding: var(--sp-2) var(--sp-4);
  }
}

/* ============================================================
   SECTION: Trust strip (shared: homepage + product page)
   ============================================================ */
.trust-strip { border-block: 1px solid var(--border-subtle); }
.trust-strip__list { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: var(--sp-4) var(--sp-8); padding-block: var(--sp-6); }
.trust-strip__item { display: inline-flex; align-items: center; gap: var(--sp-2); }
.trust-strip__item svg { width: 16px; height: 16px; color: var(--accent); }

/* ============================================================
   COMPONENT: Product grid + card (reusable)
   ============================================================ */
.product-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-6); }
.product-grid--4 { grid-template-columns: repeat(4, 1fr); }
.grid-cta { margin-top: var(--sp-8); text-align: center; }

.product-card {
  position: relative; display: flex; flex-direction: column;
  background: var(--bg-surface); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg); overflow: hidden;
  transition: transform var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.product-card:hover { transform: translateY(-4px); border-color: var(--accent); box-shadow: var(--shadow-hover); }
/* STANDARDIZED STUDIO RENDER — light theme. The Dice product photos are shot on a
   neutral-gray studio background; the render sits on a white well and a soft radial
   mask feathers the photo's gray edge into the card. The vial is zoomed to lead the
   card. Same framing/scale everywhere so every product reads as one studio. Card
   chrome (surface, border, radius, shadow, padding) is unchanged. */
.product-card__media { position: relative; aspect-ratio: 1; overflow: hidden; display: flex; align-items: center; justify-content: center; background: var(--bg-surface); }
.product-card__media img { width: 100%; height: 100%; object-fit: cover; object-position: center center; transform: scale(1.18); transform-origin: center center; -webkit-mask-image: radial-gradient(74% 84% at 50% 48%, #000 60%, transparent 100%); mask-image: radial-gradient(74% 84% at 50% 48%, #000 60%, transparent 100%); transition: transform var(--dur-slow) var(--ease-out); }
.product-card:hover .product-card__media img { transform: scale(1.22); }
.product-card__flag { position: absolute; top: 12px; left: 12px; }
.product-card__body { display: flex; flex-direction: column; padding: var(--sp-4); flex: 1; }
.product-card__stars { color: var(--warning); font-size: 12px; margin-top: var(--sp-2); position: relative; z-index: 1; }   /* amber = semantic rating (v1.0); below price, above the hover Quick-Add */
.product-card__stars .count { color: var(--text-muted); }
.product-card__name { font-size: 15px; font-weight: 600; color: var(--text-primary); }
.product-card__name a { text-decoration: none; }
.product-card__name a::after { content: ''; position: absolute; inset: 0; }  /* stretched link → whole card focusable/clickable */
.product-card__name a:focus-visible { outline: none; }
.product-card:has(.product-card__name a:focus-visible) { outline: 2px solid var(--accent-light); outline-offset: 2px; }
.product-card__stock { margin-top: var(--sp-1); }
.product-card__price { margin-top: var(--sp-2); font-size: 17px; font-weight: 700; color: var(--accent); }
.product-card__price del { color: var(--text-muted); font-weight: 400; font-size: 14px; margin-right: 6px; }
.product-card__price ins { text-decoration: none; background: transparent; }  /* sale price = accent blue, same size/weight, no underline */
.product-card__action { margin-top: var(--sp-3); position: relative; z-index: 2; opacity: 0; transition: opacity var(--dur-fast); }
.product-card:hover .product-card__action,
.product-card:focus-within .product-card__action { opacity: 1; }

/* ============================================================
   COMPONENT: Breadcrumb (shared — shop archive, product, etc.)
   ============================================================ */
.breadcrumb { padding-top: var(--sp-6); }
.breadcrumb__list { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); font-size: 13px; color: var(--text-muted); }
.breadcrumb__link { color: var(--text-secondary); transition: color var(--dur-fast); }
.breadcrumb__link:hover { color: var(--accent); }
.breadcrumb__sep { color: var(--text-muted); user-select: none; }
.breadcrumb__current { color: var(--text-primary); }

/* ============================================================
   COMPONENT: Tabs (Explore filter / product jump-nav)
   ============================================================ */
/* flex-wrap lets a long pill group (e.g. the homepage "Find your compound" and
   FAQ category tabs) wrap onto a second row on narrow screens instead of
   overflowing the viewport and causing a left/right scroll. No effect on wide
   screens where the tabs fit in one row. The shop keeps its own scroll behavior
   via `.shop-cats .tabs { flex-wrap: nowrap }`. */
.tabs { display: inline-flex; flex-wrap: wrap; gap: 4px; background: var(--bg-elevated); padding: 4px; border-radius: var(--radius-md); margin-bottom: var(--sp-8); }
.tab { padding: 8px 16px; border: none; background: transparent; border-radius: var(--radius-sm);
  font-size: 13px; font-weight: 500; color: var(--text-secondary); transition: background-color var(--dur-fast), color var(--dur-fast); }
.tab[aria-pressed="true"] { background: var(--bg-overlay); color: var(--text-primary); }
.tab[aria-pressed="false"]:hover { color: var(--text-primary); }
.product-card.is-hidden { display: none; }

/* ============================================================
   COMPONENT: Lab testing / COA cards
   ============================================================ */
.coa-card {
  display: flex; flex-direction: column; gap: var(--sp-3);
  background: var(--bg-surface); border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg); padding: var(--sp-5);
  transition: transform var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.coa-card:hover { transform: translateY(-4px); border-color: var(--accent); box-shadow: var(--shadow-hover); }
.coa-card__thumb { position: relative; aspect-ratio: 3/2; overflow: hidden; display: flex; align-items: center; justify-content: center;
  background: var(--bg-elevated); border-radius: var(--radius-md); color: var(--text-muted);
  font-size: 11px; font-weight: 500; letter-spacing: 0.05em; }
.coa-card__thumb-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: top center; opacity: 0.8; }
.coa-card__thumb::after { content: ''; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(255,255,255,0.10), rgba(15,26,51,0.10)); pointer-events: none; }
.coa-card__name { font-size: 14px; font-weight: 600; color: var(--text-primary); }
.coa-card__purity { display: flex; align-items: center; gap: 6px; }
.coa-card__bar { flex: 1; height: 3px; background: var(--border-default); border-radius: var(--radius-full); overflow: hidden; }
.coa-card__fill { height: 100%; background: var(--success); border-radius: var(--radius-full); }
.coa-card__pct { font-size: 12px; font-weight: 700; color: var(--success); }
.coa-card__meta { font-size: 11px; color: var(--text-muted); }
.coa-card__actions { display: flex; gap: var(--sp-2); margin-top: auto; }

/* ============================================================
   COMPONENT: FAQ accordion (shared: homepage + product + FAQ page)
   ============================================================ */
.faq { max-width: 720px; }
.accordion__item { border-bottom: 1px solid var(--border-subtle); }
.accordion__trigger {
  width: 100%; display: flex; justify-content: space-between; align-items: center; gap: var(--sp-4);
  padding: var(--sp-4) 0; background: none; border: none; text-align: left;
  font-size: 15px; font-weight: 500; color: var(--text-primary); transition: color var(--dur-fast);
}
.accordion__trigger:hover { color: var(--accent); }
.accordion__icon { flex-shrink: 0; width: 20px; height: 20px; border-radius: 50%; border: 1px solid var(--border-default);
  display: flex; align-items: center; justify-content: center; color: var(--text-secondary);
  transition: border-color var(--dur-fast), color var(--dur-fast), transform var(--dur-fast); }
.accordion__trigger:hover .accordion__icon { border-color: var(--accent); color: var(--accent); }
.accordion__trigger[aria-expanded="true"] .accordion__icon { transform: rotate(45deg); }
.accordion__panel { overflow: hidden; }
.accordion__panel[hidden] { display: none; }
.accordion__panel-inner { padding-bottom: var(--sp-4); font-size: 14px; color: var(--text-secondary); line-height: 1.7; }

/* ============================================================
   COMPONENT: Pre-footer CTA band
   ============================================================ */
.cta-band { text-align: center; }
.cta-band__title { color: var(--text-primary); }
.cta-band__actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); justify-content: center; margin-top: var(--sp-8); }

/* ============================================================
   COMPONENT: Footer
   ============================================================ */
.site-footer { background: var(--bg-surface); border-top: 1px solid var(--border-subtle); padding-block: var(--sp-12) var(--sp-8); }
.footer__grid { display: grid; grid-template-columns: 2fr 1fr 1fr 1fr; gap: var(--sp-10); margin-bottom: var(--sp-10); }
.footer__logo { font-size: 18px; font-weight: 800; color: var(--text-primary); margin-bottom: var(--sp-3); }
.footer__logo span { color: var(--accent); }
.footer__tagline { font-size: 13px; color: var(--text-secondary); line-height: 1.7; max-width: 260px; }
.footer__col-title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-muted); margin-bottom: var(--sp-4); }
.footer__col li { list-style: none; }
.footer__link { display: block; font-size: 13px; color: var(--text-secondary); margin-bottom: 10px; transition: color var(--dur-fast); }
.footer__link:hover { color: var(--text-primary); }
.footer__bottom { display: flex; justify-content: space-between; align-items: center; gap: var(--sp-4);
  padding-top: var(--sp-6); border-top: 1px solid var(--border-subtle); font-size: 12px; color: var(--text-muted); }
.footer__social { display: flex; gap: var(--sp-3); margin-top: var(--sp-4); }
.footer__social a { color: var(--text-muted); transition: color var(--dur-fast); }
.footer__social a:hover { color: var(--accent); }
.footer__social svg { width: 18px; height: 18px; }

/* ============================================================
   RESPONSIVE (global / shared components)
   ============================================================ */
@media (max-width: 900px) {
  :root { --section-gap: var(--sp-16); --gutter: var(--sp-5); }
  .product-grid, .product-grid--4 { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 600px) {
  .product-grid, .product-grid--4 { grid-template-columns: 1fr; }
  .footer__grid { grid-template-columns: 1fr 1fr; }
  .footer__bottom { flex-direction: column; align-items: flex-start; }

  /* Phone rhythm: tighter vertically, unchanged horizontally. Generous side
     gutters are what keep it feeling premium — it's the dead vertical space
     between sections that reads as unfinished, so only that is reduced. */
  :root { --section-gap: var(--sp-10); }   /* was 64px on phones */

  /* Slightly shorter cards: trim the body padding and close the gap under the
     price. The media, type scale and button are untouched. */
  .product-card__body { padding: var(--sp-3) var(--sp-4) var(--sp-4); }
  .product-card__action { margin-top: var(--sp-3); }

  /* On phones the primary menu is off-canvas (position:fixed → out of flow),
     leaving only the logo + icon actions in the nav's flex row. Without a spacer
     the desktop 40px gap sat *between* them and pushed the actions toward the
     screen edge, wasting space and — on very narrow phones — shoving the last
     icon (menu toggle) off-screen. Anchor the two groups to opposite ends and
     drop the gap to a small minimum so the row always fits and reads as an
     intentional logo-left / actions-right header. */
  .nav { justify-content: space-between; gap: var(--sp-4); }

  /* Mobile nav: hide inline menu, show toggle + drawer */
  .nav__menu {
    position: fixed; inset: var(--nav-h) 0 auto 0; z-index: var(--z-drawer);
    flex-direction: column; gap: 0; background: var(--bg-surface);
    border-bottom: 1px solid var(--border-subtle); padding: var(--sp-4) var(--sp-5);
    transform: translateY(-12px); opacity: 0; pointer-events: none;
    transition: opacity var(--dur-fast), transform var(--dur-fast);
  }
  .nav__menu.is-open { transform: none; opacity: 1; pointer-events: auto; }
  .nav__link { padding: var(--sp-3) 0; font-size: 15px; }
  /* In the vertical drawer the sliding underline would bleed onto the next
     item; show the active/current item with weight + colour instead. */
  .nav__menu .nav__link::after { display: none; }
  .nav__menu .nav__link[aria-current="page"] { font-weight: 700; }
  .nav__toggle { display: inline-flex; }

  /* Submenus expand inline (indented) inside the off-canvas panel rather than
     floating as a dropdown. */
  .nav__menu .sub-menu {
    position: static; opacity: 1; visibility: visible; transform: none;
    min-width: 0; padding: 0 0 var(--sp-2) var(--sp-4);
    background: transparent; border: none; box-shadow: none;
  }
  .nav__menu .sub-menu a { padding: var(--sp-2) 0; white-space: normal; }
}

/* Touch devices: enforce 44px minimum targets (v1.0) */
@media (pointer: coarse) {
  .btn-sm { min-height: 44px; }
  .nav__icon { width: 44px; height: 44px; }
  .tab { min-height: 44px; }
  .product-card__action { opacity: 1; }  /* Quick Add always visible on touch */
}

/* ---- NARROW PHONES (≤370px: iPhone SE-and-below width class, small Androids) --
   The header carries a wordmark logo + four 44px touch targets. That set fits
   375px and up (see the space-between rule above) but not the 320–360px class,
   where it would overflow and clip the menu toggle. Tighten the header — and
   only the header — so it fits down to 320px: trim the header's own inline
   padding (scoped to .site-header so cart/checkout/product containers keep the
   normal gutter), ease the wordmark, collapse the icon gap, and step the icon
   targets from 44px to 36px (a deliberate, contained trade at this sub-iPhone
   width — still a usable tap target; every listed iPhone is ≥375px and keeps
   the full-size header). Placed AFTER the pointer:coarse block so it wins. */
@media (max-width: 370px) {
  .site-header .container { padding-inline: var(--sp-3); }   /* 12px header inset (scoped, not the global gutter) */
  .nav { gap: var(--sp-2); }
  /* Pin the wordmark so flex never shrinks it below its content width — that was
     truncating "Dice Peptides" at 320px. Ease its footprint slightly instead. */
  .nav__logo { flex-shrink: 0; }
  .site-header .nav__logo { font-size: 14px; }
  .nav__logo .nav__logo-mark,
  .nav__logo .custom-logo { height: 24px; }
  .nav__actions { gap: var(--sp-1); }
  .nav__icon,
  .nav__toggle { width: 36px; height: 36px; }
}

/* ============================================================
   SLIDE-OUT CART DRAWER  (matches cart-preview.html)
   Site-wide mini-cart. Slides in from the right over a blurred
   overlay. Structure: header · scrollable body · pinned footer.
   Arrangement-only — every value resolves to a v1.0 token.
   ============================================================ */
body.dice-cart-open { overflow: hidden; }

/* Overlay — ink scrim + blurred, fades in/out */
.cart-overlay {
  position: fixed; inset: 0; z-index: var(--z-cart-overlay);
  background: rgba(15,26,51,0.45);
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  opacity: 0; visibility: hidden;
  transition: opacity var(--dur-base) var(--ease-out), visibility var(--dur-base) var(--ease-out);
}
.cart-overlay.is-open { opacity: 1; visibility: visible; }

/* Panel — slides in from the right. Scoped to #cart so it never collides
   with WooCommerce's generic form.cart / div.cart elements. */
#cart {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: var(--z-cart);
  width: min(var(--cart-w), 100vw);
  display: flex; flex-direction: column;
  background: var(--bg-surface); border-left: 1px solid var(--border-subtle);
  box-shadow: -12px 0 48px rgba(15,26,51,0.18);
  transform: translateX(100%);
  transition: transform var(--dur-base) var(--ease-out); will-change: transform;
}
#cart.is-open { transform: translateX(0); }
.cart__inner { display: contents; }
/* Loading state is VISUAL ONLY — concurrency is guarded by the single-flight
   JS lock (see request() in dice.js), never by blocking pointer events (a stuck
   class must never be able to freeze the controls). */
#cart.is-loading .cart__body { opacity: 0.6; transition: opacity var(--dur-fast); }
/* Affected control while its own request is in flight (queue keeps absorbing
   clicks; this just signals "working" and blocks a repeat on the same control). */
#cart [aria-busy="true"] { cursor: progress; opacity: 0.6; }

/* 1 · HEADER */
.cart__header {
  flex-shrink: 0; display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-5) var(--sp-6); border-bottom: 1px solid var(--border-subtle);
}
.cart__title { font-size: 17px; font-weight: 600; letter-spacing: -0.01em; color: var(--text-primary); }
.cart__count { font-size: 13px; font-weight: 600; color: var(--accent); background: var(--accent-dim); border-radius: var(--radius-full); padding: 2px 9px; }
.cart__close {
  margin-left: auto; display: inline-flex; align-items: center; justify-content: center;
  width: 36px; height: 36px; border-radius: var(--radius-sm);
  background: var(--bg-elevated); border: 1px solid var(--border-subtle); color: var(--text-secondary);
  transition: border-color var(--dur-fast), color var(--dur-fast), transform var(--dur-fast);
}
.cart__close:hover { border-color: var(--accent); color: var(--accent); }
.cart__close:active { transform: scale(0.94); }
.cart__close svg { width: 18px; height: 18px; }

/* Scrollable body */
.cart__body {
  flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain;
  padding: var(--sp-5) var(--sp-6); display: flex; flex-direction: column; gap: var(--sp-6);
}
.cart__section-label { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-4); }
.cart__section-label .t-label { white-space: nowrap; }
.cart__section-label::after { content: ''; flex: 1; height: 1px; background: var(--border-subtle); }

/* 2 · CART ITEM */
.cart__items { display: flex; flex-direction: column; }
.cart-item {
  display: grid; grid-template-columns: 72px 1fr; gap: var(--sp-4);
  padding: var(--sp-5) 0; border-bottom: 1px solid var(--border-subtle);
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.cart-item:first-child { padding-top: 0; }
/* No card behind the vial — the product image sits directly on the drawer
   background and is the visual element (enlarged ~13% to stay prominent). */
.cart-item__media {
  position: relative; width: 72px; height: 72px;
  display: flex; align-items: center; justify-content: center;
}
.cart-item__media img { width: auto; height: auto; max-width: 94%; max-height: 94%; object-fit: contain; }
.cart-item__main { display: flex; flex-direction: column; min-width: 0; }
.cart-item__top { display: flex; align-items: flex-start; gap: var(--sp-3); }
.cart-item__name { font-size: 15px; font-weight: 600; color: var(--text-primary); line-height: 1.3; }
/* Purchased configuration ("10 mg • 3 Vials (5% Off)") — one secondary line
   under the product title; the title stays the primary text. */
.cart-item__config { font-size: 12.5px; font-weight: 500; color: var(--text-muted); line-height: 1.35; margin-top: 2px; }
.cart-item__unit { margin-left: auto; text-align: right; flex-shrink: 0; }
.cart-item__price { font-size: 15px; font-weight: 700; color: var(--text-primary); }
/* Quantity row pulled up close to the name (no large gap after removing meta). */
.cart-item__bottom { display: flex; align-items: center; gap: var(--sp-3); margin-top: 8px; }

/* Quantity selector (scoped so the drawer never depends on product.css) */
#cart .qty { display: inline-flex; align-items: center; border: 1px solid var(--border-default); border-radius: var(--radius-md); background: var(--bg-elevated); overflow: hidden; flex-shrink: 0; transition: border-color var(--dur-fast); }
#cart .qty:focus-within { border-color: var(--accent); }
#cart .qty button { width: 32px; height: 32px; color: var(--text-primary); font-size: 16px; line-height: 1; border: none; background: none; transition: color var(--dur-fast), background-color var(--dur-fast); }
#cart .qty button:hover { color: var(--accent); background: var(--bg-overlay); }
#cart .qty button:active { background: var(--accent-dim); }
#cart .qty button:disabled { color: var(--text-muted); cursor: not-allowed; background: none; }
#cart .qty input { width: 34px; height: 32px; text-align: center; border: none; border-inline: 1px solid var(--border-default); background: none; color: var(--text-primary); font-size: 14px; font-weight: 600; font-family: inherit; outline: none; -moz-appearance: textfield; }
#cart .qty input::-webkit-outer-spin-button, #cart .qty input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* Remove button */
.cart-item__remove { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 500; color: var(--text-muted); padding: 8px; border: none; background: none; border-radius: var(--radius-sm); transition: color var(--dur-fast), background-color var(--dur-fast); }
.cart-item__remove:hover { color: var(--danger); background: rgba(239,68,68,0.08); }
.cart-item__remove svg { width: 15px; height: 15px; }

/* Non-blocking failure notice (e.g. a coupon couldn't be applied). */
.cart-toast { display: flex; align-items: center; gap: 8px; margin-top: var(--sp-3); padding: 10px 14px; border-radius: var(--radius-md); background: rgba(239,68,68,0.10); border: 1px solid rgba(239,68,68,0.28); color: var(--danger); font-size: 12px; font-weight: 500; line-height: 1.4; opacity: 0; transform: translateY(-4px); transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out); }
.cart-toast.is-shown { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .cart-toast { transition: none; } }

/* 4 · PROMO CODE */
.cart-promo { display: flex; gap: var(--sp-2); }
.cart-promo .field { flex: 1; }
.cart-applied { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3); margin-top: var(--sp-3); padding: 10px 14px; background: rgba(34,197,94,0.12); border: 1px solid rgba(34,197,94,0.3); border-radius: var(--radius-md); font-size: 13px; color: var(--success); font-weight: 600; }
.cart-applied__remove { font-size: 12px; color: var(--text-secondary); border: none; background: none; transition: color var(--dur-fast); }
.cart-applied__remove:hover { color: var(--text-primary); }
.cart-promo__msg { margin-top: var(--sp-3); font-size: 12px; color: var(--text-secondary); }
.cart-promo__msg[data-error] { color: var(--danger); }

/* Pinned footer — compact vertical rhythm so the cart items stay the focus.
   Only spacing + the two requested size tweaks change here; no colors,
   type hierarchy, structure or behavior are altered. */
.cart__footer {
  flex-shrink: 0; border-top: 1px solid var(--border-subtle); background: var(--bg-surface);
  padding: var(--sp-3) var(--sp-6) calc(var(--sp-3) + env(safe-area-inset-bottom));
}

/* 5 · ORDER SUMMARY */
.cart-totals { display: flex; flex-direction: column; gap: 5px; margin-bottom: 8px; }
.cart-line { display: flex; align-items: center; justify-content: space-between; font-size: 13px; line-height: 1.25; color: var(--text-secondary); }
.cart-line dt { color: inherit; } .cart-line dd { margin: 0; }
.cart-line__val { color: var(--text-primary); font-weight: 500; }
.cart-line--free .cart-line__val { color: var(--success); }
.cart-grand { display: flex; align-items: baseline; justify-content: space-between; margin-top: 7px; padding-top: 7px; border-top: 1px solid var(--border-default); }
.cart-grand__label { font-size: 14px; font-weight: 600; line-height: 1.2; color: var(--text-primary); }
.cart-grand__label small { display: block; font-size: 11px; font-weight: 400; color: var(--text-muted); margin-top: 1px; }
.cart-grand__amount { font-size: 20px; font-weight: 800; line-height: 1.1; letter-spacing: -0.02em; color: var(--accent); }

/* Shipping note — compact status bar (half the vertical padding), same styling */
.cart-shipnote { display: flex; gap: var(--sp-3); align-items: flex-start; margin-bottom: 8px; padding: 6px var(--sp-4); background: var(--bg-elevated); border: 1px solid var(--border-subtle); border-radius: var(--radius-md); }
.cart-shipnote__icon { flex-shrink: 0; width: 18px; height: 18px; color: var(--accent); margin-top: 1px; }
.cart-shipnote__text { font-size: 12px; line-height: 1.45; color: var(--text-secondary); }
.cart-shipnote__text strong { color: var(--text-primary); font-weight: 600; }
.cart-shipnote__text b { color: var(--success); font-weight: 600; }

/* 6 · CHECKOUT CTA */
.cart-checkout .btn { font-size: 16px; padding: 14px 32px; }
.cart-checkout__sub { display: flex; align-items: center; justify-content: center; gap: 6px; margin-top: var(--sp-2); font-size: 11px; line-height: 1.3; color: var(--text-muted); }
.cart-checkout__sub svg { width: 12px; height: 12px; color: var(--success); }

/* 7 · PAYMENT METHODS — collapsible footer strip (native <details>, starts
   collapsed). Compact: minimal margin/padding so it reads as a footer line,
   not a section. The <summary> is the "We Accept" toggle; pills reveal on open. */
.cart-pay { margin-top: 3px; padding-top: 2px; border-top: 1px solid var(--border-subtle); text-align: center; }
/* display:flex (not inline-flex) so the summary doesn't inherit the parent's
   1.6 line-box strut — that phantom height is what made the collapsed row tall. */
.cart-pay__label { display: flex; align-items: center; justify-content: center; gap: 5px; cursor: pointer; list-style: none; user-select: none; font-size: 10px; font-weight: 600; line-height: 1; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); transition: color var(--dur-fast) var(--ease-out); }
.cart-pay__label::-webkit-details-marker { display: none; }
.cart-pay__label:hover { color: var(--text-secondary); }
.cart-pay__chevron { width: 12px; height: 12px; transition: transform var(--dur-base) var(--ease-out); }
.cart-pay[open] .cart-pay__chevron { transform: rotate(180deg); }
/* Explicit display toggle: an author `display` on the toggled child would beat the
   UA `details:not([open]) > * { display:none }` rule and leak the pills into the
   collapsed state — so hide by default and only flex when open. */
.cart-pay__list { display: none; align-items: center; justify-content: center; gap: 5px; flex-wrap: wrap; margin-top: 4px; }
.cart-pay[open] .cart-pay__list { display: flex; }
.cart-pay__chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 11px; line-height: 1.2; background: var(--bg-elevated); border: 1px solid var(--border-subtle); border-radius: var(--radius-full); font-size: 12px; font-weight: 600; color: var(--text-secondary); }
.cart-pay__chip svg { width: 14px; height: 14px; color: var(--accent); }
@media (prefers-reduced-motion: reduce) { .cart-pay__chevron { transition: none; } }

/* EMPTY STATE */
.cart__empty { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: var(--sp-4); padding: var(--sp-10) var(--sp-6); }
.cart__empty-icon { width: 56px; height: 56px; display: flex; align-items: center; justify-content: center; border-radius: var(--radius-full); background: var(--bg-elevated); border: 1px solid var(--border-subtle); color: var(--text-muted); }
.cart__empty-icon svg { width: 26px; height: 26px; }
.cart__empty h3 { font-size: 18px; font-weight: 600; color: var(--text-primary); }
.cart__empty p { font-size: 13px; color: var(--text-muted); max-width: 32ch; }

@media (max-width: 520px) {
  #cart { border-left: none; }

  /* Header — ~14% shorter: tighter block padding + slightly smaller title/pill.
     Type sizes only nudge down (hierarchy + readability preserved). */
  .cart__header { padding: 14px var(--sp-5); }
  .cart__title { font-size: 16px; }
  .cart__count { font-size: 12px; padding: 2px 8px; }

  /* Body — tighter section rhythm so more of the cart shows with less scrolling */
  .cart__body { padding: var(--sp-4) var(--sp-5); gap: var(--sp-4); }
  .cart__footer { padding-inline: var(--sp-5); }
  .cart__section-label { margin-bottom: var(--sp-3); }

  /* Cart items — readable boxless vial; height comes off internal spacing +
     ~25% tighter gap BETWEEN items (padding 20→15 each side). */
  .cart-item { grid-template-columns: 72px 1fr; padding: 15px 0; }
  .cart-item__media { width: 72px; height: 72px; }
  .cart-item__bottom { margin-top: 6px; }

  /* Order summary — a touch tighter on top of the global compression */
  .cart-totals { gap: 4px; margin-bottom: 6px; }
  .cart-grand { margin-top: 6px; padding-top: 6px; }
  .cart-shipnote { padding: 5px var(--sp-4); margin-bottom: 6px; }
  .cart-checkout .btn { padding: 12px 32px; } /* ~50px tall — still >=44px touch */
}
@media (pointer: coarse) {
  /* Quantity stepper smaller per request, but kept a comfortable ~38x36 tap
     area for the +/- targets. Close stays 44px. */
  #cart .qty button { width: 38px; height: 36px; }
  #cart .qty input { height: 36px; }
  .cart__close { width: 44px; height: 44px; }
  .cart-pay__label { padding: 1px 0; } /* compact collapsed payment header on touch */
}

/* ==========================================================================
   Button busy state — inline spinner
   Used while an add-to-cart request is in flight, including the silent
   backoff-and-retry that rides out the host's HTTP 429 limiter. Keeping the
   control disabled + spinning is what turns a rate-limited add into a short
   wait instead of an error the shopper has to act on.
   ========================================================================== */
.btn.is-loading { cursor: progress; }
.btn.is-loading .btn-spinner {
  display: inline-block;
  width: 1em;
  height: 1em;
  margin-right: 0.5em;
  vertical-align: -0.125em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: dice-btn-spin 0.6s linear infinite;
}
@keyframes dice-btn-spin { to { transform: rotate(360deg); } }

/* Respect a reduced-motion preference: keep the affordance, drop the spin. */
@media (prefers-reduced-motion: reduce) {
  .btn.is-loading .btn-spinner { animation: none; opacity: 0.6; }
}
