/* ==========================================================================
   Sticker Customizer - frontend styles
   ========================================================================== */

/*
 * Two-column product layout (fallback only).
 *
 * Many modern themes (Storefront, Astra, Kidioz, …) already provide their
 * own gallery/summary column layout inside .product (e.g. a Tailwind
 * `.grid.grid-cols-12` wrapper, a Bootstrap `.row`, or explicit `col-*`
 * children). If we *also* force `display: grid` onto .product itself, the
 * theme's nested layout collapses: the whole gallery+summary wrapper is
 * squashed into one grid cell and the tabs / upsells / related products
 * scatter into the remaining cells, producing a broken page.
 *
 * The :has() guard scopes our fallback grid to "naked" .product wrappers
 * that have no theme-provided layout container as a direct child, so the
 * plugin works on default WooCommerce themes without fighting themes that
 * already lay the page out for us. :has() is supported in all evergreen
 * browsers.
 */
.sticker-customizer-product.woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)),
.sticker-customizer-product .woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	grid-column-gap: 40px;
	grid-row-gap: 24px;
	align-items: start;
}

.sticker-customizer-product.woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) > .woocommerce-product-gallery,
.sticker-customizer-product .woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) > .woocommerce-product-gallery,
.sticker-customizer-product.woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) > .sc-gallery,
.sticker-customizer-product .woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) > .sc-gallery {
	width: 100% !important;
	max-width: 100%;
	float: none;
	grid-column: 1;
	min-width: 0;
}

.sticker-customizer-product.woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) > .summary,
.sticker-customizer-product .woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) > .summary {
	width: 100% !important;
	max-width: 100%;
	float: none;
	grid-column: 2;
	margin-bottom: 0;
	min-width: 0;
}

.sticker-customizer-product.woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) > .woocommerce-tabs,
.sticker-customizer-product.woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) > .related,
.sticker-customizer-product.woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) > .upsells,
.sticker-customizer-product .woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) > .woocommerce-tabs,
.sticker-customizer-product .woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) > .related,
.sticker-customizer-product .woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) > .upsells {
	grid-column: 1 / -1;
}

/* Tablet & smaller: stack into a single column so nothing gets squeezed.
 * Same :has() guard – only the fallback layout collapses, themes with
 * their own responsive layout (kidioz, etc.) keep doing their thing. */
@media (max-width: 1024px) {
	.sticker-customizer-product.woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)),
	.sticker-customizer-product .woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) {
		grid-template-columns: 1fr;
		grid-column-gap: 0;
	}
	.sticker-customizer-product.woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) > .woocommerce-product-gallery,
	.sticker-customizer-product .woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) > .woocommerce-product-gallery,
	.sticker-customizer-product.woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) > .sc-gallery,
	.sticker-customizer-product .woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) > .sc-gallery,
	.sticker-customizer-product.woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) > .summary,
	.sticker-customizer-product .woocommerce div.product:not(:has(> .grid, > .row, > [class*="col-"], > .product-image, > .product-summary)) > .summary {
		grid-column: 1;
	}
}

/*
 * Theme-grid awareness.
 *
 * On themes that *do* have a nested column layout (kidioz et al.), the
 * gallery and the customizer panel still need to be width:100% inside
 * whatever container the theme provides, and we must NOT inherit
 * grid-column / float values from any other source that would shrink
 * them. These rules are intentionally toothless about column placement –
 * they only normalise width and floats so our components fill the
 * theme-provided column cleanly.
 */
.sticker-customizer-product .sc-gallery,
.sticker-customizer-product .sc-customizer {
	width: 100%;
	max-width: 100%;
	float: none;
	min-width: 0;
}

/* ---- Customizer wrapper ------------------------------------------------- */

/* .sc-picker-modal is portaled to <body> at runtime (0.11.44) so it
 * lives outside `.sc-customizer`. Include it explicitly here so the
 * shared design tokens still resolve inside the modal — otherwise
 * every var(--sc-*) falls back to empty and header / close X / NEXT
 * button / input border / tile background all render transparent. */
.sc-customizer,
.sc-gallery,
.sc-picker-modal {
	--sc-accent: #2ea7b9;
	--sc-text: #2f3b4a;
	--sc-muted: #7b8594;
	--sc-border: #e6e8ea;
	--sc-bg-soft: #f4f5f6;
	color: var(--sc-text);
}

.sc-customizer {
	margin: 20px 0;
	display: flex;
	flex-direction: column;
	gap: 16px;
}

/* ---- Gallery (left column) --------------------------------------------- */

.sc-gallery {
	display: flex;
	flex-direction: column;
	gap: 12px;
	width: 100%;
}

