/**
 * Catalog Mode — frontend styles.
 *
 * Layout shell + category sidebar. All colours, radii and focus recipes come
 * from the CaterOS design tokens, using the same var(--token, fallback) idiom
 * as Free's wizard.css. No new tokens are introduced.
 */

/* ── Region container ───────────────────────────────────────────────────────
   container-type on the REGION (a container query cannot style the container
   itself, so the queried grid lives one level down on .cateros-catalog).

   THE BREAKPOINT IS A CONTAINER QUERY, NOT A VIEWPORT QUERY — DELIBERATE.
   The space this layout fits into is the panel's first grid column, whose
   width the THEME controls (Elementor container %, boxed vs full-width), not
   the viewport. Measured on the reference site (full-width template, 80%
   content width) the usable step-body width is 993px at 1920 viewport but
   only 609px at 1440 — while a boxed ~1140px theme container never exceeds
   ~642px at ANY viewport. A viewport breakpoint would therefore be tuned to
   one site and wrong on every other; the @container query keys on the real
   constraint. Threshold arithmetic (revised 2026-08-27): 160px sidebar +
   16px gap + two ~200px cards + 16px card gap = 592 → 580 with the cards
   flexing slightly, which is what puts the sidebar on 1536px and 1440px
   laptops on this site. Browsers without container-query support (pre-2023)
   simply keep the mobile-first pill layout at all widths — functional, never
   broken. Do not "fix" this back to a media query.

   Threshold arithmetic (revised again 2026-08-29, sidebar widened for the
   group icons — owner decision, option B on record): the widest track that
   still gives a 1440 laptop the sidebar. Region at 1440 measures 622px, so
   622 − 16 column gap − (2×200px cards + 16px card gap = 416) = 190px
   sidebar, and the query fires at exactly 190 + 16 + 416 = 622. Entry
   chrome is 63px (12+12 padding, 2 border, 20 icon, 6+8 gaps, 15 tally),
   so names up to ~127px fit one line — every current group except
   'Frühstück & Belegtes' (143px), which wraps to two lines by accepted
   trade. Deriving from that longest name instead (206px track, threshold
   638) would push 1440 (622) down to pills — rejected 2026-08-29.

   Revised 2026-08-29 (same day, measurement report accepted): 174px track,
   192px card minimum, threshold 590. The arithmetic:
   - 192 is the FLOOR for a card, not a preference: the buy row's control
     family (36+40+36 stepper + 8px gap + the site's widest price '60.00$'
     at ~46px) needs exactly the 166px a 192px card provides — at 188 it is
     4px into overflow. Do not go below 192 without shrinking the controls.
   - 174 is the WIDEST track that still yields four 192px columns at 1920
     (region 1006 − 16 − 174 = 816 = 4×192 + 3×16 exactly). Name fit at
     174 comes from the 8px entry padding in sidebar mode (see the
     has-icons rule below): 107px of name budget vs 104px for the longest
     current name.
   - Threshold 590 = 174 + 16 + 2×192 + 16, giving 1440 (region 622) a 32px
     margin where option B had 0. Measured spread: 1920 4-up @192,
     1680 3-up @197, 1600/1536/1440 2-up @272/246/208, 1366/1280 pills. */
.cateros-catalog-region {
	container-type: inline-size;
}

/* Screen-reader-only text (scoped utility; the standard WP clip pattern). */
.cateros-catalog-sr {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* ── Group list: mobile-first = horizontal scrollable pill row ───────────── */
.cateros-catalog__nav {
	margin: 0 0 16px;
}

/* WRAPPING chip strip (U6) below the rail breakpoint: the horizontal
   scroller this used to be is gone — chips wrap onto lines, 8px gaps, and
   catalogChipsRecalc() in catalog-mode.js caps the strip at TWO lines with a
   "+N more" expander chip. The rail container query below still overrides
   this into the vertical list. */
.cateros-catalog__groups {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	/*
	 * position:relative is LOAD-BEARING on phones (kept from the scroller
	 * era as cheap insurance): Chrome for Android let the old 850px pill
	 * row widen the page's layout viewport to ~900px — the whole page
	 * rendered zoomed out at 360/390/414. Wrapped chips cannot overflow
	 * that way, but the positioned box costs nothing and clips nothing.
	 */
	position: relative;
}

.cateros-catalog__groups-item {
	flex: 0 0 auto;
	margin: 0;
}

/* One entry. A native <button>: Tab-reachable, Enter/Space-operable, focus
   handling all UA-native — nothing to re-implement.

   EVERY state below sets background, colour AND border EXPLICITLY, and every
   button rule is scoped under .cateros-wizard. Both are load-bearing, not
   style: hello-elementor's reset.css paints ALL native buttons pink —
   `button { border/color: #c36 }` and `button:hover, button:focus
   { background: #c36; color: #fff }` — and its selectors tie with or beat a
   single class on any property a state here leaves unset. The .cateros-wizard
   scope wins the specificity fight, and the explicit per-state properties
   leave the theme nothing to paint. This is the same defence Free's own
   buttons use. Do not "simplify" either half away. */
.cateros-wizard .cateros-catalog__group {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	min-height: 44px; /* tap-target floor, matching the wizard's controls */
	padding: 8px 14px;
	border: 1px solid var(--cateros-border, #e5e7eb);
	border-radius: var(--cateros-radius-card);
	background: #fff;
	font-family: inherit;
	font-size: 0.9375rem;
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 90%, transparent);
	cursor: pointer;
	white-space: nowrap;
}

.cateros-wizard .cateros-catalog__group:hover {
	border-color: var(--cateros-primary-hover-border);
	background: #fff;
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 90%, transparent);
}

/* Mouse-click focus: keep the button looking like itself (no ring). */
.cateros-wizard .cateros-catalog__group:focus {
	outline: none;
	border-color: var(--cateros-primary);
	background: #fff;
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 90%, transparent);
}

