/*
 * YeffoPrint storefront styles: homepage patterns + Shop Labels gallery.
 * Global chrome (header/footer/drawers/buttons/forms) lives in
 * global.css; this file is scoped to page/section content. See
 * docs/ARCHITECTURE.md §9.
 */

/* ---------- Shared section rhythm ---------- */

.yp-section {
	/* Tighter than the shared --spacing-xl token (used verbatim
	   elsewhere, e.g. the footer) — direct feedback that the homepage's
	   section rhythm reads as too much blank space stacked between
	   fairly sparse content; a slightly denser rhythm plus the richer
	   content added within each section (icons, stat row, material
	   swatch copy) address that together rather than through padding
	   alone. */
	padding-block: 3rem;
	/* Every .yp-section is a direct child of `main.wp-block-group`,
	   which now carries its own padding-inline (global.css, "Root
	   template spacing") so mobile content isn't flush against the
	   screen edge. That padding would also inset a --dark/--tint
	   section's own background, though, which is meant to bleed full-
	   width — clawed back here with a matching negative margin, then
	   restored as this element's own padding so its *content* still
	   gets the same inset. A background always paints under an
	   element's own padding regardless, so this two-step is only
	   needed to keep main's padding from doubling up visually. */
	margin-inline: calc(-1 * var(--wp--preset--spacing--sm));
	padding-inline: var(--wp--preset--spacing--sm);
}

@media (min-width: 782px) {
	.yp-section {
		margin-inline: calc(-1 * var(--wp--preset--spacing--md));
		padding-inline: var(--wp--preset--spacing--md);
	}
}

.yp-section--dark {
	position: relative;
	background: var(--wp--preset--color--near-black);
	color: var(--wp--preset--color--warm-white);
	overflow: hidden;
	isolation: isolate;
}

.yp-section--dark::before {
	content: "";
	position: absolute;
	inset: 0;
	background:
		radial-gradient(32rem 22rem at 15% 0%, rgba(0, 174, 239, 0.45), transparent 65%),
		radial-gradient(30rem 24rem at 90% 100%, rgba(236, 0, 140, 0.4), transparent 65%);
	z-index: -1;
	pointer-events: none;
}

.yp-section--dark h1,
.yp-section--dark h2,
.yp-section--dark h3 {
	color: var(--wp--preset--color--warm-white);
}

/* A faint brand-tinted wash — not flat gray — applied to alternating
   homepage sections so the page isn't wall-to-wall white/warm-white. */
.yp-section--tint {
	background: linear-gradient(180deg, rgba(0, 174, 239, 0.06), rgba(236, 0, 140, 0.06));
}

.yp-eyebrow {
	/* Block, not inline-block: has-text-align-center (the WP core class
	   already on Materials/Trending/Inspiration/Fully Custom's eyebrow
	   paragraphs) centers a block's full-width content, but has no
	   visible effect on an inline-block box that's already shrunk to
	   fit its own text — which was rendering those four off to the
	   left instead of centered under their heading. */
	display: block;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-size: 0.8125rem;
	font-weight: 700;
	color: var(--wp--preset--color--magenta-deep);
	margin-bottom: 0.5rem;
}

.yp-section--dark .yp-eyebrow {
	color: var(--wp--preset--color--cyan);
}

.yp-section--dark .wp-block-button__link {
	background: var(--wp--preset--color--warm-white);
	color: var(--wp--preset--color--near-black);
}

.yp-section--dark .wp-block-button__link:hover {
	background: var(--wp--preset--color--white);
	box-shadow: 0 0 0 3px var(--wp--preset--color--cyan);
}

.yp-section--dark .wp-block-button.is-style-outline .wp-block-button__link {
	background: transparent;
	color: var(--wp--preset--color--warm-white);
	border-color: var(--wp--preset--color--warm-white);
}

/* ---------- Hero ---------- */

.yp-hero {
	position: relative;
	padding-block: 4.5rem 3rem;
	background: var(--wp--preset--color--warm-white);
	border-radius: 0 0 var(--wp--custom--radius--container) var(--wp--custom--radius--container);
	overflow: hidden;
	isolation: isolate;
}

.yp-hero::before {
	content: "";
	position: absolute;
	inset: 0;
	background:
		radial-gradient(38rem 26rem at 8% 10%, rgba(0, 174, 239, 0.4), transparent 62%),
		radial-gradient(34rem 28rem at 92% 8%, rgba(236, 0, 140, 0.34), transparent 62%),
		radial-gradient(32rem 24rem at 50% 100%, rgba(255, 242, 0, 0.28), transparent 62%);
	z-index: -1;
	pointer-events: none;
}

.yp-hero__eyebrow-accent {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	margin-bottom: 1rem;
	padding: 0 0.6rem;
	position: relative;
}

/* A pair of print registration ticks flanking the CMY dots — a small,
   literal nod to the press-proof motif (crop marks/registration marks)
   without touching the hero's existing copy or layout. */
.yp-hero__eyebrow-accent::before,
.yp-hero__eyebrow-accent::after {
	content: "";
	width: 9px;
	height: 9px;
	flex-shrink: 0;
	border: 1.2px solid var(--wp--preset--color--charcoal);
	border-radius: 50%;
	opacity: 0.3;
	background:
		linear-gradient(var(--wp--preset--color--charcoal), var(--wp--preset--color--charcoal)) center / 1px 100% no-repeat,
		linear-gradient(var(--wp--preset--color--charcoal), var(--wp--preset--color--charcoal)) center / 100% 1px no-repeat;
}

.yp-hero__eyebrow-accent span {
	width: 0.6rem;
	height: 0.6rem;
	border-radius: 999px;
}

.yp-hero__eyebrow-accent span:nth-child(1) { background: var(--wp--preset--color--cyan); box-shadow: 0 0 14px rgba(0, 174, 239, 0.55); }
.yp-hero__eyebrow-accent span:nth-child(2) { background: var(--wp--preset--color--magenta); box-shadow: 0 0 14px rgba(236, 0, 140, 0.55); }
.yp-hero__eyebrow-accent span:nth-child(3) { background: var(--wp--preset--color--yellow); box-shadow: 0 0 14px rgba(255, 242, 0, 0.55); }

.yp-eyebrow-label {
	display: inline-flex;
	align-items: center;
	font-family: var(--wp--preset--font-family--mono);
	font-size: 0.72rem;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--wp--preset--color--charcoal);
	background: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--light-gray);
	border-radius: 999px;
	padding: 0.4rem 0.9rem;
	margin: 0 0 1.1rem;
}

.yp-hero__accent-word {
	color: var(--wp--preset--color--magenta-deep);
}

