/*
 * ShopMetro Pre-Order — front-end styles.
 * Everything is scoped under .spo-app so this never leaks into (or is
 * fought by) the active theme's own styles.
 */

.spo-app {
	--spo-green: #17603b;
	--spo-green-2: #0d4b2d;
	--spo-green-bg: #eef4ee;
	--spo-green-border: #cfe3d2;
	--spo-gold: #d4ad2c;
	--spo-cream: #f7f6ef;
	--spo-white: #ffffff;
	--spo-border: #e4e6dc;
	--spo-border-2: #e4e6dc;
	--spo-input-border: #d3d8c9;
	--spo-text: #26342c;
	--spo-text-muted: #778078;
	--spo-text-muted-2: #97a094;
	--spo-text-dark-muted: #46524a;
	--spo-notice-bg: #fdf6e3;
	--spo-notice-border: #ecd9a0;
	--spo-notice-text: #7a5c00;
	--spo-red: #b95d57;
	--spo-red-dark: #713330;
	--spo-red-light: #f6dcda;
	--spo-radius-lg: 12px;
	--spo-radius-md: 8px;
	--spo-radius-sm: 5px;

	font-family: 'Work Sans', -apple-system, BlinkMacSystemFont, sans-serif;
	background: var(--spo-cream);
	color: var(--spo-text);
	font-size: 15px;
	line-height: 1.5;
	-webkit-font-smoothing: antialiased;
}

.spo-app *,
.spo-app *::before,
.spo-app *::after {
	box-sizing: border-box;
}

/*
 * Safety net: several elements here (the modals especially) rely on the
 * plain `hidden` attribute to disappear, but any author rule that sets
 * `display` on the same element at equal specificity (e.g. `.spo-modal {
 * display: flex; }`) wins over the browser default `[hidden] { display:
 * none; }` regardless of source order, since author styles always beat
 * user-agent styles. Most themes happen to carry their own `[hidden]`
 * reset, which is why this doesn't normally show up — but the plugin
 * shouldn't depend on that. This makes `hidden` reliably win on its own.
 */
.spo-app [hidden] {
	display: none !important;
}

.spo-app h1,
.spo-app h2,
.spo-app h3 {
	font-family: 'Fraunces', Georgia, serif;
	margin: 0;
	color: var(--spo-text);
}

.spo-app p {
	margin: 0;
}

.spo-app button {
	font-family: inherit;
	cursor: pointer;
}

.spo-app a {
	color: inherit;
}

.spo-app ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

/*
 * .spo-app.spo-app (the class written twice) is a specificity bump, not a
 * typo: some host themes ship a broad reset like
 * `input[type=email], input[type=text], select, textarea { padding: ...;
 * height: ...; border: ...; }` which has the same specificity as a plain
 * `.spo-app input` rule (one class + one element either way), so the
 * winner becomes whichever stylesheet happens to print later in <head> —
 * on at least one live site that was the theme, silently clobbering our
 * padding/height/border/background here. Repeating the class costs
 * nothing and reliably outranks a single-class or attribute-selector
 * theme rule regardless of load order, without reaching for !important.
 */
.spo-app.spo-app input,
.spo-app.spo-app textarea,
.spo-app.spo-app select {
	font-family: inherit;
	font-size: 14px;
	line-height: 1.4;
	color: var(--spo-text);
}

/*
 * Selects specifically: browsers (Chrome on Windows especially) can clip a
 * <select>'s selected-option text at the top of the box once vertical
 * padding is added, because the native control lays its text out on its
 * own terms rather than following normal CSS box rules. Turning off the
 * native appearance and drawing our own arrow hands the whole box back to
 * plain CSS, so the text centers the way the padding/line-height say it
 * should — this also protects against a host theme's own global `select`
 * rules (e.g. a fixed height shorter than our padding needs) doing the
 * same thing, since box-sizing is border-box everywhere in .spo-app.
 */
.spo-app.spo-app select {
	-webkit-appearance: none;
	-moz-appearance: none;
	appearance: none;
	height: auto;
	min-height: 44px;
	background-color: var(--spo-white);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='%234a4536'%3E%3Cpath d='M5.5 7.5l4.5 5 4.5-5z'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 12px center;
	background-size: 14px;
}

.spo-app.spo-app input:focus,
.spo-app.spo-app textarea:focus,
.spo-app.spo-app select:focus {
	outline: 2px solid #3a9e5f;
	outline-offset: 1px;
}

.spo-step {
	display: none;
}

.spo-step.is-active {
	display: block;
}

.spo-empty {
	max-width: 640px;
	margin: 60px auto;
	padding: 24px;
	text-align: center;
	color: var(--spo-text-muted);
}

/* ---------------------------------------------------------------- */
/* Header                                                            */
/* ---------------------------------------------------------------- */

.spo-header {
	position: sticky;
	top: 0;
	z-index: 40;
	background: var(--spo-white);
	border-bottom: 1px solid var(--spo-border-2);
}

.spo-header__row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 16px 32px;
}

.spo-header__left {
	display: flex;
	align-items: center;
	gap: 20px;
}

.spo-back-link {
	background: none;
	border: none;
	padding: 0;
	font-size: 13px;
	color: var(--spo-green);
	font-weight: 600;
}

.spo-brand {
	display: flex;
	align-items: baseline;
	gap: 10px;
}

.spo-brand__name {
	font-family: 'Fraunces', Georgia, serif;
	font-weight: 700;
	font-size: 22px;
	color: var(--spo-green);
}

.spo-brand__tag {
	font-size: 13px;
	color: var(--spo-text-muted);
}

.spo-badge {
	font-size: 13px;
	color: var(--spo-green);
	background: var(--spo-green-bg);
	border: 1px solid var(--spo-green-border);
	padding: 6px 14px;
	border-radius: 999px;
	white-space: nowrap;
}

/* Pre-order period — plain text under the brand row, not a pill/badge.
   Pickup window is intentionally not duplicated here. */
.spo-header__subtext {
	margin: 0;
	padding: 0 32px 14px;
	font-size: 13px;
	color: var(--spo-text-muted);
}

.spo-nav-row {
	border-top: 1px solid #f0ead9;
}

.spo-nav {
	display: flex;
	gap: 10px;
	flex-wrap: wrap;
	align-items: center;
	padding: 14px 32px;
	max-width: 1280px;
	margin: 0 auto;
}

.spo-nav__label {
	font-size: 12px;
	color: var(--spo-text-muted-2);
	margin-right: 4px;
}

.spo-nav__link {
	border-radius: 999px;
	padding: 9px 16px;
	font-size: 13px;
	font-weight: 600;
	border: 1px solid var(--spo-input-border);
	background: var(--spo-white);
	color: var(--spo-text-dark-muted);
	text-decoration: none;
	white-space: nowrap;
}

.spo-nav__link:hover,
.spo-nav__link:focus-visible {
	border-color: var(--spo-green);
	color: var(--spo-green);
}

/* Mobile "Browse Categories" — a native <details> so it works without JS. */
.spo-mobile-menu {
	display: none;
}

.spo-mobile-menu__summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	list-style: none;
	cursor: pointer;
	background: var(--spo-white);
	border: 1px solid var(--spo-green-border);
	border-radius: var(--spo-radius-md);
	padding: 13px 14px;
	font-size: 13px;
	font-weight: 600;
	color: var(--spo-green);
}

.spo-mobile-menu__summary::-webkit-details-marker {
	display: none;
}

