/* ==========================================================================
   ULTRA PEP LABS - HOMEPAGE REFRESH  (TopOpti, 2026-09-17)
   --------------------------------------------------------------------------
   Standalone stylesheet, same pattern as pdp-refresh.css and
   cart-checkout.css: loaded from functions.php as 'upl-home-refresh',
   depends on 'upl-pdp-refresh' so the navy token set is already in scope,
   guarded by file_exists(), versioned by filemtime().

   To disable: comment out the wp_enqueue_style call in functions.php, or
   rename this file. No Elementor content, no page markup and no copy was
   changed to make this work.

   WHAT THIS DOES
   Carries the design direction already shipped on the product page, cart and
   checkout across to the homepage: the 1240px centred measure, the navy
   token family, Inter for body text as well as headings, small-caps accent
   eyebrows, pill CTAs and the card language with soft navy shadows.

   It closes these findings from Frontend-UX-Audit-2026-09-15.md:
     3.5  header is not sticky            (section 1, SITE-WIDE)
     3.3  testimonial rail scrolls blank  (section 7, with home-refresh.js)
     4.4  five font stacks on one page    (section 2)
     6.   hero stats are one wrapping line, not a 4-up block  (section 4)

   SCOPING NOTE
   Section 1 is deliberately site-wide - a sticky header is a navigation fix,
   not a homepage one, and the audit calls for it everywhere. Everything else
   is scoped to body.home so this deploy cannot affect another page.

   SELECTOR NOTE
   Elementor widget ids (.elementor-element-xxxxxxx) are stable for the life
   of a widget but die if the widget is deleted and rebuilt. Where a rule is
   pinned to an id, the id is named in a comment so it can be re-pointed.
   Structural selectors are used wherever they are specific enough.
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. STICKY HEADER  (SITE-WIDE - the only rule here that is not body.home)

   Audit 3.5. The header is position:relative and scrolls away permanently,
   so on a 4,800px homepage the cart, search and nav are unreachable after
   the first screen. Astra's header wrapper already carries z-index 99, so
   only the positioning and a scrolled state are needed.

   .ast-above-header-wrap is deliberately NOT included, so the announcement
   strip still scrolls away and the sticky element stays 138px, not 180px.
   -------------------------------------------------------------------------- */
#masthead .main-header-bar-wrap,
#masthead .ast-mobile-header-wrap {
	position: sticky;
	top: 0;
	z-index: 60;
	background: #fff;
	transition: box-shadow .18s ease;
}

/* The WordPress admin bar occupies the top 32px for logged-in staff. */
body.admin-bar #masthead .main-header-bar-wrap,
body.admin-bar #masthead .ast-mobile-header-wrap { top: 32px; }

@media (max-width: 782px) {
	body.admin-bar #masthead .main-header-bar-wrap,
	body.admin-bar #masthead .ast-mobile-header-wrap { top: 46px; }
}

/* Lift the header off the page once it is over content. .upl-stuck is set by
   home-refresh.js; with JavaScript off the header is still sticky, just flat. */
#masthead .main-header-bar-wrap.upl-stuck,
#masthead .ast-mobile-header-wrap.upl-stuck {
	box-shadow: var(--shadow-nav);
}

/* Anchor targets and the skip link have to clear the sticky header. */
:root { scroll-padding-top: 150px; }


/* --------------------------------------------------------------------------
   2. TYPOGRAPHY. Inter for body copy, not just headings.

   Audit 4.4 measured five stacks on the homepage: 889 elements in Arial, 296
   in the system stack, 172 in Inter. Headings already resolve to Inter; body
   copy does not, which is why the page renders differently on Windows, macOS
   and Android.

   Scoped to body.home on purpose. Rolling this out site-wide is a one-line
   change (drop the body.home prefix) but it touches every page, so it wants
   its own review pass rather than riding along with a homepage deploy.
   -------------------------------------------------------------------------- */
body.home,
body.home p,
body.home li,
body.home a,
body.home span,
body.home div,
body.home button,
body.home input,
body.home select,
body.home textarea {
	font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
}

/* Icon fonts have to keep their own families or the glyphs turn into letters. */
body.home .dashicons,
body.home .dashicons-before:before { font-family: dashicons !important; }

body.home .star-rating,
body.home .star-rating:before,
body.home .star-rating span:before { font-family: star !important; }

body.home [class^="fa-"],
body.home [class*=" fa-"] { font-family: 'Font Awesome 5 Free' !important; }

/* Body copy at 16px/1.65 in the navy-grey secondary tone, matching the PDP.
   Flat black on white was the reference's one weak spot. */