.yp-hero__stats {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	justify-content: flex-start;
	gap: 0.75rem 1.75rem;
	margin: 2rem 0 0;
	padding: 0;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	color: var(--wp--preset--color--charcoal);
}

/* ---------- Hero: two-column grid + press-proof visual ---------- */

/* layout:"default" on the block (a flow container) so WordPress's own
   blockGap CSS custom property stays available to fall back on, then
   overridden into an actual grid here — the same technique already
   used by .yp-steps below, for the same reason: a real grid, not a
   flex/flow approximation of one. */
.yp-hero__grid {
	display: grid;
	grid-template-columns: 1.05fr 0.95fr;
	gap: clamp(2rem, 5vw, 4rem);
	align-items: center;
}

/* Same fix as .yp-steps below: layout:"default" auto-injects
   margin-block-start on every child but the first, meant for a
   stacked flow layout — this container is a grid instead, already
   spaced by `gap` above, so that margin only pushes the second column
   out of vertical alignment with the first. */
.yp-hero__grid > * {
	margin-block-start: 0 !important;
	margin-block-end: 0 !important;
}

@media (max-width: 900px) {
	.yp-hero__grid {
		grid-template-columns: 1fr;
	}
}

.yp-hero__visual {
	display: flex;
	justify-content: center;
}

.yp-proof {
	position: relative;
	aspect-ratio: 1 / 1;
	width: 100%;
	max-width: 400px;
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--wp--preset--color--white);
	border: 1px solid var(--wp--preset--color--light-gray);
	border-radius: var(--wp--custom--radius--container);
	box-shadow: var(--wp--custom--shadow-elevation--medium);
}

.yp-proof__corner {
	position: absolute;
	width: 20px;
	height: 20px;
	opacity: 0.35;
}

.yp-proof__corner::before,
.yp-proof__corner::after {
	content: "";
	position: absolute;
	background: var(--wp--preset--color--charcoal);
}

.yp-proof__corner::before { top: 0; left: 0; width: 1.4px; height: 100%; }
.yp-proof__corner::after { top: 0; left: 0; width: 100%; height: 1.4px; }

.yp-proof__corner--tl { top: 16px; left: 16px; }
.yp-proof__corner--tr { top: 16px; right: 16px; transform: scaleX(-1); }
.yp-proof__corner--bl { bottom: 16px; left: 16px; transform: scaleY(-1); }
.yp-proof__corner--br { bottom: 16px; right: 16px; transform: scale(-1); }

.yp-proof__mark {
	/* Direct report: on a phone this read as a small, oddly narrow strip
	   floating in a mostly-empty white card. The SVG's own shape (in
	   patterns/hero.php) is a squared-off swatch now instead of a tall
	   pill, and this width is bumped up to actually fill the card's
	   available space (.yp-proof's corner brackets sit at a fixed 16px
	   inset regardless of card size, so there's still clear room at
	   every size this card renders at, mobile included). */
	width: 62%;
	filter: drop-shadow(0 14px 20px rgba(20, 20, 20, 0.18));
}

/* Each bar snaps in from a slightly different direction/delay — a
   small nod to a press proof's colors dropping into registration one
   pass at a time. */
.yp-proof__bar {
	transform-origin: bottom;
	animation-duration: 1.1s;
	animation-timing-function: cubic-bezier(0.2, 0.9, 0.25, 1);
	animation-iteration-count: 1;
	animation-fill-mode: both;
}

.yp-proof__bar--c { animation-name: yp-proof-snap-left; animation-delay: 0s; }
.yp-proof__bar--m { animation-name: yp-proof-snap-down; animation-delay: 0.06s; }
.yp-proof__bar--y { animation-name: yp-proof-snap-right; animation-delay: 0.12s; }

@keyframes yp-proof-snap-left {
	0% { transform: translateX(-14px); opacity: 0; }
	60% { opacity: 1; }
	100% { transform: translateX(0); opacity: 1; }
}

@keyframes yp-proof-snap-down {
	0% { transform: translateY(14px); opacity: 0; }
	60% { opacity: 1; }
	100% { transform: translateY(0); opacity: 1; }
}

@keyframes yp-proof-snap-right {
	0% { transform: translateX(14px); opacity: 0; }
	60% { opacity: 1; }
	100% { transform: translateX(0); opacity: 1; }
}

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

.yp-proof__caption {
	position: absolute;
	bottom: 20px;
	left: 50%;
	transform: translateX(-50%);
	font-family: var(--wp--preset--font-family--mono);
	font-size: 0.68rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--charcoal);
	opacity: 0.55;
	white-space: nowrap;
}

.yp-hero__stats li {
	display: flex;
	align-items: center;
	gap: 0.5rem;
}

.yp-hero__stats-dot {
	width: 0.55rem;
	height: 0.55rem;
	border-radius: 999px;
	flex-shrink: 0;
}

.yp-view-all-link {
	display: inline-flex;
	align-items: center;
	font-weight: 600;
	font-size: var(--wp--preset--font-size--small);
	padding: 0.55rem 1.1rem;
	border-radius: var(--wp--custom--radius--control);
	background: var(--wp--preset--color--white);
	box-shadow: var(--wp--custom--shadow-elevation--low);
	text-decoration: none !important;
	color: var(--wp--preset--color--near-black) !important;
	transition: box-shadow 150ms ease, transform 150ms ease;
}

.yp-view-all-link:hover {
	box-shadow: var(--wp--custom--shadow-elevation--medium);
	transform: translateY(-1px);
}

/* ---------- Card grids (Featured Designs, Popular Designs) ---------- */

.yp-card-grid {
	/* Fixed-width columns (auto-fill, not auto-fit/minmax(...,1fr)) —
	   the previous 1fr version stretched each item's own grid cell to
	   fill the row, so with e.g. 2 cards in a 4-column-wide row, card 2
	   sat at the start of its own (very wide) second cell, landing far
	   to the right instead of right next to card 1 — the "cards aren't
	   lined up" bug. Fixed columns mean every card is the same width
	   and sits immediately next to the last one; any leftover row
	   space is simply blank at the end, not distributed into cells.
	   Still fully responsive: auto-fill fits as many 270px columns as
	   the container allows at any viewport, down to one on mobile.
	   !important on the grid-defining properties: this has now gone
	   through several rounds of genuine, verified-correct fixes for
	   *different* real bugs (sparse-row tracks, a stretch regression, a
	   static-positioned image, an aspect-ratio specificity conflict)
	   without the live site ever confirming resolved — strongly
	   suggesting something outside this stylesheet (a competing rule
	   with unexpected load order, or a caching/Site-Editor-database
	   override serving a stale version of this file/template entirely)
	   rather than another undiscovered bug in this exact rule. This
	   guarantees the grid itself can't lose to anything else targeting
	   the same element, closing off that specific failure mode either
	   way. See docs/ARCHITECTURE.md §9. */
	display: grid !important;
	grid-template-columns: repeat(auto-fill, 270px) !important;
	/* justify-content only — align-items stays the grid default
	   (stretch), which keeps every card the same outer height across a
	   row even when body text length differs between cards; align-
	   items:start would let each card size to its own content instead,
	   leaving bottom edges misaligned whenever text length differs. */
	justify-content: start !important;
	gap: var(--wp--preset--spacing--sm);
}

