/* Westhill Watch Boxes — single product (both variants).
   Hand-written to match the existing design, breakpoint for breakpoint. Loaded only on a product
   page, and only inside the preview gate.

   Every number below was read off the live product pages — 806 (template 12571) and 4650
   (template 14085) — with getComputedStyle at 1440x900 and 360x740, or out of those two Elementor
   documents' own inline CSS, and not guessed. Where a number looks strange it is because the live
   one is strange, and there is a comment saying so.

   WHY THIS FILE HAS TO CARRY SO MUCH. elementor_css_print_method is `internal` on this site, so
   12571's CSS is not a stylesheet with a handle — it is 32,341 bytes inlined on the
   elementor-frontend handle (14085's is 32,282, and the two are IDENTICAL once the document id is
   normalised, bar five rules that are the same rules under different element ids). Alongside it
   sit the header's 34,606, the footer's 39,363, the kit's 1,442, popup 12373's 12,943 and — on a
   product whose description is an Elementor document — that product's own, e.g. 4650's 1,108
   bytes at offset 1,442. The gate leg in NOTES-pdp.md §8 suppresses ONLY the replaced template's
   share; everything it was doing for the breadcrumb, the buy box, the bands and the related row
   has to be done here instead.

   FIVE ELEMENTOR WIDGET STYLESHEETS ARE ALSO DROPPED (NOTES-pdp.md §8b), and this file restates
   what each was doing that the rebuilt markup still needs:

     widget-woocommerce-product-images     nothing the rebuild needs; all rules are scoped to
                                           .elementor-widget-woocommerce-product-images
     widget-woocommerce-product-price      one rule, for a block price layout live does not use
     widget-woocommerce-product-add-to-cart form.cart margin and the quantity/button row
     widget-woocommerce-products           THE RELATED GRID — `ul.products.elementor-grid` is a
                                           CSS grid with 20px/40px gaps, `li.product` is unfloated
                                           and unpadded, `li.product .onsale` is hidden, and
                                           `.products > h2` is hidden. All four are restated below.
     widget-divider                        the rule between the price row and the cart

   Breakpoints are Elementor's own, from the Default Kit (12246): tablet is (max-width:1024px) and
   mobile is (max-width:767px), mobile last. Elementor's tablet rules apply on phones too unless a
   mobile rule overrides them, which is why several blocks below restate a value.

   ---------------------------------------------------------------------------
   Tokens.

   TYPE. This storefront downloads no webfont at all: Perfmatters' disable_google_fonts is on, WP
   Rocket's host_fonts_locally is off and there is no uploads/elementor/google-fonts directory, so
   Questrial, Poppins, Manrope and Roboto all fall through to the browser's generic sans-serif.
   Measured in milestone 0, not assumed. The baseline captures record that fallback, so these
   tokens carry the fallback and nothing else. When the fonts are fixed (open decision D1) this is
   a one-line-per-token change and nothing else in this file moves. Same convention as home.css
   and category.css, so the three flip together.

   COLOUR. Values are the Elementor global kit's own (post 12246), named by role rather than by
   Elementor's generated ids.
   --------------------------------------------------------------------------- */

.wh-pdp {
	--wh-ff-questrial: sans-serif;   /* intended: "Questrial", sans-serif */
	--wh-ff-poppins: sans-serif;     /* intended: "Poppins", sans-serif   */
	--wh-ff-manrope: sans-serif;     /* intended: "Manrope", sans-serif   */
	--wh-ff-roboto: sans-serif;      /* intended: "Roboto", sans-serif    */
	/* Astra's own body stack, used where Elementor set no family of its own. */
	--wh-ff-body: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;

	--wh-primary: #0a1c2e;      /* kit: Primary          */
	--wh-secondary: #54595f;    /* kit: Secondary        */
	--wh-text: #7a7a7a;         /* kit: Text             */
	--wh-accent: #ccbb7e;       /* kit: Accent           */
	--wh-stone: #e9e8e6;        /* kit: 5af3dd5b         */
	--wh-white: #fff;           /* kit: 10b519c8         */
	--wh-ink: #000;             /* kit: 1cfbcb3e         */
	--wh-body-ink: #010101;
	--wh-navy-title: #1c244b;   /* the two Poppins headings */
	--wh-rust: #ad5207;         /* the review-wall heading  */
	--wh-acc-rule: #0a1c2e29;   /* accordion 46bd72a's own border colour, verbatim */

	/* The body line-height on this site is 1.65 against a 16px root, which computes to 26.4px and
	   is then INHERITED as that pixel value by children with a smaller font-size. That is why the
	   short description reads 14px/26.4px rather than 14px/23.1px, and why this is px. */
	--wh-lh: 26.4px;

	/* Elementor kit 12246: `.e-con{--container-max-width:1140px}` on desktop, 1024 at <=1024px,
	   767 at <=767px. Boxed containers centre a --container-max-width inner inside 10px padding. */
	--wh-boxed: 1140px;

	color: var(--wh-body-ink);
}

/* Astra boxes a normal single post in .ast-container. This page is full-bleed, exactly as the
   Elementor template it replaces is — measured on live, #content.site-content and .ast-container
   are both plain 1440-wide blocks with no padding. The template also asks Astra for the
   page-builder content layout; this is the braces to that belt. */
