/**
 * Société Jersiaise, shop components
 *
 * Every component the shop shares: buttons, links, form fields, notices,
 * prices, product cards, the archive shell, filters and pagination. Single
 * product additions live in product.css, cart and checkout in checkout.css.
 *
 * No raw colour, size, spacing or radius value appears here. tokens.css is the
 * only file allowed one.
 *
 * SPECIFICITY
 *
 * Everything is scoped under .sj-shop. That is not cosmetic namespacing, it is
 * load bearing.
 *
 * The Elementor global kit is post 8, and it emits site wide rules of the form
 * .elementor-kit-8 button, .elementor-kit-8 input and .elementor-kit-8 h2, at
 * specificity (0,1,1). Those rules reach shop pages because the header and
 * footer are still Elementor templates. A bare .sj-btn is (0,1,0) and loses.
 *
 * .sj-shop .sj-btn is (0,2,0), which wins cleanly and costs nothing. It also
 * means no component needs a doubled class or an !important, and the shop CSS
 * physically cannot leak onto an Elementor built page.
 *
 * The one requirement this places on markup: every shop template must render
 * inside the .sj-shop wrapper. inc/setup.php guarantees that on WooCommerce
 * pages, and template-styleguide.php carries the class for the same reason, so
 * the style guide renders components through the exact same cascade as
 * production.
 *
 * @package sj-child
 */

/* -------------------------------------------------------------------------
 * Wrapper
 * ---------------------------------------------------------------------- */

/**
 * The shop sits on a tinted ground, not on white.
 *
 * Every surface above it is white: product tiles, the filter bar, dropdown
 * panels. That is what gives the page definition, and it is why a white card on
 * a white page read as nothing at all. Three light steps are in play:
 *
 *   --sj-color-surface-tint        the ground
 *   --sj-color-surface             tiles and panels
 *   --sj-color-border              the hairline between them
 */

.sj-shop {
	font-family: var(--sj-font);
	font-size: var(--sj-text-sm);
	line-height: var(--sj-leading-body);
	letter-spacing: var(--sj-tracking-body);
	color: var(--sj-color-ink-body);
	background-color: var(--sj-color-surface-tint);
}

.sj-shop *,
.sj-shop *::before,
.sj-shop *::after {
	box-sizing: border-box;
}

/**
 * The hidden attribute has to be reasserted, at a specificity that cannot lose.
 *
 * The user agent rule is [hidden] { display: none } at (0,1,0). Any component
 * setting its own display beats it, and .sj-btn sets inline-flex at (0,2,0).
 * The symptom is that element.hidden = true in JavaScript appears to do
 * nothing, which breaks the filter drawer and strands the no-JavaScript submit
 * button on screen.
 *
 * The attribute is doubled rather than merely scoped. .sj-shop [hidden] is also
 * (0,2,0), which ties with .sj-shop .sj-btn and is then decided by source
 * order, so it only works from the bottom of the file and quietly breaks the
 * first time a rule is added after it. (0,3,0) is order independent.
 */

.sj-shop [hidden][hidden] {
	display: none;
}

/**
 * One container, used by every shop template and by the breadcrumb, so the page
 * has a single left edge. Previously the breadcrumb ran full bleed while the
 * content sat in a 1220px box, giving the archive three different left edges.
 */

.sj-shop__container {
	inline-size: 100%;
	max-inline-size: var(--sj-container-wide);
	margin-inline: auto;
	padding-inline: var(--sj-gutter);
}

/* Prose and forms stay narrow, whatever the shell does. */

.sj-shop__container--narrow {
	max-inline-size: var(--sj-container);
}

/* The single product page is narrower than the archive: one item, not 226. */

.sj-shop__container--product {
	max-inline-size: var(--sj-container-product);
}

/**
 * Visually hidden, but still announced. Used for filter legends and live
 * regions that would otherwise duplicate a visible label.
 */

.sj-u-visually-hidden {
	position: absolute;
	inline-size: var(--sj-border-width);
	block-size: var(--sj-border-width);
	padding: 0;
	margin: calc(var(--sj-border-width) * -1);
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* -------------------------------------------------------------------------
 * Breadcrumb
 *
 * Rendered by WooCommerce, wrapped by sj_breadcrumb_defaults in inc/woo-hooks.php.
 * ---------------------------------------------------------------------- */

.sj-shop .sj-breadcrumb {
	padding-block: var(--sj-space-4);
	font-size: var(--sj-text-3xs);
	letter-spacing: var(--sj-tracking-none);
	color: var(--sj-color-ink-body);
}

.sj-shop .sj-breadcrumb a {
	color: var(--sj-color-navy);
	text-decoration: none;
}

.sj-shop .sj-breadcrumb a:hover {
	text-decoration: underline;
	text-underline-offset: var(--sj-border-width-thick);
}

.sj-shop .sj-breadcrumb__sep {
	padding-inline: var(--sj-space-2);
	color: var(--sj-color-ink-muted);
}

/* -------------------------------------------------------------------------
 * Buttons
 *
 * Four treatments, per the style guide: primary, secondary, dark and a text
 * link. One primary per view.
 *
 * Each state is available both as a real pseudo class and as an --is-*
 * modifier, so the style guide can show hover, focus and active side by side
 * without a mouse. The modifiers are part of the component, not style guide
 * furniture.
 * ---------------------------------------------------------------------- */

.sj-shop .sj-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--sj-space-2);
	min-block-size: var(--sj-tap-target);
	min-inline-size: var(--sj-tap-target);
	padding: var(--sj-space-3) var(--sj-space-5);
	border: var(--sj-border-width) solid transparent;
	border-radius: var(--sj-radius-sm);
	font-family: var(--sj-font);
	font-size: var(--sj-text-sm);
	font-weight: var(--sj-weight-bold);
	line-height: var(--sj-leading-normal);
	letter-spacing: var(--sj-tracking-tight);
	text-align: center;
	text-decoration: none;
	text-transform: none;
	white-space: normal;
	cursor: pointer;
	transition: background-color var(--sj-duration-fast) var(--sj-ease),
		border-color var(--sj-duration-fast) var(--sj-ease),
		color var(--sj-duration-fast) var(--sj-ease);
}

.sj-shop .sj-btn:disabled,
.sj-shop .sj-btn--is-disabled,
.sj-shop .sj-btn[aria-disabled="true"] {
	cursor: not-allowed;
	opacity: 0.5;
}

