/*
Theme Name: Provenance
Theme URI: https://github.com/jnemanpour/Get-retta
Description: WooCommerce port of the Provenance Bio Labs storefront — a premium, research-use-only peptide store. The design system is shared verbatim with the static site (assets/css/base.css, generated by wordpress/tools/sync-styles.sh); this stylesheet holds only the WordPress and WooCommerce additions.
Version: 1.0.0
Requires at least: 6.4
Requires PHP: 7.4
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: provenance
Tags: e-commerce, woocommerce, custom-colors, translation-ready
*/

/* ============================================================
   WordPress / WooCommerce additions.

   The full design system lives in assets/css/base.css and loads
   first. Everything here maps WooCommerce's own markup onto that
   system, or covers markup the static site never had (cart page,
   checkout, notices, pagination).
   ============================================================ */

/* ---------- WordPress core markup ---------- */

.alignwide  { max-width: 1100px; margin-inline: auto; }
.alignfull  { width: 100%; }
.aligncenter { margin-inline: auto; }
.screen-reader-text {
  border: 0;
  clip-path: inset(50%);
  height: 1px;
  width: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
}

.entry-content > * + * { margin-top: 1.1rem; }
.entry-content h2 { margin-top: 2.4rem; font-family: var(--font-display); }
.entry-content h3 { margin-top: 1.8rem; font-family: var(--font-display); }
.entry-content ul,
.entry-content ol { padding-left: 1.3rem; }
.entry-content ul { list-style: disc; }
.entry-content ol { list-style: decimal; }
.entry-content li + li { margin-top: 0.4rem; }
.entry-content a { color: var(--brand); font-weight: 600; text-decoration: underline; }

/* Availability badges (.product-badge, .badge-sold-out, .badge-coming-soon)
   are already defined in base.css — do not restate them here or the two
   sites drift apart. */

/* ---------- Bridging Woo markup to the card design ---------- */
/* base.css styles .product-price and .price-was, but WooCommerce renders
   prices as <span class="price"> with <del>/<ins> for sales. These rules
   map Woo's markup onto the identical appearance rather than duplicating
   the card design. */

.product-foot .price {
  font-weight: 700;
  font-size: 1.08rem;
  color: var(--ink);
}
.product-foot .price del,
.single-product-summary .price del {
  opacity: 1;
  text-decoration: none;
}
.product-foot .price del .amount {
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--ink-soft);
  text-decoration: line-through;
  margin-right: 0.4rem;
}
.product-foot .price ins { text-decoration: none; }
.product-foot .price .from,
.product-foot .price small { font-size: 0.8rem; font-weight: 500; color: var(--ink-soft); }

/* The card's add-to-cart is an <a> under WooCommerce (it may need to link to
   the product page for variable products) but must read as the same button. */
a.add-btn {
  display: inline-block;
  text-align: center;
  line-height: 1.2;
}
a.add-btn:hover { background: var(--brand-dark); }
.add-btn.loading { opacity: 0.6; pointer-events: none; }
.add-btn.added { background: var(--accent); color: var(--ink); }

/* Category chips are links here, not buttons, so they need the box model
   buttons get for free. */
a.chip {
  display: inline-block;
  text-decoration: none;
  line-height: 1.2;
}

/* ---------- Assigned nav menus ---------- */
/* base.css styles .nav-links as a flex row of bare <a>, which is what the
   static site emitted and what this theme's no-menu fallback still emits.
   Once a menu is assigned in Appearance → Menus, wp_nav_menu() wraps every
   link in an <li>, which would otherwise show a list marker and sit outside
   the flex layout. These rules make the assigned-menu path render identically
   to the fallback. */
.nav-links li {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* WordPress marks the current page with its own class rather than .active. */
.nav-links .current-menu-item > a,
.nav-links .current_page_item > a {
  color: var(--brand);
}
.nav-links .current-menu-item > a::after,
.nav-links .current_page_item > a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -4px;
  height: 2px;
  background: var(--brand);
  border-radius: 2px;
}

/* The footer link columns are <ul> in both paths, assigned or fallback. */
.site-footer .footer-col li { list-style: none; }

/* ---------- WooCommerce buttons ---------- */

.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button,
.woocommerce #respond input#submit,
.woocommerce a.button.alt,
.woocommerce button.button.alt {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.9rem;
  letter-spacing: 0.01em;
  line-height: 1.2;
  border: 1px solid var(--brand);
  border-radius: var(--radius);
  background: var(--brand);
  color: #fff;
  padding: 0.85rem 1.5rem;
  transition: transform 0.15s, box-shadow 0.15s, background 0.15s;
}