.spo-mobile-menu__summary::marker {
	content: '';
}

.spo-mobile-menu__icon {
	display: inline-flex;
	color: var(--spo-green);
}

.spo-mobile-menu[open] .spo-mobile-menu__summary {
	border-radius: var(--spo-radius-md) var(--spo-radius-md) 0 0;
}

.spo-mobile-menu__list {
	background: var(--spo-white);
	border: 1px solid var(--spo-green-border);
	border-top: none;
	border-radius: 0 0 var(--spo-radius-md) var(--spo-radius-md);
	overflow: hidden;
}

.spo-mobile-menu__item {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 13px 14px;
	border-top: 1px solid #f0ead9;
	text-decoration: none;
	font-size: 14px;
	font-weight: 600;
	color: var(--spo-text);
}

.spo-mobile-menu__count {
	font-size: 12px;
	font-weight: 400;
	color: var(--spo-text-muted-2);
}

/*
 * Compare tray. A plain white strip read as invisible sitting between two
 * white/cream sections of the page, so the tray itself is now tinted with
 * the same pale green used for chips elsewhere, with a solid green top
 * border — it reads as its own distinct panel at a glance instead of
 * blending into the page. Chips flip to white-on-green so they still stand
 * out against the tray's new background. It still sits inline in the page
 * flow (not a floating bottom sheet like the reference's own
 * .compare-panel) since the cart bar already owns that fixed-bottom
 * position and stacking two fixed panels gets messy.
 */
.spo-compare-tray {
	border-top: 2px solid var(--spo-green);
	background: var(--spo-green-bg);
	box-shadow: 0 -6px 20px rgba(20, 46, 32, .12);
}

.spo-compare-tray__row {
	max-width: 1280px;
	margin: 0 auto;
	padding: 10px 32px;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	flex-wrap: wrap;
}

.spo-compare-tray__meta {
	display: flex;
	align-items: center;
	gap: 10px;
	flex-wrap: wrap;
	min-width: 0;
}

.spo-compare-tray__chips {
	display: flex;
	align-items: center;
	gap: 6px;
	flex-wrap: wrap;
}

.spo-compare-tray__label {
	font-size: 13px;
	font-weight: 700;
	color: var(--spo-text);
	white-space: nowrap;
}

.spo-compare-tray__hint {
	font-size: 12px;
	font-weight: 400;
	color: var(--spo-text-muted);
	white-space: nowrap;
}

.spo-chip {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	background: var(--spo-white);
	border: 1px solid var(--spo-green-border);
	border-radius: 6px;
	padding: 3px 4px 3px 10px;
	font-size: 11px;
	color: var(--spo-text);
}

.spo-chip__name {
	white-space: nowrap;
}

.spo-chip__remove {
	flex: 0 0 auto;
	background: none;
	border: none;
	padding: 0 4px;
	color: var(--spo-red-dark);
	font-size: 13px;
	line-height: 1;
}

.spo-compare-tray__actions {
	display: flex;
	gap: 14px;
	align-items: center;
}

.spo-btn-link {
	background: none;
	border: none;
	font-size: 12px;
	color: var(--spo-text-muted);
	text-decoration: underline;
	padding: 0;
}

.spo-btn-compare-now {
	background: var(--spo-green);
	color: var(--spo-white);
	border: none;
	border-radius: var(--spo-radius-sm);
	padding: 9px 16px;
	font-size: 13px;
	font-weight: 700;
}

.spo-btn-compare-now:disabled {
	background: #f3efe3;
	color: #b6ad98;
	cursor: not-allowed;
}

/* Compare "Clear" — a filled red button matching the confirmation modal's
   "Clear all", so the destructive action reads the same everywhere (rather than
   a quiet underlined link next to the solid Compare Now button). */
.spo-btn-compare-clear {
	background: var(--spo-red);
	color: var(--spo-white);
	border: none;
	border-radius: var(--spo-radius-sm);
	padding: 9px 16px;
	font-size: 13px;
	font-weight: 700;
	white-space: nowrap;
}

.spo-btn-compare-clear:hover,
.spo-btn-compare-clear:focus-visible {
	background: var(--spo-red-dark);
}

/* ---------------------------------------------------------------- */
/* Hero + notice                                                     */
/* ---------------------------------------------------------------- */

/*
 * The hero is now purely an uploaded banner image (Pre-Order → Campaigns →
 * (this campaign) → "Banner image") — no overlaid label/headline/
 * description text, and no green fallback block when a campaign hasn't set
 * one yet (it just doesn't render — see front-end.php).
 */
.spo-hero {
	max-width: 1280px;
	margin: 0 auto;
	padding: 24px 32px 0;
}

.spo-hero__banner-image {
	display: block;
	width: 100%;
	max-height: 360px;
	object-fit: cover;
	border-radius: var(--spo-radius-lg);
}

.spo-notice {
	background: var(--spo-notice-bg);
	border: 1px solid var(--spo-notice-border);
	border-radius: var(--spo-radius-md);
	padding: 14px 18px;
	font-size: 13px;
	color: var(--spo-notice-text);
	line-height: 1.5;
}

/* ---------------------------------------------------------------- */
/* Category sections + cards                                        */
/* ---------------------------------------------------------------- */

.spo-section {
	scroll-margin-top: 180px;
	max-width: 1280px;
	margin: 0 auto;
	padding: 36px 32px 0;
}

.spo-section__head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	border-bottom: 1px solid #9ab69e;
	padding-bottom: 7px;
	margin-bottom: 12px;
}

.spo-section__title {
	font: bold 21px 'Fraunces', Georgia, serif;
	font-weight: 700;
	color: var(--spo-text);
}

.spo-section__count {
	font-size: 11px;
	color: var(--spo-text-muted-2);
}

.spo-grid {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 14px;
}

.spo-card {
	background: var(--spo-white);
	border: 1px solid var(--spo-border);
	border-radius: 9px;
	overflow: hidden;
	display: flex;
	flex-direction: column;
}

.spo-card__image {
	aspect-ratio: 1 / 1;
	background: var(--spo-green-bg);
	display: flex;
	align-items: center;
	justify-content: center;
	border-bottom: 1px solid var(--spo-border);
	overflow: hidden;
}

.spo-card__image img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.spo-card__image-placeholder {
	color: #9fb5a2;
	font-size: 12px;
	letter-spacing: .04em;
	text-transform: uppercase;
}

.spo-card__body {
	padding: 12px 13px 14px;
	display: flex;
	flex-direction: column;
	gap: 7px;
	flex-grow: 1;
}

.spo-card__top {
	display: flex;
	justify-content: space-between;
	align-items: flex-start;
	gap: 8px;
}

.spo-card__name {
	font-family: 'Fraunces', Georgia, serif;
	font-size: 16px;
	font-weight: 700;
	line-height: 1.3;
}

.spo-card__price {
	font-family: 'Fraunces', Georgia, serif;
	font-size: 16px;
	font-weight: 700;
	color: var(--spo-green);
	white-space: nowrap;
}

.spo-card__itemcount {
	font-size: 11px;
	color: var(--spo-text-muted);
	margin: 2px 0 0;
}

.spo-card__preview {
	font-size: 11px;
	color: var(--spo-text-muted);
	line-height: 1.5;
	min-height: 33px;
}

.spo-card__actions {
	display: flex;
	gap: 8px;
	align-items: center;
	margin-top: 3px;
}