/**
 * Every interactive state is declared explicitly, including the ones we do not
 * change.
 *
 * The Elementor kit styles button, button:hover, button:focus and button:active
 * site wide, and it paints them with the global accent, which on this site is
 * sage green. Anything we leave undeclared falls through to that, which is why
 * the mobile filter buttons were turning green when pressed. Declaring the full
 * set closes the gap rather than chasing each symptom.
 *
 * The focus ring is our token ring, replacing Elementor's, which it suppresses
 * in several places.
 */

.sj-shop .sj-btn:focus,
.sj-shop .sj-btn:focus-visible,
.sj-shop .sj-btn:active,
.sj-shop .sj-facet__toggle:focus,
.sj-shop .sj-facet__toggle:focus-visible,
.sj-shop .sj-facet-toggle:focus,
.sj-shop .sj-facet-toggle:focus-within {
	outline: var(--sj-focus-width) solid var(--sj-focus-color);
	outline-offset: var(--sj-focus-offset);
}

.sj-shop .sj-btn--secondary:focus,
.sj-shop .sj-btn--secondary:focus-visible {
	background-color: var(--sj-color-surface-tint-strong);
	border-color: var(--sj-color-navy);
	color: var(--sj-color-navy);
}

.sj-shop .sj-btn--text:focus,
.sj-shop .sj-btn--text:focus-visible,
.sj-shop .sj-btn--text:active {
	background-color: transparent;
	color: var(--sj-color-navy-deep);
}

/* Primary */

.sj-shop .sj-btn--primary {
	background-color: var(--sj-color-navy);
	border-color: var(--sj-color-navy);
	color: var(--sj-color-ink-inverse);
}

.sj-shop .sj-btn--primary:hover,
.sj-shop .sj-btn--primary.sj-btn--is-hover {
	background-color: var(--sj-color-navy-deep);
	border-color: var(--sj-color-navy-deep);
	color: var(--sj-color-ink-inverse);
}

.sj-shop .sj-btn--primary:active,
.sj-shop .sj-btn--primary.sj-btn--is-active {
	background-color: var(--sj-color-navy-deep);
	border-color: var(--sj-color-navy-deep);
}

/* Secondary */

.sj-shop .sj-btn--secondary {
	background-color: transparent;
	border-color: var(--sj-color-navy);
	color: var(--sj-color-navy);
}

.sj-shop .sj-btn--secondary:hover,
.sj-shop .sj-btn--secondary.sj-btn--is-hover {
	background-color: var(--sj-color-navy);
	color: var(--sj-color-ink-inverse);
}

.sj-shop .sj-btn--secondary:active,
.sj-shop .sj-btn--secondary.sj-btn--is-active {
	background-color: var(--sj-color-navy-deep);
	border-color: var(--sj-color-navy-deep);
	color: var(--sj-color-ink-inverse);
}

/* Dark */

.sj-shop .sj-btn--dark {
	background-color: var(--sj-color-ink-strong);
	border-color: var(--sj-color-ink-strong);
	color: var(--sj-color-ink-inverse);
}

.sj-shop .sj-btn--dark:hover,
.sj-shop .sj-btn--dark.sj-btn--is-hover {
	background-color: var(--sj-color-ink);
	border-color: var(--sj-color-ink);
	color: var(--sj-color-ink-inverse);
}

/* Text */

.sj-shop .sj-btn--text {
	min-inline-size: 0;
	padding-inline: 0;
	background-color: transparent;
	border-color: transparent;
	color: var(--sj-color-navy);
}

.sj-shop .sj-btn--text:hover,
.sj-shop .sj-btn--text.sj-btn--is-hover {
	color: var(--sj-color-navy-deep);
	text-decoration: underline;
}

/* Full width, used on the mobile filter panel and in narrow cards. */

.sj-shop .sj-btn--block {
	inline-size: 100%;
}

/**
 * Forced focus ring.
 *
 * :focus-visible only paints after real keyboard input, so the style guide
 * cannot demonstrate it. This modifier draws the identical ring on demand.
 */

.sj-shop .sj-btn--is-focus {
	outline: var(--sj-focus-width) solid var(--sj-focus-color);
	outline-offset: var(--sj-focus-offset);
}

/* -------------------------------------------------------------------------
 * Links in body copy
 *
 * Underlined by default. Colour alone fails WCAG 1.4.1, and navy against the
 * body grey is not a sufficient distinguisher.
 * ---------------------------------------------------------------------- */

.sj-shop .sj-link {
	color: var(--sj-color-navy);
	text-decoration: underline;
	text-underline-offset: var(--sj-border-width-thick);
	text-decoration-thickness: var(--sj-border-width);
	transition: color var(--sj-duration-fast) var(--sj-ease);
}

.sj-shop .sj-link:hover,
.sj-shop .sj-link.sj-link--is-hover {
	color: var(--sj-color-navy-deep);
	text-decoration-thickness: var(--sj-border-width-thick);
}

/* -------------------------------------------------------------------------
 * Form fields
 *
 * Critical for checkout. Real visible labels, errors associated by
 * aria-describedby, never colour alone, token focus ring, 44px minimum.
 * ---------------------------------------------------------------------- */

.sj-shop .sj-field {
	display: flex;
	flex-direction: column;
	gap: var(--sj-space-2);
	margin-block-end: var(--sj-space-5);
}

.sj-shop .sj-field__label {
	font-size: var(--sj-text-2xs);
	font-weight: var(--sj-weight-bold);
	line-height: var(--sj-leading-normal);
	letter-spacing: var(--sj-tracking-none);
	color: var(--sj-color-ink);
}

.sj-shop .sj-field__required {
	color: var(--sj-color-error);
}

.sj-shop .sj-field__hint {
	font-size: var(--sj-text-2xs);
	line-height: var(--sj-leading-normal);
	letter-spacing: var(--sj-tracking-none);
	color: var(--sj-color-ink-body);
}

.sj-shop .sj-field__input,
.sj-shop .sj-field__select,
.sj-shop .sj-field__textarea {
	inline-size: 100%;
	min-block-size: var(--sj-tap-target);
	padding: var(--sj-space-2) var(--sj-space-3);
	background-color: var(--sj-color-surface);
	border: var(--sj-border-width) solid var(--sj-color-border);
	border-radius: var(--sj-radius-sm);
	font-family: var(--sj-font);
	font-size: var(--sj-text-sm);
	line-height: var(--sj-leading-normal);
	letter-spacing: var(--sj-tracking-body);
	color: var(--sj-color-ink);
	transition: border-color var(--sj-duration-fast) var(--sj-ease);
}