body.home p { color: #16233d; line-height: 1.65; }

/* ---- Keep that navy OUT of the footer  (2026-09-22, TopOpti) -------------
   The rule above is unscoped, so it also caught the paragraphs in the footer's
   BLACK bottom bar: #16233d on #000 is 1.34:1, i.e. invisible. It hit the
   research-use-only disclaimer and the copyright line, and only on the
   homepage - every other page renders the same two lines white at 21:1,
   because `body.home` does not apply there. Ralph spotted it 2026-09-22.

   Scoped to the two blocks that were wrong rather than to `.site-footer p`.
   A blanket footer rule would also catch the widget paragraph ("Where quality
   is measured, not assumed"), whose PARENT is black - inheriting there would
   turn it black on black and trade one invisible line for another.

   `inherit` rather than a hard-coded #fff: both parents (.ast-footer-copyright
   and the inherited Avada .fusion-text block) already resolve to white from
   Astra's own footer colour, so this hands the colour back to the theme and
   the footer keeps matching the rest of the site if that setting is changed.

   Verified in-page before shipping: all four footer text nodes land at 21:1,
   identical to /products/. Do NOT widen this to `body.home .site-footer p`.
   -------------------------------------------------------------------------- */
body.home .site-footer .ast-footer-copyright p,
body.home .site-footer .fusion-text p,
body.home .site-footer .fusion-text em { color: inherit; }


/* --------------------------------------------------------------------------
   3. SECTION RHYTHM + MEASURE

   Every top-level Elementor container on this page has zero padding of its
   own, but its .e-con-inner carries its own, and those were set per section
   with no pattern: 60/60, 60/0, 120/120, 60/40, 48/48. The gap between two
   sections is the sum of the pair, so it swings between 60px and 180px down
   the page.

   The rhythm is therefore set ON THE INNER, not by adding section padding on
   top of it - adding a second layer is what makes a long page feel padded
   out rather than paced. 64px each side gives a 128px gap between standard
   sections; the exceptions below are deliberate.

   Section backgrounds stay full-bleed - only the inner measure is capped.
   -------------------------------------------------------------------------- */
body.home .e-con > .e-con-inner {
	max-width: var(--pdp-max);
	padding-top: 64px;
	padding-bottom: 64px;
}

/* The marquee is a 42px strip, not a section: it should sit tight against
   the band below it. It has no .e-con-inner, so it is set on the container. */
body.home .site-content .elementor > .e-con.elementor-element-ea0b897 {
	padding-top: 0;
	padding-bottom: 0;
}

/* Hero: less on top, because the sticky header is already 138px of furniture
   above it, and a little more underneath to separate it from the grid. */
body.home .elementor-element-bc808be > .e-con-inner {
	padding-top: 40px;
	padding-bottom: 64px;
}

/* The dark guarantee band is full-bleed and carries four cards - it needs
   more room inside it than a section sitting on white does. */
body.home .elementor-element-5774449 > .e-con-inner {
	padding-top: 88px;
	padding-bottom: 88px;
}


/* --------------------------------------------------------------------------
   4. HERO  (container bc808be)

   Left column: eyebrow / heading / sub / two CTAs / stats line.
   Right column: a 650x700 product image.

   Three things change. The eyebrow becomes a small-caps accent line instead
   of 16px black Arial. The heading takes the PDP's fluid scale and tighter
   tracking. The stats line - currently one 14px sentence that wraps - becomes
   a ruled strip, which is the gap section 6 of the audit asks to close.
   -------------------------------------------------------------------------- */

/* Eyebrow (widget 77f77a5) */
body.home .elementor-element-77f77a5,
body.home .elementor-element-77f77a5 div {
	font-size: 12px;
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--accent-deep);
	line-height: 1.4;
}

/* Heading (widget b21431e). Currently rendered as <p>; styled for either tag
   so switching the Elementor setting to h1 needs no CSS change. */
body.home .elementor-element-b21431e p,
body.home .elementor-element-b21431e h1 {
	font-size: clamp(38px, 4.2vw, 54px);
	line-height: 1.06;
	letter-spacing: -.02em;
	font-weight: 600;
	color: var(--ink);
	margin: 14px 0 0;
	max-width: 15ch;   /* 12ch broke the headline over four lines */
}

/* Sub (widget 2ea96ac) */
body.home .elementor-element-2ea96ac p {
	font-size: 17px;
	line-height: 1.6;
	color: var(--muted);
	margin: 18px 0 0;
	max-width: 46ch;
}

/* CTA row (container 8418f03) */
body.home .elementor-element-8418f03 { gap: 14px; margin-top: 30px; }

/* Elementor pins each button's wrapper to a percentage width (222px and
   322px here). Once the buttons become pills with 26px of side padding,
   "Shop all compounds" no longer fits its 222px shell and breaks over two
   lines inside the pill. Let both shells size to their content instead. */
body.home .elementor-element-8418f03 > .e-con {
	width: auto;
	flex: 0 0 auto;
}

