/*
 * OfflineOps — what theme.json cannot express.
 * Design tokens stay in theme.json; this file holds motion and the few
 * components blocks don't cover. Logical properties throughout, so the
 * layout flips correctly if the site is ever set to RTL.
 */

/* ---------- Scroll reveal ---------- */
.oo-reveal,
[data-reveal] {
	opacity: 0;
	transform: translateY(14px);
	transition:
		opacity   var(--wp--custom--transition--slow) var(--wp--custom--transition--ease),
		transform var(--wp--custom--transition--slow) var(--wp--custom--transition--ease);
	will-change: opacity, transform;
}
.oo-reveal.is-visible,
[data-reveal].is-visible {
	opacity: 1;
	transform: none;
}
[data-reveal="fade"]  { transform: none; }
[data-reveal="left"]  { transform: translateX(-18px); }
[data-reveal="right"] { transform: translateX(18px); }
[data-reveal="scale"] { transform: scale(.97); }

/* Motion is decoration: strip it when asked, and never hide content. */
@media (prefers-reduced-motion: reduce) {
	.oo-reveal,
	[data-reveal] {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}
	html { scroll-behavior: auto !important; }
}

/* ---------- Site chrome ---------- */
.oo-logo img {
	width: var(--oo-logo-width, 150px);
	height: auto;
	display: block;
}

.oo-announce {
	background: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
	text-align: center;
	font-size: var(--wp--preset--font-size--xs);
	padding-block: .6rem;
	padding-inline: var(--wp--custom--container--gutter);
}
.oo-announce a { color: inherit; text-decoration: underline; }

/* ---------- Product cards ----------
 * One card, built once in patterns/product-card.php and used by every product
 * listing. Deliberately no wishlist, compare or quick-view affordances.
 *
 * The card is a surface in its own right: white panel, soft border, the photo
 * floating on it. Everything below the photo is one flex column so the price
 * row can be pinned to the bottom and line up across a row of cards.
 */
.wc-block-product-template li.wc-block-product {
	/* Declared on the card, not the button: custom properties inherit down, so
	   a value set on .oo-card__cta is invisible to .oo-card__body above it. */
	--oo-cta-h: 2.75rem;
	position: relative;
	/* Not inherited here, and it matters in the sliding rows: with content-box
	   a flex-basis sets the content width and the card's own padding and
	   border are added on top, so cards came out 23px wider than asked and
	   4.3 across rendered as 4. */
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--20);
	padding: var(--wp--preset--spacing--30);
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--lg);
	/* Clips the button while it is parked below the body. */
	overflow: hidden;
	transition:
		transform    var(--wp--custom--transition--base) var(--wp--custom--transition--ease),
		box-shadow   var(--wp--custom--transition--base) var(--wp--custom--transition--ease),
		border-color var(--wp--custom--transition--base) var(--wp--custom--transition--ease);
}

@media (hover: hover) {
	.wc-block-product-template li.wc-block-product:hover {
		transform: translateY(-3px);
		border-color: transparent;
		box-shadow: 0 10px 28px rgba(23, 22, 20, .10);
	}
}

/* The photo panel. position:relative anchors the sale badge.
 * No background of its own: the photo sits on the card itself, so a cut-out
 * product shot floats rather than sitting in a visible tray. A tint here plus
 * the multiply below turned every product shot muddy. */
.wc-block-product-template li.wc-block-product .wc-block-components-product-image {
	position: relative;
	margin: 0;
	padding: var(--wp--preset--spacing--20);
	border-radius: var(--wp--custom--radius--md);
	overflow: hidden;
}

.wc-block-components-product-image img {
	aspect-ratio: 1 / 1;
	object-fit: contain;
	inline-size: 100%;
	border-radius: 0;
	/* Collapses the white box around a cut-out shot into the card. Harmless
	   on a photo that already fills its frame. */
	mix-blend-mode: multiply;
	transition: transform var(--wp--custom--transition--slow) var(--wp--custom--transition--ease);
}

@media (hover: hover) {
	li.wc-block-product:hover .wc-block-components-product-image img {
		transform: scale(1.04);
	}
}

/* Sale badge as a pill in the corner. Inset-inline-start, not left: under RTL
   a physical corner puts it on the wrong side of the photo. */
.wc-block-product-template li.wc-block-product .wc-block-components-product-sale-badge {
	position: absolute;
	inset-block-start: var(--wp--preset--spacing--20);
	inset-inline-start: var(--wp--preset--spacing--20);
	z-index: 1;
	margin: 0;
	padding-block: .3rem;
	padding-inline: .6rem;
	font-size: var(--wp--preset--font-size--xs);
	font-weight: 600;
	line-height: 1.4;
	color: var(--wp--preset--color--base);
	background: var(--wp--preset--color--accent);
	border: 0;
	border-radius: var(--wp--custom--radius--pill);
}