/* Keyboard focus: the wizard input recipe — primary border + 3px ring. */
.cateros-wizard .cateros-catalog__group:focus-visible {
	outline: none;
	border-color: var(--cateros-primary);
	box-shadow: var(--cateros-focus-ring-offset, 0 0 0 2px #fff, 0 0 0 4px var(--cateros-primary)); /* U9: the planner-wide brand ring */
}

/* Active entry: THREE signals, never colour alone — primary border + subtle
   tinted background (colour), heavier weight (shape), and aria-current
   carries it programmatically. Sidebar mode adds an inset start bar.
   Explicit colour repeated in every active state so the theme reset's
   `button:focus/:hover { color: #fff }` can never bleach the label. */
.cateros-wizard .cateros-catalog__group.is-active,
.cateros-wizard .cateros-catalog__group.is-active:hover,
.cateros-wizard .cateros-catalog__group.is-active:focus {
	border-color: var(--cateros-primary);
	background: var(--cateros-primary-subtle);
	color: var(--cateros-text-strong, #111827);
	font-weight: 600;
}

/* Product count — quiet inventory metadata, deliberately NOT the pill badge
   the selection count used: a plain muted number, no background, no border,
   normal weight. It answers "how much is in here", which should murmur, not
   compete with the group name. 68% text-strong keeps it ≥ 4.5:1 on both the
   white entry and the active tint. */
.cateros-wizard .cateros-catalog__group-tally {
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 68%, transparent);
	font-size: 0.8125rem;
	font-weight: 400;
	line-height: 1;
	white-space: nowrap;
}

/* ── Content region ─────────────────────────────────────────────────────── */
.cateros-catalog__content {
	min-width: 0;
}

/* Section header as a small grid: [icon chip] [title / description] [tools].
   Chip and description only exist when the group has them (x-if), and an
   empty grid track has no width, so a group with neither lays out exactly
   as the old flex header did: title left, tools right, same margins. */
.cateros-catalog__content-head {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr) auto;
	grid-template-areas:
		'icon title tools'
		'icon desc tools';
	align-items: center;
	column-gap: 12px;
	margin: 0 0 14px;
}