body.home .elementor-element-8418f03 a.elementor-button {
	border-radius: 999px;
	font-weight: 600;
	letter-spacing: .01em;
	padding: 0 26px;
	height: 54px;
	white-space: nowrap;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	transition: transform .16s ease, box-shadow .16s ease, background-color .16s ease;
}

/* Primary pill (container 1564f64) */
body.home .elementor-element-1564f64 a.elementor-button {
	background: var(--ink);
	color: #fff;
	box-shadow: var(--shadow-nav);
}
body.home .elementor-element-1564f64 a.elementor-button:hover {
	background: var(--ink-soft);
	transform: translateY(-1px);
}

/* Secondary, outlined (container fc2fee1) */
body.home .elementor-element-fc2fee1 a.elementor-button {
	background: transparent;
	color: var(--ink);
	border: 1.5px solid var(--line);
}
body.home .elementor-element-fc2fee1 a.elementor-button:hover {
	border-color: var(--ink);
	background: rgba(0, 42, 143, .04);
	transform: translateY(-1px);
}

/* ---- Hero stats strip: HIDDEN  (Aaron, 2026-09-17) ---------------------
   "4.8 * 12,000+ reviews 75k+ customers, 48 compounds, Same-day dispatch"
   is hidden at every width, on both heroes.

   Two ids because the page carries two heroes: 065cfa7 is the desktop one,
   2bf43cf the mobile one (see section 4b). Hiding the CONTAINERS rather than
   the paragraphs also takes away the hairline rule and the spacing this
   stylesheet put above them, so the CTAs become the last thing in the hero
   and the column closes cleanly.

   Worth recording why this matters beyond layout: every figure in that line
   is inherited from the reference site and none of it is true of this store -
   "12,000+ reviews", "75k+ customers", and "48 compounds" against a catalogue
   of twelve products with two ratings between them. Frontend-UX-Audit
   2.4 flagged it as live copied content; this takes it off the page.

   The rules below are kept, not deleted: they still describe how the strip
   should look if it is ever reinstated with real figures, and the
   .upl-hero-stats block further down is the 4-up shape the content pass can
   drop in. Delete these two lines to bring the strip back.
   -------------------------------------------------------------------------- */
body.home .elementor-element-065cfa7,
body.home .elementor-element-2bf43cf { display: none; }


/* ---- Hero stats  (widget 065cfa7) --------------------------------------
   The source is a single <p> of comma/space separated claims. Splitting it
   into four boxes means editing the content, which is out of scope for this
   pass, so it is laid out as a ruled stat strip: the rule and the spacing do
   the grouping that four separate widgets would.

   When the content pass replaces this line with four separate figures, the
   .upl-hero-stats block below is ready for them - see the deploy log. */
body.home .elementor-element-065cfa7 {
	margin-top: 38px;
	padding-top: 22px;
	border-top: 1px solid var(--line);
}

/* Deliberately NOT display:flex. The paragraph is three inline children -
   a span of claims, a span holding just the separating comma, and a strong -
   so flex promotes the comma to a flex item of its own and leaves it
   floating in the middle of the row. Inline layout keeps the punctuation
   attached to the text it belongs to. */
body.home .elementor-element-065cfa7 p {
	font-size: 13px;
	font-weight: 600;
	letter-spacing: .02em;
	color: var(--muted);
	line-height: 1.5;
	margin: 0;
}

body.home .elementor-element-065cfa7 strong {
	color: var(--ink);
	font-weight: 600;
}

/* Target shape for the content pass: four figure/label pairs. */
body.home .upl-hero-stats {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 0;
	margin-top: 38px;
	padding-top: 22px;
	border-top: 1px solid var(--line);
}
body.home .upl-hero-stats > * {
	padding: 0 18px;
	border-left: 1px solid var(--line);
}
body.home .upl-hero-stats > *:first-child { padding-left: 0; border-left: 0; }
body.home .upl-hero-stats strong {
	display: block;
	font-size: 22px;
	font-weight: 600;
	color: var(--ink);
	line-height: 1.2;
}
body.home .upl-hero-stats span {
	display: block;
	margin-top: 4px;
	font-size: 12px;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--muted);
}

/* Hero image column (container 34e8320) - card language, not a bare image. */
body.home .elementor-element-34e8320 img {
	border-radius: 18px;
	box-shadow: var(--shadow-lg);
}


/* --------------------------------------------------------------------------
   4b. HERO, MOBILE  (container 624f9ad)

   The homepage carries TWO heroes. Container bc808be above is desktop only;
   below 768px Elementor hides it and shows 624f9ad instead, which is a
   different set of widgets with different ids. Styling only the first one
   leaves every phone visitor - the majority of the traffic - on the old
   design, which is exactly what happened on the first pass here.

   No media query is needed: 624f9ad is display:none above 767px, so these
   rules can only ever apply on the mobile hero.

   Widget map, top to bottom:
     831d582 > b5206b8  icon-box   eyebrow
     eba847f > bb58122  text       heading   (+ 3f75c30 image, side by side)
     4f284df > 82b24d3  text       sub
     565bd0b > ab5aa4d  button     primary
     cfbc979 > cb40600  button     secondary
     2bf43cf > b86afca  text       stats line
   -------------------------------------------------------------------------- */