/* The body holds everything under the photo and moves as one piece on hover.
   It is the flex column now, so .oo-card__foot's margin-block-start:auto still
   has a flex parent to push against. */
.oo-card__body {
	position: relative;
	z-index: 1;
	display: flex;
	flex: 1 1 auto;
	flex-direction: column;
	gap: var(--wp--preset--spacing--20);
	/* Breathing room over the title, and it doubles as the panel's own top
	   edge once this box rides up over the photo. */
	padding-block-start: var(--wp--preset--spacing--40);
	/* Opaque so that when it rides up on hover it masks the lower part of the
	   photo instead of letting the picture show through the text.
	   position:relative here is only for that stacking — the button is a
	   sibling, not a child, precisely so it anchors to the card rather than to
	   this box, which moves. */
	background: var(--wp--preset--color--base);
}

/* Title and rating share a line; the title takes the slack. */
.oo-card__head { margin-block-start: var(--wp--preset--spacing--20); }
.oo-card__head .wp-block-post-title { flex: 1 1 auto; min-inline-size: 0; }
.oo-card__head .wp-block-post-title a { text-decoration: none; color: inherit; }

.oo-card__head .wc-block-components-product-rating {
	flex: 0 0 auto;
	margin: 0;
}
.oo-card__head .wc-block-components-product-rating__stars { margin: 0; }

.oo-card__cat {
	margin: 0;
	line-height: 1.6;
}
.oo-card__cat a { text-decoration: none; color: inherit; }

/* Price and swatches share the last line. margin-top:auto pins the row to the
   bottom so cards of differing title length still line their prices up.
 *
 * The row wraps rather than holding one line: in a two-up grid on a phone the
 * card is ~137px wide, and "از ۵۸.۱۷۴.۰۰۰ تومان" alone is wider than that. Held
 * on one line the swatches were pushed 46px outside the card and took the whole
 * page into horizontal scroll. Wrapped, the swatches drop to their own line. */
.oo-card__foot {
	margin-block-start: auto;
	padding-block-start: var(--wp--preset--spacing--20);
	row-gap: var(--wp--preset--spacing--20);
}

.oo-card__foot .wc-block-components-product-price {
	flex: 1 1 auto;
	min-inline-size: 0;
	color: var(--wp--preset--color--accent);
}
.oo-card__foot .wc-block-components-product-price del { color: var(--wp--preset--color--muted); }

.oo-card__swatches {
	display: flex;
	flex: 0 0 auto;
	align-items: center;
	gap: .3rem;
}

.oo-card__swatch {
	inline-size: 1rem;
	block-size: 1rem;
	border-radius: 50%;
	background: var(--oo-swatch, transparent);
	/* Inset ring rather than a border, so a white swatch stays visible on a
	   white card without the dot changing size. */
	box-shadow: inset 0 0 0 1px rgba(23, 22, 20, .18);
}

.oo-card__swatch-more {
	font-size: var(--wp--preset--font-size--xs);
	color: var(--wp--preset--color--muted);
}

/* The call to action.
 *
 * Base state is a plain in-flow button, always visible. That is what touch
 * devices get: there is no hover there to reveal anything, and a button that
 * only appears on a hover that can never happen is just a missing button.
 *
 * Only where a real pointer exists does it become the sliding panel below.
 *
 * Both selectors carry the extra classes on purpose. Woo ships
 *   .wp-block-button.wc-block-components-product-button            { align-items: center }
 *   .wp-block-button.wc-block-components-product-button .wp-block-button__link { width: auto }
 * at specificity 0,2,0 and 0,3,0 — a plain .oo-card__cta rule loses to both, so
 * the button kept hugging its text at 137px inside a 255px card.
 */
li.wc-block-product .oo-card__cta.wc-block-components-product-button {
	display: flex;
	align-items: stretch;
	margin: 0;
}

li.wc-block-product .oo-card__cta.wc-block-components-product-button .wp-block-button__link {
	display: flex;
	align-items: center;
	justify-content: center;
	inline-size: 100%;
	block-size: var(--oo-cta-h);
	padding-block: 0;
	border-radius: var(--wp--custom--radius--pill);
}

/* Pointer devices: the button leaves the flow so it reserves no height — with
 * it in flow the card had to keep a button-sized blank band under the photo at
 * rest, which read as a layout bug rather than a waiting button.
 *
 * At rest it is parked below the card's clip. On hover the body slides up by
 * exactly the button's height plus the gap, and the button slides into the
 * space the body just vacated. The body is opaque, so riding up covers the
 * lower part of the photo — the photo itself never moves.
 */