.sc-gallery-main {
	position: relative;
	display: block;
	width: 100%;
	/* Soft cap on wide desktops paired with a 1200 px source
	 * `sc_tile_preview` (see class-frontend.php). 1200 → 720 CSS is
	 * a clean 1.67× downscale on 1x monitors and only a 1.2× upscale
	 * on 2× retina (which paints 1440 physical px), so text and
	 * edges stay sharp on every modern viewport without shipping the
	 * raw 1181 × 2362 PDF raster. Older versions of this rule used
	 * a tighter 520 / 560 px cap paired with a smaller 500 / 800 px
	 * source — the stage looked cramped inside wide WooCommerce
	 * layouts and the 800 px source blurred noticeably on retina. */
	max-width: 720px;
	margin-left: auto;
	margin-right: auto;
	background: #f7f7f7;
	border-radius: 8px;
	overflow: hidden;
	line-height: 0;
}

.sc-gallery-main .sc-stage {
	position: relative;
	display: block;
	width: 100%;
	max-width: 100%;
	line-height: 0;
}

.sc-gallery-main .sc-stage[hidden] {
	display: none !important;
}

.sc-gallery-main-image {
	display: block;
	width: 100%;
	height: auto;
	user-select: none;
}

.sc-gallery-main-image[hidden] {
	display: none !important;
}

.sc-gallery-thumbs {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
}

.sc-gallery-thumb {
	position: relative;
	flex: 0 0 auto;
	width: 72px;
	height: 72px;
	padding: 0;
	background: #fff;
	border: 2px solid var(--sc-border);
	border-radius: 6px;
	cursor: pointer;
	overflow: hidden;
	transition: border-color 0.15s ease, transform 0.15s ease;
	display: flex;
	align-items: center;
	justify-content: center;
}

.sc-gallery-thumb:hover {
	border-color: var(--sc-muted);
}

.sc-gallery-thumb.is-active {
	border-color: var(--sc-accent);
	box-shadow: 0 0 0 1px var(--sc-accent) inset;
}

.sc-gallery-thumb img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	display: block;
}

.sc-gallery-thumb-stage {
	flex-direction: column;
	gap: 2px;
}

.sc-gallery-thumb-stage img {
	flex: 1 1 auto;
	min-height: 0;
	height: 70%;
}

.sc-gallery-thumb-label {
	display: block;
	font-size: 10px;
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: var(--sc-muted);
	line-height: 1;
	padding: 2px 0 4px;
}

.sc-gallery-thumb.is-active .sc-gallery-thumb-label {
	color: var(--sc-accent);
}

/* ---- Shared stage/overlay visuals (live preview) ----------------------- */

.sc-stage .sc-base-image,
.sc-base-image {
	display: block;
	width: 100%;
	height: auto;
	user-select: none;
}

/*
 * When the stage has an explicit aspect-ratio (set inline from the product's
 * print dimensions), the base image must FILL the stage so zones stored as
 * percentages of the stage match the print canvas 1:1. Without this, a base
 * JPG with its own aspect would letterbox inside the stage and zones would
 * drift to the wrong position on the printed PDF. !important to beat theme
 * rules that may set `width: auto` on images inside product summary.
 */
.sc-stage[style*="aspect-ratio"] {
	width: 100% !important;
	height: auto !important;
	position: relative;
	line-height: 0;
	display: block !important;
}

.sc-stage[style*="aspect-ratio"] .sc-base-image,
.sc-stage[style*="aspect-ratio"] > .sc-base-image,
.sc-stage[style*="aspect-ratio"] img.sc-base-image {
	width: 100% !important;
	height: 100% !important;
	max-width: none !important;
	object-fit: fill !important;
	display: block !important;
}

/* ---- Auto-composite tiles (frontend live preview) ---------------------- */

/* While a design switch is waiting on its REST payload we dim the stage
 * slightly and disable pointer events so the customer sees that a load
 * is in flight without any layout shift. The class is toggled by
 * frontend-customizer.js in selectDesign(). */
.sc-gallery.is-loading-design .sc-stage {
	opacity: 0.55;
	pointer-events: none;
	transition: opacity 120ms ease-out;
}

/* In auto mode the stage has no <img.sc-base-image>; instead each PDF
 * contributes one tile that visually shows one cropped "sample cell"
 * from its preview image. The tile is a clipped frame; the <img> inside
 * is sized so that the sample-cell rectangle exactly fills the tile. */
.sc-stage-auto {
	background: #ffffff;
	width: 100% !important;
	height: auto !important;
	position: relative;
	line-height: 0;
	display: block !important;
}

.sc-stage .sc-composite-tile {
	position: absolute;
	overflow: visible;
	user-select: none;
	-webkit-user-select: none;
	line-height: 1.0;
}

/* Inner wrapper that clips the cropped sample-cell image. Keeping the
 * clip on a child instead of the tile itself lets the tile caption
 * render outside the tile box (below the image, centered). */