body.home .elementor-element-b5206b8,
body.home .elementor-element-b5206b8 div {
	font-size: 11px;
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--accent-deep);
	line-height: 1.4;
}

/* The heading shares its row with a 156px image, so the copy column is only
   156px wide. overflow-wrap still stops an overlong word forcing a horizontal
   scroll at 320px, but hyphenation is OFF: `hyphens: auto` was splitting
   "Peptides" into "Pep-tides" (client report, 29 Sep 2026). */
body.home .elementor-element-bb58122 p {
	font-size: 30px;
	line-height: 1.08;
	letter-spacing: -.02em;
	font-weight: 600;
	color: var(--ink);
	margin: 0;
	overflow-wrap: break-word;
	-webkit-hyphens: manual;
	hyphens: manual;
}

body.home .elementor-element-3f75c30 img {
	border-radius: 14px;
	box-shadow: var(--shadow-lg);
}

body.home .elementor-element-82b24d3 p {
	font-size: 15px;
	line-height: 1.6;
	color: var(--muted);
	margin: 16px 0 0;
}

/* Both mobile CTAs full width, matching the desktop pill treatment. */
body.home .elementor-element-ab5aa4d a.elementor-button,
body.home .elementor-element-cb40600 a.elementor-button {
	border-radius: 999px;
	font-weight: 600;
	letter-spacing: .01em;
	height: 52px;
	width: 100%;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	white-space: nowrap;
}

body.home .elementor-element-ab5aa4d a.elementor-button {
	background: var(--ink);
	color: #fff;
	box-shadow: var(--shadow-nav);
}

body.home .elementor-element-cb40600 a.elementor-button {
	background: transparent;
	color: var(--ink);
	border: 1.5px solid var(--line);
}

/* Stats strip, same ruled treatment as the desktop hero. */
body.home .elementor-element-2bf43cf {
	margin-top: 22px;
	padding-top: 18px;
	border-top: 1px solid var(--line);
}

body.home .elementor-element-b86afca p {
	font-size: 12.5px;
	font-weight: 600;
	letter-spacing: .02em;
	line-height: 1.5;
	color: var(--muted);
	margin: 0;
}

body.home .elementor-element-b86afca strong {
	color: var(--ink);
	font-weight: 600;
}


/* --------------------------------------------------------------------------
   5. BEST SELLERS  (container 2596eb5)

   Header row is an h2 plus a "Shop all compounds" button (widgets 26c70f9 /
   9a7dad0); the grid below is WooCommerce's own [products] shortcode at
   columns-3, so every card already inherits the archive styling from
   pdp-refresh.css - including the COA badge and the Select-options button
   that opens the size sheet.
   -------------------------------------------------------------------------- */
body.home .elementor-element-25d25d6 {
	align-items: baseline;
	justify-content: space-between;
	padding-bottom: 8px;
	border-bottom: 1px solid var(--line);
	margin-bottom: 34px;
}

body.home .elementor-element-26c70f9 h2 {
	font-size: clamp(26px, 2.4vw, 34px);
	line-height: 1.15;
	letter-spacing: -.015em;
	color: var(--ink);
	margin: 0;
}

/* "Shop all compounds" reads as a link with a rule, not a second pill - the
   pills in this section belong to the cards.

   PADDING, WITH THE EDGE HELD (2026-09-22). It was padding: 0, which left a
   16px-tall click target and the text jammed against the rule beneath it.
   The padding gives it room to breathe and something to press; the matching
   negative margins pull the BOX back out so the text's own edges still line
   up with the heading on the left and the product grid below on the right.
   Padding alone would have pushed the label inward and broken that column. */
body.home .elementor-element-9a7dad0 a.elementor-button {
	background: transparent;
	color: var(--ink);
	padding: 6px 10px 7px;
	margin: -6px -10px -7px;
	height: auto;
	font-size: 14px;
	font-weight: 600;
	letter-spacing: .01em;
	border-bottom: 1.5px solid transparent;
	border-radius: 0;
}
body.home .elementor-element-9a7dad0 a.elementor-button:hover {
	border-bottom-color: var(--ink);
	background: transparent;
}

/* Grid gutters. The shortcode ships WooCommerce's default 20px float grid. */
body.home .elementor-widget-shortcode ul.products {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 28px;
	margin: 0;
}
body.home .elementor-widget-shortcode ul.products::before,
body.home .elementor-widget-shortcode ul.products::after { content: none; }