.sj-shop .sj-field__textarea {
	min-block-size: var(--sj-space-10);
	line-height: var(--sj-leading-body);
	resize: vertical;
}

.sj-shop .sj-field__input:hover,
.sj-shop .sj-field__select:hover,
.sj-shop .sj-field__textarea:hover {
	border-color: var(--sj-color-ink-muted);
}

.sj-shop .sj-field__input::placeholder,
.sj-shop .sj-field__textarea::placeholder {
	color: var(--sj-color-ink-body);
}

/**
 * Error state.
 *
 * The red border is reinforcement, never the message. The message itself is
 * .sj-field__error, and the input points at it with aria-describedby.
 */

.sj-shop .sj-field--error .sj-field__input,
.sj-shop .sj-field--error .sj-field__select,
.sj-shop .sj-field--error .sj-field__textarea {
	border-color: var(--sj-color-error);
	border-inline-start-width: var(--sj-border-width-thick);
}

.sj-shop .sj-field__error {
	display: flex;
	align-items: flex-start;
	gap: var(--sj-space-2);
	font-size: var(--sj-text-2xs);
	font-weight: var(--sj-weight-semibold);
	line-height: var(--sj-leading-normal);
	letter-spacing: var(--sj-tracking-none);
	color: var(--sj-color-error);
}

.sj-shop .sj-field--is-focus .sj-field__input {
	outline: var(--sj-focus-width) solid var(--sj-focus-color);
	outline-offset: var(--sj-focus-offset);
}

/**
 * Checkbox and radio rows.
 *
 * The whole row is the label, so the 44px target covers the text as well as
 * the control itself.
 */

.sj-shop .sj-choice {
	display: flex;
	align-items: center;
	gap: var(--sj-space-3);
	min-block-size: var(--sj-tap-target);
	cursor: pointer;
}

.sj-shop .sj-choice__control {
	flex: none;
	inline-size: var(--sj-space-4);
	block-size: var(--sj-space-4);
	accent-color: var(--sj-color-navy);
	cursor: pointer;
}

.sj-shop .sj-choice__label {
	flex: 1 1 auto;
	font-size: var(--sj-text-2xs);
	line-height: var(--sj-leading-normal);
	letter-spacing: var(--sj-tracking-none);
	color: var(--sj-color-ink);
}

.sj-shop .sj-choice:hover .sj-choice__label {
	color: var(--sj-color-navy);
}

/**
 * Counts sit hard right and quiet. Aligned, tabular and unbracketed they read
 * as a column you can scan; inline in parentheses they read as part of the
 * label and make every row look like a filename.
 */

.sj-shop .sj-choice__count {
	flex: none;
	font-size: var(--sj-text-3xs);
	color: var(--sj-color-ink-muted);
	font-variant-numeric: tabular-nums;
}

.sj-shop .sj-choice__control:checked ~ .sj-choice__label {
	font-weight: var(--sj-weight-semibold);
	color: var(--sj-color-navy);
}

.sj-shop .sj-choice--disabled {
	cursor: not-allowed;
	opacity: 0.45;
}

/* A child category sits in from its parent. Category is the only nested facet. */

.sj-shop .sj-choice--nested {
	padding-inline-start: var(--sj-space-5);
}

/* -------------------------------------------------------------------------
 * Notices
 *
 * Maps WooCommerce success, info and error notices onto the feedback tokens.
 * Tinted background with a solid left border. An element with a single sided
 * border takes no radius, per the style guide.
 * ---------------------------------------------------------------------- */

.sj-shop .sj-notice {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: var(--sj-space-4);
	padding: var(--sj-space-4) var(--sj-space-5);
	margin-block-end: var(--sj-space-5);
	border-inline-start: var(--sj-border-width-thick) solid var(--sj-color-info);
	border-radius: 0;
	background-color: var(--sj-color-info-bg);
	font-size: var(--sj-text-xs);
	line-height: var(--sj-leading-normal);
	color: var(--sj-color-ink);
}

.sj-shop .sj-notice--success {
	border-inline-start-color: var(--sj-color-info);
	background-color: var(--sj-color-info-bg);
}

.sj-shop .sj-notice--error {
	border-inline-start-color: var(--sj-color-error);
	background-color: var(--sj-color-error-bg);
}

.sj-shop .sj-notice--warning {
	border-inline-start-color: var(--sj-color-warning);
	background-color: var(--sj-color-warning-bg);
}

.sj-shop .sj-notice__text {
	margin: 0;
}

.sj-shop .sj-notice__action {
	flex: none;
}

/**
 * WooCommerce's own notices.
 *
 * Styled rather than forked. Woo emits ul.woocommerce-message,
 * ul.woocommerce-error and ul.woocommerce-info from three templates, and every
 * gateway, plugin and validation path in the stack writes into them. Matching
 * the class names here means all of that inherits the house treatment without
 * three more files to maintain against future Woo releases.
 */

.sj-shop .woocommerce-message,
.sj-shop .woocommerce-error,
.sj-shop .woocommerce-info,
.sj-shop .woocommerce-noreviews {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sj-space-3);
	padding: var(--sj-space-4) var(--sj-space-5);
	margin-block: 0 var(--sj-space-5);
	border: 0;
	border-inline-start: var(--sj-border-width-thick) solid var(--sj-color-info);
	border-radius: 0;
	background-color: var(--sj-color-info-bg);
	list-style: none;
	font-size: var(--sj-text-xs);
	line-height: var(--sj-leading-normal);
	letter-spacing: var(--sj-tracking-body);
	color: var(--sj-color-ink);
}

/**
 * The confirmation notice takes the same navy on pale blue as the informational
 * one, by client preference. Errors keep red, because on an error the colour is
 * carrying meaning rather than decoration.
 */

.sj-shop .woocommerce-message {
	border-inline-start-color: var(--sj-color-info);
	background-color: var(--sj-color-info-bg);
}

.sj-shop .woocommerce-error {
	border-inline-start-color: var(--sj-color-error);
	background-color: var(--sj-color-error-bg);
}