/* Direct request: on a phone-width screen this grid almost always has
   room for exactly one 270px column, and justify-content:start above
   (deliberately kept for desktop's multi-card rows, see that rule's own
   comment) left that single card pinned to the left edge with a wall of
   blank space beside it instead of centered. Same 782px breakpoint the
   rest of this theme already treats as the mobile/desktop line (e.g.
   global.css's main.wp-block-group padding-inline). */
@media (max-width: 782px) {
	.yp-card-grid {
		justify-content: center !important;
	}
}

/* Defensive reset on the grid items themselves (core/post-template
   renders each result as an <li>, one level above .yp-template-card) —
   in case any core/theme default ever puts a width or margin on these
   that would fight the grid's own column sizing. */
.yp-card-grid > li {
	margin: 0 !important;
	width: auto !important;
	min-width: 0;
}

.yp-customer-tile {
	/* Real customer photos aren't in yet — a soft brand-gradient wash
	   with a photo icon reads as "coming soon," not as a broken/missing
	   image the way a flat gray box (the .yp-card__media default) did. */
	display: flex;
	align-items: center;
	justify-content: center;
	background: linear-gradient(135deg, rgba(0, 174, 239, 0.14), rgba(236, 0, 140, 0.14));
	color: var(--wp--preset--color--magenta-deep);
}

/* ---------- Template card (gallery + homepage rails) ---------- */

.yp-template-card {
	/* .yp-card-grid's columns are a fixed width now, so the card just
	   fills its own column — no separate cap needed. */
	display: block;
	width: 100%;
	color: inherit;
	text-decoration: none;
}

.yp-card__media.yp-template-card__media {
	/* Both classes in the selector, not just .yp-template-card__media
	   alone — .yp-card__media (global.css) sets aspect-ratio:4/5 on the
	   exact same element (render.php outputs both classes together),
	   and with equal single-class specificity on each, which one wins
	   depended entirely on stylesheet load order rather than being
	   guaranteed. Was 15:7 (the real flat label's 45mm x 21mm ratio)
	   back when the flat label artwork was the primary card image —
	   now that the vial-mockup photo is primary (direct request: show
	   the vial preview, not just the label), that wide/short box would
	   object-fit:cover-crop a tall standing-vial photo down to a
	   narrow middle strip, cutting off most of the actual label. No
	   override needed: falls through to .yp-card__media's own 4:5,
	   which is also what the approved brand mockup used for these
	   cards.

	   The navy gradient background is the approved brand mockup's
	   product-photography backdrop — kept on this combined selector
	   (not the shared .yp-card__media base) so other card types, e.g.
	   the customer-work tiles, keep their own background. It only
	   shows through where an image has transparent padding, but still
	   reads as a considered "on a light table" backdrop even when the
	   image fills the box completely. */
	position: relative;
	background: var(--wp--custom--gradient-navy);
}

.yp-template-card__image {
	/* Absolute, not static — with .yp-template-card__media a fixed
	   aspect-ratio box, a static image relying on height:100% doesn't
	   reliably resolve against an aspect-ratio-derived height and falls
	   back to its own intrinsic ratio instead, so the card's height
	   would end up depending on whatever ratio the uploaded image
	   happens to have rather than the fixed box. No hover-swap anymore
	   (direct request — the second image read badly cropped in this
	   box's shape) — just the one vial-mockup-or-artwork-fallback image
	   from render.php, filling the box via object-fit:cover. */
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.yp-template-card__badge {
	position: absolute;
	top: 0.75rem;
	left: 0.75rem;
	background: var(--wp--preset--color--white);
	/* The base .yp-card__badge rule (global.css) sets color:white for
	   its own gradient background — never overridden here, so the
	   label text was invisible (white on this white pill) ever since
	   this rule first set a white background. Direct report: "the
	   badges appear blank on the templates I select a badge for." */
	color: var(--wp--preset--color--magenta-deep);
	box-shadow: var(--wp--custom--shadow-elevation--low);
}

.yp-template-card__body {
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
}

.yp-template-card__title {
	font-weight: 600;
}

.yp-template-card__specs {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem;
}

.yp-spec-chip {
	font-family: var(--wp--preset--font-family--mono);
	font-size: 0.68rem;
	font-weight: 600;
	letter-spacing: 0.02em;
	color: var(--wp--preset--color--charcoal);
	background: var(--wp--preset--color--warm-white);
	border: 1px solid var(--wp--preset--color--light-gray);
	border-radius: var(--wp--custom--radius--control);
	padding: 0.2rem 0.5rem;
}

.yp-template-card__foot {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.5rem;
	margin-top: auto;
}

.yp-template-card__price {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	color: var(--wp--preset--color--charcoal);
}

.yp-template-card__cta {
	font-size: 0.78rem;
	font-weight: 600;
	color: var(--wp--preset--color--warm-white);
	background: var(--wp--preset--color--near-black);
	border-radius: var(--wp--custom--radius--control);
	padding: 0.4rem 0.85rem;
	transition: background 150ms ease, color 150ms ease;
}

.yp-template-card:hover .yp-template-card__cta {
	background: var(--wp--custom--gradient-brand-deep);
}

/* ---------- How It Works ---------- */

.yp-steps {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--wp--preset--spacing--md);
	align-items: stretch;
}

/* The real cause of "first card taller than the rest": .yp-steps is a
   Group block with layout:"default" (flow), so WordPress auto-injects
   its own vertical blockGap spacing as margin-block-start on every
   child except the first — meant for a normal stacked/flow layout, but
   this container is a grid instead (our own `gap` above already spaces
   the 3 columns). With align-items:stretch, each item's box is
   stretched to fill the shared row height *minus its own margin* — so
   card 1 (no margin subtracted, nothing bumps it) ends up visibly
   taller than cards 2/3 (which lose height to that unwanted top
   margin), even though all three have identical box-sizing otherwise.
   Zeroing it is safe: spacing between the cards is already fully
   handled by `gap`, so this margin was doing nothing but causing this. */
.yp-steps > * {
	margin-block-start: 0 !important;
	margin-block-end: 0 !important;
}

