/**
 * HAViK components — CSS versions for markup outside Elementor
 * (block content, the knife wizard, HTML widgets, custom templates).
 *
 * The same pieces exist as Elementor Components (HAViK Badge Card,
 * HAViK Testimonial, HAViK Text Link) and Elementor global classes
 * (hv-badge-grid, hv-topo). Keep both in step: they're built from the
 * same Figma nodes and the same tokens. See the README for markup.
 *
 * Every value comes from a --hv-* token, except where noted:
 * - 1px / 2px stroke widths (no stroke scale; same as .hv-border-*)
 * - unitless line heights and font weights (as in tokens.css)
 * - the topo image's own geometry (agreed to hardcode; see .hv-topo)
 *
 * Utilities are prefixed with :root to lift specificity above the
 * Elementor kit's element defaults without !important (see tokens.css).
 * Layout changes happen at 767px, matching Elementor's mobile breakpoint.
 */

/* ==========================================================================
   Badge card + grid
   Figma: desktop "why havik" 7:618, mobile 14:1261.
   Markup:
     <div class="hv-badge-grid">
       <div class="hv-badge">
         <span class="hv-badge__icon"><svg aria-hidden="true">…</svg></span>
         <p class="hv-badge__label">Lifetime warranty</p>
       </div>
       …
     </div>
   The icon is decorative (the label says the same thing): mark it
   aria-hidden, or use an <img alt="">. Icons should use currentColor.
   ========================================================================== */

:root .hv-badge-grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--hv-space-32);
}

:root .hv-badge {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: var(--hv-space-12);
	padding: var(--hv-space-64) var(--hv-space-24);
	border: 1px solid var(--hv-color-border);
	text-align: center;
	color: var(--hv-color-text-strong);
}

:root .hv-badge__icon {
	display: block;
	flex-shrink: 0;
	width: var(--hv-space-96);
	height: var(--hv-space-96);
	color: var(--hv-color-green);
}

:root .hv-badge__icon svg,
:root .hv-badge__icon img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
}

:root .hv-badge__label {
	margin: 0;
	font-family: var(--hv-font-body);
	font-size: var(--hv-size-label);
	font-weight: 700;
	line-height: 1.4375rem;
	letter-spacing: 0;
	text-transform: none;
	color: var(--hv-color-text-strong);
}

@media (max-width: 767px) {
	:root .hv-badge-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--hv-space-20);
	}

	:root .hv-badge {
		padding: var(--hv-space-32) var(--hv-space-20);
	}

	:root .hv-badge__icon {
		width: var(--hv-space-32);
		height: var(--hv-space-32);
	}
}

/* ==========================================================================
   Testimonial
   Figma: desktop "quote" 14:825, mobile 14:933. No photo on mobile.
   Markup (figure/blockquote/figcaption give it proper semantics):
     <figure class="hv-testimonial">
       <img class="hv-testimonial__photo" src="…" alt="…">
       <div class="hv-testimonial__content">
         <h3 class="hv-testimonial__heading">flawless</h3>
         <blockquote class="hv-testimonial__quote"><p>Five months in…</p></blockquote>
         <figcaption class="hv-testimonial__attribution">
           <span>Parker W</span> <span aria-hidden="true">|</span>
           <a class="hv-testimonial__handle" href="…">@perseverancewins87</a>
         </figcaption>
       </div>
     </figure>
   Use whichever heading level fits the page; the look comes from the class.
   The quote mark is drawn by CSS (decorative, no markup needed).
   ========================================================================== */

:root .hv-testimonial {
	display: flex;
	flex-direction: row;
	align-items: center;
	gap: var(--hv-space-40);
	margin: 0;
}

:root .hv-testimonial__photo {
	display: block;
	flex-shrink: 0;
	width: var(--hv-space-240);
	height: auto;
	aspect-ratio: 5 / 6;
	object-fit: cover;
}

:root .hv-testimonial__content {
	position: relative;
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--hv-space-20);
	min-width: 0;
}

/* Decorative quote mark behind the heading. assets/icons/quote.svg is a
   100×100 square with space around the mark. */
:root .hv-testimonial__content::before {
	content: "";
	position: absolute;
	top: calc(var(--hv-space-64) * -1);
	right: 0;
	width: var(--hv-space-240);
	aspect-ratio: 1 / 1;
	background-color: var(--hv-color-green-dark);
	opacity: var(--hv-opacity-70);
	-webkit-mask: url(../icons/quote.svg) no-repeat center / contain;
	mask: url(../icons/quote.svg) no-repeat center / contain;
	pointer-events: none;
}

:root .hv-testimonial__heading {
	position: relative;
	margin: 0;
	font-family: var(--hv-font-display);
	font-size: var(--hv-size-h3);
	font-weight: 400;
	line-height: 1;
	letter-spacing: 0;
	text-transform: none;
	color: var(--hv-color-text-strong);
}