.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover,
.woocommerce #respond input#submit:hover,
.woocommerce a.button.alt:hover,
.woocommerce button.button.alt:hover {
  background: var(--brand-dark);
  border-color: var(--brand-dark);
  color: #fff;
  transform: translateY(-1px);
  box-shadow: var(--shadow-lift);
}

.woocommerce a.button.disabled,
.woocommerce button.button:disabled,
.woocommerce button.button.disabled {
  opacity: 0.5;
  transform: none;
  box-shadow: none;
  cursor: not-allowed;
}

/* ---------- Notices ---------- */

.woocommerce-message,
.woocommerce-info,
.woocommerce-error {
  border-top: none;
  border-left: 3px solid var(--brand);
  background: #fafaf8;
  border-radius: var(--radius);
  font-size: 0.92rem;
  padding: 1rem 1.2rem;
  margin-bottom: 1.6rem;
  list-style: none;
}
.woocommerce-error { border-left-color: #e5222e; }
.woocommerce-message::before,
.woocommerce-info::before,
.woocommerce-error::before { display: none; }

/* ---------- Shop archive ---------- */

.woocommerce-result-count,
.woocommerce-ordering { display: none; }

.woocommerce-pagination ul {
  display: flex;
  gap: 0.5rem;
  justify-content: center;
  border: none;
  margin-top: 3rem;
}
.woocommerce-pagination ul li { border: none; }
.woocommerce-pagination ul li a,
.woocommerce-pagination ul li span {
  display: grid;
  place-items: center;
  min-width: 40px;
  height: 40px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-size: 0.88rem;
  font-weight: 600;
}
.woocommerce-pagination ul li span.current {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}

/* ---------- Single product ---------- */

.single-product-layout {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 3.5rem;
  align-items: start;
  padding: 3.5rem 0 4.5rem;
}
.single-product-gallery {
  background: #fafaf8;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  display: grid;
  place-items: center;
  padding: 2rem;
  min-height: 380px;
}
.single-product-gallery img { border-radius: var(--radius); }
.single-product-gallery svg { width: 46%; height: auto; }

.single-product-summary h1 {
  font-family: var(--font-display);
  font-size: clamp(1.8rem, 3.4vw, 2.5rem);
  letter-spacing: -0.02em;
  margin-bottom: 0.4rem;
}
.single-product-summary .subtitle {
  color: var(--ink-soft);
  font-size: 0.98rem;
  margin-bottom: 1.4rem;
}
.single-product-summary .price {
  font-family: var(--font-display);
  font-size: 1.7rem;
  font-weight: 700;
  margin: 1.2rem 0;
  color: var(--ink);
}
.single-product-summary .price del { opacity: 1; }
.single-product-summary .price del .amount {
  font-size: 1.05rem;
  font-weight: 500;
  color: var(--ink-soft);
  text-decoration: line-through;
}
.single-product-summary .price ins { text-decoration: none; }

.spec-table {
  width: 100%;
  border-top: 1px solid var(--line);
  margin: 1.6rem 0;
  font-size: 0.9rem;
}
.spec-table div {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--line);
}
.spec-table .k { color: var(--ink-soft); }
.spec-table .v { font-weight: 600; font-family: var(--font-mono); font-size: 0.85rem; }

.woocommerce div.product form.cart { margin: 1.6rem 0; }
.woocommerce div.product form.cart .quantity { margin-right: 0.8rem; }
.woocommerce .quantity input.qty {
  width: 72px;
  height: 46px;
  text-align: center;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-family: var(--font-body);
}
.woocommerce div.product form.cart .variations { margin-bottom: 1.2rem; }
.woocommerce div.product form.cart .variations td { padding: 0.4rem 0; }
.woocommerce div.product form.cart .variations label { font-weight: 600; font-size: 0.85rem; }
.woocommerce div.product form.cart .variations select {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.7rem 0.8rem;
  font-family: var(--font-body);
  min-width: 180px;
}

.product-ruo-note {
  margin-top: 1.6rem;
  padding: 1rem 1.1rem;
  background: #fafaf8;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  font-size: 0.8rem;
  line-height: 1.6;
  color: var(--ink-soft);
}

