/* Westhill Watch Boxes — product category archive.
   Hand-written to match the existing design, breakpoint for breakpoint. Loaded only on a product
   category, and only inside the preview gate.

   Every number below was read off the live archive
   (/a/all-watch-boxes/premium-watch-boxes/) with getComputedStyle at 1440x900, 1024x900, 767x900
   and 360x740, or out of Elementor archive template 14379's 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
   14379's CSS is not a stylesheet with a handle — it is 36,558 bytes inlined on the
   elementor-frontend handle, alongside the header's 34,606, the footer's 39,363, the kit's 1,444
   and popup 12373's 12,942. The gate leg in NOTES-category.md suppresses 14379's share for the
   previewed archive; everything it was doing for the hero, the sort select, the sidebar, the
   grid and the Load More button has to be done here instead.

   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 and Roboto both fall through to the browser's generic sans-serif. Measured, not
   assumed — a width probe against a deliberately impossible family returned identical widths for
   every declared family. 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:

       --wh-ff-questrial: "Questrial", sans-serif;

   and nothing else in this file has to move.

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

.wh-cat {
	--wh-ff-questrial: sans-serif;  /* intended: "Questrial", 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-accent: #ccbb7e;       /* kit: Accent        */
	--wh-white: #fff;           /* kit: 10b519c8      */
	--wh-ink: #000;             /* kit: 1cfbcb3e      */
	--wh-hover-tint: #0e0f1133; /* kit: 66b4e453, the pagination hover */
	--wh-rule: rgba(122, 122, 122, 0.32);   /* divider 6388a52 */
	--wh-acc-rule: rgba(0, 0, 0, 0.17);     /* accordion 157edad0: #0000002B */
	--wh-ctrl-border: #ccc;                 /* Jet's own control border      */
	--wh-select-border: #e2e8f0;
	--wh-body-ink: #010101;
	--wh-acc-ink: #1f2124;

	/* 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
	   description reads 14px/26.4px rather than 14px/23.1px, and why these are px and not ratios. */
	--wh-lh: 26.4px;

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

/* Astra boxes a normal archive in .ast-container. This page is full-bleed, exactly as the
   Elementor template it replaces is. The template also asks Astra for the page-builder content
   layout; this is the braces to that belt. */
.wh-cat-page .ast-container,
.wh-cat-page #primary,
.wh-cat-page .site-content > .ast-container {
	max-width: none;
	width: auto;
	padding-left: 0;
	padding-right: 0;
	margin-left: 0;
	margin-right: 0;
}

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

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

/* ---------------------------------------------------------------------------
   1. Hero — live container b0b1636.

   1440x200 desktop, 1024x126 tablet, 360x103 mobile. One shared photo for every category
   (background-position: bottom center, background-size: cover), no overlay: the ::before layer
   exists on live but paints rgba(0,0,0,0). The inner is Elementor's e-con-inner at the
   container's --content-width of 980px, centred, and the title is vertically centred in the band.
   --------------------------------------------------------------------------- */

.wh-cat__hero {
	display: flex;
	flex-direction: column;
	justify-content: center;
	min-height: 200px;
	padding: 0 4%;
	background-position: bottom center;
	background-repeat: no-repeat;
	background-size: cover;
	/* The background-image itself is printed inline by the template, because it is data (a term
	   thumbnail when one exists, the shared photo otherwise) rather than design. */
}

.wh-cat__heroinner {
	width: 100%;
	max-width: 980px;
	margin: 0 auto;
	padding: 0 20px;
	display: flex;
	justify-content: center;
}

/* The h1 itself measures 940 inside a 980px content width on live, so the 20px each side belongs
   to the wrapper (above) and the heading fills what is left. */
.wh-cat__title {
	width: 100%;
	margin: 0;
	padding: 0;
	font-family: var(--wh-ff-questrial);
	font-size: 31px;
	font-weight: 400;
	line-height: 1.1em;
	letter-spacing: 10px;
	text-transform: uppercase;
	text-align: center;
	color: var(--wh-white);
}