:root .hv-testimonial__quote,
:root .hv-testimonial__quote p {
	position: relative;
	margin: 0;
	padding: 0;
	border: 0;
	font-family: var(--hv-font-body);
	font-size: var(--hv-size-body);
	font-weight: 400;
	font-style: normal;
	line-height: 1.5;
	letter-spacing: 0;
	color: var(--hv-color-text-strong);
}

/* The 2px line is as long as the attribution below it. */
:root .hv-testimonial__attribution {
	position: relative;
	display: flex;
	align-items: center;
	gap: var(--hv-space-8);
	padding-top: var(--hv-space-8);
	border-top: 2px solid var(--hv-color-green);
	font-family: var(--hv-font-body);
	font-size: var(--hv-size-body);
	font-weight: 400;
	line-height: 1.5;
	color: var(--hv-color-text-strong);
}

/* Underlined at every size; the block padding makes a 48px tap target. */
:root .hv-testimonial__handle {
	padding-block: var(--hv-space-12);
	font-weight: 400;
	color: var(--hv-color-text-strong);
	text-decoration: underline;
}

@media (max-width: 767px) {
	:root .hv-testimonial {
		flex-direction: column;
		align-items: stretch;
	}

	/* Phones: the photo moves below the quote, centred, as a break before
	   the next section (288px wide, 5:6 as on desktop). */
	:root .hv-testimonial__photo {
		order: 2;
		align-self: center;
		width: calc(var(--hv-space-240) + var(--hv-space-48));
		max-width: 100%;
	}

	:root .hv-testimonial__content::before {
		top: 0;
		width: var(--hv-space-96);
	}
}

/* ==========================================================================
   Topo background wrapper
   Figma: "topop background container" 30:2138. Put the class on the ONE
   parent that wraps all the sections the lines run behind, not on each
   section.

   assets/img/topo.webp is Figma's render of the lines, with the 11.4°
   rotation and 40% opacity baked in (WebP, 147KB; topo.png, the 347KB
   original, stays for the hv-topo class saved in Elementor until the
   components script next runs with `update classes`). Its geometry is hardcoded here by
   agreement; it's the image's own size, not a design token:
   - 631px   the image width, fixed so the lines never stretch
   - 284.5px half of (1200px Figma content column − 631px image)
   - 360px   how far the image's left edge sits left of the content
             column (Figma, 1920 frame), so it stays put at any width
   At 768–1024 it moves a further --hv-space-160 off-canvas, where the
   text column moves into the lines. Hidden below 767.
   The image's left edge is a hard cut, so it never comes in past the
   page's left edge: wider than 1920 (where the formula would bring it on
   screen) it stays pinned at 0 (min(…, 0px)).
   ========================================================================== */

:root .hv-topo {
	background-image: url(../img/topo.webp);
	background-repeat: no-repeat;
	background-size: 631px auto;
	background-position: min(calc(max(50% - 284.5px, 0px) - 360px), 0px) center;
}

@media (max-width: 1024px) {
	:root .hv-topo {
		background-position: calc(max(50% - 284.5px, 0px) - 360px - var(--hv-space-160)) center;
	}
}

@media (max-width: 767px) {
	:root .hv-topo {
		background-image: none;
	}
}

/* With .hv-parallax (motion.css) and the effect running, the lines move from
   the wrapper's background onto its drifting ::after layer, at the same
   geometry. Where the effect is off (reduced motion, below 768px, no
   browser support) these rules don't apply and the background stays put. */
@media (min-width: 768px) and (prefers-reduced-motion: no-preference) {
	@supports (animation-timeline: view()) {
		:root .hv-topo.hv-parallax {
			background-image: none;
		}

		:root .hv-topo.hv-parallax::after {
			background-image: url(../img/topo.webp);
			background-repeat: no-repeat;
			background-size: 631px auto;
			background-position: min(calc(max(50% - 284.5px, 0px) - 360px), 0px) center;
		}
	}
}

@media (min-width: 768px) and (max-width: 1024px) and (prefers-reduced-motion: no-preference) {
	@supports (animation-timeline: view()) {
		:root .hv-topo.hv-parallax::after {
			background-position: calc(max(50% - 284.5px, 0px) - 360px - var(--hv-space-160)) center;
		}
	}
}