.wh-pdp-page .ast-container,
.wh-pdp-page #primary,
.wh-pdp-page .site-content > .ast-container {
	max-width: none;
	width: auto;
	padding-left: 0;
	padding-right: 0;
	margin-left: 0;
	margin-right: 0;
}

.wh-pdp-page #content .ast-container {
	display: block;
}

.wh-pdp *,
.wh-pdp *::before,
.wh-pdp *::after {
	box-sizing: border-box;
}

/* ---------------------------------------------------------------------------
   Band shell.

   Live's seven top-level containers are Elementor "boxed" containers: full-width outer with 10px
   side padding, and an inner capped at --container-max-width and centred. At 1440 that puts the
   content at x=150 and 1,140 wide, which is what the live measurement reports for the breadcrumb
   nav, the buy box and the related row.
   --------------------------------------------------------------------------- */

.wh-pdp__band {
	width: 100%;
}

/* ---------------------------------------------------------------------------
   1. Breadcrumb — live container c21dcc6 + widget 02908b2.
   Measured live at 1440: band 1440x56 at y=182, nav 1140 wide at x=150, font-size 10px,
   line-height 26.4px, colour #777 (Astra's), margin-bottom 10px.
   --------------------------------------------------------------------------- */

.wh-pdp__crumb {
	padding: 0 10px;
}

/* 10px top and bottom, none at the sides: live's nav measures 1,140 wide at x=150 inside a band
   whose own padding is 0 10px, and sits 10px below the band's top edge in a 56px band. */
.wh-pdp__crumb-inner {
	max-width: var(--wh-boxed);
	margin: 0 auto;
	padding: 10px 0;
}

.wh-pdp .woocommerce-breadcrumb {
	/* #777 is Astra's, measured on live. It is restated because .wh-pdp sets its own inherited
	   colour and inheritance would otherwise reach the breadcrumb first. */
	color: #777;
	font-size: 10px;
	line-height: var(--wh-lh);
	margin: 0 0 10px;
	padding: 0;
}

/* ---------------------------------------------------------------------------
   2. The buy box — live container ffaf464 holding 867ee79 (60%) and a608ac5 (40%).

   div.product is WooCommerce's own wrapper, printed by content-single-product.php, and the
   template gives it .wh-pdp__product through post_class(). It is the buy-box row and nothing
   else: the five bands below are fired from `woocommerce_after_single_product`, i.e. OUTSIDE it,
   because live's bands are siblings of the buy box rather than children of it.

   `margin-left:auto` on the media column and `margin-right:auto` on the summary centres the pair
   inside a full-width row while leaving the row itself full width — which is what a band that has
   to be full-bleed needs, and it needs no 100vw trick and therefore cannot introduce the
   horizontal overflow those tricks always do.

   Measured live at 1440: media 684x1344 at x=150, summary 456x1344 at x=834, both with 10px
   padding; the media column has a 20px flex gap, the summary column none.
   --------------------------------------------------------------------------- */

#content .wh-pdp .wh-pdp__product,
.wh-pdp .wh-pdp__product {
	display: flex;
	flex-wrap: wrap;
	/* stretch, not flex-start: live's two columns both measure 1,344px tall on 806 at 1440, i.e.
	   the shorter one is stretched to the row. Elementor's container default is stretch and
	   ffaf464 does not override it. */
	align-items: stretch;
	width: 100%;
	max-width: none;
	margin: 0;
	padding: 0 10px;
	float: none;
}

/* ⚠ #content IS IN THESE SELECTORS ON PURPOSE, and it is not defensive noise.
   Astra's and WooCommerce's own product rules are written as
       .woocommerce #content div.product div.summary,
       .woocommerce-page #content div.product div.images, …
   i.e. specificity (1,3,3) — an ID, because Astra's header.php prints
   `<div id="content" class="site-content">` around every page. A four-class selector is (0,4,0)
   and LOSES to that, which is not obvious and cost this build a measurement: the summary column
   came out 568px wide against live's 456, the gallery 319 against 664, and the whole buy-box row
   sat 56px left of where it belongs. Adding #content makes these (1,4,x) and they win on the
   rules of the cascade rather than on !important. */
#content .wh-pdp .wh-pdp__product > .wh-pdp__media,
.wh-pdp .wh-pdp__product > .wh-pdp__media {
	/* flex:0 0 auto is not decoration. Something in Astra's or WooCommerce's stylesheet gives
	   .summary a flex-grow, and with it the summary measured 568px against live's 456 and dragged
	   the whole row 56px left. Both columns are explicitly un-growable. */
	flex: 0 0 auto;
	width: 684px;
	max-width: 60%;
	margin-left: auto;
	padding: 10px;
	display: flex;
	flex-direction: column;
	gap: 20px;
}

#content .wh-pdp .wh-pdp__product > .summary.entry-summary,
.wh-pdp .wh-pdp__product > .summary.entry-summary {
	flex: 0 0 auto;
	width: 456px;
	max-width: 40%;
	margin-right: auto;
	margin-top: 0;
	margin-bottom: 0;
	padding: 10px;
	display: flex;
	flex-direction: column;
	gap: 0;
	float: none;
	clear: none;
}