body.home .elementor-widget-shortcode ul.products li.product {
	width: auto !important;
	margin: 0 !important;
	float: none !important;
	clear: none !important;
}

/* Card titles render #0945D6 bright blue here against --ink navy on the
   archive. One family, one tone. */
body.home ul.products li.product h2,
body.home ul.products li.product .woocommerce-loop-product__title { color: var(--ink); }


/* --------------------------------------------------------------------------
   6. GUARANTEE BAND  (container 5774449)

   Eyebrow / h2 / sub over four image-topped cards. The eyebrow renders as
   plain white 16px Arial, and the cards have no shell, so the four images
   float on the dark ground at uneven heights.
   -------------------------------------------------------------------------- */
body.home .elementor-element-9ba9810 p {
	font-size: 12px;
	font-weight: 700;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, .72);
	margin: 0;
}

body.home .elementor-element-6e19030 h2 {
	font-size: clamp(28px, 2.6vw, 38px);
	line-height: 1.15;
	letter-spacing: -.015em;
	margin: 14px 0 0;
}

body.home .elementor-element-8e95450 p {
	color: rgba(255, 255, 255, .78);
	font-size: 16px;
	margin: 14px auto 0;
	max-width: 62ch;
}

/* Card row (container e73d31c)
   IMPORTANT: the band is dark, but the four CARDS are opaque white - Elementor
   paints them with --e-global-color-astglobalcolor4. So the heading, eyebrow
   and sub above take white text (they sit on the dark ground), while anything
   INSIDE a card must take dark text. Getting that backwards makes the card
   copy white on white and invisible, which is easy to do because the section
   reads as dark in a screenshot. */
body.home .elementor-element-e73d31c { gap: 24px; margin-top: 46px; }

body.home .elementor-element-e73d31c > .e-con {
	border: 1px solid var(--line);
	border-radius: 16px;
	padding: 24px;
	overflow: hidden;
	box-shadow: 0 18px 40px -28px rgba(0, 20, 70, .55);
	transition: transform .18s ease, box-shadow .18s ease;
}
body.home .elementor-element-e73d31c > .e-con:hover {
	transform: translateY(-2px);
	box-shadow: 0 26px 52px -26px rgba(0, 20, 70, .6);
}

/* The four card images are the slowest assets on the page (audit 3.9) and
   they arrive at different aspect ratios. A fixed ratio stops the row
   reflowing as each one lands. */
body.home .elementor-element-e73d31c > .e-con img {
	border-radius: 10px;
	aspect-ratio: 3 / 2;
	object-fit: cover;
	width: 100%;
}

/* Inside a card: dark text on white. h3 keeps the navy it already has. */
body.home .elementor-element-e73d31c h3 {
	font-size: 17px;
	font-weight: 600;
	letter-spacing: -.005em;
	margin: 18px 0 8px;
}

body.home .elementor-element-e73d31c p {
	color: var(--muted);
	font-size: 14.5px;
	line-height: 1.6;
	margin: 0;
}


/* --------------------------------------------------------------------------
   7. TESTIMONIAL RAIL  (container 2922712, widget markup .tslider)

   Audit 3.3. The widget is a hand-rolled slider: a 4,300px .ts-track inside a
   1,200px .ts-track-wrap, moved by a transform with no clamp, so Next walks
   the track past its own end and the section renders as blank white until
   the page is reloaded.

   The fix is to stop transforming it and let it be a scroll rail - the same
   pattern already shipped as the PDP section rail (pdp-refresh.css 16).
   Native scrolling cannot overrun, snaps to card boundaries, and is
   swipeable on touch. home-refresh.js re-points the existing arrow buttons
   at scrollBy() and disables them at each end.

   The widget ships its own inline stylesheet with blanket !important rules,
   which is why the overrides below carry body.home and !important too.
   -------------------------------------------------------------------------- */
/* The widget's own rule is `overflow: hidden !important`, so these two need
   !important to win - a scrollable rail is the whole fix. The widget also
   sets its own symmetric edge mask with !important; that is left alone,
   because a fade on both edges is the right affordance for a rail that
   scrolls in both directions. */
body.home .tslider .ts-track-wrap {
	overflow-x: auto !important;
	overflow-y: hidden !important;
	scroll-snap-type: x mandatory;
	scroll-behavior: smooth;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: none;
	-ms-overflow-style: none;
}
body.home .tslider .ts-track-wrap::-webkit-scrollbar { display: none; }

body.home .tslider .ts-track {
	transform: none !important;
	transition: none !important;
	width: max-content !important;
	display: flex !important;
	gap: 20px !important;
	padding: 4px 0 !important;
}

body.home .tslider .ts-track > * {
	scroll-snap-align: start;
	flex: 0 0 auto;
}