/* ==========================================================================
   Homepage hero headline
   "BUILT FOR THE WILD" is display text (a <p>, not a heading; the page's
   h1 is the eyebrow above it). On phones "FOR THE" drops to its own line
   at 57px between 80px "BUILT" and "WILD", as in the Figma mobile frame.
   57px isn't on the type scale; 0.7125em is 57/80 of the h1 size (flagged),
   so it scales with the fluid h1. The span is set in the page content
   (create-elementor-home.php); #hv-hero-title is the paragraph's CSS id.

   Both line counts are fixed rather than left to wrapping, so the headline
   is the same height before and after the display font loads. On phones the
   span is a block, which gives three lines on its own; the <br> inside it is
   only there to break the desktop line after "FOR", so it's off here. Left
   to wrap, the desktop headline changed by a whole h1 line (80-128px) when
   the font swapped — that was the page's entire layout shift.
   ========================================================================== */

@media (max-width: 767px) {
	#hv-hero-title span {
		display: block;
		font-size: 0.7125em;
	}

	#hv-hero-title span br {
		display: none;
	}
}


/* ==========================================================================
   Knife cycler
   The "your knife, your way" photo: [data-hv-cycler] (behavior in
   assets/js/motion.js). The first photo is in the markup and renders
   without JavaScript; the others are added by the script as needed and
   stacked on it, so the space never changes (fixed 1640:762 ratio, the
   photos' own size) and changing photo is opacity only.

   The fade has no dip: the new photo fades in on top (400ms) while the
   old one stays fully visible underneath (.is-previous), and the old one
   is hidden only once the new one is opaque. Fading both at once would
   leave both half-transparent midway, and the knife would go dark and
   ghosted.

   The photos have their black background baked in. The stage's edges fade
   into the page (mask) so the topo lines behind the section aren't cut by
   a hard rectangle: 6% at the sides, 15% top and bottom (the knife sits
   well inside both; flagged geometry, like the other photo placements).

   Indicators: short bars, current in accent, the rest in texture grey.
   Each is a 44px-tall button (tap target); the bar is 24×4 (4px is off the
   spacing scale, flagged; a stroke weight like the 1px/2px ones above).
   ========================================================================== */

:root [data-hv-cycler] {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--hv-space-8);
	width: 100%;
}

:root [data-hv-cycler-stage] {
	position: relative;
	width: 100%;
	aspect-ratio: 1640 / 762;
	touch-action: pan-y;
	-webkit-mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent), linear-gradient(to bottom, transparent, #000 15%, #000 85%, transparent);
	mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent), linear-gradient(to bottom, transparent, #000 15%, #000 85%, transparent);
	-webkit-mask-composite: source-in;
	mask-composite: intersect;
}

:root [data-hv-cycler-stage] > img {
	position: absolute;
	inset: 0;
	width: 100%;
	max-width: none;
	height: 100%;
	margin: 0;
	object-fit: cover;
	-webkit-user-drag: none;
	user-select: none;
}

:root [data-hv-cycler].is-enhanced [data-hv-cycler-stage] > img {
	z-index: 0;
	opacity: 0;
}

:root [data-hv-cycler].is-enhanced [data-hv-cycler-stage] > img.is-previous {
	z-index: 1;
	opacity: 1;
}

:root [data-hv-cycler].is-enhanced [data-hv-cycler-stage] > img.is-current {
	z-index: 2;
	opacity: 1;
	transition: opacity 400ms ease;
}

/* Decorative images laid over interactive things (the splatters and the
   "Stay Sharp" lettering over the cycler) let taps and swipes through. */
:root [data-hv-decoration] {
	pointer-events: none;
}

:root .hv-cycler__controls {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
}

:root .hv-cycler__indicator {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: none;
	cursor: pointer;
}

:root .hv-cycler__indicator:hover,
:root .hv-cycler__indicator:focus {
	background: none;
}

:root .hv-cycler__indicator::before {
	content: "";
	width: var(--hv-space-24);
	height: 4px;
	background-color: var(--hv-color-texture);
	transition: background-color 150ms ease-out;
}

:root .hv-cycler__indicator:hover::before {
	background-color: var(--hv-color-text-strong);
}

:root .hv-cycler__indicator[aria-current="true"]::before {
	background-color: var(--hv-color-accent);
}

:root .hv-cycler__indicator:focus-visible {
	outline: 2px solid var(--hv-color-accent);
	outline-offset: -2px;
	box-shadow: none;
}

@media (prefers-reduced-motion: reduce) {
	:root [data-hv-cycler].is-enhanced [data-hv-cycler-stage] > img.is-current,
	:root .hv-cycler__indicator::before {
		transition: none;
	}
}



/* ==========================================================================
   Filter bar (assets/js/filter.js)
   [data-hv-filter-bar] gets a row of filter buttons made by the script: a
   small label, then outlined buttons; the chosen one is in accent. Each
   button is at least 44px tall to tap. Items the filter hides get the
   hidden attribute, which has to beat the containers' own display.
   ========================================================================== */