/*
 * Desktop/tablet: side-by-side row. "See full contents" is the one allowed
 * to give: flex-shrink (with min-width: 0 so the flex default doesn't floor
 * it at its unwrapped text width) and no white-space: nowrap means it wraps
 * to a second line rather than overflowing, if it's ever squeezed. "+
 * Compare" stays fixed-width and nowrap, pushed to the row's right edge via
 * margin-left: auto. Below 760px this row layout is replaced entirely with
 * simple full-width stacked buttons (see the @media (max-width: 760px)
 * block) — a row of shrink/wrap buttons reads as cramped on a narrow 2-up
 * mobile card, so mobile gets its own straightforward layout instead.
 */
.spo-btn-outline {
	flex: 1 1 auto;
	min-width: 0;
	background: var(--spo-white);
	border: 1px solid var(--spo-input-border);
	border-radius: var(--spo-radius-sm);
	padding: 9px 10px;
	font-size: 12px;
	font-weight: 700;
	color: var(--spo-green);
}

.spo-btn-compare {
	flex: 0 0 auto;
	margin-left: auto;
	background: var(--spo-white);
	color: var(--spo-green);
	border: 1px solid var(--spo-input-border);
	border-radius: var(--spo-radius-sm);
	padding: 9px 10px;
	font-size: 12px;
	font-weight: 700;
	white-space: nowrap;
}

.spo-btn-compare.is-active {
	background: var(--spo-green);
	color: var(--spo-white);
	border-color: var(--spo-green);
}

.spo-btn-compare:disabled {
	background: #f3efe3;
	color: #b6ad98;
	border-color: var(--spo-border);
	cursor: not-allowed;
}

.spo-card__qty-wrap {
	margin-top: auto;
	padding-top: 8px;
}

.spo-btn-add {
	width: 100%;
	background: var(--spo-green);
	color: var(--spo-white);
	border: none;
	border-radius: var(--spo-radius-md);
	padding: 10px;
	font-size: 14px;
	font-weight: 700;
}

.spo-qty {
	display: flex;
	align-items: center;
	background: var(--spo-green-bg);
	border-radius: var(--spo-radius-md);
	padding: 6px 10px;
}

/*
 * .spo-app prefix + explicit min-height/min-width/padding resets: a host theme
 * (Flatsome on the live site) styles every <button> with a tall min-height
 * (~2.5em) and wide padding, which inflated these steppers to ~45px squares and
 * squeezed the number between them down to a few pixels wide. A plain
 * `.spo-qty__btn` never set those properties, so the theme's values applied.
 * Prefixing with .spo-app outranks the theme's element selector, and zeroing
 * min-height/min-width/padding here keeps the button exactly the size we ask
 * for regardless of what the theme forces on buttons generally.
 */
.spo-app .spo-qty__btn {
	width: 30px;
	height: 30px;
	min-width: 0;
	min-height: 0;
	padding: 0;
	/* margin:0 — the live theme puts `margin: 0 17px 17px 0` on every button,
	   which spaced the steppers apart and, via the 17px bottom margin, made the
	   whole pill ~17px taller than the buttons. Resetting it is what actually
	   makes the stepper compact; the min-height/padding resets above weren't
	   enough on their own. */
	margin: 0;
	flex: 0 0 auto;
	border-radius: var(--spo-radius-sm);
	border: 1px solid var(--spo-green-border);
	background: var(--spo-white);
	color: var(--spo-green);
	font-size: 16px;
	line-height: 1;
	display: flex;
	align-items: center;
	justify-content: center;
}

/*
 * flex: 1 + text-align: center (rather than relying on justify-content:
 * space-between across the row) keeps the number visually centered between
 * the two +/- buttons regardless of their size — space-between only
 * balances the gaps around this item, which reads as off-center as soon as
 * the buttons shrink on mobile.
 */
.spo-qty__value {
	flex: 1;
	text-align: center;
	font-size: 14px;
	font-weight: 600;
	color: var(--spo-green);
}

/* ---------------------------------------------------------------- */
/* Cart bar                                                          */
/* ---------------------------------------------------------------- */

.spo-cartbar-spacer {
	height: 132px;
}

.spo-cartbar {
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	background: var(--spo-green-2);
	color: var(--spo-white);
	padding: 14px 32px 12px;
	display: flex;
	flex-direction: column;
	gap: 4px;
	box-shadow: 0 -8px 24px rgba(0, 0, 0, .18);
	/*
	 * High enough to sit ABOVE a host theme's own fixed bottom mobile nav
	 * (Flatsome's .smbn-bottom-nav on the live site is z-index: 999) — at the
	 * old z-index: 50 the cart bar rendered behind that nav on phones, hiding
	 * its buttons. The cart only appears once a basket is selected, so covering
	 * the theme nav while the customer is mid-order is the right trade. Kept
	 * below the modals (z-index: 999999) so Quick View / Compare still overlay
	 * the cart bar.
	 */
	z-index: 99990;
}

/* "Clear" — empties the cart. A quiet underlined link in the info column so it
   never competes with the two primary CTAs (Quotation / Continue). */
.spo-cartbar__clear {
	align-self: flex-start;
	background: none;
	border: none;
	padding: 0;
	margin-top: 1px;
	color: #cfe0d2;
	font-size: 12px;
	font-weight: 600;
	text-decoration: underline;
}

.spo-cartbar__clear:hover,
.spo-cartbar__clear:focus-visible {
	color: var(--spo-white);
}

.spo-cartbar__row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
}

.spo-cartbar__info {
	display: flex;
	align-items: center;
	gap: 18px;
}

.spo-cartbar__count {
	font-size: 14px;
	color: #dfe9df;
}

.spo-cartbar__total {
	font-family: 'Fraunces', Georgia, serif;
	font-size: 20px;
	font-weight: 700;
}

.spo-cartbar__cta {
	background: var(--spo-gold);
	color: var(--spo-green-2);
	font-weight: 700;
	font-size: 13px;
	padding: 10px 18px;
	border-radius: var(--spo-radius-sm);
	border: none;
}

.spo-cartbar__actions {
	display: flex;
	align-items: center;
	gap: 10px;
}

.spo-cartbar__secondary {
	background: transparent;
	color: var(--spo-white);
	font-weight: 600;
	font-size: 13px;
	padding: 10px 16px;
	border-radius: var(--spo-radius-sm);
	border: 1.5px solid #b7d0be;
}

/* ---------------------------------------------------------------- */
/* Modals                                                            */
/* ---------------------------------------------------------------- */

.spo-modal {
	position: fixed;
	inset: 0;
	/*
	 * The host theme's own sticky site header/nav is also `position: fixed`
	 * (or sticky) and, on shopmetro.ph, sits at a much higher z-index than
	 * a typical in-page overlay — so at only z-index: 100 the modal's top
	 * edge (close button, top of the image) was rendering *underneath* it,
	 * getting visually clipped by the theme's own nav bar. A very high
	 * z-index guarantees the modal always wins that stack, regardless of
	 * what the active theme does with its own header.
	 */
	z-index: 999999;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 24px;
}

.spo-modal__overlay {
	position: absolute;
	inset: 0;
	background: rgba(26, 20, 10, .45);
	border: none;
	padding: 0;
}

.spo-modal__dialog {
	position: relative;
	background: var(--spo-white);
	border-radius: 18px;
	max-width: 560px;
	width: 100%;
	max-height: 82vh;
	overflow-y: auto;
}

.spo-modal__dialog--wide {
	max-width: 1100px;
	padding: 28px;
}