@media (hover: hover) {
	li.wc-block-product .oo-card__cta.wc-block-components-product-button {
		position: absolute;
		inset-inline: var(--wp--preset--spacing--30);
		inset-block-end: var(--wp--preset--spacing--30);
		z-index: 2;
		/* Its own height plus the bottom padding, because overflow clips at
		   the padding box and padding hides nothing sitting inside it. */
		transform: translateY(calc(100% + var(--wp--preset--spacing--30)));
		transition: transform var(--wp--custom--transition--base) var(--wp--custom--transition--ease);
	}

	.oo-card__body {
		transition: transform var(--wp--custom--transition--base) var(--wp--custom--transition--ease);
	}

	li.wc-block-product:hover .oo-card__body,
	li.wc-block-product:focus-within .oo-card__body {
		transform: translateY(calc(-1 * (var(--oo-cta-h) + var(--wp--preset--spacing--20))));
	}

	li.wc-block-product:hover .oo-card__cta.wc-block-components-product-button,
	li.wc-block-product:focus-within .oo-card__cta.wc-block-components-product-button {
		transform: none;
	}
}

/* Woo appends a "View cart" link to the card after an AJAX add. The cart
   drawer already opens on that same event, so the link is a second, quieter
   route to a drawer the shopper is currently looking at — and it rendered as a
   zero-width box hanging 16px outside the card. */
.wc-block-product-template li.wc-block-product .added_to_cart {
	display: none;
}

@media (prefers-reduced-motion: reduce) {
	.wc-block-product-template li.wc-block-product,
	.wc-block-components-product-image img,
	.oo-card__body {
		transition: none;
	}
	.wc-block-product-template li.wc-block-product:hover { transform: none; }
	li.wc-block-product:hover .wc-block-components-product-image img { transform: none; }
}

/* ---------- Accessibility ---------- */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
	border-radius: var(--wp--custom--radius--sm);
}

.skip-link:not(:focus) {
	position: absolute !important;
	width: 1px; height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

html { scroll-behavior: smooth; }

/* ---------- Variable products ----------
 * Woo renders the variation form as a legacy <table>, outside the block
 * system, so theme.json tokens cannot style it. Done here instead, using
 * logical properties so it mirrors correctly in RTL.
 */
.variations {
	width: 100%;
	border-collapse: collapse;
	margin-block: var(--wp--preset--spacing--40);
}
.variations tr { display: flex; flex-wrap: wrap; align-items: center; gap: .75rem; }
.variations tr + tr { margin-block-start: var(--wp--preset--spacing--30); }

.variations th.label {
	flex: 0 0 auto;
	min-inline-size: 5.5rem;
	text-align: start;
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 500;
}
.variations td.value { flex: 1 1 12rem; }

.variations select {
	inline-size: 100%;
	padding-block: .6rem;
	padding-inline: .9rem;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--sm);
	color: var(--wp--preset--color--contrast);
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--md);
	transition: border-color var(--wp--custom--transition--fast) var(--wp--custom--transition--ease);
}
.variations select:focus {
	border-color: var(--wp--preset--color--primary);
	outline: none;
}

.reset_variations {
	display: inline-block;
	margin-block-start: .5rem;
	font-size: var(--wp--preset--font-size--xs);
	color: var(--wp--preset--color--muted);
}
/* Woo toggles this link's visibility inline; don't fight it when hidden. */
.reset_variations[style*="visibility: hidden"] { display: none; }

.woocommerce-variation-price {
	font-size: var(--wp--preset--font-size--lg);
	font-weight: 700;
	margin-block: var(--wp--preset--spacing--30);
}
.woocommerce-variation-availability { font-size: var(--wp--preset--font-size--sm); }
.woocommerce-variation-availability .out-of-stock { color: var(--wp--preset--color--sale); }

/* Quantity + add-to-cart sit on one line. */
form.cart { display: flex; flex-wrap: wrap; gap: .75rem; align-items: stretch; }
form.cart .quantity input[type="number"] {
	inline-size: 5rem;
	padding-block: .7rem;
	text-align: center;
	font-family: inherit;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--md);
}
form.cart button[type="submit"] { flex: 1 1 12rem; }

/* ---------- Brand-coloured surfaces ----------
 * on-primary is computed from the brand colour's luminance, so a pale brand
 * colour still gets readable text.
 */
.has-primary-background-color { color: var(--oo-on-primary); }

/* ---------- Variation swatches ----------
 * Woo's <select> stays in the DOM and is only hidden once the swatch script
 * is running (.oo-has-swatches), so the page degrades to working dropdowns
 * if that script fails to load.
 */
.oo-has-swatches .variations td.value { position: relative; }

/* Pin the hidden select to its container. Without an explicit inset an
   absolutely positioned box keeps its static position, which under RTL landed
   it outside the viewport and gave the whole page horizontal scroll. */
