/**
 * Configurator and design catalogue.
 *
 * An editorial, technical look: a warm white background, black type, a
 * red accent, sharp corners, uppercase mono labels.
 */

/* ---------------------------------------------------------------
 * The plugin's typography.
 *
 * All three families are under the SIL Open Font License, so they can
 * travel with the plugin and be embedded in whatever it generates. A site
 * using the plugin may override --pomp-display and --pomp-mono with its own.
 *
 * latin-ext carries Croatian diacritics (č, ć, ž, š, đ), so without it a
 * design's text would come out cut short.
 * ------------------------------------------------------------ */

@font-face { font-display: swap; font-family: Anton; font-style: normal; font-weight: 400; src: url(../fonts/Anton-latin-ext.woff2) format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-display: swap; font-family: Anton; font-style: normal; font-weight: 400; src: url(../fonts/Anton-latin.woff2) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-display: swap; font-family: "Space Mono"; font-style: normal; font-weight: 400; src: url(../fonts/SpaceMono-400-latin-ext.woff2) format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-display: swap; font-family: "Space Mono"; font-style: normal; font-weight: 400; src: url(../fonts/SpaceMono-400-latin.woff2) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-display: swap; font-family: "Space Mono"; font-style: normal; font-weight: 700; src: url(../fonts/SpaceMono-700-latin-ext.woff2) format("woff2"); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-display: swap; font-family: "Space Mono"; font-style: normal; font-weight: 700; src: url(../fonts/SpaceMono-700-latin.woff2) format("woff2"); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
/* Inter loads the full latin range, for the same reason as the theme: the
   latin subset alone is missing č, ć, ž, š and đ, which then dropped out of
   labels mid-word. */
@font-face { font-display: swap; font-family: Inter; font-style: normal; font-weight: 100 900; src: url(../fonts/Inter-Variable.woff2) format("woff2"); }

:root {
	--pomp-max: 1680px;
	--pomp-gutter: clamp(16px, 2.5vw, 44px);
	--pomp-bar-height: 46px;
	/* The desktop stage's sticky fields panel (see min-width: 900px below) -
	   a plain constant, not measured, since a JS-driven width would have
	   nothing to react to (the panel doesn't resize with its own content
	   the way a mobile sheet does). Grows gently with the viewport rather
	   than sitting at a single fixed width regardless of screen size, capped
	   well short of crowding the photo column even on a very wide monitor. */
	--pomp-desktop-panel-width: clamp(380px, 26vw, 560px);

	--pomp-bg: #fff9f7;
	--pomp-ink: #000000;
	--pomp-accent: #ed3833;
	--pomp-muted: #8a8a8a;
	--pomp-line: rgba(0, 0, 0, .16);
	/* The brush stroke behind buttons and a selected size, and the text on it.
	   The stroke is a mask, so it takes any colour; left alone it follows the
	   text colour - the black it has always been. Set from Pomp → Settings →
	   Appearance, or overridden like any other variable here. */
	--pomp-brush: var(--pomp-ink);
	--pomp-on-brush: #ffffff;

	--pomp-display: 'Anton', 'Arial Narrow', 'Haettenschweiler', Impact, sans-serif;
	--pomp-mono: 'Space Mono', ui-monospace, 'SFMono-Regular', 'Menlo', monospace;

	/* Brush stroke for buttons, and the strike for a selected chip. The marker
	   stroke (pomp_marker.svg) goes inline in the DOM, not as a CSS background -
	   see StepMarker in configurator.js. */
	--pomp-blob: url("../img/pomp-brush-bg.webp");
	--pomp-circle: url("../img/brush-circle.png");
	--pomp-text: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
}

/*
 * Instead of breaking out of the theme's narrow column, the column itself
 * opens to full width. That avoids doing the maths in vw, which includes
 * the scrollbar's width and causes overflow.
 */
body.pomp-page .wp-site-blocks {
	padding-left: var(--pomp-gutter);
	padding-right: var(--pomp-gutter);
}

/*
 * The theme stacks several nested has-global-padding wrappers, each with its
 * own spacing, so the content indents in steps. Only the spacing above is kept.
 */
body.pomp-page .wp-site-blocks .has-global-padding {
	padding-left: 0 !important;
	padding-right: 0 !important;
}

body.pomp-page .wp-site-blocks .has-global-padding > .alignfull {
	margin-left: 0 !important;
	margin-right: 0 !important;
}

body.pomp-page .wp-block-post-title,
body.pomp-page .wp-block-post-content,
body.pomp-page .entry-title,
body.pomp-page .entry-content {
	max-width: none !important;
	margin-left: 0 !important;
	margin-right: 0 !important;
}

.pomp-configurator,
.pomp-catalog,
.pomp-single {
	width: 100%;
	max-width: var(--pomp-max) !important;
	margin-left: auto !important;
	margin-right: auto !important;
	color: var(--pomp-ink);
	/* Clips anything inside that ends up wider than the viewport (a
	   sideways-scrolling strip whose own width leaked out, a preview
	   that hasn't settled into its box yet) right here, at this
	   component's own edge, instead of letting it push the whole page
	   wide enough to drag sideways on mobile. */
	overflow-x: hidden;
}

/* The theme's header is hidden, so the page reads as a single design.
   .site-header covers most block and classic themes; header#header is
   Blocksy's own id, tested live and added by name since nothing more
   generic catches it. */
body.pomp-chrome-off .wp-site-blocks > header,
body.pomp-chrome-off header.wp-block-template-part,
body.pomp-chrome-off .site-header,
body.pomp-chrome-off header#header {
	display: none;
}

body.pomp-chrome-off .wp-site-blocks > main {
	padding-top: 0;
}

/* A design's own page (single-pomp_design) is a real WordPress post, so a theme
   that shows "by AUTHOR / DATE" under a post title (tested live: Astra,
   Blocksy) shows it here too - meaningless on a print design nobody
   "wrote". .entry-meta/.byline/.posted-on/.entry-date are the widely
   shared _s-starter-theme convention a lot of themes build on; edit_post_link()
   is core WP's own "Edit" link, shown to a logged-in editor only. */
body.single-pomp_design .entry-meta,
body.single-pomp_design .byline,
body.single-pomp_design .posted-on,
body.single-pomp_design .entry-date,
body.single-pomp_design .post-edit-link {
	display: none;
}

/*
 * The design is drawn in an <svg> nested in the product photo's, and a row
 * may reach past that inner box on purpose - the print area is a guide, not
 * a wall. Themes built on normalize.css clip it anyway with
 * "svg:not(:root) { overflow: hidden }", which outranks the overflow="visible"
 * attribute the drawing carries. On WoodMart, measured, that cut the top row
 * of a five-row design in half, in the live preview and on the catalogue
 * card alike. Scoped to the plugin's own roots, and specific enough to win.
 */
.pomp-configurator svg[overflow="visible"],
.pomp-catalog svg[overflow="visible"],
.pomp-single svg[overflow="visible"] {
	overflow: visible;
}

/*
 * The configurator and catalogue pages. Their background is Pomp style's
 * alone (see further down). clip, not hidden: hidden would create a new
 * scroll container and break the sticky bar.
 */
body.pomp-page {
	overflow-x: clip;
	/* Stops an overscrolled drag anywhere in the configurator (the mobile
	   sheet included) from chaining up into the browser's own pull-to-
	   refresh, which reloads the page out from under whatever was being
	   dragged. */
	overscroll-behavior-y: contain;
}

/* The page title, in the same tight display face - Pomp style only; in the
   theme's style the title is the theme's. */
body.pomp-style-pomp.pomp-page .wp-block-post-title,
body.pomp-style-pomp.pomp-page .entry-title {
	font-family: var(--pomp-display);
	text-transform: uppercase;
	letter-spacing: .005em;
	line-height: .92;
	font-size: clamp(48px, 9vw, 132px);
	margin-bottom: 4px;
	text-align: left;
	width: 100%;
	max-width: var(--pomp-max) !important;
	margin-left: auto !important;
	margin-right: auto !important;
}

.pomp-configurator *,
.pomp-configurator *::before,
.pomp-configurator *::after,
.pomp-catalog *,
.pomp-catalog *::before,
.pomp-catalog *::after {
	box-sizing: border-box;
}

/* ---------------------------------------------------------------
 * Typographic labels
 * ------------------------------------------------------------ */

.pomp-label,
.pomp-steps,
.pomp-hint,
.pomp-summary,
.pomp-breadcrumb,
.pomp-pagination,
.pomp-eyebrow {
	font-family: var(--pomp-mono);
	font-weight: 400;
	text-transform: uppercase;
	letter-spacing: -.03em;
	font-size: 19px;
	line-height: 1.35;
}

/*
 * Labels above fields (Choose a variant, etc.), matching their own SELECT
 * SIZE: small Inter, semi-bold, black.
 */
.pomp-attribute__label,
.pomp-label {
	font-family: var(--pomp-text);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: -.04em;
	font-size: 12px;
	line-height: 1.2;
	color: var(--pomp-ink);
}