.sj-shop .woocommerce-message li,
.sj-shop .woocommerce-error li,
.sj-shop .woocommerce-info li {
	flex: 1 1 auto;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Woo puts its continue and view basket links inside the notice as .button. */

.sj-shop .woocommerce-message .button,
.sj-shop .woocommerce-error .button,
.sj-shop .woocommerce-info .button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	order: 1;
	min-block-size: var(--sj-tap-target-sm);
	padding-inline: var(--sj-space-5);
	border: var(--sj-border-width) solid var(--sj-color-navy);
	border-radius: var(--sj-radius-sm);
	background-color: transparent;
	font-family: var(--sj-font);
	font-size: var(--sj-text-3xs);
	font-weight: var(--sj-weight-bold);
	letter-spacing: var(--sj-tracking-none);
	text-decoration: none;
	white-space: nowrap;
	color: var(--sj-color-navy);
	transition: background-color var(--sj-duration-fast) var(--sj-ease),
		color var(--sj-duration-fast) var(--sj-ease);
}

.sj-shop .woocommerce-message .button:hover,
.sj-shop .woocommerce-error .button:hover,
.sj-shop .woocommerce-info .button:hover {
	background-color: var(--sj-color-navy);
	color: var(--sj-color-ink-inverse);
}

/* Woo's default tick and cross glyphs, which do not match anything here. */

.sj-shop .woocommerce-message::before,
.sj-shop .woocommerce-error::before,
.sj-shop .woocommerce-info::before {
	content: none;
}

/* -------------------------------------------------------------------------
 * Price
 * ---------------------------------------------------------------------- */

.sj-shop .sj-price {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: var(--sj-space-2);
	font-size: var(--sj-text-sm);
	font-weight: var(--sj-weight-semibold);
	line-height: var(--sj-leading-normal);
	letter-spacing: var(--sj-tracking-body);
	color: var(--sj-color-navy);
}

.sj-shop .sj-price__original {
	font-weight: var(--sj-weight-regular);
	color: var(--sj-color-ink-body);
	text-decoration: line-through;
}

/**
 * Sale flag. Carries text as well as colour, so the saving is not signalled by
 * colour alone.
 */

.sj-shop .sj-price__badge {
	padding: var(--sj-space-1) var(--sj-space-2);
	border-radius: var(--sj-radius-pill);
	background-color: var(--sj-color-success-bg);
	font-size: var(--sj-text-3xs);
	font-weight: var(--sj-weight-bold);
	letter-spacing: var(--sj-tracking-none);
	text-transform: uppercase;
	color: var(--sj-color-success);
}

/* -------------------------------------------------------------------------
 * Product card
 *
 * The catalogue is 225 books out of 226 products, so the card is built as a
 * shelf rather than a tile.
 *
 * Covers are bottom aligned to a common baseline inside a fixed height frame,
 * each keeping its own proportions and carrying its own shadow. A row then
 * reads the way a shelf does, with tall and short spines sharing a line. The
 * alternative, forcing every cover into an identical box, either crops the
 * title off a portrait cover or strands it in dead space, and it makes the page
 * look like a grid of placeholders.
 *
 * The title is the link, not the whole card. That keeps the accessible name
 * clean and leaves the text selectable.
 * ---------------------------------------------------------------------- */

/**
 * Measured across all 299 catalogue images: 297 are artwork to the edge, only
 * 2 sit on a white background, and 265 of 299 are portrait. So the card ground
 * is white, covers keep their own proportions, and the shadow reads as the edge
 * of the book rather than outlining a photograph's white margin.
 */

.sj-shop .sj-product-card {
	display: flex;
	flex-direction: column;
}

/**
 * The shelf. align-items: flex-end is what puts every cover on one baseline.
 * No background, no radius, no border: the cover is the object, the page is
 * the surface it sits on.
 */

.sj-shop .sj-product-card__media {
	position: relative;
	display: block;
	aspect-ratio: var(--sj-ratio-product);
	max-block-size: var(--sj-cover-max);
	margin-block-end: var(--sj-space-4);
	background-color: var(--sj-color-surface);
}

/**
 * Contained, never cropped. The image keeps its intrinsic proportions and is
 * bounded by the frame on both axes, so a 0.54 ratio paperback and a 2.14 ratio
 * folded map both fit without either being cut. object-fit is declared as well
 * as the max sizes, so the behaviour holds if a fixed size is ever set on it.
 */

/**
 * Four classes, deliberately.
 *
 * A site-wide Code Snippets rule, ".woocommerce ul.products li.product a img",
 * forces height: 240px and object-fit: cover on every catalogue image. It is
 * (0,3,3) and it is left over from the Elementor shop this build replaces. Any
 * selector of ours below (0,4,0) loses to it and the covers come out cropped.
 *
 * The snippet should be deleted, but site-wide CSS lives in Code Snippets Pro
 * and is out of this repo's scope. See docs/SETTINGS.md.
 */

.sj-shop .sj-product-card__media .sj-product-card__image.sj-product-card__image {
	inline-size: 100%;
	block-size: 100%;
	max-block-size: none;
	object-fit: contain;
	object-position: center center;
}

/**
 * No hover treatment on the cover. The tile's own border and shadow already
 * signal that the card is interactive, and moving the artwork underneath the
 * pointer adds nothing but noise on a page showing twenty five of them.
 */

/**
 * Products with no image get a proportioned blank rather than nothing, so the
 * baseline still reads and the row does not collapse.
 */

.sj-shop .sj-product-card__placeholder {
	display: flex;
	align-items: center;
	justify-content: center;
	inline-size: 100%;
	block-size: 100%;
	padding: var(--sj-space-4);
	background-color: var(--sj-color-surface-tint);
	font-size: var(--sj-text-3xs);
	letter-spacing: var(--sj-tracking-none);
	text-align: center;
	color: var(--sj-color-ink-muted);
}

.sj-shop .sj-product-card__flag {
	position: absolute;
	inset-block-start: 0;
	inset-inline-start: 0;
	padding: var(--sj-space-1) var(--sj-space-2);
	background-color: var(--sj-color-ink);
	font-size: var(--sj-text-3xs);
	font-weight: var(--sj-weight-bold);
	line-height: var(--sj-leading-normal);
	letter-spacing: var(--sj-tracking-caps);
	text-transform: uppercase;
	color: var(--sj-color-ink-inverse);
}

.sj-shop .sj-product-card__flag--sale {
	background-color: var(--sj-color-success);
}

.sj-shop .sj-product-card__flag--sold-out {
	background-color: var(--sj-color-ink-body);
}

.sj-shop .sj-product-card__body {
	display: flex;
	flex-direction: column;
	gap: var(--sj-space-1);
}