.oo-has-swatches .variations select {
	position: absolute !important;
	inset-inline-start: 0;
	inset-block-start: 0;
	inline-size: 1px !important;
	block-size: 1px !important;
	margin: -1px !important;
	padding: 0 !important;
	border: 0 !important;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

.oo-swatches {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem;
	align-items: center;
}

.oo-swatch {
	--oo-sw-size: 2.5rem;
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-inline-size: var(--oo-sw-size);
	block-size: var(--oo-sw-size);
	padding-inline: .75rem;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--xs);
	color: var(--wp--preset--color--contrast);
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--md);
	cursor: pointer;
	transition:
		border-color var(--wp--custom--transition--fast) var(--wp--custom--transition--ease),
		transform    var(--wp--custom--transition--fast) var(--wp--custom--transition--ease);
}
@media (hover: hover) {
	.oo-swatch:hover:not(.is-unavailable) { border-color: var(--wp--preset--color--contrast); }
}

.oo-swatch--color {
	inline-size: var(--oo-sw-size);
	padding: 3px;
	border-radius: var(--wp--custom--radius--pill);
}
.oo-swatch__chip {
	inline-size: 100%;
	block-size: 100%;
	border-radius: inherit;
	/* Keeps a white or very pale swatch visible against a white card. */
	box-shadow: inset 0 0 0 1px rgba(23,22,20,.12);
}

.oo-swatch.is-selected {
	border-color: var(--wp--preset--color--primary);
	box-shadow: 0 0 0 1px var(--wp--preset--color--primary);
}

/* Unavailable rather than hidden: a shopper should see that a combination
   exists but is not available with their current choice. */
.oo-swatch.is-unavailable {
	opacity: .35;
	cursor: not-allowed;
}
.oo-swatch.is-unavailable::after {
	content: "";
	position: absolute;
	inset-inline: 10%;
	inset-block-start: 50%;
	block-size: 1px;
	background: currentColor;
	transform: rotate(-20deg);
}

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

/* Stagger reveals among siblings. Delay is CSS rather than a data attribute
   because the block editor exposes className but not arbitrary attributes. */
.wp-block-columns > .oo-reveal:nth-child(2) { transition-delay: 90ms; }
.wp-block-columns > .oo-reveal:nth-child(3) { transition-delay: 180ms; }
.wp-block-columns > .oo-reveal:nth-child(4) { transition-delay: 270ms; }
@media (prefers-reduced-motion: reduce) {
	.wp-block-columns > .oo-reveal { transition-delay: 0s !important; }
}

/* ---------- Product gallery, RTL containment ----------
 * Woo's gallery is FlexSlider, which lays slides out side by side and offsets
 * the track with a transform. Under RTL that track sits to the left of its
 * container, and the zoom overlay is positioned from the wrong edge; both
 * escape the layout and give the page horizontal scroll. Clip them at the
 * container instead of hiding overflow on <body>, which would mask the cause.
 */
.woocommerce-product-gallery,
.woocommerce-product-gallery .flex-viewport {
	overflow: hidden;
	max-inline-size: 100%;
}
.woocommerce-product-gallery__wrapper { max-inline-size: 100%; }
.woocommerce-product-gallery img { max-inline-size: 100%; height: auto; }
/* The zoom plugin injects an absolutely positioned clone at page scale. */
.woocommerce-product-gallery img.zoomImg { max-inline-size: none; }
.woocommerce-product-gallery__image { position: relative; overflow: hidden; }

/* ---------- Hero slider ----------
 * Scroll-snap rather than transforms: native scrolling already handles RTL,
 * touch and keyboard, so there is no direction maths to get wrong.
 */
.oo-slider { position: relative; }
.oo-slider__track {
	display: flex;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	-webkit-overflow-scrolling: touch;
	overscroll-behavior-inline: contain;
}
.oo-slider__track::-webkit-scrollbar { display: none; }

/* Image and caption share one grid cell. Stacking them this way avoids
   absolute positioning and a negative z-index, which put the image behind
   an ancestor's background and left the slide blank. */