/* ---------------------------------------------------------------------------
   2. Term description and sort — live section 156f6c14.

   A legacy Elementor section: 0 40px padding, two columns at 80% and 20% of the 1360px inner,
   each with 10px padding, and the description carrying a further 10px from the nested container
   Elementor put it in. That nesting is why the description starts at x=60 and is 1048 wide on a
   1440 viewport, and it is reproduced rather than tidied so the two pages line up.

   The sort column carries `elementor-hidden-tablet elementor-hidden-mobile` on live, so the sort
   control DISAPPEARS at 1024px and below and there is no way to sort on a phone. Reproduced.
   NOTES-category.md files it as a deviation candidate rather than quietly fixing it.
   --------------------------------------------------------------------------- */

.wh-cat__intro {
	padding: 0 40px;
}

.wh-cat__introinner {
	display: flex;
	align-items: center;
}

.wh-cat__desccol {
	width: 80%;
	padding: 20px;
}

.wh-cat__sortcol {
	width: 20%;
	padding: 10px;
}

/* The -25px is live's, not a mistake. Widget f4af166 carries `_margin: bottom -25px` in template
   14379, and Astra gives every <p> a 1.75em bottom margin, which at 14px is 24.5px. The two
   collapse together to -0.5px, which is why the live description block measures 78.719px against
   the 79.219px its three lines of text occupy, and why the whole intro row is 118.719px rather
   than 119.219px. Half a pixel — but it is half a pixel on every archive on the site, and without
   it every element below this row sits one rounded pixel low against the live page. */
.wh-cat__desc {
	margin-bottom: -25px;
	font-family: var(--wh-ff-questrial);
	font-size: 14px;
	font-weight: 400;
	line-height: var(--wh-lh);
	color: var(--wh-primary);
}

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

/* flex-column, exactly as live's .jet-sorting--flex-column wrapper is. Not decoration: an
   inline-block <select> inside a plain block sits in a line box whose descender makes the wrapper
   ~41px rather than 37px, and centring THAT in the 119px row puts the control one pixel low —
   which then carried down the whole page in the comparison. */
.wh-cat__sort {
	display: flex;
	flex-direction: column;
	margin: 0;
}

.wh-cat__select {
	width: 100%;
	max-width: 100%;
	height: 37px;
	padding: 8px 32px 8px 12.8px;
	font-family: var(--wh-ff-body);
	font-size: 16px;
	font-weight: 400;
	line-height: normal;
	color: #666;
	background-color: var(--wh-white);
	border: 1px solid var(--wh-select-border);
	border-radius: 3px;
	-webkit-appearance: none;
	-moz-appearance: none;
	appearance: none;
	/* NO background-image. The chevron on live's sort select is ASTRA'S — an inline SVG data URI
	   at `98% 50%` and 12.8px, applied by the theme to selects generally, and it reaches this
	   control for the same reason it reaches live's. A hand-drawn arrow here was drawn instead of
	   Astra's, and the screenshot showed the difference before the measurements did. */
}

.wh-cat__sortgo {
	margin-top: 8px;
}

/* ---------------------------------------------------------------------------
   3. The rule — live container 46a1639 with divider 6388a52.
   15px of padding above and below a 1px line, 31px in total.
   --------------------------------------------------------------------------- */

.wh-cat__rule {
	display: flex;
	padding: 15px 0;
}

.wh-cat__ruleline {
	display: block;
	width: 100%;
	border-top: 1px solid var(--wh-rule);
}

/* ---------------------------------------------------------------------------
   4. Sidebar and grid — live container 726ea9d.
   flex row, 10px padding, 20px gap; sidebar 20%, grid column 78%.
   The 2% that is left over is live's own: 20 + 78 + the gap does not reach 100 and the row is
   left-aligned, so there is 18px of unused space on the right at 1440. Reproduced, because
   "correcting" it would move every card two pixels and make the comparison captures argue.
   --------------------------------------------------------------------------- */

.wh-cat__body {
	padding: 10px;
}

.wh-cat__inner {
	display: flex;
	flex-direction: row;
	gap: 20px;
}

.wh-cat__side {
	width: 20%;
	padding: 10px;
	/* align-self keeps the aside at its content height so position:sticky has something to slide
	   inside. Live stretches the column to the full row height and drives the stickiness from
	   Elementor's e-sticky JavaScript (sticky: top, offset 100, sticky_parent: yes); this is the
	   same behaviour with no script, which is also why e-sticky can leave the page. */
	align-self: flex-start;
	position: sticky;
	top: 100px;
}