.woocommerce-tabs { padding: 0 0 4rem; }
.woocommerce-tabs ul.tabs {
  display: flex;
  gap: 1.6rem;
  border-bottom: 1px solid var(--line);
  padding: 0 0 0.8rem;
  margin-bottom: 1.8rem;
  list-style: none;
}
.woocommerce-tabs ul.tabs li a {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.woocommerce-tabs ul.tabs li.active a { color: var(--brand); }
.woocommerce-tabs .panel h2 { display: none; }
.woocommerce-tabs .panel ul { list-style: disc; padding-left: 1.3rem; }
.woocommerce-tabs .panel li + li { margin-top: 0.4rem; }
.woocommerce-tabs .panel p + ul,
.woocommerce-tabs .panel ul + p { margin-top: 1rem; }

/* ---------- Cart & checkout ---------- */

.woocommerce-cart-form,
.woocommerce-checkout { padding-bottom: 4rem; }

.woocommerce table.shop_table {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  border-collapse: separate;
  font-size: 0.92rem;
}
.woocommerce table.shop_table th {
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
  padding: 1rem;
}
.woocommerce table.shop_table td { padding: 1rem; }

.woocommerce form .form-row { padding: 0; margin-bottom: 1.1rem; }
.woocommerce form .form-row label {
  font-size: 0.85rem;
  font-weight: 600;
  margin-bottom: 0.4rem;
  display: block;
}
.woocommerce form .form-row input.input-text,
.woocommerce form .form-row textarea,
.woocommerce form .form-row select,
.woocommerce .select2-container .select2-selection--single {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.8rem 0.9rem;
  font-family: var(--font-body);
  font-size: 0.95rem;
  height: auto;
  background: var(--paper);
}
.woocommerce form .form-row input.input-text:focus,
.woocommerce form .form-row textarea:focus,
.woocommerce form .form-row select:focus {
  outline: none;
  border-color: var(--brand);
}

/* The required research-use consent sits directly above the pay button and
   should read as a deliberate stop, not a fine-print afterthought. */
.woocommerce form .form-row.validate-required#research_use_consent_field,
#research_use_consent_field {
  background: #fafaf8;
  border: 1px solid var(--line);
  border-left: 3px solid var(--brand);
  border-radius: var(--radius);
  padding: 1rem 1.1rem;
  margin: 1.4rem 0;
}
#research_use_consent_field label {
  font-weight: 500;
  font-size: 0.85rem;
  line-height: 1.6;
  display: flex;
  gap: 0.7rem;
  align-items: flex-start;
  cursor: pointer;
}
#research_use_consent_field input[type="checkbox"] {
  margin-top: 0.15rem;
  width: 17px;
  height: 17px;
  flex-shrink: 0;
  accent-color: var(--brand);
}
#research_use_consent_field .required { color: #e5222e; }

.woocommerce-checkout #payment {
  background: #fafaf8;
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.woocommerce-checkout #payment div.payment_box { background: var(--paper); }
.woocommerce-checkout #payment ul.payment_methods { border-bottom: 1px solid var(--line); }

/* ---------- Responsive ---------- */

@media (max-width: 900px) {
  .single-product-layout { grid-template-columns: 1fr; gap: 2rem; padding-top: 2rem; }
}

@media (max-width: 640px) {
  .woocommerce-tabs ul.tabs { gap: 1rem; overflow-x: auto; }
  .spec-table { font-size: 0.85rem; }
}

/* ---------- Promotions marquee ----------
   Every live promotion scrolls continuously across the top. Bigger and
   higher contrast than the old static line: this is the only place an
   automatic discount gets announced, so it has to be read rather than
   skimmed past.

   Two identical tracks slide left together. When the first has moved its
   full width the animation resets, and because the second is sitting
   exactly one width behind, the seam is invisible. */
.announcement.announcement-marquee {
  --marquee-seconds: 38s;
  background: var(--accent);
  color: var(--accent-ink);
  padding: 0;
  display: flex;
  overflow: hidden;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: 0.86rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border-bottom: 1px solid rgba(74, 83, 22, 0.25);
  /* Nothing below should shift while the fonts load. */
  min-height: 44px;
  align-items: center;
}

.announcement-marquee .announcement-track {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
  min-width: 100%;
  animation: provenance-marquee var(--marquee-seconds) linear infinite;
  will-change: transform;
}

.announcement-marquee .announcement-item { padding: 0 1.1rem; }

.announcement-marquee .announcement-sep {
  color: rgba(74, 83, 22, 0.5);
  font-size: 1.1em;
  line-height: 1;
}

@keyframes provenance-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-100%); }
}

/* Let someone stop it to actually read an offer. */
.announcement-marquee:hover .announcement-track,
.announcement-marquee:focus-within .announcement-track {
  animation-play-state: paused;
}

/* Motion sensitivity: show the offers, do not move them. The duplicate
   track would just be a repeated list, so it is hidden outright. */
@media (prefers-reduced-motion: reduce) {
  .announcement-marquee { overflow-x: auto; }
  .announcement-marquee .announcement-track { animation: none; }
  .announcement-marquee .announcement-track[aria-hidden="true"] { display: none; }
}

@media (max-width: 640px) {
  .announcement.announcement-marquee { font-size: 0.78rem; min-height: 40px; }
  .announcement-marquee .announcement-item { padding: 0 0.85rem; }
}

