/* Research Compound Product Fields — front-end styles
   Namespaced under .rcpf- for our own elements; the rest targets standard
   WooCommerce classes so it themes the parts Astra leaves largely default
   (gallery frame, price, add-to-cart button, product cards) without
   touching Astra's header/footer/container/typography. Edit the variables
   below, or set colors from Settings > Research Compound Fields. */

@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');

:root{
  --rcpf-ink:#0E1420;
  --rcpf-ink-soft:#586174;
  --rcpf-ink-faint:#8B93A3;
  --rcpf-accent:#5B5FEF;
  --rcpf-accent-soft:#EEEEFD;
  --rcpf-teal:#12A594;
  --rcpf-teal-soft:#E4F7F4;
  --rcpf-gold:#C68A2E;
  --rcpf-gold-soft:#FBF1DF;
  --rcpf-rose:#C4536B;
  --rcpf-rose-soft:#FBEAEE;
  --rcpf-red:#D0473E;
  --rcpf-line:#E4E7EC;
  --rcpf-line-soft:#F1F2F5;
  --rcpf-radius:12px;
  /* Shared soft elevation for the white "panel" cards (molecule,
     metrics, mechanism…) — a tight contact shadow plus a wider, faint
     ambient one, instead of a flat 1px border doing all the work. */
  --rcpf-shadow-card: 0 1px 2px rgba(14,20,32,.05), 0 16px 36px -20px rgba(14,20,32,.16);
  --rcpf-display: 'Space Grotesk', sans-serif;
  --rcpf-mono: 'JetBrains Mono', monospace;
}

/* =========================================================
   SINGLE PRODUCT PAGE
========================================================= */

body.single-product div.product{
  align-items: flex-start !important;
}

/* Hard override: force the buy-box back to normal document flow no
   matter what set it to sticky/fixed — whether that's a leftover
   cached version of this plugin's CSS, or a theme/addon feature like
   Astra Pro's built-in "Sticky Add to Cart" for single products. If
   you actually want a sticky buy box, this is the block to remove —
   but verify on the live site first, since it's what caused the
   overlap bug in the previous version of this plugin.
*/
body.single-product div.product .summary.entry-summary,
body.single-product .ast-single-product-sticky-cart,
body.single-product .astra-sticky-add-to-cart{
  position: static !important;
  top: auto !important;
}

body.single-product div.product .woocommerce-product-gallery{
  border-radius: var(--rcpf-radius);
  overflow: hidden;
  border: 1px solid var(--rcpf-line);
  background:#fafafb;
  box-shadow: var(--rcpf-shadow-card);
  position: relative;
  /* No fixed max-width here on purpose. WooCommerce's own default
     single-product CSS floats .images and .summary side by side as a
     matched pair (each roughly 48% of div.product, e.g. .images{
     width:48%;float:left;margin-right:4%} .summary{width:48%;
     float:right}). A hardcoded max-width here (600px was tried first)
     can end up LARGER than that 48% actually computes to on this site's
     container width — and when a floated box doesn't fit next to its
     sibling float, the sibling gets pushed down to find room instead of
     sitting beside it, which is exactly the huge gap that appeared
     above the title/price. Letting this size itself the same way the
     summary column already does (100% of whatever float width the
     theme hands it) keeps the two columns matched, the way they were
     before this was a single image instead of a multi-image gallery. */
}
body.single-product div.product .woocommerce-product-gallery img{
  border-radius: 0;
  width: 100%;
  height: auto;
  display: block;
  cursor: zoom-in;
  transition: transform .45s cubic-bezier(.2,.7,.2,1);
}
body.single-product div.product .woocommerce-product-gallery:hover img{
  transform: scale(1.06);
}
/* Product video (when uploaded) replaces the <img> in the exact same
   slot — sized/cropped the same way so the hero doesn't jump around
   depending on whether a given product has a video or a photo. */
body.single-product div.product .woocommerce-product-gallery video.rcpf-product-video{
  width: 100%;
  height: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  display: block;
  cursor: default;
}
@media (prefers-reduced-motion: reduce){
  body.single-product div.product .woocommerce-product-gallery img{ transition: none !important; }
}
/* Same swap on shop-grid / related-product cards. */
body.woocommerce ul.products li.product video.rcpf-product-video,
body.woocommerce-page ul.products li.product video.rcpf-product-video{
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: 8px;
  display: block;
}

/* Breadcrumb tidy-up */
body.single-product .woocommerce-breadcrumb{
  font-size: 12.5px;
  color: var(--rcpf-ink-faint);
  margin-bottom: 18px !important;
}
body.single-product .woocommerce-breadcrumb a{ color: var(--rcpf-ink-faint); }
body.single-product .woocommerce-breadcrumb a:hover{ color: var(--rcpf-accent); }

/* Title / price */
body.single-product div.product .product_title{
  font-family: var(--rcpf-display);
  font-weight:700;
  font-size: 30px !important;
  letter-spacing:-0.01em;
  color: var(--rcpf-ink);
  margin-bottom: 4px !important;
}
body.single-product div.product p.price,
body.single-product div.product p.price ins{
  color: var(--rcpf-ink);
  font-weight: 700;
  font-size: 1.7em;
  font-family: var(--rcpf-display);
}
body.single-product div.product p.price del{
  opacity:.5;
  font-weight:400;
  font-size:.6em;
  font-family: var(--rcpf-body, inherit);
}

/* Add to cart / buy buttons — the CTA color is intentionally one
   strong, consistent accent (the brand blue/purple) rather than black,
   so every "act now" control on the page reads as the same visual
   language. */
body.single-product div.product form.cart .button,
body.single-product div.product .single_add_to_cart_button{
  background: var(--rcpf-accent) !important;
  background-image: none !important;
  border-color: var(--rcpf-accent) !important;
  color:#fff !important;
  border-radius: 100px !important;
  padding: 15px 34px !important;
  font-weight: 600 !important;
  font-size: 14.5px !important;
  letter-spacing: 0;
  transition: filter .15s ease, transform .15s ease;
}
body.single-product div.product form.cart .button:hover,
body.single-product div.product .single_add_to_cart_button:hover{
  filter: brightness(0.9);
  transform: translateY(-1px);
}
body.single-product div.product form.cart{
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
}
body.single-product div.product form.cart .quantity input.qty{
  border-radius: 100px;
  border-color: var(--rcpf-line);
  height: 50px;
  width: 64px;
  text-align:center;
  font-family: var(--rcpf-mono);
}