/**
 * Card titles are set at body size in ink, not at h4 size in navy. Repeated
 * twenty four times down a page, a large bold navy title stops being a title
 * and becomes texture. The cover is the thing doing the selling here.
 */

.sj-shop .sj-product-card__title {
	font-size: var(--sj-text-xs);
	font-weight: var(--sj-weight-bold);
	line-height: var(--sj-leading-snug);
	letter-spacing: var(--sj-tracking-none);
	text-transform: none;
	color: var(--sj-color-ink);
	text-wrap: pretty;
}

.sj-shop .sj-product-card__link {
	color: inherit;
	text-decoration: none;
}

.sj-shop .sj-product-card__link:hover {
	color: var(--sj-color-navy);
	text-decoration: none;
}

.sj-shop .sj-product-card__meta {
	font-size: var(--sj-text-3xs);
	line-height: var(--sj-leading-normal);
	letter-spacing: var(--sj-tracking-none);
	color: var(--sj-color-ink-body);
}

/**
 * Wraps rather than clips.
 *
 * At two columns on a 390px screen the card's inner width is about 139px, and
 * price plus button needs about 161px. Without wrapping, the button runs out of
 * the card and the label is cut in half.
 */

.sj-shop .sj-product-card__foot {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--sj-space-2);
	padding-block-start: var(--sj-space-2);
}

.sj-shop .sj-product-card__foot .sj-btn {
	flex: 0 1 auto;
}

.sj-shop .sj-product-card__foot .sj-price {
	font-size: var(--sj-text-2xs);
	font-weight: var(--sj-weight-semibold);
	color: var(--sj-color-ink);
}

/**
 * The card action is deliberately quiet. Twenty four outlined buttons down a
 * page compete with the covers and with each other, and there is only one
 * primary action per view. It still meets the 44px target: the height comes
 * from padding, not from the type size.
 */

.sj-shop .sj-product-card__foot .sj-btn {
	min-inline-size: 0;
	min-block-size: var(--sj-tap-target-sm);
	padding-block: var(--sj-space-1);
	padding-inline: var(--sj-space-5);
	font-size: var(--sj-text-3xs);
	letter-spacing: var(--sj-tracking-none);
	text-transform: none;
	white-space: nowrap;
}

/**
 * A hairline rather than a navy outline. Twenty four navy boxes read as the
 * loudest thing on the page, above the covers they are meant to be selling.
 * The border only earns its colour on hover, when the action is actually being
 * considered.
 */

.sj-shop .sj-product-card__foot .sj-btn--secondary {
	border-color: var(--sj-color-border);
}

.sj-shop .sj-product-card__foot .sj-btn--secondary:hover {
	border-color: var(--sj-color-navy);
}

.sj-shop .sj-product-card--sold-out .sj-product-card__image {
	opacity: 0.5;
	filter: saturate(0.4);
}

/* -------------------------------------------------------------------------
 * Product grid
 *
 * Explicit column counts rather than an auto-fill minimum, so the number of
 * books per row is a deliberate decision at each breakpoint instead of a side
 * effect of a magic pixel width. Five across at the widest, which is the
 * density a specialist bookseller wants.
 *
 * align-items: start is load bearing. Stretching every card to the height of
 * the tallest in its row, then pushing the price to the bottom, opens a chasm
 * of empty space under any card with a short title. Natural heights put the
 * price directly under the author where it belongs, and the covers still align
 * because the cover frame is a fixed height.
 * ---------------------------------------------------------------------- */

.sj-shop .sj-product-grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--sj-space-4);
	align-items: start;
	padding: 0;
	margin: 0;
	list-style: none;
}

/**
 * Rows align across the grid, without truncating a single title.
 *
 * Each item is a subgrid spanning four rows, so cover, title, author and price
 * share a baseline with every other card in the row. The alternative is either
 * stretching cards and opening a chasm of white under the short ones, or
 * letting them run ragged so no two prices line up. Both look like an accident.
 *
 * Browsers without subgrid fall back to the natural flow above, which is
 * untidy but not broken.
 */

/**
 * The grid item is the card box, not the article inside it.
 *
 * The box has to be the subgrid item, because an element set to display:
 * contents has no box to border. So the li carries the border, padding and
 * background, and the article collapses into it.
 */

.sj-shop .sj-product-grid__item {
	display: flex;
	flex-direction: column;
	padding: var(--sj-space-3);
	border: var(--sj-border-width) solid var(--sj-color-border);
	border-radius: var(--sj-radius-lg);
	background-color: var(--sj-color-surface);
	transition: border-color var(--sj-duration-fast) var(--sj-ease),
		box-shadow var(--sj-duration-fast) var(--sj-ease);
}

/* No resting shadow. The tile is defined by the ground behind it, not by lift. */

.sj-shop .sj-product-grid__item:hover {
	border-color: var(--sj-color-ink-muted);
	box-shadow: var(--sj-shadow-md);
}

@supports (grid-template-rows: subgrid) {

	.sj-shop .sj-product-grid__item {
		display: grid;
		grid-row: span 4;
		grid-template-rows: subgrid;
		gap: 0;
	}

	.sj-shop .sj-product-grid__item .sj-product-card {
		display: contents;
	}
}

@media (min-width: 48rem) {

	.sj-shop .sj-product-grid {
		grid-template-columns: repeat(3, minmax(0, 1fr));
		gap: var(--sj-space-5);
	}

	.sj-shop .sj-product-grid__item {
		padding: var(--sj-space-4);
	}
}

@media (min-width: 64rem) {

	.sj-shop .sj-product-grid {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}

@media (min-width: 80rem) {

	.sj-shop .sj-product-grid {
		grid-template-columns: repeat(5, minmax(0, 1fr));
		gap: var(--sj-space-5);
	}
}

/* -------------------------------------------------------------------------
 * Archive shell
 * ---------------------------------------------------------------------- */

.sj-shop .sj-archive {
	padding-block: var(--sj-space-7) var(--sj-section-y);
}

/**
 * Title left, breadcrumb right, on one line. Previously the breadcrumb sat in a
 * band of its own above the heading and the two together left a large empty
 * area before any product appeared.
 */

.sj-shop .sj-archive__header {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--sj-space-3);
	margin-block-end: var(--sj-space-4);
}

.sj-shop .sj-archive__header .sj-breadcrumb {
	padding-block: 0;
	margin-inline-start: auto;
	text-align: end;
}