/* ---------- Hero product shot ----------
   The vial, not a drawing of a certificate. Sits on a light card so the
   studio-white photograph reads deliberately against the dark hero
   rather than looking like a hole punched in it. */
.hero-product {
  position: relative;
  margin: 0;
  background: var(--bone);
  border-radius: calc(var(--radius) * 2);
  overflow: visible;
  aspect-ratio: 1 / 0.86;
  display: grid;
  place-items: center;
}
.hero-product img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: calc(var(--radius) * 2);
  display: block;
}
.hero-product .hero-product-fallback { width: 46%; height: auto; }

/* Availability, stated before the customer has to look for it. */
.hero-product-flag {
  position: absolute;
  top: 1rem;
  left: 1rem;
  z-index: 2;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 0.5rem 0.8rem;
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

/* The certificate overlays the vial: the claim sitting on the thing it
   describes, rather than beside it. */
.hero-coa {
  position: absolute;
  left: -1.5rem;
  bottom: -1.25rem;
  z-index: 2;
  display: grid;
  gap: 0.42rem;
  min-width: 15.5rem;
  background: var(--paper);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lift);
  padding: 0.95rem 1.1rem;
}
.hero-coa-head {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  color: var(--ink);
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--line);
}
.hero-coa-row {
  display: flex;
  justify-content: space-between;
  gap: 1.2rem;
  font-size: 0.82rem;
}
.hero-coa-row .k { color: var(--ink-soft); }
.hero-coa-row .v { font-family: var(--font-mono); font-weight: 600; color: var(--ink); }

/* ---------- Trust band ----------
   A light strip straight under the dark hero. It is the first thing after
   the headline, so it is sized to be read rather than decorated. */
.trust-bar-strong {
  background: var(--paper);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  padding: 1.35rem 0;
}
.trust-claims {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.9rem 2.6rem;
}
.trust-claim {
  font-family: var(--font-mono);
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
  white-space: nowrap;
}
/* A lime tick before each claim: enough to register as a checklist
   without spending the accent on five separate icons. */
.trust-claim::before {
  content: "";
  display: inline-block;
  width: 0.5rem;
  height: 0.5rem;
  margin-right: 0.6rem;
  border-radius: 50%;
  background: var(--accent);
  vertical-align: 0.05em;
}

@media (max-width: 900px) {
  .hero-coa { left: 0; right: 0; bottom: -0.75rem; min-width: 0; }
}
@media (max-width: 640px) {
  .trust-claims { gap: 0.7rem 1.4rem; }
  .trust-claim { font-size: 0.72rem; letter-spacing: 0.08em; }
  .hero-product-flag { font-size: 0.62rem; }
}

/* ---------- Hero promo card ----------
   One offer, stated where the decision is made, linking to the place it
   can be used. Sits between the lead and the buttons: read after the
   pitch, before the click. */