@media (max-width: 781px) {
	.yp-steps {
		grid-template-columns: 1fr;
	}
}

.yp-step {
	/* flex column, not just relying on implicit grid stretch — the
	   three cards' description text differs slightly in length, and
	   this guarantees identical card heights regardless of that rather
	   than leaving it to each browser's own stretch/sizing behavior. */
	position: relative;
	display: flex;
	flex-direction: column;
	background: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--radius--card);
	box-shadow: var(--wp--custom--shadow-elevation--low);
	padding: var(--wp--preset--spacing--md);
	overflow: hidden;
}

.yp-step::before {
	content: "";
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	height: 4px;
}

/* :nth-child(3n+1/2/3), not the literal 1/2/3 this started as — the
   How It Works page's own process-steps pattern reuses .yp-steps with
   6 cards, and this cycle needs to repeat every 3 rather than stopping
   after the first three. Matches the homepage's 3-card case exactly
   (3n+1 = child 1, 4, 7…, so nothing changes there). */
.yp-step:nth-child(3n+1)::before { background: var(--wp--preset--color--cyan); }
.yp-step:nth-child(3n+2)::before { background: var(--wp--preset--color--magenta-deep); }
.yp-step:nth-child(3n)::before { background: var(--wp--preset--color--yellow); }

.yp-step__index {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.5rem;
	height: 2.5rem;
	border-radius: 999px;
	background: var(--wp--preset--color--near-black);
	color: var(--wp--preset--color--warm-white);
	font-weight: 700;
	margin-bottom: 1rem;
}

.yp-step:nth-child(3n+1) .yp-step__index {
	background: var(--wp--preset--color--cyan);
	color: var(--wp--preset--color--near-black);
	box-shadow: 0 6px 16px rgba(0, 174, 239, 0.35);
}

.yp-step:nth-child(3n+2) .yp-step__index {
	background: var(--wp--preset--color--magenta-deep);
	color: var(--wp--preset--color--white);
	box-shadow: 0 6px 16px rgba(236, 0, 140, 0.35);
}

.yp-step:nth-child(3n) .yp-step__index {
	background: var(--wp--preset--color--yellow);
	color: var(--wp--preset--color--near-black);
	box-shadow: 0 6px 16px rgba(255, 242, 0, 0.4);
}

/* ---------- Turnaround Time (How It Works page) ---------- */

.yp-turnaround {
	max-width: 480px;
	margin-inline: auto;
	text-align: center;
	background: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--radius--card);
	box-shadow: var(--wp--custom--shadow-elevation--medium);
	padding: var(--wp--preset--spacing--lg) var(--wp--preset--spacing--md);
}

.yp-turnaround__stat {
	font-size: var(--wp--preset--font-size--xx-large);
	font-weight: 700;
	color: var(--wp--preset--color--magenta-deep);
	margin: 0 0 0.5rem;
	line-height: 1;
}

/* ---------- Materials ---------- */

.yp-materials-grid {
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	gap: var(--wp--preset--spacing--sm);
}

@media (max-width: 1024px) {
	.yp-materials-grid {
		grid-template-columns: repeat(3, 1fr);
	}
}

@media (max-width: 600px) {
	.yp-materials-grid {
		grid-template-columns: repeat(2, 1fr);
	}
}

.yp-material-swatch {
	text-align: center;
}

.yp-material-swatch__chip {
	/* A real uploaded photo (admin: Materials → Featured Image for the
	   swatch, "Hover / on-vial image" for the hover-swap — V2, direct
	   request) always wins; the gradient variants below are the fallback
	   for a Material that doesn't have a photo uploaded yet, keyed by
	   the record's own slug (matches the demo-seeded Glossy White/Matte
	   White/Holographic/Clear/Metallic records) rather than a flat gray
	   box that actively misrepresents these finishes' distinct looks. */
	aspect-ratio: 1;
	border-radius: var(--wp--custom--radius--card);
	box-shadow: var(--wp--custom--shadow-elevation--low);
	background: var(--wp--preset--color--light-gray);
	margin-bottom: 0.75rem;
	position: relative;
	overflow: hidden;
}

.yp-material-swatch__image {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: opacity 250ms ease;
}

.yp-material-swatch__image--primary {
	opacity: 1;
}

.yp-material-swatch__image--hover {
	opacity: 0;
}

@media (hover: hover) {
	.yp-material-swatch:hover .yp-material-swatch__image--hover {
		opacity: 1;
	}
}

/* Each fallback here is shared with material-guide.php's own photo
   circles (.yp-material-guide__photo--{slug}) via the same selector
   list, not duplicated — one "what does this material look like
   without a real photo yet" definition per material, used by both the
   swatch grid and the guide below it. */

