/* ═══════════════════════════════════════════
   SHARED COMPONENTS
   Buttons · product card · drag carousel · notices
   ═══════════════════════════════════════════ */

/* ── Generic buttons (age gate, cookie modal, 404) ───────── */

.se-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5rem;
	min-height: 44px;
	padding: 0.625rem 1.5rem;
	font-family: var(--font-heading);
	font-size: 1.125rem;
	text-transform: uppercase;
	border: 1px solid currentColor;
	transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
}

.se-btn--solid {
	background: var(--se-black);
	color: var(--se-white);
	border-color: var(--se-black);
}

.se-btn--solid:hover {
	background: var(--se-pink);
	border-color: var(--se-pink);
	color: var(--se-white);
}

.se-btn--ghost {
	background: transparent;
	color: currentColor;
}

.se-btn--ghost:hover {
	background: var(--se-black);
	color: var(--se-white);
	border-color: var(--se-black);
}

/* ── The "bite" torn-corner mark ─────────────────────────── */

.hero__cta-bite,
.product-carousel__cta-bite,
.serpent-society__cta-bite,
.confessional__cta-bite,
.pdp__btn-bite,
.site-footer__newsletter-bite {
	pointer-events: none;
}

/* ── Carousel shell ──────────────────────────────────────── */

.product-carousel {
	position: relative;
	z-index: 1;
	display: flex;
	flex-direction: column;
	justify-content: center;
	background: var(--se-black);
	padding-block: clamp(2.5rem, 1.9rem + 3vw, 3.75rem);
	padding-inline: var(--gutter) 0;
	overflow: hidden;
}

@media (min-width: 64rem) {
	.product-carousel { min-height: 800px; }
}

.product-carousel--white {
	background: var(--se-white);
}

.product-carousel--gold {
	background: var(--se-gold);
}

.product-carousel__title {
	font-family: var(--font-heading);
	font-size: clamp(2rem, 1.5rem + 2.2vw, 3rem);
	text-transform: uppercase;
	color: var(--se-white);
	margin-bottom: 20px;
	padding-inline-end: var(--gutter);
}

.product-carousel--white .product-carousel__title,
.product-carousel--gold .product-carousel__title {
	color: var(--se-black);
}

/* ── Track ───────────────────────────────────────────────── */

.product-carousel__track,
.pdp__gallery-track {
	display: flex;
	gap: var(--card-gap);
	padding-block: clamp(1.5rem, 1.2rem + 1.2vw, 2.5rem);
	padding-inline: 0 var(--gutter);
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scroll-snap-type: x proximity;
	scrollbar-width: none;
	-ms-overflow-style: none;
	cursor: grab;
	/* Pointer-driven horizontal drag needs the browser to stop claiming
	   horizontal pans, but vertical page scroll must keep working. */
	touch-action: pan-y;
}

.product-carousel__track::-webkit-scrollbar,
.pdp__gallery-track::-webkit-scrollbar {
	display: none;
}

.product-carousel__track.is-dragging,
.pdp__gallery-track.is-dragging {
	cursor: grabbing;
	scroll-behavior: auto;
	user-select: none;
}

.product-carousel__track:focus-visible,
.pdp__gallery-track:focus-visible {
	outline: var(--se-focus-width) solid var(--se-focus);
	outline-offset: -2px;
}

.product-carousel--white .product-carousel__track:focus-visible,
.product-carousel--gold .product-carousel__track:focus-visible {
	outline-color: var(--se-black);
}

/* ── Product card ────────────────────────────────────────── */

.product-card {
	position: relative;
	flex: 0 0 var(--card-width);
	width: var(--card-width);
	background: var(--se-white);
	scroll-snap-align: start;
}

@media (max-width: 47.9375rem) {
	.product-card {
		--card-width: 280px;
	}
}

.product-card > article {
	display: flex;
	flex-direction: column;
	height: 100%;
}

/*
 * The box is the photograph's own ratio (1571 × 1920), written as those
 * numbers so it is obvious where it comes from. Paired with se-card at
 * 358 × 438 in inc/setup.php — change one and you must change the other.
 */