/* Astra and WooCommerce both size .woocommerce-product-gallery as a floated half-column on a
   normal product page — `.woocommerce div.product div.images{width:48%;float:left}`. Live escapes
   it because Elementor's widget stylesheet overrides it at equal specificity; that stylesheet is
   dropped here, so the override has to be restated, and at a specificity that beats (0,3,2).
   Measured on live: the gallery is 664 wide inside the 684 media column, with a 32px bottom
   margin. Without this rule it measured 319 wide and 1,912 tall. */
.woocommerce #content .wh-pdp .wh-pdp__media div.images,
.woocommerce-page #content .wh-pdp .wh-pdp__media div.images,
.woocommerce #content .wh-pdp .wh-pdp__media .woocommerce-product-gallery,
.woocommerce .wh-pdp .wh-pdp__media div.images,
.wh-pdp .woocommerce-product-gallery {
	float: none;
	width: 100%;
	margin: 0 0 32px;
	padding: 0;
}

/* widget-woocommerce-product-images did exactly this on live, scoped to its own widget class. */
.wh-pdp .woocommerce-product-gallery__trigger + .woocommerce-product-gallery__wrapper {
	overflow: hidden;
}

/* The flexslider thumbnail strip. These four are the product-images widget's own settings from
   12571/14085 — zero gap between thumbnails, no border, no gap under the viewport — and without
   them WooCommerce's default padding on .flex-control-thumbs li made the gallery measure 1,288px
   tall against live's 1,004. */
.wh-pdp .wh-pdp__media .flex-viewport:not(:last-child) {
	margin-bottom: 0;
}

.wh-pdp .wh-pdp__media .flex-control-thumbs {
	margin-right: 0;
	margin-left: 0;
}

.wh-pdp .wh-pdp__media .flex-control-thumbs li {
	padding-right: 0;
	padding-left: 0;
	padding-bottom: 0;
}

.wh-pdp .wh-pdp__media .flex-control-thumbs img {
	border-style: none;
}

/* The sale badge. Astra's markup, WooCommerce's template, Elementor's zero padding — measured on
   live 13418, `<span  class="onsale circle">` immediately above the gallery inside the left
   column. Only the padding reset came from the dropped widget stylesheet. */
.wh-pdp .wh-pdp__media > span.onsale {
	padding: 0;
}

/* Title — live h1 21px/600 Questrial, colour the kit Primary, margin-bottom 10.5px. */
.wh-pdp h1.product_title {
	font-family: var(--wh-ff-questrial);
	font-size: 21px;
	font-weight: 600;
	line-height: 1.4em;
	color: var(--wh-primary);
	margin: 0 0 10.5px;
	padding: 0;
	text-align: start;
}

/* Price row — live container 63b23b0 (12571) / 70eb5b4 (14085): flex row, space-between, 20px
   gap, 10px padding. 12571 additionally sets flex-wrap:nowrap; 14085 does not. nowrap is used
   here for both, because at 360 the row still measures as one line on live. */
.wh-pdp__pricerow {
	display: flex;
	flex-direction: row;
	flex-wrap: nowrap;
	justify-content: space-between;
	align-items: baseline;
	gap: 20px;
	padding: 10px;
	width: 100%;
}

.wh-pdp__pricerow p.price,
.wh-pdp__pricerow .price {
	font-family: var(--wh-ff-questrial);
	font-size: 23px;
	font-weight: 400;
	line-height: var(--wh-lh);
	color: var(--wh-body-ink);
	margin: 0 0 4.6px;
	padding: 0;
}

.wh-pdp__stars {
	flex: 0 0 auto;
}

/* ⚠ The one CSS difference between the two documents, and it is real. 12571's price row
   (63b23b0) has Elementor's default 10px container padding and `flex-wrap:nowrap`; 14085's
   (70eb5b4) sets `--padding: 0px` on all four sides and does not set flex-wrap. Measured: the row
   is 51px tall on 806 and 31px on 4650, and the price starts at x=854 on 806 and x=844 on 4650.
   Reproduced through the body class the template sets for the branch. */
.wh-pdp-premium .wh-pdp__pricerow {
	padding: 0;
}

/* The rule — live's divider widget 9dab088: 1px solid in the kit Secondary, left aligned, full
   width, 15px padding above and below, which computes to a 31px box. */
.wh-pdp__rule {
	padding-block-start: 15px;
	padding-block-end: 15px;
	width: 100%;
}

.wh-pdp__rule > span {
	display: block;
	border-top: 1px solid var(--wh-secondary);
	width: 100%;
	margin-left: 0;
	margin-right: auto;
}

/* The cart. form.cart's margin reset is the one thing the dropped
   widget-woocommerce-product-add-to-cart stylesheet was doing that the rebuilt markup still needs;
   its `display:flex` rule is deliberately NOT restated, because live's form computes to
   `display:block` anyway (something later in the cascade beats it) and the parts stack. */
.wh-pdp .summary form.cart {
	margin: 0;
}

/* The black pill. Live's rule, from the add-to-cart widget's own settings (7615cb9 on 12571,
   abcfa34 on 14085 — identical declarations):
       .cart button, .cart .button { border:1px solid var(--e-global-color-1cfbcb3e);
                                     border-radius:20px; color:var(--e-global-color-10b519c8);
                                     background-color:var(--e-global-color-1cfbcb3e);
                                     transition:all .2s }
       :hover { colour and background swapped }
       .quantity .qty { transition:all .2s }
   i.e. white on black with a 20px radius, inverting on hover. It went with the suppressed
   document CSS, so it is restated here — without it the button rendered black-on-accent, which
   is Astra's default and is not what any customer has seen. */