.yp-material-swatch__chip--glossy-white,
.yp-material-guide__photo--glossy-white {
	background: linear-gradient(135deg, #ffffff 0%, #f2f1ee 55%, #ffffff 100%);
}

.yp-material-swatch__chip--glossy-white::after {
	/* A soft diagonal highlight band reads as "glossy/reflective" rather
	   than flat, without needing a real photo. Swatch-grid only (its
	   square chip has room for this); the guide's own small circle
	   skips it rather than fighting for space with border-radius:50%. */
	content: "";
	position: absolute;
	inset: -60% -10%;
	background: linear-gradient(115deg, transparent 40%, rgba(255, 255, 255, 0.9) 50%, transparent 60%);
	transform: rotate(3deg);
}

.yp-material-swatch__chip--matte-white,
.yp-material-guide__photo--matte-white {
	background: linear-gradient(160deg, #f5f4f0 0%, #e9e7e1 100%);
}

.yp-material-swatch__chip--holographic,
.yp-material-guide__photo--holographic {
	background: linear-gradient(120deg, #00aeef 0%, #ec008c 33%, #fff200 66%, #00aeef 100%);
	background-size: 220% 220%;
}

.yp-material-swatch__chip--prism,
.yp-material-guide__photo--prism {
	/* Narrow repeating bands, distinct from holographic's broad diagonal
	   wash above — reads as a fine prism/light-split pattern rather than
	   a second holographic look. */
	background: repeating-linear-gradient(
		100deg,
		#00aeef 0%, #00aeef 8%,
		#ec008c 8%, #ec008c 16%,
		#fff200 16%, #fff200 24%,
		#ffffff 24%, #ffffff 32%
	);
}

.yp-material-swatch__chip--clear,
.yp-material-guide__photo--clear {
	background:
		repeating-linear-gradient(45deg, rgba(20, 20, 20, 0.05) 0 2px, transparent 2px 10px),
		linear-gradient(160deg, rgba(0, 174, 239, 0.12), rgba(236, 0, 140, 0.1));
	border: 1.5px solid rgba(20, 20, 20, 0.12);
}

.yp-material-swatch__chip--metallic,
.yp-material-guide__photo--metallic {
	background: linear-gradient(135deg, #d8dbe0 0%, #9a9fa8 40%, #eef0f2 55%, #7d828c 100%);
}

.yp-material-swatch__name {
	font-weight: 600;
	margin-bottom: 0.15rem;
}

.yp-material-swatch__blurb {
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--charcoal);
	margin: 0;
}

/* ---------- Material guide (How It Works page — material-guide.php) ---------- */

.yp-material-guide {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--sm);
	margin-top: var(--wp--preset--spacing--md);
}

.yp-material-guide__item {
	display: flex;
	align-items: flex-start;
	gap: var(--wp--preset--spacing--sm);
	background: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--radius--card);
	box-shadow: var(--wp--custom--shadow-elevation--low);
	padding: var(--wp--preset--spacing--md);
}

@media (max-width: 600px) {
	/* A circle competing with a card's own padding for space reads as
	   cramped at this width — centered above the text instead. */
	.yp-material-guide__item {
		flex-direction: column;
		align-items: center;
		text-align: center;
	}

	.yp-material-guide__header {
		justify-content: center;
	}
}

/* Circle so it reads as a material sample, not a product photo —
   .yp-material-swatch above already establishes photo = square chip,
   so a circle here keeps this section visually distinct from that one
   despite reusing its same fallback-gradient definitions. */
.yp-material-guide__photo {
	flex-shrink: 0;
	width: 88px;
	height: 88px;
	border-radius: 50%;
	object-fit: cover;
	box-shadow: var(--wp--custom--shadow-elevation--low);
}

/* Configurator's Material info modal (patterns/material-info-modal.php)
   reuses this exact component inside a 600px-wide drawer instead of
   the How It Works page's full content width — a smaller circle keeps
   six items comfortably scannable without shrinking the drawer's own
   scroll area down to nothing. */
.yp-material-guide--modal .yp-material-guide__photo {
	width: 64px;
	height: 64px;
}

/* Click-to-enlarge (direct request: "hover or click... to see a bigger
   image"). The button wraps the same .yp-material-guide__photo circle
   unchanged; a small always-visible badge signals it's tappable (touch
   devices never get a :hover state, so the affordance can't depend on
   one), and hovering/focusing scales the circle up as tactile feedback
   before the click opens the real enlarged photo in a modal. Only
   rendered at all when there's a larger image to show — see this
   pattern's own docblock. */
.yp-material-guide__photo-btn {
	flex-shrink: 0;
	position: relative;
	display: block;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: none;
	cursor: pointer;
	transition: transform 200ms ease;
}

.yp-material-guide__photo-btn:hover,
.yp-material-guide__photo-btn:focus-visible {
	transform: scale(1.06);
}

.yp-material-guide__photo-btn:focus-visible {
	outline: 2px solid var(--wp--preset--color--cyan-deep);
	outline-offset: 2px;
}

.yp-material-guide__zoom-badge {
	position: absolute;
	right: -2px;
	bottom: -2px;
	width: 22px;
	height: 22px;
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--wp--preset--color--charcoal);
	color: var(--wp--preset--color--white);
	border-radius: 50%;
	border: 2px solid var(--wp--preset--color--white);
	box-shadow: var(--wp--custom--shadow-elevation--low);
}

.yp-material-guide__zoom-body img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: var(--wp--custom--radius--card);
}

.yp-material-guide__body {
	flex-grow: 1;
	min-width: 0;
}

.yp-material-guide__header {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 0.5rem 1rem;
	margin-bottom: 0.5rem;
}

.yp-material-guide__header h3 {
	margin: 0;
}

.yp-material-guide__spec {
	flex-shrink: 0;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: var(--wp--preset--color--cyan-deep);
	background: rgba(0, 174, 239, 0.1);
	border-radius: var(--wp--custom--radius--control);
	padding: 0.2rem 0.65rem;
}

.yp-material-guide__item p {
	margin: 0 0 0.5rem;
}

.yp-material-guide__item p:last-child {
	margin-bottom: 0;
}

.yp-material-guide__note {
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--charcoal);
	background: var(--wp--preset--color--warm-white);
	border-left: 3px solid var(--wp--preset--color--magenta-deep);
	border-radius: 0 var(--wp--custom--radius--control) var(--wp--custom--radius--control) 0;
	padding: 0.65rem 0.9rem;
}

/* ---------- Rewards promo ---------- */

.yp-rewards-promo {
	background: var(--wp--preset--color--warm-white);
	border: 1.5px solid rgba(236, 0, 140, 0.22);
	border-radius: var(--wp--custom--radius--container);
	padding: var(--wp--preset--spacing--lg);
	position: relative;
	overflow: hidden;
	isolation: isolate;
}

.yp-rewards-promo::before {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(120deg, rgba(0, 174, 239, 0.18), rgba(236, 0, 140, 0.18), rgba(255, 242, 0, 0.18));
	z-index: -1;
	pointer-events: none;
}

/* ---------- Reviews ---------- */

.yp-reviews-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--wp--preset--spacing--sm);
}

@media (max-width: 781px) {
	.yp-reviews-grid {
		grid-template-columns: 1fr;
	}
}

.yp-review-card {
	background: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--radius--card);
	box-shadow: var(--wp--custom--shadow-elevation--low);
	padding: var(--wp--preset--spacing--md);
}

.yp-review-card__stars {
	color: var(--wp--preset--color--magenta-deep);
	letter-spacing: 0.15em;
	margin-bottom: 0.75rem;
}

/* ---------- FAQ (core/details) ---------- */

.yp-faq .wp-block-details {
	border-bottom: 1px solid var(--wp--preset--color--light-gray);
	padding-block: 1rem;
}

.yp-faq .wp-block-details summary {
	font-weight: 600;
	cursor: pointer;
}

.yp-faq .wp-block-details summary:focus-visible {
	outline: 2px solid var(--wp--custom--focus-ring);
	outline-offset: 4px;
}

/* ---------- Shop Labels: sort + filter bar ---------- */

.yp-gallery-toolbar {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 1rem;
	margin-bottom: var(--wp--preset--spacing--md);
}

.yp-filter-group {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
}

.yp-filter-pill {
	display: inline-flex;
	align-items: center;
	padding: 0.4rem 0.9rem;
	border-radius: var(--wp--custom--radius--control);
	border: 1px solid var(--wp--preset--color--light-gray);
	background: var(--wp--preset--color--white);
	font-family: var(--wp--preset--font-family--mono);
	font-size: 0.78rem;
	font-weight: 600;
	color: var(--wp--preset--color--charcoal);
	text-decoration: none;
	transition: background-color 150ms ease, border-color 150ms ease, color 150ms ease;
}