/* Arrow buttons: circular, navy, and visibly dead at the ends. The disabled
   state is set by home-refresh.js. */
body.home .tslider .ts-nav-btn {
	width: 42px;
	height: 42px;
	border-radius: 999px !important;
	border: 1px solid var(--line) !important;
	background: #fff !important;
	color: var(--ink) !important;
	display: inline-flex !important;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	transition: border-color .16s ease, opacity .16s ease;
}
body.home .tslider .ts-nav-btn:hover:not([disabled]) { border-color: var(--ink) !important; }
body.home .tslider .ts-nav-btn[disabled] { opacity: .35; cursor: default; }

/* The heading is 44.8px/900 with negative tracking - the only weight-900 type
   on the site. Bring it onto the section-heading scale used everywhere else. */
body.home .tslider .ts-heading {
	font-size: clamp(26px, 2.4vw, 34px) !important;
	font-weight: 600 !important;
	letter-spacing: -.015em !important;
	color: var(--ink) !important;
	line-height: 1.15 !important;
}

body.home .tslider .ts-tag {
	font-size: 12px !important;
	font-weight: 700 !important;
	letter-spacing: .14em !important;
	text-transform: uppercase !important;
	color: var(--accent-deep) !important;
}


/* --------------------------------------------------------------------------
   8. NEWSLETTER  (container ad20526)

   "Get 15% off your first order" plus a WPForms email capture, sitting on
   white with no shell, so it reads as a loose fragment after the testimonial
   band. Given a panel it closes the page properly.
   -------------------------------------------------------------------------- */
body.home .elementor-element-ad20526 > .e-con-inner {
	background: var(--gr);
	border: 1px solid var(--line);
	border-radius: 20px;
	padding: 48px 40px;
	text-align: center;
}

/* The heading is an <h4> rendering at 16px/400 - semantically a heading,
   visually indistinguishable from the paragraph under it. Targeted by
   Elementor's own heading class so the tag can change without breaking this. */
body.home .elementor-element-ad20526 .elementor-heading-title {
	font-size: clamp(24px, 2.2vw, 30px);
	line-height: 1.2;
	font-weight: 600;
	letter-spacing: -.015em;
	color: var(--ink);
	margin: 0;
}

body.home .elementor-element-ad20526 p {
	max-width: 56ch;
	margin: 12px auto 0;
	color: var(--muted);
}

/* WPForms sizes its fields through CSS custom properties, and the theme's own
   input rules live inside an @layer - where, for !important declarations, the
   cascade REVERSES layer order, so an unlayered rule loses regardless of
   specificity. body prefix plus !important is the pattern that wins here,
   same as the cart/checkout overrides and the size sheet's quantity input. */
body.home .elementor-element-ad20526 .wpforms-field-medium,
body.home .elementor-element-ad20526 input[type="email"],
body.home .elementor-element-ad20526 input[type="text"] {
	border-radius: 999px !important;
	border: 1px solid var(--line) !important;
	height: 50px !important;
	padding: 0 20px !important;
	font-size: 15px !important;
	background: #fff !important;
}

body.home .elementor-element-ad20526 button[type="submit"],
body.home .elementor-element-ad20526 .wpforms-submit {
	border-radius: 999px !important;
	background: var(--ink) !important;
	color: #fff !important;
	height: 50px !important;
	padding: 0 30px !important;
	font-weight: 600 !important;
	border: 0 !important;
}
body.home .elementor-element-ad20526 button[type="submit"]:hover,
body.home .elementor-element-ad20526 .wpforms-submit:hover {
	background: var(--ink-soft) !important;
}


/* --------------------------------------------------------------------------
   9. MARQUEE  (container ea0b897, Premium Addons post-ticker)

   Already navy. It only needs the type to match the eyebrow scale used in
   sections 4 and 6 so the three small-caps lines on the page agree.
   -------------------------------------------------------------------------- */
body.home .elementor-element-ea0b897 .premium-post-ticker__content,
body.home .elementor-element-ea0b897 .premium-post-ticker__posts-wrapper {
	font-size: 12px;
	font-weight: 600;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, .92);
}


/* --------------------------------------------------------------------------
   10. RESPONSIVE

   Verified with the iframe harness described in deploy-pdp/DEPLOYED.md
   ("Twelfth deploy") - resize_window does nothing in this environment, so an
   iframe with its own viewport is the only way to exercise media queries.
   -------------------------------------------------------------------------- */
@media (max-width: 1024px) {
	body.home .e-con > .e-con-inner {
		padding-top: 52px;
		padding-bottom: 52px;
	}
	body.home .elementor-element-bc808be > .e-con-inner {
		padding-top: 32px;
		padding-bottom: 52px;
	}
	body.home .elementor-element-5774449 > .e-con-inner {
		padding-top: 68px;
		padding-bottom: 68px;
	}

	body.home .elementor-widget-shortcode ul.products { gap: 20px; }
	body.home .elementor-element-e73d31c { gap: 18px; }
}