/**
 * The archive h1 is set at h2 size. At the h1 clamp it runs to 60px, which on a
 * two word heading like "Shop all" leaves a band of empty page above a grid
 * that is the actual content. Uppercase is retained, so the house rule that h1
 * is the one capitalised heading still reads.
 */

.sj-shop .sj-archive__title {
	margin-block-end: var(--sj-space-2);
	text-wrap: pretty;
	font-size: var(--sj-text-2xl);
	line-height: var(--sj-leading-tight);
	letter-spacing: var(--sj-tracking-caps);
}

.sj-shop .sj-archive__intro {
	max-inline-size: var(--sj-container-narrow);
	margin: 0;
}

.sj-shop .sj-archive__toolbar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--sj-space-3);
	padding-block-end: var(--sj-space-3);
	margin-block-end: var(--sj-space-5);
	border-block-end: var(--sj-border-width) solid var(--sj-color-border);
}

.sj-shop .sj-archive__count {
	margin: 0;
	font-size: var(--sj-text-3xs);
	letter-spacing: var(--sj-tracking-none);
	color: var(--sj-color-ink-body);
}

.sj-shop .sj-archive__empty {
	padding-block: var(--sj-space-8);
	text-align: center;
}

.sj-shop .sj-archive__empty-title {
	margin-block-end: var(--sj-space-3);
}

/**
 * Dimmed while a filter request is in flight. The grid stays in place so the
 * page does not jump, and pointer events are suspended so a second click
 * cannot race the first.
 */

.sj-shop .sj-archive__results {
	transition: opacity var(--sj-duration-fast) var(--sj-ease);
}

.sj-shop .sj-archive__results[aria-busy="true"] {
	opacity: 0.45;
	pointer-events: none;
}

/* -------------------------------------------------------------------------
 * Sort
 * ---------------------------------------------------------------------- */

.sj-shop .sj-sort {
	display: flex;
	align-items: center;
	gap: var(--sj-space-2);
}

.sj-shop .sj-sort__label {
	font-size: var(--sj-text-3xs);
	font-weight: var(--sj-weight-regular);
	letter-spacing: var(--sj-tracking-none);
	white-space: nowrap;
	color: var(--sj-color-ink-body);
}

/**
 * The native select chrome is replaced with our own chevron. A default select
 * is the single most obviously unstyled control on a storefront, and it sits
 * right at the top of the grid where it is impossible to miss.
 */

.sj-shop .sj-sort__select {
	min-block-size: var(--sj-tap-target);
	padding-block: var(--sj-space-2);
	padding-inline: 0 var(--sj-space-5);
	border: 0;
	border-radius: 0;
	background-color: transparent;
	background-image: linear-gradient(45deg, transparent 50%, currentColor 50%),
		linear-gradient(135deg, currentColor 50%, transparent 50%);
	background-position: right var(--sj-space-3) center, right var(--sj-space-2) center;
	background-size: var(--sj-border-width-thick) var(--sj-border-width-thick),
		var(--sj-border-width-thick) var(--sj-border-width-thick);
	background-repeat: no-repeat;
	font-family: var(--sj-font);
	font-size: var(--sj-text-3xs);
	font-weight: var(--sj-weight-semibold);
	letter-spacing: var(--sj-tracking-none);
	color: var(--sj-color-ink);
	cursor: pointer;
	appearance: none;
}

.sj-shop .sj-sort__select:hover {
	color: var(--sj-color-navy);
}

/* -------------------------------------------------------------------------
 * Filter bar
 *
 * A horizontal row of facet dropdowns above the grid, not a sidebar. On a
 * catalogue of 226 covers the sidebar was costing about 300px of a 1600px
 * screen permanently, and the products are the reason anyone is on the page.
 *
 * Each facet is a native details/summary pair, so it opens and closes with no
 * JavaScript at all. filters.js only adds the niceties: close on outside click,
 * close on Escape, and one open at a time.
 * ---------------------------------------------------------------------- */

.sj-shop .sj-filters {
	position: relative;
	z-index: var(--sj-z-dropdown);
}

.sj-shop .sj-filters__bar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sj-space-2);
	padding: var(--sj-space-3) var(--sj-space-5);
	border: var(--sj-border-width) solid var(--sj-color-border);
	border-radius: var(--sj-radius-lg);
	background-color: var(--sj-color-surface);
}

.sj-shop .sj-filters {
	margin-block-end: var(--sj-space-5);
}

/* A quiet label in front of the chips, so the row states what it is. */

.sj-shop .sj-filters__bar-label {
	margin: 0;
	padding-inline-end: var(--sj-space-2);
	font-size: var(--sj-text-3xs);
	font-weight: var(--sj-weight-bold);
	line-height: var(--sj-leading-normal);
	letter-spacing: var(--sj-tracking-caps);
	text-transform: uppercase;
	color: var(--sj-color-ink-muted);
}

.sj-shop .sj-filters__legend {
	font-size: var(--sj-text-3xs);
	letter-spacing: var(--sj-tracking-none);
	color: var(--sj-color-ink-body);
}

/**
 * The panel heading and close button belong to the small screen drawer. On a
 * wide screen the chips are self evident and a second "Filter" title above them
 * is noise, so the head is dropped rather than restyled.
 */

.sj-shop .sj-filters__head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--sj-space-3);
	padding-block-end: var(--sj-space-3);
	margin-block-end: var(--sj-space-3);
	border-block-end: var(--sj-border-width) solid var(--sj-color-ink);
}

/**
 * Type declared here, not left to a .sj-h* utility. A bare utility is (0,1,0)
 * and loses to .elementor-kit-8 h2 at (0,1,1), which renders this at 44px
 * uppercase. Scoped under .sj-shop it is (0,2,0) and wins.
 */

.sj-shop .sj-filters__title {
	margin: 0;
	font-size: var(--sj-text-2xs);
	font-weight: var(--sj-weight-bold);
	line-height: var(--sj-leading-normal);
	letter-spacing: var(--sj-tracking-caps);
	text-transform: uppercase;
	color: var(--sj-color-ink);
}

.sj-shop .sj-filters__actions {
	display: flex;
	flex-direction: column;
	gap: var(--sj-space-2);
	margin-block-start: var(--sj-space-4);
}

@media (min-width: 48rem) {

	.sj-shop .sj-filters__head,
	.sj-shop .sj-filters__actions {
		display: none;
	}
}