.wh-cat__main {
	width: 78%;
	min-width: 0;   /* a grid child of a flex item will not shrink below its content without this */
	padding: 10px;
	display: flex;
	flex-direction: column;
	gap: 40px 0;
}

/* WooCommerce prints an empty .woocommerce-notices-wrapper when there is nothing to say. Live
   nests it inside the products widget, where it costs nothing; here it is a direct child of a flex
   column with a 40px gap, so an empty one would push the grid down 40px. `:empty` removes it from
   the flex flow without hiding a real notice. */
.wh-cat__main > .woocommerce-notices-wrapper:empty {
	display: none;
}

.wh-cat__mobilebar {
	display: none;
}

.wh-cat__tail {
	padding: 10px;
}

/* Sidebar chrome ------------------------------------------------------------ */

.wh-cat__sidetitle {
	margin: 0;
	font-family: var(--wh-ff-roboto);
	font-size: 17px;
	font-weight: 600;
	line-height: 1.2em;
	color: var(--wh-primary);
}

/* 25px above and below the line: the heading ends at y=572 on live, the line sits at 597 and the
   first accordion summary starts at 623. */
.wh-cat__siderule {
	display: flex;
	padding: 25px 0;
}

.wh-drawer__rule {
	display: flex;
	padding: 15px 0;
}

/* ---------------------------------------------------------------------------
   5. The filter accordion — live's nested-accordion 157edad0 with the three Jet widgets inside.

   <details>/<summary> instead of Elementor's div-and-JavaScript accordion, so a group opens with
   scripts disabled. Everything visible is matched: 10px padding on the summary, a 1px #0000002B
   rule under it, 1rem/26.4px title in Astra's body stack at #1f2124, the +/- icon at the end,
   10px of padding round the panel.
   --------------------------------------------------------------------------- */

.wh-filters {
	margin: 0;
}

.wh-acc__item {
	border: 0;
}

.wh-acc__summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 10px;
	margin: 0;
	border-bottom: 1px solid var(--wh-acc-rule);
	font-family: var(--wh-ff-body);
	font-size: 1rem;
	font-weight: 400;
	line-height: var(--wh-lh);
	color: var(--wh-acc-ink);
	cursor: pointer;
	list-style: none;
}

/* The default disclosure triangle would sit alongside the +/- glyph. */
.wh-acc__summary::-webkit-details-marker {
	display: none;
}

.wh-acc__summary::marker {
	content: "";
}

.wh-acc__icon {
	display: inline-flex;
	align-items: center;
	flex: 0 0 auto;
}

.wh-acc__icon svg {
	width: 13px;
	height: 15px;
	fill: currentColor;
}

/* Which of the two glyphs shows is the <details> element's own state, not a script's. */
.wh-acc__item .wh-acc__minus {
	display: none;
}

.wh-acc__item[open] .wh-acc__minus {
	display: block;
}

.wh-acc__item[open] .wh-acc__plus {
	display: none;
}

.wh-acc__panel {
	padding: 10px;
}

/* Live's Size list is a fixed-height scroller: the Jet widget prints style="max-height:332px" on
   .jet-filter-items-scroll and lets the remaining nine rows overflow. */
.wh-filters__list--scroll {
	max-height: 332px;
	overflow-y: auto;
}

.wh-filters__set {
	margin: 0;
	padding: 0;
	border: 0;
	min-width: 0;   /* a fieldset will not shrink inside a grid or flex parent without this */
}

/* Live's Jet widgets cancel their own row margins on the list wrapper — Size with
   margin:-5px -2.5px, Price with 0 -2.5px — so the controls line up with the panel's padding
   rather than sitting 2.5px inside it. Same here. */
.wh-acc__item--size .wh-filters__set {
	margin: -5px -2.5px;
}

.wh-acc__item--price .wh-filters__set {
	margin: 0 -2.5px;
}

/* Row spacing differs per group on live and the difference is visible, so it is kept:
   Size (3a42dbd5) 0 2.5px 5px with 5px of padding-top; Price (2261060) 0 2.5px with 10px between
   rows; Colour (48b3488d) block rows with 10px between them. */
.wh-filters__row {
	display: block;
	margin: 0 2.5px 5px;
	padding-top: 5px;
}