/* Card title in small Inter, price in bold mono, matching their own cards. */
.pomp-card__title {
	font-family: var(--pomp-text);
	font-weight: 500;
	text-transform: uppercase;
	letter-spacing: -.04em;
	font-size: 12px;
	line-height: 1.2;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.pomp-card__price {
	font-family: var(--pomp-mono);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: -.11em;
	font-size: 13px;
	line-height: 1.2;
}

.pomp-eyebrow {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 16px;
	margin: 0 0 18px;
	color: var(--pomp-accent);
}

.pomp-eyebrow__count {
	color: var(--pomp-muted);
}

/* ---------------------------------------------------------------
 * The page's own background - Pomp style only
 *
 * In the theme's style the page is the theme's: its background, its title,
 * its header. No space is added above the content in either style. That
 * space belonged to one theme's floating header, and in every other theme
 * it pushed the theme's own header down - on Woodmart, measured, a 110 px
 * empty band above it. A theme with a floating header adds its own.
 * ------------------------------------------------------------ */

body.pomp-style-pomp.pomp-page {
	background: var(--pomp-bg);
}

/* ---------------------------------------------------------------
 * Steps as a menu
 * ------------------------------------------------------------ */

.pomp-steps {
	display: flex;
	list-style: none;
	margin: 0;
	padding: 0;
}

.pomp-steps__item {
	display: flex;
	align-items: baseline;
	white-space: nowrap;
	color: var(--pomp-muted);
}

.pomp-steps__item.is-done {
	color: var(--pomp-ink);
}

.pomp-steps__item.is-active {
	color: var(--pomp-accent);
}

/*
 * A finished step gets struck through with a hand-drawn marker stroke
 * (pomp_marker.svg), like crossing an item off a list. The image itself
 * goes inline in the DOM (StepMarker in configurator.js), not as a
 * background - the clip-path reveal (see .pomp-step-marker__clip further
 * down) needs a real <rect> to animate, which a CSS background can't
 * provide. SVG, not PNG: preserveAspectRatio="none" lets it stretch to the
 * step name's width without losing edge sharpness.
 */
.pomp-steps__label {
	position: relative;
	font-family: var(--pomp-display);
	font-weight: 400;
	text-transform: uppercase;
	letter-spacing: .01em;
	line-height: 1;
	/* The display font doesn't use the space reserved for descenders on
	   UPPERCASE text, so the letters sit visually too high - a slight
	   downward shift corrects that; the brackets are nudged back separately. */
	transform: translateY(.1em);
}

/* The marker sits behind the text (negative z-index), like a real
   highlighter over the printed name - the name stays readable through the
   stroke. It's the label's full height (brackets and text), a little wider
   on both sides than the label itself. */
.pomp-step-marker {
	position: absolute;
	left: -8%;
	top: 0;
	width: 116%;
	height: 100%;
	z-index: -1;
	overflow: visible;
	pointer-events: none;
}

/* The rect inside the marker's clipPath is always drawn at full width; a
   CSS transform (not the width attribute) reveals it left to right, so
   the animation runs on the browser's own compositor with no library. A
   transform-based reveal, rather than transitioning the width attribute
   itself, is also the more broadly supported way to animate SVG geometry. */
.pomp-step-marker__clip {
	transform: scaleX(0);
	transform-origin: 0 0;
	transition: transform .55s cubic-bezier(.25, .46, .45, .94);
}

.pomp-step-marker__clip.is-drawn {
	transform: scaleX(1);
}

.pomp-steps__label::before,
.pomp-steps__label::after {
	content: "";
	display: inline-block;
	width: .35em;
	height: 1em;
	background-color: currentColor;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
	vertical-align: middle;
	transform: translateY(-.1em);
}

.pomp-steps__label::before {
	margin-right: .3em;
	-webkit-mask-image: url(../svg/bracket_left.svg);
	mask-image: url(../svg/bracket_left.svg);
}

.pomp-steps__label::after {
	margin-left: .3em;
	-webkit-mask-image: url(../svg/bracket_right.svg);
	mask-image: url(../svg/bracket_right.svg);
}

.pomp-steps__number {
	font-family: var(--pomp-mono);
	font-weight: 400;
	font-variant-numeric: tabular-nums;
	color: var(--pomp-muted);
	/* The mono font has the same "invisible padding-bottom" as the display
	   face on UPPERCASE text - the same shift, with the brackets nudged
	   back separately. */
	transform: translateY(.12em);
}

.pomp-steps__number::before,
.pomp-steps__number::after {
	content: "";
	display: inline-block;
	width: .35em;
	height: 1em;
	background-color: currentColor;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
	vertical-align: middle;
	transform: translateY(-.12em);
}

.pomp-steps__number::before {
	margin-right: .3em;
	-webkit-mask-image: url(../svg/bracket_left.svg);
	mask-image: url(../svg/bracket_left.svg);
}

.pomp-steps__number::after {
	margin-left: .3em;
	-webkit-mask-image: url(../svg/bracket_right.svg);
	mask-image: url(../svg/bracket_right.svg);
}

.pomp-steps__item.is-active .pomp-steps__number {
	color: var(--pomp-accent);
}

/* Secondary links at the bottom of the side menu. */
.pomp-menu__meta {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 8px;
}

.pomp-menu__meta a {
	font-family: var(--pomp-mono);
	font-weight: 400;
	text-transform: uppercase;
	letter-spacing: -.03em;
	font-size: 13px;
	color: var(--pomp-muted);
	text-decoration: none;
	/* The mono font has the same "invisible padding-bottom" as the display
	   face on UPPERCASE text - the same shift, with the brackets nudged
	   back separately. */
	transform: translateY(.12em);
}

.pomp-menu__meta a::before,
.pomp-menu__meta a::after {
	content: "";
	display: inline-block;
	width: .35em;
	height: 1em;
	background-color: currentColor;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
	vertical-align: middle;
	transform: translateY(-.12em);
}

.pomp-menu__meta a::before {
	margin-right: .3em;
	-webkit-mask-image: url(../svg/bracket_left.svg);
	mask-image: url(../svg/bracket_left.svg);
}

.pomp-menu__meta a::after {
	margin-left: .3em;
	-webkit-mask-image: url(../svg/bracket_right.svg);
	mask-image: url(../svg/bracket_right.svg);
}

.pomp-menu__meta a:hover {
	color: var(--pomp-accent);
}

/* Desktop: a vertical side menu, like in their popup. */
@media (min-width: 900px) {
	.pomp-menu {
		position: sticky;
		top: calc(var(--pomp-bar-height) + 24px);
		align-self: start;
		padding-right: 24px;
		border-right: 1px solid var(--pomp-line);
	}

	/*
	 * Steps at the top, secondary links at the bottom, like their own
	 * menu__inner.
	 */
	/*
	 * The menu starts below the title, so the full screen height would
	 * push the bottom links off screen. So the smaller of the two
	 * measurements is used instead.
	 */
	.pomp-menu__inner {
		display: flex;
		flex-direction: column;
		justify-content: space-between;
		gap: 48px;
		min-height: min(560px, calc(100vh - var(--pomp-bar-height) - 96px));
	}

	.pomp-steps {
		flex-direction: column;
		gap: 14px;
	}

	.pomp-steps__item {
		justify-content: space-between;
		gap: 16px;
	}

	.pomp-steps__label {
		font-size: 26px;
	}

	.pomp-steps__number {
		font-size: 19px;
	}
}

/* Phone: horizontal, below the bar, with scrolling. */
@media (max-width: 899px) {
	.pomp-menu {
		margin: 0 0 8px;
		padding-bottom: 14px;
		border-bottom: 1px solid var(--pomp-line);
		overflow-x: auto;
		scrollbar-width: none;
		/* Same edge fade as the other sideways-scrolling strips (see
		   .pomp-own__tune) - the hint that there's more to it sideways. */
		-webkit-mask-image: linear-gradient(to right, transparent 0, #000 14px, #000 calc(100% - 14px), transparent 100%);
		mask-image: linear-gradient(to right, transparent 0, #000 14px, #000 calc(100% - 14px), transparent 100%);
	}

	.pomp-menu::-webkit-scrollbar {
		display: none;
	}

	/* Shown here too now (used to be hidden - the theme's own bar has
	   equivalents for two of these three, but not "Create your own
	   design", so hiding the whole group hid that one along with them). */
	.pomp-menu__meta {
		margin-top: 10px;
	}

	.pomp-steps {
		gap: 18px;
	}

	.pomp-steps__item {
		gap: 6px;
	}

	.pomp-steps__label {
		font-size: 19px;
	}

	.pomp-steps__number {
		font-size: 18px;
	}
}

/* The old floating "jump to preview" shortcut lived here - replaced by
   the mobile bottom sheet below, which keeps the preview in view
   without a manual jump. */

/* ---------------------------------------------------------------
 * Layout
 * ------------------------------------------------------------ */

.pomp-layout {
	display: grid;
	grid-template-columns: 1fr;
	gap: 32px;
}

@media (min-width: 900px) {
	.pomp-layout {
		/* Side menu, working column, preview. */
		grid-template-columns: minmax(190px, 240px) minmax(0, 1fr) minmax(0, 1.05fr);
	}

	/* With no preview the third column has nothing to hold, so it's not reserved. */
	.pomp-layout--no-preview {
		grid-template-columns: minmax(190px, 240px) minmax(0, 1fr);
		align-items: start;
		gap: 40px;
	}

	.pomp-preview-column {
		position: sticky;
		top: calc(var(--pomp-bar-height) + 24px);
	}
}

/* ---------------------------------------------------------------
 * Desktop stage (once there's something to show)
 *
 * Reuses the mobile stage's own classes rather than a parallel set of
 * desktop-only ones - every rule here only takes effect at this width
 * (the classes' original, mobile-only rules all live inside the
 * max-width: 899px query above, so the two never collide), which is what
 * lets the product-pick row push the photo down under it in plain
 * document flow here too, with nothing measured in JS to keep in sync.
 *
 * The fields panel is a third grid column, sticky within it (the usual
 * "buy box" pattern most sites use for this - a fixed panel pinned to
 * the screen's own edge was tried first, but that's non-standard for
 * good reason: it reads as blocking whatever's behind it rather than
 * living alongside the page the way a sticky sidebar does, and it very
 * literally did, covering the theme's own cart/account links). Capped at
 * its own viewport-relative max-height with its own scrollbar, so an
 * unusually tall step doesn't push the sticky position itself off
 * screen. What's different from the plain three-column layout used
 * before there's a canvas: the product-pick row sits above the photo,
 * and the fields column is what's sticky now, not the photo.
 * ------------------------------------------------------------ */

@media (min-width: 900px) {
	.pomp-layout--stage {
		grid-template-columns: minmax(190px, 240px) minmax(0, 1fr) var(--pomp-desktop-panel-width);
		align-items: start;
		gap: 40px;
	}

	.pomp-mobile-stage--desktop {
		position: sticky;
		top: calc(var(--pomp-bar-height) + 24px);
	}

	/* Already sticky by itself above (see .pomp-preview-column, min-width:
	   900px) - stacking that on top of the stage's own sticky position
	   would offset it twice over. */
	.pomp-mobile-stage--desktop .pomp-preview-column {
		position: static;
	}

	.pomp-mobile-stage--desktop .pomp-product-quick-pick__clip {
		overflow: hidden;
		background: var(--pomp-bg);
		transition: height .3s ease;
	}

	/* The general rule for this width (further up this file) hides the
	   mobile copy of the row and shows the one built into the step panel
	   instead - here it's the reverse: this copy is the one meant to show
	   (see .pomp-mobile-sheet--desktop .pomp-product-quick-pick--panel below,
	   which hides that other one so the row isn't shown twice). */
	.pomp-mobile-stage--desktop .pomp-product-quick-pick--mobile {
		display: block;
		padding: 0 0 20px;
	}

	.pomp-mobile-sheet--desktop {
		position: sticky;
		top: calc(var(--pomp-bar-height) + 24px);
		max-height: calc(100vh - var(--pomp-bar-height) - 48px);
		overflow-y: auto;
		padding: 28px;
		background: #ffffff;
		border: 1px solid var(--pomp-line);
		border-radius: 16px;
		box-shadow: 0 12px 32px rgba(0, 0, 0, .08);
	}

	.pomp-mobile-sheet--desktop .pomp-product-quick-pick--panel {
		display: none;
	}
}

/* ---------------------------------------------------------------
 * Mobile bottom sheet (phone only, once a canvas exists)
 *
 * The preview fills a stage that stays put while the page scrolls; the
 * step menu and every step's fields live in a sheet dragged over it,
 * snapping between a low peek, half height, and nearly full. Replaces
 * the old floating "jump to preview" shortcut - with the preview
 * always in view there's nothing left to jump to.
 * ------------------------------------------------------------ */

@media (max-width: 899px) {
	/* Fixed, not sticky: the stage has nothing taller than itself around
	   it to stick within (it's the shortcode's only mobile content), so
	   sticky would just scroll away with the page. Pinned below the
	   theme's own bar, same offset the desktop preview already sticks to. */
	.pomp-mobile-stage {
		--pomp-product-pick-height: 0px;
		position: fixed;
		top: var(--pomp-bar-height);
		left: 0;
		right: 0;
		height: calc(100vh - var(--pomp-bar-height));
		height: calc(100dvh - var(--pomp-bar-height));
		overflow: hidden;
		background: var(--pomp-bg);
		/* The theme's own header (.pomp-site-header) is fixed too, at z-index:
		   1000 - without clearing that, it sits on top of the stage (and
		   the sheet, and the product-pick row's thumbnail) instead of
		   behind it. This is the only content on the page once the stage
		   takes over, so it wins outright. */
		z-index: 1001;
	}

	/* Holds the product-pick row and the preview, in normal flow (not
	   pinned by a top offset measured in JS) - the preview simply comes
	   after the row, so it starts exactly where the row's own (possibly
	   still animating) box currently ends, every single frame, guaranteed
	   by the browser's own layout rather than by a JS-measured height fed
	   back in through a CSS variable one React commit later. That JS/CSS
	   relay is exactly what let the preview run behind the row after
	   choosing a product mid-way through the row growing a colour swatch
	   line onto itself - normal flow can't drift out of sync like that,
	   because there's nothing left to keep in sync.
	   The photo shows at its full, uncropped height now (see .pomp-preview
	   below), so this box scrolls on its own when that plus the row above
	   it runs taller than the room below the bar - capped at the sheet's
	   collapsed height so its peek always stays reachable, whatever the
	   sheet's current position is (this box doesn't scroll the sheet
	   itself; that's a sibling, not a child, of it). */
	.pomp-mobile-stage__scroll {
		position: absolute;
		top: 0;
		left: 0;
		right: 0;
		bottom: 16%;
		overflow-y: auto;
		-webkit-overflow-scrolling: touch;
		overscroll-behavior-y: contain;
	}

	.pomp-mobile-stage__scroll > .pomp-preview-column {
		display: flex;
		align-items: center;
		justify-content: center;
	}

	/* Its own height is set inline (ownHeightState in configurator.js) and
	   clipped here, so growing or shrinking that height - a colour row
	   appearing, the row collapsing back to one thumbnail - reads as the
	   row itself animating, and the preview below simply follows since
	   it's the very next thing in flow. */
	.pomp-mobile-stage__scroll > .pomp-product-quick-pick__clip {
		overflow: hidden;
		background: var(--pomp-bg);
		transition: height .3s ease;
	}

	/* Always spans the full width of the phone (edge to edge, like the
	   product photo itself) - height follows from that via the image's own
	   aspect ratio, same as the general .pomp-preview__svg rule, and is never
	   cropped: however tall that makes it, the scroll box above is what
	   gives it the room, rather than shrinking the photo down to fit or
	   cropping the top/bottom of it. */
	.pomp-mobile-stage .pomp-preview {
		width: 100%;
	}

	.pomp-mobile-sheet {
		position: absolute;
		left: 0;
		right: 0;
		bottom: 0;
		display: flex;
		flex-direction: column;
		background: #ffffff;
		border-top: 1px solid var(--pomp-line);
		box-shadow: 0 -8px 24px rgba(0, 0, 0, .16);
		height: 55%;
		/* Stops 5% of the stage's height short of the product-pick row
		   above (--pomp-product-pick-height, the row's own measured height -
		   see productPickHeightState in configurator.js) instead of the
		   "full" snap's fixed 92%, which could run past the row when it's
		   taller than that 8% gap allows and end up tucked behind it (the
		   row sits above the sheet in stacking order). Applies during an
		   active drag too, since that also sets height directly. */
		max-height: calc( 100% - var( --pomp-product-pick-height ) - 5% );
		transition: height .3s cubic-bezier(.32, .72, 0, 1);
	}

	/* No transition mid-drag - the sheet must track the finger exactly,
	   not ease toward it a frame behind. */
	.pomp-mobile-sheet.is-dragging {
		transition: none;
	}

	.pomp-mobile-sheet--collapsed {
		height: 16%;
	}

	.pomp-mobile-sheet--half {
		height: 55%;
	}

	.pomp-mobile-sheet--full {
		height: 92%;
	}

	/* Sized and positioned to cover the grip icon's own full visual footprint
	   (56px, centred 12px above the sheet's edge - see .pomp-mobile-sheet__grip
	   below), not just a thin strip flush with the sheet's top. The icon
	   itself is pointer-events: none, so touches on it fall through to
	   whatever's underneath at that screen position - previously that was
	   only this handle for the sliver actually inside the sheet, and the
	   scrolling preview behind it for the rest of the (now bigger) icon
	   poking out above, which both missed the drag entirely and could
	   trigger the browser's own pull-to-refresh over the preview's scroll
	   area. Taken out of flow (position: absolute) so it can extend above
	   the sheet's own top edge without pushing its content down - see the
	   matching top padding on .pomp-mobile-sheet__scroll below, which is what
	   actually reserves that room now. */
	.pomp-mobile-sheet__handle {
		position: absolute;
		top: -44px;
		left: 0;
		right: 0;
		height: 80px;
		touch-action: none;
		cursor: grab;
	}

	.pomp-mobile-sheet.is-dragging .pomp-mobile-sheet__handle {
		cursor: grabbing;
	}

	/* Straddles the sheet's own top edge - half sitting over the preview
	   behind it, half over the handle row - instead of sitting flush inside
	   it, so it reads as a handle on the sheet rather than one more row of
	   content in it. The handle row still owns the actual drag gesture
	   (the pointer handlers are on it, not this icon), so this stays
	   click-through. */
	.pomp-mobile-sheet__grip {
		position: absolute;
		/* This positions the icon's CENTRE (translate(-50%,-50%) below turns
		   "top" into a centre-point, not an edge), 12px above the sheet's
		   own edge - exactly the amount the chip grew by (44px to 56px), so
		   the part sitting over the sheet stays the same size it was, and
		   only the part poking out above got bigger. .pomp-mobile-sheet__handle
		   (this icon's containing block, since it's the positioned parent)
		   now starts 44px above the sheet's edge, not flush with it, so the
		   value here is relative to THAT, not to the sheet: -12px above the
		   sheet works out to handle-top + 32px. */
		top: 32px;
		left: 50%;
		transform: translate(-50%, -50%);
		width: 56px;
		height: 56px;
		padding: 8px 15px 4px 1px;
		border: 1px solid rgba(0, 0, 0, .16);
		border-radius: 50%;
		background-color: #ffffff;
		/* Same drop shadow as .pomp-mobile-sheet itself, so the chip reads as
		   lifted off the preview behind it the same way the sheet is. */
		box-shadow: 0 -8px 24px rgba(0, 0, 0, .16);
		background-image: url(../svg/drag.svg);
		background-repeat: no-repeat;
		background-position: center;
		background-size: contain;
		/* Sized to the padded content box, not the padding/border too - so
		   the icon stays clear of the border instead of touching it. */
		background-origin: content-box;
		pointer-events: none;
	}

	.pomp-mobile-sheet__scroll {
		flex: 1 1 auto;
		overflow-y: auto;
		-webkit-overflow-scrolling: touch;
		overscroll-behavior-y: contain;
		/* The handle used to reserve this room itself, by being an in-flow
		   row with vertical padding; it's absolutely positioned now (see
		   .pomp-mobile-sheet__handle above), so it no longer pushes this
		   down on its own. */
		padding: 20px var(--pomp-gutter) 24px;
	}

	/* Inside the sheet the step bar is one more scrollable block, not a
	   pinned strip - the .pomp-menu phone rules above still apply. */
	.pomp-mobile-sheet .pomp-menu {
		margin-top: 0;
	}
}

/* ---------------------------------------------------------------
 * Preview
 * ------------------------------------------------------------ */

/* Preview with no frame, the image sits freely on the background, like theirs. */
.pomp-preview {
	position: relative;
	overflow: hidden;
}

/* The design rendered by the server sits over the SVG preview. The SVG stays
   underneath and covers the time spent typing, so there's no gap or flash.
   The image appears with a short transition, so the swap doesn't jump. */
.pomp-preview__rendered {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
	background-repeat: no-repeat;
	background-position: center;
	background-size: cover;
	animation: pomp-rendered-in .18s ease both;
}

/* Without a product the render carries only the graphic on a transparent
   background, so it's used as a mask over a solid colour - the same
   technique and the same colour as in the SVG underneath. The crop has to
   be "contain", to match the fit used in the SVG. */
.pomp-preview__ink {
	position: absolute;
	inset: 0;
	display: block;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
}

@keyframes pomp-rendered-in {
	from { opacity: 0; }
	to   { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
	.pomp-preview__rendered {
		animation: none;
	}
}

.pomp-preview--empty {
	display: flex;
	align-items: center;
	justify-content: center;
	aspect-ratio: 1 / 1;
	background-color: transparent;
	background-repeat: no-repeat;
	background-position: center;
	background-size: cover;
	border-style: dashed;
	border-color: var(--pomp-line);
}

.pomp-preview__placeholder {
	font-family: var(--pomp-mono);
	font-weight: 400;
	text-transform: uppercase;
	letter-spacing: -.03em;
	font-size: 19px;
	color: var(--pomp-muted);
	/* The mono font has the same "invisible padding-bottom" as the display
	   face on UPPERCASE text - the same shift, with the brackets nudged
	   back separately. */
	transform: translateY(.12em);
}

.pomp-preview__placeholder::before,
.pomp-preview__placeholder::after {
	content: "";
	display: inline-block;
	width: .35em;
	height: 1em;
	background-color: currentColor;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
	vertical-align: middle;
	transform: translateY(-.12em);
}

.pomp-preview__placeholder::before {
	margin-right: .3em;
	-webkit-mask-image: url(../svg/bracket_left.svg);
	mask-image: url(../svg/bracket_left.svg);
}

.pomp-preview__placeholder::after {
	margin-left: .3em;
	-webkit-mask-image: url(../svg/bracket_right.svg);
	mask-image: url(../svg/bracket_right.svg);
}

.pomp-preview__svg {
	display: block;
	width: 100%;
	height: auto;
}

/* Stands in for the entered name on a real product while the server's own
   curves are still on their way - a crosshair, a nod to a print
   registration mark, rather than the placeholder text that would otherwise
   have to be swapped out from under the customer a moment later. Each arm's
   own back-and-forth sweep is animated directly on its SVG coordinates (see
   configurator.js), since a CSS transform here would be in the wrong
   coordinate space - this class only sets its resting opacity. */
.pomp-preview__loader {
	opacity: .75;
}

@media (prefers-reduced-motion: reduce) {
	.pomp-preview__loader {
		opacity: .6;
	}
}

/* ---------------------------------------------------------------
 * Links to the design's page
 *
 * They sit above the grid, exactly where the category filter used to be.
 * Browsing by category lives at /natpisi/; the configurator is a step, so
 * only two exits lead from here back to that list.
 * ------------------------------------------------------------ */

.pomp-designlinks {
	display: flex;
	flex-wrap: wrap;
	gap: 4px 28px;
	margin: 24px 0 8px;
}

.pomp-designlinks .pomp-button {
	flex: 0 0 auto;
}

/* ---------------------------------------------------------------
 * Fields
 * ------------------------------------------------------------ */

.pomp-search,
.pomp-input {
	width: 100%;
	padding: 14px 0;
	font-family: var(--pomp-mono);
	font-size: 24px;
	letter-spacing: -.03em;
	color: var(--pomp-ink);
	background: transparent;
	border: 0;
	border-bottom: 1px solid var(--pomp-ink);
	border-radius: 0;
}

.pomp-search::placeholder,
.pomp-input::placeholder {
	color: var(--pomp-muted);
	text-transform: uppercase;
}

.pomp-search:focus,
.pomp-input:focus {
	outline: 0;
	border-bottom-color: var(--pomp-accent);
}

.pomp-input.is-invalid {
	border-bottom-color: var(--pomp-accent);
}

.pomp-label {
	display: block;
	margin-bottom: 2px;
}

.pomp-hint {
	margin: 10px 0 0;
	color: var(--pomp-muted);
}

.pomp-hint--error,
.pomp-error {
	color: var(--pomp-accent);
}

/* Text boxes: one per line of the design. The gap is bigger than the gap
   inside a single box, so the "label + field" pair reads as one unit. */
.pomp-rows {
	display: flex;
	flex-direction: column;
	gap: 26px;
}

/* A line can carry several boxes and fixed parts. The rule along the left
   edge holds them together, so it's clear what belongs to the same line. */
.pomp-row {
	display: flex;
	flex-direction: column;
	gap: 10px;
	padding-left: 14px;
	border-left: 2px solid var(--pomp-line);
}

/* A line with no box at all isn't something the customer changes, so it
   doesn't need the rule either. */
.pomp-row--fixed {
	border-left-color: transparent;
}

/* The fixed part of a line: the customer sees it but can't change it. It's
   set in the display font and ink colour, so it reads as part of the design
   rather than an instruction - otherwise it blends into the small box labels
   above the field. */
.pomp-row__fixed {
	font-family: var(--pomp-display, inherit);
	font-size: clamp(1.9rem, 3.4vw, 2.6rem);
	line-height: .95;
	color: var(--pomp-ink);
	text-transform: uppercase;
	overflow-wrap: anywhere;
}

.pomp-row__slot {
	display: block;
}

/* The character-count note sits right by its own box, so it needs less
   spacing than when it was the only one in the step. */
.pomp-row .pomp-hint {
	margin-top: 6px;
}

.pomp-error {
	font-family: var(--pomp-mono);
	font-weight: 400;
	text-transform: uppercase;
	letter-spacing: -.03em;
	font-size: 19px;
	margin: 0 0 20px;
	padding: 12px 14px;
	border: 1px solid var(--pomp-accent);
	background: transparent;
}

.pomp-success {
	font-family: var(--pomp-mono);
	font-weight: 400;
	text-transform: uppercase;
	letter-spacing: -.03em;
	font-size: 19px;
	margin: 0 0 20px;
	padding: 12px 14px;
	border: 1px solid var(--pomp-ink);
}

/* ---------------------------------------------------------------
 * Cards
 * ------------------------------------------------------------ */

.pomp-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
	gap: 20px 16px;
	margin: 20px 0 0;
}

.pomp-card {
	display: flex;
	flex-direction: column;
	gap: 8px;
	padding: 0;
	border: 0;
	background: transparent;
	cursor: pointer;
	text-align: left;
	font: inherit;
	color: inherit;
	text-decoration: none;
}

.pomp-card:focus,
.pomp-card:focus-visible,
.pomp-card__image:focus,
.pomp-card__image:focus-visible {
	outline: none;
}

.pomp-card__image {
	width: 100%;
	/* height:auto is needed, otherwise the img's width/height attributes override aspect-ratio. */
	height: auto;
	aspect-ratio: 1 / 1;
	object-fit: contain;
	background: var(--pomp-ink);
	border: 1px solid transparent;
	transition: border-color .15s ease, opacity .15s ease;
}

/* Design cards: usually a product mounted behind the design (an inline SVG
   with its own real photo, so no background is set here); the rare card
   with no product at all falls back to a plain neutral background-color,
   set inline per card - see Pomp_Catalog::render_archive() and DesignSearch. */
.pomp-card--design .pomp-card__image {
	position: relative;
	background-color: transparent;
	background-repeat: no-repeat;
	background-position: center;
	background-size: cover;
}

/* A real <svg> now (not a CSS mask on a span) - clipping the baked-in
   frame and colouring both happen inside the SVG itself (viewBox +
   <mask>), so there's no distortion when a card isn't square. */
.pomp-card__design {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	display: block;
	-webkit-box-shadow: 2px 3px 10px 0px rgba(0, 0, 0, 0.36);
	box-shadow: 2px 3px 10px 0px rgba(0, 0, 0, 0.36);
}

/* A design with no graphic: the card shows the name as typography, in the
   same colour the graphic would have had. The text wraps and fits inside
   the card. */
.pomp-card__design--text {
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 8% 10%;
	font-family: var(--pomp-display, inherit);
	font-size: clamp(1.1rem, 3.2vw, 2.2rem);
	line-height: 1;
	text-align: center;
	text-transform: uppercase;
	text-wrap: balance;
	overflow-wrap: anywhere;
	/* Inherits its shadow from .pomp-card__design, so text-only cards sit the
	   same way as ones with a graphic. */
}

.pomp-card:hover .pomp-card__image {
	opacity: .82;
}

.pomp-card.is-selected .pomp-card__image {
	border-color: var(--pomp-accent);
}

.pomp-card.is-disabled {
	opacity: .35;
	cursor: not-allowed;
}

.pomp-card__title {
	color: var(--pomp-ink);
}

/* The price is black and bold, like theirs; a sale price is red. */
.pomp-card__price {
	color: var(--pomp-ink);
}

.pomp-card__price del {
	opacity: .5;
}

.pomp-card__price ins {
	text-decoration: none;
	color: var(--pomp-accent);
}

/* Product images are photos, they need a light background. */
.pomp-step--products .pomp-card__image {
	background: #ffffff;
	border: 1px solid var(--pomp-line);
}

/* Quick-pick row: the top-priority products (set per product in its own
   settings), as small thumbnails - "More products" below opens the full
   grid above, with every eligible product. */
.pomp-product-quick {
	display: flex;
	flex-wrap: wrap;
	margin: 20px 0 0;
}

/* Every button in the row - product/colour swatches, the "more" tile, the
   "none" clear button - carries its own 4px margin instead of a gap on the
   row, so the same spacing applies whether the row wraps (desktop) or
   scrolls in one line (mobile), and each button is free to be a different
   width (the clear button, unlike the square swatches) without throwing
   the others off. */
.pomp-product-quick__item,
.pomp-product-quick__more,
.pomp-product-quick__clear {
	margin: 4px;
}

.pomp-product-quick__item {
	width: 70px;
	height: 70px;
	padding: 0;
	border: 1px solid var(--pomp-line);
	border-radius: 8px;
	background: #ffffff;
	cursor: pointer;
	overflow: hidden;
	transition: transform .15s cubic-bezier(.34, 1.56, .64, 1), box-shadow .15s ease;
}

.pomp-product-quick__item img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	display: block;
}

.pomp-product-quick__item:hover:not(.is-disabled) {
	transform: scale(1.06);
}

.pomp-product-quick__item:focus,
.pomp-product-quick__item:focus-visible {
	outline: none;
}

.pomp-product-quick__item.is-selected {
	border-color: var(--pomp-accent);
	box-shadow: 0 0 0 2px var(--pomp-accent);
}

.pomp-product-quick__item.is-disabled {
	opacity: .35;
	cursor: not-allowed;
}

.pomp-product-quick__more {
	width: 70px;
	height: 70px;
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
	font-size: 11px;
	line-height: 1.3;
	padding: 4px;
	border: 1px dashed var(--pomp-line);
	border-radius: 8px;
	background: transparent;
	cursor: pointer;
	color: inherit;
}

.pomp-product-quick__more:hover {
	border-color: var(--pomp-accent);
	color: var(--pomp-accent);
}

/* Same row, shown earlier - alongside name/text/artwork entry, before the
   dedicated product step - so it carries its own label and a little
   breathing room instead of sitting flush against what's above it. */
.pomp-product-quick--inline {
	margin-top: 24px;
}

/* Two copies of the row exist in the markup, same convention as
   .pomp-design-tab--panel / .pomp-design-tab--mobile: one inline in the panel, one
   above the preview stage. Mobile-first: the panel copy (buried in the
   sheet the customer has to drag up) stays hidden until the layout has
   room to show both side by side; the standalone copy above the stage
   takes over below that, so a mobile visitor sees straight away that
   there's more than one product on offer, without any extra step. */
.pomp-product-quick-pick--panel {
	display: none;
}

.pomp-product-quick-pick--mobile {
	display: block;
	/* Bottom padding isn't just breathing room: the selected item's ring
	   (box-shadow, so it doesn't add to layout height) needs somewhere to
	   sit inside the row's own measured height, or the clip wrapper above
	   (height set to that exact measurement, overflow: hidden) cuts its
	   bottom edge off. */
	padding: 10px var(--pomp-gutter) 6px;
}

/* Compact: this copy competes with the preview itself for room in a
   fixed-height stage, so it trades the wrapping grid and the label for a
   single scrollable row of smaller thumbnails - a mug and a t-shirt icon
   need no caption to be understood. */
.pomp-product-quick-pick--mobile .pomp-product-quick {
	margin-top: 0;
	flex-wrap: nowrap;
	overflow-x: auto;
	scrollbar-width: none;
	-webkit-mask-image: linear-gradient(to right, transparent 0, #000 14px, #000 calc(100% - 14px), transparent 100%);
	mask-image: linear-gradient(to right, transparent 0, #000 14px, #000 calc(100% - 14px), transparent 100%);
}

.pomp-product-quick-pick--mobile .pomp-product-quick::-webkit-scrollbar {
	display: none;
}

.pomp-product-quick-pick--mobile .pomp-product-quick__item,
.pomp-product-quick-pick--mobile .pomp-product-quick__more,
.pomp-product-quick-pick--mobile .pomp-product-quick__clear {
	width: 52px;
	height: 52px;
	flex: 0 0 auto;
}

.pomp-product-quick-pick--mobile .pomp-product-quick__label {
	display: none;
}

/* The row-reset above (margin-top: 0) would otherwise leave the colour row
   flush against the product row - put back some of the breathing room the
   desktop panel gets from .pomp-product-quick--inline's own margin-top,
   scaled down to fit the compact mobile row. */
.pomp-product-quick-pick--mobile .pomp-product-quick--variation {
	margin-top: 14px;
}

/* The settled state: a thumbnail of whatever's actually chosen, and a
   plain link back to the full row above - costs a fraction of the space
   the row itself needs, so the preview gets to keep the rest. */
.pomp-product-quick-pick--collapsed {
	padding: 10px var(--pomp-gutter);
}

.pomp-product-quick__current {
	display: flex;
	align-items: center;
	gap: 10px;
	padding: 0;
	border: 0;
	background: none;
	color: inherit;
	cursor: pointer;
	text-align: left;
}

.pomp-product-quick__current img {
	width: 44px;
	height: 44px;
	flex: 0 0 auto;
	object-fit: contain;
	border: 1px solid var(--pomp-line);
	border-radius: 8px;
	background: #ffffff;
}

/* Same bordered-chip look as .pomp-product-quick__clear (the "Auto" button),
   sized to its own text instead of forced into that button's fixed square -
   a whole phrase needs the room, and there's nothing else in this row for
   it to line up with anyway. */
.pomp-product-quick__change {
	display: inline-flex;
	align-items: center;
	padding: 10px 14px;
	border: 1px solid var(--pomp-line);
	border-radius: 8px;
	color: var(--pomp-accent);
	white-space: nowrap;
	transition: border-color .15s ease, color .15s ease;
}

.pomp-product-quick__current:hover .pomp-product-quick__change {
	border-color: var(--pomp-accent);
}

@media (min-width: 900px) {
	/* Desktop: the copy inline in the panel, alongside the step it belongs to. */
	.pomp-product-quick-pick--panel {
		display: block;
	}

	/* The mobile copy (above pomp-preview) isn't shown on desktop, where the
	   panel and the preview already sit side by side. */
	.pomp-product-quick-pick--mobile {
		display: none;
	}
}

.pomp-product-quick__label {
	display: block;
	width: 100%;
	margin-bottom: 10px;
	color: var(--pomp-accent);
}

/* The design catalogue's own row: every card mounted on the chosen
   product instead of its own random placeholder, so it sits above the
   grid with room on both sides. */
.pomp-product-quick--catalog {
	align-items: center;
	margin-bottom: 28px;
}

.pomp-product-quick--catalog .pomp-product-quick__label {
	width: auto;
	margin: 0 4px 0 0;
}

/* Same footprint as the swatch buttons it sits beside (.pomp-product-quick__item)
   rather than sized to fit its own text, so it reads as one more option in
   the row instead of an odd-sized outlier. */
.pomp-product-quick__clear {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 70px;
	height: 70px;
	padding: 4px;
	border: 1px solid var(--pomp-line);
	border-radius: 8px;
	color: var(--pomp-muted);
	text-decoration: none;
	text-align: center;
	font-size: 13px;
	line-height: 1.2;
	transition: border-color .15s ease, color .15s ease;
}

.pomp-product-quick__clear:hover {
	border-color: var(--pomp-accent);
	color: var(--pomp-accent);
}

/* A design mounted on the chosen product fills its card exactly like the
   placeholder image it replaces - the SVG carries its own real size
   (canvas width/height), so it has to be told to fill the box instead. */
.pomp-card__mounted {
	display: block;
	width: 100%;
	height: 100%;
}

/* ---------------------------------------------------------------
 * Variations
 * ------------------------------------------------------------ */

.pomp-attribute {
	margin: 0 0 40px;
}

.pomp-attribute__label {
	display: block;
	margin-bottom: 12px;
}

/*
 * Price like on their own product page: red display face, in round
 * brackets.
 */
.pomp-attribute__price {
	font-family: var(--pomp-display);
	font-size: 23px;
	letter-spacing: .01em;
	text-transform: uppercase;
	color: var(--pomp-accent);
	margin: 0 0 4px;
}

.pomp-attribute__price::before {
	content: "(";
}

.pomp-attribute__price::after {
	content: ")";
}

.pomp-variations {
	display: flex;
	flex-wrap: wrap;
	gap: 4px 14px;
	margin: 0;
}

/*
 * Chips are selectors: display text in thin angle brackets. On hover a red
 * hand-drawn strike is drawn through the text, and the selected one gets
 * white text on a circular brush stroke, exactly like their own size picker.
 */
.pomp-chip {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 2px;
	position: relative;
	padding: 6px 2px;
	/* A minimum width - so S/M/L (a single letter) aren't narrow/stretched,
	   but get the same "breathing room" as XL/XXL. */
	min-width: 64px;
	border: 0;
	background: transparent;
	color: var(--pomp-ink);
	cursor: pointer;
	font: inherit;
	font-family: var(--pomp-display);
	text-transform: uppercase;
	letter-spacing: .01em;
	font-size: 20px;
	line-height: 1;
}

.pomp-chip::before,
.pomp-chip::after {
	content: "";
	display: inline-block;
	width: .61em;
	height: 1.5em;
	background-color: currentColor;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
	vertical-align: middle;
}

.pomp-chip::before {
	-webkit-mask-image: url(../svg/bracket_left.svg);
	mask-image: url(../svg/bracket_left.svg);
}

.pomp-chip::after {
	-webkit-mask-image: url(../svg/bracket_right.svg);
	mask-image: url(../svg/bracket_right.svg);
}

/* Hover: the brackets grow slightly. */
.pomp-chip:hover:not(.is-disabled)::before,
.pomp-chip:hover:not(.is-disabled)::after {
	transform: scale(1.25);
}

/* A circular brush stroke behind the selected one, wider and taller than the text, like theirs. */
.pomp-chip.is-selected {
	color: var(--pomp-on-brush);
}

.pomp-chip::before,
.pomp-chip::after {
	position: relative;
	z-index: 2;
}

/* The brush circle behind the selected one - now covers the WHOLE chip
 * (letters and brackets), not just the letters, and instead of a
 * display:none/block toggle (which can't be animated) uses an
 * opacity/scale transition. */
.pomp-chip__brush {
	position: absolute;
	left: 50%;
	top: 50%;
	width: 170%;
	height: 170%;
	/* A minimum size - so the circle isn't narrower/smaller for S/M/L (a
	   single letter) than for the wider sizes, matching the min-width on
	   .pomp-chip itself. */
	min-width: 84px;
	min-height: 84px;
	transform: translate(-50%, -50%) scale(.6);
	z-index: 1;
	/* A mask over a plain colour, not a picture, so the stroke takes the
	   button colour. */
	background: var(--pomp-brush);
	-webkit-mask: var(--pomp-circle) no-repeat 50% 50% / 60% 60%;
	mask: var(--pomp-circle) no-repeat 50% 50% / 60% 60%;
	opacity: 0;
	pointer-events: none;
	transition: opacity .25s ease, transform .3s cubic-bezier(.34, 1.56, .64, 1);
}

.pomp-chip.is-selected .pomp-chip__brush {
	opacity: 1;
	transform: translate(-50%, -50%) scale(1);
}

.pomp-chip__label {
	position: relative;
	z-index: 2;
	/* The display font (--pomp-display) doesn't use the space reserved for
	   descenders on UPPERCASE text, so the letters visually sit too high
	   within the centred line - a slight downward shift corrects that
	   without touching the brackets beside it. */
	transform: translateY(.1em);
}

.pomp-chip.is-disabled {
	opacity: .25;
	cursor: not-allowed;
}

.pomp-chip__price {
	color: inherit;
	opacity: .7;
}

/* Tighter on a phone, so a full row of sizes (S/M/L/XL/XXL) fits on one line
   instead of wrapping to a second. It has to sit after the rules above: the
   base .pomp-chip sets a wider minimum at the same specificity, so while this
   block stood before it, nothing in it ever applied - measured at 390px, where
   XXL still fell to a second row. The brush stroke shrinks with the chip, or
   it would be wider than the button it sits behind. */
@media (max-width: 899px) {
	.pomp-variations {
		gap: 4px 4px;
	}

	.pomp-chip {
		min-width: 40px;
		padding: 6px 0;
		font-size: 15px;
	}

	.pomp-chip__brush {
		min-width: 52px;
		min-height: 52px;
	}
}

/* ---------------------------------------------------------------
 * Colour/image swatches, for attributes set up as WooCommerce's own
 * "Color"/"Image" type. Each swatch is just a thick border in its own
 * colour. There's only one shared, filled dot (.pomp-swatch__dot), which
 * "jumps" to the selected one with an animation.
 * ------------------------------------------------------------ */

.pomp-variations--visual {
	position: relative;
	gap: 12px;
	align-items: center;
}

.pomp-swatch {
	position: relative;
	/* A theme may give every button a minimum height - WoodMart's base.css
	   does, 42px - which stretched these 30px circles into eggs (30 x 42,
	   measured). Kept exactly round, and out of the row's flex sizing. */
	flex: none;
	width: 30px;
	height: 30px;
	min-width: 0;
	min-height: 0;
	padding: 0;
	border: 4px solid rgba(0, 0, 0, .16);
	border-radius: 50%;
	background-color: transparent;
	cursor: pointer;
	transition: transform .15s cubic-bezier(.34, 1.56, .64, 1);
}

/* A swatch representing an image (a rare case) stays fully filled, a border wouldn't make sense. */
.pomp-swatch--image {
	border: 0;
	background-color: #fff;
	background-size: cover;
	background-position: center;
	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .16);
}

.pomp-swatch--image.is-selected {
	box-shadow: 0 0 0 2px var(--pomp-accent);
}

.pomp-swatch:hover:not(.is-disabled) {
	transform: scale(1.08);
}

.pomp-swatch:focus,
.pomp-swatch:focus-visible {
	outline: none;
}

.pomp-swatch.is-disabled {
	cursor: not-allowed;
	opacity: .4;
	border: 0;
}

.pomp-swatch.is-disabled:not(.pomp-swatch--image) {
	background-color: rgba(0, 0, 0, .16);
}

.pomp-swatch.is-disabled::before {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: 50%;
	background: linear-gradient(
		to top right,
		transparent calc(50% - 1px),
		rgba(0, 0, 0, .55) calc(50% - 1px) calc(50% + 1px),
		transparent calc(50% + 1px)
	);
}

/* The shared filled dot - the only "inside" in the whole row, jumps from
 * position to position when the selection changes. */
.pomp-swatch__dot {
	position: absolute;
	width: 13px;
	height: 13px;
	border-radius: 50%;
	background-size: cover;
	background-position: center;
	transform: translate(-50%, -50%);
	transition: left .3s cubic-bezier(.34, 1.56, .64, 1), top .3s cubic-bezier(.34, 1.56, .64, 1), background-color .2s ease;
	pointer-events: none;
}

/* ---------------------------------------------------------------
 * Changing the text on a button - fade-out then fade-in (e.g. "Choose a
 * colour" -> "Choose a size"), no sliding and no external animation library.
 * ------------------------------------------------------------ */

.pomp-fade-button__label {
	display: inline-block;
	opacity: 1;
	transition: opacity .18s ease;
}

.pomp-fade-button__label.is-hidden {
	opacity: 0;
}

/* ---------------------------------------------------------------
 * Summary
 * ------------------------------------------------------------ */

.pomp-summary {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: 10px 20px;
	margin: 0 0 24px;
	padding: 18px 0 0;
	border-top: 1px solid var(--pomp-ink);
}

.pomp-summary dt {
	color: var(--pomp-muted);
}

.pomp-summary dd {
	margin: 0;
	color: var(--pomp-ink);
}

.pomp-summary dd:last-of-type {
	font-family: var(--pomp-display);
	font-size: 23px;
	letter-spacing: .01em;
	color: var(--pomp-accent);
}

.pomp-summary dd:last-of-type::before {
	content: "(";
}

.pomp-summary dd:last-of-type::after {
	content: ")";
}

/* Whatever a plugin hooked onto "woocommerce_before/after_add_to_cart_button"
   for this product (a size guide's own link is the common case) - unstyled
   on purpose, since it's the plugin's own markup, not ours; just enough
   margin to sit apart from the button row next to it. */
.pomp-product-extra {
	margin: 10px 0;
}

/*
 * The theme's own variation form on the variant step (Pomp_Compat::swatch_form()).
 * What WooCommerce shows under it for the chosen variation - its price and
 * stock - the configurator shows itself.
 */
.pomp-theme-variations table.variations {
	width: 100%;
	margin: 0 0 12px;
	border: 0;
}

.pomp-theme-variations .single_variation_wrap,
.pomp-theme-variations .woocommerce-variation {
	display: none !important;
}

/* ---------------------------------------------------------------
 * Buttons
 * ------------------------------------------------------------ */

.pomp-actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 16px;
	margin-top: 26px;
}

/*
 * Main buttons: display text in thin brackets on a brush stroke - white on
 * black unless the shop sets colours of its own. On hover the brackets grow
 * slightly.
 */
.pomp-button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 22px 46px;
	border: 0;
	-webkit-appearance: none;
	appearance: none;
	/* The stroke is a mask over a plain colour, so it takes the button colour
	   (--pomp-brush) rather than being a black picture. The mask clips the
	   brackets and the text as well, but both sit well inside the stroke -
	   checked at the brackets' hover size too. */
	background: var(--pomp-brush);
	-webkit-mask: var(--pomp-blob) no-repeat 50% 50% / 100% 100%;
	mask: var(--pomp-blob) no-repeat 50% 50% / 100% 100%;
	color: var(--pomp-on-brush);
	font-family: var(--pomp-display);
	font-size: 21px;
	/* Pinned, not left to inherit: a theme's own reset for <button> can
	   (and on at least one real theme, does) set its own weight here,
	   which Anton doesn't have to give - 400 is the only one it ships. */
	font-weight: 400;
	letter-spacing: .05em;
	line-height: 1;
	text-transform: uppercase;
	cursor: pointer;
	text-decoration: none;
	/* The display font (--pomp-display) doesn't use the space reserved for
	   descenders on UPPERCASE text, so the text sits visually too high -
	   a slight downward shift corrects that. The brackets are nudged
	   back separately (they don't have this problem, being SVG masks
	   rather than text in the same font). */
	transform: translateY(.1em);
}

.pomp-button::before,
.pomp-button::after {
	transform: translateY(-.1em);
	content: "";
	display: inline-block;
	width: .61em;
	height: 1.5em;
	background-color: currentColor;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
	vertical-align: middle;
}

.pomp-button::before {
	margin-right: .38em;
	-webkit-mask-image: url(../svg/bracket_left.svg);
	mask-image: url(../svg/bracket_left.svg);
}

.pomp-button::after {
	margin-left: .38em;
	-webkit-mask-image: url(../svg/bracket_right.svg);
	mask-image: url(../svg/bracket_right.svg);
}

.pomp-button:hover:not(:disabled) {
	background: var(--pomp-brush);
	color: var(--pomp-on-brush);
}

.pomp-button:hover:not(:disabled)::before,
.pomp-button:hover:not(:disabled)::after {
	transform: translateY(-.1em) scale(1.25);
}

.pomp-button:focus,
.pomp-button:focus-visible,
.pomp-chip:focus,
.pomp-chip:focus-visible {
	outline: none;
}

.pomp-button:disabled {
	opacity: .5;
	cursor: not-allowed;
}

/* Shown on "Add to cart" while the print-ready SVG is being generated
   server-side - brief (see the README's own numbers), but real, and a
   button that just sits there disabled otherwise reads as stuck. Sized in
   em so it follows the button's own font-size; in the button's own text
   colour, since it sits on that same brush stroke. */
.pomp-spinner {
	display: inline-block;
	width: .85em;
	height: .85em;
	margin-right: .4em;
	border: .13em solid rgba(255, 255, 255, .35);
	border: .13em solid color-mix(in srgb, var(--pomp-on-brush) 35%, transparent);
	border-top-color: var(--pomp-on-brush);
	border-radius: 50%;
	vertical-align: -.1em;
	animation: pomp-spin .7s linear infinite;
}

@keyframes pomp-spin {
	to { transform: rotate(360deg); }
}

/* Secondary action: the same text with no brush stroke, no hover effect at all. */
.pomp-button--ghost {
	padding: 14px 2px;
	background: transparent;
	color: var(--pomp-ink);
}

.pomp-button--ghost:hover,
.pomp-button--ghost:hover:not(:disabled) {
	background: transparent;
	color: var(--pomp-ink);
	font-size: 21px;
}

.pomp-button--ghost:hover::before,
.pomp-button--ghost:hover::after,
.pomp-button--ghost:hover:not(:disabled)::before,
.pomp-button--ghost:hover:not(:disabled)::after {
	transform: translateY(-.1em) scale(1.25);
}

/* At their desktop size, the summary and buttons take up too much
   room on a narrow screen - both shrink, and the spacing around
   them tightens too. */
@media (max-width: 899px) {
	.pomp-summary {
		gap: 6px 14px;
		margin: 0 0 18px;
		padding: 14px 0 0;
	}

	.pomp-summary dd:last-of-type {
		font-size: 19px;
	}

	/* Stacked, not side by side - the primary action (.pomp-fade-button, e.g.
	   "Next") goes full width below, easy to hit with a thumb and hard to
	   miss at the end of a long step, instead of sharing a row where its
	   own width was whatever its text happened to need. Back stays a small
	   text link above it, in the same order they already render in. */
	.pomp-actions {
		flex-direction: column;
		align-items: stretch;
		gap: 10px;
		margin-top: 18px;
	}

	.pomp-actions .pomp-button--ghost {
		align-self: flex-start;
	}

	.pomp-button {
		padding: 15px 30px;
		font-size: 16px;
	}

	.pomp-actions .pomp-fade-button {
		width: 100%;
	}

	.pomp-button--ghost {
		padding: 10px 2px;
		font-size: 16px;
	}
}

/* ---------------------------------------------------------------
 * Catalogue
 * ------------------------------------------------------------ */

.pomp-catalog__search {
	display: flex;
	align-items: flex-end;
	gap: 16px;
	margin: 0 0 28px;
}

.pomp-catalog__search .pomp-search {
	flex: 1 1 auto;
}

.pomp-grid--catalog {
	grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
	gap: 28px 20px;
}

.pomp-pagination {
	display: flex;
	justify-content: center;
	margin: 44px 0 0;
	padding-top: 20px;
	border-top: 1px solid var(--pomp-line);
}

.pomp-pagination .page-numbers {
	display: inline-block;
	padding: 8px 12px;
	margin: 0 2px;
	text-decoration: none;
	color: var(--pomp-muted);
	font-variant-numeric: tabular-nums;
}

.pomp-pagination .page-numbers:hover {
	color: var(--pomp-ink);
}

.pomp-pagination .page-numbers.current {
	color: var(--pomp-accent);
	border-bottom: 1px solid var(--pomp-accent);
}

/* ---------------------------------------------------------------
 * The design's page
 * ------------------------------------------------------------ */

.pomp-single {
	margin-bottom: 4px;
}

.pomp-breadcrumb {
	margin: 0;
}

.pomp-breadcrumb a {
	color: var(--pomp-muted);
	text-decoration: none;
	/* The mono font has the same "invisible padding-bottom" as the display
	   face on UPPERCASE text - the same shift, with the brackets nudged
	   back separately. */
	transform: translateY(.12em);
}

.pomp-breadcrumb a::before,
.pomp-breadcrumb a::after {
	content: "";
	display: inline-block;
	width: .35em;
	height: 1em;
	background-color: currentColor;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
	vertical-align: middle;
	transform: translateY(-.12em);
}

.pomp-breadcrumb a::before {
	margin-right: .3em;
	-webkit-mask-image: url(../svg/bracket_left.svg);
	mask-image: url(../svg/bracket_left.svg);
}

.pomp-breadcrumb a::after {
	margin-left: .3em;
	-webkit-mask-image: url(../svg/bracket_right.svg);
	mask-image: url(../svg/bracket_right.svg);
}

.pomp-breadcrumb a:hover {
	color: var(--pomp-accent);
}

/* ---------------------------------------------------------------
 * Final screen
 * ------------------------------------------------------------ */

.pomp-done__image {
	display: block;
	max-width: 380px;
	height: auto;
	margin: 0 0 22px;
	border: 1px solid var(--pomp-ink);
}

/* ---------------------------------------------------------------
 * Accessibility
 * ------------------------------------------------------------ */

@media (prefers-reduced-motion: reduce) {
	.pomp-card__image,
	.pomp-chip,
	.pomp-button,
	.pomp-steps__label,
	.pomp-step-marker__clip {
		transition: none;
	}
}

.pomp-configurator :focus-visible,
.pomp-catalog :focus-visible {
	outline: none;
}

/* Fields already show focus with the underline, so they don't need an outline too. */
.pomp-search:focus,
.pomp-search:focus-visible,
.pomp-input:focus,
.pomp-input:focus-visible {
	outline: none;
	box-shadow: none;
}

/* Title and intro on a category page. */
.pomp-catalog__title {
	margin: 0 0 10px;
	font-size: clamp(2rem, 6vw, 3.4rem);
	line-height: 1.05;
	letter-spacing: -0.02em;
	text-transform: uppercase;
}

.pomp-catalog__intro {
	max-width: 62ch;
	margin: 0 0 6px;
	opacity: 0.75;
	line-height: 1.5;
}

/*
 * The design's description, and - alongside it - any tab a third-party
 * plugin (a size guide, most often) registered for the chosen product. A
 * small label and its content below; more than one label turns into a row
 * to switch between them (DesignTabs in configurator.js). The same content
 * exists in two copies in the JS, because where it sits in the layout
 * depends on screen width - a single-column grid on a phone follows DOM
 * order, not "order". This is where it's decided which copy shows.
 */
.pomp-design-tab {
	margin-top: 32px;
}

.pomp-design-tab__list {
	display: flex;
	flex-wrap: wrap;
	gap: 20px;
}

.pomp-design-tab__label {
	display: inline-block;
	font-family: var(--pomp-text);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: -.04em;
	font-size: 12px;
	line-height: 1.2;
	color: var(--pomp-ink);
	padding: 0 0 8px;
	border-bottom: 2px solid var(--pomp-accent);
}

/* Inside a row of more than one, only the active label keeps the accent
   underline - the others sit muted. */
.pomp-design-tab__list .pomp-design-tab__label {
	appearance: none;
	background: none;
	border-color: transparent;
	cursor: pointer;
	color: var(--pomp-muted);
}

.pomp-design-tab__list .pomp-design-tab__label:hover {
	color: var(--pomp-ink);
}

.pomp-design-tab__list .pomp-design-tab__label.is-active {
	color: var(--pomp-ink);
	border-bottom-color: var(--pomp-accent);
}

.pomp-design-tab__panel {
	max-width: 62ch;
	margin-top: 14px;
	color: var(--pomp-ink);
	opacity: 0.85;
	line-height: 1.6;
}

/* A size guide is very often exactly this: a plain HTML table. Nothing
   fancy, just enough for it to read cleanly at this content width. */
.pomp-design-tab__panel table {
	width: 100%;
	border-collapse: collapse;
	margin: 1em 0;
	font-size: 14px;
}

.pomp-design-tab__panel th,
.pomp-design-tab__panel td {
	padding: 6px 10px;
	border: 1px solid var(--pomp-line);
	text-align: left;
}

/* Rich text from the editor brings its own <p>, <h2> and so on - the
   panel's own outer spacing is enough, the first/last element doesn't
   need extra. */
.pomp-design-tab__panel > :first-child {
	margin-top: 0;
}

.pomp-design-tab__panel > :last-child {
	margin-bottom: 0;
}

.pomp-design-tab__panel h1,
.pomp-design-tab__panel h2,
.pomp-design-tab__panel h3,
.pomp-design-tab__panel h4 {
	font-family: var(--pomp-display);
	font-weight: 400;
	text-transform: uppercase;
	letter-spacing: .01em;
	line-height: 1.1;
	color: var(--pomp-ink);
	opacity: 1;
	margin: 1em 0 .4em;
}

.pomp-design-tab--panel {
	display: none;
}

.pomp-design-tab--mobile {
	display: block;
}

@media (min-width: 900px) {
	/* Desktop: the copy inside pomp-panel, below the current step. */
	.pomp-design-tab--panel {
		display: block;
	}

	/* The mobile copy (below pomp-preview) isn't shown on desktop. */
	.pomp-design-tab--mobile {
		display: none;
	}
}

/* ---------------------------------------------------------------------------
 * Category filter in the catalogue
 *
 * The same shape as the configurator's steps: name in brackets, number on
 * the right. The difference is these are links, so the whole item has to
 * be clickable, not just the text.
 * ------------------------------------------------------------------------ */

.pomp-catalog__cats {
	margin: 20px 0 28px;
}

.pomp-steps--cats {
	flex-direction: column;
	gap: 10px;
	max-width: 320px;
}

.pomp-steps--cats .pomp-steps__item {
	color: var(--pomp-muted);
}

.pomp-steps__link {
	/* The same look whether it's a link or a button. */
	appearance: none;
	padding: 0;
	border: 0;
	background: none;
	font: inherit;
	text-align: left;
	cursor: pointer;
	display: flex;
	flex: 1 1 auto;
	align-items: baseline;
	justify-content: space-between;
	gap: 16px;
	color: inherit;
	text-decoration: none;
}

.pomp-steps__link:hover,
.pomp-steps__link:focus-visible {
	color: var(--pomp-ink);
}

.pomp-steps--cats .pomp-steps__item.is-active,
.pomp-steps--cats .pomp-steps__item.is-active .pomp-steps__link:hover {
	color: var(--pomp-accent);
}

.pomp-steps--cats .pomp-steps__label {
	font-size: 22px;
}

.pomp-steps--cats .pomp-steps__number {
	font-size: 15px;
}

/* On a wide screen the filter sits beside the grid, not above it. */
@media (min-width: 900px) {
	.pomp-catalog__cats {
		float: left;
		width: 240px;
		margin: 40px 40px 24px 0;
	}
}

/* Title and intro on a category page. */
.pomp-catalog__title {
	margin: 0 0 10px;
	font-size: clamp(2rem, 6vw, 3.4rem);
	line-height: 1.05;
	letter-spacing: -0.02em;
	text-transform: uppercase;
}

.pomp-catalog__intro {
	max-width: 62ch;
	margin: 0 0 6px;
	opacity: 0.75;
	line-height: 1.5;
}

/* ---------------------------------------------------------------
 * The customer's own artwork
 *
 * Sits in the summary, where the product and variant are already known -
 * only then does the server know how large the image needs to be for that
 * print.
 * ------------------------------------------------------------ */

.pomp-artwork {
	margin: 0 0 24px;
}

.pomp-artwork__label {
	display: block;
	margin-bottom: 8px;
	font-family: var(--pomp-mono);
	font-size: 13px;
	letter-spacing: .06em;
	text-transform: uppercase;
}

.pomp-artwork__pick input[type="file"] {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
}

.pomp-artwork__pick {
	position: relative;
	display: inline-flex;
	align-items: center;
	padding: 12px 0;
	border-bottom: 1px solid var(--pomp-ink);
	cursor: pointer;
	font-family: var(--pomp-mono);
	font-size: 15px;
}

.pomp-artwork__has {
	display: flex;
	gap: 16px;
	align-items: flex-start;
}

.pomp-artwork__thumb {
	width: 88px;
	height: 88px;
	object-fit: contain;
	background: #f6f6f4;
	border-radius: 3px;
}

.pomp-artwork__note {
	margin: 0 0 6px;
	font-size: 14px;
}

.pomp-artwork__clear {
	appearance: none;
	padding: 0;
	border: 0;
	background: none;
	font: inherit;
	font-size: 14px;
	color: var(--pomp-accent);
	text-decoration: underline;
	cursor: pointer;
}

.pomp-artwork__color {
	margin: 0 0 10px;
	padding: 0;
	border: 0;
}

.pomp-artwork__color legend {
	margin: 0 0 6px;
	padding: 0;
	font-family: var(--pomp-mono);
	font-size: 12px;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: var(--pomp-ink-muted, #6b6b66);
}

.pomp-artwork__color-option {
	display: flex;
	align-items: center;
	gap: 6px;
	margin: 0 0 6px;
	font-size: 14px;
	cursor: pointer;
}

.pomp-artwork__color-swatch {
	width: 22px;
	height: 22px;
	padding: 0;
	border: 1px solid var(--pomp-line);
	border-radius: 3px;
	background: none;
	cursor: pointer;
}

/* ---------------------------------------------------------------
 * Choosing a path: a ready design or your own artwork
 *
 * Sits above the first step. Two mutually exclusive offers, so they're
 * visually separated too, rather than items in the same list.
 * ------------------------------------------------------------ */

.pomp-paths {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 2px;
	margin: 0 0 28px;
}

/* Same brush-stroke button as "Continue"/"Search" elsewhere - this is the
   very first choice in the whole configurator, so on desktop (room being
   no issue there) it's sized to read as the start of things rather than
   one more small control; a phone-width copy of these same rules further
   below keeps it compact instead, where a doubled size would just force
   an early wrap. The chosen path is the filled button, the other two are
   its ghost variant (see .pomp-button / .pomp-button--ghost). Scoped here so
   the size doesn't leak into every other button on the page. */
.pomp-paths .pomp-button {
	padding: 24px 44px;
	font-size: 30px;
}

.pomp-paths .pomp-button--ghost {
	padding: 24px 20px;
	color: var(--pomp-accent);
}

.pomp-paths .pomp-button--ghost:hover {
	font-size: 30px;
}

/* Proportional breathing room for the bigger buttons above - the tight
   2px gap they share with the phone version (where the row scrolls
   sideways at its original, compact size) reads as cramped once the
   buttons themselves are this much larger. */
@media (min-width: 900px) {
	.pomp-paths {
		gap: 14px;
	}

	/* The doubled size above is sized for the old, full-width column this
	   row used to sit in alone (still does, before a design/product picked
	   through it exists) - once there's a canvas, it moves into the sticky
	   fields panel next to the photo (see .pomp-mobile-sheet--desktop), which
	   is nowhere near that wide regardless of how big the screen is, so it
	   goes back to the same compact size the phone version uses. */
	.pomp-mobile-sheet--desktop .pomp-paths {
		gap: 2px;
	}

	.pomp-mobile-sheet--desktop .pomp-paths .pomp-button,
	.pomp-mobile-sheet--desktop .pomp-paths .pomp-button--ghost {
		padding: 10px 8px;
		font-size: 13px;
	}

	.pomp-mobile-sheet--desktop .pomp-paths .pomp-button--ghost:hover {
		font-size: 13px;
	}
}

/* On a phone the three labels ("Gotov natpis", "Vlastiti tekst", "Vlastita
   grafika") rarely fit one line at full size - shrunk a bit, and sliding
   sideways instead of wrapping to a second row, same as the step bar (.pomp-menu). */
@media (max-width: 899px) {
	.pomp-paths {
		flex-wrap: nowrap;
		gap: 2px;
		margin-bottom: 18px;
		overflow-x: auto;
		scrollbar-width: none;
		/* Same edge fade as the other sideways-scrolling strips (see
		   .pomp-own__tune) - the hint that there's more to it sideways. */
		-webkit-mask-image: linear-gradient(to right, transparent 0, #000 14px, #000 calc(100% - 14px), transparent 100%);
		mask-image: linear-gradient(to right, transparent 0, #000 14px, #000 calc(100% - 14px), transparent 100%);
	}

	.pomp-paths::-webkit-scrollbar {
		display: none;
	}

	.pomp-paths .pomp-button,
	.pomp-paths .pomp-button--ghost {
		padding: 10px 8px;
		font-size: 13px;
		white-space: nowrap;
	}
}

/* ---------------------------------------------------------------
 * Submitted artwork below the product
 *
 * On the product there's a grid at the image's ratio; here is the image
 * itself, with an arrow pointing at that grid. The grid shows position and
 * curve, the image shows the content.
 * ------------------------------------------------------------ */

.pomp-artref {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 8px;
	margin: 4px 0 0;
	text-align: center;
	color: var(--pomp-muted);
}

.pomp-artref__arrow {
	width: 22px;
	height: 36px;
	flex: 0 0 auto;
}

.pomp-artref__image {
	max-width: 180px;
	max-height: 180px;
	width: auto;
	height: auto;
	background: #f6f6f4;
	border-radius: 3px;
}

.pomp-artref__note {
	max-width: 260px;
	margin: 0;
	font-size: 13px;
	line-height: 1.35;
}

/* A grid over the submitted image.
 *
 * The same 4x4 split as on the product, so the cells can be compared. The
 * colour alternates white/black every second: black shows on a light image,
 * white on a dark one, so no artwork is left without a visible grid. The
 * switch is a hard cut, not gradual - being grey for half the cycle would
 * be the worst of both. */

.pomp-artref__frame {
	position: relative;
	display: inline-block;
	line-height: 0;
}

.pomp-artref__grid {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	overflow: visible;
	pointer-events: none;
}

.pomp-artref__grid path {
	fill: none;
	stroke-width: 1.5px;
	vector-effect: non-scaling-stroke;
	animation: pomp-artref-flip 2s step-end infinite;
}

@keyframes pomp-artref-flip {
	0% {
		stroke: #ffffff;
	}

	50% {
		stroke: #000000;
	}
}

/* Whoever turned off animations doesn't need the flicker; black shows on most artwork. */
@media ( prefers-reduced-motion: reduce ) {
	.pomp-artref__grid path {
		animation: none;
		stroke: #000000;
	}

	/* Still visibly a ring, just not a spinning one. */
	.pomp-spinner {
		animation: none;
	}
}

/* ---------------------------------------------------------------
 * Custom text
 *
 * The number of lines and the spacing are chosen before typing, since they
 * change the number and shape of the fields - the customer shouldn't be
 * adjusting them mid-write.
 * ------------------------------------------------------------ */

.pomp-own__row {
	display: flex;
	flex-wrap: wrap;
	gap: 8px 16px;
	align-items: baseline;
	margin: 0 0 16px;
}

.pomp-own__label {
	flex: 0 0 auto;
	min-width: 120px;
	font-family: var(--pomp-mono);
	font-size: 13px;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--pomp-accent);
}

.pomp-own__choices {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
}

.pomp-own__choice {
	appearance: none;
	min-width: 40px;
	padding: 7px 10px;
	border: 1px solid rgba(0, 0, 0, .18);
	border-radius: 2px;
	background: transparent;
	font-family: var(--pomp-mono);
	font-size: 14px;
	color: var(--pomp-ink);
	cursor: pointer;
}

.pomp-own__choice:hover {
	border-color: var(--pomp-ink);
}

.pomp-own__choice.is-active {
	border-color: var(--pomp-ink);
	background: var(--pomp-ink);
	color: #ffffff;
}

/* A font sample is text in its own right, so it needs more breathing room than a number. */

.pomp-own__choice--font {
	padding: 9px 14px;
	font-family: inherit;
	font-size: 17px;
	line-height: 1.2;
}

.pomp-own__lines {
	display: flex;
	flex-direction: column;
	gap: 4px;
	margin: 22px 0 0;
}

/* A line of custom text: the input, then its spacing and margin. */

.pomp-own__line {
	display: flex;
	flex-wrap: wrap;
	gap: 4px 16px;
	align-items: baseline;
	padding: 0 0 10px;
	border-bottom: 1px solid rgba(0, 0, 0, .07);
}

.pomp-own__line .pomp-input {
	flex: 1 1 220px;
	min-width: 0;
}

/* Its controls (spacing/margins/font) never wrap onto more lines of their
   own, so on a narrow screen they can add up to more than the line's own
   width. Rather than let that push the whole page wider, the strip scrolls
   sideways instead - same trick as the step bar (.pomp-menu) uses. */
.pomp-own__tune {
	display: flex;
	flex: 0 0 auto;
	max-width: 100%;
	gap: 14px;
	align-items: baseline;
	overflow-x: auto;
	scrollbar-width: none;
	-webkit-overflow-scrolling: touch;
	/* A soft fade at both edges, the standard hint for "this scrolls
	   sideways" on touch devices (no scrollbar to see otherwise) - present
	   whether or not the row actually overflows, since there's no way to
	   tell in plain CSS, and it's unnoticeable against the row's own
	   background when it doesn't. */
	-webkit-mask-image: linear-gradient(to right, transparent 0, #000 14px, #000 calc(100% - 14px), transparent 100%);
	mask-image: linear-gradient(to right, transparent 0, #000 14px, #000 calc(100% - 14px), transparent 100%);
}

.pomp-own__tune::-webkit-scrollbar {
	display: none;
}

.pomp-own__tune label {
	display: inline-flex;
	flex: 0 0 auto;
	gap: 5px;
	align-items: baseline;
	font-family: var(--pomp-mono);
	font-size: 12px;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: var(--pomp-accent);
}

.pomp-own__tune select {
	padding: 3px 4px;
	border: 1px solid rgba(0, 0, 0, .18);
	border-radius: 2px;
	background: transparent;
	font-family: var(--pomp-mono);
	font-size: 13px;
	color: var(--pomp-ink);
	cursor: pointer;
}

/* Font names run longer than "1.1" or "10%" - capped so one row's font
   pick doesn't push the rest of the tune row around. */
.pomp-own__tune-font {
	max-width: 130px;
}

/* ===============================================================
 * Theme style
 *
 * Pomp → Settings → Appearance → Style: "Theme style", the default, hands
 * the look to the theme. The layout above stays - the steps, the panels,
 * the preview - and the Pomp look comes off: the bracket marks, the
 * finished-step stroke, the brush behind a selected size, uppercase labels.
 * Fonts fall back to the theme's (see Pomp_Appearance::css()), and buttons
 * carry the theme's own button classes instead of .pomp-button, so the theme
 * draws them as it draws every other button in the shop.
 *
 * Scoped to .pomp-style-theme, which is on the body and on the plugin's own
 * root elements - the latter for a page whose shortcode the body class
 * cannot see (a page builder keeping its content elsewhere).
 * =============================================================== */

.pomp-style-theme .pomp-steps__label::before,
.pomp-style-theme .pomp-steps__label::after,
.pomp-style-theme .pomp-steps__number::before,
.pomp-style-theme .pomp-steps__number::after,
.pomp-style-theme .pomp-menu__meta a::before,
.pomp-style-theme .pomp-menu__meta a::after,
.pomp-style-theme .pomp-preview__placeholder::before,
.pomp-style-theme .pomp-preview__placeholder::after,
.pomp-style-theme .pomp-chip::before,
.pomp-style-theme .pomp-chip::after,
.pomp-style-theme .pomp-breadcrumb a::before,
.pomp-style-theme .pomp-breadcrumb a::after {
	content: none;
	display: none;
}

.pomp-style-theme .pomp-step-marker,
.pomp-style-theme .pomp-chip__brush {
	display: none;
}

/* The stroke across a finished step, said plainly. */
.pomp-style-theme .pomp-steps__item.is-done .pomp-steps__label {
	text-decoration: line-through;
}

.pomp-style-theme .pomp-label,
.pomp-style-theme .pomp-steps,
.pomp-style-theme .pomp-hint,
.pomp-style-theme .pomp-summary,
.pomp-style-theme .pomp-breadcrumb,
.pomp-style-theme .pomp-pagination,
.pomp-style-theme .pomp-eyebrow,
.pomp-style-theme .pomp-attribute__label,
.pomp-style-theme .pomp-card__title,
.pomp-style-theme .pomp-card__price,
.pomp-style-theme .pomp-steps__label,
.pomp-style-theme .pomp-menu__meta a,
.pomp-style-theme .pomp-preview__placeholder,
.pomp-style-theme .pomp-search::placeholder,
.pomp-style-theme .pomp-input::placeholder,
.pomp-style-theme .pomp-row__fixed,
.pomp-style-theme .pomp-error,
.pomp-style-theme .pomp-success,
.pomp-style-theme .pomp-card__design--text,
.pomp-style-theme .pomp-attribute__price,
.pomp-style-theme .pomp-chip,
.pomp-style-theme .pomp-catalog__title,
.pomp-style-theme .pomp-design-tab__label,
.pomp-style-theme .pomp-design-tab__panel h1,
.pomp-style-theme .pomp-design-tab__panel h2,
.pomp-style-theme .pomp-design-tab__panel h3,
.pomp-style-theme .pomp-design-tab__panel h4,
.pomp-style-theme .pomp-artwork__label,
.pomp-style-theme .pomp-artwork__color legend,
.pomp-style-theme .pomp-own__label,
.pomp-style-theme .pomp-own__tune label {
	text-transform: none;
	letter-spacing: normal;
}

/* A selected size: a filled box in the button colour, not a brush stroke. */
.pomp-style-theme .pomp-chip {
	padding: .45em .9em;
	border: 1px solid var(--pomp-line);
}

.pomp-style-theme .pomp-chip.is-selected {
	border-color: var(--pomp-brush);
	background: var(--pomp-brush);
	color: var(--pomp-on-brush);
}

/* Buttons: the theme's own classes draw them. Only the layout the
   configurator needs from a button is kept here. */
.pomp-style-theme .pomp-designlinks .pomp-action {
	flex: 0 0 auto;
}

.pomp-style-theme .pomp-actions .pomp-action--ghost {
	align-self: flex-start;
}

.pomp-style-theme .pomp-paths .pomp-action {
	white-space: nowrap;
}

.pomp-style-theme .pomp-action:disabled {
	opacity: .5;
	cursor: not-allowed;
}

.pomp-style-theme .pomp-spinner {
	border-color: rgba(127, 127, 127, .35);
	border-color: color-mix(in srgb, currentColor 35%, transparent);
	border-top-color: currentColor;
}