.wh-pdp .summary form.cart button,
.wh-pdp .summary form.cart .button {
	border-style: solid;
	border-width: 1px;
	border-radius: 20px;
	color: var(--wh-white);
	background-color: var(--wh-ink);
	border-color: var(--wh-ink);
	transition: all 0.2s;
}

.wh-pdp .summary form.cart button:hover,
.wh-pdp .summary form.cart .button:hover {
	color: var(--wh-ink);
	background-color: var(--wh-white);
	border-color: var(--wh-ink);
}

.wh-pdp .summary .quantity .qty {
	transition: all 0.2s;
}

/* Elementor's e-atc-qty-button-holder, under our own class and reproduced from its measured
   computed style on live: flex, wrapping, flex-start. Both children are full width, so they
   stack — which is why the live button sits under the quantity rather than beside it. */
.wh-pdp__qtyrow {
	display: flex;
	flex-wrap: wrap;
	justify-content: flex-start;
	width: 100%;
}

.wh-pdp .summary .quantity {
	vertical-align: middle;
}

.wh-pdp .summary .quantity .qty {
	margin-inline-end: 0;
	vertical-align: top;
}

/* "Features" — heading widget 1f324bd: 14px/600, 0.9px letter-spacing, padding 0 0 6px 14px. */
/* Live's heading widget carries padding 0 0 6px 14px on its .elementor-widget-container, so the
   h3 itself measures 18px tall and the 6px sits outside it. Reproduced as a margin so the heading
   box matches live's 18px rather than live's 24px container. */
.wh-pdp__features-title {
	font-family: var(--wh-ff-questrial);
	font-size: 14px;
	font-weight: 600;
	letter-spacing: 0.9px;
	line-height: 1.3em;
	color: var(--wh-primary);
	margin: 0 0 6px 14px;
	padding: 0;
	text-align: start;
}

/* ⚠ ONE PRODUCT'S SHORT DESCRIPTION CONTAINS PASTED ELEMENTOR MARKUP, AND IT REUSES THE
   REPLACED TEMPLATE'S ELEMENT IDS.

   Product 4650's post_excerpt is not text: it is a copy of the rendered "Features" heading and
   short-description widgets, `<div class="elementor-element elementor-element-1f324bd …">` and
   `…-7574eed`, pasted into the excerpt field. On live those pasted divs are styled by document
   14085's own inline CSS, because they carry the same element ids as 14085's real widgets — so
   suppressing that document's CSS (gate leg 3c) also unstyles the paste, and the inner "Features"
   heading falls back to the browser's default h-size. Measured: live's pasted heading block is
   24px tall, the rebuilt one was 78px, and the safe's short description came out 127px too long
   at 1440 and 190px at 360.

   These four rules restate what 14085's CSS was doing for exactly those two element ids inside a
   short description, and nowhere else. Nothing on any other product matches them.

   (The equivalent problem does NOT arise for the safe's long description: that is a proper
   `product-post` document with its own `.elementor-4650` CSS, which leg 3c is careful to leave
   alone — see NOTES-pdp.md §6.) */
.wh-pdp .woocommerce-product-details__short-description .elementor-element {
	margin-block-end: 0;
}

.wh-pdp .woocommerce-product-details__short-description .elementor-heading-title {
	font-family: var(--wh-ff-questrial);
	font-size: 14px;
	font-weight: 600;
	letter-spacing: 0.9px;
	line-height: 1.3em;
	color: var(--wh-primary);
	margin: 0;
}

.wh-pdp .woocommerce-product-details__short-description .elementor-element-1f324bd > .elementor-widget-container {
	padding: 0 0 6px 14px;
}

.wh-pdp .woocommerce-product-details__short-description .elementor-element-7574eed > .elementor-widget-container {
	padding: 0;
}

/* Short description — widget 7574eed: padding 0 0 0 13px, kit text typography (Questrial 14px). */
.wh-pdp .woocommerce-product-details__short-description {
	font-family: var(--wh-ff-questrial);
	font-size: 14px;
	font-weight: 400;
	line-height: var(--wh-lh);
	color: var(--wh-body-ink);
	margin: 0 0 0 13px;
	padding: 0;
}

/* ---------------------------------------------------------------------------
   The accordion — live's nested-accordion widget 46bd72a.

   From its own CSS: --n-accordion-title-font-size:14px, item spacing 9px, distance from content
   0px, container margin 0 / padding 10px 0 0 0, each item title bordered 0 0 1px 0 in #0A1C2E29,
   title text weight 500 and line-height 9px. Measured: the title box is 436x30 with 10px padding
   and align-items:center; four .e-n-accordion-item elements on live (two of them the widget's own
   and two inside the safe's builder description), the first 436x669.
   --------------------------------------------------------------------------- */

.wh-pdp__acc {
	margin: 0;
	padding: 10px 0 0 0;
	width: 100%;
}

.wh-pdp__acc-item {
	display: flex;
	flex-direction: column;
	margin: 0 0 9px;
	border-bottom: 1px solid var(--wh-acc-rule);
}