.yp-filter-pill:hover {
	border-color: var(--wp--preset--color--charcoal);
}

.yp-filter-pill.is-active {
	background: var(--wp--preset--color--near-black);
	border-color: var(--wp--preset--color--near-black);
	color: var(--wp--preset--color--warm-white);
}

.yp-sort-select {
	width: auto;
	min-width: 10rem;
}

.yp-gallery-empty {
	text-align: center;
	padding: var(--wp--preset--spacing--xl) 0;
	color: var(--wp--preset--color--charcoal);
}

/* ---------- Predictive search results ---------- */

.yp-search-results__list {
	list-style: none;
	margin: 1rem 0 0;
	padding: 0;
}

.yp-search-results__item {
	display: block;
	padding: 0.75rem 0;
	border-bottom: 1px solid var(--wp--preset--color--light-gray);
	text-decoration: none;
	color: var(--wp--preset--color--near-black);
}

.yp-search-results__empty {
	margin-top: 1rem;
	color: var(--wp--preset--color--charcoal);
	font-size: var(--wp--preset--font-size--small);
}

/* ---------- Homepage promo banner (blocks/promo-banner) ----------
   Dashboard → YeffoPrint → Settings → Homepage Promo. One set of rules
   for all 12 seasonal themes (YeffoPrint_Promo_Themes) — render.php
   sets the --yp-promo-* custom properties per theme on the section
   root, so switching themes never means switching stylesheets. */

.yp-promo {
	position: relative;
	background-color: var(--yp-promo-bg);
	background-image:
		radial-gradient(circle at 14% -10%, var(--yp-promo-glow-a), transparent 55%),
		radial-gradient(circle at 100% 120%, var(--yp-promo-glow-b), transparent 60%);
	color: var(--yp-promo-ink);
	overflow: hidden;
	/* A little breathing room off the search bar directly above it — same
	   radius token as the other full-width rounded banner on this page,
	   .yp-rewards-promo. Needs !important: confirmed via computed styles
	   that WordPress's own generated layout CSS for a "flow" group
	   (`.wp-block-group.is-layout-flow > *:first-child { margin-block-
	   start: 0; }`, three classes/pseudo-classes) otherwise beats a plain
	   `.yp-promo` selector (one class) regardless of load order or the
	   physical/logical property difference — the earlier flow-root fix
	   on `main` (global.css) was real and necessary (stops the margin
	   from collapsing through main entirely) but doesn't help against
	   this separate, more specific rule zeroing the child's own margin
	   directly. Also bumped a size up from the original spacing--sm. */
	margin-top: var(--wp--preset--spacing--md) !important;
	border-radius: var(--wp--custom--radius--container);
}

.yp-promo__grid {
	display: grid;
	grid-template-columns: 1.15fr 0.85fr;
	align-items: center;
	gap: var(--wp--preset--spacing--md);
	max-width: 1200px;
	margin: 0 auto;
	padding: var(--wp--preset--spacing--lg) var(--wp--preset--spacing--sm);
}

.yp-promo__eyebrow {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	font-family: var(--wp--preset--font-family--heading);
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--yp-promo-accent);
	margin: 0 0 0.85rem;
}

.yp-promo__dash {
	width: 20px;
	height: 1.5px;
	background: var(--yp-promo-accent);
	display: inline-block;
}

.yp-promo__headline {
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 800;
	font-size: clamp(1.9rem, 3.3vw, 2.75rem);
	line-height: 1.05;
	margin: 0 0 0.9rem;
	letter-spacing: -0.01em;
	text-wrap: balance;
	color: var(--yp-promo-ink);
}

.yp-promo__body {
	font-size: 1.02rem;
	line-height: 1.55;
	color: var(--yp-promo-ink-soft);
	max-width: 46ch;
	margin: 0 0 1.5rem;
}

.yp-promo__row {
	display: flex;
	align-items: center;
	gap: 1.1rem;
	flex-wrap: wrap;
}

.yp-promo__code {
	display: inline-flex;
	align-items: center;
	gap: 0.55rem;
	background: var(--yp-promo-code-bg);
	color: var(--yp-promo-code-ink);
	padding: 0.55rem 0.5rem 0.55rem 0.9rem;
	border-radius: var(--wp--custom--radius--control);
	font-family: var(--wp--preset--font-family--mono);
	font-weight: 600;
	font-size: 0.92rem;
	letter-spacing: 0.02em;
}

.yp-promo__code-hole {
	width: 14px;
	height: 14px;
	border-radius: 50%;
	background: color-mix(in srgb, var(--yp-promo-code-ink) 10%, transparent);
	border: 1.5px dashed color-mix(in srgb, var(--yp-promo-code-ink) 35%, transparent);
	flex-shrink: 0;
}

.yp-promo__code-label {
	font-family: var(--wp--preset--font-family--body);
	font-weight: 600;
	font-size: 0.74rem;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	opacity: 0.65;
}

.yp-promo__cta {
	display: inline-flex;
	align-items: center;
	gap: 0.4rem;
	background: var(--yp-promo-accent);
	color: var(--yp-promo-accent-ink);
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 700;
	font-size: 0.92rem;
	text-decoration: none;
	padding: 0.8rem 1.4rem;
	border-radius: var(--wp--custom--radius--input);
	transition: filter 150ms ease;
}

.yp-promo__cta:hover {
	filter: brightness(1.08);
}

.yp-promo__visual {
	display: flex;
	justify-content: center;
	align-items: center;
}

.yp-promo__proof {
	position: relative;
	width: 220px;
	height: 250px;
}

.yp-promo__corner {
	position: absolute;
	width: 22px;
	height: 22px;
	border-color: color-mix(in srgb, var(--yp-promo-ink) 55%, transparent);
}

.yp-promo__corner--tl {
	top: 0;
	left: 0;
	border-top: 1.5px solid;
	border-left: 1.5px solid;
}

.yp-promo__corner--tr {
	top: 0;
	right: 0;
	border-top: 1.5px solid;
	border-right: 1.5px solid;
}

.yp-promo__corner--bl {
	bottom: 0;
	left: 0;
	border-bottom: 1.5px solid;
	border-left: 1.5px solid;
}

.yp-promo__corner--br {
	bottom: 0;
	right: 0;
	border-bottom: 1.5px solid;
	border-right: 1.5px solid;
}

.yp-promo__mark {
	position: absolute;
	inset: 8px;
	border-radius: 20px;
	overflow: hidden;
	display: flex;
	box-shadow: var(--wp--custom--shadow-elevation--high);
}