.oo-slider__slide {
	position: relative;
	flex: 0 0 100%;
	scroll-snap-align: start;
	display: grid;
	grid-template-areas: "stack";
	min-block-size: clamp(320px, 46vw, 560px);
}
.oo-slider__img {
	grid-area: stack;
	inline-size: 100%;
	block-size: 100%;
	object-fit: cover;
	/* The slide is the only sizing authority; without this the intrinsic
	   image height stretches short slides. */
	min-block-size: 0;
}
.oo-slider__body {
	grid-area: stack;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--wp--preset--spacing--60) var(--wp--custom--container--gutter);
	/* Readable over any photograph without flattening the whole image. */
	background: linear-gradient(to top, rgba(23,22,20,.45), rgba(23,22,20,.12));
}
.oo-slider__inner { max-inline-size: 38rem; text-align: center; color: #fff; }
.oo-slider__title {
	font-size: var(--wp--preset--font-size--3xl);
	line-height: 1.3;
	margin: 0;
	text-shadow: 0 1px 18px rgba(0,0,0,.35);
}
.oo-slider__text {
	font-size: var(--wp--preset--font-size--lg);
	margin-block-start: var(--wp--preset--spacing--30);
	text-shadow: 0 1px 14px rgba(0,0,0,.35);
}
.oo-slider__cta {
	display: inline-block;
	margin-block-start: var(--wp--preset--spacing--40);
	padding: .8rem 1.75rem;
	background: var(--wp--preset--color--primary);
	color: var(--oo-on-primary, #fff);
	border-radius: var(--wp--custom--radius--md);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 550;
	text-decoration: none;
	text-shadow: none;
}

/* display:contents so the arrows and dots position against .oo-slider
   itself rather than this wrapper — arrows at the sides, dots at the
   bottom, instead of all four crowded into one cluster. */
.oo-slider__nav { display: contents; }

.oo-slider__arrow {
	position: absolute;
	inset-block-start: 50%;
	transform: translateY(-50%);
	inline-size: 2.75rem;
	block-size: 2.75rem;
	display: grid;
	place-items: center;
	border: 0;
	border-radius: 50%;
	background: rgba(255, 255, 255, .92);
	box-shadow: 0 2px 10px rgba(23, 22, 20, .18);
	cursor: pointer;
	opacity: .85;
	transition:
		opacity var(--wp--custom--transition--fast) var(--wp--custom--transition--ease),
		background var(--wp--custom--transition--fast) var(--wp--custom--transition--ease);
}
.oo-slider__arrow[data-dir="prev"] { inset-inline-start: var(--wp--custom--container--gutter); }
.oo-slider__arrow[data-dir="next"] { inset-inline-end: var(--wp--custom--container--gutter); }
@media (hover: hover) {
	.oo-slider__arrow:hover { opacity: 1; background: #fff; }
}
.oo-slider__arrow:focus-visible { opacity: 1; background: #fff; }

/* Physical borders plus an explicit RTL flip. Logical borders combined
   with a rotation produced up/down chevrons once direction changed. */
.oo-slider__arrow::before {
	content: "";
	inline-size: .56rem;
	block-size: .56rem;
	border-top: 2px solid #171614;
	border-right: 2px solid #171614;
	/* Nudge toward the point so the glyph looks optically centred. */
	margin-inline-start: -.16rem;
}
.oo-slider__arrow[data-dir="next"]::before { transform: rotate(45deg); }
.oo-slider__arrow[data-dir="prev"]::before { transform: rotate(-135deg); margin-inline: .16rem 0; }
[dir="rtl"] .oo-slider__arrow[data-dir="next"]::before { transform: rotate(-135deg); margin-inline: .16rem 0; }
[dir="rtl"] .oo-slider__arrow[data-dir="prev"]::before { transform: rotate(45deg); margin-inline: 0 .16rem; }

.oo-slider__dots {
	position: absolute;
	inset-block-end: var(--wp--preset--spacing--40);
	inset-inline: 0;
	display: flex;
	gap: .4rem;
	align-items: center;
	justify-content: center;
}
.oo-slider__dot {
	inline-size: .5rem;
	block-size: .5rem;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: rgba(255, 255, 255, .55);
	box-shadow: 0 1px 3px rgba(23, 22, 20, .25);
	cursor: pointer;
	transition: inline-size var(--wp--custom--transition--base) var(--wp--custom--transition--ease),
	            background var(--wp--custom--transition--base) var(--wp--custom--transition--ease);
}
.oo-slider__dot.is-active {
	inline-size: 1.75rem;
	border-radius: var(--wp--custom--radius--pill);
	background: #fff;
}

@media (max-width: 600px) {
	.oo-slider__arrow { inline-size: 2.25rem; block-size: 2.25rem; }
}

.oo-slider--empty {
	padding: var(--wp--preset--spacing--60);
	text-align: center;
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--muted);
}
@media (prefers-reduced-motion: reduce) {
	.oo-slider__track { scroll-behavior: auto; }
	.oo-slider__dot { transition: none; }
}

/* ---------- Category tiles ----------
 * Circular, matching the reference. auto-fit rather than a fixed column
 * count so three categories centre instead of leaving two empty cells,
 * and ten still wrap sensibly.
 */
.oo-cats {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(0, var(--oo-cat-size, 172px)));
	justify-content: center;
	gap: var(--wp--preset--spacing--50) var(--wp--preset--spacing--40);
}
@media (max-width: 600px) { .oo-cats { --oo-cat-size: 132px; } }

.oo-cat { display: block; text-decoration: none; color: inherit; }

.oo-cat__media {
	display: block;
	position: relative;
	aspect-ratio: 1 / 1;
	overflow: hidden;
	border-radius: 50%;
	background: var(--wp--preset--color--surface-alt);
	transition: box-shadow var(--wp--custom--transition--base) var(--wp--custom--transition--ease);
}
.oo-cat__img {
	position: absolute;
	inset: 0;
	inline-size: 100%;
	block-size: 100%;
	object-fit: cover;
	transition: transform var(--wp--custom--transition--slow) var(--wp--custom--transition--ease);
}
@media (hover: hover) {
	.oo-cat:hover .oo-cat__media { box-shadow: 0 0 0 3px var(--wp--preset--color--primary); }
	.oo-cat:hover .oo-cat__img { transform: scale(1.06); }
}
.oo-cat__body { display: block; margin-block-start: var(--wp--preset--spacing--30); text-align: center; }
.oo-cat__name { display: block; font-size: var(--wp--preset--font-size--sm); font-weight: 600; line-height: 1.6; }
.oo-cat__count { display: block; margin-block-start: .1rem; font-size: var(--wp--preset--font-size--xs); color: var(--wp--preset--color--muted); }
@media (prefers-reduced-motion: reduce) {
	.oo-cat__img, .oo-cat__media { transition: none; }
}

/* ---------- Catalog sorting ----------
 * Woo renders a bare <select>; without this it is the only browser-default
 * control left on the page.
 */
.woocommerce-ordering select,
.wc-block-catalog-sorting select,
.wp-block-woocommerce-catalog-sorting select {
	appearance: none;
	padding-block: .55rem;
	padding-inline: 2.1rem .9rem;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--xs);
	color: var(--wp--preset--color--contrast);
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--pill);
	cursor: pointer;
	/* Inline SVG chevron, positioned on the inline-end edge so it follows
	   the document direction instead of always sitting on the right. */
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%236b6962' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-size: .7rem;
	background-position: left .8rem center;
}
[dir="rtl"] .woocommerce-ordering select,
[dir="rtl"] .wp-block-woocommerce-catalog-sorting select { background-position: left .8rem center; }
[dir="ltr"] .woocommerce-ordering select,
[dir="ltr"] .wp-block-woocommerce-catalog-sorting select { background-position: right .8rem center; }