.sc-stage .sc-composite-tile-clip {
	position: absolute;
	inset: 0;
	overflow: hidden;
}

.sc-stage .sc-composite-tile-img {
	position: absolute;
	max-width: none;
	pointer-events: none;
	user-select: none;
	-webkit-user-select: none;
}

/* Customer-facing caption rendered under each composite tile, centered
 * horizontally. The text is set by the admin per tile in the product
 * editor's auto-composite tiles panel. */
.sc-stage .sc-composite-tile-caption {
	position: absolute;
	top: 100%;
	left: 50%;
	transform: translateX(-50%);
	margin-top: 6px;
	max-width: 220%;
	padding: 1px 6px;
	font-size: clamp(10px, 1.6vw, 14px);
	font-weight: 600;
	color: #1d2327;
	background: rgba(255, 255, 255, 0.85);
	border-radius: 2px;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	text-align: center;
	pointer-events: none;
	line-height: 1.2;
}

.sc-stage .sc-overlay {
	position: absolute;
	display: flex;
	align-items: center;
	justify-content: center;
	color: #111;
	line-height: 1.0;
	pointer-events: none;
	transform-origin: center center;
	text-align: center;
	overflow: hidden;
}

/*
 * Multi-line text stack inside an overlay. JS sets font-size, line-height,
 * and inter-line gap inline so every zone matches what the print pipeline
 * (PDF + EPS) renders. We just make sure the container fills the zone and
 * the inner spans don't add their own margins.
 */
.sc-stage .sc-overlay-stack {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	width: 100%;
	height: 100%;
	text-align: center;
}

.sc-stage .sc-overlay-text {
	display: inline-block;
	max-width: 100%;
	white-space: nowrap;
	line-height: 1.0;
}

/*
 * Normalize spacing / variant / stretch / transform on the live-preview
 * overlays so themes (Astra, Kadence, block themes, Woo templates) cannot
 * cascade extra tracking or small-caps into them. Canvas measureText does
 * not know about CSS letter-spacing/word-spacing, so any cascade would
 * make the binary-search fit undercount the real painted width and clip
 * the trailing glyph (ć, č, đ) against the overflow-hidden bounds.
 * Font weight and style are intentionally NOT forced — the theme's
 * chosen weight stays visible, and JS reads it via getComputedStyle
 * before measuring so canvas metrics stay in sync.
 */
.sc-stage .sc-overlay,
.sc-stage .sc-overlay-stack,
.sc-stage .sc-overlay-text {
	letter-spacing: normal;
	word-spacing: normal;
	font-variant: normal;
	font-stretch: normal;
	text-transform: none;
	font-kerning: auto;
}

/*
 * Force the inner text spans to always inherit the font-family set on
 * .sc-overlay. Otherwise a theme rule like `.woocommerce span { font-family:
 * ThemeSerif !important }` would override our picked family for the actual
 * rendered text while leaving .sc-overlay's inline family intact — canvas
 * would then measure with the picked family, CSS would paint with the theme
 * font, and the fit would clip. `inherit !important` here is stronger than
 * theme rules that don't also use !important against .sc-overlay-text (or
 * that select higher-specificity ancestors), and it makes the inheritance
 * chain observable via getComputedStyle on .sc-overlay.
 */
.sc-stage .sc-overlay-stack,
.sc-stage .sc-overlay-text {
	font-family: inherit !important;
}

/* ---- Sections ----------------------------------------------------------- */