/* Small confirmation dialog (e.g. Clear pre-order) — a compact card with a
   short message and a cancel/confirm button pair. */
.spo-modal__dialog--confirm {
	max-width: 400px;
	padding: 26px 26px 22px;
}

.spo-confirm-modal__title {
	font-size: 19px;
	font-weight: 700;
	margin-bottom: 8px;
}

.spo-confirm-modal__text {
	font-size: 14px;
	color: var(--spo-text-muted);
	line-height: 1.55;
}

.spo-confirm-modal__actions {
	display: flex;
	justify-content: flex-end;
	gap: 10px;
	margin-top: 22px;
}

.spo-btn-ghost {
	background: var(--spo-white);
	border: 1px solid var(--spo-input-border);
	border-radius: var(--spo-radius-md);
	padding: 11px 18px;
	font-size: 14px;
	font-weight: 700;
	color: var(--spo-text-dark-muted);
}

.spo-btn-danger {
	background: var(--spo-red);
	border: none;
	border-radius: var(--spo-radius-md);
	padding: 11px 18px;
	font-size: 14px;
	font-weight: 700;
	color: var(--spo-white);
}

.spo-modal__close {
	position: absolute;
	top: 16px;
	right: 16px;
	background: #f3efe3;
	border: none;
	border-radius: var(--spo-radius-sm);
	width: 32px;
	height: 32px;
	font-size: 16px;
	color: var(--spo-text-dark-muted);
	z-index: 2;
	/* Center the × glyph: a bare button leaves the character on its own text
	   baseline, so it sat low/left of the box. Flex centering + line-height: 1
	   and zero padding put it dead center regardless of font metrics. */
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	line-height: 1;
}

.spo-modal__dialog--wide .spo-modal__close {
	position: static;
}

.spo-modal__head {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 18px;
}

/*
 * Basket photos vary a lot in their own composition — some are a tight
 * square product shot, some (like a flat-lay bundle photo) have real
 * blank space baked into the image itself. Forcing a fixed aspect-ratio
 * box with object-fit: cover either left that blank space visible (wide
 * box) or cropped into the actual product (narrow/mobile box), depending
 * on the photo. Showing the whole photo uncropped (object-fit: contain,
 * height capped rather than forced) avoids both failure modes for any
 * photo shape — the box just letterboxes on the background color instead.
 */
.spo-quickview__image {
	max-height: 360px;
	background: var(--spo-green-bg);
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 18px 18px 0 0;
	overflow: hidden;
}

.spo-quickview__image img {
	width: 100%;
	height: 100%;
	max-height: 360px;
	object-fit: contain;
}

.spo-quickview__body {
	padding: 24px;
	display: flex;
	flex-direction: column;
	gap: 14px;
}

.spo-quickview__head {
	display: flex;
	justify-content: space-between;
	align-items: flex-start;
	gap: 12px;
}

.spo-quickview__name {
	font-size: 20px;
	font-weight: 600;
}

.spo-quickview__count {
	font-size: 12px;
	color: var(--spo-text-muted);
}

.spo-quickview__price {
	font-family: 'Fraunces', Georgia, serif;
	font-size: 24px;
	font-weight: 700;
	color: var(--spo-green);
}

.spo-quickview__items {
	display: flex;
	flex-direction: column;
	gap: 8px;
	border-top: 1px solid var(--spo-border);
	padding-top: 14px;
}

.spo-quickview__items li {
	font-size: 13px;
	color: var(--spo-text-dark-muted);
}

.spo-quickview__items li::before {
	content: '• ';
}

.spo-quickview__compare-btn {
	width: 100%;
}

/* Compare grid */
.spo-compare-grid {
	display: grid;
	gap: 18px;
}

.spo-compare-col {
	border: 1px solid var(--spo-border);
	border-radius: 14px;
	overflow: hidden;
	display: flex;
	flex-direction: column;
}

.spo-compare-col__image {
	aspect-ratio: 1 / 1;
	background: var(--spo-green-bg);
	display: flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
}

.spo-compare-col__image img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.spo-compare-col__body {
	padding: 16px;
	display: flex;
	flex-direction: column;
	gap: 8px;
	flex-grow: 1;
}

.spo-compare-col__remove {
	align-self: flex-end;
	background: none;
	border: none;
	font-size: 11px;
	color: var(--spo-text-muted-2);
	text-decoration: underline;
	padding: 0;
}

.spo-compare-col__name {
	font-size: 15px;
	font-weight: 600;
}

.spo-compare-col__price {
	font-family: 'Fraunces', Georgia, serif;
	font-size: 17px;
	font-weight: 700;
	color: var(--spo-green);
}

.spo-compare-col__count {
	font-size: 11px;
	color: var(--spo-text-muted);
}

.spo-compare-col__items {
	display: flex;
	flex-direction: column;
	gap: 5px;
	border-top: 1px solid var(--spo-border);
	padding-top: 10px;
}

.spo-compare-col__items li {
	font-size: 12px;
	color: var(--spo-text-dark-muted);
}

.spo-compare-col__items li::before {
	content: '• ';
}

.spo-compare-col__qty-wrap {
	margin-top: auto;
	padding-top: 6px;
}

/* ---------------------------------------------------------------- */
/* Details step                                                      */
/* ---------------------------------------------------------------- */

.spo-details {
	max-width: 1280px;
	margin: 0 auto;
	padding: 40px 32px 100px;
	display: grid;
	grid-template-columns: 1.6fr 1fr;
	gap: 40px;
	align-items: start;
}

.spo-details__main {
	display: flex;
	flex-direction: column;
	gap: 20px;
}

.spo-details__title {
	font-size: 28px;
	font-weight: 600;
}

.spo-details__desc {
	font-size: 14px;
	color: var(--spo-text-muted);
	margin-top: 8px;
}

.spo-form {
	background: var(--spo-white);
	border: 1px solid var(--spo-border);
	border-radius: var(--spo-radius-lg);
	padding: 28px;
	display: flex;
	flex-direction: column;
	gap: 18px;
}

.spo-form__error {
	background: #fdecea;
	border: 1px solid #f3c2bc;
	color: #9a2f26;
	border-radius: var(--spo-radius-sm);
	padding: 12px 14px;
	font-size: 13px;
}

