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

/* The original WooCommerce <select> stays in the DOM (JS needs it) but must
   take ZERO layout space. Our inline hiding can be beaten by theme `!important`
   rules (e.g. select padding), which left an invisible gap that pushed the
   swatch row taller than the label. Force it fully out of flow, padding included.
   Targets the `aria-hidden="true"` we inject onto every hidden select. */
.variations select[aria-hidden="true"] {
	position: absolute !important;
	width: 1px !important;
	height: 1px !important;
	padding: 0 !important;
	margin: 0 !important;
	border: 0 !important;
	overflow: hidden !important;
	clip: rect(0, 0, 0, 0) !important;
	opacity: 0 !important;
	pointer-events: none !important;
}

/* WooCommerce hides the "Clear" link with `visibility:hidden`, which still
   reserves layout space. It lives in the last attribute's value cell, so in the
   swatch layout that reserved space becomes an unwanted blank line. Collapse it
   only while hidden; WooCommerce reveals it by switching the inline style away
   from "hidden", at which point this selector stops matching and it reappears. */
.variations .reset_variations[style*="hidden"] {
	display: none !important;
}

/* Accessible reset control — rendered as a real <button> (see Frontend.php).
   `.reset_variations` is a WooCommerce class that opinionated themes (Astra…)
   style heavily, out-specifying us. Force the accessibility-critical bits —
   contrast, focus, and a predictable text-button look — with !important, the
   same theme-hardening approach used for the hidden <select> above. */
.variations .reset_variations {
	display: inline-block;
	margin: 4px 0 0;
	padding: 4px 8px;
	-webkit-appearance: none;
	appearance: none;
	border: 0 !important;
	background: none !important;
	box-shadow: none !important;
	color: #1a1a1a !important;
	font: inherit;
	font-size: 0.9375rem !important;
	line-height: 1.4;
	opacity: 1 !important;
	text-transform: none !important;
	text-decoration: underline !important;
	cursor: pointer;
}

.variations .reset_variations:hover {
	text-decoration: none !important;
}

/* Visible focus regardless of theme — WCAG 2.4.11. */
.variations .reset_variations:focus-visible {
	outline: 3px solid #0066cc !important;
	outline-offset: 2px;
	border-radius: 2px;
}

/* Vertically center the attribute label against the (taller) swatch row.
   WooCommerce marks up the name cell as `td.label` (some themes remap it to
   `th.label`), so target both. */
.variations td.label,
.variations th.label,
.variations td.value {
	vertical-align: middle;
}

/* The attribute name is a <label> too, so it also inherits the theme's
   `label { margin-bottom }` — reset it so the text sits on the swatch-row
   centerline instead of being pushed up by its own bottom margin. */
.variations td.label label,
.variations th.label label {
	margin: 0;
}

.ivsw-swatch-group {
	--ivsw-swatch-size: 40px;
	--ivsw-swatch-radius: 4px;
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	/* No asymmetric bottom margin: it would offset the vertically-centered
	   attribute label from the swatch row. Row spacing comes from the table. */
	padding: 0;
	margin: 0;
	border: 0;
}

/* Global shape (Settings) — circle is special-cased on color/image below. */
.ivsw-swatch-group--shape-square {
	--ivsw-swatch-radius: 0;
}

.ivsw-swatch-group--shape-circle {
	--ivsw-swatch-radius: 4px;
}

/* Global size (Settings) — all ≥24px target (WCAG 2.5.8). */
.ivsw-swatch-group--size-s {
	--ivsw-swatch-size: 32px;
}

.ivsw-swatch-group--size-l {
	--ivsw-swatch-size: 48px;
}

/* Hide the group's <legend> visually but keep it as the accessible group name —
   don't depend on the theme/WooCommerce providing `.screen-reader-text`. */