@media (max-width: 767px) {
	body.home .e-con > .e-con-inner {
		padding-top: 44px;
		padding-bottom: 44px;
	}
	body.home .elementor-element-bc808be > .e-con-inner {
		padding-top: 24px;
		padding-bottom: 40px;
	}
	body.home .elementor-element-5774449 > .e-con-inner {
		padding-top: 56px;
		padding-bottom: 56px;
	}

	body.home .elementor-element-b21431e p,
	body.home .elementor-element-b21431e h1 { max-width: none; }

	/* Both CTAs full width and stacked - at 390px they were 233px and 353px
	   side by side, which wraps the second one onto its own line anyway. */
	body.home .elementor-element-8418f03 { flex-direction: column; gap: 10px; }
	body.home .elementor-element-8418f03 > .e-con,
	body.home .elementor-element-8418f03 a.elementor-button { width: 100%; }

	body.home .elementor-element-065cfa7 p { gap: 8px 18px; font-size: 12.5px; }
	body.home .upl-hero-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px 0; }
	body.home .upl-hero-stats > *:nth-child(odd) { padding-left: 0; border-left: 0; }

	/* Two-up grid, matching WooCommerce's own mobile columns-2, but with the
	   gutter kept consistent with the desktop grid. */
	body.home .elementor-widget-shortcode ul.products {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 14px;
	}

	body.home .elementor-element-25d25d6 { margin-bottom: 24px; }

	body.home .elementor-element-e73d31c { gap: 14px; }
	body.home .elementor-element-e73d31c > .e-con { padding: 18px; }

	body.home .elementor-element-ad20526 > .e-con-inner { padding: 32px 20px; border-radius: 16px; }

	/* Let the rail bleed to the screen edge on phones so the next card is
	   visibly clipped and the swipe affordance is obvious. */
	body.home .tslider .ts-track-wrap {
		margin-left: -16px;
		margin-right: -16px;
		padding-left: 16px;
		padding-right: 16px;
	}
}

/* NOTE, 2026-09-17: there used to be a `@media (max-width: 480px)` block here
   dropping the home grid to a single column. It was removed on Ralph's call -
   the homepage and the shop archive both hold two cards across at every phone
   width now. The 767px rule above is what produces the 2-up; the card
   internals that make it work at ~159px are in pdp-refresh.css section 18,
   which owns both grids so the two pages cannot drift apart. */


/* --------------------------------------------------------------------------
   11. MOTION
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
	body.home .tslider .ts-track-wrap { scroll-behavior: auto; }
	body.home .elementor-element-8418f03 a.elementor-button:hover,
	body.home .elementor-element-e73d31c > .e-con:hover { transform: none; }
}

/* --------------------------------------------------------------------------
   8b. NEWSLETTER CORRECTION  (2026-09-18, TopOpti)
   --------------------------------------------------------------------------
   Section 8 above gave container ad20526 a light panel (--gr with a --line
   border), on the reading that the newsletter "sat on white with no shell".
   It does not: Elementor supplies its own black card inside it, element
   7ebf851. The result was a black box floating inside a pale rounded box, and
   worse, the paragraph rule written for that pale panel painted --muted
   (#5a6478) onto black - 3.53:1, under the 4.5:1 minimum, which is what made
   the block look wrong once the rewritten copy ran to two lines.

   Drop the redundant outer shell and let the dark card carry the section, then
   make the copy inside it readable: 78% white on black is 12.3:1.
   -------------------------------------------------------------------------- */
body.home .elementor-element-ad20526 > .e-con-inner {
	background: none;
	border: 0;
	padding: 0;
}

body.home .elementor-element-ad20526 .elementor-element-7ebf851 p {
	color: rgba(255, 255, 255, .78);
}

body.home .elementor-element-ad20526 .elementor-element-7ebf851 .elementor-heading-title {
	color: #fff;
}

/* --------------------------------------------------------------------------
   HEADER PHONE NUMBER  (TopOpti, 2026-09-18)
   --------------------------------------------------------------------------
   Sits in the primary header's right-hand section, in the astra-settings
   'header-html-2' slot, which previously held a lone "|" acting as a divider
   between the QUALITY / SHIPPING menu and the account, search and cart icons.
   The divider is kept; the number goes in front of it.

   Hidden below 921px, which is where Astra swaps to its mobile header - the
   number would otherwise crowd the hamburger row. The FAQ and the Return
   Policy both carry it as a tel: link, so it stays reachable on a phone.
   -------------------------------------------------------------------------- */