.product-card__image {
	position: relative;
	width: 100%;
	aspect-ratio: 1571 / 1920;
	overflow: hidden;
	background: linear-gradient(135deg, #1a1a2e, #16213e);
}

.product-carousel--white .product-card__image,
.product-carousel--gold .product-card__image {
	background: linear-gradient(135deg, #2a1a0a, #3a2a1a);
}

.product-card__image-link {
	display: block;
	width: 100%;
	height: 100%;
}

/*
 * Full width, no bleed.
 *
 * This used to be `width: 115%` pulled left by 7.5%, which made the image
 * element very nearly square (0.999) while the photograph is 0.818 — and
 * `cover` then ate 18% of the height. That bleed was the single biggest cause
 * of the beheaded model, and it was invisible in the CSS because the number
 * that mattered was the *element's* ratio, which no line stated.
 *
 * At 100% the element is exactly the box, the box is exactly the photograph's
 * ratio, and `cover` has nothing left to crop. `object-position` stays as
 * insurance for any image that does not match.
 */
.product-card__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center top;
}

/* ── Second image on hover ───────────────────────────────────
   Sits on top of the first and fades in. It is aria-hidden and purely
   decorative: the card's name and link already say what the product is, so a
   screen reader gains nothing from a second photograph of it. */

.product-card__img--hover {
	opacity: 0;
	/* Literal, not --transition-fast: that token already carries its own easing
	   ("150ms ease"), so appending one here would make the value invalid. */
	transition: opacity 320ms ease;
}

/*
 * Revealed on hover AND on keyboard focus inside the card — a hover-only
 * reveal is content a keyboard user can never reach.
 */
.product-card:hover .product-card__img--hover,
.product-card:focus-within .product-card__img--hover {
	opacity: 1;
}

/*
 * Touch has no hover. Without this the swap fires on tap and sticks, so the
 * card shows the second photograph until you tap elsewhere — which reads as a
 * bug rather than a flourish.
 */
@media (hover: none) {
	.product-card__img--hover { display: none; }
}

@media (prefers-reduced-motion: reduce) {
	.product-card__img--hover { transition: none; }
}

.product-card__image-placeholder {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
	font-family: var(--font-heading);
	font-size: var(--type-body-size);
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.35);
}

.product-card__flash {
	position: absolute;
	top: 21px;
	inset-inline-start: 21px;
	z-index: 2;
	padding: 4px 10px;
	background: var(--se-pink);
	/* White on this pink is 3.5:1 and fails AA. Black on it is 6:1. */
	color: var(--se-black);
	font-family: var(--font-heading);
	font-size: 0.875rem;
	text-transform: uppercase;
}

.product-card__flash--oos {
	background: var(--se-black);
	color: var(--se-white);
}

.product-card__wishlist {
	position: absolute;
	top: 13px;
	inset-inline-end: 13px;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	color: var(--se-white);
	transition: color var(--transition-fast);
}

.product-card__wishlist svg {
	width: 25px;
	height: 22px;
	fill: none;
}

.product-card__wishlist:hover,
.product-card__wishlist.is-active {
	color: var(--se-pink);
}

.product-card__wishlist.is-active svg {
	fill: currentColor;
}

.product-card__info {
	position: relative;
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-height: 109px;
	padding: 10px 15px 15px;
	padding-inline-end: 76px; /* room for the collapsed + button */
}

.product-card__name {
	font-family: var(--font-heading);
	font-size: 1.5rem;
	line-height: normal;
	color: var(--se-black);
}

.product-card__link::after {
	/* The whole card is clickable, but only the title is the link — this keeps
	   one link per card in the accessibility tree. */
	content: '';
	position: absolute;
	inset: -100% 0 0 0;
	z-index: 1;
}

.product-card__edition {
	font-family: var(--font-body);
	font-size: 0.875rem;
	color: var(--se-muted-on-light);
}

.product-card__price {
	font-family: var(--font-heading);
	font-size: 1.5rem;
	font-weight: 700;
	color: var(--se-black);
}

.product-card__price del {
	opacity: 0.55;
	margin-inline-end: 0.35em;
}

/*
 * The reveal animates the label's grid track from 0fr to 1fr, which means the
 * animated quantity IS the label's real width. `max-width` could not do that:
 * it needed a guessed ceiling (160px) for a label that measures 112px, so the
 * button hit its final size in ~100ms of a 340ms transition and then sat still
 * while the text finished fading in — a hard pop followed by a lag, which is
 * what read as crude. With 0fr → 1fr the whole duration maps to the whole
 * travel, for any label length, with no magic number to keep in sync.
 */
.product-card__add {
	position: absolute;
	z-index: 2;
	inset-block-start: 50%;
	inset-inline-end: 17px;
	transform: translateY(-50%);
	display: grid;
	grid-auto-flow: column;
	grid-template-columns: auto 0fr;
	column-gap: 0;
	align-items: center;
	justify-content: center;
	width: auto;
	min-width: 44px;
	height: 44px;
	padding-inline: 10px;
	border-radius: 50px;
	background: var(--se-black);
	color: var(--se-white);
	font-family: var(--font-heading);
	font-size: 1.5rem;
	font-weight: 700;
	white-space: nowrap;
	transition: background var(--transition-fast),
		grid-template-columns var(--card-add-ease),
		column-gap var(--card-add-ease);
}