.hero-promo {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin: 1.8rem 0 0;
  padding: 0.85rem 1.1rem;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: calc(var(--radius) * 2);
  background: rgba(255, 255, 255, 0.04);
  text-decoration: none;
  transition: border-color .18s, background .18s, transform .18s;
  max-width: 30rem;
}
.hero-promo:hover {
  border-color: var(--accent);
  background: rgba(217, 224, 33, 0.08);
  transform: translateY(-1px);
}
.hero-promo-mark {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 2.6rem;
  height: 2.6rem;
  border-radius: var(--radius);
  background: var(--accent);
  color: var(--accent-ink);
}
.hero-promo-mark svg { width: 1.3rem; height: 1.3rem; }
.hero-promo-text { display: grid; gap: 0.1rem; min-width: 0; }
.hero-promo-text strong {
  color: #fff;
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.hero-promo-text small {
  color: rgba(255, 255, 255, 0.6);
  font-size: 0.78rem;
}
.hero-promo-go {
  margin-left: auto;
  color: var(--accent);
  font-size: 1.15rem;
  line-height: 1;
  flex: 0 0 auto;
}

/* The gift line in the cart: a zero price needs a reason next to it. */
.gift-tag {
  display: inline-block;
  margin-left: 0.5rem;
  padding: 0.12rem 0.45rem;
  border-radius: 3px;
  background: var(--accent);
  color: var(--accent-ink);
  font-family: var(--font-mono);
  font-size: 0.62rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  vertical-align: 0.1em;
}

@media (max-width: 640px) {
  .hero-promo { max-width: none; padding: 0.75rem 0.9rem; gap: 0.8rem; }
  .hero-promo-text strong { font-size: 0.92rem; }
  .hero-promo-text small { font-size: 0.72rem; }
}

/* ---------- Hero actions ----------
   The promo card and the two buttons are one block, sharing a width, so
   their edges line up instead of the card overhanging. The buttons split
   that width evenly; the card fills it.

   Scoped to .hero-actions so the centred call to action further down the
   page keeps its own layout. */
.hero-actions {
  display: grid;
  gap: 0.85rem;
  max-width: 27rem;
  margin-top: 1.8rem;
}
.hero-actions .hero-promo {
  margin: 0;
  max-width: none;
  width: 100%;
  padding: 0.8rem 1rem;
}
.hero-actions .hero-cta {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.8rem;
  margin: 0;
}
.hero-actions .hero-cta .btn {
  width: 100%;
  text-align: center;
  justify-content: center;
}

@media (max-width: 640px) {
  .hero-actions { max-width: none; }
  .hero-actions .hero-cta { grid-template-columns: 1fr; }
}

/* ---------- Marquee: backlit lettering ----------
   Dark type on lime is legible but flat. A tight light halo behind each
   letter reads as light coming through from behind rather than a glow
   sitting on top — the letters lift off the band instead of being
   printed on it.

   Two shadows, not one: a wide soft pool for the lift, and a tight
   bright ring that keeps the edges crisp. A single large blur just makes
   the text look smeared. */
.announcement-marquee .announcement-item {
  color: #1a1e08;
  text-shadow:
    0 0 1px rgba(255, 255, 255, 0.85),
    0 0 6px rgba(255, 255, 255, 0.65),
    0 0 18px rgba(255, 255, 255, 0.45);
}
.announcement-marquee .announcement-sep {
  color: rgba(26, 30, 8, 0.55);
  text-shadow: 0 0 8px rgba(255, 255, 255, 0.6);
}

/* ---------- Buying from the catalogue card ---------- */
.card-buy { display: block; }

.size-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin: 0.7rem 0 0.15rem;
}
.size-chip {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  padding: 0.32rem 0.6rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper);
  color: var(--ink-soft);
  cursor: pointer;
  transition: border-color .15s, background .15s, color .15s;
}
.size-chip:hover:not(:disabled) { border-color: var(--ink); color: var(--ink); }
.size-chip.is-active {
  background: var(--ink);
  border-color: var(--ink);
  color: #fff;
}
.size-chip:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  text-decoration: line-through;
}

.card-buy-actions { display: flex; gap: 0.4rem; align-items: stretch; }
.card-qty {
  width: 3.2rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  text-align: center;
  font-family: var(--font-mono);
  font-size: 0.86rem;
  padding: 0.4rem 0.2rem;
  background: var(--paper);
  color: var(--ink);
}
.card-qty:focus { outline: none; border-color: var(--ink); }
/* The number spinners crowd a 3-character field. */
.card-qty::-webkit-outer-spin-button,
.card-qty::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.card-qty { -moz-appearance: textfield; appearance: textfield; }

.card-buy .add-btn { padding-inline: 1rem; }

@media (max-width: 420px) {
  .card-buy-actions { flex-direction: column; }
  .card-qty { width: 100%; }
}


/* =========================================================
   BONE GROUND
   Pure white is the one thing that made this read as a
   template. Bone is the page; white is reserved for things
   that sit ON the page — cards, panels, the sticky header —
   so elevation comes from the paper being a different colour
   from the card, not from a heavier shadow.
   ========================================================= */

:root {
  --bone-line: #e8e6e1;  /* hairline that reads on bone */
  --card-shadow: 0 1px 2px rgba(18, 22, 26, 0.04), 0 8px 24px rgba(18, 22, 26, 0.05);
  --card-shadow-lift: 0 2px 4px rgba(18, 22, 26, 0.05), 0 18px 40px rgba(18, 22, 26, 0.10);
}

/* The grain. An inline SVG turbulence tile rather than a JPEG:
   it is ~400 bytes, needs no request, and never shows a seam
   because stitchTiles keeps the noise continuous across the
   repeat. Kept under 6% opacity — at paper weight it should be
   felt and not seen. */
body {
  background-color: var(--bone);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23p)' opacity='0.055'/%3E%3C/svg%3E");
  background-repeat: repeat;
  background-size: 200px 200px;
}

/* Full-width bands that were white are the page, not cards. */
.trust-bar-strong,
.section.alt,
.woocommerce-cart .section,
.woocommerce-checkout .section {
  background: transparent;
}

/* Things that genuinely sit on the page keep their white, and
   pick up the warmer hairline so the edge is not blue-grey. */
.product-card,
.panel,
.card,
.site-header {
  border-color: var(--bone-line);
}

.product-card {
  background: var(--paper);
  box-shadow: var(--card-shadow);
}
.product-card:hover {
  box-shadow: var(--card-shadow-lift);
}