/* The open option list is drawn by the OS and does not inherit the select's
   font, so it fell back to a Latin system face and rendered Persian badly.
   Setting it on the options themselves is what Chrome honours. */
.woocommerce-ordering select option,
.wp-block-woocommerce-catalog-sorting select option,
.woocommerce select option,
.oo-swatches + select option {
	font-family: var(--wp--preset--font-family--sans);
	font-size: var(--wp--preset--font-size--sm);
}

/* ---------- Mini cart on the cart and checkout pages ----------
 * Woo hides the button with visibility:hidden there. It still occupies its
 * space, so the header keeps a gap where a control used to be, which reads
 * as a rendering fault. Shown but inert instead: the shopper can see the
 * cart control and see that it does nothing useful on this page.
 */
body.woocommerce-cart .wc-block-mini-cart__button,
body.woocommerce-checkout .wc-block-mini-cart__button {
	visibility: visible;
	opacity: .45;
	pointer-events: none;
	cursor: default;
}
/* ---------- Price direction ----------
 * Woo wraps amounts in <bdi>, whose UA style is unicode-bidi: isolate with
 * dir=auto. Persian WooCommerce rewrites the displayed price and drops that
 * wrapper, but the variation price is injected from pre-generated JSON and
 * keeps it — so two prices on the same page were resolved under different
 * bidi rules and came out in opposite orders.
 *
 * The amount is always Persian digits plus "تومان" inside an RTL document,
 * so there is no mixed-direction hazard for the isolation to protect
 * against. Letting it flow with the paragraph makes every price agree.
 */
.woocommerce-Price-amount bdi {
	unicode-bidi: normal;
}

/* Woo's &nbsp; sits between amount and symbol logically, but bidi reordering
   moves it to the outer edge, so the two run together. An inline-start margin
   on the symbol puts the gap where it is actually seen, in em so it scales
   with whatever size the price is rendered at. */
.woocommerce-Price-currencySymbol {
	margin-inline-start: .28em;
}

/* ---------- Add-to-cart busy state ----------
 * Adding is two round trips — the POST, then the mini cart re-reading the
 * Store API — so there is a real wait to cover. The button holds its width
 * while the label is hidden, otherwise the layout jumps as it swaps.
 */