/* Expands on hover AND on keyboard focus — the label must not be mouse-only. */
.product-card:hover .product-card__add,
.product-card__add:focus-visible {
	grid-template-columns: auto 1fr;
	column-gap: 7px;
}

/*
 * The "+" is an icon, not type, and it must never depend on which font happened
 * to load. Bebas Neue is a display face with tall metrics and no reliable "+",
 * so rendering the mark in it left an empty black disc on machines where the
 * Typekit/Google fonts resolve — while a fallback-font machine looked fine.
 * Two bars in a fixed 44px box render identically everywhere, with no glyph,
 * no metrics and no clipping involved.
 *
 * The button itself is deliberately NOT `overflow: hidden` any more: the label
 * clips itself via its own max-width, so the button's clip could only ever hurt
 * the mark and never help.
 */
.product-card__add-mark {
	position: relative;
	width: 15px;
	height: 15px;
	font-size: 0;
	line-height: 0;
}

/* currentColor, so the mark follows the button — including forced-colours mode. */
.product-card__add-mark::before,
.product-card__add-mark::after {
	content: '';
	position: absolute;
	inset-block-start: 50%;
	inset-inline-start: 50%;
	background: currentColor;
	border-radius: 1px;
}

.product-card__add-mark::before {
	width: 15px;
	height: 2.5px;
	transform: translate(-50%, -50%);
}

.product-card__add-mark::after {
	width: 2.5px;
	height: 15px;
	transform: translate(-50%, -50%);
}

/*
 * The track does the revealing, so the label needs no transition of its own —
 * one driver, and the wipe alone is the effect. `min-width: 0` is what lets a
 * grid item shrink below its content, and `overflow: hidden` does the clipping.
 */
.product-card__add-text {
	min-width: 0;
	overflow: hidden;
	font-size: 1.125rem;
	font-weight: 400;
	white-space: nowrap;
}

/* Touch devices have no hover, so the control is shown open from the start. */
@media (hover: none) {
	.product-card__info { padding-inline-end: 15px; }

	.product-card__add {
		position: static;
		transform: none;
		width: 100%;
		margin-top: 10px;
		grid-template-columns: auto auto;
		column-gap: 7px;
		justify-content: center;
	}

	.product-card__add-text {
		overflow: visible;
	}
}

.product-card__add.loading {
	opacity: 0.6;
	pointer-events: none;
}

.product-card__add.added::after {
	content: '✓';
	margin-inline-start: 0.25em;
}

/* ── Carousel CTA ────────────────────────────────────────── */

.product-carousel__cta-wrap {
	display: flex;
	justify-content: center;
	margin-top: 40px;
	padding-inline-end: var(--gutter);
}

.product-carousel__cta,
.hero__cta,
.serpent-society__cta,
.confessional__cta {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	padding: 5px 20px;
	font-family: var(--font-heading);
	font-size: 1.25rem;
	line-height: normal;
	color: var(--se-white);
	background: transparent;
	border: 1px solid currentColor;
	overflow: visible;
	transition: background var(--transition-base), color var(--transition-base), border-color var(--transition-base);
}

.product-carousel__cta-bite,
.hero__cta-bite,
.serpent-society__cta-bite,
.confessional__cta-bite {
	position: absolute;
	top: -1px;
	inset-inline-end: -1px;
	width: 20px;
	height: 21px;
	z-index: 2;
	opacity: 0;
	color: var(--se-black);
	transition: opacity var(--transition-base);
}

.product-carousel__cta:hover,
.product-carousel__cta:focus-visible,
.hero__cta:hover,
.hero__cta:focus-visible,
.serpent-society__cta:hover,
.serpent-society__cta:focus-visible,
.confessional__cta:hover,
.confessional__cta:focus-visible {
	background: var(--se-black);
	border-color: var(--se-black);
	color: var(--se-gold);
}

.product-carousel__cta:hover .product-carousel__cta-bite,
.product-carousel__cta:focus-visible .product-carousel__cta-bite,
.hero__cta:hover .hero__cta-bite,
.hero__cta:focus-visible .hero__cta-bite,
.serpent-society__cta:hover .serpent-society__cta-bite,
.serpent-society__cta:focus-visible .serpent-society__cta-bite,
.confessional__cta:hover .confessional__cta-bite,
.confessional__cta:focus-visible .confessional__cta-bite {
	opacity: 1;
}

/* Gold ground: the rail's own colour flips to gold on scroll, so the CTA
   flips to black in step. */
.product-carousel--gold .product-carousel__cta,
.product-carousel.is-gold .product-carousel__cta,
.product-carousel__cta--dark {
	color: var(--se-black);
}