.upl-header-phone {
	font-size: 14px;
	font-weight: 600;
	letter-spacing: .01em;
	color: var(--navy, #002A8F);
	text-decoration: none;
	white-space: nowrap;
	transition: opacity .15s ease;
}
.upl-header-phone:hover,
.upl-header-phone:focus-visible {
	opacity: .72;
	text-decoration: underline;
}
.upl-header-sep {
	margin-left: 10px;
	opacity: .38;
}

@media (max-width: 921px) {
	.upl-header-phone { display: none; }
}

/* --------------------------------------------------------------------------
   MOBILE HERO CTAs, RELOCATED  (2026-09-22)

   home-refresh.js lifts the mobile hero's two buttons out of the hero and
   drops them in after the product block. The wrapper it builds carries
   Elementor's own hidden-desktop/hidden-tablet classes, so this only ever
   paints on mobile - see moveHeroCTAs() for why that matters.

   Styling stays deliberately thin: the buttons are Elementor button widgets
   and keep their own skin. All this does is give them a column to sit in and
   the same rhythm as the section above.
   -------------------------------------------------------------------------- */
.upl-hero-ctas {
	display: flex;
	flex-direction: column;
	gap: 12px;
	padding: 4px 20px 28px;
}

/* The buttons are full width here, unlike in the hero where they sit in the
   flow of a narrower container. Two stacked pills of different widths read as
   a mistake. */
.upl-hero-ctas .elementor-widget-button,
.upl-hero-ctas .elementor-button {
	width: 100%;
}

.upl-hero-ctas .elementor-button {
	justify-content: center;
}

/* --------------------------------------------------------------------------
   MOBILE HERO: close the gap the moved buttons left  (2026-09-22)

   moveHeroCTAs() marks the two emptied Elementor containers with .upl-emptied.
   They are flex children of the hero with their own padding, so an empty one
   still holds open roughly the height the button used to occupy, plus its
   share of the hero's row gap. Ralph saw the result as a big white space under
   the hero on mobile.

   display: none rather than zeroed padding, so they stop counting as flex
   items and stop drawing gap either side of themselves.

   The hero's own bottom padding then matches its top: Elementor sets 40px top
   and 30px bottom at this breakpoint, and the ask was for the two to read the
   same. Overriding the custom property keeps Elementor's own box model doing
   the work; the extra `body` raises specificity above post-18.css regardless
   of which stylesheet the page loads first.
   -------------------------------------------------------------------------- */
@media (max-width: 767px) {
	.upl-emptied { display: none !important; }

	body .elementor-18 .elementor-element.elementor-element-624f9ad {
		--padding-bottom: 40px;
	}
}

/* --------------------------------------------------------------------------
   FOOTER LINKS: UNDERLINED  (2026-09-23, TopOpti)

   Ralph asked for the footer links to keep their colour and gain an underline.
   Colour is deliberately NOT set here - Astra's own footer-widget-*-link-color
   settings still own it, so changing the palette in the customiser keeps
   working and this rule does not have to be revisited.

   Scoped to the footer's own containers rather than `.site-footer a`, and the
   logo link is excluded, because underlining an image link draws a stray rule
   under the mark.

   text-underline-offset keeps the line clear of the descenders on the navy
   footer, where a tight underline reads as a strikethrough at small sizes.
   -------------------------------------------------------------------------- */
.site-footer .footer-widget-area a,
.site-footer .ast-footer-copyright a,
.site-footer .ast-builder-html-element a,
.site-footer .widget a {
	text-decoration: underline;
	text-underline-offset: 0.18em;
	text-decoration-thickness: from-font;
}

.site-footer .widget_media_image a,
.site-footer a:has(> img),
.site-footer a:has(> svg) {
	text-decoration: none;
}

/* --------------------------------------------------------------------------
   FOOTER COPYRIGHT LINKS: MATCH THE TEXT AROUND THEM  (2026-09-23, TopOpti)

   The legal identity block added for the payment processor put the support
   email and phone number into the copyright row as links. Astra colours the
   copyright TEXT white but leaves links on the global link colour, so those
   two rendered navy (#002A8F) on the footer's black background - about 1.7:1
   contrast, against a 4.5:1 minimum. The two contact details underwriting
   specifically asked to see were the least readable thing on the page.

   `inherit` rather than a hard-coded #fff, so if the footer text colour is
   ever changed in the customiser these follow it instead of being wrong in a
   new way. The 13 menu links above already inherit white and are untouched.
   -------------------------------------------------------------------------- */
.site-footer .ast-footer-copyright a,
.site-footer .ast-footer-copyright a:visited,
.site-footer .ast-builder-html-element a,
.site-footer .ast-builder-html-element a:visited {
	color: inherit;
}

.site-footer .ast-footer-copyright a:hover,
.site-footer .ast-footer-copyright a:focus,
.site-footer .ast-builder-html-element a:hover,
.site-footer .ast-builder-html-element a:focus {
	color: inherit;
	opacity: 0.75;
}