/**
 * Catalogue search, pushed to the far end of the row.
 *
 * margin-inline-start: auto rather than a spacer element, so the row still
 * wraps sensibly when the chips run out of space.
 */

.sj-shop .sj-filters__search {
	position: relative;
	display: flex;
	align-items: center;
	flex: 1 1 var(--sj-facet-width);
	max-inline-size: var(--sj-search-width);
	margin-inline-start: auto;
}

.sj-shop .sj-filters__search-input {
	min-block-size: var(--sj-tap-target);
	padding-inline-end: var(--sj-space-8);
	border-radius: var(--sj-radius-sm);
	font-size: var(--sj-text-2xs);
}

.sj-shop .sj-filters__search-submit {
	position: absolute;
	inset-inline-end: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	inline-size: var(--sj-tap-target);
	min-block-size: var(--sj-tap-target);
	padding: 0;
	border: 0;
	border-radius: var(--sj-radius-sm);
	background-color: transparent;
	font-size: var(--sj-text-md);
	color: var(--sj-color-ink-body);
	cursor: pointer;
	transform: rotate(-45deg);
}

.sj-shop .sj-filters__search-submit:hover {
	color: var(--sj-color-navy);
}

@media (max-width: 47.99rem) {

	.sj-shop .sj-filters__search {
		max-inline-size: none;
		margin-inline-start: 0;
	}
}

/* The facet chip */

.sj-shop .sj-facet {
	position: relative;
}

.sj-shop .sj-facet__toggle {
	display: inline-flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--sj-space-2);
	min-block-size: var(--sj-tap-target);
	min-inline-size: var(--sj-facet-width);
	padding-inline: var(--sj-space-4);
	border: var(--sj-border-width) solid var(--sj-color-border);
	border-radius: var(--sj-radius-sm);
	background-color: var(--sj-color-surface);
	font-size: var(--sj-text-2xs);
	font-weight: var(--sj-weight-semibold);
	letter-spacing: var(--sj-tracking-none);
	white-space: nowrap;
	color: var(--sj-color-ink);
	cursor: pointer;
	list-style: none;
	transition: border-color var(--sj-duration-fast) var(--sj-ease),
		background-color var(--sj-duration-fast) var(--sj-ease);
}

.sj-shop .sj-facet__toggle::-webkit-details-marker {
	display: none;
}

.sj-shop .sj-facet__toggle:hover {
	border-color: var(--sj-color-navy);
}

.sj-shop .sj-facet[open] .sj-facet__toggle {
	border-color: var(--sj-color-navy);
	background-color: var(--sj-color-surface-tint);
}

/**
 * Open AND active.
 *
 * The two states are both (0,3,0), so source order decided it and the open rule
 * repainted an active chip's navy ground back to a pale tint while the text
 * stayed white. The chip became unreadable the moment you opened the facet you
 * had already used, which is the common case.
 */

.sj-shop .sj-facet--active[open] .sj-facet__toggle {
	background-color: var(--sj-color-navy-deep);
	border-color: var(--sj-color-navy-deep);
	color: var(--sj-color-ink-inverse);
}

/* A facet with something chosen states it on the chip, not just in the panel. */

.sj-shop .sj-facet--active .sj-facet__toggle {
	border-color: var(--sj-color-navy);
	background-color: var(--sj-color-navy);
	color: var(--sj-color-ink-inverse);
}

.sj-shop .sj-facet__count {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-inline-size: var(--sj-space-4);
	padding-inline: var(--sj-space-1);
	border-radius: var(--sj-radius-pill);
	background-color: var(--sj-color-ink-inverse);
	font-size: var(--sj-text-3xs);
	font-variant-numeric: tabular-nums;
	color: var(--sj-color-navy);
}

.sj-shop .sj-facet__marker {
	font-size: var(--sj-text-3xs);
	transition: transform var(--sj-duration-fast) var(--sj-ease);
}

.sj-shop .sj-facet[open] .sj-facet__marker {
	transform: rotate(180deg);
}

/* The dropdown panel */

.sj-shop .sj-facet__panel {
	position: absolute;
	inset-block-start: calc(100% + var(--sj-space-1));
	inset-inline-start: 0;
	z-index: var(--sj-z-overlay);
	inline-size: max-content;
	min-inline-size: 100%;
	max-inline-size: min(90vw, var(--sj-container-narrow));
	padding: var(--sj-space-3);
	border: var(--sj-border-width) solid var(--sj-color-border);
	border-radius: var(--sj-radius-md);
	background-color: var(--sj-color-surface);
	box-shadow: var(--sj-shadow-md);
}

/* Keep the last chips' panels on screen rather than off the right edge. */

.sj-shop .sj-facet--end .sj-facet__panel {
	inset-inline-start: auto;
	inset-inline-end: 0;
}

.sj-shop .sj-facet__panel fieldset {
	padding: 0;
	margin: 0;
	border: 0;
	min-inline-size: 0;
}

.sj-shop .sj-facet__list {
	padding: 0;
	margin: 0;
	list-style: none;
}

/**
 * Long facets scroll. Author is 168 terms, so the type-to-narrow box above the
 * list is what actually finds one.
 */

.sj-shop .sj-facet__list--scroll {
	max-block-size: var(--sj-space-10);
	overflow-y: auto;
	overscroll-behavior: contain;
}

/* Category is two columns in the panel: 28 terms is a long single list. */

.sj-shop .sj-facet__list--columns {
	column-count: 2;
	column-gap: var(--sj-space-5);
}

.sj-shop .sj-facet__list--columns > li {
	break-inside: avoid;
}

/**
 * Group label: small, bold, letter-spaced, muted. Lifted from the reference
 * build, where it is what separates "this is a group of options" from "this is
 * an option", and it is the piece the previous filter panel was missing.
 */

.sj-shop .sj-facet__group-label {
	display: block;
	margin-block-end: var(--sj-space-2);
	font-size: var(--sj-text-3xs);
	font-weight: var(--sj-weight-bold);
	line-height: var(--sj-leading-normal);
	letter-spacing: var(--sj-tracking-caps);
	text-transform: uppercase;
	color: var(--sj-color-ink-muted);
}

.sj-shop .sj-facet__search {
	margin-block-end: var(--sj-space-2);
}

.sj-shop .sj-facet__empty {
	margin: 0;
	font-size: var(--sj-text-2xs);
	letter-spacing: var(--sj-tracking-none);
	color: var(--sj-color-ink-body);
}