.product-carousel--gold .product-carousel__cta:hover,
.product-carousel.is-gold .product-carousel__cta:hover,
.product-carousel__cta--dark:hover,
.product-carousel__cta--dark:focus-visible {
	background: var(--se-black);
	border-color: var(--se-black);
	color: var(--se-white);
}

.product-carousel__cta--dark .product-carousel__cta-bite {
	color: var(--se-white);
}

/* ── WooCommerce notices ─────────────────────────────────── */

.se-woo-notices:empty { display: none; }

.se-woo-notices {
	max-width: var(--container-max);
	margin-inline: auto;
	padding: calc(var(--header-height) + 1rem) var(--gutter) 0;
}

.woocommerce-message,
.woocommerce-error,
.woocommerce-info {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.75rem;
	padding: 0.875rem 1.25rem;
	margin-bottom: 1rem;
	font-family: var(--font-body);
	font-size: 1rem;
	line-height: 1.5;
	border-inline-start: 4px solid;
}

.woocommerce-message { background: #F1F8F2; border-color: #276738; color: #17331F; }
.woocommerce-info    { background: #EEF3FA; border-color: #1F4B87; color: #14294A; }
.woocommerce-error   { background: #FBEDED; border-color: #A11B1B; color: #4A1010; }

.woocommerce-error { list-style: none; }

.woocommerce-message .button,
.woocommerce-error .button,
.woocommerce-info .button {
	margin-inline-start: auto;
	padding: 0.5rem 1rem;
	background: var(--se-black);
	color: var(--se-white);
	font-family: var(--font-heading);
	text-transform: uppercase;
}

/* ── Pagination ──────────────────────────────────────────── */

.woocommerce-pagination ul,
.se-main .navigation.pagination .nav-links {
	display: flex;
	justify-content: center;
	flex-wrap: wrap;
	gap: 0.5rem;
	padding: 2.5rem var(--gutter);
}

.woocommerce-pagination a,
.woocommerce-pagination span,
.navigation.pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 44px;
	min-height: 44px;
	padding: 0 0.5rem;
	font-family: var(--font-heading);
	border: 1px solid var(--se-line-on-light);
}

.woocommerce-pagination .current,
.navigation.pagination .page-numbers.current {
	background: var(--se-black);
	color: var(--se-white);
	border-color: var(--se-black);
}

/* ═══════════════════════════════════════════
   BRAND MARKS (inline SVG)
   ═══════════════════════════════════════════
   logo-horizontal.svg and logo-circle.svg are drawn with fill="currentColor",
   so each placement sets a `color` rather than stacking filters. The red
   accent in the wordmark follows currentColor by default; set
   --se-logo-accent to bring the brand red back in a given context.
   ═══════════════════════════════════════════ */

.site-header__logo { color: var(--se-white); }
.se-age-gate__logo { color: var(--se-white); }

.forbidden-collection__badge svg,
.forbidden-collection__badge img { width: 100%; height: auto; }
.forbidden-collection__badge { color: var(--se-white); }

.born-wild__badge svg { width: 100%; height: 100%; }
.born-wild__badge { color: var(--se-black); }

.serpent-society__logo svg { width: 100%; height: 100%; }
.serpent-society__logo { color: var(--se-white); }

.confessional__badge svg { width: 100%; height: auto; opacity: 0.8; }
.confessional__badge { color: var(--se-black); }

.tagline-banner__logo svg { width: 100%; height: auto; }
.tagline-banner__logo { color: var(--se-black); }

.pdp__tagline-logo svg { width: 100%; height: auto; }
.pdp__tagline-logo { color: var(--se-black); }

/* ── Sale prices ─────────────────────────── */

/*
 * WooCommerce renders a sale as <del>old</del> <ins>new</ins>. The theme's only
 * rules for those were scoped to `.woocommerce`, which never wraps the product
 * card or the hand-built PDP — so on both, the new price arrived carrying the
 * browser's default underline (reading as a link) and the old price was exactly
 * as loud as the new one. These are unscoped on purpose.
 */
del,
.price del,
.product-card__price del,
.pdp__price-value del {
	text-decoration: line-through;
	/* A real colour rather than opacity: opacity over a photograph or a pink
	   ground produces a different, unpredictable result each time. */
	color: var(--se-muted-on-light);
	font-weight: 400;
	font-size: 0.82em;
	margin-inline-end: 0.4em;
}

ins,
.price ins,
.product-card__price ins,
.pdp__price-value ins {
	text-decoration: none;
	background: transparent;
	color: inherit;
	font-weight: 700;
}

/* On a dark ground the muted grey is the wrong one. */
.se-theme-dark del,
.product-carousel--dark del,
.confession-wall del {
	color: var(--se-muted-on-dark);
}