.site-header {
  background: color-mix(in srgb, var(--bone) 88%, white);
  backdrop-filter: saturate(1.4) blur(8px);
}


/* =========================================================
   CHAIN — the five claims, and the four photographed steps
   One component, two densities. The rule behind the marks
   fills as the section crosses the viewport, so the sequence
   reads as a sequence instead of five parallel boasts.
   ========================================================= */

.chain {
  --chain-p: 0;   /* 0..1, written by theme.js on scroll */
  --chain-n: 5;   /* number of steps, set per variant */

  /* One variable sizes the circle, and everything that has to line up
     with it — the icon, the type, and the rule running between marks —
     is derived from it. That is what lets the row shrink to a phone
     without the line drifting off the centres. */
  --mark: clamp(1.35rem, 5.4vw, 2.7rem);
  --chain-line-top: calc(var(--mark) / 2);

  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(var(--chain-n), 1fr);
  gap: clamp(0.5rem, 1.6vw, 1.4rem) clamp(0.3rem, 1.4vw, 1rem);
  position: relative;
}

/* The track and its fill both span mark-centre to mark-centre,
   which with equal columns is half a column in from each end. */
.chain::before,
.chain::after {
  content: "";
  position: absolute;
  top: var(--chain-line-top, 1.35rem);
  height: clamp(1px, 0.35vw, 2px);
  border-radius: 2px;
  pointer-events: none;
}
.chain::before {
  left: calc(50% / var(--chain-n));
  right: calc(50% / var(--chain-n));
  background: var(--bone-line);
}
.chain::after {
  left: calc(50% / var(--chain-n));
  width: calc((100% - 100% / var(--chain-n)) * var(--chain-p));
  background: var(--accent);
  transition: width 0.15s linear;
}

.chain-step {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: clamp(0.28rem, 1vw, 0.55rem);
}

.chain-mark {
  display: grid;
  place-items: center;
  width: var(--mark);
  height: var(--mark);
  border-radius: 50%;
  background: var(--paper);
  border: clamp(1px, 0.4vw, 2px) solid var(--bone-line);
  color: var(--ink-soft);
  font-family: var(--font-mono);
  font-size: clamp(0.5rem, 1.9vw, 0.85rem);
  font-weight: 700;
  flex-shrink: 0;
  transition: background 0.3s ease, border-color 0.3s ease, color 0.3s ease, transform 0.3s ease;
}
.chain-mark svg { width: calc(var(--mark) * 0.46); height: calc(var(--mark) * 0.46); }

/* Reached. The accent lands on the marks the line has passed,
   which is the whole point of the interaction. */
.chain-step.is-on .chain-mark {
  background: var(--accent);
  border-color: var(--accent);
  color: #101314;
  transform: scale(1.06);
}

.chain-label {
  font-family: var(--font-mono);
  font-size: clamp(0.44rem, 1.55vw, 0.78rem);
  font-weight: 700;
  /* Tracking has to come off as the type shrinks, or the labels stop
     fitting their column and wrap mid-word. */
  letter-spacing: clamp(0.01em, 0.22vw, 0.11em);
  text-transform: uppercase;
  color: var(--ink);
  line-height: 1.3;
  hyphens: auto;
}

.chain-text {
  font-size: clamp(0.5rem, 1.5vw, 0.87rem);
  line-height: 1.5;
  color: var(--ink-soft);
  max-width: 24ch;
}

.chain-shot {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border-radius: var(--radius);
  border: 1px solid var(--bone-line);
  background: var(--paper);
  margin-top: 0.3rem;
}
.chain-shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
}

/* Compact variant: the five claims under the hero. */
.trust-bar-strong .chain { --chain-n: 5; }

/* Photo variant: four evidenced steps. Slightly bigger marks, since the
   numbers carry more weight than the icons above them. */
.chain-photos {
  --chain-n: 4;
  --mark: clamp(1.45rem, 6vw, 2.7rem);
  gap: clamp(0.5rem, 1.8vw, 1.6rem) clamp(0.35rem, 1.6vw, 1.6rem);
}

.chain-photos-section .section-lead {
  max-width: 60ch;
  margin: 0.6rem auto 0;
  color: var(--ink-soft);
}

/* The row stays a row all the way down. It used to break to two columns
   and then one, which dropped the connecting rule and with it the reason
   the section exists — five claims in a column are a list again, not a
   sequence. Everything above is sized in vw so it simply gets smaller
   instead. */
/* A step may carry a short label for narrow screens. Only one is ever
   displayed, and display:none keeps the other out of the accessibility
   tree so a screen reader hears the step named once. */
.chain-label-short { display: none; }