.yp-promo__bar {
	flex: 1;
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
}

.yp-promo__bar--1 {
	background: var(--yp-promo-bar-1);
}

.yp-promo__bar--2 {
	background: var(--yp-promo-bar-2);
}

.yp-promo__bar--3 {
	background: var(--yp-promo-bar-3);
}

.yp-promo__icon {
	width: 28px;
	height: 28px;
	color: var(--yp-promo-bg);
	opacity: 0.85;
}

/* ---------- Multi-banner rotation (2+ active themes) ----------
   Direct request: "select more than one active promo banner and have
   it slide through the active ones." Only one `.yp-promo--slide` is
   ever laid out at a time (display:none on the rest) rather than an
   absolutely-positioned crossfade stack — themes vary slightly in copy
   length, and this sidesteps needing a JS-measured shared height
   entirely; the brief fade-in on activation still reads as a
   transition. site.js's initPromoRotator() owns the timer/dot clicks;
   this file only owns how each state looks. */

.yp-promo-rotator {
	position: relative;
	overflow: hidden;
	border-radius: var(--wp--custom--radius--container);
	margin-top: var(--wp--preset--spacing--md) !important;
}

.yp-promo-rotator .yp-promo--slide {
	display: none;
	margin-top: 0 !important;
}

.yp-promo-rotator .yp-promo--slide.is-active {
	display: block;
	animation: yp-promo-fade-in 500ms ease;
}

@media (prefers-reduced-motion: reduce) {
	.yp-promo-rotator .yp-promo--slide.is-active {
		animation: none;
	}
}

@keyframes yp-promo-fade-in {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}

.yp-promo-rotator .yp-promo__grid {
	/* Room for the dot pill below, on top of the CTA row's own spacing. */
	padding-bottom: calc(var(--wp--preset--spacing--lg) + 1.75rem);
}

/* A translucent dark pill behind the dots, not theme-colored — the
   active slide's own palette ranges from near-black to near-white
   across the 13 themes, so a fixed light or dark dot alone would
   disappear against roughly half of them. This reads on all of them. */
.yp-promo-rotator__dots {
	position: absolute;
	bottom: 0.85rem;
	left: 50%;
	transform: translateX(-50%);
	z-index: 2;
	display: flex;
	gap: 0.4rem;
	padding: 0.4rem 0.55rem;
	border-radius: 999px;
	background: rgba(0, 0, 0, 0.28);
	backdrop-filter: blur(6px);
}

.yp-promo-rotator__dot {
	width: 0.5rem;
	height: 0.5rem;
	padding: 0;
	border: none;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.45);
	cursor: pointer;
	transition: background 150ms ease, transform 150ms ease;
}

.yp-promo-rotator__dot:hover {
	background: rgba(255, 255, 255, 0.7);
}

.yp-promo-rotator__dot.is-active {
	background: #ffffff;
	transform: scale(1.3);
}

@media (max-width: 761px) {
	.yp-promo__grid {
		grid-template-columns: 1fr;
		text-align: left;
	}

	.yp-promo__visual {
		order: -1;
		margin-bottom: 0.5rem;
	}

	.yp-promo__proof {
		width: 150px;
		height: 170px;
	}
}

/* ---------- Web Design page ---------- */

.yp-browser-mock {
	width: 100%;
	max-width: 420px;
	filter: drop-shadow(0 14px 24px rgba(20, 20, 20, 0.14));
}

.yp-browser-mock__frame {
	fill: var(--wp--preset--color--white);
	stroke: var(--wp--preset--color--light-gray);
	stroke-width: 1.5;
}

.yp-browser-mock__chrome {
	fill: var(--wp--preset--color--warm-white);
}

.yp-browser-mock__dot--c { fill: var(--wp--preset--color--cyan); }
.yp-browser-mock__dot--m { fill: var(--wp--preset--color--magenta); }
.yp-browser-mock__dot--y { fill: var(--wp--preset--color--yellow); }

.yp-browser-mock__address {
	fill: var(--wp--preset--color--light-gray);
}

.yp-browser-mock__banner {
	fill: url(#ypWebDesignBannerGradient);
}

.yp-browser-mock__banner-line {
	fill: var(--wp--preset--color--white);
	opacity: 0.9;
}

.yp-browser-mock__banner-line--soft {
	opacity: 0.6;
}

.yp-browser-mock__card rect:first-child {
	fill: var(--wp--preset--color--white);
	stroke: var(--wp--preset--color--light-gray);
	stroke-width: 1.2;
}

.yp-browser-mock__swatch {
	opacity: 0.85;
}

.yp-browser-mock__swatch--c { fill: var(--wp--preset--color--cyan-deep); }
.yp-browser-mock__swatch--m { fill: var(--wp--preset--color--magenta-deep); }
.yp-browser-mock__swatch--y { fill: var(--wp--preset--color--yellow); }

.yp-browser-mock__text {
	fill: var(--wp--preset--color--charcoal);
	opacity: 0.5;
}

.yp-browser-mock__text--soft {
	opacity: 0.28;
}

.yp-browser-mock__cart {
	fill: var(--wp--preset--color--near-black);
}

.yp-browser-mock__cart-icon {
	stroke: var(--wp--preset--color--warm-white);
	stroke-width: 1.5;
	stroke-linecap: round;
	stroke-linejoin: round;
}

/* Package tier cards — same 3-column grid + margin-block-start reset as
   .yp-steps above (a Group block with layout:"default" auto-injects a
   top margin on every child but the first, which fights a grid's own
   `gap` and makes the first card look taller; see .yp-steps' own
   comment for the full explanation). */
.yp-web-design-packages {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--wp--preset--spacing--md);
	align-items: stretch;
	margin-top: var(--wp--preset--spacing--md);
}

.yp-web-design-packages > * {
	margin-block-start: 0 !important;
	margin-block-end: 0 !important;
}

@media (max-width: 781px) {
	.yp-web-design-packages {
		grid-template-columns: 1fr;
	}
}

/* Hosting/domain-not-included disclaimer, under the grid — direct
   follow-up. Muted via opacity rather than a separate color token, same
   convention as the browser-mockup's own --soft variants above. */
.yp-web-design-packages__disclaimer {
	margin-top: var(--wp--preset--spacing--md);
	font-size: var(--wp--preset--font-size--small);
	opacity: 0.7;
}

.yp-web-design-package {
	position: relative;
	display: flex;
	flex-direction: column;
	background: var(--wp--preset--color--white);
	border: 1.5px solid var(--wp--preset--color--light-gray);
	border-radius: var(--wp--custom--radius--card);
	box-shadow: var(--wp--custom--shadow-elevation--low);
	padding: var(--wp--preset--spacing--md);
}