:root .hv-filter {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--hv-space-12);
	padding-bottom: var(--hv-space-12);
	border-bottom: 1px solid var(--hv-color-line);
}

:root .hv-filter__label {
	margin-inline-end: var(--hv-space-8);
	color: var(--hv-color-muted);
	font-family: var(--hv-font-body);
	font-size: var(--hv-size-body-sm);
	font-weight: 800;
	letter-spacing: 0.16em;
	text-transform: uppercase;
}

:root .hv-filter__button {
	min-height: 44px;
	margin: 0;
	padding: var(--hv-space-8) var(--hv-space-16);
	border: 1px solid var(--hv-color-line);
	border-radius: 0;
	background: none;
	color: var(--hv-color-text-dim);
	font-family: var(--hv-font-body);
	font-size: var(--hv-size-body-sm);
	font-weight: 800;
	line-height: 1.4;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	cursor: pointer;
	transition: border-color 150ms ease-out, color 150ms ease-out;
}

:root .hv-filter__button:hover,
:root .hv-filter__button:focus {
	border-color: var(--hv-color-muted);
	background: none;
	color: var(--hv-color-text-strong);
}

:root .hv-filter__button[aria-pressed="true"] {
	border-color: var(--hv-color-accent);
	color: var(--hv-color-accent);
}

:root .hv-filter__button:focus-visible {
	outline: 2px solid var(--hv-color-accent);
	outline-offset: 2px;
}

:root [data-hv-filter-tags][hidden] {
	display: none !important;
}

/* Phones: one row that scrolls sideways, no "Shopping for" label (the
   button group keeps its accessible name), and shorter buttons: the 44px
   minimum counts the padding and border here (44px in all, down from 62px),
   like the shop's filter. A little space at the top so a focused button's
   outline isn't cut off by the scrolling row. */
@media (max-width: 767px) {
	:root .hv-filter {
		flex-wrap: nowrap;
		overflow-x: auto;
		padding-block-start: var(--hv-space-4);
	}

	:root .hv-filter__label {
		display: none;
	}

	:root .hv-filter__button {
		flex-shrink: 0;
		box-sizing: border-box;
		white-space: nowrap;
	}
}

/* The shop's category filter (Elementor Pro Taxonomy Filter, class
   hv-shop-filter on the widget) looks like the filter bar above: outlined
   buttons in a row with a rule under them, the chosen one in accent. Its
   own style settings are left empty in the shop template so these apply. */
:root .hv-shop-filter .e-filter {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--hv-space-12);
	padding-bottom: var(--hv-space-12);
	border-bottom: 1px solid var(--hv-color-line);
}

:root .hv-shop-filter .e-filter-item {
	min-height: 44px;
	margin: 0;
	padding: var(--hv-space-8) var(--hv-space-16);
	border: 1px solid var(--hv-color-line);
	border-radius: 0;
	background: none;
	color: var(--hv-color-text-dim);
	font-family: var(--hv-font-body);
	font-size: var(--hv-size-body-sm);
	font-weight: 800;
	line-height: 1.4;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	white-space: nowrap;
	cursor: pointer;
	transition: border-color 150ms ease-out, color 150ms ease-out;
}

:root .hv-shop-filter .e-filter-item:hover,
:root .hv-shop-filter .e-filter-item:focus {
	border-color: var(--hv-color-muted);
	background: none;
	color: var(--hv-color-text-strong);
}

:root .hv-shop-filter .e-filter-item[aria-pressed="true"] {
	border-color: var(--hv-color-accent);
	background: none;
	color: var(--hv-color-accent);
}

:root .hv-shop-filter .e-filter-item:focus-visible {
	outline: 2px solid var(--hv-color-accent);
	outline-offset: 2px;
}

/* Phones: one scrolling row (the widget's own horizontal scroll), and
   shorter buttons: the 44px minimum counts the padding and border here
   (44px in all, down from 62px), still a comfortable tap. */
@media (max-width: 767px) {
	:root .hv-shop-filter .e-filter {
		flex-wrap: nowrap;
		overflow-x: auto;
	}

	:root .hv-shop-filter .e-filter-item {
		box-sizing: border-box;
	}
}


/* ==========================================================================
   Gift guide product cards (create-elementor-gift-guide.php)
   The card, its parts and their spacing are the hv-gg-card* global classes
   in Elementor. Only the list bullets live here: atomic elements can't
   output <ul>/<li>, so a card's list is a role="list" container of
   role="listitem" paragraphs, and the bullet is drawn here.
   ========================================================================== */

:root .hv-gg-card-item {
	position: relative;
	padding-inline-start: var(--hv-space-20);
}

:root .hv-gg-card-item::before {
	content: "";
	position: absolute;
	inset-inline-start: var(--hv-space-8);
	top: 0.7em;
	width: 4px;
	height: 4px;
	border-radius: 50%;
	background-color: currentColor;
}