.wh-pdp__acc-item:last-child {
	margin-bottom: 0;
}

/* The widget's own numbers land on two different elements, and putting them all on one was worth
   a measured 6px and the wrong weight. Live's .e-n-accordion-item-title computes to the inherited
   16px/400/26.4px in #1F2124 with 10px padding and align-items:center; it is the inner
   .e-n-accordion-item-title-text that carries font-weight:500 and line-height:9px, and the
   widget's --n-accordion-title-font-size:14px. */
.wh-pdp__acc-title {
	display: flex;
	flex-direction: row;
	align-items: center;
	gap: 0;
	padding: 10px;
	cursor: pointer;
	list-style: none;
	font-family: var(--wh-ff-body);
	font-size: 16px;
	font-weight: 400;
	line-height: var(--wh-lh);
	color: #1f2124;
}

.wh-pdp__acc-text {
	font-size: 14px;
	font-weight: 500;
	line-height: 9px;
}

/* Elementor's nested-accordion prints no icon here: the widget's accordion_item_title_icon is
   empty and only the ACTIVE icon is set, which it does not render. Safari and Chrome both draw a
   disclosure triangle on a bare <summary>, so it is removed to match. */
.wh-pdp__acc-title::-webkit-details-marker,
.wh-pdp__acc-title::marker {
	display: none;
	content: "";
}

.wh-pdp__acc-body {
	padding: 0;
}

/* Live's accordion body is a container with a 20px flex gap holding exactly ONE widget, so the
   gap never separates anything. One wrapper, one flex child, live's spacing.

   The 10px side padding is Elementor's container default on that body container, and it is not
   cosmetic: the safe's specification sheet is 4,296px of wrapped text on live and every pixel of
   indent changes where the lines break. Measured off the live 4650 capture — the body copy starts
   10px right of the summary text, not level with it. */
.wh-pdp__acc-inner {
	padding: 0 10px 10px;
	font-family: var(--wh-ff-questrial);
	font-size: 14px;
	font-weight: 400;
	line-height: var(--wh-lh);
	color: var(--wh-ink);
}

.wh-pdp__acc-inner p {
	margin: 0 0 1.75em;
}

/* ---------------------------------------------------------------------------
   3. Trust band — live container 1615fb6d, byte-identical on both documents.
   Desktop: background #0A1C2E, flex row, space-between, gap 6%/8%, padding 3% 8% 1%,
   margin-top 4%. Measured at 1440: 1440x316 at y=1660, padding 43.19/115.19/14.39,
   margin-top 57.59.
   Each column (1aeaa261) is a flex column with a 12px gap; the icon is 35px wide; the title
   (4f2900bf) is Questrial 20px/600 white centred with 10px of padding above; the text (6937ccee)
   is white and centred.
   --------------------------------------------------------------------------- */

.wh-pdp__trust {
	display: flex;
	flex-direction: row;
	justify-content: space-between;
	background-color: var(--wh-primary);
	row-gap: 6%;
	column-gap: 8%;
	margin: 4% 0 0;
	padding: 3% 8% 1%;
}

/* Elementor's default container padding is 10px, and live's first trust column measures 339 wide
   at x=115 with its title inset to x=125 — i.e. the 10px is on the column, not on the widgets. */
.wh-pdp__trust-col {
	display: flex;
	flex-direction: column;
	gap: 12px;
	flex: 1 1 0;
	min-width: 0;
	padding: 10px;
}

.wh-pdp__trust-icon {
	width: 35px;
	height: auto;
	align-self: center;
}

.wh-pdp__trust-title {
	font-family: var(--wh-ff-questrial);
	font-size: 20px;
	font-weight: 600;
	line-height: 26px;   /* live's measured value, not a ratio */
	color: var(--wh-white);
	text-align: center;
	margin: 10px 0 0 0;
	padding: 0;
}

/* ⚠ margin-bottom, not 0. On live each of these paragraphs sits inside an Elementor widget
   container, so Astra's `p{margin-bottom:1.75em}` stays INSIDE the widget's box and counts toward
   the column height. Here the paragraph IS the flex item, so zeroing the margin lost 24px per
   column and the whole trust band measured 292px against live's 316. Same reasoning for the
   "Perfect Watch Box" copy, the "Here To Help" copy and the accordion bodies below. */
.wh-pdp__trust-text {
	font-family: var(--wh-ff-questrial);
	font-size: 14px;
	font-weight: 400;
	line-height: var(--wh-lh);
	color: var(--wh-white);
	text-align: center;
	margin: 0 0 1.75em;
}

.wh-pdp__trust-text a {
	color: var(--wh-white);
}

/* ---------------------------------------------------------------------------
   4. "Your Perfect Watch Box Is Here!" — live container 5ef0c06d (boxed, flex row,
   align-items:center, gap 4px/50px, margin-top 20px, padding 20px) with a copy column 39079016
   (flex, 20px gap; 15px at <=1024) and a photo container 5439040c whose only content is a
   background image, min-height 491px (290px at <=767), background-position top center,
   background-size cover.
   Measured at 1440: band 1440x531 at y=1996; photo 550x491 at x=740.
   --------------------------------------------------------------------------- */

.wh-pdp__perfect {
	margin: 20px 0 0;
	padding: 20px;
}