.yp-web-design-package--featured {
	border-color: var(--wp--preset--color--magenta-deep);
	box-shadow: var(--wp--custom--shadow-elevation--high);
}

.yp-web-design-package__badge {
	position: absolute;
	top: -0.7rem;
	left: 50%;
	transform: translateX(-50%);
	background: var(--wp--preset--color--magenta-deep);
	color: var(--wp--preset--color--white);
	font-size: 0.75rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	padding: 0.3rem 0.85rem;
	border-radius: 999px;
	box-shadow: var(--wp--custom--shadow-elevation--low);
}

.yp-web-design-package__name {
	margin: 0 0 0.35rem;
}

.yp-web-design-package__tagline {
	color: var(--wp--preset--color--charcoal);
	font-size: var(--wp--preset--font-size--small);
	margin: 0 0 1rem;
}

.yp-web-design-package__price {
	margin-bottom: 1rem;
	padding-bottom: 1rem;
	border-bottom: 1px solid var(--wp--preset--color--light-gray);
}

.yp-web-design-package__price-flag {
	display: block;
	font-size: 0.7rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: var(--wp--preset--color--magenta-deep);
	margin-bottom: 0.25rem;
}

.yp-web-design-package__price-amount {
	display: block;
	font-family: var(--wp--preset--font-family--heading);
	font-size: 2rem;
	font-weight: 700;
	color: var(--wp--preset--color--near-black);
	border-bottom: 1.5px dashed var(--wp--preset--color--magenta-deep);
	width: fit-content;
}

.yp-web-design-package__features {
	list-style: none;
	margin: 0 0 1.25rem;
	padding: 0;
	flex-grow: 1;
}

.yp-web-design-package__features li {
	display: flex;
	align-items: flex-start;
	gap: 0.5rem;
	font-size: var(--wp--preset--font-size--small);
	margin-bottom: 0.6rem;
}

.yp-web-design-package__features li svg {
	flex-shrink: 0;
	margin-top: 0.15rem;
	color: var(--wp--preset--color--cyan-deep);
}

.yp-web-design-package__cta {
	display: block;
	text-align: center;
	/* Direct report: "the get a quote buttons are all different sizes
	   because each package contains a different number of items" — each
	   card's own feature list is a different length (admin-editable per
	   tier), so without this the button just sits right after wherever
	   that list happens to end. margin-top:auto (this is the last child
	   of .yp-web-design-package's own column flex layout) claims all
	   leftover vertical space above itself, pinning every card's button
	   to the same bottom edge regardless of how tall its own features
	   list is — independent of, and a firmer guarantee than, the
	   flex-grow already on .yp-web-design-package__features above. */
	margin-top: auto;
}

/* "What's Included" icon grid */
.yp-included-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--wp--preset--spacing--md);
	margin-top: var(--wp--preset--spacing--md);
}

@media (max-width: 781px) {
	.yp-included-grid {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (max-width: 500px) {
	.yp-included-grid {
		grid-template-columns: 1fr;
	}
}

.yp-included-item {
	background: var(--wp--preset--color--white);
	border-radius: var(--wp--custom--radius--card);
	box-shadow: var(--wp--custom--shadow-elevation--low);
	padding: var(--wp--preset--spacing--md);
}

.yp-included-item__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.5rem;
	height: 2.5rem;
	border-radius: 999px;
	margin-bottom: 1rem;
}

.yp-included-item:nth-child(3n+1) .yp-included-item__icon {
	background: var(--wp--preset--color--cyan);
	color: var(--wp--preset--color--near-black);
}

.yp-included-item:nth-child(3n+2) .yp-included-item__icon {
	background: var(--wp--preset--color--magenta-deep);
	color: var(--wp--preset--color--white);
}

.yp-included-item:nth-child(3n) .yp-included-item__icon {
	background: var(--wp--preset--color--yellow);
	color: var(--wp--preset--color--near-black);
}

.yp-included-item h3 {
	margin: 0 0 0.35rem;
	font-size: var(--wp--preset--font-size--medium);
}

.yp-included-item p {
	margin: 0;
	color: var(--wp--preset--color--charcoal);
	font-size: var(--wp--preset--font-size--small);
}

/* Maintenance subscription badge — direct follow-up: "move it towards
   the top on some badge on the pricing table." Sits between the
   packages section's intro paragraph and the grid itself (both a real
   `.yp-web-design-packages` grid); width:fit-content + margin:auto
   centers the pill regardless of the parent's own text-align. A real
   <button> (opens the maintenance modal below), not a link — the
   border/background/font/cursor resets undo default button chrome so
   it still reads as the same pill it was as an <a>. */
/* Wraps the Maintenance and Hosting badges — direct follow-up, adding
   the Hosting add-on alongside the existing Maintenance one. A flex
   column so a second badge stacks under the first with even spacing,
   rather than each badge's own auto-margin centering separately with no
   gap between them. */
.yp-web-design-badge-row {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.75rem;
	margin-top: 1.25rem;
}

.yp-web-design-badge-row .yp-web-design-maintenance-badge {
	margin-top: 0;
}

.yp-web-design-maintenance-badge {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 0.6rem;
	width: fit-content;
	margin: 1.25rem auto 0;
	padding: 0.65rem 1.35rem;
	border: 0;
	background: var(--wp--custom--gradient-brand-deep);
	color: var(--wp--preset--color--white);
	border-radius: 999px;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	text-decoration: none;
	cursor: pointer;
	box-shadow: var(--wp--custom--shadow-elevation--low);
	transition: transform 150ms ease, box-shadow 150ms ease;
}

.yp-web-design-maintenance-badge:hover,
.yp-web-design-maintenance-badge:focus-visible {
	transform: translateY(-1px);
	box-shadow: var(--wp--custom--shadow-elevation--medium);
	color: var(--wp--preset--color--white);
}

.yp-web-design-maintenance-badge svg {
	flex-shrink: 0;
}

@media (max-width: 500px) {
	/* A pill sized to fit-content can't shrink below its own content's
	   natural width — at this width that content (icon + full sentence +
	   icon, all one line) is wider than the viewport itself. Switching to
	   a full-width, less-rounded banner that wraps lets the same content
	   fit without ever overflowing horizontally. */
	.yp-web-design-maintenance-badge {
		width: 100%;
		flex-wrap: wrap;
		border-radius: var(--wp--custom--radius--control);
		text-align: center;
	}
}

.yp-maintenance-modal__cta {
	margin-top: 1.25rem;
}

.yp-maintenance-modal__cta .wp-block-button__link {
	width: 100%;
	text-align: center;
}