/* The shop FAQs (atomic accordion, class hv-faq): the plus turns into an x
   when a question is open. Elementor's own rule turns the icon 180deg, which
   a plus doesn't show. */
:root .hv-faq .e-accordion-item-base[open] > summary .e-accordion-item-icon-base svg {
	transform: rotate(45deg);
}

/* ==========================================================================
   Shop product cards (the "Product Main Loop" loop item, in the atomic shop
   template's Loop Grid, class hv-shop-grid)
   Restyled on the tokens: a 1px line border, the square photo edge to edge,
   the text and buttons with space-20 at the sides and bottom, the name in
   the body font. Each row's cards are the same height (as tall as the
   tallest in that row); the name grows so the price and button line up at
   the bottom. The loop
   item and the post_class PHP that shows and hides its parts (limited,
   has-wizard-content, havik-soon, havik-simple-btns, havik-variable-btn,
   stock-message) are untouched: nothing here sets display on those, except
   the one rule below that removes the BUILD MY KNIFE button.
   Scoped to hv-shop-grid, so the previous shop template looks as it did.
   ========================================================================== */

/* No BUILD MY KNIFE button on product cards, wherever the loop item is used
   (the shop and the single product template's related products). Wizard
   products keep their VIEW OPTIONS button. Only the button widget: the
   "custom configurations" bar has the same has-wizard-content class and still
   shows. Beats havik-core.css's .has-wizard .has-wizard-content. The button
   is still in the loop item (#618); delete it there if it should go for good. */
:root .e-loop-item .elementor-widget-button.has-wizard-content {
	display: none;
}

/* A card can't be wider than its column, even while a photo is loading or
   missing (a broken image otherwise keeps its 768px width and stretches the
   grid). */
:root .hv-shop-grid .e-loop-item {
	min-width: 0;
}

/* Rows fit their own tallest card. The grid's Equal height setting makes
   every row as tall as the tallest card on the page (grid-auto-rows: 1fr);
   the cards in a row still stretch to match each other. Specific enough to
   beat the template's own rule for that setting. */
:root .hv-shop-grid.elementor-widget-loop-grid .elementor-loop-container.elementor-grid {
	grid-auto-rows: auto;
}

/* No padding on the card itself, so the photo and the bars reach its edges;
   the rest get their own (below). */
:root .hv-shop-grid .e-loop-item > .e-con {
	height: 100%;
	padding: 0 0 var(--hv-space-20);
	border: 1px solid var(--hv-color-line);
	gap: var(--hv-space-12);
}

/* The text and buttons: space-20 at the sides. Everything but the photo and
   the bars (custom configurations, RARE BREED, COMING SOON, the HHF line). */
:root .hv-shop-grid .e-loop-item > .e-con > :not(.havik-zoom-img, .e-con:is(.has-wizard-content, .limited, .havik-soon, .havik-hhf-content)) {
	padding-inline: var(--hv-space-20);
}

/* The name takes the spare height, so the price and button sit at the same
   place in every card of a row. Only the name: the loop item's own grow and
   negative bottom margins on the name and price are cleared, so the card's
   gap spaces everything evenly. One column, never wrapped. */
:root .hv-shop-grid .e-loop-item > .e-con {
	flex-wrap: nowrap;
}

:root .hv-shop-grid .e-loop-item .elementor-widget-woocommerce-product-title.elementor-element {
	--flex-grow: 1;
	flex-grow: 1;
	margin-block-end: 0;
}

:root .hv-shop-grid .e-loop-item .elementor-widget-woocommerce-product-price.elementor-element {
	--flex-grow: 0;
	flex-grow: 0;
	margin-block-end: 0;
}

:root .hv-shop-grid .havik-zoom-img a {
	display: block;
	width: 100%;
	max-width: 100%;
}

/* The photo runs the full width of the card, from its top edge (the card
   has no padding there). The bars stay on top of it (absolute, from the
   loop item) except on phones, below. */
:root .hv-shop-grid .havik-zoom-img {
	display: block;
	width: 100%;
	max-width: 100%;
	margin: 0;
}

:root .hv-shop-grid .havik-zoom-img img {
	display: block;
	width: 100%;
	max-width: 100%;
	height: auto;
	aspect-ratio: 1 / 1;
	object-fit: cover;
}