.sj-shop .sj-facet__apply {
	display: flex;
	justify-content: flex-end;
	padding-block-start: var(--sj-space-2);
	margin-block-start: var(--sj-space-2);
	border-block-start: var(--sj-border-width) solid var(--sj-color-border);
}

/* Price range inputs inside a panel */

.sj-shop .sj-filter-price {
	display: flex;
	align-items: flex-end;
	gap: var(--sj-space-3);
}

.sj-shop .sj-filter-price .sj-field {
	flex: 1 1 0;
	margin-block-end: 0;
}

.sj-shop .sj-filter-price .sj-field__input {
	min-inline-size: var(--sj-space-9);
}

/* Availability is a switch, not a dropdown: it has exactly one option. */

.sj-shop .sj-facet-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--sj-space-2);
	min-block-size: var(--sj-tap-target);
	min-inline-size: var(--sj-facet-width);
	padding-inline: var(--sj-space-4);
	border: var(--sj-border-width) solid var(--sj-color-border);
	border-radius: var(--sj-radius-sm);
	background-color: var(--sj-color-surface);
	font-size: var(--sj-text-2xs);
	font-weight: var(--sj-weight-semibold);
	letter-spacing: var(--sj-tracking-none);
	white-space: nowrap;
	color: var(--sj-color-ink);
	cursor: pointer;
}

.sj-shop .sj-facet-toggle:hover {
	border-color: var(--sj-color-navy);
}

.sj-shop .sj-facet-toggle:has(:checked) {
	border-color: var(--sj-color-navy);
	background-color: var(--sj-color-navy);
	color: var(--sj-color-ink-inverse);
}

/* Small screens: the whole bar collapses behind one button. */

/**
 * Small screen filter controls.
 *
 * A light tint rather than a solid, so the control reads as secondary chrome
 * rather than as the page's primary action, and so it can never inherit the
 * Elementor accent.
 */

.sj-shop .sj-filters__toggle,
.sj-shop .sj-filters__close {
	background-color: var(--sj-color-surface-tint-strong);
	border-color: var(--sj-color-border);
	color: var(--sj-color-navy);
}

.sj-shop .sj-filters__toggle:hover,
.sj-shop .sj-filters__toggle:focus,
.sj-shop .sj-filters__toggle:active,
.sj-shop .sj-filters__close:hover,
.sj-shop .sj-filters__close:focus,
.sj-shop .sj-filters__close:active {
	background-color: var(--sj-color-surface-tint-strong);
	border-color: var(--sj-color-navy);
	color: var(--sj-color-navy-deep);
}

.sj-shop .sj-filters__toggle {
	inline-size: 100%;
}

@media (min-width: 48rem) {

	.sj-shop .sj-filters__toggle {
		display: none;
	}
}

@media (max-width: 47.99rem) {

	.sj-shop .sj-filters--drawer .sj-filters__panel {
		position: fixed;
		inset-block: 0;
		inset-inline-start: 0;
		z-index: var(--sj-z-modal);
		inline-size: min(100%, var(--sj-container-narrow));
		padding: var(--sj-space-5);
		overflow-y: auto;
		background-color: var(--sj-color-surface);
		box-shadow: var(--sj-shadow-md);
	}

	.sj-shop .sj-filters__bar {
		flex-direction: column;
		align-items: stretch;
	}

	.sj-shop .sj-facet__panel {
		position: static;
		inline-size: auto;
		max-inline-size: none;
		border: 0;
		box-shadow: none;
		padding-inline: 0;
	}

	.sj-shop .sj-filters__scrim {
		position: fixed;
		inset: 0;
		z-index: var(--sj-z-overlay);
		background-color: var(--sj-color-ink);
		opacity: 0.4;
		border: 0;
	}
}

@media (min-width: 48rem) {

	.sj-shop .sj-filters__close,
	.sj-shop .sj-filters__scrim {
		display: none;
	}
}

/* Active filters */

.sj-shop .sj-active-filters {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sj-space-2);
	margin-block-start: var(--sj-space-3);
}

.sj-shop .sj-active-filters__label {
	font-size: var(--sj-text-3xs);
	letter-spacing: var(--sj-tracking-none);
	color: var(--sj-color-ink-body);
}

.sj-shop .sj-active-filters__item {
	display: inline-flex;
	align-items: center;
	gap: var(--sj-space-2);
	padding: var(--sj-space-1) var(--sj-space-3);
	border: var(--sj-border-width) solid var(--sj-color-navy);
	border-radius: var(--sj-radius-pill);
	background-color: var(--sj-color-surface);
	font-size: var(--sj-text-3xs);
	letter-spacing: var(--sj-tracking-none);
	text-decoration: none;
	color: var(--sj-color-navy);
	transition: background-color var(--sj-duration-fast) var(--sj-ease),
		color var(--sj-duration-fast) var(--sj-ease);
}

.sj-shop .sj-active-filters__item:hover {
	background-color: var(--sj-color-navy);
	color: var(--sj-color-ink-inverse);
}

.sj-shop .sj-active-filters__remove {
	font-weight: var(--sj-weight-bold);
}

/* -------------------------------------------------------------------------
 * Pagination
 * ---------------------------------------------------------------------- */

.sj-shop .sj-pagination {
	margin-block-start: var(--sj-space-7);
}

.sj-shop .sj-pagination__list {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: var(--sj-space-2);
	padding: 0;
	margin: 0;
	list-style: none;
}

.sj-shop .sj-pagination__link {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-inline-size: var(--sj-tap-target);
	min-block-size: var(--sj-tap-target);
	padding-inline: var(--sj-space-2);
	border: var(--sj-border-width) solid var(--sj-color-border);
	border-radius: var(--sj-radius-sm);
	font-size: var(--sj-text-xs);
	font-weight: var(--sj-weight-semibold);
	text-decoration: none;
	color: var(--sj-color-navy);
	transition: background-color var(--sj-duration-fast) var(--sj-ease),
		border-color var(--sj-duration-fast) var(--sj-ease);
}

.sj-shop .sj-pagination__link:hover {
	border-color: var(--sj-color-navy);
	background-color: var(--sj-color-surface-tint);
}

.sj-shop .sj-pagination__link--current {
	background-color: var(--sj-color-navy);
	border-color: var(--sj-color-navy);
	color: var(--sj-color-ink-inverse);
}

.sj-shop .sj-pagination__link--dots {
	border-color: transparent;
	color: var(--sj-color-ink-body);
}