.spo-field {
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.spo-field__label {
	font-size: 13px;
	font-weight: 600;
	color: var(--spo-text-dark-muted);
}

.spo-field__hint {
	font-size: 12px;
	color: var(--spo-text-muted-2);
}

/* .spo-app prefix here for the same reason as the .spo-app.spo-app rules
   above: a host theme's own input/select/textarea reset can tie in
   specificity with a bare `.spo-field input` and win on load order. */
.spo-app .spo-field input,
.spo-app .spo-field textarea,
.spo-app .spo-field select {
	padding: 13px 14px;
	border: 1px solid var(--spo-input-border);
	border-radius: var(--spo-radius-sm);
	/* background-color, not the `background` shorthand: a select's custom
	   arrow is drawn as a background-image in the base .spo-app select rule,
	   and the shorthand would reset that back to none here. */
	background-color: var(--spo-white);
	width: 100%;
}

/*
 * min-height, not on the shared rule above: a host theme's own reset can
 * set an explicit `height` on inputs (seen live: ~35px) that we never
 * declare a competing `height` for, so there's nothing to win — the
 * theme's shorter box just applies and squeezes this padding vertically.
 * A floor here guarantees the room the padding above actually needs,
 * regardless of what height a theme forces. Left off textarea (which
 * sizes by its `rows` attribute, not a fixed height) and select (which
 * already has its own min-height in the base .spo-app select rule).
 */
.spo-app .spo-field input {
	min-height: 48px;
}

.spo-app .spo-field select {
	padding-right: 34px; /* room for the custom arrow drawn in the base select rule */
}

.spo-field textarea {
	resize: vertical;
}

.spo-field-row {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 16px;
}

.spo-btn-submit {
	text-align: center;
	background: var(--spo-green);
	color: var(--spo-white);
	border: none;
	border-radius: var(--spo-radius-md);
	padding: 14px;
	font-size: 15px;
	font-weight: 700;
	margin-top: 6px;
}

.spo-btn-submit:disabled {
	opacity: .65;
	cursor: default;
}

.spo-summary {
	position: sticky;
	top: 96px;
	background: var(--spo-white);
	border: 1px solid var(--spo-border);
	border-radius: var(--spo-radius-lg);
	padding: 24px;
	display: flex;
	flex-direction: column;
	gap: 14px;
}

.spo-summary__title {
	font-size: 16px;
	font-weight: 600;
}

.spo-summary__lines {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

/*
 * Quotation basket rows: photo on the left, name/qty/price + contents on
 * the right — used on-screen and (since the printed PDF is the same DOM,
 * just re-laid-out for print) on the printed/PDF quotation too.
 */
.spo-summary__line-group {
	display: flex;
	align-items: flex-start;
	gap: 14px;
}

.spo-summary__line-media {
	flex-shrink: 0;
}

.spo-summary__line-image {
	display: block;
	width: 72px;
	height: 72px;
	border-radius: 10px;
	object-fit: cover;
	border: 1px solid var(--spo-border);
	background: var(--spo-white);
}

.spo-summary__line-image--placeholder {
	background: var(--spo-green-bg);
	border-color: var(--spo-green-border);
}

.spo-summary__line-content {
	flex: 1;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.spo-summary__line {
	display: flex;
	justify-content: space-between;
	font-size: 13px;
	color: var(--spo-text-dark-muted);
}

.spo-summary__line-price {
	font-weight: 600;
}

.spo-summary__line-list {
	margin: 0;
	padding-left: 18px;
	font-size: 11.5px;
	color: var(--spo-text-muted-2);
	line-height: 1.6;
}

.spo-summary__line-list li {
	margin: 0 0 2px;
}

/* 120×120 on desktop per request — a little bigger/more visible than the
   72px default above, which stays as the mobile size (see the max-width:
   900px block further down). */
@media (min-width: 901px) {
	.spo-summary__line-image {
		width: 120px;
		height: 120px;
	}
}

.spo-summary__totals {
	border-top: 1px solid var(--spo-border);
	padding-top: 14px;
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.spo-summary__subtotal {
	display: flex;
	justify-content: space-between;
	font-size: 13px;
	color: var(--spo-text-muted);
}

.spo-summary__total {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
}

.spo-summary__total span:first-child {
	font-size: 14px;
	font-weight: 600;
	color: var(--spo-text);
}

.spo-summary__total span:last-child {
	font-family: 'Fraunces', Georgia, serif;
	font-size: 22px;
	font-weight: 700;
	color: var(--spo-green);
}

.spo-summary__note {
	font-size: 12px;
	color: var(--spo-text-muted-2);
	line-height: 1.5;
}

/* ---------------------------------------------------------------- */
/* Confirmation step                                                 */
/* ---------------------------------------------------------------- */

.spo-confirm {
	max-width: 720px;
	margin: 0 auto;
	padding: 56px 24px 80px;
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	gap: 18px;
}

.spo-confirm__icon {
	width: 64px;
	height: 64px;
	border-radius: 50%;
	background: var(--spo-green);
	display: flex;
	align-items: center;
	justify-content: center;
}

.spo-confirm__title {
	font-size: 28px;
	font-weight: 600;
}

.spo-confirm__desc {
	font-size: 14px;
	color: var(--spo-text-muted);
	max-width: 440px;
	line-height: 1.6;
}

.spo-confirm__ref {
	font-family: 'Fraunces', Georgia, serif;
	font-size: 20px;
	font-weight: 700;
	color: var(--spo-green);
	background: var(--spo-white);
	border: 1.5px dashed var(--spo-gold);
	border-radius: var(--spo-radius-md);
	padding: 12px 24px;
	letter-spacing: .03em;
}

.spo-confirm__card {
	width: 100%;
	background: var(--spo-white);
	border: 1px solid var(--spo-border);
	border-radius: var(--spo-radius-lg);
	padding: 24px;
	display: flex;
	flex-direction: column;
	gap: 14px;
	text-align: left;
}

.spo-confirm__card h2 {
	font-size: 15px;
	font-weight: 600;
}

.spo-confirm__total {
	border-top: 1px solid var(--spo-border);
	padding-top: 14px;
	display: flex;
	justify-content: space-between;
	align-items: baseline;
}

.spo-confirm__total span:first-child {
	font-size: 14px;
	font-weight: 600;
}

.spo-confirm__total span:last-child {
	font-family: 'Fraunces', Georgia, serif;
	font-size: 20px;
	font-weight: 700;
	color: var(--spo-green);
}

.spo-confirm__grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 14px;
}

.spo-confirm__field-label {
	display: block;
	font-size: 11px;
	color: var(--spo-text-muted-2);
	text-transform: uppercase;
	letter-spacing: .04em;
}

.spo-confirm__grid > div > span:last-child {
	font-size: 14px;
	color: var(--spo-text);
}

.spo-confirm__notice {
	width: 100%;
	text-align: left;
	line-height: 1.6;
}

.spo-confirm__actions {
	display: flex;
	gap: 12px;
	margin-top: 8px;
}

.spo-btn-print {
	background: var(--spo-white);
	color: var(--spo-green);
	border: 1.5px solid var(--spo-green);
	border-radius: var(--spo-radius-md);
	padding: 12px 22px;
	font-size: 14px;
	font-weight: 700;
}

.spo-btn-back-home {
	background: none;
	border: none;
	color: var(--spo-text-muted);
	font-size: 14px;
	font-weight: 600;
	align-self: center;
}

/* ---------------------------------------------------------------- */
/* Quotation (no order placed)                                      */
/* ---------------------------------------------------------------- */

.spo-quote__loading {
	color: var(--spo-text-muted);
	font-size: 14px;
	padding: 24px 0;
}

.spo-quote__ref-row {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	font-size: 13px;
	color: var(--spo-text-muted);
}

.spo-quote__ref-row strong {
	font-family: 'Fraunces', Georgia, serif;
	font-size: 16px;
	color: var(--spo-green);
}

.spo-quote__email-card {
	gap: 10px;
}

.spo-quote__email-desc {
	font-size: 13px;
	color: var(--spo-text-muted);
	margin: -4px 0 4px;
}

.spo-quote__email-form {
	display: flex;
	align-items: center;
	gap: 10px;
	flex-wrap: wrap;
}

/* .spo-app prefix: see the note above the base input/textarea/select rule
   — this specific field is the one a host theme's reset was confirmed to
   be winning against (padding/height/border/background/border-radius all
   silently overridden), so it needs the same specificity bump. */
.spo-app .spo-quote__email-form input {
	flex: 1;
	min-width: 200px;
	height: 46px;
	padding: 0 16px;
	border: 1px solid var(--spo-input-border);
	border-radius: var(--spo-radius-sm);
	background: var(--spo-white);
	font-family: inherit;
	font-size: 14px;
	box-sizing: border-box;
}

.spo-quote__email-form .spo-btn-submit {
	width: auto;
	height: 46px;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0 22px;
	white-space: nowrap;
	margin-top: 0;
	box-sizing: border-box;
}

.spo-quote__email-status {
	font-size: 13px;
	font-weight: 600;
	color: var(--spo-green);
}

.spo-quote__email-status.is-error {
	color: #9a2f26;
}

/* ---------------------------------------------------------------- */
/* Print-only header (logo + store name) — hidden on screen, shown   */
/* only inside @media print below, on the Confirmation/Quotation     */
/* steps so a printed/PDF copy carries a store mark instead of the   */
/* full page chrome around it.                                       */
/* ---------------------------------------------------------------- */

.spo-print-header {
	display: none;
}

.spo-print-header__logo {
	width: 48px;
	height: 48px;
	border-radius: 8px;
	object-fit: cover;
}

.spo-print-header__logo-placeholder {
	width: 48px;
	height: 48px;
	border-radius: 8px;
	background: var(--spo-green);
	color: var(--spo-white);
	display: flex;
	align-items: center;
	justify-content: center;
	font-family: 'Fraunces', Georgia, serif;
	font-weight: 700;
	font-size: 11px;
	letter-spacing: .05em;
	flex-shrink: 0;
}

.spo-print-header__name {
	font-family: 'Fraunces', Georgia, serif;
	font-weight: 700;
	font-size: 17px;
	color: var(--spo-text);
}

.spo-print-header__campaign {
	font-size: 12px;
	color: var(--spo-text-muted);
}

/* ---------------------------------------------------------------- */
/* Responsive                                                        */
/* ---------------------------------------------------------------- */

@media (max-width: 900px) {
	.spo-header__row {
		padding: 14px 18px;
		flex-wrap: wrap;
		row-gap: 10px;
	}

	/*
	 * The simple step header (Details / Confirmation / Quotation) packs
	 * "← Back to baskets", the "ShopMetro" wordmark, and a step-status pill
	 * into one flex row on desktop. On a phone that row doesn't have room
	 * for all three, so it wraps — but wrapping a single flex item down
	 * (the pill) reads as orphaned and misaligned rather than intentional.
	 * Switching to a 2-row grid instead gives each piece its own place:
	 * the back link gets its own full-width row, and the wordmark + pill
	 * share the row below with the pill pinned to the right. `display:
	 * contents` on .spo-header__left un-wraps it so its two children (the
	 * back link and the wordmark) become direct grid items here, without
	 * touching the markup.
	 */
	.spo-header--simple .spo-header__row {
		display: grid;
		grid-template-columns: 1fr auto;
		grid-template-areas: "back back" "brand badge";
		align-items: center;
		row-gap: 8px;
		flex-wrap: unset;
	}

	.spo-header--simple .spo-header__left {
		display: contents;
	}

	.spo-header--simple .spo-back-link {
		grid-area: back;
		/* Grid items stretch to fill their area by default, and a <button>'s
		   own text-align: center then centers the label inside that full-
		   width box — justify-self: start keeps it a normal left-aligned,
		   content-sized button instead. */
		justify-self: start;
	}

	.spo-header--simple .spo-brand__name {
		grid-area: brand;
	}

	.spo-header--simple .spo-badge {
		grid-area: badge;
		justify-self: end;
	}

	.spo-nav {
		display: none;
	}

	.spo-mobile-menu {
		display: block;
		padding: 14px 18px;
	}

	.spo-nav-row {
		border-top: none;
	}

	.spo-compare-tray__row {
		padding: 8px 18px;
		gap: 8px;
	}

	.spo-compare-tray__label {
		font-size: 11.5px;
	}

	/* The "Choose up to X baskets" hint is desktop-only breathing room —
	   on a tight mobile row it just crowds the label and chips. */
	.spo-compare-tray__hint {
		display: none;
	}

	.spo-chip {
		padding: 2px 3px 2px 8px;
		font-size: 10.5px;
		border-radius: 5px;
	}

	.spo-compare-tray__actions {
		gap: 10px;
	}

	.spo-btn-compare-now {
		padding: 7px 12px;
		font-size: 12px;
	}

	.spo-hero {
		padding: 18px 18px 0;
	}

	.spo-hero__banner-image {
		max-height: 220px;
		border-radius: var(--spo-radius-md);
	}

	.spo-header__subtext {
		padding: 0 18px 12px;
	}

	.spo-section {
		padding: 28px 18px 0;
		scroll-margin-top: 120px;
	}

	/*
	 * Cart bar: a compact single row (basket count/total on the left, both
	 * buttons sharing the rest of the row) instead of stacking the buttons
	 * into their own full-width rows underneath — smaller text/padding on
	 * the count and buttons buys enough room that neither button needs to
	 * wrap, and it costs a lot less vertical space on a phone.
	 *
	 * Clearance above a theme's own fixed bottom nav (and often a raised
	 * circular action button) turned out to work better as extra padding
	 * *inside* the bar than as a `bottom` offset: offsetting the whole bar
	 * left a visible gap of page background showing underneath it, while
	 * padding-bottom keeps the bar's own green background flush with the
	 * page bottom and just pushes its row content up clear of whatever
	 * sits in front of it. The spacer grows to match so page content isn't
	 * left hidden behind the now-taller bar.
	 */
	.spo-cartbar-spacer {
		height: 104px;
	}

	.spo-cartbar {
		padding: 10px 18px 12px;
		gap: 8px;
	}

	.spo-cartbar__row {
		gap: 10px;
	}

	.spo-cartbar__info {
		flex-direction: column;
		align-items: flex-start;
		gap: 1px;
		min-width: 84px;
		flex: 0 0 auto;
	}

	.spo-cartbar__count {
		font-size: 11px;
		line-height: 1.25;
	}

	.spo-cartbar__total {
		font-size: 18px;
	}

	.spo-cartbar__actions {
		flex: 1;
		gap: 7px;
	}

	.spo-cartbar__secondary,
	.spo-cartbar__cta {
		flex: 1;
		min-height: 38px;
		text-align: center;
		padding: 8px 7px;
		font-size: 11px;
	}

	.spo-details {
		grid-template-columns: 1fr;
		padding: 24px 18px 90px;
		gap: 24px;
	}

	.spo-summary {
		position: static;
	}

	.spo-field-row {
		grid-template-columns: 1fr;
	}

	.spo-form {
		padding: 20px;
	}

	.spo-confirm {
		padding: 32px 18px 60px;
	}

	.spo-confirm__grid {
		grid-template-columns: 1fr;
	}

	/*
	 * "Print / Save as PDF" + "Continue to Pre-Order →" (and, on the
	 * quotation screen, "Print Quotation" + "Back to ShopMetro") sat side
	 * by side with no wrap handling — on a phone the combined label width
	 * regularly exceeded the row, so the browser squeezed and wrapped one
	 * or both buttons unevenly. Stacking them full-width removes that.
	 */
	.spo-confirm__actions {
		flex-direction: column;
		align-items: stretch;
		gap: 10px;
	}

	.spo-btn-print,
	.spo-btn-back-home {
		width: 100%;
		text-align: center;
	}

	.spo-quote__email-form {
		flex-direction: column;
		align-items: stretch;
	}

	/*
	 * The input's `flex: 1` (desktop-only, for sharing the row with the
	 * button) sets flex-basis: 0%, which is harmless while the form is a
	 * row — but once it switches to flex-direction: column here, that same
	 * flex-basis becomes the item's *height* basis instead of its width,
	 * silently shrinking the input to a sliver regardless of the
	 * height: 46px declared above. `flex: none` drops the input back to
	 * its own declared height/width for this stacked mobile layout.
	 */
	.spo-app .spo-quote__email-form input {
		flex: none;
	}

	.spo-app .spo-quote__email-form input,
	.spo-quote__email-form .spo-btn-submit {
		width: 100%;
	}

	.spo-modal__dialog--wide {
		padding: 18px;
	}

	/*
	 * Mobile Quick View: stays stacked (image on top, details below —
	 * side-by-side is too cramped at this width), but the image was a full
	 * 1:1 square eating most of the screen before you could even see the
	 * contents list. A shorter, wider crop plus tighter padding keeps the
	 * photo recognizable while leaving real room for the item list.
	 */
	.spo-modal {
		padding: 14px;
	}

	.spo-modal__dialog {
		max-height: 88vh;
	}

	.spo-quickview__image {
		max-height: 220px;
		border-radius: 14px 14px 0 0;
	}

	.spo-quickview__image img {
		max-height: 220px;
	}

	.spo-quickview__body {
		padding: 18px;
		gap: 12px;
	}
}

/*
 * This used to trigger at 700px while every other mobile rule in this file
 * switches at 900px — so on a phone between 701–900px wide (landscape, or
 * some larger phones/small tablets in portrait) every other button in the
 * plugin went to its compact mobile layout except this one: the Compare
 * grid kept the JS-set multi-column inline style (one column per basket
 * being compared), squeezing each column's Remove/Add buttons into a
 * sliver too narrow for their own text. Matching the 900px breakpoint used
 * everywhere else fixes that gap.
 */
@media (max-width: 900px) {
	.spo-compare-grid {
		grid-template-columns: 1fr !important;
	}
}

/*
 * Basket grid breakpoints. Desktop is 4 columns; a straight drop to 2
 * columns at the same ~900px point the rest of the layout switches at
 * made the cards uncomfortably wide on a tablet, so there's a 3-column
 * tier in between. The 2-column mobile grid (instead of 1 giant card per
 * row) is the actual fix for the cramped/awkward feel on a phone — cards
 * get smaller, not just narrower, so the whole catalog reads like a
 * normal shopping grid instead of a single scrolling list.
 */
@media (min-width: 761px) and (max-width: 1024px) {
	.spo-grid {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

@media (max-width: 760px) {
	.spo-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 9px;
	}

	.spo-card__body {
		padding: 10px;
		gap: 5px;
	}

	.spo-card__name {
		font-size: 14px;
	}

	.spo-card__price {
		font-size: 13px;
	}

	.spo-card__itemcount {
		font-size: 10px;
		margin: 1px 0 0;
	}

	.spo-card__preview {
		font-size: 10px;
		min-height: 30px;
	}

	/*
	 * Requested layout: three simple full-width rows in DOM order — "See
	 * full contents", "+ Compare", "Add to Pre-Order" — instead of a
	 * shrink/wrap row. Stacking removes the squeeze entirely, so neither
	 * button needs flex-shrink, min-width tricks, or wrapped text.
	 */
	.spo-card__actions {
		flex-direction: column;
		align-items: stretch;
		gap: 6px;
		margin-top: 3px;
	}

	/*
	 * Font-size/padding tuned down from the desktop values specifically so
	 * "See full contents" fits on one line at typical 2-up mobile card
	 * widths (~150-180px) — at the larger desktop size it wraps to 2 lines
	 * on real phones (narrower system/webfont rendering than our own test
	 * fonts made this easy to miss locally).
	 */
	.spo-btn-outline,
	.spo-btn-compare {
		flex: 0 0 auto;
		width: 100%;
		margin-left: 0;
		white-space: normal;
		text-align: center;
		font-size: 11px;
		padding: 8px 6px;
	}

	.spo-btn-add {
		font-size: 12.5px;
		padding: 9px 6px;
	}

	.spo-qty {
		padding: 5px 8px;
	}

	.spo-app .spo-qty__btn {
		width: 32px;
		height: 32px;
		font-size: 17px;
	}
}

/*
 * Small-phone tuning. Set at 400px (not 380px) so it actually covers the
 * most common modern phones: iPhone 12–14 (390px), iPhone 15/16 (393px),
 * and Pixel-class Androids sit right at ~390–412px. A 380px cutoff missed
 * every one of them, leaving the single most common phone width on the
 * roomier ≤760px tier where the 2-up cards and the two-button cart bar run
 * cramped. 400px catches the whole 360–393px class while still excluding
 * the wider 412–430px phones, which have room to spare on the ≤760px tier.
 */
/*
 * Compare tray on phones. The chips are pills that don't wrap their text, so
 * four long basket names ("All Time Favorites 2/3/4/5") packed into an uneven
 * two-up jumble and could overflow at very small widths. Stack the tray into a
 * clean column: the "Comparing (n/n)" label on its own line, the chips in an
 * even two-column grid with each name truncating to a single line, and the
 * Clear / Compare Now actions on their own full-width row below.
 */
@media (max-width: 600px) {
	.spo-compare-tray__row {
		flex-direction: column;
		align-items: stretch;
		gap: 10px;
	}

	.spo-compare-tray__meta {
		flex-direction: column;
		align-items: stretch;
		gap: 8px;
		width: 100%;
	}

	.spo-compare-tray__chips {
		display: grid;
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 6px;
		width: 100%;
	}

	.spo-chip {
		width: 100%;
	}

	/* min-width:0 lets the flex child shrink below its text width so the
	   ellipsis can kick in instead of the name overflowing the chip. */
	.spo-chip__name {
		min-width: 0;
		overflow: hidden;
		text-overflow: ellipsis;
	}

	.spo-compare-tray__actions {
		width: 100%;
	}

	.spo-btn-compare-now {
		flex: 1;
	}
}

@media (max-width: 400px) {
	.spo-grid {
		gap: 7px;
	}

	.spo-card__body {
		padding: 8px;
	}

	.spo-card__name {
		font-size: 13px;
	}

	.spo-card__price {
		font-size: 12.5px;
	}

	.spo-card__preview {
		font-size: 9px;
	}

	.spo-btn-outline,
	.spo-btn-compare {
		font-size: 10px;
		padding: 7px 5px;
	}

	.spo-btn-add {
		font-size: 11.5px;
	}

	/* Quantity stepper: at ≤760px the –/+ buttons shrank to 24px, which on a
	   narrow 2-up card left two tiny controls floating at the ends of a wide
	   pill with the number marooned between them — unbalanced and a poor tap
	   target. Bigger square end buttons + a tighter pill make the –, value and
	   + read as one evenly-weighted control. */
	.spo-qty {
		padding: 4px 5px;
	}

	.spo-app .spo-qty__btn {
		width: 34px;
		height: 34px;
		font-size: 18px;
	}

	.spo-qty__value {
		font-size: 15px;
	}

	.spo-cartbar {
		gap: 6px;
		padding-left: 12px;
		padding-right: 12px;
	}

	.spo-cartbar__info {
		min-width: 68px;
	}

	.spo-cartbar__total {
		font-size: 17px;
	}

	.spo-cartbar__secondary,
	.spo-cartbar__cta {
		font-size: 10px;
		padding: 8px 5px;
	}

	/* Header wordmark + pre-order period line: trim so the sticky header
	   doesn't eat two rows of a short 390px viewport before any baskets show. */
	.spo-brand__name {
		font-size: 19px;
	}

	.spo-header__subtext {
		font-size: 12px;
	}

	/* Quick View / Compare modals: edge-to-edge breathing room is scarce at
	   390px — trim the outer gutter so the dialog isn't a narrow column. */
	.spo-modal {
		padding: 10px;
	}

	.spo-quickview__body {
		padding: 16px;
	}

	/* Details form + Confirmation/Quotation: the ≤900px block already drops
	   these to a single column, but their desktop 28px titles and 20–24px card
	   padding still dominate a 390px viewport. Scale the headings and trim the
	   padding so the form fields and order summary get the width instead. */
	.spo-details__title,
	.spo-confirm__title {
		font-size: 22px;
	}

	.spo-form {
		padding: 16px;
	}

	.spo-field__label {
		font-size: 12.5px;
	}

	/* "Review & Confirm Pre-Order →" is a long label; at 15px it ran edge to
	   edge and, in a real device's system font, wrapped mid-phrase. Ease the
	   size/padding and give it a comfortable line-height so it fits on one line
	   on common small phones and wraps cleanly if a translation is longer. */
	.spo-btn-submit {
		font-size: 14px;
		padding: 13px 12px;
		line-height: 1.3;
	}

	.spo-confirm {
		padding: 24px 14px 56px;
	}

	.spo-confirm__ref {
		font-size: 18px;
		padding: 10px 18px;
	}

	.spo-confirm__card,
	.spo-summary {
		padding: 18px;
	}

	/* Quotation/confirmation basket rows: shrink the thumbnail a touch so the
	   name + contents list beside it isn't squeezed into a narrow column. */
	.spo-summary__line-image {
		width: 60px;
		height: 60px;
	}

	.spo-confirm__total span:last-child,
	.spo-summary__total span:last-child {
		font-size: 19px;
	}
}

/* ---------------------------------------------------------------- */
/* Print (Confirmation step / Quotation → Print / Save as PDF)      */
/*                                                                    */
/* Printing used to print the whole page — theme header, search bar, */
/* footer and all — because only .spo-header etc. were hidden and    */
/* everything outside #spo-app (the site's own header/footer) was     */
/* left untouched. The fix: hide the entire page, then re-reveal only */
/* the active step inside #spo-app, pulled to the top of the sheet so */
/* it doesn't leave a blank-page gap where the hidden content was.    */
/* ---------------------------------------------------------------- */

/* Give the printed sheet a bit of breathing room at the very top so the store
   logo/name isn't jammed against the paper edge. Chrome's "Save as PDF" honors
   this when its Margins setting is Default (its None setting overrides it). */
@page {
	margin-top: 0.5in;
}

@media print {
	/*
	 * Print only this plugin's active step, with no leftover blank space.
	 *
	 * The old approach set `body * { visibility: hidden }` and pulled .spo-app
	 * to position: absolute; top: 0. But visibility: hidden keeps every hidden
	 * element's box in the layout — so the theme's own header/footer/sidebar
	 * (which live OUTSIDE #spo-app and can't be display:none'd by name without
	 * knowing each theme's markup) still reserved their full height, printing
	 * as a tall band of white space above the receipt and often a trailing
	 * blank page.
	 *
	 * Instead, display:none everything that is neither #spo-app, nor inside it,
	 * nor an ancestor of it. :has(#spo-app) keeps the app's ancestor chain
	 * (html › body › the theme's content wrappers) rendered so the app still
	 * shows; every sibling of that chain — the theme chrome — is removed from
	 * layout entirely and reserves zero height. The ancestors then collapse to
	 * the app's own height, so the active step prints flush at the top with no
	 * gap and no blank trailing page. No JS, nothing theme-specific to target.
	 *
	 * :has() and complex :not() are supported by the Chromium engine behind
	 * Chrome's "Print ▸ Save as PDF" (and every current print-capable browser).
	 */
	body *:not(#spo-app):not(#spo-app *):not(:has(#spo-app)) {
		display: none !important;
	}

	/*
	 * The app's ancestor chain stays displayed (above) so the receipt renders —
	 * but those theme wrappers carry their own on-screen spacing that would
	 * otherwise print as a blank band at the top of the sheet: a content-area
	 * padding-top to clear a fixed site header, a 100vh min-height, a row gap,
	 * etc. (on the live Flatsome theme, .content-area has 30px of padding-top).
	 * Zeroing padding/margin/min-height on every ancestor of #spo-app — and
	 * nothing inside it — drops the receipt flush to the top with no inherited
	 * gap. This is what actually removes the leftover white space; :has() picks
	 * out exactly the ancestor chain (html › body › theme wrappers).
	 */
	:has(#spo-app) {
		margin: 0 !important;
		padding: 0 !important;
		min-height: 0 !important;
		/* Paint the whole ancestor chain (incl. <html> and <body>) white. The
		   live theme sets a green background on <html>; since the printed app is
		   only as tall as the receipt, the page area below it showed that green
		   as a full-width "footer" band. Whiting out the ancestors removes it. */
		background: var(--spo-white) !important;
	}

	#spo-app {
		background: var(--spo-white);
	}

	/*
	 * Inactive steps live inside #spo-app (so they survive the rule above) —
	 * drop them from layout so only the active step prints, starting at the top
	 * rather than behind the full-height Browse grid.
	 */
	.spo-app .spo-step:not(.is-active) {
		display: none !important;
	}

	.spo-header,
	.spo-cartbar,
	.spo-cartbar-spacer,
	.spo-modal,
	.spo-confirm__actions,
	.spo-quote__email-card {
		display: none !important;
	}

	/* Guaranteed 120×120 regardless of the printed page's rendered width
	   (which doesn't reliably match the min-width: 901px screen breakpoint
	   above depending on paper size/margins). */
	.spo-summary__line-image {
		width: 120px;
		height: 120px;
	}

	/*
	 * .spo-confirm is a 720px box with 24px of left/right padding, so its
	 * actual CONTENT (the card underneath) sits 24px in from that box's own
	 * edges — at 720-48=672px wide. .spo-print-header used to be a 720px box
	 * too, but with its border-bottom rule drawn on that same OUTER box
	 * (borders always follow the border edge, never the padding), so the
	 * rule ended up ~24px wider on each side than the card below it — a
	 * real, visible mismatch confirmed by rendering an actual PDF via
	 * Playwright's page.pdf() (which — unlike emulateMedia()+screenshot() —
	 * runs Chromium's real print/PDF layout engine, the same one behind
	 * Chrome's "Print ▸ Save as PDF") and measuring the pixel edges: the
	 * rule spanned ~24px past the card on both sides. Sizing this box to
	 * 672px (720 minus that same 48px of padding) and dropping its own
	 * left/right padding puts the rule — and the logo/name inside it — on
	 * exactly the same left/right edges as the card.
	 */
	.spo-confirm {
		padding: 0 24px 40px;
		max-width: 720px;
		margin: 0 auto;
	}

	.spo-print-header {
		display: flex !important;
		align-items: center;
		gap: 14px;
		width: 100%;
		max-width: 672px;
		margin: 0 auto 24px;
		padding: 0 0 18px;
		border-bottom: 2px solid var(--spo-green);
		text-align: left;
		box-sizing: border-box;
	}
}