/* The "24 custom configurations" and "RARE BREED" bars. */
:root .hv-shop-grid :is(.has-wizard-content, .limited) .elementor-heading-title {
	padding: var(--hv-space-8) var(--hv-space-12);
	background-color: var(--hv-color-surface-raised);
	color: var(--hv-color-text-strong);
	font-family: var(--hv-font-body);
	font-size: var(--hv-size-body-sm);
	font-weight: 800;
	line-height: 1;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

/* Phones: the bars (custom configurations, RARE BREED, COMING SOON, the HHF
   line) sit above the photo instead of covering it. They're absolute in the
   loop item; here they join the flow, first in the card, full width like
   the photo, with the photo right below (the negative margin cancels the
   card's gap). */
@media (max-width: 767px) {
	:root .hv-shop-grid .e-loop-item > .e-con > .e-con:is(.has-wizard-content, .limited, .havik-soon, .havik-hhf-content) {
		position: static;
		order: -1;
		width: 100%;
		max-width: 100%;
		margin: 0 0 calc(-1 * var(--hv-space-12));
	}

	:root .hv-shop-grid .e-loop-item > .e-con > .e-con:is(.has-wizard-content, .limited, .havik-soon, .havik-hhf-content) .elementor-heading-title {
		text-align: center;
	}
}

/* The product page's related products (grid on desktop, class
   havik-related-loop): havik-core.css makes the row a centered flex row, so
   each card sized to its own photo. Each card gets a quarter of the row
   (the grid's 30px gaps taken out), still centered when there are fewer. */
:root .havik-related-loop.hv-shop-grid .elementor-loop-container > .e-loop-item {
	flex: 0 1 calc((100% - 3 * 30px) / 4);
	width: calc((100% - 3 * 30px) / 4);
}

/* The name. Specific enough to beat a font set on the title widget in the
   loop item itself, so the cards look the same on every environment. */
:root .hv-shop-grid .e-loop-item .elementor-widget-woocommerce-product-title .elementor-heading-title.product_title,
:root .hv-shop-grid .e-loop-item .elementor-widget-woocommerce-product-title .elementor-heading-title.product_title a {
	color: var(--hv-color-text-strong);
	font-family: var(--hv-font-body);
	font-size: var(--hv-size-h5);
	font-weight: 700;
	line-height: 1.2;
	letter-spacing: 0;
	text-transform: none;
}

:root .hv-shop-grid .elementor-widget-woocommerce-product-price .price {
	margin: 0;
	color: var(--hv-color-text);
	font-family: var(--hv-font-body);
	font-size: var(--hv-size-body);
	font-weight: 500;
	line-height: 1.4;
}

:root .hv-shop-grid .havik-soon .elementor-heading-title,
:root .hv-shop-grid .stock-message .elementor-heading-title {
	color: var(--hv-color-texture);
	font-family: var(--hv-font-accent);
	font-size: var(--hv-size-cta);
	font-weight: 700;
	line-height: 1;
}

/* The shop's review (the Testimonial component, section id shop-review):
   no photo on phones, on this page only. It would sit right after the custom
   orders photo, two photos in a row. */
@media (max-width: 767px) {
	:root #shop-review .e-image-base {
		display: none;
	}
}

/* The shop hero on phones: the text sits on the photo, so a black layer
   (an inset shadow paints over the background, under the text) keeps it
   readable. Desktop has the text beside the photo and needs none. */
@media (max-width: 767px) {
	:root #shop-hero {
		box-shadow: inset 0 0 0 100vmax rgb(0 0 0 / 0.5);
	}
}

/* ==========================================================================
   Podcast episode cards (the "Podcast Loop Item" loop item, in the atomic
   podcast template's Loop Grid, class hv-podcast-grid)
   Like the shop's cards: a 1px line border, the square photo edge to edge,
   the text and button with space-20 at the sides and bottom, the title in
   the display font. The loop item itself is untouched.
   ========================================================================== */

:root .hv-podcast-grid .e-loop-item {
	min-width: 0;
}

:root .hv-podcast-grid .e-loop-item > .e-con {
	height: 100%;
	padding: 0 0 var(--hv-space-20);
	border: 1px solid var(--hv-color-line);
	gap: var(--hv-space-12);
}

/* The title and button: space-20 at the sides. Not the photo or the
   LIMITED EDITION bar, which reach the card's edges. (No padding on the
   card itself: Elementor 4.3.2+ caps a widget at the card's content width,
   so the photo can't stretch past card padding.) */
:root .hv-podcast-grid .e-loop-item > .e-con > :not(.havik-zoom-img, .e-con.limited) {
	padding-inline: var(--hv-space-20);
}

:root .hv-podcast-grid .havik-zoom-img {
	display: block;
	width: 100%;
	max-width: 100%;
	margin: 0;
}

:root .hv-podcast-grid .havik-zoom-img a {
	display: block;
	width: 100%;
	max-width: 100%;
}

:root .hv-podcast-grid .havik-zoom-img img {
	display: block;
	width: 100%;
	max-width: 100%;
	height: auto;
	aspect-ratio: 1 / 1;
	object-fit: cover;
}