.single_add_to_cart_button.oo-is-loading,
.wc-block-components-product-button .wc-block-components-product-button__button.oo-is-loading {
	position: relative;
	color: transparent !important;
	pointer-events: none;
}
.single_add_to_cart_button.oo-is-loading::after,
.wc-block-components-product-button__button.oo-is-loading::after {
	content: "";
	position: absolute;
	inset-block-start: 50%;
	inset-inline-start: 50%;
	inline-size: 1.1rem;
	block-size: 1.1rem;
	margin-block-start: -.55rem;
	margin-inline-start: -.55rem;
	border: 2px solid currentColor;
	border-top-color: var(--oo-on-primary, #fff);
	border-radius: 50%;
	/* currentColor is transparent above, so the ring reads as a single arc. */
	border-inline-start-color: var(--oo-on-primary, #fff);
	opacity: .9;
	animation: oo-spin .6s linear infinite;
}
@keyframes oo-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
	.single_add_to_cart_button.oo-is-loading::after,
	.wc-block-components-product-button__button.oo-is-loading::after {
		animation-duration: 1.6s;
	}
}

/* ---------- Shop filter sidebar ----------
 * The filters only became visible once patterns stopped losing their block
 * context (inc/pattern-context.php), so this is the first styling they get.
 *
 * Woo lays the price slider out as
 *   grid-template-columns: auto 1fr auto
 * with the min input in the first track and the max in the third. An `auto`
 * track is sized by its content, and the content here is a Persian currency
 * string — "۶۸.۴۴۰.۰۰۰ تومان" is sixteen glyphs. Each track resolved to 185px,
 * so 393px of tracks sat inside a 240px column and the max input spilled out
 * over the product grid. Same shape as Woo's float/percentage widths in a
 * grid: an intrinsic width that never agreed to the track it was given.
 *
 * Clamping the tracks to minmax(0, 1fr) stops the overflow but leaves ~108px
 * per input, which truncates the price — worse than useless on a filter. In
 * the sidebar the pair is stacked instead, so each input gets the full width.
 * Below the column breakpoint the sidebar is full width and Woo's own
 * side-by-side layout is fine, so this is scoped to the width where it bites.
 */
.oo-filters .wc-block-product-filter-price-slider__content {
	/* Belt and braces: an fr track floors at min-content without this, which
	   is what let the inputs push the grid wider than its container. */
	grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
}

.oo-filters .wc-block-product-filter-price-slider__content .text,
.oo-filters .wc-block-product-filter-price-slider__content input {
	min-inline-size: 0;
	inline-size: 100%;
	/* Woo leaves these at the UA default content-box, so the padding below
	   would otherwise be added outside the 100% and overflow again. */
	box-sizing: border-box;
}

@media (min-width: 782px) {
	.oo-filters .wc-block-product-filter-price-slider__content {
		grid-template-areas:
			"price-slider"
			"left-input"
			"right-input";
		grid-template-columns: minmax(0, 1fr);
		row-gap: var(--wp--preset--spacing--20);
	}
}

/* Woo ships these as bare inputs; match the pill fields used at checkout.
 *
 * font-family: inherit is not cosmetic here. The digits in these fields are
 * Latin in the HTML — nothing server-side converts them, and the price filter
 * is no exception. They read as Persian everywhere else because the face is
 * IRANYekanX *FaNum*, which maps the Latin digit glyphs to Persian ones. An
 * unstyled input falls back to the UA font (Arial here), so it was the one
 * place on the page showing "4.900.000" next to the catalogue's "۲۴.۲۲۵.۰۰۰".
 */
.oo-filters .wc-block-product-filter-price-slider__content input[type="text"] {
	padding-block: .4rem;
	padding-inline: .7rem;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--xs);
	color: var(--wp--preset--color--contrast);
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--pill);
	text-align: center;
}

/* Separate one filter from the next without a divider on the last. */
.oo-filters .wp-block-woocommerce-product-filter-price,
.oo-filters .wp-block-woocommerce-product-filter-attribute,
.oo-filters .wp-block-woocommerce-product-filter-status {
	padding-block-end: var(--wp--preset--spacing--40);
	border-block-end: 1px solid var(--wp--preset--color--line);
}

.oo-filters .wp-block-woocommerce-product-filter-status {
	border-block-end: 0;
}

/* ---------- Category tiles: horizontal scroller on mobile ----------
 * Six circular tiles wrapped onto three rows on a phone, which pushed
 * everything below them off the first screen. A single scrolling row keeps
 * the section one screen tall and makes "there is more" obvious.
 *
 * Native overflow scrolling, deliberately: no scroll maths. Under RTL the
 * first item sits at the right and scrollLeft runs negative, so a scripted
 * carousel has to work in measured deltas — the browser already gets this
 * right on its own, and a CSS-only scroller cannot regress it.
 */