@media (max-width: 560px) {
  /* At a quarter of a phone screen the full label wraps and drags its
     photo out of line with the other three. Swapping to the short form
     realigns the row by fitting rather than by padding the others. */
  .chain-label-long { display: none; }
  .chain-label-short { display: inline; }

  .chain-photos .chain-text {
    /* The captions are the first thing that stops being readable at this
       width; the photo and its label carry the step on their own. */
    display: none;
  }
}

/* Someone who asked for less motion still gets the finished
   state, just not the travel. */
@media (prefers-reduced-motion: reduce) {
  .chain::after { transition: none; }
  .chain-mark { transition: none; }
}


/* =========================================================
   PRODUCT CARDS — bigger, and carrying their provenance
   ========================================================= */

.product-grid {
  grid-template-columns: repeat(auto-fill, minmax(310px, 1fr));
  gap: 1.9rem;
}

/* The provenance row: which lot this is, and the certificate
   for it. Mono, because a lot number is a serial and should
   look like one. */
.card-prov {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  margin-top: 0.55rem;
  padding-top: 0.7rem;
  border-top: 1px solid var(--bone-line);
  font-family: var(--font-mono);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
}

.card-lot {
  color: var(--ink-soft);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.card-lot b {
  color: var(--ink);
  font-weight: 600;
}

.card-coa {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.28rem 0.6rem;
  border-radius: 3px;
  border: 1px solid var(--bone-line);
  color: var(--ink);
  text-decoration: none;
  font-weight: 600;
  white-space: nowrap;
  transition: background 0.2s ease, border-color 0.2s ease;
}
.card-coa svg { width: 0.85rem; height: 0.85rem; }
.card-coa:hover { background: var(--bone); border-color: var(--ink); }

/* No certificate on record yet. Said plainly rather than
   dressed up as one — an unbacked lot number is the exact
   trust signal this catalogue must not fake. */
.card-coa.is-request {
  color: var(--ink-soft);
  border-style: dashed;
}
.card-coa.is-request:hover { color: var(--ink); }


/* =========================================================
   HERO VIAL — cut out, and drifting
   The photo's plate is gone, so the frame that used to hold
   it has to go too: a card behind a cut-out object puts the
   background straight back. What is left is the vial, its
   own soft shadow, and the COA card it is evidence for.
   ========================================================= */

.hero-product-float {
  background: none;
  border: 0;
  box-shadow: none;
  padding: 0;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 30rem;
}

/* Specificity note: `.hero-product img` in base.css sizes the framed
   photo to fill its card with object-fit:cover. A cut-out must keep its
   own proportions, so this has to outrank it — hence the parent in the
   selector and the explicit resets. */
.hero-product-float .hero-vial {
  width: min(60%, 18rem);
  height: auto;
  max-height: none;
  object-fit: contain;
  border-radius: 0;
  display: block;
  /* The hero paints a dark ground and a grid overlay above the normal
     flow, so an untouched static image lands underneath both and simply
     does not appear. The flag and COA card already carry z-index for the
     same reason. */
  position: relative;
  z-index: 1;
  /* Pushed to the right of the column so the COA card has the lower
     left to itself. Overlapping the two put the card straight over the
     compound name, which is the one thing on the label that has to be
     readable at a glance. */
  margin-left: auto;
  margin-right: 0;
  /* The cut-out has no contact shadow of its own any more, so one is
     cast here — soft and offset down, which is what sells "floating"
     rather than "pasted on". */
  filter: drop-shadow(0 34px 40px rgba(0, 0, 0, 0.55));
  will-change: transform;
}

.hero-product-float .hero-vial { animation: hero-vial-drift 6s ease-in-out infinite; }

/* The original hover: a slow rise and fall with a touch of tilt. Tried a
   game-style bounce with squash and overshoot here and it was too busy
   behind the headline — this is deliberately the quiet version. */
@keyframes hero-vial-drift {
  0%, 100% { transform: translateY(-0.65rem) rotate(-0.4deg); }
  50%      { transform: translateY(0.65rem) rotate(0.4deg); }
}

.hero-product-float .hero-product-flag { z-index: 3; top: 0.5rem; left: 0; }

/* Tucked into the vial's lower left: overlapping enough to read as one
   object, clear of the label so both stay legible. */
.hero-product-float .hero-coa { z-index: 3; left: 0; bottom: 0.75rem; }

/* ---------- Narrow screens ----------
   Stacked, the vial became a second screenful below the copy that nobody
   scrolled past to reach the buttons. It is decoration at this width, so
   it stops taking up layout entirely: the figure is lifted out of the
   flow and pinned into the empty upper right of the hero, behind the
   type, still drifting.

   Everything is sized in viewport and percentage units rather than fixed
   breapoints-worth of pixels, so it keeps the same relationship to the
   headline from a small phone up to a tablet. */
@media (max-width: 900px) {
  .hero.dark { position: relative; overflow: hidden; }

  .hero-grid > div:last-child {
    position: absolute;
    inset: 0;
    margin: 0;
    pointer-events: none;   /* it must never eat a tap meant for the CTA */
    z-index: 0;
  }
  .hero-grid > div:first-child { position: relative; z-index: 1; }

  .hero-product-float {
    position: static;
    min-height: 0;
    display: block;
  }

  /* Give the vial a column of its own rather than letting the copy run
     underneath it. The headline and the paragraph stop short of the
     right edge; everything below the vial — the promo card, the buttons,
     the stats — still runs full width. */
  .hero-grid > div:first-child > .eyebrow,
  .hero-grid > div:first-child > h1,
  .hero-grid > div:first-child > .hero-dash,
  .hero-grid > div:first-child > .lead {
    max-width: 66%;
  }

  .hero-product-float .hero-vial {
    position: absolute;
    top: 3%;
    /* Fully in frame now. It was hung past the edge to keep it clear of
       the paragraph; with the text narrowed there is nothing to dodge,
       and a cropped vial only looked like one that would not fit. */
    right: 2%;
    width: clamp(6.5rem, 30vw, 11rem);
    margin: 0;
    /* Nothing overlaps it any more, so it can carry its own weight.
       Clear glass on a near-black ground has very little contrast to
       start with. */
    opacity: 0.92;
    filter: drop-shadow(0 18px 30px rgba(0, 0, 0, 0.5));
  }

  /* The COA card and the stock flag belong to the desktop composition;
     over the headline they are just clutter. */
  .hero-product-float .hero-coa,
  .hero-product-float .hero-product-flag { display: none; }
}

/* Phones proper: smaller still, and tucked further into the corner so it
   sits beside the headline rather than across it. */
/* Phones proper: the text column has to give up a little less, so the
   vial gives up a little more. */
@media (max-width: 560px) {
  .hero-grid > div:first-child > .eyebrow,
  .hero-grid > div:first-child > h1,
  .hero-grid > div:first-child > .hero-dash,
  .hero-grid > div:first-child > .lead {
    max-width: 70%;
  }

  .hero-product-float .hero-vial {
    top: 2%;
    right: 0;
    width: clamp(5.5rem, 27vw, 9rem);
    opacity: 0.95;
  }
}

/* Hovering is decoration; nobody should have to sit through it. */
@media (prefers-reduced-motion: reduce) {
  .hero-product-float .hero-vial { animation: none; transform: none; }
}

/* The hover is the one piece of motion on the page that repeats
   forever, so it stops while a menu or dialog is open over it. */
body.nav-open .hero-product-float .hero-vial { animation-play-state: paused; }

/* FAQ at the foot of the homepage. The list is centred and narrower than
   a full-width section: a question that runs the whole page width is
   harder to scan than one that does not. */
.faq-home .faq-list {
  max-width: 46rem;
  margin: 0 auto;
}
.faq-more {
  margin: 1.6rem 0 0;
  text-align: center;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.faq-more a {
  color: var(--ink);
  text-decoration: none;
  font-weight: 600;
  border-bottom: 1px solid var(--bone-line);
  padding-bottom: 0.15rem;
}
.faq-more a:hover { border-bottom-color: var(--ink); }


/* =========================================================
   SECTION RHYTHM
   base.css sets a flat 5.5rem section padding and a 3rem
   head margin at every width. On a phone that is 88px of
   nothing above each section, and because .section-head
   becomes a column there, its single 2rem gap lands between
   the eyebrow and the heading it labels as well as before
   the lead — 314px of whitespace before the first real
   content. Overridden here rather than in base.css, which is
   synced from the static site and would lose the edit.
   ========================================================= */

.section {
  padding: clamp(2.75rem, 6.5vw, 5rem) 0;
}

.section-head {
  margin-bottom: clamp(1.5rem, 3.5vw, 3rem);
}

@media (max-width: 900px) {
  /* The eyebrow is a label for the heading, so it sits with it.
     The lead is a separate thought and keeps its own space. */
  .section-head { gap: 0.6rem; }
  .section-head .lead,
  .section-head .section-lead { margin-top: 0.5rem; }
}

/* The strip under the hero is its own band; it does not need a
   section's worth of air beneath it as well. */
.trust-bar-strong + .section { padding-top: clamp(2.25rem, 5vw, 4rem); }

/* Two sections in a row each pay full padding, so the seam between them
   is double the space either one asked for. The one that follows gives
   some back — enough to read as a new section, not as a gap. */
.section + .section { padding-top: clamp(1.5rem, 3.5vw, 3rem); }