:root .hv-podcast-grid .elementor-widget-theme-post-title .elementor-heading-title,
:root .hv-podcast-grid .elementor-widget-theme-post-title .elementor-heading-title a {
	color: var(--hv-color-text-strong);
	font-family: var(--hv-font-display);
	font-size: var(--hv-size-h5);
	font-weight: 400;
	line-height: 1.1;
	letter-spacing: 0;
	text-transform: none;
}

/* The podcast hero on phones: the text sits on the photo, so a black layer
   (an inset shadow paints over the background, under the text) keeps it
   readable, like the shop hero. */
@media (max-width: 767px) {
	:root #podcast-hero {
		box-shadow: inset 0 0 0 100vmax rgb(0 0 0 / 0.5);
	}
}

/* The HAViK Social component's @spreadhavik link: accent, no underline;
   underlined on hover and keyboard focus. */
:root .hv-social-body a {
	color: var(--hv-color-accent);
	text-decoration: none;
}

:root .hv-social-body a:is(:hover, :focus-visible) {
	text-decoration: underline;
	text-underline-offset: 0.15em;
}

/* Social links (the HAViK Social component, class hv-social-link): accent
   on hover and keyboard focus, like the footer's. */
:root .hv-social-link {
	transition: color 150ms ease-out;
}

:root .hv-social-link:is(:hover, :focus-visible) {
	color: var(--hv-color-accent);
}

:root .hv-social-link:focus-visible {
	outline: 2px solid var(--hv-color-accent);
	outline-offset: 2px;
}

/* ==========================================================================
   HAViK Society waitlist form (the page's Elementor Pro Form widget, class
   hv-waitlist, create-elementor-society.php)
   The email field fills the row with the button beside it, both 56px tall;
   stacked on phones. Field on the tokens: black, 1px line border, accent
   border on focus. The button is the site's solid button
   (legacy-overrides.css); only its size is set here.
   ========================================================================== */

:root .hv-waitlist .elementor-form-fields-wrapper {
	display: flex;
	flex-wrap: nowrap;
	align-items: stretch;
	gap: var(--hv-space-12);
	margin: 0;
}

:root .hv-waitlist .elementor-form-fields-wrapper > .elementor-field-group {
	width: auto;
	flex: 0 0 auto;
	margin: 0;
	padding: 0;
}

:root .hv-waitlist .elementor-form-fields-wrapper > .elementor-field-type-email {
	flex: 1 1 auto;
	min-width: 0;
}