.cateros-catalog__content-icon {
	grid-area: icon;
	align-self: center; /* centred against the name+description block */
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* 44px — the header's group mark. A 64px version was tried against the
	   list view's larger photos (2026-08-30) and reverted the same day as
	   too big: at 44 the mark stays subordinate to the title. Radius is
	   the 8px token shared by the whole image family (20 sidebar / 44 here
	   / 96–160 list). Phones use 36px (see the mobile block). */
	width: 44px;
	height: 44px;
	overflow: hidden;
	border-radius: var(--cateros-radius-card);
	background: var(--cateros-primary-subtle, color-mix(in srgb, var(--cateros-primary) 12%, #fff));
}

.cateros-catalog__content-title {
	grid-area: title;
	align-self: end;
}

/* With an image but NO description the second grid row is empty, and the
   end-aligned title hugged the top half — 10px above the chip's centre
   (measured). Let a lone title span both rows and centre itself; browsers
   without :has() keep the old, slightly-off rendering — legible, not
   broken. */
.cateros-catalog__content-head:not(:has(.cateros-catalog__content-descwrap)) .cateros-catalog__content-title {
	grid-row: title / desc;
	align-self: center;
}

/* Uploaded image in the chip: fills the fixed box, cropped, never stretched.
   Same .cateros-wizard scope as the sidebar image, same reason. */
.cateros-wizard .cateros-catalog__content-img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.cateros-catalog__content-descwrap {
	grid-area: desc;
	align-self: start;
	min-width: 0;
}

/* Caterer's own words: plain text via x-text, line breaks kept by pre-line
   (the same treatment as the Quick View description), quiet weight. */
.cateros-catalog__content-desc {
	margin: 2px 0 0;
	font-size: 0.875rem;
	line-height: 1.45;
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 68%, transparent);
	white-space: pre-line;
	overflow-wrap: anywhere;
}

.cateros-catalog__content-desc-toggle {
	display: none; /* phones only — see the mobile block */
}

.cateros-catalog__content-tools {
	grid-area: tools;
}

.cateros-catalog__content-title {
	margin: 0;
	font-size: 1.25rem;
	color: var(--cateros-text-strong, #111827);
}

/* Sidebar / pill icon: a fixed 22px slot so every name starts at the same
   x whether or not its group has an icon; centred, sized between the name
   and the tally, and top-aligned so a wrapping name keeps it on line one. */
.cateros-catalog__group-icon {
	flex: 0 0 20px;
	width: 20px;
	height: 20px; /* fixed box: an empty slot can never grow a stray line box */
	margin-inline-end: -2px; /* 6px to the name (the row's gap is 8) */
	/* Centred by the row's align-items — the old flex-start + 3px top nudge
	   (an emoji-era relic for wrapped names) sat the image 3px above the
	   name's centre. A future wrapping name centres the image against the
	   whole block, which is the right reading too. */
}

/* Uploaded image in the slot: a fixed 20px square whatever the source —
   object-fit:cover crops, the box never stretches. Scoped under
   .cateros-wizard: a bare single-class selector loses border-radius to any
   theme `.class img` rule (one class + type outranks one class). */
.cateros-wizard .cateros-catalog__group-img {
	display: block;
	width: 20px;
	height: 20px;
	/* Surface for transparent PNGs — the same 5% ink wash the card media
	   uses. Invisible behind an opaque photo (the image covers the box). */
	background: color-mix(in srgb, var(--cateros-text-strong, #111827) 5%, transparent);
	margin: 0 auto;
	/* The 8px card radius is nearly a circle on a 20px square; the BASE ui
	   token (4px — radius-card is calc(ui × 2)) reads as a rounded square at
	   this size. The 44px chip keeps radius-card: at 44px, 8px is right. */
	border-radius: var(--cateros-ui-radius, 4px);
	object-fit: cover;
}

/* The header's tools box — now home to the grid/list toggle. The fixed
   min-height long predates the toggle, so mounting it reflowed nothing. */
.cateros-catalog__content-tools {
	display: flex;
	align-items: center;
	gap: 8px;
	min-height: 36px;
}

/* ── Grid/list toggle: one button styled as a segmented pill ────────────
   The ACTIVE segment carries a bordered white chip with a hairline shadow
   — a shape/elevation signal on top of the colour change — while the
   track behind stays muted. Hidden on phones (see the mobile block). */
.cateros-wizard .cateros-catalog__view-toggle {
	display: inline-flex;
	align-items: center;
	gap: 2px;
	padding: 3px;
	border: 1px solid var(--cateros-border, #e5e7eb);
	border-radius: var(--cateros-radius-card);
	background: color-mix(in srgb, var(--cateros-text-strong, #111827) 5%, #fff);
	cursor: pointer;
	font-family: inherit;
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 55%, transparent);
}

.cateros-wizard .cateros-catalog__view-toggle:hover,
.cateros-wizard .cateros-catalog__view-toggle:focus {
	border-color: var(--cateros-primary-hover-border);
	background: color-mix(in srgb, var(--cateros-text-strong, #111827) 5%, #fff);
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 55%, transparent);
	outline: none;
}

.cateros-wizard .cateros-catalog__view-toggle:focus-visible {
	outline: none;
	border-color: var(--cateros-primary);
	box-shadow: var(--cateros-focus-ring-offset, 0 0 0 2px #fff, 0 0 0 4px var(--cateros-primary)); /* U9: the planner-wide brand ring */
}

.cateros-catalog__view-seg {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 30px;
	height: 26px;
	border-radius: calc(var(--cateros-radius-card) - 2px);
	border: 1px solid transparent;
}

.cateros-catalog__view-seg .dashicons {
	font-size: 16px;
	width: 16px;
	height: 16px;
}

/* ACTIVE segment: the site's own selected-state language — the brand tint
   with a primary border, exactly like the sidebar's active entry — plus
   the chip's elevation. Signals beyond colour: the bordered, shadowed
   chip SHAPE exists only on the active segment, and aria-pressed carries
   the state programmatically. */
.cateros-catalog__view-seg.is-on {
	background: var(--cateros-primary-subtle);
	border-color: var(--cateros-primary);
	box-shadow: 0 1px 2px color-mix(in srgb, var(--cateros-text-strong, #111827) 12%, transparent);
	/* Brand-coloured glyph so the whole chip reads as one selected thing.
	   primary-DARK, not primary: the glyph is the segment's only label, and
	   raw primary measures ~2.0:1 on the tinted chip — under the 3:1 non-text
	   floor — while primary-dark measures ~3.3:1. Same token the active-hover
	   border below already leans on, so the hue family stays consistent. */
	color: var(--cateros-primary-dark, var(--cateros-primary));
}

/* Hovering the INACTIVE segment: a neutral wash and darker glyph — an
   invitation, never the branded chip, so hovered-inactive cannot be
   mistaken for active. Hovering the ACTIVE segment deepens its border. */
.cateros-catalog__view-seg:not(.is-on):hover {
	background: color-mix(in srgb, var(--cateros-text-strong, #111827) 8%, #fff);
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 90%, transparent);
}

.cateros-catalog__view-seg.is-on:hover {
	border-color: var(--cateros-primary-dark, var(--cateros-primary));
}

/* ── Grid region and its states ─────────────────────────────────────────── */
.cateros-catalog__grid-region {
	min-height: 120px;
}

.cateros-catalog__state {
	margin: 0;
	padding: 28px 16px;
	border: 1px dashed color-mix(in srgb, var(--cateros-text-strong, #111827) 20%, transparent);
	border-radius: var(--cateros-radius-card);
	text-align: center;
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 60%, transparent);
}

.cateros-catalog__state--error p {
	margin: 0 0 12px;
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 80%, transparent);
}

/* The retry is a real button styled like the wizard's secondary buttons.
   Same .cateros-wizard scope + explicit per-state colours as the group
   entries, for the same theme-reset reason. */
.cateros-wizard .cateros-catalog__retry {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	padding: 8px 18px;
	border: 1px solid var(--cateros-border, #e5e7eb);
	border-radius: var(--cateros-radius-card);
	background: #fff;
	font-family: inherit;
	font-size: 0.9375rem;
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 90%, transparent);
	cursor: pointer;
}

.cateros-wizard .cateros-catalog__retry:hover,
.cateros-wizard .cateros-catalog__retry:focus {
	border-color: var(--cateros-primary-hover-border);
	background: #fff;
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 90%, transparent);
	outline: none;
}

.cateros-wizard .cateros-catalog__retry:focus-visible {
	outline: none;
	border-color: var(--cateros-primary);
	box-shadow: var(--cateros-focus-ring-offset, 0 0 0 2px #fff, 0 0 0 4px var(--cateros-primary)); /* U9: the planner-wide brand ring */
}

/* Loading spinner: a token-coloured ring. The text beside it is the real
   signal (and the role=status announcement); the ring just reads as motion.
   Honours reduced-motion by simply not spinning — the text stays. */
.cateros-catalog__spinner {
	display: inline-block;
	width: 16px;
	height: 16px;
	margin-inline-end: 8px;
	vertical-align: -2px;
	border: 2px solid color-mix(in srgb, var(--cateros-primary) 30%, transparent);
	border-top-color: var(--cateros-primary);
	border-radius: 50%;
	animation: cateros-catalog-spin 0.8s linear infinite;
}

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

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

	/* Hover on the card image: no zoom for reduced-motion users — a static
	   dim carries the "this is clickable" signal without movement. */
	.cateros-catalog-card__img,
	.cateros-catalog-card__img-ph {
		transition: none;
	}

	.cateros-catalog-card__media:hover .cateros-catalog-card__img,
	.cateros-catalog-card__media:hover .cateros-catalog-card__img-ph {
		transform: none;
		opacity: 0.85;
	}
}

/* ── Product cards ──────────────────────────────────────────────────────────
   auto-fill at the ~200px target the layout arithmetic is built on: however
   wide the content region is, cards flow to fit — 2-up around the threshold,
   3-up on wide screens — with no per-width rules to maintain. */
.cateros-catalog__cards {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(192px, 1fr));
	gap: 16px;
	align-items: start;
}

.cateros-catalog-card {
	margin: 0;
	display: flex;
	flex-direction: column;
	border: 1px solid var(--cateros-border, #e5e7eb);
	border-radius: var(--cateros-radius-card);
	background: #fff;
	overflow: hidden;
}

/* Fixed-ratio media box: with or without an image, every card's top is the
   same shape, so a missing photo cannot break a row. position:relative
   anchors the minimum badge; on a missing image the badge overlays the
   placeholder box the same way. */
/* The image is a Quick View target (pointer-only — see the template for
   why it is not a tab stop). overflow:hidden clips the hover zoom; the
   zoom itself is the clickability signal: quiet at rest, unmistakable under
   the pointer, and the same treatment for the no-image placeholder so the
   surface behaves identically with or without a photo. tabindex="-1" lets
   focus RETURN here after a Quick View the image opened; the inset ring
   shows that focus only when it is keyboard-relevant (:focus-visible). */
.cateros-catalog-card__media {
	position: relative;
	/*
	 * 1 / 1, and truthfully so. This box declared 4 / 3 from the grid task
	 * on, but the site's WooCommerce thumbnails are 300×300 and, with the
	 * box unclipped, the square image stretched it to 1 / 1 on every card
	 * — the layout the owner has seen and approved in every screenshot
	 * since. The overflow:hidden the hover zoom needs would have snapped
	 * the box to the declared 4 / 3 and shortened every card by ~61px,
	 * cropping every photo — a design change, not a refinement, so the
	 * declaration now matches what renders. To move to a landscape crop
	 * (the reference's), change this one value to 4 / 3: every card gets
	 * ~61px shorter and photos crop top and bottom.
	 */
	aspect-ratio: 1 / 1;
	display: flex;
	align-items: center;
	justify-content: center;
	overflow: hidden;
	background: color-mix(in srgb, var(--cateros-text-strong, #111827) 5%, transparent);
	cursor: pointer;
}

.cateros-catalog-card__media:focus {
	outline: none;
}

.cateros-catalog-card__media:focus-visible {
	outline: none;
	box-shadow: inset 0 0 0 2px var(--cateros-primary); /* U9: inset brand ring (clipped context exception) */
}

/* Hover-only devices: on touch there is no hover, and a :hover rule would
   stick the zoom on after a tap — so the zoom exists only where a pointer
   can actually hover. The image's clickability on touch is carried by
   convention (product images open detail everywhere) plus the title. */
@media (hover: hover) {
	.cateros-catalog-card__media:hover .cateros-catalog-card__img,
	.cateros-catalog-card__media:hover .cateros-catalog-card__img-ph {
		transform: scale(1.04);
	}
}

/* Minimum badge — the shop pages' .cateros-min-badge treatment, spoken in
   tokens: same top-left placement, same small light chip. The near-opaque
   light background with a border and its own dark text is what keeps it
   legible over ANY photograph — the photo never shows through enough to
   matter, so dark food, light food and busy patterns all read the same. */
.cateros-catalog-card__min-badge {
	position: absolute;
	top: 8px;
	inset-inline-start: 8px;
	z-index: 2;
	display: inline-block;
	padding: 3px 8px;
	font-size: 11px;
	font-weight: 600;
	line-height: 1.3;
	color: var(--cateros-text, #1f2937);
	background: color-mix(in srgb, #fff 95%, var(--cateros-text-strong, #111827));
	border: 1px solid var(--cateros-border, #e5e7eb);
	border-radius: 4px;
	box-shadow: 0 1px 2px color-mix(in srgb, var(--cateros-text-strong, #111827) 6%, transparent);
	pointer-events: none;
	white-space: nowrap;
}

.cateros-catalog-card__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform 200ms ease;
}

.cateros-catalog-card__img-ph {
	font-size: 1.5rem;
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 30%, transparent);
	transition: transform 200ms ease;
}

.cateros-catalog-card__body {
	padding: 10px 12px 0;
	flex: 1 1 auto;
}

/* Dietary/allergen icon line (between name and the price row). Since U12 the
   element only exists on products WITH diet tags (template x-if), so this
   height applies exactly where icons will render and no card reserves a
   blank line any more. */
.cateros-catalog-card__diet {
	height: 20px;
}

/* ONE-LINE title (reversal of the earlier wrap decision, by task): the row's
   cards keep identical content heights. Truncation is CSS-only — the full
   name stays in the DOM for AT, on :title for hover, and in the Quick View
   for touch. The button IS the Quick View trigger: text-styled, underline on
   hover/focus so it signals clickable without reading as a button. Explicit
   background/colour on every state = the theme-reset defence (hello-elementor
   paints buttons #c36 on hover/focus). */
.cateros-catalog-card__name {
	margin: 0 0 4px;
	font-size: 0.9375rem;
	font-weight: 600;
	color: var(--cateros-text-strong, #111827);
	white-space: nowrap;
	overflow: hidden;
}

.cateros-wizard .cateros-catalog-card__name-btn {
	display: block;
	max-width: 100%;
	padding: 0;
	border: 0;
	background: transparent;
	font-family: inherit;
	font-size: inherit;
	font-weight: inherit;
	line-height: inherit;
	color: var(--cateros-text-strong, #111827);
	text-align: left;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	cursor: pointer;
}

.cateros-wizard .cateros-catalog-card__name-btn:hover,
.cateros-wizard .cateros-catalog-card__name-btn:focus {
	background: transparent;
	color: var(--cateros-text-strong, #111827);
	text-decoration: underline;
	text-underline-offset: 3px;
	outline: none;
}

.cateros-wizard .cateros-catalog-card__name-btn:focus-visible {
	outline: none;
	text-decoration: underline;
	text-underline-offset: 3px;
	box-shadow: var(--cateros-focus-ring-offset, 0 0 0 2px #fff, 0 0 0 4px var(--cateros-primary)); /* U9: the planner-wide brand ring */
	border-radius: 2px;
}

.cateros-wizard .cateros-catalog-card__name-btn:active {
	background: transparent;
	color: var(--cateros-text-strong, #111827);
}

.cateros-catalog-card__price {
	margin: 0;
	flex: 1 1 auto;
	min-width: 0;
	font-size: 0.875rem;
	font-weight: 600;
	color: var(--cateros-text-strong, #111827);
}

/* WooCommerce sale markup inside price_html: keep its del/ins readable. */
.cateros-catalog-card__price del {
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 45%, transparent);
	margin-inline-end: 6px;
}

.cateros-catalog-card__price ins {
	text-decoration: none;
	font-weight: 600;
}

/* Card footer: variation picker, then THE BUY ROW (price left, control
   right, one line, both states 36px tall so add→stepper cannot shift the
   card), then the variable choose-hint. Buttons/inputs keep the
   .cateros-wizard scope + explicit per-state colours — the theme-reset
   defence. margin-top:auto pins the footer so rows of cards stay aligned.
   36px control height matches the reference's compact controls (read at
   ~34–38px against its type scale) and stays above WCAG 2.5.8's 24px
   target minimum with clear gaps between adjacent targets; the wizard's
   own 44px floor applies to its primary nav controls, not these in-card
   steppers. */
.cateros-catalog-card__actions {
	margin-top: auto;
	min-height: 54px;
	padding: 6px 12px 12px;
}

.cateros-catalog-card__buy {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 8px;
	min-height: 36px;
	flex-wrap: nowrap;
}

/* Dashicons inside the controls: sized to the buttons, centred. */
.cateros-catalog-card__buy .dashicons {
	font-size: 16px;
	width: 16px;
	height: 16px;
	line-height: 1;
}

.cateros-catalog-card__vars {
	margin: 0 0 8px;
	padding: 0;
	border: 0;
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.cateros-catalog-card__var {
	display: flex;
	align-items: center;
	gap: 8px;
	font-size: 0.875rem;
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 85%, transparent);
	cursor: pointer;
}

.cateros-wizard .cateros-catalog-card__var-radio {
	accent-color: var(--cateros-primary);
	width: 16px;
	height: 16px;
	margin: 0;
	flex: 0 0 auto;
	cursor: pointer;
}

.cateros-catalog-card__choose-hint {
	margin: 0 0 6px;
	font-size: 0.8125rem;
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 68%, transparent);
}

/* THE CONTROL FAMILY — one 36px height throughout: the stepper's − and +
   are 36×36 squares (a glyph button reads best square, and it is what the
   reference does), the quantity input is 40×36 (a numeral field needs the
   extra width for four digits; matching the add button's width keeps the
   row's control cluster to exactly two widths), and the add button is 40×36
   — the card's single action, a touch wider than the squares so it anchors
   the row. Icon-only add: */
.cateros-wizard .cateros-catalog-card__add {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 40px;
	min-height: 36px;
	padding: 0;
	border: 1px solid var(--cateros-primary);
	border-radius: var(--cateros-radius-card);
	background: var(--cateros-primary);
	font-family: inherit;
	color: var(--cateros-btn-text, #fff);
	cursor: pointer;
}

.cateros-wizard .cateros-catalog-card__add:hover,
.cateros-wizard .cateros-catalog-card__add:focus {
	background: var(--cateros-primary-dark, var(--cateros-primary));
	border-color: var(--cateros-primary-dark, var(--cateros-primary));
	color: var(--cateros-btn-text, #fff);
	outline: none;
}

.cateros-wizard .cateros-catalog-card__add:focus-visible {
	outline: none;
	box-shadow: var(--cateros-focus-ring-offset, 0 0 0 2px #fff, 0 0 0 4px var(--cateros-primary)); /* U9: the planner-wide brand ring */
}

.cateros-wizard .cateros-catalog-card__add:disabled {
	background: color-mix(in srgb, var(--cateros-text-strong, #111827) 12%, transparent);
	border-color: transparent;
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 45%, transparent);
	cursor: not-allowed;
}

.cateros-catalog-card__qty {
	display: flex;
	align-items: center;
	gap: 4px;
	flex: 0 0 auto;
}

.cateros-wizard .cateros-catalog-card__qty-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	min-height: 36px;
	padding: 0;
	border: 1px solid var(--cateros-border, #e5e7eb);
	border-radius: var(--cateros-radius-card);
	background: #fff;
	font-family: inherit;
	line-height: 1;
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 90%, transparent);
	cursor: pointer;
}

.cateros-wizard .cateros-catalog-card__qty-btn:hover,
.cateros-wizard .cateros-catalog-card__qty-btn:focus {
	border-color: var(--cateros-primary-hover-border);
	background: #fff;
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 90%, transparent);
	outline: none;
}

.cateros-wizard .cateros-catalog-card__qty-btn:focus-visible {
	outline: none;
	border-color: var(--cateros-primary);
	box-shadow: var(--cateros-focus-ring-offset, 0 0 0 2px #fff, 0 0 0 4px var(--cateros-primary)); /* U9: the planner-wide brand ring */
}

.cateros-wizard .cateros-catalog-card__qty-input {
	width: 40px;
	min-height: 36px;
	padding: 2px;
	border: 1px solid var(--cateros-border, #e5e7eb);
	border-radius: var(--cateros-radius-card);
	background: #fff;
	font-family: inherit;
	font-size: 0.875rem;
	text-align: center;
	color: var(--cateros-text-strong, #111827);
	-moz-appearance: textfield;
	appearance: textfield;
}

.cateros-wizard .cateros-catalog-card__qty-input::-webkit-outer-spin-button,
.cateros-wizard .cateros-catalog-card__qty-input::-webkit-inner-spin-button {
	-webkit-appearance: none;
	margin: 0;
}

.cateros-wizard .cateros-catalog-card__qty-input:focus,
.cateros-wizard .cateros-catalog-card__qty-input:focus-visible {
	outline: none;
	border-color: var(--cateros-primary);
	box-shadow: var(--cateros-focus-ring-offset, 0 0 0 2px #fff, 0 0 0 4px var(--cateros-primary)); /* U9: the planner-wide brand ring */
}

/* ── Quick View modal ─────────────────────────────────────────────────────
   Pro's own dialog (see catalog-mode.js for why Free's shop Quick View is
   not reused). Fixed overlay above everything on the page (the theme's
   sticky header and Free's sticky summary included); the panel scrolls
   itself when content outgrows the viewport. Controls inside reuse the
   card's own classes — same look, same theme-reset defence. */
body.cateros-catalog-qv-lock {
	overflow: hidden;
}

.cateros-catalog-qv {
	position: fixed;
	inset: 0;
	z-index: 100000;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 16px;
}

.cateros-catalog-qv__backdrop {
	position: absolute;
	inset: 0;
	background: color-mix(in srgb, var(--cateros-text-strong, #111827) 55%, transparent);
	cursor: pointer;
}

.cateros-catalog-qv__panel {
	position: relative;
	width: min(720px, 100%);
	max-height: min(90vh, 640px);
	overflow: auto;
	background: #fff;
	border-radius: var(--cateros-radius-card);
	box-shadow: 0 20px 50px rgba(0, 0, 0, 0.25);
	padding: 20px;
	outline: none;
}

/* The panel takes programmatic focus on open (tabindex="-1") but is not an
   interactive control in the tab order, so the theme's/browser's
   focus-visible outline — which rendered as a hard dark border around the
   whole dialog — is suppressed here explicitly. Standard dialog pattern;
   every interactive control inside keeps its own focus ring. */
.cateros-catalog-qv__panel:focus,
.cateros-catalog-qv__panel:focus-visible {
	outline: none;
}

.cateros-wizard .cateros-catalog-qv__close {
	position: absolute;
	top: 8px;
	inset-inline-end: 8px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	padding: 0;
	border: 0;
	border-radius: var(--cateros-radius-card);
	background: transparent;
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 70%, transparent);
	cursor: pointer;
}

.cateros-wizard .cateros-catalog-qv__close:hover,
.cateros-wizard .cateros-catalog-qv__close:focus {
	background: color-mix(in srgb, var(--cateros-text-strong, #111827) 8%, transparent);
	color: var(--cateros-text-strong, #111827);
	outline: none;
}

.cateros-wizard .cateros-catalog-qv__close:focus-visible {
	outline: none;
	box-shadow: var(--cateros-focus-ring-offset, 0 0 0 2px #fff, 0 0 0 4px var(--cateros-primary)); /* U9: the planner-wide brand ring */
}

.cateros-catalog-qv__grid {
	display: flex;
	gap: 20px;
	align-items: flex-start;
	flex-wrap: wrap;
}

.cateros-catalog-qv__media {
	position: relative;
	flex: 1 1 240px;
	max-width: 320px;
	aspect-ratio: 4 / 3;
	border-radius: var(--cateros-radius-card);
	overflow: hidden;
	background: color-mix(in srgb, var(--cateros-text-strong, #111827) 6%, transparent);
}

.cateros-catalog-qv__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.cateros-catalog-qv__info {
	flex: 1 1 300px;
	min-width: 0;
	display: flex;
	flex-direction: column;
}

.cateros-catalog-qv__title {
	margin: 0 32px 0 0; /* keeps clear of the close button */
	font-size: 1.125rem;
	font-weight: 600;
	color: var(--cateros-text-strong, #111827);
	overflow-wrap: break-word; /* the modal is where the FULL name shows */
}

/* Reserved dietary icon row — the reference's position, under the title.
   Held height, same contract as the card's __diet line: icons drop in
   later with zero reflow. */
.cateros-catalog-qv__diet {
	height: 24px;
	margin-top: 4px;
}

.cateros-catalog-qv__desc {
	margin: 4px 0 0;
	font-size: 0.875rem;
	line-height: 1.5;
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 80%, transparent);
	white-space: pre-line;
}

/* Reserved allergen block — the reference's position, under the
   description. Renders nothing (zero height) until the allergen task
   lands; unlike the icon row it reserves no space, because a text list
   has no fixed height to hold. */
.cateros-catalog-qv__allergens {
	margin: 0;
}

.cateros-catalog-qv__actions {
	margin-top: 16px;
}

/* Card description: exists for LIST view; grid hides it so grid renders
   byte-for-byte as it did before the toggle. */
.cateros-catalog-card__desc {
	display: none;
}

/* ── LIST VIEW ────────────────────────────────────────────────────────────
   The same cards, same DOM, same behaviours — re-laid as full-width rows
   by CSS alone: photo left (96px, the usual rounded crop), name +
   description centre, the existing buy block right in a fixed 200px
   column so add→stepper cannot shift the row. Desktop/pill widths only:
   the phone grid is already one column (the toggle is hidden there). */
@media (min-width: 768px) {
	.cateros-catalog__cards.is-list {
		grid-template-columns: 1fr;
		gap: 10px;
	}

	.cateros-catalog__cards.is-list .cateros-catalog-card {
		display: grid;
		/* Photo column: 24% of the row, floored at the old 96px and capped at
		   160px (the reference's scale) — so the photo grows with the room the
		   row actually has. The buy column funds part of it: its content never
		   exceeds 166px measured (stepper 36+40+36 + gap + the widest price),
		   so 176px keeps 10px slack and returns 24px of dead space to the
		   photo. At 1536 (509px rows) the text column keeps exactly the width
		   it had before the enlargement (163px). */
		grid-template-columns: clamp(96px, 24%, 160px) minmax(0, 1fr) 176px;
		grid-template-areas: 'media body actions';
		align-items: center;
		column-gap: 14px;
		padding: 10px;
	}

	.cateros-catalog__cards.is-list .cateros-catalog-card__media {
		grid-area: media;
		aspect-ratio: 1 / 1;
		width: 100%; /* fills the clamp()ed photo column */
		border-radius: var(--cateros-radius-card);
	}

	.cateros-catalog__cards.is-list .cateros-catalog-card__media .cateros-catalog-card__min-badge {
		top: 4px;
		inset-inline-start: 4px;
		padding: 2px 6px;
	}

	.cateros-catalog__cards.is-list .cateros-catalog-card__body {
		grid-area: body;
		padding: 0;
		display: flex;
		flex-direction: column;
		justify-content: center;
	}

	/* Rows do not need cross-row height alignment, so the name may use the
	   room list view exists to provide: full, wrapping, untruncated. */
	.cateros-catalog__cards.is-list .cateros-catalog-card__name {
		white-space: normal;
	}

	.cateros-wizard .cateros-catalog__cards.is-list .cateros-catalog-card__name-btn {
		white-space: normal;
		overflow: visible;
		text-overflow: clip;
	}

	.cateros-catalog__cards.is-list .cateros-catalog-card__diet {
		display: none; /* the reserved icon line is a grid-card affordance */
	}

	.cateros-catalog__cards.is-list .cateros-catalog-card__desc {
		display: -webkit-box;
		-webkit-line-clamp: 2;
		-webkit-box-orient: vertical;
		overflow: hidden;
		margin: 2px 0 0;
		font-size: 0.8125rem;
		line-height: 1.45;
		color: color-mix(in srgb, var(--cateros-text-strong, #111827) 68%, transparent);
	}

	.cateros-catalog__cards.is-list .cateros-catalog-card__actions {
		grid-area: actions;
		margin: 0;
		padding: 0;
		min-height: 0;
		justify-self: end;
		width: 176px;
	}
}

/* ── Phones (pill mode below the container-query threshold) ───────────────
   Measured reality on this theme: the wizard's panel chrome leaves the
   catalog region 224px wide at a 360px viewport (254 @390, 278 @414), so
   the grid is ONE column there by arithmetic, not by choice — two legible
   cards need ~330px. Rules here are keyed on viewport width for layout
   and on (pointer: coarse) for touch sizing, so a touch tablet at desktop
   widths still gets the larger targets. */
@media (max-width: 767.98px) {
	/* Pill row STAYS while the list scrolls (Antipasti alone is 37 cards
	   in one column — ~12,000px). Sticky inside .cateros-catalog, so it
	   releases once the grid ends. Solid background so cards slide under
	   it cleanly; the edge fades below are the scroll affordance. */
	.cateros-catalog__nav {
		position: sticky;
		top: 0;
		z-index: 5;
		margin: 0 0 12px;
		padding-top: 4px;
		background: #fff;
	}

	/* The edge fades that signposted the old horizontal scroller are GONE
	   (U6): wrapped chips have no hidden sides to hint at. The
	   is-scroll-start/end class plumbing in the template stays inert. */

	.cateros-catalog__cards {
		gap: 12px;
	}

	/* No view toggle on a phone: the one-column grid already reads as a
	   list, and the header space is scarcer than the difference between
	   the two layouts. The is-list styles above are also gated to ≥768px,
	   so a pre-set list state renders as the normal grid here. */
	.cateros-wizard .cateros-catalog__view-toggle {
		display: none;
	}

	/* Section description on a phone: two lines, then "More". Vertical
	   space is what a phone has least of (sticky pills above, Free's bar
	   below), and portion guidance is a glance, not a read; the full text
	   is one tap away and the toggle appears only when text is hidden. */
	.cateros-catalog__content-desc {
		display: -webkit-box;
		-webkit-line-clamp: 2;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	.cateros-catalog__content-desc.is-expanded {
		display: block;
		-webkit-line-clamp: unset;
		overflow: visible;
	}

	.cateros-wizard .cateros-catalog__content-desc-toggle {
		display: inline-block;
		margin: 2px 0 0;
		padding: 6px 0;
		border: 0;
		background: transparent;
		font-family: inherit;
		font-size: 0.8125rem;
		font-weight: 600;
		color: var(--cateros-primary-dark, var(--cateros-primary));
		text-decoration: underline;
		text-underline-offset: 2px;
		cursor: pointer;
	}

	.cateros-wizard .cateros-catalog__content-desc-toggle:hover,
	.cateros-wizard .cateros-catalog__content-desc-toggle:focus {
		background: transparent;
		color: var(--cateros-primary-dark, var(--cateros-primary));
		outline: none;
	}

	.cateros-wizard .cateros-catalog__content-desc-toggle:focus-visible {
		outline: none;
		box-shadow: var(--cateros-focus-ring-offset, 0 0 0 2px #fff, 0 0 0 4px var(--cateros-primary)); /* U9: the planner-wide brand ring */
		border-radius: 2px;
	}

	.cateros-catalog__content-icon {
		width: 36px;
		height: 36px;
	}

	/* Titles: single-column cards have no row-mates to align with, so the
	   name may take TWO lines here (clamped, ellipsis on the second) —
	   at ~200px a one-line title kept only ~24 of a 46-character name. */
	.cateros-catalog-card__name {
		white-space: normal;
	}

	.cateros-wizard .cateros-catalog-card__name-btn {
		white-space: normal;
		display: -webkit-box;
		-webkit-line-clamp: 2;
		-webkit-box-orient: vertical;
		overflow: hidden;
		text-overflow: ellipsis;
	}

	/* Quick View becomes a BOTTOM SHEET: full width, anchored to the
	   bottom edge, capped at 92% of the (dynamic) viewport and scrolling
	   inside; image on top, text and the buy row below. The sheet sits
	   above Free's fixed order bar (z-index 100000 vs 999). */
	.cateros-catalog-qv {
		align-items: flex-end;
		padding: 0;
	}

	.cateros-catalog-qv__panel {
		width: 100%;
		max-height: 92vh;
		max-height: 92dvh;
		border-radius: 16px 16px 0 0;
		padding: 16px 16px calc(16px + env(safe-area-inset-bottom, 0px));
	}

	.cateros-catalog-qv__media {
		flex-basis: 100%;
		max-width: none;
	}

	.cateros-catalog-qv__title {
		margin-inline-end: 40px;
	}
}

/* ── Touch sizing ─────────────────────────────────────────────────────────
   Coarse pointers get the larger control family: 40px squares, 44px-wide
   input and add button, one 40px height. Fits the narrowest measured buy
   row (198px @360: 40+4+44+4+40 = 132, + 8 gap + "60.00$" 46 = 186). The
   quantity input goes to 16px type: below that iOS zooms the page on
   focus. Card height on touch is +4px (the 40px row) — the two states are
   still identical, so the add→stepper swap still cannot shift a card. */
@media (pointer: coarse) {
	.cateros-catalog-card__actions {
		min-height: 58px;
	}

	.cateros-catalog-card__buy {
		min-height: 40px;
	}

	.cateros-wizard .cateros-catalog-card__add {
		width: 44px;
		min-height: 40px;
	}

	.cateros-wizard .cateros-catalog-card__qty-btn {
		width: 40px;
		min-height: 40px;
	}

	.cateros-wizard .cateros-catalog-card__qty-input {
		width: 44px;
		min-height: 40px;
		font-size: 16px;
	}

	/* The title is a tap target too: padding lifts it from a 23px text
	   line to a ~39px strip the full width of the card. */
	.cateros-wizard .cateros-catalog-card__name-btn {
		padding: 8px 0;
	}

	.cateros-wizard .cateros-catalog-qv__close {
		width: 40px;
		height: 40px;
	}

	/* Variation rows: the whole label is the target — lifted to a 40px
	   strip with a 20px radio so a thumb lands on one option, not two. */
	.cateros-catalog-card__var {
		min-height: 40px;
		padding: 2px 0;
	}

	.cateros-wizard .cateros-catalog-card__var-radio {
		width: 20px;
		height: 20px;
	}
}

/* ── Sidebar-beside layout, when the PANEL is wide enough ───────────────── */
@container (min-width: 590px) {
	.cateros-catalog {
		display: grid;
		grid-template-columns: 174px minmax(0, 1fr);
		gap: 16px;
		align-items: start;
	}

	/* Sticky, mirroring Free's Order Summary card exactly — now literally
	   (U3): the shared --cateros-sticky-top token (18px, 50px under the
	   admin bar) and the same viewport cap the card uses (top offset + the
	   fixed bar's height + 16px breathing room), scrolling internally when
	   the group list outgrows the viewport. */
	.cateros-catalog__nav {
		margin: 0;
		position: sticky;
		top: var(--cateros-sticky-top, 18px);
		max-height: calc(100vh - var(--cateros-sticky-top, 18px) - var(--cateros-bar-h, 60px) - 16px);
		overflow-y: auto;
		scrollbar-width: thin;
		scrollbar-color: color-mix(in srgb, var(--cateros-text-strong, #111827) 30%, transparent) transparent;
	}

	/* ONE CARD: the list carries the border and radius; entries sit inside
	   with no box of their own, separated by hairlines. overflow:hidden
	   clips entry backgrounds to the rounded corners — which is why the
	   focus ring below is INSET (an outer ring would be clipped). */
	.cateros-catalog__groups {
		display: flex;
		flex-direction: column;
		gap: 0;
		overflow: hidden;
		padding: 0;
		border: 1px solid var(--cateros-border, #e5e7eb);
		border-radius: var(--cateros-radius-card);
		background: #fff;
	}

	/* Separators: a top hairline on every entry but the first, so the first
	   meets the card's top edge and the last meets its bottom edge with a
	   single line each — nothing doubled. */
	.cateros-catalog__groups-item + .cateros-catalog__groups-item {
		border-top: 1px solid var(--cateros-border, #e5e7eb);
	}

	.cateros-wizard .cateros-catalog__group {
		width: 100%;
		justify-content: space-between;
		border: 0;
		border-radius: 0;
		background: #fff;
		white-space: normal;
		text-align: start;
	}

	/* Hover: a faint wash (no border to colour any more). */
	.cateros-wizard .cateros-catalog__group:hover {
		border-color: transparent;
		background: color-mix(in srgb, var(--cateros-text-strong, #111827) 4%, #fff);
	}

	.cateros-wizard .cateros-catalog__group:focus {
		border-color: transparent;
		background: #fff;
	}

	/* Keyboard focus: an inset ring — outer rings would be clipped by the
	   card's rounded overflow. */
	.cateros-wizard .cateros-catalog__group:focus-visible {
		border-color: transparent;
		box-shadow: inset 0 0 0 2px var(--cateros-primary);
	}

	.cateros-catalog__group-name {
		flex: 1 1 auto;
	}

	/* With images in the list, entry padding drops to 8px so the name gets
	   the width back: chrome beside the name is then 8+8 padding + 2 border
	   + 20 slot + 6 gap + 8 gap + 15 tally = 67px, leaving 174 − 67 = 107px
	   for the name — 3px over 'Soups & Salads' (104px bold), the longest
	   current name. (The first cut kept 12px padding on a 63px chrome figure
	   that really summed to 75px, and the name wrapped; measured, corrected.)
	   Without images nothing here applies and entries keep their 14px. */
	.cateros-catalog__nav.has-icons .cateros-catalog__group {
		padding-inline: 8px;
	}

	/* Active inside the card: three signals beyond colour — the 3px start
	   bar, the 600 weight, and aria-current for AT — on the tinted wash. */
	.cateros-wizard .cateros-catalog__group.is-active,
	.cateros-wizard .cateros-catalog__group.is-active:hover,
	.cateros-wizard .cateros-catalog__group.is-active:focus {
		border-color: transparent;
		background: var(--cateros-primary-subtle);
		box-shadow: inset 3px 0 0 0 var(--cateros-primary);
	}

	.cateros-wizard .cateros-catalog__group.is-active:focus-visible {
		box-shadow: inset 3px 0 0 0 var(--cateros-primary), inset 0 0 0 2px var(--cateros-primary);
	}
}

/* ── Load more (U2) — button styling only ──────────────────────────────────
   Secondary (outline) control mirroring Free's .cateros-dish-show-more
   treatment (same !important shields: themes often repaint bare buttons), so
   the two layouts' Load more read as the same control. The count beside it is
   deliberately muted: the button is the action, the count is context. */
.cateros-catalog__more {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 12px;
	margin-top: 16px;
}

.cateros-wizard .cateros-catalog__load-more {
	background: #fff !important;
	background-color: #fff !important;
	border: 2px solid var(--cateros-primary, #2271B1) !important;
	color: var(--cateros-primary, #2271B1) !important;
	border-radius: var(--cateros-ui-radius, 8px) !important;
	padding: 10px 22px;
	font-weight: 800;
	cursor: pointer;
}

.cateros-wizard .cateros-catalog__load-more:hover,
.cateros-wizard .cateros-catalog__load-more:focus {
	color: var(--cateros-primary-dark, #135E96) !important;
	border-color: var(--cateros-primary-dark, #135E96) !important;
}

.cateros-catalog__more-count {
	font-size: 13px;
	font-weight: 600;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 65%, transparent);
	white-space: nowrap;
}

/* ── Menu search (U3) ──────────────────────────────────────────────────────
   One control, two placements: the desktop copy tops the product column, the
   mobile copy sits above the category chips; CSS displays exactly one. */
.cateros-catalog__search {
	position: relative;
	margin: 0 0 14px;
}

.cateros-catalog__search--mobile {
	display: none;
}

.cateros-wizard .cateros-catalog__search-input {
	width: 100%;
	box-sizing: border-box;
	padding: 10px 40px 10px 14px;
	border: 1px solid var(--cateros-input-border, color-mix(in srgb, var(--cateros-text-strong, #111827) 14%, transparent)); /* U10: the shared input border */
	border-radius: var(--cateros-ui-radius, 8px);
	background: #fff;
	font: inherit;
	color: var(--cateros-text, #1f2937);
}

.cateros-wizard .cateros-catalog__search-input::placeholder {
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 45%, transparent);
	font-weight: 500;
}

/* Suppress the native WebKit cancel control — the × below is the one clear. */
.cateros-catalog__search-input::-webkit-search-decoration,
.cateros-catalog__search-input::-webkit-search-cancel-button {
	-webkit-appearance: none;
	appearance: none;
}

.cateros-wizard .cateros-catalog__search-clear {
	position: absolute;
	right: 6px;
	top: 50%;
	transform: translateY(-50%);
	width: 28px;
	height: 28px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border: 0;
	border-radius: 999px;
	background: transparent;
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 55%, transparent);
	font-size: 18px;
	line-height: 1;
	cursor: pointer;
	padding: 0;
}

.cateros-wizard .cateros-catalog__search-clear:hover {
	color: var(--cateros-text-strong, #111827);
}

/* Dimmed rail while results span every category. Still clickable — a pick
   exits the search. */
.cateros-catalog__nav.is-search-dimmed {
	opacity: 0.45;
}

.cateros-catalog__search-note {
	margin: 0 0 12px;
	font-size: 13px;
	line-height: 1.5;
}

.cateros-catalog__search-note-text {
	font-weight: 700;
	color: var(--cateros-text-strong, var(--cateros-text, #1f2937));
}

.cateros-catalog__search-note-count {
	margin-left: 8px;
	font-weight: 600;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 65%, transparent);
}

/* The empty state's "Clear search" — a link, not a button face. */
.cateros-wizard .cateros-catalog__search-clear-link {
	border: 0;
	background: transparent;
	padding: 0;
	margin-left: 6px;
	color: var(--cateros-primary, #2271B1);
	text-decoration: underline;
	font: inherit;
	cursor: pointer;
}

.cateros-wizard .cateros-catalog__search-clear-link:hover {
	color: var(--cateros-primary-dark, #135E96);
}

@media (max-width: 767.98px) {
	.cateros-catalog__search--desktop {
		display: none;
	}

	.cateros-catalog__search--mobile {
		display: block;
		margin: 0 0 10px;
	}
}

/* ── Chips wrap + expander (U6) ───────────────────────────────────────────── */

/* Touch target: every chip at least 44px tall in the wrapped strip (the rail
   entries are taller list rows already). */
.cateros-wizard .cateros-catalog__group {
	min-height: 44px;
}

/* The "+N more" / "Show less" expander chip: a chip like its neighbours, in
   the brand colour so it reads as a control rather than a category. Hidden by
   default; catalogChipsRecalc() shows it only when a third line would exist. */
.cateros-wizard .cateros-catalog__group--more {
	color: var(--cateros-primary, #2271B1);
	font-weight: 700;
}

/* Search icon (U6): the same magnifier Free's sequential search carries, as
   a data-URI SVG background — decorative by construction (backgrounds never
   reach the accessibility tree), no icon font. 12px inset + 16px icon + 12px
   gap before the text, mirroring wizard.css. */
.cateros-wizard .cateros-catalog__search-input {
	padding-left: calc(12px + 16px + 12px);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' stroke='%2394a3b8' stroke-width='2' viewBox='0 0 24 24'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M21 21l-4.3-4.3'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: 12px center;
	background-size: 16px 16px;
}