.sc-controls {
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.sc-section {
	background: #fff;
	border-top: 1px solid var(--sc-border);
	padding: 22px 4px;
}

.sc-section:first-child {
	border-top: none;
	padding-top: 8px;
}

.sc-section-header {
	margin-bottom: 16px;
}

.sc-section-title {
	margin: 0;
	font-size: 25px;
	font-weight: 700;
	letter-spacing: 0;
	color: var(--sc-text);
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: 4px 8px;
}

.sc-section-num {
	color: var(--sc-text);
	font-weight: 700;
}

/* Small parenthetical hint next to a step title (e.g. "(ćirilica i latinica)"
 * next to "Upiši ime i prezime"). Lighter, muted, so it reads as a
 * subtitle instead of stealing focus from the primary heading. */
.sc-section-title-hint {
	font-size: 14px;
	font-weight: 500;
	color: var(--sc-muted, #6b7280);
	letter-spacing: 0;
}

.sc-summary-card__hint {
	display: inline;
	margin-left: 4px;
	font-size: 12px;
	font-weight: 500;
	color: var(--sc-muted, #6b7280);
}

/* ---- Carousel shared ---------------------------------------------------- */

.sc-carousel {
	position: relative;
	display: flex;
	align-items: center;
	gap: 8px;
	min-width: 0;
}

.sc-carousel-track {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	gap: 10px;
	overflow-x: auto;
	overflow-y: hidden;
	scroll-behavior: smooth;
	padding: 4px 2px;
	scrollbar-width: none;
}

.sc-carousel-track::-webkit-scrollbar {
	display: none;
}

/* Tiles always start from the left edge, whether or not they overflow. */
.sc-carousel-track {
	justify-content: flex-start;
}

/* Arrows are hidden by default; JS adds `.is-overflow` on the carousel
   only when the track actually has more content than can be shown. */
.sc-carousel-arrow {
	display: none;
	flex: 0 0 32px;
	width: 32px;
	height: 32px;
	align-items: center;
	justify-content: center;
	background: transparent;
	border: none;
	color: var(--sc-muted);
	cursor: pointer;
	font-size: 20px;
	padding: 0;
	border-radius: 50%;
	transition: background 0.15s ease, color 0.15s ease;
}

.sc-carousel.is-overflow .sc-carousel-arrow {
	display: flex;
}

.sc-carousel-arrow:hover {
	color: var(--sc-text);
	background: var(--sc-bg-soft);
}

/* Dim the arrow that can't scroll any further (start/end of scroll range). */
.sc-carousel-arrow.is-disabled {
	opacity: 0.3;
	pointer-events: none;
}

.sc-carousel-arrow span {
	display: block;
	line-height: 1;
}

/* ---- Extra inputs (Subject, Class, …) ---------------------------------- */

.sc-section-extra .sc-required-mark {
	color: #c00;
	font-weight: 700;
	margin-left: 4px;
}

.sc-section-extra .sc-section-title {
	display: flex;
	align-items: baseline;
	gap: 6px;
}

/* ---- Text field (floating label) --------------------------------------- */

.sc-text-field {
	position: relative;
	background: #fff;
	border: 1px solid var(--sc-border);
	border-radius: 10px;
	padding: 12px 16px 10px;
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.sc-text-field:focus-within {
	border-color: var(--sc-accent);
	box-shadow: 0 0 0 1px var(--sc-accent);
}

.sc-floating-label {
	display: block;
	font-size: 11px;
	color: var(--sc-muted);
	font-weight: 500;
	letter-spacing: 0.02em;
	margin-bottom: 2px;
	text-transform: none;
}

.sc-text-input {
	width: 100%;
	border: none;
	background: transparent;
	padding: 0;
	font-size: 16px;
	color: var(--sc-text);
	box-sizing: border-box;
	outline: none;
}

.sc-text-input::placeholder {
	color: #bbb;
}

.sc-text-help {
	margin: 8px 2px 0;
	font-size: 12px;
	color: var(--sc-muted);
}

.sc-inline-error {
	margin: 0 0 12px;
	padding: 10px 12px;
	border: 1px solid #f1b3b3;
	border-radius: 10px;
	background: #fff1f1;
	color: #b42318;
	font-size: 14px;
	line-height: 1.4;
}

.sc-inline-error[hidden] {
	display: none !important;
}

.sc-text-field.is-invalid {
	box-shadow: 0 0 0 2px rgba(180, 35, 24, 0.25);
	border-radius: 10px;
}

.sticker-customizer-product .single_add_to_cart_button.sc-purchase-locked,
.sticker-customizer-product .ajax_add_to_cart.sc-purchase-locked,
.sticker-customizer-product button.sc-purchase-locked,
.sticker-customizer-product .buy-now a.sc-purchase-locked {
	opacity: 0.45;
	cursor: not-allowed !important;
	pointer-events: none !important;
	box-shadow: none !important;
}

.sc-purchase-hint {
	margin: 8px 0 16px;
	padding: 0 4px;
	color: #6b6b80;
	font-size: 13px;
	line-height: 1.4;
	text-align: center;
}

.sc-purchase-hint[hidden] {
	display: none !important;
}

/* ---- Section lock (step-by-step gating) --------------------------------- */
/*
 * The customizer is step-by-step: a section is "locked" until the
 * prerequisite step has been completed (design -> text -> font). The
 * section is still visible (so the user can see what's next) but its
 * inputs are disabled and we dim the whole card.
 *
 * The hint line is hidden by default and only shown when the section is
 * locked. Conversely, the standard helper line (.sc-text-help) is hidden
 * while the section is locked to avoid two competing messages.
 */
.sc-section-lock-hint {
	display: none;
	margin: 10px 2px 0;
	padding: 10px 12px;
	font-size: 13px;
	color: #8a6d3b;
	background: #fcf8e3;
	border: 1px solid #faebcc;
	border-radius: 6px;
}
.sc-section.is-locked {
	opacity: 0.72;
}
.sc-section.is-locked .sc-section-title {
	color: var(--sc-muted);
}
.sc-section.is-locked .sc-section-lock-hint {
	display: block;
}
.sc-section.is-locked .sc-text-help {
	display: none;
}
.sc-section.is-locked .sc-carousel-track,
.sc-section.is-locked .sc-carousel-arrow {
	pointer-events: none;
	filter: grayscale(0.4);
}
.sc-section.is-locked .sc-text-input {
	background: #f5f5f5;
	cursor: not-allowed;
}
.sc-section.is-locked .sc-font-tile {
	cursor: not-allowed;
}

/* ---- Designs filter (category tabs) ------------------------------------
 *
 * Text-tab bar with an accent underline for the active tab. Search was
 * removed in 0.11.14 (copyright concerns) and its stray CSS was cleared
 * in 0.11.18 when we redesigned this block to match the reference look:
 * airy, typography-first, no chunky pill chips.
 */

.sc-design-filters {
	display: flex;
	flex-direction: column;
	margin: 6px 2px 14px;
}

.sc-design-tabs {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 4px 22px;
	padding: 0 2px;
	border-bottom: 1px solid var(--sc-border);
}

.sc-design-tab {
	appearance: none;
	border: none;
	background: transparent;
	color: var(--sc-muted);
	font-size: 14px;
	font-weight: 500;
	line-height: 1.2;
	padding: 10px 2px;
	border-radius: 0;
	cursor: pointer;
	position: relative;
	transition: color 0.15s ease;
	/* Pulls the tab's own bottom border down 1px so it overlaps the
	 * bar's underline, giving the active tab a clean flush edge. */
	margin-bottom: -1px;
	border-bottom: 2px solid transparent;
}

.sc-design-tab:hover,
.sc-design-tab:focus-visible {
	color: var(--sc-text);
	outline: none;
}

.sc-design-tab.is-active {
	color: var(--sc-text);
	font-weight: 600;
	border-bottom-color: var(--sc-accent);
}

.sc-design-tile.is-filtered-out {
	display: none;
}

.sc-designs-empty {
	flex: 1 1 auto;
	align-self: center;
	margin: 0;
	padding: 12px 4px;
	font-size: 13px;
	color: var(--sc-muted);
}

/* ---- Designs carousel ---------------------------------------------------
 *
 * Two-row layout: designs flow top-to-bottom inside each column, then
 * the next column starts to the right. The carousel arrows still drive
 * horizontal scrolling because `grid-auto-flow: column` expands the
 * track sideways when more designs are added. We keep `display: none`
 * for filtered tiles so the row pairing reshuffles cleanly.
 *
 * Full-bleed tile aesthetic (0.11.18): each tile is a rounded square
 * that the tile-preview image fills edge-to-edge via `object-fit:
 * cover`. No inner padding, no visible outer card, no per-tile label
 * — the sole visual is the artwork. Matches the reference designs
 * the shop provided. Shop owners are expected to upload square
 * tile-preview images per design (added in 0.11.14) so the crop
 * stays predictable; a fallback composite image will still `cover`
 * cleanly since we retain a light background under it.
 */
.sc-designs-grid {
	display: grid;
	grid-auto-flow: column;
	grid-template-rows: repeat(2, auto);
	grid-auto-columns: minmax(110px, 1fr);
	gap: 12px;
	overflow-x: auto;
	scrollbar-width: none;
	padding: 4px 2px;
	align-items: stretch;
}

.sc-designs-grid::-webkit-scrollbar {
	display: none;
}

.sc-design-tile {
	display: block;
	appearance: none;
	background: var(--sc-bg-soft);
	border: 2px solid transparent;
	border-radius: 14px;
	padding: 0;
	cursor: pointer;
	transition: border-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
	min-width: 110px;
	max-width: 150px;
	aspect-ratio: 1 / 1;
	overflow: hidden;
	position: relative;
}

.sc-design-tile:hover {
	transform: translateY(-1px);
	box-shadow: 0 4px 10px rgba(0, 0, 0, 0.06);
}

.sc-design-tile:focus-visible {
	outline: none;
	border-color: var(--sc-accent);
}

.sc-design-tile img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
	border-radius: 12px;
	background: #fff;
	display: block;
}

.sc-design-tile.is-selected {
	border-color: var(--sc-accent);
	/* Soft accent halo behind the border ring; the hardcoded RGB
	 * mirrors --sc-accent (#2ea7b9) — CSS can't derive an alpha
	 * channel from a hex custom property without color-mix(). */
	box-shadow: 0 0 0 3px rgba(46, 167, 185, 0.18);
}

/* Hide sections that the active design does not use. JS toggles
   `is-hidden` on each sc-section-extra / sc-section-name section. */
.sc-section.is-hidden {
	display: none;
}

.sc-gallery-thumb-design {
	flex-direction: column;
}

.sc-gallery-thumb-design img {
	height: 75%;
}

/* ---- Fonts grid --------------------------------------------------------- */

/* Fixed (not stretchy) column width: with only one or two fonts the
 * tiles stay a compact pill instead of expanding to the full panel
 * width. The carousel arrows take over once the row of pills exceeds
 * the visible track width. */
.sc-fonts-grid {
	display: grid;
	grid-auto-flow: column;
	grid-template-rows: repeat(2, auto);
	grid-auto-columns: 170px;
	gap: 8px;
	justify-content: start;
}

.sc-font-tile {
	width: 170px;
	min-width: 170px;
	height: 48px;
	padding: 0 14px;
	margin: 0;
	border: 2px solid transparent;
	border-radius: 10px;
	background: var(--sc-bg-soft);
	cursor: pointer;
	font-size: 17px;
	line-height: 1;
	color: var(--sc-text);
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
	transition: border-color 0.15s ease, background 0.15s ease;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.sc-font-tile:hover {
	background: #eceff1;
}

.sc-font-tile.is-selected {
	border-color: var(--sc-accent);
	background: #fff;
}

/*
 * v0.11.54 — script-aware font filter.
 *
 * Frontend JS detects Latin / Cyrillic in the customer's input and
 * tags every tile whose data-supports-lat / data-supports-cyr flags
 * don't cover the detected script(s) with `.is-hidden-script`.
 * `display:none` (rather than `visibility:hidden`) keeps the carousel
 * scroll arithmetic honest — hidden tiles vanish from the flex layout
 * so the arrows step past visible tiles only.
 */
.sc-font-tile.is-hidden-script {
	display: none !important;
}

/* ==========================================================================
   Responsive adjustments
   ========================================================================== */

/* Tablet: slightly tighter spacing on the controls panel. */
@media (max-width: 1024px) {
	.sc-customizer {
		margin: 16px 0;
	}
}

/* Small tablet / large phone: shrink tiles, arrows and section spacing. */
@media (max-width: 768px) {
	.sc-section {
		padding: 18px 2px;
	}
	.sc-section-header {
		margin-bottom: 12px;
	}
	.sc-section-title {
		font-size: 22px;
	}

	.sc-gallery-thumb {
		width: 60px;
		height: 60px;
	}

	.sc-fonts-grid {
		grid-auto-columns: 150px;
		gap: 6px;
	}
	.sc-font-tile {
		width: 150px;
		min-width: 150px;
		height: 44px;
		font-size: 16px;
		padding: 0 12px;
	}

	.sc-designs-grid {
		grid-auto-columns: minmax(96px, 1fr);
		gap: 10px;
	}
	.sc-design-tile {
		min-width: 96px;
		max-width: 128px;
	}

	.sc-text-input {
		font-size: 15px;
	}

	.sc-carousel-arrow {
		flex-basis: 28px;
		width: 28px;
		height: 28px;
		font-size: 18px;
	}
}

/* Phones. */
@media (max-width: 480px) {
	.sc-section {
		padding: 16px 0;
	}
	.sc-section-title {
		font-size: 20px;
	}

	.sc-gallery-thumbs {
		gap: 6px;
	}
	.sc-gallery-thumb {
		width: 52px;
		height: 52px;
		border-width: 2px;
		border-radius: 5px;
	}
	.sc-gallery-thumb-label {
		font-size: 9px;
		padding: 1px 0 2px;
	}

	/* Phones: keep 2 rows + fixed-width pills so the visual rhythm
	 * matches "Choose a design" right above it. Tighter dimensions
	 * let ~2 pill columns fit per visible track width before scroll. */
	.sc-fonts-grid {
		grid-auto-columns: 140px;
		gap: 6px;
	}
	.sc-font-tile {
		width: 140px;
		min-width: 140px;
		height: 40px;
		font-size: 15px;
		padding: 0 10px;
	}

	/* Phones: keep designs in 2 rows but tighten everything one more
	 * notch. We deliberately do NOT collapse to a single row here — the
	 * 2-row strip is the point of this layout — and the smaller tile
	 * lets ~4 columns fit in a typical phone viewport before scroll. */
	.sc-designs-grid {
		grid-auto-columns: minmax(84px, 1fr);
		gap: 8px;
	}
	.sc-design-tile {
		min-width: 84px;
		max-width: 112px;
		border-radius: 12px;
	}
	.sc-design-tile img {
		border-radius: 10px;
	}

	.sc-text-field {
		padding: 10px 12px 8px;
		border-radius: 8px;
	}
	.sc-text-help {
		font-size: 11px;
	}

	.sc-carousel {
		gap: 0;
	}
	.sc-carousel-arrow {
		flex-basis: 24px;
		width: 24px;
		height: 24px;
		font-size: 16px;
	}
}

/* Cart / checkout: keep our swapped thumbnails sensibly sized. */
.sc-cart-thumbnail,
img.sc-cart-thumbnail {
	max-width: 100%;
	height: auto;
	border-radius: 4px;
}

/* -----------------------------------------------------------------------
 * Mobile compact customizer + fullscreen picker modal (0.11.20)
 *
 * At <=768px the vertical stack of full-width sections was pushing the
 * add-to-cart button off-screen and forcing several scrolls before a
 * shopper could even see all the steps. This block replaces that with
 * a short list of summary cards on the landing view; tapping a card
 * opens `.sc-picker-modal` which physically moves the target section
 * (design tiles / text input / font pills) into a slide-up sheet, with
 * a mini preview docked at the top and a sticky Prev/Next footer.
 *
 * Desktop keeps the original layout with zero visual change — every
 * override below is media-scoped, and the .sc-mobile-summary /
 * .sc-picker-modal blocks are `display: none` by default.
 * ----------------------------------------------------------------------- */

.sc-mobile-summary,
.sc-picker-modal {
	display: none;
}

@media (max-width: 768px) {
	/* Hide the stacked desktop controls; the summary + modal take over. */
	.sc-customizer > .sc-controls {
		display: none;
	}

	/* -------- Summary card list ------------------------------------ */
	.sc-mobile-summary {
		display: flex;
		flex-direction: column;
		gap: 10px;
		padding: 0;
		margin: 0;
	}

	.sc-summary-card {
		display: flex;
		align-items: stretch;
		width: 100%;
		padding: 0;
		border: 1px solid var(--sc-border);
		border-radius: 12px;
		background: #fff;
		text-align: left;
		cursor: pointer;
		overflow: hidden;
		font: inherit;
		color: inherit;
		-webkit-tap-highlight-color: transparent;
		transition: border-color 160ms ease, box-shadow 160ms ease, transform 120ms ease;
	}

	.sc-summary-card:hover,
	.sc-summary-card:focus-visible {
		border-color: var(--sc-accent);
		box-shadow: 0 2px 8px rgba(46, 167, 185, 0.14);
		outline: none;
	}

	.sc-summary-card:active {
		transform: scale(0.99);
	}

	.sc-summary-card.is-hidden {
		display: none;
	}

	.sc-summary-card__accent {
		width: 4px;
		flex: 0 0 4px;
		background: var(--sc-accent);
	}

	.sc-summary-card__body {
		flex: 1 1 auto;
		display: flex;
		flex-direction: column;
		gap: 6px;
		padding: 12px 14px;
		min-width: 0;
	}

	.sc-summary-card__title {
		display: flex;
		align-items: center;
		gap: 8px;
		font-size: 15px;
		font-weight: 600;
		color: var(--sc-text);
	}

	.sc-summary-card__num {
		color: var(--sc-accent);
		font-weight: 700;
	}

	.sc-summary-card__label {
		flex: 1 1 auto;
		min-width: 0;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	.sc-summary-card__check {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		color: var(--sc-accent);
		flex: 0 0 auto;
	}

	.sc-summary-card__preview {
		display: block;
		font-size: 14px;
		color: var(--sc-text);
		min-height: 20px;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	.sc-summary-card__preview.is-placeholder {
		color: var(--sc-muted);
		font-style: italic;
	}

	.sc-summary-card__thumb {
		display: block;
		width: 48px;
		height: 48px;
		object-fit: cover;
		border-radius: 8px;
		border: 1px solid var(--sc-border);
	}

	.sc-summary-card__edit {
		display: inline-flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		padding: 0 14px;
		gap: 2px;
		color: var(--sc-muted);
		font-size: 11px;
		text-transform: uppercase;
		letter-spacing: 0.5px;
		border-left: 1px solid var(--sc-border);
	}

	.sc-summary-card__edit-label {
		display: none; /* icon-only on narrow screens; label re-appears at 480+ */
	}

	/* -------- Picker modal ----------------------------------------- */
	/* JS portals this element to <body> at init so the position:fixed
	 * layer isn't trapped in a nested stacking context created by any
	 * transformed / filtered / will-changed ancestor in the theme's
	 * product column. The near-int32-max z-index is insurance against
	 * greedy theme sticky bars (typical values sit around 9999-999999).
	 */
	.sc-picker-modal {
		display: flex;
		position: fixed;
		inset: 0;
		z-index: 2147483000;
		flex-direction: column;
		background: #fff;
		transform: translateY(100%);
		transition: transform 240ms cubic-bezier(0.2, 0.8, 0.2, 1);
		will-change: transform;
	}

	.sc-picker-modal[hidden] {
		display: none;
	}

	.sc-picker-modal.is-open {
		transform: translateY(0);
	}

	.sc-picker-modal__header {
		position: sticky;
		top: 0;
		z-index: 2;
		display: flex;
		align-items: center;
		gap: 12px;
		padding: 14px 16px;
		background: var(--sc-accent);
		color: #fff;
	}

	.sc-picker-modal__title {
		flex: 1 1 auto;
		margin: 0;
		font-size: 17px;
		font-weight: 600;
		line-height: 1.2;
		min-width: 0;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	.sc-picker-modal__close {
		flex: 0 0 auto;
		width: 36px;
		height: 36px;
		display: inline-flex;
		align-items: center;
		justify-content: center;
		background: rgba(255, 255, 255, 0.16);
		color: #fff;
		border: 0;
		border-radius: 50%;
		font-size: 16px;
		cursor: pointer;
		-webkit-tap-highlight-color: transparent;
	}

	.sc-picker-modal__close:hover,
	.sc-picker-modal__close:focus-visible {
		background: rgba(255, 255, 255, 0.28);
		outline: none;
	}

	.sc-picker-modal__preview-slot {
		flex: 0 0 auto;
		display: flex;
		align-items: center;
		justify-content: center;
		padding: 10px 12px 6px;
		border-bottom: 1px solid var(--sc-border);
	}

	.sc-picker-modal__preview-slot:empty {
		display: none;
	}

	/* Preview stage stays at its natural aspect ratio inside the
	 * modal — no height cap. Any earlier attempt at shrinking it
	 * (max-height: 34vh) broke the pixel-fit text sizer because the
	 * cache keys by family|weight|text and never invalidates on
	 * stage-size change, so the returning landing-view stage
	 * inherited stale sizes. The modal body scrolls beneath if the
	 * combined header + preview + tiles exceed viewport height, so
	 * the picker never falls fully offscreen.
	 */
	.sc-picker-modal__preview-slot .sc-gallery-main.is-in-modal {
		max-width: 100%;
		margin: 0 auto;
	}

	.sc-picker-modal__body {
		flex: 1 1 auto;
		/* min-height: 0 is required for a flex item to shrink below
		 * its intrinsic content height and let overflow-y: auto
		 * actually scroll — without it the body pushes the sticky
		 * footer off-screen when preview + tiles are taller than
		 * the viewport. */
		min-height: 0;
		overflow-y: auto;
		overflow-x: hidden;
		-webkit-overflow-scrolling: touch;
		padding: 12px 14px 16px;
	}

	/* Section inside modal: strip the desktop wrapper padding since
	 * the modal body already provides breathing room, and the header
	 * (title + step number) is redundant with the sticky modal title. */
	.sc-picker-modal__body .sc-section {
		padding: 0;
		margin: 0;
	}

	.sc-picker-modal__body .sc-section-header {
		display: none;
	}

	/* Design + font grids intentionally inherit the desktop carousel
	 * layout inside the modal (2 rows, horizontal swipe scroll, tiles
	 * keep their compact size, arrows appear only when JS toggles
	 * `.is-overflow`). Earlier revisions flattened this into a
	 * 3-column vertical grid (designs) and a 1-column stack (fonts),
	 * which pushed the design filters into a detaching sticky mode
	 * on scroll and gave the fonts step no breathing room. Reverting
	 * to the desktop rules fixes both symptoms and keeps every step
	 * short enough that the modal body rarely needs to scroll. */

	.sc-picker-modal__footer {
		position: sticky;
		bottom: 0;
		z-index: 2;
		display: flex;
		align-items: center;
		gap: 10px;
		padding: 12px 14px calc(12px + env(safe-area-inset-bottom, 0px));
		background: #fff;
		border-top: 1px solid var(--sc-border);
	}

	.sc-picker-modal__prev,
	.sc-picker-modal__next {
		flex: 1 1 auto;
		height: 48px;
		padding: 0 18px;
		border-radius: 24px;
		border: 1px solid var(--sc-border);
		background: #fff;
		font: inherit;
		font-weight: 600;
		font-size: 15px;
		color: var(--sc-text);
		cursor: pointer;
		-webkit-tap-highlight-color: transparent;
	}

	.sc-picker-modal__next {
		flex: 1.4 1 auto;
		background: var(--sc-accent);
		border-color: var(--sc-accent);
		color: #fff;
	}

	.sc-picker-modal__prev:disabled {
		opacity: 0.45;
		cursor: not-allowed;
	}

	.sc-picker-modal__step {
		flex: 0 0 auto;
		font-size: 13px;
		color: var(--sc-muted);
		white-space: nowrap;
	}

	/* Body scroll-lock while the modal is open. */
	body.sc-picker-open {
		overflow: hidden;
		touch-action: none;
	}
}

/* Bring back the "edit" text label on slightly larger phones where
 * the card has more horizontal room. */
@media (min-width: 480px) and (max-width: 768px) {
	.sc-summary-card__edit-label {
		display: inline;
	}
}

/* Reduced-motion: swap the slide-up transform for a fade-in. */
@media (prefers-reduced-motion: reduce) {
	.sc-picker-modal {
		transition: opacity 120ms ease;
		transform: none;
		opacity: 0;
	}
	.sc-picker-modal.is-open {
		transform: none;
		opacity: 1;
	}
}