.wh-pdp__perfect-inner {
	max-width: var(--wh-boxed);
	margin: 0 auto;
	display: flex;
	flex-direction: row;
	align-items: center;
	row-gap: 4px;
	column-gap: 50px;
}

/* Equal halves. Live's are 540 and 550 inside a 1,140 row with a 50px gap — Elementor
   distributes them by content and lands 5px off centre. `flex:1 1 auto` reproduces the mechanism
   but not the result here, because the rebuilt photo element has no content at all to be measured
   by: it took 0px and the copy took the whole row. 545/545 is 5px from live and is the honest
   trade. Filed as deviation 6 in NOTES-pdp.md. */
.wh-pdp__perfect-copy {
	display: flex;
	flex-direction: column;
	gap: 20px;
	flex: 1 1 0;
	min-width: 0;
	padding: 0;
}

.wh-pdp__perfect-title {
	font-family: var(--wh-ff-poppins);
	font-size: 48px;
	font-weight: 600;
	line-height: 1.2em;
	letter-spacing: 0;
	text-transform: none;
	text-decoration: none;
	color: var(--wh-navy-title);
	text-align: center;
	margin: 0;
}

.wh-pdp__perfect-text {
	/* kit typography aed9f43: Questrial 16px/400 */
	font-family: var(--wh-ff-questrial);
	font-size: 16px;
	font-weight: 400;
	line-height: var(--wh-lh);
	color: var(--wh-primary);
	text-align: center;
	margin: 0 0 1.75em;
}

.wh-pdp__perfect-photo {
	flex: 1 1 0;
	min-width: 0;
	min-height: 491px;
	background-position: top center;
	background-repeat: no-repeat;
	background-size: cover;
}

/* ---------------------------------------------------------------------------
   5. The review wall — live container 74c0ea62: flex column, justify-content:space-evenly,
   align-items:center, 9px gap, 20px padding, width 80% at >=768px (so 1152 of 1440, centred);
   heading 684e2f43 is Manrope 34px/700 uppercase 1px-tracked #AD5207, centred, and grows to
   100% width and 43px at <=767px.
   Measured at 1440: band 1152x2137 at x=144, wall 760x2023 at y=2621, and it converged in under
   three seconds behind a real input event.

   The min-height reserves the space the plugin's script fills, so the two sections below do not
   jump when it lands. It is a floor, not a fixed height: a wall that renders taller simply pushes
   the page down as live's does.
   --------------------------------------------------------------------------- */

.wh-pdp__reviews {
	display: flex;
	flex-direction: column;
	justify-content: space-evenly;
	align-items: center;
	gap: 9px;
	padding: 20px;
	width: 80%;
	margin-left: auto;
	margin-right: auto;
}

/* The heading is a flex item in a centred column, so it is sized to its content — measured 526
   wide on live at 1440, not the full 1,152 band. It only grows to 100% at <=767px, which is what
   the widget's own mobile rule says and what the mobile block below restates. */
.wh-pdp__reviews-title {
	font-family: var(--wh-ff-manrope);
	font-size: 34px;
	font-weight: 700;
	line-height: 1.2em;
	letter-spacing: 1px;
	word-spacing: 0;
	text-transform: uppercase;
	text-decoration: none;
	color: var(--wh-rust);
	text-align: center;
	margin: 0;
	padding: 0;
	flex-grow: 1;
	flex-shrink: 0;
}

.wh-pdp__reviews .wsr_wall {
	width: 100%;
	/* Deploy-time finding (28/08): Wiser sizes its masonry from its container and self-assigns a
	   width-tier class. Live hands it a 760px Elementor column (chain measured on the deployed
	   pages: wall 760 wide, 2,023 tall, class ...-theme-wrap-medium); at this band's full 1,152px
	   the widget took its wide tier, packed four columns instead of two, and the document came out
	   ~650px short. The cap below is live's column width; margin auto is live's centring. Inert on
	   mobile, where the container is already narrower than the cap. */
	max-width: 760px;
	margin-left: auto;
	margin-right: auto;
	min-height: 320px;
}

/* ---------------------------------------------------------------------------
   6. "You might also like.." + the related row.

   Live container 88bc414 holds heading e318935 (Questrial 30px/600, centred) and the
   product-related widget 5b38b82, whose grid is Elementor's:
      ul.products.elementor-grid { display:grid; grid-column-gap:20px; grid-row-gap:40px }
      li.product { float:none; margin:0; padding:0; width:auto }
      li.product .onsale { display:none }
      .elementor-products-grid:not(.show-heading-yes) .products > h2 { display:none }
   and the columns come from the widget's own columns / columns_tablet / columns_mobile controls,
   which measure 4 / 3 / 2 — the body class list on live says so in as many words
   (`rel-up-columns-4 tablet-rel-up-columns-3 mobile-rel-up-columns-2`).
   Measured at 1440: ul 1140 wide, grid-template-columns 270px x4, gap 40px 20px, cards 270x370.
   Card title and price are kit typography aed9f43, i.e. Questrial 16px/400.

   WooCommerce's own `<h2>Related products</h2>` is left in the markup and hidden, because that is
   what live does and because removing it would change what a screen reader is handed.
   --------------------------------------------------------------------------- */