@media (max-width: 600px) {
	.oo-cats {
		display: flex;
		justify-content: flex-start;
		overflow-x: auto;
		overscroll-behavior-inline: contain;
		scroll-snap-type: x proximity;
		/* Bleed to the screen edges so a partial tile shows at the cut,
		   which is what signals the row scrolls.
		   !important because the tiles are alignwide, and core centres
		   alignwide children with `margin-left/right: auto !important` —
		   a plain logical margin loses to it and the bleed silently
		   does nothing. */
		margin-inline: calc(-1 * var(--wp--custom--container--gutter)) !important;
		padding-inline: var(--wp--custom--container--gutter);
		/* Room for the focus ring on the last tile. */
		padding-block-end: var(--wp--preset--spacing--20);
		scrollbar-width: none;
	}

	.oo-cats::-webkit-scrollbar { display: none; }

	.oo-cat {
		flex: 0 0 var(--oo-cat-size, 132px);
		scroll-snap-align: center;
	}
}

/* ---------- Feature row ----------
 * Rendered by offlineops/features from Store Settings. auto-fit for the same
 * reason as the category tiles: two features centre rather than leaving a
 * third cell empty, and the row collapses to one column on a phone.
 */
.oo-features {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
	gap: var(--wp--preset--spacing--50) var(--wp--preset--spacing--40);
}

.oo-feature { text-align: center; }

.oo-feature__icon {
	display: block;
	inline-size: 2.25rem;
	block-size: 2.25rem;
	margin-inline: auto;
	margin-block-end: var(--wp--preset--spacing--30);
	color: var(--wp--preset--color--primary);
}

.oo-feature__title {
	margin: 0;
	font-size: var(--wp--preset--font-size--lg);
	line-height: 1.45;
}

.oo-feature__text {
	margin-block: var(--wp--preset--spacing--20) 0;
	font-size: var(--wp--preset--font-size--sm);
	color: var(--wp--preset--color--muted);
}

/* ---------- Product rows as sliders ----------
 * The home page rows scroll sideways instead of wrapping. The track shows
 * 4.3 cards on purpose: the fractional card is the affordance — a row of
 * exactly four looks complete and nobody tries to scroll it.
 *
 * Native overflow scrolling, like the hero and the category tiles. Under RTL
 * the browser already starts the track at the right and runs scrollLeft
 * negative; anything doing its own sign maths gets this wrong, so the arrows
 * in product-row.js scroll by a measured delta rather than an absolute offset.
 *
 * The arrows are a progressive enhancement injected by that script. Without
 * JavaScript the row is still a perfectly good scroller — it just scrolls by
 * swipe, trackpad, scrollbar and keyboard instead.
 */
.oo-row .wc-block-product-template {
	--oo-row-n: 4.3;
	--oo-row-gap: var(--wp--preset--spacing--40);

	display: flex;
	flex-wrap: nowrap;
	gap: var(--oo-row-gap);
	/* Woo's displayLayout emits a grid; this row is a flex track instead. */
	grid-template-columns: none;
	overflow-x: auto;
	overscroll-behavior-inline: contain;
	scroll-snap-type: x proximity;
	/* Room for the card's hover lift and shadow, which would otherwise be
	   clipped by the scroll container. */
	padding-block: 4px 14px;
	scrollbar-width: none;
}

.oo-row .wc-block-product-template::-webkit-scrollbar { display: none; }

.oo-row .wc-block-product-template > li {
	flex: 0 0 calc(
		(100% - (var(--oo-row-n) - 1) * var(--oo-row-gap)) / var(--oo-row-n)
	);
	scroll-snap-align: start;
	/* Woo sets a width on the grid child; in a flex track it fights the basis. */
	inline-size: auto;
	max-inline-size: none;
}

@media (max-width: 1100px) { .oo-row .wc-block-product-template { --oo-row-n: 3.3; } }
@media (max-width: 782px)  { .oo-row .wc-block-product-template { --oo-row-n: 2.3; } }
@media (max-width: 560px)  { .oo-row .wc-block-product-template { --oo-row-n: 1.4; } }

/* Arrows sit above the row at the inline end, clear of the cards. Overlaying
   them on the track would collide with the card's own hover panel. */
.oo-row__nav {
	display: flex;
	gap: .4rem;
	justify-content: flex-end;
	margin-block-end: var(--wp--preset--spacing--30);
}

.oo-row__arrow {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	inline-size: 2rem;
	block-size: 2rem;
	padding: 0;
	color: var(--wp--preset--color--contrast);
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--pill);
	cursor: pointer;
	transition:
		background-color var(--wp--custom--transition--fast) var(--wp--custom--transition--ease),
		border-color     var(--wp--custom--transition--fast) var(--wp--custom--transition--ease);
}

.oo-row__arrow svg { inline-size: .85rem; block-size: .85rem; }

@media (hover: hover) {
	.oo-row__arrow:not(:disabled):hover {
		background: var(--wp--preset--color--primary);
		border-color: var(--wp--preset--color--primary);
		color: var(--oo-on-primary, #fff);
	}
}

/* Disabled rather than hidden: the pair keeps its position, so the row does
   not shift when you reach either end. */
.oo-row__arrow:disabled { opacity: .35; cursor: default; }

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