/* Stock / availability text */
body.single-product div.product p.stock{
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--rcpf-teal);
  background: var(--rcpf-teal-soft);
  padding: 5px 11px;
  border-radius: 100px;
  margin-bottom: 14px !important;
}
body.single-product div.product p.stock::before{
  content:'';
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--rcpf-teal);
}
body.single-product div.product p.stock.out-of-stock{
  color:#C6403E;
  background: #FBEAEA;
}
body.single-product div.product p.stock.out-of-stock::before{ background:#C6403E; }

/* Any WooCommerce tabs left standing (e.g. "Additional information" on
   variable products) — Description and Reviews are unhooked in PHP, so
   most products won't render this block at all. Tidied for consistency
   on the products that do still have a tab. */
body.single-product .woocommerce-tabs ul.tabs{
  border-bottom: 1px solid var(--rcpf-line);
  margin-bottom: 20px;
}
body.single-product .woocommerce-tabs ul.tabs li{
  background: none !important;
  border: none !important;
}
body.single-product .woocommerce-tabs ul.tabs li a{
  font-weight: 600;
  color: #9098AC;
}
body.single-product .woocommerce-tabs ul.tabs li.active a{
  color: var(--rcpf-ink);
}

/* Badges under the title — refined to sit with the rest of the type
   system instead of reading like debug output. */
.rcpf-tagline{
  color: var(--rcpf-ink-soft);
  font-size: 15px;
  margin: 2px 0 14px;
}
.rcpf-badges{display:flex;gap:8px;margin:0 0 18px;flex-wrap:wrap;}
.rcpf-pill{display:inline-flex;align-items:center;font-size:12px;font-weight:600;padding:6px 13px;border-radius:100px;font-family: var(--rcpf-body, inherit);}
.rcpf-pill-accent{background:var(--rcpf-teal-soft);color:var(--rcpf-teal);}
.rcpf-pill-muted{background:var(--rcpf-line-soft);color:var(--rcpf-ink-soft);}

/* Quick specs list */
.rcpf-quick-specs{list-style:none;margin:18px 0;padding:16px 0;border-top:1px solid var(--rcpf-line);border-bottom:1px solid var(--rcpf-line);}
.rcpf-quick-specs li{display:flex;justify-content:space-between;font-size:13.5px;padding:6px 0;color:var(--rcpf-ink-soft);}
.rcpf-quick-specs li span{font-weight:600;color:var(--rcpf-ink);}

/* Disclaimer banner */
.rcpf-disclaimer{background:#FFF7E6;border:1px solid #F5DA9E;color:#8A6100;font-size:12.5px;padding:12px 16px;border-radius:8px;margin:18px 0 0;line-height:1.5;}
.rcpf-archive-disclaimer{max-width:1200px;margin:0 auto 24px;}

/* Research Info section table (specifications) */
.rcpf-spec-table{width:100%;border-collapse:collapse;}
.rcpf-spec-table td{padding:12px 0 12px 14px;border-bottom:1px solid var(--rcpf-line-soft);font-size:14px;}
.rcpf-spec-table td:first-child{
  width:220px;
  font-family: var(--rcpf-mono);
  font-size:11.5px;
  font-weight:700;
  text-transform:uppercase;
  letter-spacing:.03em;
  border-left: 3px solid var(--rcpf-line);
}
/* Each spec row's label gets a color from the brand palette, cycling
   through so the table reads as lively/categorized rather than one flat
   block of gray — the accent bar + colored label do the same job an
   icon-per-row would, without needing an icon for every possible field. */
.rcpf-spec-table tr:nth-child(4n+1) td:first-child{ border-left-color: var(--rcpf-accent); color: var(--rcpf-accent); }
.rcpf-spec-table tr:nth-child(4n+2) td:first-child{ border-left-color: var(--rcpf-teal);   color: var(--rcpf-teal); }
.rcpf-spec-table tr:nth-child(4n+3) td:first-child{ border-left-color: var(--rcpf-gold);   color: var(--rcpf-gold); }
.rcpf-spec-table tr:nth-child(4n+4) td:first-child{ border-left-color: var(--rcpf-rose);   color: var(--rcpf-rose); }
.rcpf-spec-table tr:nth-child(even) td{ background: rgba(255,255,255,.55); }

.rcpf-btn{display:inline-flex;align-items:center;gap:6px;font-weight:600;font-size:13.5px;padding:11px 20px;border-radius:100px;border:1px solid transparent;text-decoration:none;margin-right:8px;}
.rcpf-btn-secondary{background:transparent;color:var(--rcpf-ink);border-color:var(--rcpf-line);}
.rcpf-btn-ghost{background:var(--rcpf-accent-soft);color:var(--rcpf-accent);}
.rcpf-btn-sm{padding:8px 15px;font-size:12.5px;}

body.single-product .related.products > h2{
  font-family: var(--rcpf-display);
  font-size: 22px;
  margin: 64px 0 22px;
}

/* =========================================================
   PER-PRODUCT SECTIONS (trust stats, mechanism, applications,
   metrics, FAQ) — all driven by repeatable custom fields, so
   content is genuinely unique from one product to the next.
========================================================= */
.rcpf-section{
  max-width: 1200px;
  margin: 0 auto;
  padding: 76px 24px;
  /* These sections are appended via woocommerce_after_single_product_summary,
     which fires inside div.product, as a sibling to .woocommerce-product-gallery
     and .summary.entry-summary — not after div.product closes. WooCommerce's
     own default single-product CSS lays those two out as classic floated
     columns (float:left / float:right), not flexbox — confirmed from the
     live page HTML, where the gallery and summary are plain floated
     siblings with no flex/grid wrapper. Floated columns don't push
     following content below them on their own: without an explicit
     `clear`, whatever comes next in the DOM starts rendering as soon as
     the SHORTER of the two floated columns ends, overlapping the bottom
     of the taller one — which is exactly what was happening here, since
     the gallery (~370px, sized by the image's own aspect ratio) is
     shorter than the summary column once it has a title, badges, spec
     list, short description and stock message stacked in it. `clear:both`
     is what actually fixes that. flex/width below are kept too, in case
     a different theme or Astra version does use flex/grid instead —
     harmless no-ops when the parent is float-based like it is here. */
  clear: both !important;
  flex: 0 0 100% !important;
  width: 100% !important;
  box-sizing: border-box;
}
.rcpf-section-title{
  font-family: var(--rcpf-display);
  font-size: 26px;
  font-weight: 700;
  color: var(--rcpf-ink);
  margin-bottom: 14px;
}
.rcpf-section-sub{
  color: var(--rcpf-ink-soft);
  font-size: 15px;
  line-height: 1.6;
  margin-bottom: 24px;
}

/* Section eyebrow + heading — the small-caps kicker label used above
   every standalone section (Overview, Full Specification, Certificate
   of Analysis, FAQ, etc.) so each container reads as its own distinct
   module rather than a floating heading. */
.rcpf-section-head{ margin-bottom: 40px; max-width: 720px; }
.rcpf-eyebrow{
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--rcpf-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--rcpf-accent);
  margin-bottom: 10px;
}
.rcpf-eyebrow::before{
  content: "";
  width: 14px;
  height: 1.5px;
  background: var(--rcpf-accent);
  display: inline-block;
}
.rcpf-section-head .rcpf-section-title{ margin-bottom: 12px; }
.rcpf-section-head .rcpf-section-sub{ margin-bottom: 0; }

/* Section color bands — every research section runs full-bleed (see
   .rcpf-full-bleed below) and gets its own soft, distinct background
   wash, so each one reads as a clearly separate module as the page
   scrolls instead of the whole thing blurring into one long white
   surface. Kept as pale washes (not saturated blocks) so body text
   inside each section stays comfortably readable — the color is there
   to mark the section boundary, not to compete with the content. */
/* Simplified 4-tier color system: Primary (white) for most content,
   Secondary (a single very light blue-gray) for rhythm between them,
   Research for the scientific/data sections specifically (one subtle
   tint, not a different color per section), and CTA reserved for
   buttons and the sticky purchase bar rather than a section background.
   Replaces an earlier version of this plugin that gave every section
   its own distinct pastel — visually busier than it needed to be. */
.rcpf-band-primary{   background: #FFFFFF; }
.rcpf-band-secondary{ background: #F4F6FA; }
.rcpf-band-research{  background: #F1F1FB; }

/* Overview and Full Specification are separate full-width sections
   (see render_overview_section / render_specification_section). */
.rcpf-overview-copy{
  max-width: 720px;
  font-size: 15px;
  line-height: 1.8;
  color: var(--rcpf-ink-soft);
}
.rcpf-overview-copy p{ margin: 0 0 1em; }
.rcpf-overview-copy p:last-child{ margin-bottom: 0; }

.rcpf-spec-card{
  position: relative;
  max-width: 760px;
  background: linear-gradient(165deg, #ffffff 0%, var(--rcpf-line-soft) 100%);
  border-radius: 18px;
  padding: 36px 32px 32px;
  box-shadow: var(--rcpf-shadow-card);
  border-width: 4px 0 0 0;
  border-style: solid;
  border-image: linear-gradient(90deg, var(--rcpf-accent), var(--rcpf-teal), var(--rcpf-gold), var(--rcpf-rose)) 1;
}

/* Trust stats row */
.rcpf-stats-row{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 1px;
  background: var(--rcpf-line);
  border: 1px solid var(--rcpf-line);
  border-radius: var(--rcpf-radius);
  overflow: hidden;
  padding: 0;
}
.rcpf-stat{
  background: #fff;
  padding: 22px 16px;
  text-align: center;
  box-shadow: var(--rcpf-shadow-card);
}
.rcpf-stat strong{
  display: block;
  font-family: var(--rcpf-display);
  font-size: 26px;
  font-weight: 700;
  color: var(--rcpf-accent);
}
.rcpf-stat span{
  display: block;
  font-size: 12.5px;
  color: var(--rcpf-ink-soft);
  margin-top: 4px;
}

/* "How it works" — hub-and-spoke diagram (product at center, each
   mechanism as a satellite node) beside the numbered cards. The lines
   and satellites draw themselves in once .rcpf-mechanism-section picks
   up .rcpf-in from the shared scroll-reveal observer (script.js). */
.rcpf-mechanism-layout{
  display: grid;
  grid-template-columns: minmax(320px, 440px) 1fr;
  gap: 48px;
  align-items: start;
}
.rcpf-mech-diagram{
  position: relative;
  background: #fff;
  border: 1px solid var(--rcpf-line);
  border-radius: 20px;
  padding: 40px 32px 28px;
  box-shadow: var(--rcpf-shadow-card);
}
.rcpf-mech-svg{ width: 100%; height: auto; overflow: visible; display: block; }
/* The svg's own box, and nothing else — the label layer (below) is
   scoped to exactly this, not the outer .rcpf-mech-diagram, which also
   contains the padding and caption text below the diagram. Percentage-
   based positioning (the hub label) needs its 50%/50% to land on the
   actual center of the circle, not the center of "svg + caption". */
.rcpf-mech-canvas{ position: relative; }
.rcpf-mech-caption{
  margin: 18px 0 0;
  text-align: center;
  font-family: var(--rcpf-mono);
  font-size: 11.5px;
  color: var(--rcpf-ink-faint);
  letter-spacing: .02em;
}

/* Static dotted guide circle the satellites orbit along — purely
   decorative, gives the eye a ring to anchor the motion to. */
.rcpf-mech-guide-ring{
  fill: none;
  stroke: var(--rcpf-line);
  stroke-width: 1;
  stroke-dasharray: 2.5 4;
}

/* The whole spoke assembly (lines + satellite circles) slowly revolves
   around the fixed hub, so the diagram keeps a gentle sense of motion
   even long after the entrance animation finishes. Satellite LABELS are
   not inside this rotating group at all — they're plain HTML, tracked
   onto their circle's live position every frame by initMechDiagram in
   script.js (see the long comment in render_mechanism_section() for
   why: two independently-timed CSS animations trying to stay in phase
   forever is fragile, reading the circle's actual current position each
   frame cannot drift, by construction). */
.rcpf-mech-orbit-group{
  transform-box: view-box;
  transform-origin: 100px 100px;
  animation: rcpf-mech-orbit 46s linear infinite;
}
@keyframes rcpf-mech-orbit{ to { transform: rotate(360deg); } }

.rcpf-mech-line{
  stroke-width: 1.6;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset .9s cubic-bezier(.2,.7,.2,1);
}
.rcpf-mechanism-section.rcpf-in .rcpf-mech-line{ stroke-dashoffset: 0; }
.rcpf-mech-line-accent{ stroke: var(--rcpf-accent); }
.rcpf-mech-line-teal{   stroke: var(--rcpf-teal); }
.rcpf-mech-line-gold{   stroke: var(--rcpf-gold); }
.rcpf-mech-line-rose{   stroke: var(--rcpf-rose); }

/* Continuous "signal" traveling from hub to satellite — a thin dashed
   duplicate of each line, invisible until the section reveals, then
   looping for as long as the diagram is on screen. Kept as a separate
   element from .rcpf-mech-line above so the one-time draw-in transition
   and this infinite loop never fight over the same stroke-dashoffset. */
.rcpf-mech-line-flow{
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-dasharray: 3 9;
  opacity: 0;
}
.rcpf-mechanism-section.rcpf-in .rcpf-mech-line-flow{
  opacity: .85;
  animation: rcpf-mech-flow 1.8s linear infinite;
}
.rcpf-mech-line-flow-accent{ stroke: var(--rcpf-accent); }
.rcpf-mech-line-flow-teal{   stroke: var(--rcpf-teal); }
.rcpf-mech-line-flow-gold{   stroke: var(--rcpf-gold); }
.rcpf-mech-line-flow-rose{   stroke: var(--rcpf-rose); }
@keyframes rcpf-mech-flow{ to { stroke-dashoffset: -24; } }

.rcpf-mech-sat{
  opacity: 0;
  transform: scale(.6);
  transform-box: fill-box;
  transform-origin: center;
  transition: opacity .6s cubic-bezier(.2,.7,.2,1), transform .6s cubic-bezier(.2,.7,.2,1);
}
.rcpf-mechanism-section.rcpf-in .rcpf-mech-sat{ opacity: 1; transform: scale(1); }
.rcpf-mech-sat-circle{ stroke: rgba(255,255,255,.5); stroke-width: 2; filter: drop-shadow(0 3px 8px rgba(14,20,32,.18)); }
.rcpf-mech-sat-accent .rcpf-mech-sat-circle{ fill: var(--rcpf-accent); }
.rcpf-mech-sat-teal   .rcpf-mech-sat-circle{ fill: var(--rcpf-teal); }
.rcpf-mech-sat-gold   .rcpf-mech-sat-circle{ fill: var(--rcpf-gold); }
.rcpf-mech-sat-rose   .rcpf-mech-sat-circle{ fill: var(--rcpf-rose); }

/* Soft halo that blooms and fades behind each satellite in turn, like a
   signal pulse visiting one target at a time — staggered per-node via
   the inline --rcpf-glow-delay custom property set in PHP. */
.rcpf-mech-sat-glow{
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  filter: blur(7px);
  animation: rcpf-mech-glow 3.6s ease-in-out infinite;
  animation-delay: var(--rcpf-glow-delay, 0s);
}
.rcpf-mech-sat-accent .rcpf-mech-sat-glow{ fill: var(--rcpf-accent); }
.rcpf-mech-sat-teal   .rcpf-mech-sat-glow{ fill: var(--rcpf-teal); }
.rcpf-mech-sat-gold   .rcpf-mech-sat-glow{ fill: var(--rcpf-gold); }
.rcpf-mech-sat-rose   .rcpf-mech-sat-glow{ fill: var(--rcpf-rose); }
@keyframes rcpf-mech-glow{
  0%, 100% { opacity: 0; transform: scale(1); }
  50%      { opacity: .55; transform: scale(1.3); }
}
.rcpf-mech-hub-circle{
  fill: #fff;
  stroke: var(--rcpf-line);
  stroke-width: 1.5;
  filter: drop-shadow(0 4px 14px rgba(14,20,32,.14));
}
/* Slow expanding ring pulsing outward from the hub — a heartbeat that
   keeps the diagram feeling alive even once the entrance animation has
   long finished, without being distracting. */
.rcpf-mech-hub-pulse-ring{
  fill: none;
  stroke: var(--rcpf-accent);
  stroke-width: 2;
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
}
.rcpf-mechanism-section.rcpf-in .rcpf-mech-hub-pulse-ring{
  animation: rcpf-hub-pulse 2.6s ease-out infinite;
  animation-delay: 1s;
}
@keyframes rcpf-hub-pulse{
  0%   { transform: scale(1);    opacity: .45; }
  100% { transform: scale(1.85); opacity: 0; }
}

/* The label layer — plain HTML, sitting on top of the SVG, not inside
   it. Positions are percentages of the diagram box (matching the SVG's
   own 0-200 viewBox 1:1) for the hub, which never moves, and pixel
   values written every animation frame for satellites, which do. */
.rcpf-mech-labels{
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.rcpf-mech-hub-label-html{
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: 40%;
  text-align: center;
  font-family: var(--rcpf-display);
  font-weight: 800;
  line-height: 1.2;
  color: var(--rcpf-ink);
  overflow-wrap: break-word;
  word-break: break-word;
}
.rcpf-mech-sat-label-html{
  position: absolute;
  left: 0; top: 0; /* corrected every frame by initMechDiagram in script.js — these are just a safe starting value */
  transform: translate(-50%, -50%);
  text-align: center;
  font-family: var(--rcpf-display);
  font-weight: 700;
  line-height: 1.22;
  color: #fff;
  overflow-wrap: break-word;
  word-break: break-word;
}
@media (prefers-reduced-motion: reduce){
  .rcpf-mech-line{ transition: none; stroke-dashoffset: 0; }
  .rcpf-mech-sat{ transition: none; opacity: 1; transform: none; }
  .rcpf-mech-line-flow{ animation: none !important; opacity: 0 !important; }
  .rcpf-mech-hub-pulse-ring{ animation: none !important; opacity: 0 !important; }
  .rcpf-mech-orbit-group{ animation: none; }
  .rcpf-mech-sat-glow{ animation: none; opacity: 0; }
}
@media (max-width: 780px){
  .rcpf-mechanism-layout{ grid-template-columns: 1fr; }
  .rcpf-mech-diagram{ max-width: 380px; margin: 0 auto; }
}

/* Mechanism ("how it works") cards — icon + title/subtitle head, a left
   accent border matching the diagram satellite it corresponds to, and
   an optional stack of supporting-detail tags at the bottom. */
.rcpf-mechanism-grid{
  display: flex;
  flex-direction: column;
  gap: 26px;
}
.rcpf-mechanism-card{
  position: relative;
  background: #fff;
  border: 1px solid var(--rcpf-line);
  border-left: 3px solid var(--rcpf-accent);
  border-radius: var(--rcpf-radius);
  padding: 24px 26px 22px;
  box-shadow: var(--rcpf-shadow-card);
  transition: transform .18s ease, box-shadow .18s ease;
}
.rcpf-mechanism-card:hover{
  transform: translateY(-2px);
  box-shadow: 0 1px 2px rgba(14,20,32,.06), 0 20px 40px -18px rgba(14,20,32,.22);
}
.rcpf-mechanism-card-accent{ border-left-color: var(--rcpf-accent); }
.rcpf-mechanism-card-teal{   border-left-color: var(--rcpf-teal); }
.rcpf-mechanism-card-gold{   border-left-color: var(--rcpf-gold); }
.rcpf-mechanism-card-rose{   border-left-color: var(--rcpf-rose); }

.rcpf-mech-card-head{
  display: flex;
  align-items: flex-start;
  gap: 14px;
  margin-bottom: 14px;
}
.rcpf-mech-card-icon{
  flex: 0 0 auto;
  width: 42px;
  height: 42px;
  border-radius: 11px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.rcpf-mech-card-icon svg{ width: 20px; height: 20px; }
.rcpf-mechanism-card-accent .rcpf-mech-card-icon{ background: color-mix(in srgb, var(--rcpf-accent) 14%, #fff); color: var(--rcpf-accent); }
.rcpf-mechanism-card-teal   .rcpf-mech-card-icon{ background: color-mix(in srgb, var(--rcpf-teal) 14%, #fff);   color: var(--rcpf-teal); }
.rcpf-mechanism-card-gold   .rcpf-mech-card-icon{ background: color-mix(in srgb, var(--rcpf-gold) 14%, #fff);   color: var(--rcpf-gold); }
.rcpf-mechanism-card-rose   .rcpf-mech-card-icon{ background: color-mix(in srgb, var(--rcpf-rose) 14%, #fff);   color: var(--rcpf-rose); }

.rcpf-mechanism-card h4{
  font-family: var(--rcpf-display);
  font-size: 16.5px;
  font-weight: 700;
  color: var(--rcpf-ink);
  margin: 0 0 3px;
  line-height: 1.3;
}
.rcpf-mech-card-subtitle{
  display: block;
  font-size: 12.5px;
  color: var(--rcpf-ink-soft);
}
.rcpf-mechanism-card p{
  font-size: 13.5px;
  color: var(--rcpf-ink-soft);
  line-height: 1.65;
  margin: 0;
}
.rcpf-mech-card-tags{
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 16px;
}
.rcpf-mech-tag{
  font-family: var(--rcpf-mono);
  font-size: 12px;
  line-height: 1.5;
  padding: 9px 13px;
  border-radius: 8px;
  border: 1px solid var(--rcpf-line);
}
.rcpf-mechanism-card-accent .rcpf-mech-tag{ background: color-mix(in srgb, var(--rcpf-accent) 7%, #fff); border-color: color-mix(in srgb, var(--rcpf-accent) 22%, #fff); color: color-mix(in srgb, var(--rcpf-accent) 75%, var(--rcpf-ink)); }
.rcpf-mechanism-card-teal   .rcpf-mech-tag{ background: color-mix(in srgb, var(--rcpf-teal) 7%, #fff);   border-color: color-mix(in srgb, var(--rcpf-teal) 22%, #fff);   color: color-mix(in srgb, var(--rcpf-teal) 75%, var(--rcpf-ink)); }
.rcpf-mechanism-card-gold   .rcpf-mech-tag{ background: color-mix(in srgb, var(--rcpf-gold) 7%, #fff);   border-color: color-mix(in srgb, var(--rcpf-gold) 22%, #fff);   color: color-mix(in srgb, var(--rcpf-gold) 75%, var(--rcpf-ink)); }
.rcpf-mechanism-card-rose   .rcpf-mech-tag{ background: color-mix(in srgb, var(--rcpf-rose) 7%, #fff);   border-color: color-mix(in srgb, var(--rcpf-rose) 22%, #fff);   color: color-mix(in srgb, var(--rcpf-rose) 75%, var(--rcpf-ink)); }

/* Applications cards — flat tinted background, category tag on top,
   deliberately different treatment from the mechanism cards. */
.rcpf-applications-grid{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 24px;
}
.rcpf-app-card{
  background: var(--rcpf-line-soft);
  border-radius: var(--rcpf-radius);
  padding: 28px;
  box-shadow: var(--rcpf-shadow-card);
}
.rcpf-app-cat{
  display: inline-block;
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--rcpf-accent);
  background: #fff;
  padding: 3px 9px;
  border-radius: 100px;
}
.rcpf-app-card h4{
  font-family: var(--rcpf-display);
  font-size: 15px;
  font-weight: 700;
  color: var(--rcpf-ink);
  margin: 10px 0 8px;
}
.rcpf-app-card p{
  font-size: 13.5px;
  color: var(--rcpf-ink-soft);
  line-height: 1.6;
  margin: 0;
}

/* Study-reported magnitude bars — boxed panel so it reads as a distinct
   "data" module rather than another card grid. */
/* Scroll-reveal: applied to every major research section. Purely a
   fade + slight rise, no layout shift, and disabled entirely for
   reduced-motion users below. */
.rcpf-reveal{
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .7s cubic-bezier(.2,.7,.2,1), transform .7s cubic-bezier(.2,.7,.2,1);
}
.rcpf-reveal.rcpf-in{
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce){
  .rcpf-reveal{ opacity: 1 !important; transform: none !important; transition: none !important; }
}

/* Full-bleed section wrapper — breaks a section out of the shared
   1200px content column AND out of whatever container it's actually
   nested in (div.product, the theme's page-width wrapper, etc.) to run
   genuinely edge-to-edge, independent of any other section's layout.
   Used by the molecule section so the cluster and its copy have real
   room. The classic "negative viewport margin" technique is used
   instead of a plain width:100%, because width:100% only fills
   whatever container the element happens to be nested in — here that's
   div.product's flex row (see the note on .rcpf-section above), which
   is exactly what was capping it before. flex-basis/width/margin here
   all carry !important specifically to out-rank that base .rcpf-section
   rule (same trick, opposite goal). `.rcpf-full-bleed-inner` then
   re-establishes a reading max-width inside it so text and the diagram
   don't stretch edge-to-edge themselves on very wide screens. */
.rcpf-section.rcpf-full-bleed{
  flex: 0 0 100vw !important;
  width: 100vw !important;
  max-width: 100vw !important;
  margin-left: calc(50% - 50vw) !important;
  margin-right: calc(50% - 50vw) !important;
  padding-left: 0;
  padding-right: 0;
  box-sizing: border-box;
}
.rcpf-full-bleed-inner{
  max-width: 1520px;
  margin: 0 auto;
  padding: 0 32px;
  box-sizing: border-box;
}

/* Molecule section — a ball-and-stick cluster built per-product from the
   compound's own molecular formula (see RCPF_Fields::parse_formula /
   atom_color and RCPF_Templates::render_molecule_section). Light card,
   colors set inline per element (so every atom in the formula gets its
   own true color, not a shared bucket) — legend underneath. Schematic,
   not a measured structure (said explicitly in the copy beside it). */
.rcpf-molecule-panel{
  display: grid;
  grid-template-columns: minmax(320px, 460px) 1fr;
  gap: 64px;
  align-items: center;
  background: #fff;
  border: 1px solid var(--rcpf-line);
  border-radius: 20px;
  padding: 48px;
  box-shadow: var(--rcpf-shadow-card);
}
.rcpf-molecule-visual{
  aspect-ratio: 1 / 1;
  background: radial-gradient(circle at 50% 40%, #FDFDFF 0%, #EAEDF4 100%);
  border-radius: 16px;
  overflow: hidden;
  box-shadow: inset 0 0 0 1px var(--rcpf-line-soft);
  position: relative;
}
/* The custom pasted 3D viewer (see the "3D Molecule Viewer" product
   field) — a sandboxed iframe, not inline markup, so whatever it does
   to its own document can't affect this page (see the long comment in
   render_molecule_section() for why). Iframes default to a tiny fixed
   size unless styled, so this needs the same square, responsive
   sizing .rcpf-molecule-visual gets above. */
.rcpf-3d-viewer-frame{
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  border: 0;
  border-radius: 16px;
  overflow: hidden;
  background: transparent;
}
.rcpf-molecule-svg{ width: 100%; height: 100%; }

/* Once script.js mounts the 3D renderer it replaces this element's
   entire content with a fresh <svg class="rcpf-molecule-svg-3d">, so
   the noscript fallback (rendered flat, no JS) is simply never present
   for JS users — nothing extra to hide. .rcpf-mol-3d-ready is added at
   mount time purely as a styling/debugging hook. */
.rcpf-molecule-svg-3d{ display: block; }
.rcpf-mol-node-3d{ filter: drop-shadow(0 1px 2px rgba(14,20,32,.22)); }
.rcpf-mol-bond-3d{ stroke: #B9C1D1; }

/* Small "drag to rotate" affordance, bottom-left of the visual, fading
   out the moment someone drags (or after a few seconds untouched). */
.rcpf-mol-3d-hint{
  position: absolute;
  left: 16px;
  bottom: 14px;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border-radius: 999px;
  background: rgba(255,255,255,.85);
  backdrop-filter: blur(4px);
  box-shadow: 0 1px 2px rgba(14,20,32,.08), 0 6px 16px -8px rgba(14,20,32,.18);
  font-family: var(--rcpf-mono);
  font-size: 11px;
  color: var(--rcpf-ink-soft);
  pointer-events: none;
  opacity: 1;
  transition: opacity .5s ease, transform .5s ease;
}
.rcpf-mol-3d-hint-out{ opacity: 0; transform: translateY(4px); }
@media (prefers-reduced-motion: reduce){
  .rcpf-mol-3d-hint{ transition: none; }
}
.rcpf-mol-trace{
  stroke: #C7CEDB;
  stroke-width: .55;
}
.rcpf-mol-trace-cross{ stroke: #D8DEE9; stroke-width: .4; }

.rcpf-mol-node{
  animation: rcpf-mol-pulse 3.2s ease-in-out infinite;
  filter: drop-shadow(0 1px 1px rgba(14,20,32,.18));
}

@keyframes rcpf-mol-pulse{
  0%, 100% { opacity: .78; }
  50% { opacity: 1; }
}
/* Slow independent drift per node, three variants cycled by index so
   neighbors never move in lockstep. Purely decorative transforms —
   position is already set via cx/cy, these just nudge it a little. */
@keyframes rcpf-mol-float-0{
  0%, 100% { transform: translate(0,0); }
  50% { transform: translate(.6px,-1px); }
}
@keyframes rcpf-mol-float-1{
  0%, 100% { transform: translate(0,0); }
  50% { transform: translate(-.8px,.5px); }
}
@keyframes rcpf-mol-float-2{
  0%, 100% { transform: translate(0,0); }
  50% { transform: translate(.5px,.9px); }
}
.rcpf-mol-float-0{ animation: rcpf-mol-float-0 4.2s ease-in-out infinite, rcpf-mol-pulse 3.2s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
.rcpf-mol-float-1{ animation: rcpf-mol-float-1 5.1s ease-in-out infinite, rcpf-mol-pulse 3.2s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
.rcpf-mol-float-2{ animation: rcpf-mol-float-2 4.6s ease-in-out infinite, rcpf-mol-pulse 3.2s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }

@media (prefers-reduced-motion: reduce){
  .rcpf-mol-node{ animation: none !important; }
}

.rcpf-mol-legend{
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-top: 16px;
  justify-content: center;
}
.rcpf-mol-legend-item{
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--rcpf-mono);
  font-size: 11px;
  font-weight: 500;
  color: var(--rcpf-ink-soft);
  text-transform: uppercase;
  letter-spacing: .03em;
}
.rcpf-mol-legend-dot{
  width: 11px;
  height: 11px;
  border-radius: 50%;
  display: inline-block;
  background: radial-gradient(circle at 32% 28%, color-mix(in srgb, var(--dot-color) 45%, #fff) 0%, var(--dot-color) 55%, color-mix(in srgb, var(--dot-color) 55%, #000) 100%);
  box-shadow: 0 1px 2px rgba(14,20,32,.22);
}

.rcpf-molecule-data h2{ margin-bottom: 10px; }

/* Molecular formula card — eyebrow label, big subscripted formula, then
   a bordered grid of key/value spec cells. Only whichever cells have
   data render, so a product with just weight + purity gets a clean
   2-cell row instead of empty gaps. */
.rcpf-formula-card{
  margin-top: 22px;
  background: #fff;
  border: 1px solid var(--rcpf-line);
  border-radius: 16px;
  overflow: hidden;
  box-shadow: var(--rcpf-shadow-card);
}
.rcpf-formula-card-head{
  padding: 24px 26px 26px;
  background: linear-gradient(180deg, #FBFCFE 0%, #F2F4F8 100%);
  border-bottom: 1px solid var(--rcpf-line);
}
.rcpf-formula-eyebrow{
  display: block;
  font-family: var(--rcpf-mono);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--rcpf-ink-faint);
  margin-bottom: 10px;
}
.rcpf-formula-big{
  font-family: var(--rcpf-mono);
  font-size: 34px;
  font-weight: 700;
  color: var(--rcpf-ink);
  line-height: 1.1;
  letter-spacing: .01em;
}
.rcpf-formula-big sub{ font-size: .55em; }
.rcpf-formula-grid{
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}
.rcpf-formula-cell{
  padding: 18px 22px;
  border-bottom: 1px solid var(--rcpf-line);
}
.rcpf-formula-cell:nth-child(3n+1){ border-right: 1px solid var(--rcpf-line); }
.rcpf-formula-cell:nth-child(3n+2){ border-right: 1px solid var(--rcpf-line); }
.rcpf-formula-cell:nth-last-child(-n+3){ border-bottom: none; }
.rcpf-formula-cell span{
  display: block;
  font-family: var(--rcpf-mono);
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--rcpf-ink-faint);
  margin-bottom: 6px;
}
.rcpf-formula-cell strong{
  font-family: var(--rcpf-display);
  font-size: 15px;
  font-weight: 700;
  color: var(--rcpf-ink);
  line-height: 1.3;
}
@media (max-width: 560px){
  .rcpf-formula-grid{ grid-template-columns: repeat(2, 1fr); }
  .rcpf-formula-cell:nth-child(3n+1),
  .rcpf-formula-cell:nth-child(3n+2){ border-right: 1px solid var(--rcpf-line); }
  .rcpf-formula-cell:nth-child(2n){ border-right: none; }
  .rcpf-formula-cell:nth-last-child(-n+3){ border-bottom: 1px solid var(--rcpf-line); }
  .rcpf-formula-cell:nth-last-child(-n+2){ border-bottom: none; }
  .rcpf-formula-big{ font-size: 26px; }
}
@media (max-width: 1100px){
  .rcpf-molecule-panel{ grid-template-columns: minmax(260px, 380px) 1fr; gap: 40px; padding: 36px; }
}
@media (max-width: 700px){
  .rcpf-full-bleed-inner{ padding: 0 20px; }
  .rcpf-molecule-panel{ grid-template-columns: 1fr; padding: 24px; }
  .rcpf-molecule-visual-wrap{ max-width: 280px; margin: 0 auto; }
}

.rcpf-metrics-panel{
  max-width: 640px;
  background: #fff;
  border: 1px solid var(--rcpf-line);
  border-radius: var(--rcpf-radius);
  padding: 24px 26px;
  box-shadow: var(--rcpf-shadow-card);
}
.rcpf-metrics-list{ }
.rcpf-metric-row{
  display: grid;
  grid-template-columns: 180px 1fr 44px;
  align-items: center;
  gap: 14px;
  margin-bottom: 14px;
}
.rcpf-metric-row:last-child{ margin-bottom: 0; }
.rcpf-metric-label{ font-size: 13.5px; color: var(--rcpf-ink); font-weight: 600; }
.rcpf-metric-bar{
  height: 8px;
  background: var(--rcpf-line-soft);
  border-radius: 100px;
  overflow: hidden;
}
.rcpf-metric-fill{
  height: 100%;
  background: linear-gradient(90deg, var(--rcpf-accent), var(--rcpf-teal));
  border-radius: 100px;
}
.rcpf-metric-pct{ font-size: 12.5px; color: var(--rcpf-ink-soft); text-align: right; font-family: monospace; }
@media (max-width: 560px){
  .rcpf-metric-row{ grid-template-columns: 100px 1fr 36px; gap: 8px; }
}

/* Certificate-of-Analysis panel inside the COA tab — dark accent header,
   its own distinct "document" visual language. */
.rcpf-coa-cert{
  max-width: 560px;
  background: #fff;
  border: 1px solid var(--rcpf-line);
  border-radius: 20px;
  padding: 32px 32px 28px;
  box-shadow: var(--rcpf-shadow-card);
}
.rcpf-coa-cert-checks{
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-bottom: 22px;
}
.rcpf-coa-check{
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--rcpf-display);
  font-weight: 700;
  font-size: 15.5px;
  color: var(--rcpf-ink);
}
.rcpf-coa-check svg{
  flex: 0 0 auto;
  width: 26px; height: 26px;
  padding: 5px;
  box-sizing: border-box;
  border-radius: 50%;
  background: var(--rcpf-teal);
  color: #fff;
}
.rcpf-coa-cert-rows{
  padding: 16px 0;
  margin-bottom: 20px;
  border-top: 1px solid var(--rcpf-line-soft);
  border-bottom: 1px solid var(--rcpf-line-soft);
}
.rcpf-coa-cert-rows div{
  display: flex;
  justify-content: space-between;
  padding: 7px 0;
  font-size: 13.5px;
}
.rcpf-coa-cert-rows span{ color: var(--rcpf-ink-soft); }
.rcpf-coa-cert-rows strong{ color: var(--rcpf-ink); }
.rcpf-coa-cert-actions{ display: flex; gap: 10px; }
.rcpf-coa-cert-actions .rcpf-btn{ flex: 1; justify-content: center; margin-right: 0; }

/* Product-specific FAQ — each question is its own rounded white card
   (not a plain bordered list row) with a circular +/- button, matching
   the more modern accordion style referenced. */
.rcpf-faq-list{ max-width: 780px; display: flex; flex-direction: column; gap: 16px; }
.rcpf-faq-item{
  background: #fff;
  border-radius: 16px;
  box-shadow: var(--rcpf-shadow-card);
  overflow: hidden;
  transition: box-shadow .2s ease;
}
.rcpf-faq-item.open{ box-shadow: var(--rcpf-shadow-card-hover); }
.rcpf-faq-q{
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 22px 26px;
  cursor: pointer;
  font-family: var(--rcpf-display);
  font-weight: 700;
  font-size: 15px;
  color: var(--rcpf-ink);
}
.rcpf-faq-plus{
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px; height: 30px;
  border-radius: 50%;
  background: var(--rcpf-line-soft);
  color: var(--rcpf-ink-soft);
  font-size: 16px;
  line-height: 1;
  transition: transform .2s ease, background .2s ease, color .2s ease;
}
.rcpf-faq-item.open .rcpf-faq-plus{
  transform: rotate(45deg);
  background: var(--rcpf-accent);
  color: #fff;
}
.rcpf-faq-a{ max-height: 0; overflow: hidden; transition: max-height .25s ease; }
.rcpf-faq-item.open .rcpf-faq-a{ max-height: 300px; }
.rcpf-faq-a p{ padding: 0 26px 24px; font-size: 14px; color: var(--rcpf-ink-soft); line-height: 1.65; margin: 0; }

/* =========================================================
   EXCESS-SPACE SAFETY NET
   Common causes of a big empty gap above the shop grid on
   Elementor + Astra builds: (1) an empty Elementor section left
   over from a template with a large min-height, (2) WooCommerce's
   default page-title/breadcrumb block carrying its own padding
   on top of the theme's, (3) an Elementor "Store coming soon"
   banner reserving height even when hidden. These rules only
   fix causes (2); (1) and (3) live in page content, not CSS —
   see the readme's "Fixing extra whitespace" section.
========================================================= */
body.woocommerce-shop .page-title,
body.woocommerce-shop .ast-archive-title,
body.tax-product_cat .page-title{
  padding-top: 8px;
  margin-bottom: 8px;
}
body.woocommerce-shop .site-content > .ast-container,
body.tax-product_cat .site-content > .ast-container{
  padding-top: 24px;
}
/* Elementor sometimes leaves a zero-content section with a forced
   min-height above the loop; this collapses any truly empty one. */
.elementor-section:empty,
.elementor-container:empty{
  min-height: 0 !important;
  padding: 0 !important;
}

/* =========================================================
   SHOP / CATEGORY ARCHIVE — PRODUCT CARDS
========================================================= */

/* THE definitive fix for the missing first card: WooCommerce's own
   clearfix rule puts `content:" "; display:table;` on ul.products::before
   and ::after — harmless under the old float layout (a clearfix table
   pseudo-element collapses to zero size there), but once the list
   becomes `display:grid`, the CSS Grid spec requires every in-flow
   child — including generated ::before/::after content — to become a
   real grid item. That ::before was silently claiming the FIRST grid
   cell, pushing every actual product one slot to the right and leaving
   an empty first slot exactly where it sat. Confirmed directly via
   devtools (ul.rcpf-products-grid.products.columns-4::before showing up
   as a real, positioned box). A grid/flex layout never needed a
   clearfix pseudo-element in the first place — that trick only exists
   to contain floated children — so it's removed outright rather than
   patched. */
.rcpf-products-grid::before,
.rcpf-products-grid::after,
body.woocommerce ul.products::before,
body.woocommerce ul.products::after,
body.woocommerce-page ul.products::before,
body.woocommerce-page ul.products::after{
  content: none !important;
  display: none !important;
}

/* Every rule below is anchored on .rcpf-products-grid (added to every
   product <ul> this plugin touches — shop, category, related products,
   AND the [rcpf_shop] shortcode — via add_grid_class()) rather than
   relying on body.woocommerce / body.woocommerce-page alone. Those body
   classes are only present on WooCommerce's own archive templates —
   the shortcode is commonly dropped onto a plain page (a landing page,
   the homepage) that never gets them, which is exactly why shortcode-
   rendered cards were falling back to whatever the theme/page-builder's
   own (in this case, pink) link/text color happened to be instead of
   this plugin's own styling. The body-class selectors are kept
   alongside for the pages where both are present — harmless
   duplication, not a conflict, since the rules are identical. */
.rcpf-products-grid li.product,
body.woocommerce ul.products li.product,
body.woocommerce-page ul.products li.product{
  position: relative;
  background:#fff;
  border: 1px solid var(--rcpf-line);
  border-radius: var(--rcpf-radius);
  padding: 14px 14px 18px !important;
  box-shadow: var(--rcpf-shadow-card);
  transition: box-shadow .18s ease, transform .18s ease;
  /* Equal-height cards: stretch to the tallest card in the row (grid
     does this by default with align-items:stretch), then lay the
     card out as a column so the footer can be pinned to the bottom
     regardless of how much text is above it.
     width/float/margin/max-width are reset here because WooCommerce's
     own default styling sizes cards with a float-era percentage width
     (e.g. width:30%;float:left) — floats are automatically ignored for
     children of a grid container, but an explicit WIDTH is not, and it
     was overriding the grid's own track sizing, which is what actually
     turned every card into a narrow sliver floating inside a much wider
     empty grid cell. */
  width: auto !important;
  max-width: none !important;
  float: none !important;
  margin: 0 !important;
  display: flex !important;
  flex-direction: column;
  height: 100%;
  opacity: 1 !important;
  visibility: visible !important;
}
.rcpf-products-grid,
body.woocommerce ul.products,
body.woocommerce-page ul.products{
  display: grid !important;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 28px;
  align-items: stretch;
}
.rcpf-products-grid li.product:hover,
body.woocommerce ul.products li.product:hover,
body.woocommerce-page ul.products li.product:hover{
  box-shadow: 0 10px 30px -14px rgba(14,20,32,.18);
  transform: translateY(-2px);
}
.rcpf-products-grid li.product a img,
body.woocommerce ul.products li.product a img,
body.woocommerce-page ul.products li.product a img{
  border-radius: 8px;
  aspect-ratio: 1 / 1;
  object-fit: cover;
}
.rcpf-products-grid li.product .woocommerce-loop-product__title,
body.woocommerce ul.products li.product .woocommerce-loop-product__title,
body.woocommerce-page ul.products li.product .woocommerce-loop-product__title{
  font-family: var(--rcpf-display) !important;
  font-weight: 600 !important;
  font-size: 15.5px !important;
  color: var(--rcpf-ink) !important;
  margin: 10px 0 4px !important;
  /* Clamp to 2 lines so a long product name doesn't push everything
     below it out of alignment with shorter-named cards in the row. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 2.7em;
}
.rcpf-products-grid li.product .price,
body.woocommerce ul.products li.product .price,
body.woocommerce-page ul.products li.product .price{
  color: var(--rcpf-ink) !important;
  font-weight: 700 !important;
}
.rcpf-products-grid li.product .button,
body.woocommerce ul.products li.product .button,
body.woocommerce-page ul.products li.product .button{
  border-radius: 100px !important;
  background: var(--rcpf-ink) !important;
  color:#fff !important;
  border-color: var(--rcpf-ink) !important;
  font-size: 13px !important;
  padding: 9px 16px !important;
  font-weight: 600 !important;
}
.rcpf-products-grid li.product .button:hover,
body.woocommerce ul.products li.product .button:hover,
body.woocommerce-page ul.products li.product .button:hover{
  background: var(--rcpf-accent) !important;
  border-color: var(--rcpf-accent) !important;
}

.rcpf-loop-badge{
  position:absolute;
  top:24px;
  left:24px;
  background:#fff;
  box-shadow:0 2px 8px rgba(0,0,0,.10);
  z-index:2;
}

/* COA corner ribbon */
.rcpf-coa-corner{
  position: absolute;
  top: 14px;
  right: 14px;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  background: var(--rcpf-ink);
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .04em;
  padding: 5px 9px;
  border-radius: 100px;
}

/* Tagline + meta pills on the card */
.rcpf-loop-tagline{
  font-size: 12.5px;
  color: var(--rcpf-ink-soft);
  margin: 0 0 8px;
  /* Single line, no wrap — keeps the block above the footer a
     consistent height across every card. */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rcpf-loop-pills{
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.rcpf-loop-pills .rcpf-pill{ font-size: 10.5px; padding: 4px 9px; }

/* Two-button card footer: View + Add to Cart. Pinned to the bottom of
   the card via margin-top:auto so every row's buttons line up even
   when the text above varies in length. */
.rcpf-card-footer{
  display: flex;
  gap: 8px;
  margin-top: auto;
  padding-top: 10px;
}
.rcpf-card-footer .rcpf-btn{
  flex: 1;
  justify-content: center;
  margin-right: 0;
}
.rcpf-card-footer .button,
.rcpf-card-footer a.add_to_cart_button,
.rcpf-card-footer a.button{
  flex: 1;
  text-align: center;
  border-radius: 100px !important;
  background: var(--rcpf-accent) !important;
  color: #fff !important;
  border-color: var(--rcpf-accent) !important;
  font-size: 13px !important;
  padding: 9px 14px !important;
  font-weight: 600 !important;
  margin: 0 !important;
}
.rcpf-card-footer .button:hover,
.rcpf-card-footer a.add_to_cart_button:hover{
  filter: brightness(0.9);
  border-color: var(--rcpf-accent) !important;
}

/* =========================================================
   CHECKOUT
========================================================= */
.rcpf-checkout-ack{margin:16px 0;padding:14px 16px;border:1px solid var(--rcpf-line);border-radius:8px;background:#FAFAFB;}
.rcpf-checkout-ack label{display:flex;gap:10px;align-items:flex-start;font-size:13.5px;color:var(--rcpf-ink-soft);cursor:pointer;}
.rcpf-checkout-ack input{margin-top:3px;}

/* =========================================================
   COA DATABASE SHORTCODE
========================================================= */
.rcpf-coa-db{max-width:1000px;margin:0 auto;}
.rcpf-coa-search{display:flex;gap:10px;margin-bottom:20px;}
.rcpf-coa-search input{flex:1;max-width:320px;border:1px solid var(--rcpf-line);border-radius:8px;padding:10px 14px;font-size:14px;}
.rcpf-coa-table{width:100%;border-collapse:collapse;}
.rcpf-coa-table th{text-align:left;font-size:11.5px;text-transform:uppercase;color:#9098AC;padding:10px;border-bottom:1px solid var(--rcpf-line);}
.rcpf-coa-table td{padding:12px 10px;border-bottom:1px solid var(--rcpf-line-soft);font-size:14px;}

/* [rcpf_shop] shortcode embed */
.rcpf-shop-embed-viewall{ text-align:center; margin-top:8px; }

/* [rcpf_product_hero] shortcode — a showcase block for landing pages,
   not the paginated shop grid. CSS grid auto-fit is what actually makes
   this responsive: the column count adjusts itself to whatever width
   is available (down to a single column on phones) with no separate
   mobile markup or breakpoint-specific column-count rules to keep in
   sync. */
.rcpf-hero-showcase{ max-width:1320px; margin:0 auto; padding:20px; }
.rcpf-hero-showcase-head{ text-align:center; max-width:640px; margin:0 auto 32px; }
.rcpf-hero-showcase-head h2{
  font-family: var(--rcpf-display);
  font-size: 28px;
  font-weight: 800;
  color: var(--rcpf-ink);
  margin: 0 0 8px;
}
.rcpf-hero-showcase-head p{ color: var(--rcpf-ink-soft); font-size: 15px; margin: 0; }
.rcpf-hero-showcase-grid{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 24px;
}
.rcpf-hero-card{
  background: #fff;
  border: 1px solid var(--rcpf-line);
  border-radius: 18px;
  overflow: hidden;
  box-shadow: var(--rcpf-shadow-card);
  transition: box-shadow .25s ease, transform .25s ease;
  display: flex;
  flex-direction: column;
}
.rcpf-hero-card:hover{ box-shadow: var(--rcpf-shadow-card-hover); transform: translateY(-3px); }
.rcpf-hero-card-media{
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: #fafafb;
}
.rcpf-hero-card-media img{
  width: 100%; height: 100%; object-fit: cover;
  transition: transform .5s cubic-bezier(.2,.7,.2,1);
}
.rcpf-hero-card:hover .rcpf-hero-card-media img{ transform: scale(1.06); }
.rcpf-hero-card-body{ padding: 20px 22px 22px; flex: 1; display: flex; flex-direction: column; }
.rcpf-hero-card-title{
  display: block;
  font-family: var(--rcpf-display);
  font-weight: 700;
  font-size: 18px;
  color: var(--rcpf-ink);
  text-decoration: none;
  margin-bottom: 4px;
}
.rcpf-hero-card-tagline{ color: var(--rcpf-ink-soft); font-size: 13.5px; margin: 0 0 16px; flex: 1; }
.rcpf-hero-card-foot{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-top: 14px;
  border-top: 1px solid var(--rcpf-line-soft);
}
.rcpf-hero-card-price{ font-family: var(--rcpf-mono); font-weight: 700; font-size: 15px; color: var(--rcpf-ink); }
.rcpf-hero-card-price del{ color: var(--rcpf-ink-faint); font-weight: 400; margin-right: 4px; }
@media (max-width: 520px){
  .rcpf-hero-showcase-head h2{ font-size: 23px; }
  .rcpf-hero-showcase-grid{ grid-template-columns: 1fr; }
}

@media (max-width: 600px){
  .rcpf-loop-badge{top:14px;left:14px;font-size:10.5px;padding:4px 9px;}
}

/* Variable-product size swatches (see initSizeSwatches in script.js).
   The dropdown is hidden directly by JS now (not via this class on a
   specific ancestor — that assumed an exact ".variations" wrapper
   existed, which isn't guaranteed everywhere), so this class is now
   just what strips the wrapper's own box treatment: WooCommerce/theme
   styling on the dropdown's table/row (background, padding, borders)
   was written for a plain dropdown, not a set of cards, and left the
   cards sitting inside a second, redundant panel. */
.rcpf-swatches-active,
.rcpf-swatches-active td,
.rcpf-swatches-active th,
.rcpf-swatches-active tr{
  background: none !important;
  border: none !important;
  box-shadow: none !important;
  padding: 0 !important;
  margin: 0 !important;
}
.rcpf-swatches-active{ display: block !important; }

/* The attribute label WooCommerce prints just above the dropdown
   ("Weight", "Size", whatever the attribute is named) — restyled to
   match the small-caps eyebrow label used the rest of the page over,
   instead of looking like a plain form field label. */
.rcpf-swatches-active .label,
.rcpf-swatches-active > label{
  display: block;
  font-family: var(--rcpf-mono);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--rcpf-ink-faint);
  margin-bottom: 10px;
}

.rcpf-size-swatches{
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin: 4px 0;
}
.rcpf-size-swatch{
  position: relative;
  min-width: 168px;
  border: 1.5px solid var(--rcpf-line);
  border-radius: 14px;
  padding: 16px 20px 14px;
  cursor: pointer;
  background: #fff;
  box-shadow: 0 1px 2px rgba(14,20,32,.03);
  transition: border-color .15s ease, background .15s ease, box-shadow .15s ease, transform .15s ease;
}
.rcpf-size-swatch:hover{ border-color: var(--rcpf-ink-faint); transform: translateY(-1px); }
.rcpf-size-swatch.selected{
  border-color: var(--rcpf-accent);
  background: var(--rcpf-accent-soft);
  box-shadow: 0 0 0 1.5px var(--rcpf-accent);
}
/* Sold-out / currently-unavailable size — WooCommerce leaves a variation
   out of the price data entirely once it's out of stock, which used to
   mean the swatch just rendered blank with no price and no explanation
   (looked broken, not "sold out"). Grayed out, not clickable, and says
   so plainly instead. */
.rcpf-size-swatch.unavailable{
  cursor: default;
  background: var(--rcpf-line-soft);
  border-color: var(--rcpf-line);
  opacity: .65;
}
.rcpf-size-swatch.unavailable:hover{ transform: none; border-color: var(--rcpf-line); }
.rcpf-size-swatch-unavailable{
  color: var(--rcpf-ink-faint) !important;
  font-style: italic;
}
.rcpf-size-swatch-top{
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 18px;
}
.rcpf-size-swatch-label{ font-family: var(--rcpf-display); font-weight: 700; font-size: 18px; color: var(--rcpf-ink); }
.rcpf-size-swatch-price{ font-family: var(--rcpf-display); font-weight: 700; font-size: 19px; color: var(--rcpf-ink); }
.rcpf-size-swatch-unit{ display: block; margin-top: 4px; font-family: var(--rcpf-mono); font-size: 12px; color: var(--rcpf-ink-faint); }
.rcpf-size-badge{
  position: absolute;
  top: -11px;
  left: 14px;
  font-family: var(--rcpf-mono);
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .02em;
  padding: 3px 9px;
  border-radius: 100px;
  color: #fff;
  white-space: nowrap;
}
.rcpf-size-badge-best{ background: var(--rcpf-teal); }
.rcpf-size-badge-save{ background: var(--rcpf-accent-soft); color: var(--rcpf-accent); }
@media (max-width: 480px){
  .rcpf-size-swatch{ min-width: 0; flex: 1 1 45%; }
}

/* One single price on screen, not two — see the JS-driven hiding of the
   top summary price range in initSizeSwatches (script.js), which only
   does this for products where swatches actually took over (so a
   replacement price is guaranteed to auto-populate; a plain CSS rule
   here would also hide the price on multi-attribute variable products,
   where swatches don't apply and nothing would auto-select to replace
   it — leaving no price at all until a customer manually picks a
   variation, which is worse than the two-price problem this is meant
   to fix). This just styles the one price that survives. */
.woocommerce-variation-price{
  margin: 4px 0 0;
}
.woocommerce-variation-price .price{
  font-family: var(--rcpf-display) !important;
  font-size: 34px !important;
  font-weight: 800 !important;
  color: var(--rcpf-ink) !important;
}
.woocommerce-variation-price .price ins{
  text-decoration: none;
}
.woocommerce-variation-price .price del{
  font-size: 18px;
  font-weight: 400;
  color: var(--rcpf-ink-faint);
  margin-right: 8px;
}

/* Sticky purchase bar — hidden by default (translated off-screen),
   slid into view by adding .visible once the real buy-box scrolls out
   of frame (see initStickyBar in script.js). Fixed to the bottom on
   phones (thumb-reachable, doesn't cover the header) and the top on
   larger screens (doesn't cover content, reads naturally as a
   secondary nav-adjacent bar). */
.rcpf-sticky-bar{
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 9999;
  background: #fff;
  border-top: 1px solid var(--rcpf-line);
  box-shadow: 0 -8px 28px rgba(14,20,32,.10);
  transform: translateY(100%);
  transition: transform .3s cubic-bezier(.2,.7,.2,1);
}
.rcpf-sticky-bar.visible{ transform: translateY(0); }
.rcpf-sticky-bar-inner{
  max-width: 1200px;
  margin: 0 auto;
  padding: 14px 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.rcpf-sticky-bar-info{
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.rcpf-sticky-bar-name{
  font-family: var(--rcpf-display);
  font-weight: 700;
  font-size: 14.5px;
  color: var(--rcpf-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.rcpf-sticky-bar-price{
  font-family: var(--rcpf-mono);
  font-size: 13px;
  color: var(--rcpf-ink-soft);
}
.rcpf-sticky-bar-price .amount{ color: var(--rcpf-ink-soft); }
.rcpf-sticky-bar-cta{
  flex: 0 0 auto;
  background: var(--rcpf-accent);
  color: #fff;
  border: none;
  border-radius: 100px;
  padding: 12px 26px;
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
  transition: filter .15s ease;
  white-space: nowrap;
}
.rcpf-sticky-bar-cta:hover{ filter: brightness(0.9); }
@media (min-width: 851px){
  .rcpf-sticky-bar{
    bottom: auto;
    top: 0;
    border-top: none;
    border-bottom: 1px solid var(--rcpf-line);
    box-shadow: 0 8px 28px rgba(14,20,32,.08);
    transform: translateY(-100%);
  }
  .rcpf-sticky-bar.visible{ transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce){
  .rcpf-sticky-bar{ transition: none; }
}

/* Category nav — shop by category. A horizontally-scrollable row of
   pills above the shop grid (see render_category_nav), rather than a
   dropdown or sidebar, so it works the same on mobile as desktop
   without needing a separate collapsed/expanded state. */
.rcpf-category-nav{
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin: 0 0 28px;
  padding-bottom: 2px;
}
.rcpf-category-pill{
  display: inline-flex;
  align-items: center;
  padding: 9px 18px;
  border-radius: 100px !important;
  border: 1.5px solid var(--rcpf-line) !important;
  background: #fff !important;
  background-image: none !important;
  color: var(--rcpf-ink-soft) !important;
  font-family: var(--rcpf-display);
  font-weight: 600;
  font-size: 13.5px;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer; /* buttons (the [rcpf_shop] filter pills) don't get this by default the way links do */
  transition: border-color .15s ease, background .15s ease, color .15s ease;
}
/* !important throughout this block — the theme/page builder's own
   default button/hover styling (a gradient fill, in at least one
   report) was winning over the plain version of these rules, since a
   generic ".button:hover"-style selector from the theme can carry
   higher specificity or simply load after this stylesheet. Forcing it
   guarantees these pills always show the same brand accent color
   (Settings > Research Compound Fields > Accent color) rather than
   whatever the theme's own default happens to be. */
.rcpf-category-pill:hover{
  border-color: var(--rcpf-accent) !important;
  color: var(--rcpf-accent) !important;
  background: #fff !important;
  background-image: none !important;
}
.rcpf-category-pill.active{
  background: var(--rcpf-accent) !important;
  background-image: none !important;
  border-color: var(--rcpf-accent) !important;
  color: #fff !important;
}
.rcpf-category-pill.active:hover{
  background: var(--rcpf-accent) !important;
  background-image: none !important;
  color: #fff !important;
}
@media (max-width: 600px){
  .rcpf-category-nav{
    flex-wrap: nowrap;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    margin: 0 -20px 24px;
    padding: 0 20px 6px;
  }
  .rcpf-category-pill{ flex: 0 0 auto; }
}

/* Lazy product videos: soft placeholder tone until the first frame
   arrives, then a quick fade-in. No product photo is shown first. */
video.rcpf-lazy-video{
  background: rgba(127,127,127,.12);
  opacity: .001;
  transition: opacity .25s ease;
}
video.rcpf-lazy-video.rcpf-video-ready{ opacity: 1; }
@media (prefers-reduced-motion: reduce){
  video.rcpf-lazy-video{ transition: none; }
}