/* Live's container 88bc414 holds the heading and the related widget with 41px between the
   heading's bottom edge and the section's top edge (heading y=4674 h=39, section y=4754). The
   rebuild has no wrapper around the two — wrapping them would need an opener and a closer on two
   different hooks, which is the shape that cost James Butler seven sections — so the gap is a
   margin on the heading, and it is live's measured 41px rather than a guess at Elementor's
   20px widget margin plus 10px container padding plus whatever else. */
.wh-pdp__related-title {
	font-family: var(--wh-ff-questrial);
	font-size: 30px;
	font-weight: 600;
	line-height: 1.4em;
	text-align: center;
	color: var(--wh-primary);
	max-width: var(--wh-boxed);
	width: calc(100% - 20px);
	margin: 10px auto 41px;
	padding: 0;
	line-height: 1.3em;
}

#content .wh-pdp .related.products,
.wh-pdp .related.products {
	max-width: var(--wh-boxed);
	width: calc(100% - 20px);
	margin: 0 auto;
	padding: 0;
	float: none;
}

.wh-pdp .related.products > h2 {
	display: none;
}

#content .wh-pdp .related.products ul.products,
.wh-pdp .related.products ul.products {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	column-gap: 20px;
	row-gap: 40px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.wh-pdp .related.products ul.products::before,
.wh-pdp .related.products ul.products::after {
	content: none;
	display: none;
}

#content .wh-pdp .related.products ul.products li.product,
.wh-pdp .related.products ul.products li.product {
	float: none;
	margin: 0;
	padding: 0;
	width: auto;
	clear: none;
	/* position:relative is not tidiness. aco-product-labels prints its black OUT OF STOCK pill as
	   an absolutely-positioned span inside the card; without a positioned card it takes the
	   nearest positioned ancestor and floats to the top of the whole related section. Caught in
	   the screenshot, not in the numbers. */
	position: relative;
}

/* Elementor hides the card sale badge on this grid. Reproduced, because live's related row shows
   no badge even when a card is on sale — the black `acoplw` label plugin pill is a different
   element and is NOT hidden. */
.wh-pdp .related.products ul.products li.product .onsale {
	display: none;
	padding: 0;
}

.wh-pdp .related.products ul.products li.product a.woocommerce-LoopProduct-link {
	display: block;
	position: relative;
}

.wh-pdp .related.products ul.products li.product .woocommerce-loop-product__title,
.wh-pdp .related.products ul.products li.product .price {
	font-family: var(--wh-ff-questrial);
	font-size: 16px;
	font-weight: 400;
}

/* ---------------------------------------------------------------------------
   7. "Here To Help" — live container 4444233b: background the kit stone #E9E8E6, flex row,
   justify-content:center, align-items:center, gap 13%/8%, margin-top 3%, padding 20px; at
   <=1024px it becomes column-reverse with a 70px gap, 2% margin-top and 2%/5% padding; at <=767px
   the gap is 50px and the margin-top 5%.
   The single column 626f68f is 65% wide at >=768 (100% between 768 and 1024), a flex column with
   a 15px gap and align-items:center.
   Heading 6ca35676 is Poppins 65px/600 #1C244B, left-aligned on desktop, centred and 45px at
   <=1024, centred and 28px/1.1em at <=767.
   Copy 7aab70ed is kit aed9f43 (Questrial 16px/400) in the kit Primary, centred.
   Button 8416f2e is Poppins 16px/400 capitalised, white on the kit Primary, 1px border in the
   same colour, 100px radius, padding 16px 55px; 14px and 15px/35px at <=767.
   Measured at 1440: band 1440x386 at y=5177, margin-top 43.19, button 209x50.
   --------------------------------------------------------------------------- */

.wh-pdp__help {
	display: flex;
	flex-direction: row;
	justify-content: center;
	align-items: center;
	row-gap: 13%;
	column-gap: 8%;
	background-color: var(--wh-stone);
	margin: 3% 0 0;
	padding: 20px;
}

.wh-pdp__help-inner {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 15px;
	width: 65%;
	padding: 0;
}

/* Sized to its content and centred by the column's align-items, exactly as live's is: measured
   468 wide inside a 936-wide column at 1440. */
.wh-pdp__help-title {
	font-family: var(--wh-ff-poppins);
	font-size: 65px;
	font-weight: 600;
	line-height: 1.2em;
	letter-spacing: 0;
	text-transform: none;
	text-decoration: none;
	color: var(--wh-navy-title);
	text-align: start;
	margin: 0;
}

.wh-pdp__help-text {
	font-family: var(--wh-ff-questrial);
	font-size: 16px;
	font-weight: 400;
	line-height: var(--wh-lh);
	color: var(--wh-primary);
	text-align: center;
}

.wh-pdp__help-text p {
	margin: 0 0 1.75em;
}

.wh-pdp__help-btn {
	display: inline-block;
	font-family: var(--wh-ff-poppins);
	font-size: 16px;
	font-weight: 400;
	line-height: 1em;
	letter-spacing: 0;
	text-transform: capitalize;
	text-decoration: none;
	color: var(--wh-white);
	fill: var(--wh-white);
	background-color: var(--wh-primary);
	border: 1px solid var(--wh-primary);
	border-radius: 100px;
	padding: 16px 55px;
	transition: background-color 0.2s, color 0.2s;
}

.wh-pdp__help-btn:hover,
.wh-pdp__help-btn:focus {
	background-color: transparent;
	color: var(--wh-primary);
}

/* ---------------------------------------------------------------------------
   ⚠ Astra's own breakpoint, not Elementor's, and it changes the leading everywhere.

   `astra.break_point` is 921 on this site (read from the theme's localised script data), and at
   or below it Astra drops the body font-size to 14.592px. The body line-height is 1.65 and is
   INHERITED as a computed pixel value, so every block of text on the page goes from 26.4px of
   leading to 14.592 x 1.65 = 24.0768px.

   Hard-coding --wh-lh at 26.4px cost the $16,000 safe's specification sheet 408px of extra height
   at 360 — measured: live's `.e-con-inner` reports line-height 24.0768px there and the rebuilt
   one reported 26.4px, at identical widths (both 280px) and identical font-size (both 14px).
   Nothing else about that block differed.
   --------------------------------------------------------------------------- */

@media (max-width: 921px) {
	.wh-pdp {
		--wh-lh: 24.0768px;
	}
}

/* ---------------------------------------------------------------------------
   Tablet — Elementor's (max-width:1024px).
   --------------------------------------------------------------------------- */

@media (max-width: 1024px) {
	.wh-pdp {
		--wh-boxed: 1024px;
	}

	.wh-pdp__trust {
		flex-direction: row;
		row-gap: 10px;
		column-gap: 10px;
		flex-wrap: nowrap;
		margin: 0;
		padding: 3%;
	}

	.wh-pdp__perfect-copy {
		gap: 15px;
	}

	.wh-pdp__perfect-title {
		font-size: 45px;
	}

	.wh-pdp__reviews {
		row-gap: 37px;
		column-gap: 37px;
		flex-wrap: wrap;
	}

	#content .wh-pdp .related.products ul.products,
	.wh-pdp .related.products ul.products {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}

	.wh-pdp__help {
		flex-direction: column-reverse;
		row-gap: 70px;
		column-gap: 70px;
		margin: 2% 0 0;
		padding: 2% 5%;
	}

	.wh-pdp__help-inner {
		width: 100%;
		padding: 0 15%;
	}

	.wh-pdp__help-title {
		font-size: 45px;
		text-align: center;
	}
}

/* ---------------------------------------------------------------------------
   Mobile — Elementor's (max-width:767px).
   Measured live at 360: the buy box stacks (gallery 320 wide at x=20), the trust band becomes one
   centred column 753px tall, the photo container drops to 290px, the review heading grows to
   43px, and the related grid becomes two columns.
   --------------------------------------------------------------------------- */

@media (max-width: 767px) {
	.wh-pdp {
		--wh-boxed: 767px;
	}

	#content .wh-pdp .wh-pdp__product,
	.wh-pdp .wh-pdp__product {
		flex-direction: column;
		flex-wrap: wrap;
	}

	#content .wh-pdp .wh-pdp__product > .wh-pdp__media,
	#content .wh-pdp .wh-pdp__product > .summary.entry-summary,
	.wh-pdp .wh-pdp__product > .wh-pdp__media,
	.wh-pdp .wh-pdp__product > .summary.entry-summary {
		width: 100%;
		max-width: 100%;
		margin-left: 0;
		margin-right: 0;
	}

	.wh-pdp__trust {
		flex-direction: column;
		justify-content: center;
		row-gap: 20px;
		column-gap: 20px;
		margin: 0;
		padding: 20px;
	}

	.wh-pdp__perfect-inner {
		flex-direction: column;
	}

	.wh-pdp__perfect-copy,
	.wh-pdp__perfect-photo {
		width: 100%;
		flex: 0 0 auto;
	}

	.wh-pdp__perfect-title {
		font-size: 28px;
		line-height: 1.1em;
	}

	.wh-pdp__perfect-photo {
		min-height: 290px;
	}

	.wh-pdp__reviews {
		width: 100%;
		row-gap: 20px;
		column-gap: 20px;
		padding: 15% 5%;
	}

	.wh-pdp__reviews-title {
		font-size: 43px;
		width: 100%;
		max-width: 100%;
	}


	#content .wh-pdp .related.products ul.products,
	.wh-pdp .related.products ul.products {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	/* ⚠ NOT REPRODUCING A QUIRK, AND HERE IS WHY. At 360 live's related cards measure 140px
	   inside their 160px grid tracks on product 806 — each <li> picks up a 20px right margin
	   somewhere — but 160px, filling the track, on product 4650. Same markup, same grid
	   (`160px 160px` on both), same four cards, same viewport: live is not self-consistent, and
	   the cause was not traced to a stylesheet. Reproducing one of the two would have made the
	   other wrong, so the rebuilt cards fill their track on both, which is what live does on the
	   larger of the two and what both do at 1440 (270px cards in 270px tracks). Filed as
	   deviation 7 in NOTES-pdp.md with the measurements. */

	.wh-pdp__help {
		row-gap: 50px;
		column-gap: 50px;
		margin: 5% 0 0;
	}

	.wh-pdp__help-inner {
		padding: 0;
	}

	.wh-pdp__help-title {
		font-size: 28px;
		line-height: 1.1em;
		text-align: center;
	}

	.wh-pdp__help-btn {
		font-size: 14px;
		padding: 15px 35px;
	}
}