.ivsw-legend {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* Swatch base */
.ivsw-swatch {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	min-width: var(--ivsw-swatch-size);
	min-height: var(--ivsw-swatch-size);
	padding: 4px 12px;
	border: 2px solid #767676;
	border-radius: var(--ivsw-swatch-radius);
	cursor: pointer;
	font-size: 0.875em;
	line-height: 1;
	background: #fff;
	color: #1a1a1a;
	transition: border-color 0.15s;
}

/* Swatches are <label>s, so themes fight us on generic `label` rules:
   `margin-bottom` offsets them in the flex row, and overriding `display`
   breaks the flex centering of the text in label swatches (seen on Blocksy:
   40px box, text stuck to the top). Re-assert layout with 2-class specificity
   + !important so it holds regardless of theme depth or load order. */
.ivsw-swatch-group .ivsw-swatch {
	display: inline-flex !important;
	align-items: center !important;
	justify-content: center !important;
	margin: 0;
}

/* Color & image swatches are fixed 1:1 squares so `border-radius:50%`
   (circle shape) renders a true circle regardless of theme height quirks —
   a color swatch has no in-flow content to give it intrinsic height. */
.ivsw-swatch--color,
.ivsw-swatch--image {
	flex: 0 0 auto;
	width: var(--ivsw-swatch-size);
	height: var(--ivsw-swatch-size);
	min-width: 0;
	min-height: 0;
	padding: 0;
}

/* Color swatch — always keep the base neutral border (#767676) so the swatch
   boundary stays ≥3:1 against the page on any fill color and on light OR dark
   themes (WCAG 1.4.11), without fragile per-color/background detection. */
.ivsw-swatch--color {
	background: var(--ivsw-swatch-color, #fff);
}

/* Image swatch — clip on the <img> itself, not the label, so the tooltip
   (positioned outside the box) isn't cropped by overflow. */
.ivsw-swatch--image {
	background: #fff;
}

.ivsw-swatch__img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: inherit;
}

/* Circle only makes sense for color/image; text labels stay pill-shaped. */
.ivsw-swatch-group--shape-circle .ivsw-swatch--color,
.ivsw-swatch-group--shape-circle .ivsw-swatch--image {
	border-radius: 50%;
}

/* Selected state — dark 3px border + a white inner ring: a structural
   (non-color) cue that reads on any swatch fill and is distinct from the blue
   focus outline (WCAG 1.4.1). On near-white fills the ring blends in but the
   darker, thicker border still marks the selection. */
.ivsw-radio:checked + .ivsw-swatch {
	border-color: #1a1a1a;
	border-width: 3px;
	box-shadow: inset 0 0 0 2px #fff;
}

/* Focus-visible — WCAG 2.2 SC 2.4.11 */
.ivsw-radio:focus-visible + .ivsw-swatch {
	outline: 3px solid #0066cc;
	outline-offset: 2px;
}

/* Forced colors (Windows High Contrast): the browser strips background-color,
   which would make every color swatch identical. The fill (and the image) IS
   the information here, so preserve it. Border/focus/selected keep their own
   sufficient-contrast styling; label swatches are left to the system palette,
   where their text stays legible. The variant name also remains available via
   the sr-only span and the tooltip. */
@media ( forced-colors: active ) {
	.ivsw-swatch--color,
	.ivsw-swatch--image {
		forced-color-adjust: none;
	}
}

/* Out of stock — dim via an inset overlay, NOT `opacity` on the label:
   opacity would form a group alpha and fade the tooltip (a child) too. The
   overlay only covers the swatch box (inset:0), leaving the tooltip crisp. */
.ivsw-swatch--oos {
	cursor: not-allowed;
}

.ivsw-swatch--oos::after {
	content: '';
	position: absolute;
	inset: 0;
	border-radius: inherit;
	/* Top layer: the diagonal cross. Bottom layer: a white wash that mimics
	   opacity 0.4 against a white background (0.4·color + 0.6·white). */
	background:
		linear-gradient(
			to top right,
			transparent calc(50% - 1px),
			#767676 50%,
			transparent calc(50% + 1px)
		),
		rgba( 255, 255, 255, 0.6 );
}

/* --- Tooltip (visual variant name for color/image swatches) -------------- */
/* WCAG 1.4.13: shown on hover AND keyboard focus, hoverable (bridge below),
   persistent (no timer), dismissible via Escape (JS sets the attribute). */
.ivsw-tooltip {
	position: absolute;
	bottom: 100%;
	left: 50%;
	transform: translateX(-50%);
	margin-bottom: 6px;
	z-index: 10;
	padding: 4px 8px;
	max-width: 16em;
	background: #1a1a1a;
	color: #fff;
	font-size: 0.8125em;
	line-height: 1.3;
	white-space: nowrap;
	border-radius: 4px;
	visibility: hidden;
	opacity: 0;
	transition: opacity 0.12s ease;
}

/* Invisible bridge covering the visual gap so the pointer can travel from the
   swatch onto the tooltip without leaving :hover (WCAG 1.4.13 "hoverable"). */
.ivsw-tooltip::after {
	content: '';
	position: absolute;
	top: 100%;
	left: 0;
	right: 0;
	height: 6px;
}

/* Little pointer triangle. */
.ivsw-tooltip::before {
	content: '';
	position: absolute;
	top: 100%;
	left: 50%;
	transform: translateX(-50%);
	border: 5px solid transparent;
	border-top-color: #1a1a1a;
}

.ivsw-swatch:hover > .ivsw-tooltip,
.ivsw-radio:focus-visible + .ivsw-swatch > .ivsw-tooltip {
	visibility: visible;
	opacity: 1;
}

/* Escape dismiss — wins over the hover/focus rules above. */
.ivsw-swatch[data-ivsw-tt-dismissed] > .ivsw-tooltip {
	visibility: hidden !important;
	opacity: 0 !important;
}

@media ( prefers-reduced-motion: reduce ) {
	.ivsw-tooltip {
		transition: none;
	}
}