:root .hv-waitlist .elementor-field-group input[type="email"] {
	box-sizing: border-box;
	width: 100%;
	min-height: 56px;
	padding: 0 var(--hv-space-16);
	border: 1px solid var(--hv-color-line);
	border-radius: 0;
	background-color: var(--hv-color-bg, #000);
	color: var(--hv-color-text-strong);
	font-family: var(--hv-font-body);
	font-size: var(--hv-size-body);
	line-height: 1.4;
}

:root .hv-waitlist .elementor-field-group input[type="email"]::placeholder {
	color: var(--hv-color-text-dim);
	opacity: 1;
}

:root .hv-waitlist .elementor-field-group input[type="email"]:focus {
	border-color: var(--hv-color-accent);
	outline: 2px solid var(--hv-color-accent);
	outline-offset: 2px;
}

:root .hv-waitlist .e-form__buttons .elementor-button {
	box-sizing: border-box;
	min-height: 56px;
	height: 100%;
	padding: 0 var(--hv-space-32);
	font-size: var(--hv-size-cta);
	line-height: 1;
	white-space: nowrap;
}

/* The confirmation and error lines under the form. */
:root .hv-waitlist .elementor-message {
	margin-block-start: var(--hv-space-12);
	color: var(--hv-color-text-strong);
	font-family: var(--hv-font-body);
	font-size: var(--hv-size-body);
	text-align: center;
}

@media (max-width: 767px) {
	:root .hv-waitlist .elementor-form-fields-wrapper {
		flex-direction: column;
	}

	:root .hv-waitlist .elementor-form-fields-wrapper > .elementor-field-group {
		width: 100%;
	}
}

/* Decoration on black (a JPEG with a black background, like the scattered
   splatter) over the topo lines: lighten drops the black, so only the paint
   shows and the lines stay visible behind it. Class hv-blend-lighten (set by
   create-elementor-product.php). */
:root .hv-blend-lighten {
	mix-blend-mode: lighten;
}

/* Elementor wraps the image in a <picture>; a block image sits flush with
   the corner (no gap under it for the text baseline). */
:root .hv-blend-lighten img {
	display: block;
}

/* Form fields: every dropdown and textarea on the site is black with a gray
   border and square corners, matching the variation dropdowns on the
   product pages. Plain element selectors on purpose: they replace the
   theme's white defaults, while fields with their own styling (WooCommerce
   Blocks checkout, Elementor and WS Form forms) keep it. */
select,
textarea {
	background-color: var(--hv-color-bg);
	border: 1px solid var(--hv-color-muted);
	border-radius: 0;
	color: var(--hv-color-text);
}

/*
 * Segmented controls: square, connected option buttons. Used for the
 * resharpening Method toggle and condition options (resharpening.css adds
 * their extras) and for the variation buttons on every product page
 * (includes/products/variation-buttons.php). The selected one is the brand green with
 * black text (4.5:1), so it doesn't compete with the orange add to cart
 * button; hover is the same green at 70% over the black page, with the
 * white text kept (black on that darker green would fall well short).
 * The radio inputs are visually hidden but stay focusable; each label is a
 * segment.
 *
 * The text colors are !important because the product template's add to
 * cart widget colors every label inside the form (its variations label
 * setting), with a selector these rules can't otherwise outrank. Moved
 * unchanged from resharpening.css.
 */

.havik-segmented {
	display: inline-flex;
	max-width: 100%;
}

.havik-segment-input {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
	border: 0;
}

.havik-segment {
	position: relative;
	display: inline-flex;
	flex: 1 1 auto;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	margin: 0;
	padding: 0 var(--hv-space-20, 20px);
	border: 1px solid var(--hv-color-line-strong, #555);
	border-radius: 0;
	color: var(--hv-color-text-strong, #fff) !important;
	font-weight: 700;
	line-height: 1;
	white-space: nowrap;
	cursor: pointer;
	transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

/* Connected: each segment after the first overlaps the previous border. */
.havik-segment ~ .havik-segment {
	margin-left: -1px;
}

.havik-segment:hover {
	z-index: 1;
	background: color-mix(in srgb, var(--hv-color-green, #687b50) 70%, transparent);
	border-color: color-mix(in srgb, var(--hv-color-green, #687b50) 70%, transparent);
}

.havik-segment-input:checked + .havik-segment {
	z-index: 2;
	background: var(--hv-color-green, #687b50);
	border-color: var(--hv-color-green, #687b50);
	color: var(--hv-color-bg, #000) !important;
}

.havik-segment-input:focus-visible + .havik-segment {
	z-index: 3;
	outline: 2px solid var(--hv-color-accent, currentColor);
	outline-offset: 2px;
}

/* An option that can't be chosen (variation buttons: an out-of-stock or
   nonexistent combination) is grayed out, with no hover fill. */
.havik-segment-input:disabled + .havik-segment,
.havik-segment-input:disabled + .havik-segment:hover {
	background: transparent;
	border-color: var(--hv-color-line);
	color: var(--hv-color-muted) !important;
	cursor: not-allowed;
}

/*
 * Variation buttons (variation-buttons.php): each product option (Size,
 * Type...) as a row of segments in place of WooCommerce's dropdown, which
 * stays in the form, hidden. Long lists wrap; each segment overlaps the
 * border above and to its left, so wrapped rows stay connected.
 */
select.havik-variation-select {
	display: none !important;
}

.havik-variation-buttons {
	flex-wrap: wrap;
	padding: 1px 0 0 1px;
}

.havik-variation-buttons .havik-segment,
.havik-variation-buttons .havik-segment ~ .havik-segment {
	flex: 0 0 auto;
	min-width: 56px;
	margin: -1px 0 0 -1px;
}

/*
 * Options with buttons: each label sits above its buttons instead of in a
 * column beside them, in the same gray, 16px bold as the resharpening
 * labels. The product template's add to cart widget lays the options out
 * as a table and sets the label color and size in its own settings, so
 * these need !important. Tables without variation buttons (resharpening's
 * Method toggle) are left alone.
 */
table.variations:has(.havik-variation-buttons),
table.variations:has(.havik-variation-buttons) tbody,
table.variations:has(.havik-variation-buttons) tr,
table.variations:has(.havik-variation-buttons) th,
table.variations:has(.havik-variation-buttons) td {
	display: block !important;
	width: auto !important;
	padding: 0 !important;
	border: 0 !important;
	background: transparent !important;
}

table.variations:has(.havik-variation-buttons) tr + tr {
	margin-top: var(--hv-space-20) !important;
}

table.variations:has(.havik-variation-buttons) th.label {
	margin-bottom: var(--hv-space-8) !important;
	text-align: left !important;
}

table.variations:has(.havik-variation-buttons) th.label label {
	color: var(--hv-color-text) !important;
	font-size: var(--hv-size-body) !important;
	font-weight: 700 !important;
	line-height: 1.2 !important;
}