.wh-acc__item--price .wh-filters__row {
	margin: 0 2.5px 10px;
	padding-top: 0;
}

/* The colour list is jet-color-image-list, not jet-checkboxes-list: block rows, no side margin. */
.wh-acc__item--colour .wh-filters__row {
	margin: 0 0 10px;
	padding-top: 0;
}

.wh-acc__item--colour .wh-filters__row:last-child,
.wh-acc__item--price .wh-filters__row:last-child {
	margin-bottom: 0;
}

/* The native box is hidden, not removed: it stays focusable and it is what a screen reader and a
   keyboard operate. Jet does the same (`visibility:hidden; width:0; height:0`). */
.wh-filters__input {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: 0;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.wh-filters__item {
	position: relative;
	display: flex;
	align-items: center;
	margin: 0;
	padding: 0;
	font-family: var(--wh-ff-body);
	font-size: 16px;
	font-weight: 400;
	line-height: var(--wh-lh);
	color: var(--wh-body-ink);
	cursor: pointer;
}

.wh-filters__decorator {
	position: relative;
	display: block;
	flex: 0 0 auto;
	width: 16px;
	height: 16px;
	margin: 3px 5px 0 0;
	border: 1px solid var(--wh-ctrl-border);
	border-radius: 3px;
	background-color: transparent;
}

.wh-filters__tick {
	position: absolute;
	top: 50%;
	left: 50%;
	width: 12px;
	height: 12px;
	transform: translate(-50%, -50%);
	opacity: 0;
	color: var(--wh-white);
	fill: currentColor;
}

.wh-filters__input:checked + .wh-filters__item .wh-filters__decorator {
	background-color: var(--wh-primary);
	border-color: var(--wh-primary);
}

.wh-filters__input:checked + .wh-filters__item .wh-filters__tick {
	opacity: 1;
}

.wh-filters__labeltext {
	align-self: center;
	font-size: 12px;
	line-height: var(--wh-lh);
}

/* Keyboard focus. Live's Jet control has a focus-visible ring; a hidden native checkbox with no
   visible focus state would be worse than live, not equal to it. */
.wh-filters__input:focus-visible + .wh-filters__item .wh-filters__decorator {
	outline: 2px solid var(--wh-primary);
	outline-offset: 2px;
}

/* Colour swatches — live's colour-image list 48b3488d. A 25px circle with a 3px transparent ring
   that turns #28BD24 when the swatch is chosen; that is what the ring is for. */
.wh-filters__decorator--swatch {
	width: 25px;
	height: 25px;
	margin: 0 5px 0 0;
	border: 3px solid #54595f00;
	border-radius: 30px;
	overflow: hidden;
}

.wh-filters__input:checked + .wh-filters__item .wh-filters__decorator--swatch {
	border-color: #28bd24;
}

/* "Show more" / "Show less" — live's Colour list (widget 48b3488d): Roboto 14/400, underlined,
   left-aligned, sitting where the sixth swatch would be. A <details> so it works with scripts off;
   the label swaps on [open] rather than being rewritten by JavaScript. */
.wh-filters__more {
	display: block;
}

.wh-filters__moretoggle {
	display: block;
	margin-top: 4px;
	font-family: var(--wh-ff-roboto);
	font-size: 14px;
	font-weight: 400;
	line-height: var(--wh-lh);
	color: var(--wh-body-ink);
	text-align: left;
	text-decoration: underline;
	cursor: pointer;
	list-style: none;
	/* Source order puts the toggle before the extra rows; live puts it after them, and so does
	   this, without moving it in the markup where it would lose its <details> relationship. */
	order: 2;
}

.wh-filters__moretoggle::-webkit-details-marker {
	display: none;
}

.wh-filters__moretoggle::marker {
	content: "";
}

.wh-filters__more[open] {
	display: flex;
	flex-direction: column;
}

.wh-filters__more .wh-filters__moreoff,
.wh-filters__more[open] .wh-filters__moreon {
	display: none;
}

.wh-filters__more[open] .wh-filters__moreoff {
	display: inline;
}

.wh-filters__morebody {
	order: 1;
}

.wh-filters__apply {
	display: block;
	width: 100%;
	margin-top: 14px;
	padding: 10px 20px;
	font-family: var(--wh-ff-roboto);
	font-size: 14px;
	font-weight: 400;
	color: var(--wh-white);
	background-color: var(--wh-primary);
	border: 0;
	border-radius: 50px;
	cursor: pointer;
}

/* The inline script sets `hidden` on this button once it can auto-apply a filter on change, which
   is what live's AJAX filter does. `display: block` above would beat the UA stylesheet's
   `[hidden]{display:none}`, so the button stayed on screen with JavaScript enabled — visible in
   the first comparison screenshot, invisible in every measurement. */
.wh-filters__apply[hidden] {
	display: none;
}

/* ---------------------------------------------------------------------------
   6. Active-filter chips and Clear All.

   Live's jet-smart-filters-active and -remove-filters widgets carry a `hide-widget` class and
   stay empty until JavaScript fills them, so with scripts off live shows neither. These are
   rendered from the request instead. The "Clear All" wording, the 14px Roboto and the underline
   are live's own (widget 29b3594 / 54971c61).
   --------------------------------------------------------------------------- */

.wh-chips {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
}

.wh-chips--side {
	margin-bottom: 14px;
}

.wh-chips--above {
	margin-top: 12px;
}

.wh-chips--drawer {
	margin-top: 14px;
}

.wh-chips__chip {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 0 12px;
	height: 30px;
	font-family: var(--wh-ff-body);
	font-size: 12px;
	line-height: 30px;
	color: var(--wh-primary);
	background-color: #e3e4e4;
	border-radius: 40px;
	text-decoration: none;
}

.wh-chips__x {
	font-size: 15px;
	line-height: 1;
}

.wh-chips__clear {
	font-family: var(--wh-ff-roboto);
	font-size: 14px;
	font-weight: 400;
	color: var(--wh-primary);
	text-decoration: underline;
}

/* ---------------------------------------------------------------------------
   7. The grid — live widget b5e3731 over Astra's own loop markup.

   WooCommerce's own stylesheet says `.woocommerce ul.products li.product { float:left;
   width:30.75%; margin:0 3.8% 2.992em 0 }` and the body carries the `woocommerce` class, so that
   rule reaches these cards. Live cancels it through Elementor's wrapper
   (`.elementor-element .elementor-wc-products .woocommerce[class*='columns-'] ul.products
   li.product { width:auto; margin:0; float:none }`), which this template does not print. The
   cancellation below is written to OUTRANK it rather than to hope: four classes and one type
   against three classes and two types.
   --------------------------------------------------------------------------- */

/* THE SELECTOR IS FOUR CLASSES LONG ON PURPOSE, AND THIS IS THE ONE RULE IN THIS FILE THAT WOULD
   FAIL SILENTLY IF IT WERE SHORTER.
   Astra and WooCommerce both ship `ul.products:not(.elementor-grid)` grid rules — e.g.
   `.woocommerce-page ul.products:not(.elementor-grid){grid-template-columns:repeat(4,...)}` with
   a `(max-width:921px)` variant at three and a `(max-width:544px)` variant at two. Their
   specificity is (0,3,2). LIVE never meets them, because Elementor's widget puts `elementor-grid`
   on its list and the :not() excludes it; this template's list has no such class, so they reach
   it. At (0,3,0) the obvious `.wh-cat .wh-cat__grid.products` lost to them, and the symptom was
   subtle enough to be worth recording: the desktop and 360px layouts looked perfect because
   Astra's breakpoints happen to agree there, while 1024px rendered four columns against live's
   three and 767px rendered three against live's two. Four classes and a type is (0,4,1), which
   wins, and the same reasoning is why every card rule below is written through `li.product`. */
.wh-cat .wh-cat__main ul.wh-cat__grid.products {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 40px 20px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.wh-cat .wh-cat__grid.products li.product {
	float: none;
	clear: none;
	width: auto;
	max-width: none;
	min-width: 0;
	margin: 0;
	padding: 0;
	border: 0;
	background-color: transparent;
	text-align: left;
	/* Live's card is a flex column with the summary pushed to the foot, which is what keeps the
	   titles and prices of a row on one line when the images are the same height and the titles
	   are not. Elementor writes it through --button-align-* custom properties on the same element;
	   written plainly here. */
	display: flex;
	flex-direction: column;
	justify-content: space-between;
	box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0);
}

.wh-cat .wh-cat__grid.products li.product::before,
.wh-cat .wh-cat__grid.products li.product::after {
	content: none;
}

/* The thumbnail wrapper. `position: relative` is load-bearing three times over: it is the
   containing block for the hover image, for Astra's out-of-stock band and for the labels
   plugin's badge. */
.wh-cat .astra-shop-thumbnail-wrap {
	position: relative;
	display: block;
	margin: 0 0 12.8px;
	padding: 0;
	background-color: transparent;
}

.wh-cat .astra-shop-thumbnail-wrap > a {
	display: block;
	position: relative;
}

.wh-cat .wh-cat__grid.products li.product img {
	display: block;
	width: 100%;
	height: auto;
	margin: 0;
	border-radius: 0;
}

/* Hover swap. CONFIRMED ON LIVE, not assumed: all forty cards carry `astra-woo-hover-swap` and
   thirty-nine carry a second `img.show-on-hover`; the fortieth is a product with no gallery
   image, which is exactly what astra-addon's product_flip_image does when
   get_gallery_image_ids() comes back empty. Astra's own rules are reproduced rather than relied
   on, because they are scoped to a `.woocommerce-js` body class that JavaScript adds. */
.wh-cat .wh-cat__grid.products li.product img.show-on-hover {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	width: 0;
	height: 0;
	padding: 0;
	margin: 0;
	opacity: 0;
	object-fit: cover;
	transition: all 0.2s linear;
}

.wh-cat .wh-cat__grid.products li.product:hover img.show-on-hover,
.wh-cat .wh-cat__grid.products li.product:focus-within img.show-on-hover {
	width: 100%;
	height: 100%;
	opacity: 1;
}

/* Wiser's star row. It sits INSIDE the thumbnail link on this site — image, then stars, then
   title, then price — which is not where James Butler or Empire put it, and it is 26px of every
   desktop card's height. The plugin owns the markup; only the box is ours. */
.wh-cat .wiser_review {
	display: block;
	margin: 0;
	padding: 0;
	text-align: left;
	color: var(--wh-primary);
}

/* Astra's out-of-stock band — PLAN.md decision D7, reproduced rather than dropped.
   `bottom: 1em` against a 16px font is the 16px live measures; the padding is Astra's own
   `.5em 0 .7em`. This is the WHITE band across the foot of the image; the black pill top-right is
   a different plugin's and carries its own inline styles. */
.wh-cat .wh-cat__grid.products li.product .ast-shop-product-out-of-stock {
	position: absolute;
	left: 1em;
	right: 1em;
	bottom: 1em;
	margin: 0;
	padding: 0.5em 0 0.7em;
	font-family: var(--wh-ff-body);
	/* No font-size. Astra's rule sets none either, so the band inherits the card's — 16px on
	   desktop, 14.592px once Astra scales the root on phones — and because the offsets and the
	   padding are in em they follow it. Hard-coding 16px put the band 1px out and made it 4px
	   taller than live's at 360. */
	font-weight: 700;
	line-height: 1.65;
	text-align: center;
	text-transform: uppercase;
	color: var(--wh-primary);
	background-color: rgba(255, 255, 255, 0.88);
	transition: background 0.3s;
}

.wh-cat .wh-cat__grid.products li.product a:hover .ast-shop-product-out-of-stock {
	background-color: var(--wh-white);
}

/* The labels plugin only un-hides its badge from a `.products` scope, which is why the grid keeps
   the `products` class. Restated here so the badge does not depend on Jet's stylesheet being
   enqueued — on the rebuilt archive it is not, because no Jet widget renders. */
.wh-cat .products .acoplw-badge,
.wh-cat .products .acoplw-badge-icon {
	visibility: visible;
}

/* The sale flash. Two products in Premium Watch Boxes are on sale and neither is on page one, so
   the baseline capture shows none — which is exactly how a missing rule would go unnoticed until
   a sale ran. Values from 14379's own CSS for the widget. */
.wh-cat .wh-cat__grid.products li.product span.onsale {
	display: block;
	position: absolute;
	top: 0;
	left: 0;
	z-index: 9;
	min-width: 62px;
	min-height: 22px;
	padding: 0 10px;
	line-height: 22px;
	text-align: center;
	color: #edf2f7;
	background-color: var(--wh-ink);
	border-radius: 0;
}

.wh-cat .astra-shop-summary-wrap {
	display: block;
	margin: 0;
	padding: 0;
	text-align: left;
}

.wh-cat .ast-loop-product__link {
	color: var(--wh-primary);
	text-decoration: none;
}

.wh-cat .wh-cat__grid.products li.product .woocommerce-loop-product__title {
	margin: 0 0 8px;
	padding: 0;
	font-family: var(--wh-ff-questrial);
	font-size: 16px;
	font-weight: 400;
	line-height: 1.5em;
	letter-spacing: 0;
	text-transform: none;
	color: var(--wh-primary);
}

/* Price stays WooCommerce's markup; this is the kit's "text" typography, which is what the widget
   points its price at. */
.wh-cat .wh-cat__grid.products li.product .price {
	display: block;
	margin: 0 0 7px;
	padding: 0;
	font-family: var(--wh-ff-questrial);
	font-size: 14px;
	font-weight: 400;
	line-height: 1.3em;
	color: var(--wh-primary);
}

.wh-cat .wh-cat__grid.products li.product .price del {
	font-size: 14px;
	text-decoration: line-through;
	opacity: 0.6;
}

.wh-cat .wh-cat__grid.products li.product .price ins {
	text-decoration: none;
}

.wh-cat__empty {
	font-family: var(--wh-ff-questrial);
	font-size: 14px;
	line-height: var(--wh-lh);
	color: var(--wh-primary);
}

/* ---------------------------------------------------------------------------
   8. Load More, and the pagination live does not have.

   The button is live's, to the pixel: 10px 20px of padding, an 82px radius, black on white text,
   centred in a flex row with a -3px/3px margin pair. What changes is underneath — it is an <a> to
   the next page rather than a div that waits for JavaScript. The numbered pager below it is the
   visible fallback, and it is the whole point of decision D5: with scripts off, live has no route
   past product 40 and this always does.
   --------------------------------------------------------------------------- */

.wh-more {
	display: flex;
	justify-content: center;
	margin: -3px;
}

.wh-more__link {
	display: inline-block;
	margin: 3px;
	padding: 10px 20px;
	font-family: var(--wh-ff-body);
	font-size: 16px;
	font-weight: 400;
	line-height: var(--wh-lh);
	color: var(--wh-white);
	background-color: var(--wh-ink);
	border-radius: 82px;
	text-decoration: none;
}

.wh-more__link:hover,
.wh-more__link:focus {
	color: var(--wh-white);
	background-color: var(--wh-primary);
}

/* The numbered pager borrows the colours 14379 assigns WooCommerce's own (hidden) pagination:
   primary border and link colour, white on the current page, #0E0F1133 on hover. */
.wh-pager {
	display: flex;
	justify-content: center;
}

.wh-pager__list {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.wh-pager__list li {
	margin: 0;
	list-style: none;
}

.wh-pager__list .page-numbers {
	display: inline-block;
	min-width: 36px;
	padding: 6px 10px;
	font-family: var(--wh-ff-body);
	font-size: 14px;
	line-height: 22px;
	text-align: center;
	text-decoration: none;
	color: var(--wh-primary);
	border: 1px solid var(--wh-primary);
	border-radius: 3px;
}

.wh-pager__list a.page-numbers:hover,
.wh-pager__list a.page-numbers:focus {
	background-color: var(--wh-hover-tint);
}

.wh-pager__list .page-numbers.current {
	color: var(--wh-white);
	background-color: var(--wh-primary);
}

.wh-pager__list .page-numbers.dots {
	border-color: transparent;
}

/* ---------------------------------------------------------------------------
   9. The mobile filter drawer.

   Live is an Elementor button (13608ca8) opening popup 16857. This is a <details> holding the
   same three groups, so it opens with no script and there is no popup document to load. The pill
   is matched exactly: 320x41 at 360, #0a1c2e on a 1px white border, 50px radius, 15px Roboto,
   centred; the container around it is 81px tall on live and that is reproduced with padding.
   --------------------------------------------------------------------------- */

.wh-drawer__toggle {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	width: 100%;
	padding: 12px 24px;
	font-family: var(--wh-ff-roboto);
	font-size: 15px;
	font-weight: 400;
	line-height: 15px;
	text-align: center;
	color: var(--wh-white);
	background-color: var(--wh-primary);
	border: 1px solid var(--wh-white);
	border-radius: 50px;
	cursor: pointer;
	list-style: none;
}

.wh-drawer__toggle::-webkit-details-marker {
	display: none;
}

.wh-drawer__toggle::marker {
	content: "";
}

.wh-drawer__badge {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 18px;
	height: 18px;
	padding: 0 5px;
	font-size: 11px;
	line-height: 18px;
	color: var(--wh-primary);
	background-color: var(--wh-white);
	border-radius: 20px;
}

.wh-drawer__scrim {
	display: none;
}

.wh-drawer[open] .wh-drawer__scrim {
	display: block;
	position: fixed;
	inset: 0;
	z-index: 998;
	background-color: rgba(0, 0, 0, 0.45);
}

.wh-drawer__panel {
	display: none;
}

.wh-drawer[open] .wh-drawer__panel {
	display: block;
	position: fixed;
	top: 0;
	left: 0;
	bottom: 0;
	z-index: 999;
	width: min(88vw, 340px);
	padding: 20px;
	overflow-y: auto;
	background-color: var(--wh-white);
	box-shadow: 0 0 24px rgba(0, 0, 0, 0.18);
}

.wh-drawer__heading {
	font-family: var(--wh-ff-roboto);
	font-size: 17px;
	font-weight: 600;
	color: var(--wh-primary);
}

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

   Three columns; the sort control disappears entirely (live hides its whole column); the hero
   drops to 126px and the title to 18px; card titles drop to 14px.
   --------------------------------------------------------------------------- */

@media (max-width: 1024px) {
	.wh-cat__hero {
		min-height: 126px;
	}

	.wh-cat__title {
		font-size: 18px;
		letter-spacing: 10px;
	}

	.wh-cat__sortcol {
		display: none;
	}

	.wh-cat__desccol {
		width: 100%;
	}

	.wh-cat .wh-cat__main ul.wh-cat__grid.products {
		grid-template-columns: repeat(3, minmax(0, 1fr));
		gap: 40px 20px;
	}

	.wh-cat .wh-cat__grid.products li.product .woocommerce-loop-product__title {
		font-size: 14px;
		margin: 0 0 7px;
	}

	.wh-cat .wh-cat__grid.products li.product .price del {
		font-size: 14px;
	}
}

/* ---------------------------------------------------------------------------
   Mobile — (max-width: 767px).

   Two columns; the sidebar goes and the Filter By pill arrives; the hero drops to 103px and the
   title to 11px with 8px of letter-spacing; the description centres. Astra scales the root font
   size on phones, which is why the inherited line-height lands at 24.08px rather than 26.4px —
   measured on the live page, not calculated.
   --------------------------------------------------------------------------- */

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

	.wh-cat__hero {
		min-height: 103px;
	}

	.wh-cat__title {
		font-size: 11px;
		letter-spacing: 8px;
	}

	/* Live's mobile description sits at x=20 in a 360px viewport — the 20px is the column's own
	   padding, and the section adds none. */
	.wh-cat__intro {
		padding: 0;
	}

	.wh-cat__desccol {
		width: 100%;
		padding: 20px;
	}

	.wh-cat__desc {
		text-align: center;
	}

	/* The row keeps its 20px gap: live's mobile bar is a wrapped flex item in the same row as the
	   product column, so the gap sits between them and the grid starts 20px lower than it would
	   otherwise. Setting gap:0 here put every card 20px high against live at both 767 and 360. */
	.wh-cat__inner {
		flex-wrap: wrap;
	}

	.wh-cat__mobilebar {
		display: block;
		width: 100%;
		padding: 10px 10px 30px;
	}

	.wh-cat__side {
		display: none;
	}

	.wh-cat__main {
		width: 100%;
	}

	.wh-cat .wh-cat__main ul.wh-cat__grid.products {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 20px 10px;
	}

	.wh-more__link {
		font-size: 14.592px;
		line-height: 24.08px;
	}
}

/* Screen-reader-only text, in case Astra's own utility class is not in the cascade on this
   route. Same rule Astra and WordPress both use. */
.wh-cat .screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}
