/* Branding: --cateros-* and derived tokens (--cateros-primary-subtle, etc.) from wp_head. */

.cateros-wizard {
	--cateros-ui-radius: var(--cateros-radius, 8px);
	/* Derived from --cateros-primary the same way the storefront's
	   --cateros-primary-subtle / -ring / -hover-border are (color-mix against the
	   live brand colour), so a brand change carries through with no extra setting.
	   Defined here rather than in print_frontend_css_variables() because these are
	   wizard-layout concerns, not storefront-wide branding. */
	--cateros-primary-glow: color-mix(in srgb, var(--cateros-primary, #2271B1) 25%, transparent);
	/* Card scale built ON --cateros-radius, not a disconnected set: the outer card
	   is 3x the base UI radius, the inner card 2x. Base 8px -> 24px / 16px. */
	--cateros-radius-outer: calc(var(--cateros-ui-radius) * 3);
	--cateros-radius-card: calc(var(--cateros-ui-radius) * 2);
	/* Soft surface tint for the sidebar's list / empty-state region. The reference
	   uses a warm peach because its brand is orange; ours is admin-configurable,
	   so the tint is DERIVED from the live brand instead of hardcoded. 4% against
	   white: present enough to separate the region from the white card, faint
	   enough not to read as a coloured panel at any hue. */
	--cateros-primary-tint: color-mix(in srgb, var(--cateros-primary, #2271B1) 4%, white);
	/* The fixed bottom bar's design height. Every clearance that keeps content
	   out from under the bar derives from this one value: the wizard's own
	   bottom padding and the mobile order-summary bar's offset both read it.
	   alignWizardBar() overwrites it with the measured height after paint. */
	--cateros-bar-h: 60px;
	/* ONE sticky offset for the planner's pinned columns. 18px is the value
	   the catalog's category rail has always used (catalog-mode.css mirrors
	   Free's card); the Order Summary card reads this token so both stick at
	   the same height. */
	--cateros-sticky-top: 18px;
	/* ONE focus ring for the whole planner (U9): brand, never black, never
	   yellow. Composited everywhere as `0 0 0 2px #fff` + this ring, so the
	   2px white gap keeps the brand ring legible on tinted and brand-filled
	   surfaces alike. Pro's catalog controls read the same token. */
	--cateros-focus-ring: 0 0 0 2px var(--cateros-primary, #2271B1);
	/* ONE border for every text control (U10): the date/time fields' own
	   14% ink mix, now shared by inputs, textareas, the time pair, the
	   guests stepper and the search fields. */
	--cateros-input-border: color-mix(in srgb, var(--cateros-text-strong, #111827) 14%, transparent);
	/* The composited form every rule uses: the ring pushed OUT past the 2px
	   white gap (an equal-spread pair would paint the gap over the ring). */
	--cateros-focus-ring-offset: 0 0 0 2px #fff, 0 0 0 4px var(--cateros-primary, #2271B1);
}

/* Admin-bar aware: WordPress's fixed toolbar is 32px at desktop widths, so a
   logged-in view needs the sticky offset pushed below it or the card's top
   slides underneath. Scoped to the token, so every reader follows at once. */
body.admin-bar .cateros-wizard {
	--cateros-sticky-top: 50px;
}

/* [x-cloak] has MOVED to the inline <style id="cateros-custom-colors"> block that
   Cateros_Module_Branding::print_frontend_css_variables() prints on wp_head.

   It cannot live here any more. This stylesheet is now enqueued at render time by
   the shortcode, so on a page whose builder hides its layout from a content search
   it arrives in the FOOTER — and a cloaking rule that loads after the markup it is
   meant to hide has already done nothing. The wizard carries 53 x-cloak attributes
   and holds all five step panels in the DOM at once, so the first paint would show
   every step stacked open.

   The head block is printed unconditionally on every front-end page, so the rule is
   always in place before any markup that needs it, whatever enqueued what. Defined
   in exactly one place; do not restore a copy here. */

/* ── Focus indicator ────────────────────────────────────────────────────────
   One ring for every focusable element in the wizard.

   :focus-visible only — keyboard users get the ring, mouse clicks do not.

   It is an OUTLINE, never a background change, so it can coexist with the
   selected and hover states instead of competing with them: a card can be
   selected (brand tint + brand border) AND focused (ring) at once and both stay
   readable.

   outline-offset creates a gap of page/card background between the element edge
   and the ring. That gap is what makes ONE colour work on all five backgrounds
   (white card, brand-tinted selected card, brand-filled active step card,
   brand-filled Next button, gradient sidebar card) — the ring is judged against
   the gap, not against whatever the element is filled with, which is the
   standard technique for exactly this problem.

   --cateros-text is the darkest token available and is what body copy already
   uses, so the ring is guaranteed to carry the same contrast that text does.

   THIRD SELECTOR — the fulfillment card. Its radio is visually hidden with
   .cateros-wizard__sr-only, so the first selector still matches (the input IS a
   focus-visible descendant) but paints a ring on a clipped 1x1 box: invisible.
   :has() hoists it to the label, which is the thing the customer sees.

   Added to THIS selector list rather than written as a separate rule on purpose:
   there must stay exactly one definition of the ring in this file, so its colour,
   width and offset can never drift between controls. */
.cateros-wizard :focus-visible,
.cateros-pricing :focus-visible,
.cateros-wizard__fulfillment-option:has(.cateros-wizard__fulfillment-radio:focus-visible),
.cateros-wizard__event-card:has(.cateros-wizard__event-card-radio:focus-visible),
.cateros-wizard__serving-card:has(.cateros-wizard__serving-card-radio:focus-visible) {
	/* U9: the BRAND ring (--cateros-focus-ring) with a 2px white gap, as a
	   box-shadow pair — never the old ink outline. Components whose own
	   state rules out-specify this are re-pinned in the end-of-file block. */
	outline: none;
	box-shadow: var(--cateros-focus-ring-offset);
	border-radius: inherit;
}

/* Round 12's focus background-pinning was REMOVED in round 13. It defended
   against a theme rule neither of us could isolate, and broke our own UI: the
   `background-color: inherit` line applied to .cateros-wizard__progress-btn with
   no state exclusion, so a focused ACTIVE step card inherited its <li>'s
   transparent background, lost its brand fill and rendered white-on-white.
   Focus is signalled by the :focus-visible ring above and nothing else. State
   backgrounds are owned by the state rules alone. If a theme repaints focused or
   active buttons, that is handled in the theme, not compensated for here. */

/* Horizontal jump when the lead-time banner appears/disappears: showing it makes
   the page taller, the root scrollbar toggles, and the theme's centred container
   shifts by the scrollbar width. Reserving a stable gutter fixes the sideways
   movement WITHOUT reserving any space for the banner itself — the vertical
   push-down when it appears is correct and is left alone. Root-level because the
   page scroller is the root element, not the wizard. */
html {
	scrollbar-gutter: stable;
}

/* No max-width and no auto margins: the theme / page-builder container decides
   how wide the wizard is, so it lines up with the site header and the rest of the
   page. Horizontal padding is mobile-only — a safety inset for full-bleed
   sections — and is removed at 720px so the wizard sits flush in its container.
   Vertical padding stays; only the inline axis is the container's business.

   The 84px bottom padding is the clearance for the fixed order-summary bar
   (.cateros-pricing__mobile, 70px tall with its insets), so the wizard's last
   control can always scroll above it. The bar renders below 1024px, so the
   clearance must hold for that whole range: it used to drop to 40px at 720px,
   which left a 30px band of the wizard under the bar between 720px and 1023px
   on any page where the wizard is the last content. Both Step 2 layouts sit
   inside .cateros-wizard, so this one rule serves the sequential flow and
   Catalog Mode alike — neither reserves space of its own. */
.cateros-wizard {
	padding-block: 18px 84px;
	padding-inline: 16px;
	color: var(--cateros-text, #1f2937);
	font-family: system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji";
}

@media (min-width: 720px) {
	.cateros-wizard {
		padding-block: 28px 84px;
		padding-inline: 0;
	}
}

/* The bar disappears at 1024px (its own min-width: 1024px display:none), so the
   clearance shrinks to ordinary page spacing at exactly the same breakpoint —
   no reserved band is ever shown without the bar it exists for. */
@media (min-width: 1024px) {
	.cateros-wizard {
		padding-block: 28px 40px;
	}
}

/* Clearance for the FIXED Back/Next bar — #cateros-wizard (the full planner)
   only, because the mini wizard shares .cateros-wizard but renders no bar.
   ONE rule at every width since U4: the floating mobile summary bar that
   needed its own 84px band is gone (the order summary is a drawer now), so
   the clearance is simply the bar's height plus 16px of breathing room.
   --cateros-bar-h is the bar's MEASURED height (set by alignWizardBar(),
   safe-area inset included), so no env() is added here — that would count
   the inset twice. The 60px token only covers the moment before init. */
#cateros-wizard.cateros-wizard {
	padding-bottom: calc(var(--cateros-bar-h) + 16px);
}

.cateros-wizard__layout {
	display: grid;
	grid-template-columns: 1fr;
	gap: 18px;
}

/* Desktop: progress nav and step panel are SIBLING grid items in column 1
   (rows 1 and 2); the sidebar spans both so its top aligns with the nav and its
   bottom with the panel. The old markup nested nav+panel in a .cateros-wizard__main
   wrapper, which made row-spanning impossible. Sidebar stays 360px, breakpoint
   stays 1024px. */
@media (min-width: 1024px) {
	.cateros-wizard__layout {
		grid-template-columns: minmax(0, 1fr) 360px;
		grid-template-rows: auto 1fr;
		align-items: start;
		gap: 22px;
	}

	.cateros-wizard__progress {
		grid-column: 1;
		grid-row: 1;
	}

	.cateros-wizard__panel {
		grid-column: 1;
		grid-row: 2;
	}

	.cateros-wizard__sidebar {
		grid-column: 2;
		grid-row: 1 / 3;
		align-self: stretch;
	}

	/* STICKY FIX (U2b). The sticky Order Summary card's containing block is
	   this intermediate .cateros-pricing wrapper, NOT the stretched aside —
	   and a block wrapper is only as tall as its content, so the card had
	   zero travel room and never actually stuck; it scrolled away with the
	   page. Filling the aside's stretched height gives the card the full
	   column to stick within. This was the defeater Part D asks about: not
	   an overflow, an unstretched intermediate parent. */
	.cateros-wizard__sidebar .cateros-pricing {
		height: 100%;
	}

	/* Thank You screen: nav and sidebar are gone, so the second track would sit
	   there empty and hold the panel at 1fr. One column instead. */
	.cateros-wizard__layout--success {
		grid-template-columns: minmax(0, 1fr);
		grid-template-rows: auto;
	}

	.cateros-wizard__layout--success .cateros-wizard__panel {
		grid-column: 1;
		grid-row: 1;
	}
}

/* =========================
   Progress bar
   ========================= */

/* No margin-bottom: nav, panel and sidebar are all grid items, so the layout's
   own `gap` spaces them at every width. The old 16px margin was additive on top
   of the gap, and — because this rule sits AFTER the 1024px block above — it also
   overrode that block's `margin-bottom: 0` at equal specificity. */
.cateros-wizard__progress {
	margin-block-end: 0;
	/* The layout grid's `1fr` track is minmax(auto, 1fr): without this, the
	   journey strip's min-content width (four tiles + two-line text blocks)
	   props the track open and the page scrolls sideways at tablet widths.
	   min-width: 0 lets the track shrink and the text blocks wrap instead. */
	min-width: 0;
	/* The strip's two forms switch on the NAV's own width, not the viewport:
	   the side-by-side form needs ~700px of track, and how much track exists
	   depends on the layout stage, not the screen — a 1024px desktop gives the
	   strip ~520px (two-column stage, 360px sidebar) while a 900px tablet gives
	   it ~700px (single column). A container query reads the real number.
	   Support: container queries shipped before :has() on every engine, and
	   this stylesheet already relies on :has() and color-mix(). */
	container-type: inline-size;
}

/* Journey strip: circular icon tiles on one line, text beside each tile,
   connectors between steps. Flex (not a fixed column count) so the row adapts
   if the step list ever changes. */
/* Selector is prefixed with .cateros-wizard on purpose — specificity (0,2,0).
   Astra emits `.entry-content ul, .entry-content ol { padding: revert; … }` from
   inc/dynamic-css/block-editor-compatibility.php at (0,1,1), which beat a bare
   .cateros-wizard__progress-list (0,1,0) and left the nav inset by the theme's
   list padding. We out-specify from the plugin rather than editing the theme:
   theme edits are lost on update, are site-wide, and would not travel to other
   themes. Same reason the hover rules further down are prefixed. */
/* stretch, not center: every <li> takes the height of the tallest, so a step
   whose subtitle wraps to two lines cannot be taller than its neighbours —
   the four steps are equal height by construction, whatever each line count
   is. Inside each equal-height item, align-items: center (on the item rule
   below) keeps tile, text and connector on one shared horizontal axis. */
.cateros-wizard .cateros-wizard__progress-list {
	display: flex;
	align-items: stretch;
	gap: 0;
	list-style: none;
	padding: 4px 0;
	margin: 0;
}

/* Every item but the last stretches, and its ::after draws the connector to the
   next step — so the connectors absorb all free width and the four tiles read
   as one journey. The last item is content-sized: no trailing connector, no
   trailing gap. */
.cateros-wizard__progress-item {
	display: flex;
	align-items: center;
	min-width: 0;
}

/* basis auto, not 0: with equalized zero bases the free width all flowed to
   the connectors while the text was squeezed into wrapping even in English at
   desktop widths. Content-sized bases let each step keep its natural one-line
   width first; the connectors absorb the genuine remainder, and only a real
   deficit (translation, larger type, narrow track) makes text wrap. */
.cateros-wizard__progress-item:not(:last-child) {
	flex: 1 1 auto;
}

/* The path AHEAD: a dashed hairline in the neutral border tone. Tight minimum
   footprint (10px line + 6px margins): at ~740px of track every pixel the
   connectors do not need goes to keeping the subtitles on one line. */
.cateros-wizard__progress-item:not(:last-child)::after {
	content: "";
	/* basis = the minimum: the connector's flex BASIS counts into its item's
	   content size, and any basis above the minimum re-creates the very
	   deficit that forced English subtitles to wrap at ~740px of track.
	   grow 3 vs the button's grow 1 (below): the connectors take most of the
	   free width, but the button must receive SOME — with the button at grow 0
	   it sat at exactly its one-line flex base, and sub-pixel rounding of the
	   item widths shaved fractions off that base and wrapped every subtitle. */
	flex: 3 1 6px;
	min-width: 6px;
	margin-inline: 3px;
	border-top: 2px dashed var(--cateros-border, #e5e7eb);
}

/* The path BEHIND the current step (li.is-past = this step is completed, so the
   segment to the next step has been traversed): solid brand line. Solid-vs-
   dashed is a shape difference, so the two directions differ without relying
   on colour alone. */
.cateros-wizard__progress-item.is-past:not(:last-child)::after {
	border-top-style: solid;
	border-top-color: var(--cateros-primary);
}

.cateros-wizard .cateros-wizard__progress-btn {
	display: flex;
	align-items: center;
	gap: 8px;
	/* 8px on the text side: the hover wash (and any state background) needs
	   real air between the text and its edge — 4px read as text touching. */
	padding: 4px 8px 4px 4px;
	border: 0;
	border-radius: 999px;
	background: transparent;
	cursor: pointer;
	color: var(--cateros-text, #1f2937);
	text-align: left;
	min-width: 0;
	box-shadow: none;
	/* grow 1 (connector grows at 3): a sliver of the free width lands on the
	   button so it always clears its one-line base — see the connector note. */
	flex: 1 1 auto;
	transition: background 160ms ease;
	/* Themes set white-space: nowrap on <button>; it inherits into the label
	   and subtitle spans and turns a long German subtitle into sideways
	   overflow across the neighbouring tile instead of a wrapped second line.
	   Reset it here so text inside the strip wraps normally. */
	white-space: normal;
}

.cateros-wizard__progress-btn:disabled {
	cursor: not-allowed;
}

/* Circular icon tile. Default styling = the NOT-YET-REACHED state: white disc
   with a dashed outline ("path not walked yet"), muted artwork. Dashed border
   and the disabled button are two non-colour signals for this state. */
.cateros-wizard__progress-tile {
	position: relative;
	flex: 0 0 auto;
	width: 48px;
	height: 48px;
	border-radius: 50%;
	display: flex;
	align-items: center;
	justify-content: center;
	background: #fff;
	border: 1px dashed color-mix(in srgb, var(--cateros-text, #1f2937) 30%, transparent);
	transition: background 160ms ease, border-color 160ms ease, box-shadow 160ms ease, transform 160ms ease;
}

/* Numbered badge, top-right of the tile. Its fill treatment differs per state
   (outlined / brand-filled / inverted) — a third colour-independent signal. */
.cateros-wizard__progress-num {
	position: absolute;
	top: -5px;
	right: -5px;
	width: 18px;
	height: 18px;
	border-radius: 50%;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 11px;
	font-weight: 700;
	line-height: 1;
	background: #fff;
	/* Solid mix, not an alpha fade — same reasoning as the text tones below. */
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 75%, #fff);
	border: 1.5px solid color-mix(in srgb, var(--cateros-text, #1f2937) 30%, transparent);
}

/* Icon colour is driven entirely by `color` on this element, and every SVG shape
   resolves through currentColor — so a brand change in Design/Branding carries
   straight through with no per-step colour anywhere. */
.cateros-wizard__progress-icon {
	flex-shrink: 0;
	display: block;
	line-height: 0;
	color: var(--cateros-primary);
}

/* Not-yet-reached artwork is muted through opacity on the icon (not the whole
   button, so the label keeps its own deliberate muting below). */
.cateros-wizard__progress-btn:disabled .cateros-wizard__progress-icon {
	opacity: 0.55;
}

.cateros-wizard__progress-icon svg {
	width: 24px;
	height: 24px;
	display: block;
}

/* Duotone built from currentColor: a solid tone, a darker tone and a light tone,
   so the artwork keeps depth while staying a single-hue brand derivative. */
/* Only two treatments, both resolving to currentColor. Internal detail is drawn
   as GAPS in the geometry so the card background shows through, never as a tonal
   mix.
   The old __ico-deep (currentColor mixed with black) and __ico-soft (mixed with
   white) were fragile in opposite directions: when --cateros-btn-text is white,
   __ico-soft equals __ico-fill and overlapping shapes merge (the eye's pupil
   vanished); when a pale brand makes --cateros-btn-text dark, __ico-deep equals
   __ico-fill and the gift box's lid merged instead.
   Contrast here is currentColor against the card background — i.e. exactly the
   text contrast the design already guarantees — so it holds for any brand colour
   in either direction. */
.cateros-wizard__ico-fill { fill: currentColor; }

/* Knockouts. --cos-ico-cut tracks the TILE's background per state, so a cut shape
   punches a true hole and its contrast against currentColor is identical to the
   label's text contrast — guaranteed for any brand colour, light or dark. */
.cateros-wizard__progress-btn { --cos-ico-cut: #fff; }
.cateros-wizard__progress-btn.is-active { --cos-ico-cut: var(--cateros-primary); }
.cateros-wizard__progress-btn.is-complete:not(.is-active) {
	--cos-ico-cut: var(--cateros-primary-subtle, color-mix(in srgb, var(--cateros-primary, #2271B1) 8%, transparent));
}
.cateros-wizard__ico-cut { fill: var(--cos-ico-cut); }
.cateros-wizard__ico-cut-stroke { stroke: var(--cos-ico-cut); }

/* Two-line text block beside the tile: step name over a one-line purpose. */
.cateros-wizard__progress-text {
	display: flex;
	flex-direction: column;
	gap: 2px;
	min-width: 0;
}

/* Text tones are SOLID mid-tones mixed from the text token toward the white
   surface (#fff is this file's existing surface constant — tile and badge
   backgrounds use the same literal), never alpha fades: a fade's contrast
   sinks with whatever sits behind it, and the strip sits on the theme's
   content background, not guaranteed white. Review measured the old 68%/42%
   alpha fades at 3.64 and 2.47 — both below the 4.5 floor. Solid mixes at
   these percentages measure: label 14.4 (full token), sub 78% ≈ 7.2,
   disabled label 75% ≈ 6.6, disabled sub 72% ≈ 5.9 — all ≥ 4.5 with margin
   left for a slightly tinted theme background. */
.cateros-wizard__progress-label {
	font-size: 13px;
	font-weight: 700;
	letter-spacing: -0.01em;
	line-height: 1.25;
	color: var(--cateros-text, #1f2937);
	/* No nowrap / ellipsis: translated labels must wrap, not truncate. */
	overflow-wrap: anywhere;
	hyphens: auto;
	max-width: 100%;
}

/* The subtitle wraps rather than truncates (a translation must never be cut
   off); the text block's min-width: 0 keeps a long line from widening its item
   and pushing the strip out of line — it wraps to more lines instead. */
.cateros-wizard__progress-sub {
	font-size: 11.5px;
	font-weight: 500;
	line-height: 1.35;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 78%, #fff);
	overflow-wrap: anywhere;
	hyphens: auto;
	max-width: 100%;
}

.cateros-wizard__progress-btn:disabled .cateros-wizard__progress-label {
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 75%, #fff);
	font-weight: 600;
}

.cateros-wizard__progress-btn:disabled .cateros-wizard__progress-sub {
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 72%, #fff);
}

/* CURRENT — brand-filled tile, on-brand artwork, a soft ring around the disc
   and a brand glow, with the strongest label tones. No card: the filled tile
   is the one filled shape in the strip and marks the current step on its own
   (plus aria-current for AT and the solid-vs-dashed tile border shape).
   State rules are prefixed to (0,3,0) so file order never decides against the
   (0,2,0) base rule — the same tie that once cost the active card its brand
   fill (see the note this replaced, Round 12). */
.cateros-wizard .cateros-wizard__progress-btn.is-active .cateros-wizard__progress-tile {
	background: var(--cateros-primary);
	border: 2px solid var(--cateros-primary);
	box-shadow:
		0 0 0 4px var(--cateros-primary-subtle, color-mix(in srgb, var(--cateros-primary, #2271B1) 12%, transparent)),
		0 8px 20px var(--cateros-primary-glow);
}

/* Tile is filled with --cateros-primary, so the icon flips to the on-brand
   text token (emitted from the Branding "Button text color" picker). */
.cateros-wizard__progress-btn.is-active .cateros-wizard__progress-icon {
	color: var(--cateros-btn-text);
}

.cateros-wizard__progress-btn.is-active .cateros-wizard__progress-label {
	color: var(--cateros-text-strong, var(--cateros-text, #1f2937));
}

/* The active subtitle sits beside the tile on the PAGE surface, not on the
   brand fill — white here would vanish against the page. Full text token
   instead: the strongest tone in the strip, matching the step's prominence. */
.cateros-wizard__progress-btn.is-active .cateros-wizard__progress-sub {
	color: var(--cateros-text, #1f2937);
}

/* Current badge: inverted — white disc, brand number, brand border — so it
   stays legible on top of the filled tile and its treatment differs from both
   neighbours. */
.cateros-wizard .cateros-wizard__progress-btn.is-active .cateros-wizard__progress-num {
	background: #fff;
	color: var(--cateros-primary);
	border-color: var(--cateros-primary);
}

/* COMPLETED — brand-tinted tile behind artwork that keeps its own hue, with a
   SOLID 2px brand border (vs the dashed 1px ahead) and a brand-filled badge.
   Border style+weight and badge fill are the non-colour signals; AT hears the
   existing "Completed" suffix. */
.cateros-wizard .cateros-wizard__progress-btn.is-complete:not(.is-active) .cateros-wizard__progress-tile {
	background: var(--cateros-primary-subtle, color-mix(in srgb, var(--cateros-primary, #2271B1) 8%, transparent));
	border: 2px solid var(--cateros-primary);
}

.cateros-wizard .cateros-wizard__progress-btn.is-complete:not(.is-active) .cateros-wizard__progress-num {
	background: var(--cateros-primary);
	color: var(--cateros-btn-text);
	border-color: var(--cateros-primary);
}

/* The branding module prints a theme-maroon blocker for this button that fills
   it with --cateros-primary !important on hover. With the tile design that
   fill made a hovered step read exactly like the active one, so BOTH hover
   rules below out-specify it (extra class each, both !important):
   - a clickable NON-active step gets a faint brand wash + a 1px tile lift —
     feedback that cannot be mistaken for the active step's filled tile;
   - the ACTIVE step gets no visual change at all (clicking it is a no-op
     navigation to where the customer already is), which the old counter's
     :not(.is-active) exclusion accidentally left to the branding fill. */
.cateros-wizard .cateros-wizard__progress-btn.is-clickable:hover:not(:disabled):not(.is-active) {
	background: var(--cateros-primary-subtle, color-mix(in srgb, var(--cateros-primary, #2271B1) 8%, transparent)) !important;
	background-color: var(--cateros-primary-subtle, color-mix(in srgb, var(--cateros-primary, #2271B1) 8%, transparent)) !important;
	border-color: transparent !important;
	color: var(--cateros-text, #1f2937) !important;
}

.cateros-wizard .cateros-wizard__progress-btn.is-clickable.is-active:hover:not(:disabled) {
	/* The active step shows no hover response at all (clicking it is a no-op)
	   — this counter only exists to beat the branding-printed primary fill. */
	background: transparent !important;
	background-color: transparent !important;
	border-color: transparent !important;
	color: var(--cateros-text, #1f2937) !important;
}

.cateros-wizard .cateros-wizard__progress-btn.is-clickable:hover:not(:disabled):not(.is-active) .cateros-wizard__progress-tile {
	border-color: var(--cateros-primary);
	transform: translateY(-1px);
}

.cateros-wizard .cateros-wizard__progress-btn.is-clickable:hover:not(:disabled):not(.is-active) .cateros-wizard__progress-label {
	color: var(--cateros-text-strong, var(--cateros-text, #1f2937)) !important;
}

/* Narrow track (under 700px of nav width — phones, small tablets, and the
   1024-1279 two-column stage where the sidebar leaves the strip only
   ~520-670px): four side-by-side text blocks cannot fit, so each step stacks
   its label under the tile, the subtitle bows out first, and the connectors
   align to the tile centres. Measured: the side-by-side form fits from 700px
   of track up (at exactly 700 the longest subtitle wraps to a second line,
   which is its designed degradation), and collapses into overlap below that. */
@container (max-width: 699px) {
	/* Items stay stretched (equal heights, same as desktop), but their CONTENT
	   top-aligns: with stacked tile+label, a two-line label would otherwise
	   shift its own tile off the shared axis and drag its connector with it.
	   Top-aligned, every tile centre sits at the same 22px and the connectors
	   (margin-top 21px + 2px line) run through all of them. */
	.cateros-wizard__progress-item {
		align-items: flex-start;
	}

	.cateros-wizard .cateros-wizard__progress-btn {
		flex-direction: column;
		gap: 6px;
		/* 4px under the label: at 2px the text sat on the button's edge. */
		padding: 2px 4px 4px;
	}

	.cateros-wizard__progress-tile {
		width: 40px;
		height: 40px;
	}

	.cateros-wizard__progress-icon svg {
		width: 20px;
		height: 20px;
	}

	.cateros-wizard__progress-text {
		align-items: center;
	}

	.cateros-wizard__progress-label {
		font-size: 11.5px;
		text-align: center;
	}

	.cateros-wizard__progress-sub {
		display: none;
	}

	/* Tile centre sits 2px padding + 20px radius below the item's top edge. */
	.cateros-wizard__progress-item:not(:last-child)::after {
		align-self: flex-start;
		margin-top: 21px;
		margin-inline: 4px;
	}
}

/* =========================
   Main panel
   ========================= */

.cateros-wizard__panel {
	background: #fff;
	border: 1px solid var(--cateros-border, #e5e7eb);
	border-radius: var(--cateros-radius-outer);
	box-shadow: 0 16px 40px color-mix(in srgb, var(--cateros-text, #1f2937) 10%, transparent);
	padding-block: 22px 18px;
	padding-inline: 20px;
}

@media (min-width: 1024px) {
	.cateros-wizard__panel {
		padding-block: 36px 30px;
		padding-inline: 36px;
	}
}

.cateros-wizard__panel-title {
	margin: 0 0 10px;
	font-size: 18px;
	letter-spacing: -0.02em;
}

/* Step 4 after submit. The panel keeps its ordinary surface: this screen ends a
   REQUEST, not a confirmed order, and a green success banner promises something
   the caterer has not yet agreed to. The inner step card is hidden here, so the
   panel's own padding is all there is — it was 16/18/14, tighter than the 22/20
   every other step gets, which is why it read cramped. Only this state changes;
   the other steps are left alone. */
.cateros-wizard__panel--step4-success {
	/* Even 50 all round: the composition is centred, so equal insets on all four
	   sides is what keeps it sitting in the middle of the card. */
	padding: 50px;
	min-height: 0;
	/* Capped and centred rather than filling the grid column. --success collapses
	   the layout to one full-width track, which is what lets the card stretch;
	   this is the counterweight to that. On the panel and not an inner wrapper,
	   because it is the CARD that was too wide — the text inside was already held
	   to its own measure. margin-inline rather than justify-self so it centres
	   the same way in the single-column mobile layout, which is not a grid. */
	max-width: 750px;
	margin-inline: auto;
}

.cateros-wizard__panel-body {
	padding: 14px 14px;
	border-radius: var(--cateros-ui-radius);
	background: #fafcff;
	border: 1px dashed color-mix(in srgb, var(--cateros-text-strong) 12%, transparent);
	min-height: 160px;
	display: grid;
	place-items: center;
}

/* Flattened: this wrapper used to paint its own white fill, border and inset
   highlight INSIDE the panel card, so every step's fields sat indented behind a
   second box. The reference has one surface — heading, intro and fields all sit
   directly on the panel. The element stays in the DOM: wrapper.php binds
   x-show/x-bind:class to it and the four step partials render inside it. */
/* Inner group container. Border restored (round 6) now that the theme's
   constrained-layout margins are fixed at the source — the border was never the
   cause of the old offset. Uses --cateros-border to match the panel and sidebar.
   Deliberately NO inset shadow and NO white fill: the panel behind it is already
   white, so a second white fill adds nothing. Padding is symmetric on both
   inline sides so content sits centred inside the border. */
.cateros-wizard__panel-body--steps {
	display: block;
	min-height: 0;
	background: none;
	border: 1px solid var(--cateros-border, #e5e7eb);
	box-shadow: none;
	padding-block: 20px;
	padding-inline: 20px;
	border-radius: var(--cateros-radius-card);
}

/* Theme constrained-layout defence — ALL steps.
   Astra/WP apply a max-width plus auto horizontal margins to block children
   inside .entry-content. The Alpine step mounts (<div x-show="currentStep === N">)
   and the step roots inherit it, which (a) inset every step's content relative to
   the panel heading and (b) made content jump sideways whenever the lead-time
   banner mounted/unmounted, because the constrained width is content-dependent
   and the auto margins recompute.
   The heading is unaffected because .cateros-wizard__panel-title is a direct
   child of .cateros-wizard__panel, outside .cateros-wizard__panel-body.
   This generalises a fix that already existed for step 2 only (see the
   .cateros-wizard__panel-body--step2 block lower down, whose original comment
   named this exact cause). Fixed at the source; no negative margins anywhere. */
.cateros-wizard__panel-body--steps > div,
.cateros-wizard__panel-body--steps .cateros-wizard__step {
	margin-inline: 0 !important;
	padding-inline: 0 !important;
	max-width: none !important;
	width: 100%;
	box-sizing: border-box;
}

/* Same width release for the flow content, but WITHOUT touching padding — the
   banner keeps its own 11px/14px inset; only the theme's width cap and auto
   margins are undone, so it spans the full content width and pushes down only. */
.cateros-wizard__panel-body--steps .cateros-wizard__intro,
.cateros-wizard__panel-body--steps .cateros-wizard__banner,
.cateros-wizard__panel-body--steps .cateros-wizard__grid,
.cateros-wizard__panel-body--steps .cateros-wizard__field {
	margin-inline: 0 !important;
	max-width: none !important;
	width: 100%;
	box-sizing: border-box;
}

.cateros-wizard__placeholder {
	margin: 0;
	font-weight: 700;
	color: color-mix(in srgb, var(--cateros-text-strong) 72%, transparent);
	text-align: center;
	padding: 2rem 0;
}

.cateros-wizard__intro {
	margin: 0 0 1.125rem;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 64%, transparent);
	line-height: 1.55;
	font-size: 0.9375rem;
}

.cateros-wizard__banner {
	border-radius: var(--cateros-ui-radius);
	padding: 11px 14px;
	margin-bottom: 1rem;
	font-size: 0.875rem;
	font-weight: 600;
	line-height: 1.45;
}

.cateros-wizard__banner--info {
	background: rgba(234, 179, 8, 0.12);
	border: 1px solid rgba(202, 138, 4, 0.28);
	color: #854d0e;
}

.cateros-wizard__banner--warn {
	background: rgba(249, 115, 22, 0.12);
	border: 1px solid rgba(234, 88, 12, 0.32);
	color: #9a3412;
}

.cateros-wizard__banner--error {
	background: rgba(239, 68, 68, 0.1);
	border: 1px solid rgba(220, 38, 38, 0.28);
	color: #991b1b;
}

.cateros-wizard__grid {
	display: grid;
	gap: 1rem;
	/* Reuses the same 1.25rem rhythm .cateros-wizard__field uses between field
	   groups, so the row spaces like every other group. */
	margin-bottom: 1.25rem;
}

/* Fields nested in a grid must not carry their own bottom margin: grid items do
   not collapse margins, so each cell was adding 1.25rem of dead space inside the
   row (the phantom band under the date/time row). The grid's `gap` owns the
   in-row spacing; the rule above owns the spacing after it. */
.cateros-wizard__grid > .cateros-wizard__field {
	margin-bottom: 0;
}

@media (min-width: 720px) {
	.cateros-wizard__grid--2 {
		grid-template-columns: 1fr 1fr;
		align-items: start;
	}
}

.cateros-wizard__field {
	margin-bottom: 1.25rem;
	/* Same reason as .cateros-wizard__input's min-width: 0 above: this div is
	   itself the grid item (direct child of .cateros-wizard__grid), so its
	   own auto floor is its content's min-content size, which for a native
	   date/time control is governed by the browser, not by this stylesheet.
	   Belt-and-suspenders alongside the input-level fix — harmless for every
	   other field, since none of them relies on shrinking past its content. */
	min-width: 0;
}

/* Prefixed to stay ahead of the now-prefixed .cateros-wizard .cateros-wizard__input
   base rule: that rule sets the `border` shorthand and sits LATER in the file, so
   at equal specificity it would repaint this red border back to the default.
   Only border-COLOR changes here — the width stays 1px, so entering the error
   state never shifts the field's height or the layout below it. */
.cateros-wizard .cateros-wizard__field--error .cateros-wizard__input,
.cateros-wizard .cateros-wizard__field--error .cateros-wizard__time-pair,
.cateros-wizard .cateros-wizard__field--error .cateros-wizard__qty {
	border-color: #dc2626;
	box-shadow: 0 0 0 1px rgba(220, 38, 38, 0.12);
}

.cateros-wizard__label {
	display: block;
	/* U12 heading scale: section labels 14px/600 on every step. */
	font-size: 14px;
	font-weight: 600;
	color: color-mix(in srgb, var(--cateros-text-strong) 78%, transparent);
	margin-bottom: 0.375rem;
	letter-spacing: -0.01em;
}

/* Item 4: helper text now matches the step intro line's size, and its colour is
   the same value expressed through --cateros-text instead of a hardcoded rgba.
   Was 0.75rem / rgba(17,24,39,0.52) — undersized and low contrast. */
.cateros-wizard__hint {
	margin: 0.35rem 0 0;
	/* U12 heading scale: helper lines 13px/400 muted on every step. */
	font-size: 13px;
	font-weight: 400;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 64%, transparent);
	line-height: 1.55;
}

/* Prefixed with .cateros-wizard to reach (0,2,0). The theme ships
       input[type=date] { min-height: var(--has-height, var(--theme-form-field-height, 40px)) }
   at (0,1,1), which outranked the unprefixed (0,1,0) class selector and applied
   to the date field ONLY — there is no matching input[type=time] rule anywhere
   in the theme. With no :root value for --theme-form-field-height on this site
   both vars fall through to the literal 40px, so the date box resolved to 40px
   while the time box beside it kept our 48px: an 8px mismatch in the same grid
   row. Raising our own selector so its declaration actually applies is the same
   fix used for .cateros-wizard__progress-list and the review list; no new rule
   is added to counteract the theme.

   box-sizing is now explicit rather than inherited from the theme's global
   reset, so min-height stays a border-box height under any theme. */
.cateros-wizard .cateros-wizard__input {
	box-sizing: border-box;
	width: 100%;
	max-width: 100%;
	/* Overrides the initial min-width: auto a flex or grid item resolves to —
	   the ancestor's own min-content size, not 0 (unlike a plain block box,
	   where auto already means 0 — MDN, min-width § Values). For most fields
	   that is invisible; for a native date input it is not: the mini wizard's
	   <label> is itself a flex item (.cateros-wizard__mini-row > label), and
	   iOS Safari's date control renders every segment plus the calendar icon
	   as one native widget with a real minimum content width, unlike Chrome's
	   comparatively narrow one — which is why Chrome device emulation never
	   showed the overflow a real iPhone did. width/max-width: 100% only cap
	   the SPECIFIED size; they do not touch this auto floor, so the box still
	   grew past its card on iOS regardless. Reported from the client's
	   staging site, an iPhone, Safari — never reproduced in this sandbox's
	   Chrome emulation. Sizing only: no appearance/-webkit-appearance change,
	   so the native calendar icon is untouched. */
	min-width: 0;
	/* min-height not height: native date/time controls render per browser+OS
	   locale (DD.MM.YYYY, 24h, AM/PM), so the box must be able to grow rather
	   than clip a longer locale format. */
	min-height: 48px;
	padding-block: 10px;
	padding-inline: 16px;
	border-radius: var(--cateros-radius-card);
	border: 1px solid var(--cateros-input-border);
	background: #fff;
	font-size: 0.9375rem;
	color: color-mix(in srgb, var(--cateros-text-strong) 90%, transparent);
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

/* ── Step 1 time pair ────────────────────────────────────────────────────────
   Two native <select>s (hour, minute) that must read as ONE field. The WRAPPER
   carries everything .cateros-wizard .cateros-wizard__input gives the date
   field beside it — border, radius, background, 48px min-height, padding,
   transition — and the selects inside are stripped to plain text: no border,
   no background, appearance:none. Focus shows on the wrapper via :focus-within
   (mirroring .cateros-wizard__input:focus exactly), never on the inner
   selects; the wizard-wide :focus-visible ring is suppressed on them at
   higher specificity for the same reason. Native selects are kept so mobile
   taps open the OS picker wheel — no custom overlay, no JS dropdown. */
.cateros-wizard .cateros-wizard__time-pair {
	box-sizing: border-box;
	display: flex;
	align-items: center;
	/* Left-aligned group (flex default). The group and the date input were
	   both centred for a round and REVERTED: the group now starts at the
	   wrapper's left inset again, level with the date field's text. What
	   SURVIVES from that round is the inner centring — each select centres
	   its value within its own box (see text-align on the select rule). */
	width: 100%;
	max-width: 100%;
	min-width: 0;
	min-height: 48px;
	padding-block: 0;
	padding-inline: 16px 12px;
	border-radius: var(--cateros-radius-card);
	border: 1px solid var(--cateros-input-border);
	background: #fff;
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

/* Each half wraps its select plus that select's own caret. position:relative
   so the caret can sit over the select's reserved end padding; inline-flex so
   the half is exactly as wide as its select and the row lays out naturally
   from the wrapper's left padding — the hour text starts where the date
   field's text starts, so the two grid columns align. */
.cateros-wizard__time-half {
	position: relative;
	display: inline-flex;
	align-items: center;
}

.cateros-wizard .cateros-wizard__time-select {
	appearance: none;
	-webkit-appearance: none;
	-moz-appearance: none;
	border: 0;
	background: transparent;
	box-shadow: none;
	margin: 0;
	padding-block: 0;
	/* End padding RESERVES the caret's lane: a select is intrinsically as wide
	   as its longest option ("11 PM" / "00"), so text can never run under the
	   caret at any label length, and picking a value never shifts the layout —
	   the width comes from the option list, not the selection. Zero start
	   padding so the hour text lands on the wrapper's own 16px inset, level
	   with the date input's text. */
	padding-inline: 0 24px;
	/* Centred within the CONTENT box — which the 24px end padding already
	   shrinks past the caret lane — so the value sits in the middle of its
	   usable space, not optically dragged left by lane it can't enter. A
	   shorter value ("08", the dash) no longer hugs the select's left edge.
	   Engines that ignore text-align on <select> keep the left alignment. */
	text-align: center;
	/* Comfortable tap target inside the 48px box. */
	min-height: 44px;
	font-family: inherit;
	font-size: 0.9375rem;
	color: color-mix(in srgb, var(--cateros-text-strong) 90%, transparent);
	cursor: pointer;
}

/* One caret PER select, painted over the select's reserved end padding.
   An inline SVG with currentColor rather than a background-image, because a
   url() background cannot read the colour tokens — it would hardcode a hex.
   pointer-events:none makes the caret transparent to hit-testing, so a click
   on it lands on the select underneath and opens it natively: the caret area
   IS a click target, and each half reads as its own choosable control. */
.cateros-wizard__time-half-caret {
	position: absolute;
	inset-inline-end: 4px;
	display: inline-flex;
	align-items: center;
	color: color-mix(in srgb, var(--cateros-text-strong) 55%, transparent);
	pointer-events: none;
}

.cateros-wizard__time-half-caret svg {
	width: 14px;
	height: 14px;
}

/* ── Desktop custom time dropdown ───────────────────────────────────────────
   At >=1024px (the wizard's one desktop breakpoint) each half hides its
   native <select> and shows a custom trigger + listbox panel instead; below
   it the trigger and panel are display:none and the native select keeps the
   OS picker. CSS alone flips the two — both are always in the DOM bound to
   the same state, so a resize mid-interaction cannot lose the value. The
   !important on the panel's mobile hide outranks x-show's inline display,
   so an open panel is force-hidden the moment the viewport drops under the
   breakpoint (and timeDdOnResize() closes it so it cannot reappear stale).
   No open/close transition is used — panels appear instantly — so there is
   no motion for prefers-reduced-motion to gate. */
.cateros-wizard__time-trigger {
	display: none;
	/* Width floor keeps the trigger from collapsing around the dash: all real
	   labels are two characters, so ~2.6ch + the 24px caret lane holds one
	   steady width from placeholder to value. border-box so the padding that
	   reserves the caret lane is inside the floor, exactly like the selects. */
	box-sizing: border-box;
	min-width: calc(2.6ch + 24px);
}

@media (min-width: 1024px) {
	.cateros-wizard__time-half > select.cateros-wizard__time-select {
		display: none;
	}

	.cateros-wizard__time-trigger {
		display: inline-flex;
		align-items: center;
		justify-content: center;
	}
}

/* The mini wizard shares every time-control class ON PURPOSE (that is how the
   shared tokens and control styling reach it) but it is Alpine-free by design:
   it has no custom trigger for the desktop hide above to hand over to. Without
   this exception the hide reached it through the shared classes and each half
   collapsed to its absolutely-positioned caret — a bordered 48px control
   showing nothing but carets. The mini's own root class outranks the hide, so
   its native selects stay the control at every width. */
@media (min-width: 1024px) {
	.cateros-mini-wizard .cateros-wizard__time-half > select.cateros-wizard__time-select {
		display: inline-block;
	}
}

@media (max-width: 1023.98px) {
	.cateros-wizard__time-panel {
		display: none !important;
	}
}

/* The panel: anchored inside its half (position:relative there), so it moves
   with the trigger on page scroll and can never detach. Elevation borrows the
   card recipe the panel/sidebar already use — same border token, same radius
   scale, same shadow mix. width:max-content + min-width:100% = at least the
   trigger's width, wider only if a label needs it. ~7.5 rows tall before it
   scrolls, so the 24-hour list scrolls rather than towering. */
.cateros-wizard__time-panel {
	position: absolute;
	top: calc(100% + 4px);
	inset-inline-start: 0;
	z-index: 30;
	min-width: 100%;
	width: max-content;
	max-height: 272px;
	overflow-y: auto;
	margin: 0;
	padding: 4px;
	list-style: none;
	background: #fff;
	border: 1px solid var(--cateros-border, #e5e7eb);
	border-radius: var(--cateros-radius-card);
	box-shadow: 0 16px 40px color-mix(in srgb, var(--cateros-text, #1f2937) 10%, transparent);
	/* Slim scrollbar, both engines, colours from the fixed neutral token.
	   Chromium >=121 honours scrollbar-width/color and then ignores the
	   ::-webkit-* rules below; older Chromium/Safari use the ::-webkit-*
	   rules; neither supported = the OS default scrollbar, fully functional. */
	scrollbar-width: thin;
	scrollbar-color: color-mix(in srgb, var(--cateros-text-strong) 30%, transparent) transparent;
}

.cateros-wizard__time-panel::-webkit-scrollbar {
	width: 6px;
}

.cateros-wizard__time-panel::-webkit-scrollbar-track {
	background: transparent;
}

.cateros-wizard__time-panel::-webkit-scrollbar-thumb {
	background: color-mix(in srgb, var(--cateros-text-strong) 30%, transparent);
	border-radius: 999px;
}

/* Not enough room below the trigger: flip above it. */
.cateros-wizard__time-panel--up {
	top: auto;
	bottom: calc(100% + 4px);
}

/* Row states, in ascending precedence: hover (faintest tint), keyboard-active
   (stronger tint + brand inset ring), selected (solid brand + button text) —
   the same token roles the option cards use, never the browser blue. */
.cateros-wizard__time-option {
	padding: 8px 14px;
	border-radius: var(--cateros-ui-radius);
	text-align: center;
	font-size: 0.9375rem;
	color: color-mix(in srgb, var(--cateros-text-strong) 90%, transparent);
	cursor: pointer;
	-webkit-user-select: none;
	user-select: none;
}

.cateros-wizard__time-option:hover {
	background: var(--cateros-primary-tint);
}

.cateros-wizard__time-option.is-active {
	background: var(--cateros-primary-subtle, color-mix(in srgb, var(--cateros-primary, #2271B1) 8%, transparent));
	box-shadow: inset 0 0 0 1px var(--cateros-primary);
}

.cateros-wizard__time-option.is-selected {
	background: var(--cateros-primary);
	color: var(--cateros-btn-text);
}

/* One focus treatment, on the box — identical to .cateros-wizard__input:focus
   so the pair matches the date field beside it pixel for pixel. */
.cateros-wizard .cateros-wizard__time-pair:focus-within {
	border-color: var(--cateros-primary, #2271B1);
	box-shadow: 0 0 0 3px var(--cateros-primary-ring, color-mix(in srgb, #2271B1 15%, transparent));
}

/* Beats the wizard-wide `.cateros-wizard :focus-visible` ring at higher
   specificity: the wrapper's :focus-within above is this control's one focus
   indicator, exactly as :focus/outline:none already works on the inputs. */
.cateros-wizard .cateros-wizard__time-select:focus,
.cateros-wizard .cateros-wizard__time-select:focus-visible {
	outline: none;
}

.cateros-wizard__time-colon {
	margin-inline: 6px;
	font-weight: 700;
	color: color-mix(in srgb, var(--cateros-text-strong) 60%, transparent);
	-webkit-user-select: none;
	user-select: none;
}

/* The AM/PM select (12-hour sites only — the template renders it there and
   nowhere else). A gap LARGER than the colon's 6px but well short of double
   it, so the meridiem reads as its own unit after the minute while staying
   part of the one control. 12px read as disconnected; 6px collapsed to the
   colon spacing exactly and stopped reading as a separation at all — and the
   minute's 24px caret lane already contributes visual distance before this
   margin even starts. */
.cateros-wizard__time-half--meridiem {
	margin-inline-start: 8px;
}

.cateros-wizard__input:focus {
	outline: none;
	border-color: var(--cateros-primary, #2271B1);
	box-shadow: 0 0 0 3px var(--cateros-primary-ring, color-mix(in srgb, #2271B1 15%, transparent));
}

/* Prefixed for the same reason as the error rule above: the base input rule sets
   max-width: 100% at (0,2,0), so this modifier needs matching specificity or the
   postcode field would stretch to full width instead of capping at 200px. */
/* U7: at least 160px on desktop; full width on phones (the max-width lifts
   below 783px). Any sibling City field keeps the rest of its row. */
.cateros-wizard .cateros-wizard__input--postcode {
	min-width: 160px;
	max-width: 200px;
	letter-spacing: 0.06em;
	font-variant-numeric: tabular-nums;
}

@media (max-width: 782px) {
	.cateros-wizard .cateros-wizard__input--postcode {
		min-width: 0;
		max-width: none;
		width: 100%;
	}
}

/* U11: inside a Review address row (.cateros-wizard__grid--2) the postcode is
   one of two equal 50% columns, so the 200px cap above would leave a stub in a
   full-height cell — the input fills its column like the City field next to
   it. Same (0,2,0) specificity as the cap rule; later in file, so it wins.
   Step 3's postcode is not in a grid and keeps the cap. */
.cateros-wizard__grid--2 .cateros-wizard__input--postcode {
	min-width: 0;
	max-width: none;
	width: 100%;
}

/* Locked Step 4 postcode (U7; re-stacked U11): the read-only value fills its
   column at full field width — same box as every other input — and the
   "Change" link sits under it instead of beside it, where it used to shrink
   the input inside the 50% column. */
.cateros-wizard__postcode-locked {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 4px;
}

.cateros-wizard__postcode-locked .cateros-wizard__input--postcode[readonly] {
	width: 100%;
}

.cateros-wizard__postcode-locked .cateros-wizard__input--postcode[readonly] {
	background: color-mix(in srgb, var(--cateros-text, #1f2937) 4%, #fff);
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 80%, transparent);
}

.cateros-wizard .cateros-wizard__change-link {
	color: var(--cateros-primary, #2271B1);
	text-decoration: underline;
	font-weight: 600;
	white-space: nowrap;
}

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

/* U9's block-mode ✕ badge (.cateros-wizard__s3-cardmark) was removed in U12:
   under a BLOCK verdict the Delivery card stays selectable, the red note
   under the postcode input explains the refusal, and the Step 3 gate refuses
   Next. */

/* The postcode block sliding in under the method cards (U9): Alpine's
   x-transition classes from the template. */
.cateros-wizard__s3-slide-enter {
	transition: opacity 220ms ease, transform 220ms ease;
}

.cateros-wizard__s3-slide-start {
	opacity: 0;
	transform: translateY(-8px);
}

.cateros-wizard__s3-slide-end {
	opacity: 1;
	transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
	.cateros-wizard__s3-slide-enter {
		transition: none;
	}
}

.cateros-wizard__error {
	margin: 0.35rem 0 0;
	font-size: 0.875rem;
	font-weight: 600;
	color: var(--cateros-danger, #b91c1c);
}

.cateros-wizard__error--block {
	margin-top: 0.75rem;
}

.cateros-wizard__feedback {
	margin: 0.4rem 0 0;
	font-size: 0.8125rem;
	font-weight: 600;
}

.cateros-wizard__feedback--ok {
	color: #15803d;
}

/* Out-of-area is ADVISORY: the order goes through and the caterer quotes the
   journey by hand. It is deliberately NOT --cateros-danger — red would say the
   address was rejected, which is the behaviour this replaced.

   --cateros-text rather than a new warning token: it is the body-copy colour, so
   its contrast is already whatever body copy's is on every background the wizard
   uses, and no token had to be invented to carry one notice. The brand token was
   the obvious alternative and was rejected — at the default #ff9500 it is about
   2.1:1 on white, far below AA for text.

   (.cateros-wizard__feedback--bad, the red variant this replaces, was removed:
   its only user was this paragraph.) */
.cateros-wizard__feedback--notice {
	color: var(--cateros-text, #1f2937);
}

/* Separated stepper (reference proportions): round +/- buttons flanking a
   rounded value box, rather than one fused pill. */
/* align-items: center was already here; the misalignment came from a box-sizing
   mismatch — the buttons were content-box 44px (46px with border) while the input
   was min-height 44px PLUS 16px padding PLUS 2px border = 62px. border-box on all
   three makes every box resolve to the same 44px, so they share a centre line.
   min-height (not height) keeps them growable if surrounding text scales. */
.cateros-wizard__qty {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	border: 0;
	background: transparent;
}

.cateros-wizard__qty-btn,
.cateros-wizard__qty-input {
	box-sizing: border-box;
	min-height: 44px;
}

.cateros-wizard .cateros-wizard__qty-btn {
	width: 44px;
	flex-shrink: 0;
	/* Glyph centring: the button was relying on the UA's default button text
	   centring plus padding, and border-box (added last round) made the leftover
	   horizontal padding asymmetric against the circle. Flex centring with zero
	   padding puts the − / + on the true centre, with no margin/text-indent nudge. */
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	line-height: 1;
	border: 1px solid var(--cateros-input-border);
	border-radius: 999px;
	background: #fff;
	font-size: 1.25rem;
	font-weight: 700;
	color: color-mix(in srgb, var(--cateros-text-strong) 75%, transparent);
	cursor: pointer;
	box-shadow: 0 4px 14px color-mix(in srgb, var(--cateros-text, #1f2937) 6%, transparent);
	transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

/* Sized in em so it scales with the button's font-size if the control grows.
   currentColor means it inherits the button's colour token, including the
   brand-coloured hover state — no hardcoded fill anywhere. */
.cateros-wizard__qty-ico {
	width: 1em;
	height: 1em;
	display: block;
	flex-shrink: 0;
}

.cateros-wizard .cateros-wizard__qty-btn:hover:not(:disabled) {
	border-color: var(--cateros-primary) !important;
	color: var(--cateros-primary) !important;
	background: #fff !important;
	background-color: #fff !important;
}

.cateros-wizard__qty-btn:disabled {
	opacity: 0.45;
	cursor: not-allowed;
}

/* .cateros-wizard prefix (U5a): the bare class (0,1,0) lost the border to the
   theme reset's input[type=number] (0,1,1) — the guests box was the one field
   still wearing the theme's #666. */
.cateros-wizard .cateros-wizard__qty-input {
	width: 4.5rem;
	border: 1px solid var(--cateros-input-border);
	border-radius: var(--cateros-ui-radius);
	background: #fff;
	text-align: center;
	font-size: 1rem;
	font-weight: 800;
	font-variant-numeric: tabular-nums;
	padding-block: 8px;
	padding-inline: 4px;
}

.cateros-wizard__qty-input:focus {
	outline: none;
}

/* The cards live in a <template x-for>, so they do not exist in the served HTML
   and appear only once Alpine renders — everything around them paints first, and
   the grid collapsing from 0 to its real height is the shift you see.

   min-height reserves ONE ROW: one card (104px) plus nothing, since a single row
   has no gap. That is the largest reservation that is correct for every site,
   because the row count depends on how many event types the caterer configured
   and on the breakpoint (2 / 3 / 4 columns), and CSS alone cannot know the count.
   It removes the collapse; it does not remove the whole shift for a catalogue
   that wraps onto a second row. See the report for what exact matching costs.

   When no event types are configured the whole field is display:none via x-show,
   so this reserves nothing and leaves no gap. */
.cateros-wizard__event-types {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 10px;
	margin-top: 0.25rem;
	min-height: 104px;
}

@media (min-width: 900px) {
	.cateros-wizard__event-types {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}

@media (min-width: 720px) and (max-width: 899.98px) {
	.cateros-wizard__event-types {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

/* Cards stretch to the tallest in the row (grid default), so a 2-line translated
   label grows the whole row evenly. Icon sits on top, label wraps beneath. */
.cateros-wizard .cateros-wizard__event-card {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: flex-start;
	gap: 8px;
	text-align: center;
	width: 100%;
	/* No height at all — grid items stretch to the row by default, so the tallest
	   (longest-label) card sets the row and its neighbours match. */
	min-height: 104px;
	padding-block: 18px 14px;
	padding-inline: 10px;
	border-radius: var(--cateros-radius-card);
	border: 1px solid var(--cateros-border, #e5e7eb);
	background: #fff;
	cursor: pointer;
	/* The card became a <label> wrapping a clipped radio (it was a <button>).
	   A button does not inherit the page font and a label does, so without this
	   the family could shift on a theme that never normalised buttons. Mirrors
	   the identical declaration on .cateros-wizard__serving-card. */
	font: inherit;
	color: inherit;
	box-shadow: 0 4px 14px color-mix(in srgb, var(--cateros-text, #1f2937) 6%, transparent);
	transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.14s ease, background 0.15s ease;
}

/* Hover keeps the card light and lifts it — the !important overrides exist
   because themes repaint bare <button> backgrounds. */
.cateros-wizard .cateros-wizard__event-card:hover:not(.is-selected) {
	border-color: var(--cateros-primary) !important;
	background: #fff !important;
	background-color: #fff !important;
	transform: translateY(-2px);
	box-shadow: 0 8px 20px var(--cateros-primary-glow);
}

.cateros-wizard .cateros-wizard__event-card:hover:not(.is-selected) .cateros-wizard__event-card-label,
.cateros-wizard .cateros-wizard__event-card:hover:not(.is-selected) .cateros-wizard__event-card-icon-inner {
	color: color-mix(in srgb, var(--cateros-primary) 45%, black) !important;
}

/* Selected: tinted fill + brand border + brand label (not a solid fill), so the
   artwork and text keep their contrast against a light surface. */
.cateros-wizard .cateros-wizard__event-card.is-selected,
.cateros-wizard .cateros-wizard__event-card.is-selected:hover {
	border-color: var(--cateros-primary) !important;
	background: var(--cateros-primary-subtle, color-mix(in srgb, var(--cateros-primary, #2271B1) 8%, transparent)) !important;
	background-color: var(--cateros-primary-subtle, color-mix(in srgb, var(--cateros-primary, #2271B1) 8%, transparent)) !important;
	box-shadow: 0 4px 14px var(--cateros-primary-glow);
}

.cateros-wizard .cateros-wizard__event-card.is-selected .cateros-wizard__event-card-label,
.cateros-wizard .cateros-wizard__event-card.is-selected .cateros-wizard__event-card-icon-inner,
.cateros-wizard .cateros-wizard__event-card.is-selected:hover .cateros-wizard__event-card-label,
.cateros-wizard .cateros-wizard__event-card.is-selected:hover .cateros-wizard__event-card-icon-inner {
	color: color-mix(in srgb, var(--cateros-primary) 45%, black) !important;
}

/* Icon tile: a brand-tinted disc behind the per-type dashicon, so the monoline
   glyph reads as deliberate artwork rather than a bare symbol. The icon itself
   comes from the event type's stored `icon` column — see eventTypeIconClass(). */
.cateros-wizard__event-card-icon {
	display: grid;
	place-items: center;
	flex-shrink: 0;
	width: 44px;
	height: 44px;
	border-radius: 999px;
	background: var(--cateros-primary-subtle, color-mix(in srgb, var(--cateros-primary, #2271B1) 8%, transparent));
}

.cateros-wizard__event-card-icon-inner {
	font-size: 1.25rem;
	line-height: 1;
	color: var(--cateros-primary);
}

.cateros-wizard__event-card-icon-inner.dashicons {
	font-size: 24px;
	width: 24px;
	height: 24px;
	color: var(--cateros-primary);
}

.cateros-wizard__event-card.is-selected .cateros-wizard__event-card-icon {
	background: color-mix(in srgb, var(--cateros-primary, #2271B1) 18%, transparent);
}

.cateros-wizard__event-card-icon-inner--text {
	font-size: 1.125rem;
}

.cateros-wizard__event-card-label {
	font-size: 0.8125rem;
	font-weight: 700;
	line-height: 1.35;
	color: color-mix(in srgb, var(--cateros-text-strong) 88%, transparent);
	/* Translated labels wrap instead of clipping; long single words break. */
	overflow-wrap: anywhere;
	hyphens: auto;
	max-width: 100%;
}

/* Step 3: extras */
.cateros-wizard__extras-block {
	margin-bottom: 1.75rem;
	min-width: 0;
	max-width: 100%;
	overflow: visible;
}

.cateros-wizard__extras-block .cateros-wizard__label {
	margin-bottom: 0.5rem;
}

.cateros-wizard__textarea {
	display: block;
	width: 100%;
	max-width: 100%;
	padding: 12px;
	border-radius: var(--cateros-ui-radius);
	border: 1px solid var(--cateros-input-border);
	background: #fff;
	font-family: inherit;
	font-size: 0.9375rem;
	line-height: 1.45;
	color: color-mix(in srgb, var(--cateros-text-strong) 90%, transparent);
	resize: vertical;
	min-height: 120px;
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.cateros-wizard__textarea:focus {
	outline: none;
	border-color: var(--cateros-primary, #2271B1);
	box-shadow: 0 0 0 3px var(--cateros-primary-ring, color-mix(in srgb, #2271B1 15%, transparent));
}

.cateros-wizard__textarea--notes {
	max-width: 42rem;
}

.cateros-wizard__serving-cards {
	display: grid;
	grid-template-columns: 1fr;
	grid-auto-rows: minmax(min-content, max-content);
	gap: 8px;
	margin-top: 0.3rem;
	min-width: 0;
	align-items: stretch;
}

@media (min-width: 720px) {
	.cateros-wizard__serving-cards {
		grid-template-columns: repeat(3, minmax(0, 1fr));
		gap: 10px;
	}
}

.cateros-wizard .cateros-wizard__serving-card {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	justify-content: flex-start;
	gap: 0.25rem;
	text-align: left;
	width: 100%;
	max-width: 100%;
	min-width: 0;
	min-height: 0;
	/* overflow: hidden removed — it would clip a wrapped description. Cards have
	   no fixed height, so they simply grow and the grid stretches the row. */
	white-space: normal;
	gap: 0.4rem;
	padding-block: 12px;
	padding-inline: 14px;
	border-radius: var(--cateros-ui-radius);
	border: 1px solid var(--cateros-border, #e5e7eb);
	background: #fff;
	cursor: pointer;
	font: inherit;
	color: inherit;
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

/* Round 7: mirrors the approved Event Type card treatment exactly — light card,
   brand border, brand text. The values are MIRRORED rather than shared: the two
   components have different element names (__event-card-label vs
   __serving-card-title/-desc/-fee) and different internal structure, so a shared
   rule would mean either restructuring markup or a selector list long enough to
   defeat the point. Same tokens throughout, no parallel ones.
   This removes the dark fill entirely, which is what made the white-text
   machinery (and its hover/selected divergence) necessary in the first place. */
.cateros-wizard .cateros-wizard__serving-card:hover:not(.is-selected) {
	border-color: var(--cateros-primary) !important;
	background: #fff !important;
	background-color: #fff !important;
	transform: translateY(-2px);
	box-shadow: 0 8px 20px var(--cateros-primary-glow);
}

.cateros-wizard .cateros-wizard__serving-card.is-selected,
.cateros-wizard .cateros-wizard__serving-card.is-selected:hover {
	border-color: var(--cateros-primary) !important;
	background: var(--cateros-primary-subtle, color-mix(in srgb, var(--cateros-primary, #2271B1) 8%, transparent)) !important;
	background-color: var(--cateros-primary-subtle, color-mix(in srgb, var(--cateros-primary, #2271B1) 8%, transparent)) !important;
	box-shadow: 0 4px 14px var(--cateros-primary-glow);
}

/* Title takes the brand colour in both states, exactly as the event card's label
   does. Description and fee keep their normal muted tokens — the card stays
   light, so they remain legible and no white-text override is needed anywhere. */
.cateros-wizard .cateros-wizard__serving-card:hover:not(.is-selected) .cateros-wizard__serving-card-title,
.cateros-wizard .cateros-wizard__serving-card.is-selected .cateros-wizard__serving-card-title,
.cateros-wizard .cateros-wizard__serving-card.is-selected:hover .cateros-wizard__serving-card-title {
	color: color-mix(in srgb, var(--cateros-primary) 45%, black) !important;
}

.cateros-wizard__serving-card-title {
	font-size: 0.8125rem;
	font-weight: 700;
	line-height: 1.3;
	color: color-mix(in srgb, var(--cateros-text-strong) 90%, transparent);
	width: 100%;
	max-width: 100%;
	overflow-wrap: anywhere;
	word-break: break-word;
}

/* Item 4a: matched to the intro line (0.9375rem, same colour expressed via
   --cateros-text). The nowrap/overflow/text-overflow trio that produced the "…"
   truncation is gone — a longer or translated description wraps to as many lines
   as it needs, and the grid stretches the cards to match. */
.cateros-wizard__serving-card-desc {
	display: block;
	flex-shrink: 0;
	font-size: 0.875rem;
	line-height: 1.55;
	/* 72%, not the 64% used by .cateros-wizard__hint. The selected card swaps its
	   white fill for --cateros-primary-subtle, and 64% composited over that tint
	   measured 4.47:1 — just under AA — while the same text on the white resting
	   card measured 4.58:1. There is no selected-state colour override for this
	   element (it has exactly one colour rule), so the drop came entirely from the
	   background change. Raising the single shared value fixes the selected state
	   without introducing a state-specific override, and keeps both states
	   identical. 72% is the value .cateros-wizard__serving-card-fee already uses,
	   so no new step enters the scale. Verified >= 5.5:1 on the selected tint for
	   all seven brand colours. */
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 72%, transparent);
	margin: 0;
	width: 100%;
	max-width: 100%;
	overflow-wrap: anywhere;
}

/* Item 5 polish: the fee reads as a scannable badge rather than prose. Styling
   only — the translatable label and wizardFormatMoney() output are untouched. */
.cateros-wizard__serving-card-fee {
	display: inline-flex;
	align-items: baseline;
	gap: 0.3rem;
	flex-shrink: 0;
	width: auto;
	max-width: 100%;
	margin-top: auto;
	padding-block: 3px;
	padding-inline: 10px;
	border-radius: 999px;
	background: var(--cateros-primary-tint);
	font-size: 0.8125rem;
	line-height: 1.35;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 72%, transparent);
	overflow-wrap: anywhere;
}

/* The amount sits heavier than its "Fee:" prefix in both pills. Shared selector
   list rather than a second rule, so the two card groups cannot drift apart. */
.cateros-wizard__serving-card-fee strong,
.cateros-wizard__fulfillment-fee strong {
	font-weight: 800;
}

/* Card is light in every state now, so the badge keeps dark text throughout and
   only deepens its tint when selected — enough to stay visible against the
   card's own tinted fill without needing a light-on-dark flip. */
.cateros-wizard .cateros-wizard__serving-card.is-selected .cateros-wizard__serving-card-fee,
.cateros-wizard .cateros-wizard__serving-card.is-selected:hover .cateros-wizard__serving-card-fee {
	background: color-mix(in srgb, var(--cateros-primary) 16%, white);
}

/* ── Fulfillment method cards ────────────────────────────────────────────────
   Mirrors .cateros-wizard__serving-card: same radius token, same border, same
   padding rhythm, same light-tint-plus-brand-border selected state, same fee
   pill. Values are COPIED from that component rather than rechosen — its
   selected tint had a contrast pass done on it (the description colour had to
   go 64% -> 72% because 64% over the tint measured 4.47:1), and picking fresh
   numbers here would quietly throw that work away. Never a solid brand fill:
   that is the pattern Serving Style was moved OFF, and it is what forced the
   white-text machinery it no longer needs.

   Structurally different from its two neighbours, which are <button>s: these are
   real <input type="radio"> inside <label>, which is why the group already had
   correct keyboard behaviour before it had any styling. The radio is clipped
   with .cateros-wizard__sr-only (never display:none, which would drop it out of
   the tab order and the a11y tree) and the label is painted as the card.

   No forced overrides anywhere in this block: the neighbours need them because
   themes repaint bare <button> backgrounds, and a <label> is not repainted by
   anything on the page — the only screen rule that reaches ours is
   `label { line-height: 1 }`, which the line-height below answers at (0,2,0)
   on its own. */
.cateros-wizard__fulfillment {
	display: grid;
	grid-template-columns: 1fr;
	grid-auto-rows: minmax(min-content, max-content);
	gap: 8px;
	margin-top: 0.3rem;
	min-width: 0;
	align-items: stretch;
}

@media (min-width: 720px) {
	.cateros-wizard__fulfillment {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 10px;
	}
}

.cateros-wizard .cateros-wizard__fulfillment-option {
	/* Anchors the clipped radio inside its own card rather than the page. */
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	justify-content: flex-start;
	gap: 0.4rem;
	text-align: left;
	width: 100%;
	max-width: 100%;
	min-width: 0;
	min-height: 0;
	white-space: normal;
	/* Answers the theme reset's `label { line-height: 1 }`, which would jam a
	   wrapped two-line label against itself. No fixed height anywhere: the grid
	   stretches the row, so the longest translated label sets it and its
	   neighbour matches. */
	line-height: 1.45;
	padding-block: 12px;
	padding-inline: 14px;
	border-radius: var(--cateros-ui-radius);
	border: 1px solid var(--cateros-border, #e5e7eb);
	background: #fff;
	cursor: pointer;
	font: inherit;
	color: inherit;
	transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.cateros-wizard .cateros-wizard__fulfillment-option:hover:not(.cateros-wizard__fulfillment-option--active) {
	border-color: var(--cateros-primary);
	transform: translateY(-2px);
	box-shadow: 0 8px 20px var(--cateros-primary-glow);
}

.cateros-wizard .cateros-wizard__fulfillment-option--active,
.cateros-wizard .cateros-wizard__fulfillment-option--active:hover {
	border-color: var(--cateros-primary);
	background: var(--cateros-primary-subtle, color-mix(in srgb, var(--cateros-primary, #2271B1) 8%, transparent));
	box-shadow: 0 4px 14px var(--cateros-primary-glow);
}

/* Same 90% of --cateros-text as .cateros-wizard__serving-card-title, written as
   a token mix rather than that rule's literal rgba(17, 24, 39, 0.9): identical
   colour on the default palette, but it follows a rebrand, and it matches how
   -card-desc and -card-fee in the same component already express their tints. */
.cateros-wizard__fulfillment-label {
	font-size: 0.8125rem;
	font-weight: 700;
	line-height: 1.3;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 90%, transparent);
	width: 100%;
	max-width: 100%;
	overflow-wrap: anywhere;
	word-break: break-word;
}

.cateros-wizard .cateros-wizard__fulfillment-option:hover:not(.cateros-wizard__fulfillment-option--active) .cateros-wizard__fulfillment-label,
.cateros-wizard .cateros-wizard__fulfillment-option--active .cateros-wizard__fulfillment-label,
.cateros-wizard .cateros-wizard__fulfillment-option--active:hover .cateros-wizard__fulfillment-label {
	color: color-mix(in srgb, var(--cateros-primary) 45%, black);
}

/* margin-top: auto is the load-bearing line — it pins the pill to the card floor,
   so when one label wraps to two lines both fees still sit on the same baseline
   instead of drifting apart. 72%, not 64%, for the reason recorded on
   .cateros-wizard__serving-card-desc: 64% over the selected tint fails AA. */
.cateros-wizard__fulfillment-fee {
	display: inline-flex;
	align-items: baseline;
	gap: 0.3rem;
	flex-shrink: 0;
	width: auto;
	max-width: 100%;
	margin-top: auto;
	padding-block: 3px;
	padding-inline: 10px;
	border-radius: 999px;
	background: var(--cateros-primary-tint);
	font-size: 0.8125rem;
	line-height: 1.35;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 72%, transparent);
	overflow-wrap: anywhere;
}

.cateros-wizard .cateros-wizard__fulfillment-option--active .cateros-wizard__fulfillment-fee,
.cateros-wizard .cateros-wizard__fulfillment-option--active:hover .cateros-wizard__fulfillment-fee {
	background: color-mix(in srgb, var(--cateros-primary) 16%, white);
}

/* Single configured method: no choice to present, so no radio and no card — just
   the method named, with the SAME fee pill the cards use so "Free" and a
   formatted amount read identically wherever they appear. The pill's
   margin-top: auto is reset because here it sits in a centred row, not at the
   bottom of a column. */
.cateros-wizard__fulfillment-single {
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	gap: 0.5rem;
}

.cateros-wizard__fulfillment-single .cateros-wizard__fulfillment-fee {
	margin-top: 0;
}

/* Pickup address under the group: a detail OF the selection, not a system
   message. Same muted 72% the fee pill uses, so it reads as supporting copy
   rather than as the postcode checker's feedback, which shares the base class. */
.cateros-wizard__feedback--detail {
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 72%, transparent);
}

/* Screen reader–only headings */
.cateros-wizard__sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* Thank You screen.
   Text derives from --cateros-text, never from --cateros-success: deriving both
   text and background from one token caps contrast at that hue, which read
   2.68:1 on the plugin default and 1.97:1 on the original literal — unreadable
   out of the box. Emphasis comes from size and weight instead.
   No fixed heights and no truncation anywhere: labels run 30-40% longer in some
   languages and must be free to wrap. */
/* Centred composition: heading, reference line, what-happens-next, contact
   details, action. The panel is full width here, so the content is held to a
   readable measure and centred within it rather than stretched across. */
.cateros-wizard__success {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 1.25rem;
	min-width: 0;
	width: 100%;
	max-width: 34rem;
	margin-inline: auto;
	text-align: center;
}

/* The one large heading of the composition. Larger than .cateros-wizard__panel-title
   because it is not a step label competing with a progress nav — the nav is gone
   and this is the only heading on the screen. clamp() keeps it from dominating a
   narrow phone; no fixed height, so a long translation simply wraps. */
.cateros-wizard__success-title {
	margin: 0;
	padding: 0;
	font-size: clamp(1.375rem, 1.15rem + 1vw, 1.75rem);
	font-weight: 800;
	letter-spacing: -0.02em;
	line-height: 1.3;
	color: var(--cateros-text, #1f2937);
}

.cateros-wizard__success-reference {
	margin: -0.75rem 0 0;
	font-size: 0.9375rem;
	line-height: 1.55;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 78%, transparent);
}

/* .cateros-wizard__review-block supplies the card; these only set the rhythm. */
.cateros-wizard__success-next {
	margin-bottom: 0;
	width: 100%;
}

.cateros-wizard__success-next-title,
.cateros-wizard__success-contact-title {
	margin: 0 0 0.4rem;
	font-size: 0.9375rem;
	font-weight: 700;
	line-height: 1.35;
	color: var(--cateros-text, #1f2937);
}

.cateros-wizard__success-next-text {
	margin: 0;
	font-size: 0.9375rem;
	line-height: 1.55;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 82%, transparent);
}

.cateros-wizard__success-contact {
	width: 100%;
}

.cateros-wizard__success-contact-list {
	margin: 0;
	display: flex;
	flex-direction: column;
	gap: 0.35rem;
}

/* Centred rows, NOT the review-dl label column. That pattern gives dt a 5.5rem
   min-width so values line up on a shared left edge — which is exactly what makes
   a centred block look wrong, because each row then sits off-centre by a
   different amount. Here label and value are one centred inline pair that wraps
   together when a translation is long. */
.cateros-wizard__success-contact-list div {
	margin: 0;
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	column-gap: 0.5rem;
	row-gap: 0.1rem;
	align-items: baseline;
	min-width: 0;
}

.cateros-wizard__success-contact-list dt {
	margin: 0;
	flex: 0 0 auto;
	font-weight: 600;
	font-size: 0.875rem;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 70%, transparent);
}

.cateros-wizard__success-contact-list dd {
	margin: 0;
	min-width: 0;
	font-size: 0.9375rem;
	/* A long email address breaks rather than widening the panel. */
	overflow-wrap: anywhere;
}

.cateros-wizard__success-contact-list a {
	color: var(--cateros-primary);
	text-decoration: underline;
}

.cateros-wizard__success-reply {
	margin: 0;
	font-size: 0.875rem;
	line-height: 1.55;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 68%, transparent);
}

.cateros-wizard__success-actions {
	margin: 0.25rem 0 0;
}

/* Inherits .cateros-wizard__btn--primary; only what an <a> needs differs from a
   <button>. No fixed width — the label sets it, so a longer translation grows
   the button instead of being cut. */
.cateros-wizard__success-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	text-decoration: none;
	padding-inline: 1.5rem;
	max-width: 100%;
}

.cateros-wizard__review-section {
	margin-bottom: 2rem;
	padding-bottom: 1.75rem;
	border-bottom: 1px solid color-mix(in srgb, var(--cateros-text, #1f2937) 8%, transparent);
}

.cateros-wizard__review-section:last-of-type {
	border-bottom: none;
	padding-bottom: 0;
	margin-bottom: 0;
}

.cateros-wizard__review-heading {
	font-size: 1.125rem;
	font-weight: 800;
	margin: 0 0 1rem;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 90%, transparent);
}

.cateros-wizard__review-block {
	margin-bottom: 1.25rem;
	padding: 1rem;
	border-radius: var(--cateros-ui-radius);
	border: 1px solid color-mix(in srgb, var(--cateros-text, #1f2937) 10%, transparent);
	background: var(--cateros-primary-tint);
	min-width: 0;
	overflow: hidden;
}

.cateros-wizard__review-block-title {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem;
	margin-bottom: 0.6rem;
	font-size: 0.8125rem;
	font-weight: 800;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 68%, transparent);
	min-width: 0;
	overflow-wrap: anywhere;
}

.cateros-wizard .cateros-wizard__review-edit {
	border: none;
	background: transparent;
	padding: 0;
	font-size: inherit;
	font-weight: 700;
	color: var(--cateros-primary, #2271B1);
	text-decoration: underline;
	cursor: pointer;
	flex-shrink: 0;
}

.cateros-wizard__review-edit:hover {
	color: color-mix(in srgb, var(--cateros-primary, #2271B1) 45%, black);
}

.cateros-wizard__review-dl {
	margin: 0;
	display: flex;
	flex-direction: column;
	gap: 0.5rem;
}

.cateros-wizard__review-dl div {
	margin: 0;
	display: flex;
	flex-wrap: wrap;
	column-gap: 0.85rem;
	row-gap: 0.15rem;
	align-items: baseline;
	min-width: 0;
}

.cateros-wizard__review-dl dt {
	margin: 0;
	flex: 0 0 auto;
	min-width: 5.5rem;
	font-weight: 600;
	font-size: 0.875rem;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 70%, transparent);
	word-break: normal;
	overflow-wrap: anywhere;
}

.cateros-wizard__review-dl dd {
	margin: 0;
	flex: 1 1 auto;
	min-width: 12rem;
	font-size: 0.8125rem;
	font-weight: 600;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 88%, transparent);
	overflow-wrap: anywhere;
	word-break: break-word;
}

.cateros-wizard__review-text {
	margin: 0;
	font-size: 0.8125rem;
	line-height: 1.45;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 88%, transparent);
	overflow-wrap: anywhere;
	word-break: break-word;
	min-width: 0;
	max-width: 100%;
}

.cateros-wizard__review-text--pre {
	white-space: pre-wrap;
}

/* Prefixed for the same reason — see .cateros-wizard__progress-list. */
.cateros-wizard .cateros-wizard__review-lines {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 0.65rem;
}

.cateros-wizard__review-line {
	display: flex;
	flex-wrap: wrap;
	column-gap: 0.65rem;
	row-gap: 0.2rem;
	padding-bottom: 0.65rem;
	border-bottom: 1px dashed color-mix(in srgb, var(--cateros-text, #1f2937) 10%, transparent);
	align-items: baseline;
	min-width: 0;
}

.cateros-wizard__review-line:last-child {
	border-bottom: none;
	padding-bottom: 0;
}

.cateros-wizard__review-line-name {
	flex: 1 1 100%;
	font-weight: 700;
	font-size: 0.875rem;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 90%, transparent);
	overflow-wrap: anywhere;
	word-break: break-word;
	min-width: 0;
}

.cateros-wizard__review-line-sub {
	flex: 1 1 100%;
	font-size: 0.875rem;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 70%, transparent);
	overflow-wrap: anywhere;
	word-break: break-word;
	min-width: 0;
	margin-top: 0.08rem;
}

.cateros-wizard__review-line-meta {
	flex: 0 0 auto;
	display: inline-flex;
	gap: 0.5rem;
	align-items: center;
	font-variant-numeric: tabular-nums;
	font-weight: 600;
	font-size: 0.8125rem;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 70%, transparent);
	max-width: 100%;
	flex-wrap: wrap;
}

.cateros-wizard__subhead {
	margin: 1.25rem 0 0.5rem;
	font-size: 0.9375rem;
	font-weight: 800;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 84%, transparent);
}

.cateros-wizard__req {
	font-weight: 900;
	color: var(--cateros-danger, #b91c1c);
}

.cateros-wizard__check {
	display: inline-flex;
	align-items: flex-start;
	gap: 0.5rem;
	font-size: 0.8125rem;
	line-height: 1.45;
	cursor: pointer;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 85%, transparent);
	overflow-wrap: anywhere;
	max-width: 100%;
}

.cateros-wizard__check input {
	margin-top: 0.2rem;
	flex-shrink: 0;
	accent-color: var(--cateros-primary, #2271B1);
}

.cateros-wizard__field--inline-check {
	margin-bottom: 0.75rem;
}

.cateros-wizard__field--consent {
	margin-bottom: 0.85rem;
}

.cateros-wizard__inline-link {
	color: var(--cateros-primary, #2271B1);
	font-weight: 700;
	word-break: break-word;
}

.cateros-wizard__input[readonly],
.cateros-wizard__input:read-only {
	background: color-mix(in srgb, var(--cateros-text, #1f2937) 4%, transparent);
	cursor: default;
	opacity: 0.95;
}

.cateros-wizard__review-legal {
	margin: 0 0 1rem;
	max-width: 44rem;
	font-size: 0.8125rem;
	line-height: 1.5;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 60%, transparent);
}

.cateros-wizard__btn--submit {
	min-width: 14rem;
}

.cateros-wizard__postcode-row {
	display: flex;
	align-items: center;
	gap: 10px;
	flex-wrap: wrap;
}

.cateros-wizard__postcode-status {
	display: grid;
	place-items: center;
	font-size: 1rem;
	font-weight: 800;
	min-width: 28px;
}

.cateros-wizard__postcode-status--ok {
	color: #15803d;
}

/* Matches the notice paragraph below the field — same reasoning, same token.
   (.cateros-wizard__postcode-status--bad, the red ✕ variant, was removed: its
   only user was the out-of-area marker.) */
.cateros-wizard__postcode-status--notice {
	color: var(--cateros-text, #1f2937);
}

.cateros-wizard__spinner {
	width: 20px;
	height: 20px;
	border: 2px solid color-mix(in srgb, var(--cateros-text-strong) 12%, transparent);
	border-top-color: var(--cateros-primary, #2271B1);
	border-radius: 50%;
	animation: cateros-wiz-spin 0.7s linear infinite;
}

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

/* Both Back/Next rows now live inside the fixed .cateros-wizard__bar (only one
   is shown at a time — their x-show conditions are complementary), so the row
   fills the bar instead of carrying its old in-flow top margin. */
.cateros-wizard__nav {
	display: flex;
	align-items: center;
	gap: 10px;
	flex: 1 1 auto;
	min-width: 0;
}

.cateros-wizard__nav-spacer {
	flex: 1;
}

/* =========================
   Fixed bottom bar (2026-09-13)
   ========================= */

/* Pinned to the viewport, SURFACE edge to edge: left/right: 0 at every width,
   no rounded corners. The content aligns through .cateros-wizard__bar-inner —
   alignWizardBar() in wizard.js sizes that wrapper to .cateros-wizard__layout
   above 782px (a fixed box cannot take the container's width from CSS alone);
   at or below 782px the wrapper is simply full width with its own padding.
   z-index 9999: above the mobile order-summary bar (999); the site runs no
   cookie-notice plugin today, and common ones sit at or below this — raise
   here if one ever covers the bar. Top hairline + soft upward shadow make it
   read as a paper surface above the content. */
.cateros-wizard__bar {
	position: fixed;
	bottom: 0;
	left: 0;
	right: 0;
	z-index: 9999;
	box-sizing: border-box;
	display: block;
	/* 60px target: 1px border + 9px + 40px buttons + 9px = 59, min-height
	   tops it up to exactly 60. */
	min-height: 60px;
	padding-block: 9px;
	padding-bottom: calc(9px + env(safe-area-inset-bottom, 0px));
	background: #fff;
	border-top: 1px solid var(--cateros-border, #e5e7eb);
	box-shadow: 0 -4px 16px rgba(0, 0, 0, 0.06);
}

/* The aligned content row. Above 782px alignWizardBar() sets margin-left and
   width inline to match the planner layout, so Back and Next sit exactly on
   the grid's edges; without JS (and at or below 782px) it is a full-width
   padded row. */
.cateros-wizard__bar-inner {
	position: relative;
	display: flex;
	align-items: center;
	box-sizing: border-box;
	width: 100%;
	min-height: 40px;
	padding-inline: 16px;
}

@media (min-width: 783px) {
	.cateros-wizard__bar-inner {
		padding-inline: 0;
	}
}

/* 40px-tall controls inside the bar: the ghost Back and the primary Next both
   drop from their in-flow sizes (the primary's 48px min-height and the shared
   10px padding are page-level rules) so the bar can hold its 60px line. The
   .cateros-wizard prefix is load-bearing: it out-specifies the later shared
   .cateros-wizard .cateros-wizard__btn padding rule. 7px + 24px line + 1px
   border each side = 40 exactly; min-height covers a shorter content box. */
.cateros-wizard .cateros-wizard__bar .cateros-wizard__btn {
	min-height: 40px;
	padding-block: 7px;
}

.cateros-wizard .cateros-wizard__bar .cateros-wizard__btn--primary {
	min-height: 40px;
	padding-block: 7px;
	padding-inline: 22px;
}

/* Centred summary. Absolute, so it centres on the aligned content row (its
   containing block is .cateros-wizard__bar-inner) regardless of how wide Back
   and Next happen to be; the ellipsis keeps a long menu-group Next label from
   colliding with it at mid widths. */
.cateros-wizard__bar-mid {
	position: absolute;
	left: 50%;
	top: 50%;
	transform: translate(-50%, -50%);
	max-width: min(46%, 420px);
	text-align: center;
	min-width: 0;
	/* Flex column, centred (U4b): summary and minimum line stack with equal
	   whitespace above and below whatever combination is showing. */
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
}

/* Muted line, strong amount: the item count reads quietly while the Total
   figure carries the heading colour at 600 — the same loud/quiet split the
   mobile order-summary bar uses. */
.cateros-wizard__bar-line {
	display: block;
	font-size: 13px;
	font-weight: 500;
	line-height: 1.3;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 72%, transparent);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.cateros-wizard__bar-amount {
	font-weight: 600;
	color: var(--cateros-text-strong, var(--cateros-text, #1f2937));
}

/* Only one form of the summary is ever displayed (a11y: nothing reads twice):
   the full "N items · Total" line from 1024px up, the drawer BUTTON — chevron
   + "N dishes · Total …" — at every width below (U4: the widths where the
   order drawer exists). */
.cateros-wizard__bar-sum {
	display: none;
	align-items: center;
	gap: 6px;
	max-width: 100%;
	padding: 4px 6px;
	margin: 0;
	cursor: pointer;
	border-radius: 8px;
}

/* THEME RESET (U4b): a bare <button> inside the bar is fair game for theme
   and WooCommerce globals (Hello Elementor's `button, [type=button]` reset
   and the Elementor kit's `.elementor-kit-N button` state rules, both of
   which paint background/border/box-shadow on hover and focus). All four
   states are pinned in one 0,3,0 selector list — heavier than the kit's
   0,1,1 — so no !important is needed. Hover gets its tint in the LATER rule
   below (same specificity, source order wins); focus-visible keeps the
   planner's shared outline ring, which nothing here touches. */
.cateros-wizard .cateros-wizard__bar .cateros-wizard__bar-sum,
.cateros-wizard .cateros-wizard__bar .cateros-wizard__bar-sum:hover,
.cateros-wizard .cateros-wizard__bar .cateros-wizard__bar-sum:focus,
.cateros-wizard .cateros-wizard__bar .cateros-wizard__bar-sum:active {
	appearance: none;
	-webkit-appearance: none;
	background: transparent;
	background-color: transparent;
	border: 0;
	box-shadow: none;
	color: inherit;
	font: inherit;
	text-transform: none;
	letter-spacing: normal;
	text-decoration: none;
}

/* Subtle hover tint from the planner's own tokens (4% brand on white). */
.cateros-wizard .cateros-wizard__bar .cateros-wizard__bar-sum:hover {
	background: var(--cateros-primary-tint, #f2f6f9);
	background-color: var(--cateros-primary-tint, #f2f6f9);
}

.cateros-wizard__bar-sum-chev {
	width: 14px;
	height: 14px;
	flex: 0 0 auto;
	transition: transform 160ms ease;
}

/* Chevron flips down while the drawer is open. */
.cateros-wizard__bar-sum-chev.is-open {
	transform: rotate(180deg);
}

.cateros-wizard__bar-line--compact {
	display: block;
	min-width: 0;
}

@media (max-width: 1023.98px) {
	.cateros-wizard__bar-line--full {
		display: none;
	}

	.cateros-wizard__bar-sum {
		display: inline-flex;
	}
}

/* The cateros_wizard_bar_after_summary slot: one short extension line under
   the summary — 4px below it (on the container, so an empty slot adds no
   visible gap to the centred block). Sized here so any taker inherits the
   compact scale; truncates rather than growing the bar. */
.cateros-wizard__bar-ext {
	margin-top: 4px;
	/* Flex-column child (U4b): without this cap the ellipsis on the line
	   inside could never trigger. */
	max-width: 100%;
	min-width: 0;
}

.cateros-wizard__bar-ext > * {
	margin: 0;
	font-size: 12px;
	font-weight: 500;
	line-height: 1.4;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 72%, transparent);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* Ghost Back: the bar's only primary is Next. The icon rides the text
   baseline; the label span hides at ≤782px leaving an icon-only button whose
   accessible name stays "Back" via its aria-label. */
.cateros-wizard__bar-back-ico {
	width: 16px;
	height: 16px;
	flex: 0 0 auto;
}

/* Refused Next: 600ms shake + red ring, then both go with the class. The
   ring needs !important only because the primary button carries its own glow
   shadow. Announcement stays with the step's alert slot — this is visual. */
.cateros-wizard .cateros-wizard__btn.cateros-wizard__btn--nudge {
	animation: cateros-bar-nudge 600ms ease;
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--cateros-danger, #b91c1c) 60%, transparent) !important;
}

@keyframes cateros-bar-nudge {
	0%, 100% { transform: translateX(0); }
	20%, 60% { transform: translateX(-6px); }
	40%, 80% { transform: translateX(6px); }
}

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

/* The full/compact summary toggle MOVED to the 1023.98px block above (U4):
   the drawer button covers every width the drawer exists at. Only the
   icon-only Back and the tighter centre remain phone-width concerns. */
@media (max-width: 782px) {
	/* U10: Back keeps its text on phones — icon + "Back". */
	.cateros-wizard .cateros-wizard__bar-back {
		padding: 10px 12px;
	}

	.cateros-wizard__bar-mid {
		max-width: 40%;
	}
}

.cateros-wizard .cateros-wizard__btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	border-radius: var(--cateros-ui-radius);
	padding: 10px 14px;
	border: 1px solid var(--cateros-border, #e5e7eb);
	background: #fff;
	background-color: #fff;
	color: var(--cateros-text, #1f2937);
	font-weight: 800;
	cursor: pointer;
	transition: transform 140ms ease, box-shadow 140ms ease, border-color 140ms ease, background 140ms ease, color 140ms ease;
}

.cateros-wizard .cateros-wizard__btn:not(.cateros-wizard__btn--primary):hover,
.cateros-wizard .cateros-wizard__btn:not(.cateros-wizard__btn--primary):focus {
	transform: translateY(-1px);
	box-shadow: 0 2px 8px rgba(16, 24, 40, 0.06);
	background: #fff !important;
	background-color: #fff !important;
	border-color: var(--cateros-primary) !important;
	color: var(--cateros-primary) !important;
}

.cateros-wizard__btn:disabled,
.cateros-wizard__btn[disabled] {
	opacity: 0.55;
	cursor: not-allowed;
	transform: none;
	box-shadow: none;
}

/* Pill shape + brand glow. Stays in .cateros-wizard__nav — not relocated. */
.cateros-wizard .cateros-wizard__btn--primary {
	background: var(--cateros-primary);
	background-color: var(--cateros-primary);
	border-color: var(--cateros-primary);
	color: var(--cateros-btn-text);
	border-radius: 999px;
	/* min-height + auto width: a longer translated label widens or wraps the
	   button rather than clipping it. */
	min-height: 48px;
	height: auto;
	width: auto;
	white-space: normal;
	padding-block: 12px;
	padding-inline: 26px;
	box-shadow: 0 8px 20px var(--cateros-primary-glow);
}

.cateros-wizard__btn--primary:disabled {
	box-shadow: none;
}

.cateros-wizard .cateros-wizard__btn--primary:hover,
.cateros-wizard .cateros-wizard__btn--primary:focus {
	background: var(--cateros-primary) !important;
	background-color: var(--cateros-primary) !important;
	border-color: var(--cateros-primary) !important;
	color: var(--cateros-btn-text) !important;
}

/* =========================
   Pricing sidebar (desktop) + mobile sticky bar
   ========================= */

/* ONE white surface for the whole sidebar (reference structure): the gradient
   event card, the summary heading, the item list and the price rows all sit on
   this single card. Previously this rule + .cateros-pricing__header's tinted fill
   made the summary read as a second, nested card. */
.cateros-pricing__card {
	background: #fff;
	border: 1px solid var(--cateros-border, #e5e7eb);
	border-radius: var(--cateros-radius-outer);
	box-shadow: 0 16px 40px color-mix(in srgb, var(--cateros-text, #1f2937) 10%, transparent);
	padding: 24px;
	display: flex;
	flex-direction: column;
}

/* Sticky + internally scrolling. Flex-based: the card is a flex column and the
   item list takes flex: 1 with min-height: 0, so it absorbs the leftover space
   and scrolls; everything else is flex-shrink: 0 and stays visible.
   The one max-height is unavoidable and is viewport-relative, not a pixel value:
   a sticky box has no intrinsic height cap, so without it the card would grow to
   its content height and flex: 1 would have no leftover space to distribute —
   the list would never scroll. calc(100vh - 36px) matches the 18px sticky offset
   top and bottom, so the card never exceeds the viewport and the totals stay on
   screen no matter how many items are in the order. */
.cateros-pricing__card--desktop {
	position: sticky;
	top: var(--cateros-sticky-top, 18px);
	/* The whole card — event card, internally scrolling item list, totals,
	   extension line, note — fits between the sticky offset and the fixed
	   bottom bar, with 16px of breathing room above the bar. The item list
	   is the flex: 1 / min-height: 0 child, so IT absorbs the squeeze and
	   scrolls; the Total row below it stays visible at any viewport height.
	   No second scroll container: this max-height plus the list's own
	   overflow-y is the whole mechanism. */
	max-height: calc(100vh - var(--cateros-sticky-top, 18px) - var(--cateros-bar-h, 60px) - 16px);
}

/* Sidebar event summary — gradient built from the two existing brand tokens
   (--cateros-primary / --cateros-primary-dark), so no new gradient token was
   needed. Text wraps rather than overflowing when an event-type label is long. */
.cateros-pricing__event {
	border-radius: var(--cateros-radius-card);
	padding-block: 18px;
	padding-inline: 20px;
	margin-bottom: 18px;
	background: linear-gradient(135deg, var(--cateros-primary) 0%, var(--cateros-primary-dark) 100%);
	color: var(--cateros-btn-text);
	box-shadow: 0 8px 24px var(--cateros-primary-glow);
}

.cateros-pricing__event-top {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 12px;
}

.cateros-pricing__event-eyebrow {
	font-size: 12px;
	font-weight: 500;
	color: color-mix(in srgb, var(--cateros-btn-text) 80%, transparent);
	overflow-wrap: anywhere;
}

.cateros-pricing__event-badge {
	flex-shrink: 0;
	width: 28px;
	height: 28px;
	border-radius: 999px;
	display: grid;
	place-items: center;
	background: color-mix(in srgb, var(--cateros-btn-text) 20%, transparent);
	color: var(--cateros-btn-text);
}

.cateros-pricing__event-badge svg {
	width: 14px;
	height: 14px;
	display: block;
}

.cateros-pricing__event-date {
	margin: 12px 0 0;
	font-size: 19px;
	font-weight: 800;
	line-height: 1.25;
	overflow-wrap: anywhere;
}

/* Wrap-friendly, and every child shares one baseline. The count sat high because
   the flex children each established their own line box: with `gap` providing the
   spacing and no shared line-height, the digit-only span (no descenders) and the
   word spans resolved different half-leading. Forcing an explicit, identical
   line-height on the container AND its children puts them on one baseline while
   keeping flex-wrap for long event-type labels. */
.cateros-pricing__event-meta {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 0 5px;
	margin: 6px 0 0;
	font-size: 14px;
	font-weight: 600;
	line-height: 1.4;
	color: color-mix(in srgb, var(--cateros-btn-text) 88%, transparent);
	overflow-wrap: anywhere;
}

.cateros-pricing__event-meta > span {
	font-size: inherit;
	font-weight: inherit;
	line-height: inherit;
}

/* Plain heading on the white surface — no tile, no fill, no divider. */
.cateros-pricing__header {
	background: none;
	border: 0;
	padding: 0;
	margin-block-end: 12px;
	flex-shrink: 0;
}

.cateros-pricing__title {
	margin: 0;
	font-size: 15px;
	font-weight: 700;
	letter-spacing: -0.01em;
	overflow-wrap: anywhere;
}

/* The card owns the padding now. */
.cateros-pricing__body {
	padding: 0;
	display: flex;
	flex-direction: column;
	min-height: 0;
}

/* Tinted list region. Applied to the empty state and the line list directly
   rather than to a new wrapper, because the markup must not change — the two are
   mutually exclusive (x-show on orderLines.length), so exactly one is ever
   visible and the tinted area reads as a single region either way.
   flex-shrink: 0 on the empty state so it keeps its natural height and never
   collapses to zero or shows a stray scrollbar when the order is empty. */
.cateros-pricing__empty {
	margin: 0 0 12px;
	padding: 20px 16px;
	background: var(--cateros-primary-tint);
	border-radius: var(--cateros-radius-card);
	text-align: center;
	color: color-mix(in srgb, var(--cateros-text-strong) 62%, transparent);
	font-weight: 600;
	flex-shrink: 0;
}

/* Everything below the list stays out of the scroll region and always visible. */
.cateros-pricing__rows,
.cateros-pricing__per-guest,
.cateros-pricing__help {
	flex-shrink: 0;
}

.cateros-pricing__rows {
	margin: 0;
}

.cateros-pricing__row {
	display: flex;
	justify-content: space-between;
	align-items: center;
	gap: 12px;
	padding: 8px 0;
	border-top: 1px solid color-mix(in srgb, var(--cateros-text-strong) 6%, transparent);
}

.cateros-pricing__row:first-child {
	border-top: 0;
}

.cateros-pricing__row dt {
	margin: 0;
	font-size: 13px;
	color: color-mix(in srgb, var(--cateros-text-strong) 72%, transparent);
}

.cateros-pricing__row dd {
	margin: 0;
	font-size: 13px;
	font-weight: 800;
	color: color-mix(in srgb, var(--cateros-text-strong) 86%, transparent);
}

/* Total reads as a summary line, not another row: extra space above it, label
   larger + bolder, amount the largest figure in the block. Sizes come from the
   file's existing scale — 14px is already used by the ordinary-row override and
   19px by .cateros-pricing__event-date, so no new step was invented.
   Wrap-safe: the row is flex with a gap; the label may wrap and the amount is
   flex-shrink: 0, so a longer translated "Total" grows the row instead of
   colliding with the figure. */
.cateros-pricing__row--total {
	margin-top: 8px;
	padding-top: 14px;
	align-items: baseline;
}

.cateros-pricing__row--total dt {
	font-size: 14px;
	font-weight: 700;
	color: var(--cateros-text, #1f2937);
	min-width: 0;
	overflow-wrap: anywhere;
}

.cateros-pricing__row--total dd {
	font-size: 19px;
	font-weight: 700;
	color: var(--cateros-text, #1f2937);
	flex-shrink: 0;
	white-space: nowrap;
}

/* The cateros_wizard_sidebar_after_totals slot (U2b): a real container, so
   extension lines get consistent breathing room — 8px above and below each
   line, as PADDING so the per-guest line's negative top margin below cannot
   collapse it away. Hidden lines have no box, so an idle slot adds nothing. */
.cateros-pricing__ext {
	line-height: 1.5;
}

.cateros-pricing__ext > * {
	margin: 0;
	padding-block: 8px;
	line-height: 1.5;
}

.cateros-pricing__per-guest {
	margin: -4px 0 0;
	padding: 0 0 10px;
	font-size: 12px;
	font-weight: 500;
	line-height: 1.35;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 72%, transparent);
	text-align: right;
}

.cateros-pricing__help {
	margin: 12px 0 0;
	font-size: 12px;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 72%, transparent);
}

/* Mobile order DRAWER host (U4). The floating "Total · N dishes" summary bar
   is GONE — the sticky bar's centre button opens this drawer instead. The
   host itself paints nothing and takes no pointer events; only its children
   (backdrop, drawer) do, so a closed drawer leaves the page untouched. */
.cateros-pricing__mobile {
	display: block;
	position: fixed;
	left: 0;
	right: 0;
	bottom: var(--cateros-bar-h, 64px);
	z-index: 999;
	pointer-events: none;
}

.cateros-pricing__mobile > * {
	pointer-events: auto;
}

/* Backdrop: viewport-wide but STOPPING at the fixed bar's top edge, so Back
   and Next stay visible and usable while the drawer is open. */
.cateros-pricing__drawer-backdrop {
	position: fixed;
	inset: 0 0 var(--cateros-bar-h, 64px) 0;
	background: rgba(16, 24, 40, 0.4);
	z-index: 0;
}

/* The drawer: rises from above the bar, caps at 80vh; the card inside keeps
   its flex column, so the ITEMS LIST is the one internal scroller (flex: 1 +
   min-height: 0 + overflow-y: auto, exactly the desktop card's mechanism)
   and the Total rows below it stay visible. overscroll-behavior keeps a
   finger that reaches the list's end from scrolling the locked page. */
.cateros-pricing__mobile-panel.cateros-pricing__drawer {
	position: relative;
	z-index: 1;
	margin: 0 8px 8px;
	max-height: 80vh;
	display: flex;
	flex-direction: column;
	background: #fff;
	border: 1px solid var(--cateros-border, #e5e7eb);
	border-radius: var(--cateros-radius-outer) var(--cateros-radius-outer) 12px 12px;
	box-shadow: 0 -12px 40px rgba(16, 24, 40, 0.18);
	overflow: hidden;
	overscroll-behavior: contain;
}

.cateros-pricing__drawer .cateros-pricing__card {
	border: 0;
	border-radius: 0;
	box-shadow: none;
	flex: 1 1 auto;
	min-height: 0;
	padding-top: 8px;
}

/* One title: the drawer head carries "Your order", so the card's own
   "Order Summary" header stays hidden inside it. */
.cateros-pricing__drawer .cateros-pricing__header {
	display: none;
}

/* The event card must never be the part that gives way — only the items
   list scrolls/shrinks inside the drawer. */
.cateros-pricing__drawer .cateros-pricing__event {
	flex: 0 0 auto;
}

.cateros-pricing__drawer-head {
	position: relative;
	flex: 0 0 auto;
	padding: 8px 48px 4px 20px;
	touch-action: none;
}

.cateros-pricing__drawer-handle {
	display: block;
	width: 44px;
	height: 4px;
	margin: 0 auto 8px;
	border-radius: 999px;
	background: color-mix(in srgb, var(--cateros-text-strong, #111827) 18%, transparent);
}

.cateros-pricing__drawer-title {
	margin: 0;
	font-size: 16px;
	font-weight: 800;
	color: var(--cateros-text-strong, var(--cateros-text, #1f2937));
}

.cateros-wizard .cateros-pricing__drawer-close {
	position: absolute;
	top: 10px;
	right: 10px;
	width: 32px;
	height: 32px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	border: 0;
	border-radius: 999px;
	background: color-mix(in srgb, var(--cateros-text-strong, #111827) 6%, transparent);
	color: color-mix(in srgb, var(--cateros-text-strong, #111827) 65%, transparent);
	font-size: 20px;
	line-height: 1;
	cursor: pointer;
	padding: 0;
}

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

@media (min-width: 1024px) {
	.cateros-pricing__mobile {
		display: none;
	}
}

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

/* ── Mini wizard ([cateros_wizard_mini]) ─────────────────────────────────────
   Layout and ornament only. The controls themselves are styled by the shared
   .cateros-wizard .cateros-wizard__input / __label / __btn--primary rules — the
   root carries .cateros-wizard, so those reach here directly and nothing below
   restates a declaration they already provide. The parallel input and button
   rules this block used to hold were deleted for that reason.

   Safe to place more than once on a page: no ids, no positional selectors, and
   nothing here assumes it is the only instance. */
.cateros-mini-wizard.cateros-wizard {
	max-width: 900px;
	padding: 28px 22px 26px;
	/* Opaque on purpose: the card may sit over a photograph or a dark band, so it
	   must not rely on the page background showing through. --cateros-primary-tint
	   is a brand/WHITE mix, never a transparent one. */
	background: var(--cateros-primary-tint);
	border-radius: var(--cateros-radius-outer);
	box-shadow: 0 16px 40px color-mix(in srgb, var(--cateros-text, #1f2937) 10%, transparent);
}

.cateros-mini-wizard .cateros-wizard__title {
	margin: 0 0 0.35rem;
	font-size: 1.5rem;
	font-weight: 800;
	letter-spacing: -0.02em;
	text-align: center;
}

/* Only the heading, the supporting line and the button label are centred; field
   labels stay left-aligned within their own field. */
.cateros-mini-wizard .cateros-wizard__intro {
	margin: 0 0 1.5rem;
	text-align: center;
}

/* One column, three across from 768px.
   align-items: stretch here plus margin-top: auto on the input is what keeps the
   three inputs level when one label wraps: every field grows to the tallest in
   the row, and each input is pushed to the bottom of its own field. No fixed
   heights, no nowrap, no truncation — a longer translation just makes the row
   taller, and the row never goes ragged. */
.cateros-wizard__mini-row {
	display: grid;
	grid-template-columns: 1fr;
	gap: 16px;
	align-items: stretch;
	margin-bottom: 18px;
}

@media (min-width: 768px) {
	.cateros-wizard__mini-row {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

/* The time field is a <div>, not a <label>: its wrapper names a two-select
   group via role="group"/aria-label, and a label may point at only one
   control. Same column layout as the two label-wrapped fields either side. */
.cateros-wizard__mini-row > label,
.cateros-wizard__mini-row > .cateros-wizard__mini-field {
	display: flex;
	flex-direction: column;
	min-width: 0;
}

.cateros-wizard__mini-row > label > .cateros-wizard__input,
.cateros-wizard__mini-row > .cateros-wizard__mini-field > .cateros-wizard__time-pair {
	margin-top: auto;
}

.cateros-wizard__mini-head {
	display: flex;
	align-items: center;
	gap: 10px;
	margin-bottom: 10px;
	min-width: 0;
}

/* The shared __label carries a bottom margin for stacked layouts; in this row the
   spacing is horizontal, so that single declaration is neutralised — not restated. */
.cateros-wizard__mini-head .cateros-wizard__label {
	margin-bottom: 0;
	overflow-wrap: anywhere;
}

/* Icon tile. Exactly the step-icon contract (see .cateros-wizard__progress-btn
   .is-active), not a second mechanism: `color` is --cateros-btn-text and
   --cos-ico-cut is the tile's own fill, so .cateros-wizard__ico-fill draws the
   glyph and .cateros-wizard__ico-cut punches genuine holes back to the brand.
   The point of using --cateros-btn-text rather than any mix of the brand is that
   the glyph's contrast against the tile is then IDENTICAL to the primary button
   label's contrast against that same brand — a guarantee the design already
   carries. A tonal mix would instead collapse at a very light or very dark
   brand, because it stays close to the fill it was derived from. */
.cateros-wizard .cateros-wizard__mini-ico {
	display: grid;
	place-items: center;
	flex-shrink: 0;
	width: 40px;
	height: 40px;
	border-radius: calc(var(--cateros-ui-radius) * 1.5);
	background: var(--cateros-primary);
	color: var(--cateros-btn-text);
	--cos-ico-cut: var(--cateros-primary);
}

.cateros-wizard__mini-ico svg {
	display: block;
	width: 22px;
	height: 22px;
}

/* Prefixed to (0,2,0): the shared __btn / __btn--primary rules are (0,2,0) and set
   `padding` and `width: auto`, so an unprefixed modifier would lose to them.
   Symmetric inline padding keeps the label optically centred across the whole
   button while reserving room for the badge, so a long or wrapped translation
   never runs underneath it. Height is untouched — __btn--primary already resolves
   to the same 48px min-height as the inputs. */
.cateros-wizard .cateros-wizard__mini-submit {
	position: relative;
	width: 100%;
	padding-inline: 52px;
}

.cateros-wizard .cateros-wizard__mini-arrow {
	position: absolute;
	inset-inline-end: 11px;
	top: 50%;
	transform: translateY(-50%);
	display: grid;
	place-items: center;
	width: 26px;
	height: 26px;
	color: var(--cateros-btn-text);
	--cos-ico-cut: var(--cateros-primary);
}

.cateros-wizard__mini-arrow svg {
	display: block;
	width: 26px;
	height: 26px;
}

/* Step 2 panel padding override REMOVED (round 8) so all four steps share one
   inset: 20px inline on mobile, 36px at >=1024px. It previously forced 20px at
   every width, which is why Step 2's insets never matched the other steps. */

.cateros-wizard__panel--step2 .cateros-wizard__panel-title {
	margin-left: 0;
	margin-right: 0;
	padding-left: 0;
	padding-right: 0;
}

/* Round 10: one shared inline inset for Step 2's content column.
   .cateros-dish-row keeps its own padding-inline (12px) so a selected row's tint
   and inset accent stripe still span the FULL row width with the content inset
   inside them. Stripping it would push the thumbnail and stepper hard against the
   tint's edges, so instead the sibling blocks adopt the same 12px — group title,
   badge, intro, search field, dish content and summary all land on one edge, and
   the right edges agree for the same reason. Four sibling rules beat moving the
   inset to a shared parent, because a parent inset would require removing the
   row's padding, which is the variant that breaks the tint. */
.cateros-wizard__step--2 > .cateros-wizard__menu-group-heading,
.cateros-wizard__step--2 .cateros-wizard__intro,
.cateros-wizard__step--2 > .cateros-dish-toolbar,
.cateros-wizard__menu-group-footer > .cateros-wizard__menu-group-stat,
.cateros-wizard__menu-group-footer > .cateros-wizard__error {
	padding-inline: 12px;
}

/* Round 8: border / border-radius / padding suppression removed so Step 2 gets
   the same inner grouped container as Steps 1, 3 and 4. The original concern was
   a doubled gutter from the panel's 20px plus the container's own padding —
   resolved by normalising the panel padding above rather than by suppressing the
   container. Step 2's markup adds no padded wrapper of its own (verified:
   .cateros-wizard__step--2, .cateros-dish-toolbar, .cateros-dish-groups and
   .cateros-dish-section carry no padding), so there is no third inset.
   The display/margin resets stay — those defeat the theme's layout rules. */
.cateros-wizard__panel--step2 .cateros-wizard__panel-body,
.cateros-wizard__panel-body--steps.cateros-wizard__panel-body--step2 {
	display: block !important;
	min-height: 0;
	margin: 0;
	box-shadow: none;
	background: transparent;
}

/* Alpine step mount + theme layout rules often add horizontal margin on desktop only */
.cateros-wizard__panel--step2 .cateros-wizard__panel-body > div,
.cateros-wizard__panel-body--step2 .cateros-wizard__step--2,
.cateros-wizard__panel-body--step2 .cateros-wizard__intro,
.cateros-wizard__panel-body--step2 .cateros-wizard__step--2 > .cateros-dish-toolbar,
.cateros-wizard__panel-body--step2 .cateros-wizard__step--2 > .cateros-dish-groups,
.cateros-wizard__panel-body--step2 .cateros-wizard__step--2 > .cateros-dish-show-more,
.cateros-wizard__panel-body--step2 .cateros-wizard__step--2 > .cateros-wizard__menu-group-footer,
.cateros-wizard__panel-body--step2 .cateros-dish-groups,
.cateros-wizard__panel-body--step2 .cateros-dish-section,
.cateros-wizard__panel-body--step2 .cateros-dish-list {
	margin-left: 0 !important;
	margin-right: 0 !important;
	max-width: none !important;
	width: 100%;
	box-sizing: border-box;
}

.cateros-wizard__panel-body--step2 .cateros-wizard__step--2 {
	margin: 0 !important;
	padding: 0 !important;
	min-height: 0;
	width: 100%;
	max-width: none !important;
	box-sizing: border-box;
}

/* Same alignment on large viewports (theme / WP layout constrained blocks) */
@media (min-width: 721px) {
	.cateros-wizard__panel--step2 .cateros-wizard__panel-body > div,
	.cateros-wizard__panel-body--step2 .cateros-wizard__step--2,
	.cateros-wizard__panel-body--step2 .cateros-wizard__intro,
	.cateros-wizard__panel-body--step2 .cateros-wizard__step--2 > .cateros-dish-toolbar,
	.cateros-wizard__panel-body--step2 .cateros-wizard__step--2 > .cateros-dish-groups,
	.cateros-wizard__panel-body--step2 .cateros-wizard__step--2 > .cateros-dish-show-more,
	.cateros-wizard__panel-body--step2 .cateros-wizard__step--2 > .cateros-wizard__menu-group-footer,
	.cateros-wizard__panel-body--step2 .cateros-dish-groups,
	.cateros-wizard__panel-body--step2 .cateros-dish-section,
	.cateros-wizard__panel-body--step2 .cateros-dish-list {
		margin-left: 0 !important;
		margin-right: 0 !important;
		max-width: none !important;
		width: 100%;
	}
}

.cateros-wizard__menu-group-footer {
	margin-top: 20px;
	padding-top: 16px;
	border-top: 1px solid color-mix(in srgb, var(--cateros-text-strong) 8%, transparent);
}

.cateros-wizard__menu-group-stat {
	margin: 0 0 12px;
	font-size: 15px;
	font-weight: 800;
	color: color-mix(in srgb, var(--cateros-text-strong) 88%, transparent);
}

.cateros-wizard__menu-group-head {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: space-between;
	gap: 8px 16px;
	margin-bottom: 8px;
}

.cateros-wizard__menu-group-heading {
	margin: 0;
	font-size: 1.35rem;
	font-weight: 800;
	line-height: 1.25;
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 8px 12px;
}

.cateros-wizard__menu-group-badge {
	font-size: 0.82rem;
	font-weight: 700;
	color: var(--cateros-primary, #2271B1);
	white-space: nowrap;
}

.cateros-dish-row--needs-variation {
	outline: 1px solid var(--cateros-primary-hover-border, color-mix(in srgb, #2271B1 35%, transparent));
	outline-offset: 2px;
	border-radius: var(--cateros-ui-radius);
}

.cateros-wizard__menu-skip-link {
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	font-size: 14px;
	font-weight: 700;
	color: var(--cateros-primary, #2271B1);
	text-decoration: underline;
	cursor: pointer;
	white-space: nowrap;
}

.cateros-wizard__menu-skip-link:hover,
.cateros-wizard__menu-skip-link:focus-visible {
	color: var(--cateros-primary-dark, #135E96);
}

.cateros-wizard__nav--menu-group {
	flex-wrap: wrap;
	gap: 10px;
	justify-content: space-between;
}

.cateros-wizard__nav--menu-group .cateros-wizard__btn--primary {
	margin-left: auto;
}

.cateros-dish-show-more {
	display: block;
	width: 100%;
	margin: 12px 0 0;
}

/* Full-width load more — outline primary (theme often paints generic buttons maroon). */
.cateros-wizard .cateros-dish-show-more.cateros-wizard__btn {
	background: #fff !important;
	background-color: #fff !important;
	border: 2px solid var(--cateros-primary) !important;
	color: var(--cateros-primary) !important;
	border-radius: var(--cateros-ui-radius) !important;
}

/* Load more block (U2): button above, muted "6 of 30" count centred under it. */
.cateros-dish-more {
	margin: 12px 0 0;
	text-align: center;
}

.cateros-dish-more .cateros-dish-show-more {
	margin: 0;
}

.cateros-dish-more__count {
	display: inline-block;
	margin-top: 6px;
	font-size: 13px;
	font-weight: 600;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 65%, transparent);
}

/* Step 2's layout-independent alert slot (U2b): room below, so the refusal
   message never touches the category/grid box under it. */
.cateros-wizard__error.cateros-wizard__step2-alert {
	margin: 0 0 12px;
	line-height: 1.5;
}

.cateros-wizard .cateros-dish-show-more.cateros-wizard__btn:hover,
.cateros-wizard .cateros-dish-show-more.cateros-wizard__btn:focus {
	background: var(--cateros-primary) !important;
	background-color: var(--cateros-primary) !important;
	border-color: var(--cateros-primary) !important;
	color: var(--cateros-btn-text) !important;
}

/* Item 3: the 10px nudge lives on this shared container, so the label and the
   dot row move together and can never drift apart. Logical property, so RTL
   stays correct. Exact alignment with the panel's inner content edge would be
   58px (1px panel border + 36px panel padding + 1px inner-container border +
   20px inner padding) — far more than the 10px requested, so 10px it is. */
.cateros-wizard__progress-groups {
	padding-inline-start: 10px;
	margin-top: 12px;
	padding-top: 12px;
	border-top: 1px solid color-mix(in srgb, var(--cateros-text-strong) 8%, transparent);
}

.cateros-wizard__progress-groups-label {
	margin: 0 0 8px;
	font-size: 13px;
	font-weight: 700;
	color: color-mix(in srgb, var(--cateros-text-strong) 75%, transparent);
}

.cateros-wizard__progress-groups-dots {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
}

.cateros-wizard__progress-groups-dot {
	box-sizing: border-box;
	flex-shrink: 0;
	width: 10px;
	height: 10px;
	border-radius: 50%;
	background: color-mix(in srgb, var(--cateros-text-strong) 18%, transparent);
	box-shadow: none;
}

/* Only the current group is highlighted; all other dots share the inactive style above. */
.cateros-wizard__progress-groups-dot.is-active {
	width: 12px;
	height: 12px;
	background: var(--cateros-primary, #2271B1);
}

.screen-reader-text {
	border: 0;
	clip: rect(0 0 0 0);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	width: 1px;
	white-space: nowrap;
}

.cateros-dish-toolbar {
	margin-bottom: 12px;
}

.cateros-dish-search-label {
	display: block;
	margin: 0;
	/* Anchor for the clear (×) button (U3). */
	position: relative;
}

/* Clear (×) inside the field (U3): shown only while the query is non-empty;
   the native WebKit cancel button stays suppressed below, so this is the one
   clear control at every width. */
.cateros-wizard .cateros-dish-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) 55%, transparent);
	font-size: 18px;
	line-height: 1;
	cursor: pointer;
	padding: 0;
}

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

/* "Showing results for …" + count (U3). */
.cateros-dish-search-note {
	margin: 10px 0 0;
	font-size: 13px;
	line-height: 1.5;
}

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

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

/* Empty state's "Clear search" — a link, not a button face. */
.cateros-wizard .cateros-dish-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-dish-search-clear-link:hover {
	color: var(--cateros-primary-dark, #135E96);
}

.cateros-dish-search {
	width: 100%;
	box-sizing: border-box;
	padding: 10px 12px;
	/* 12px inset + 16px icon + 12px gap before placeholder / typed text */
	padding-left: calc(12px + 16px + 12px) !important;
	text-indent: 0;
	border-radius: 12px;
	border: 1px solid var(--cateros-input-border); /* U10: was a 12% one-off */
	background-color: #fff;
	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;
	font-size: 15px;
	font-weight: 600;
	color: color-mix(in srgb, var(--cateros-text-strong) 90%, transparent);
	-webkit-appearance: none;
	appearance: none;
}

.cateros-dish-search::-webkit-search-decoration,
.cateros-dish-search::-webkit-search-cancel-button {
	-webkit-appearance: none;
	appearance: none;
}

.cateros-dish-search::placeholder {
	color: color-mix(in srgb, var(--cateros-text-strong) 45%, transparent);
	font-weight: 500;
}

.cateros-dish-search:focus {
	outline: 2px solid var(--cateros-primary-hover-border, color-mix(in srgb, #2271B1 35%, transparent));
	outline-offset: 1px;
	border-color: color-mix(in srgb, var(--cateros-primary, #2271B1) 45%, transparent);
}

.cateros-dish-groups--list {
	display: flex;
	flex-direction: column;
	gap: 0;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	box-shadow: none;
	background: transparent;
}

.cateros-dish-section + .cateros-dish-section {
	border-top: 1px solid color-mix(in srgb, var(--cateros-text-strong) 8%, transparent);
}

.cateros-wizard .cateros-dish-section__head {
	width: 100%;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	/* 12px inline to match .cateros-dish-row — was 14px, a 2px disagreement with
	   the rows beneath it. One shared value now. */
	padding-block: 11px;
	padding-inline: 12px;
	margin: 0;
	border: 0;
	background: rgba(247, 248, 250, 0.95);
	cursor: pointer;
	text-align: left;
	font: inherit;
	color: color-mix(in srgb, var(--cateros-text-strong) 78%, transparent);
	transition: background 0.14s ease;
}

.cateros-dish-section__head:hover {
	background: var(--cateros-primary-subtle, color-mix(in srgb, #2271B1 8%, transparent));
	color: color-mix(in srgb, var(--cateros-text-strong) 88%, transparent);
}

.cateros-dish-section__title {
	font-size: 13px;
	font-weight: 900;
	letter-spacing: 0.04em;
	text-transform: uppercase;
}

.cateros-dish-section__chev {
	width: 11px;
	height: 11px;
	border-right: 2px solid color-mix(in srgb, var(--cateros-text-strong) 40%, transparent);
	border-bottom: 2px solid color-mix(in srgb, var(--cateros-text-strong) 40%, transparent);
	transform: rotate(-45deg);
	flex-shrink: 0;
	transition: transform 0.15s ease;
	margin-top: -4px;
}

.cateros-dish-section__chev.is-collapsed {
	transform: rotate(45deg);
	margin-top: 0;
}

.cateros-dish-list {
	list-style: none;
	margin: 0;
	padding: 0;
}

.cateros-dish-row {
	display: grid;
	grid-template-columns: 76px minmax(0, 1fr) auto;
	gap: 12px;
	align-items: center;
	padding: 10px 12px;
	border-bottom: 1px solid color-mix(in srgb, var(--cateros-text-strong) 6%, transparent);
	background: #fff;
	transition: background 0.14s ease;
	min-height: 64px;
}

.cateros-dish-list > .cateros-dish-row:last-child {
	border-bottom: 0;
}

.cateros-dish-row--in-cart {
	background: var(--cateros-primary-subtle, color-mix(in srgb, #2271B1 8%, transparent));
	box-shadow: inset 3px 0 0 var(--cateros-primary-hover-border, color-mix(in srgb, #2271B1 35%, transparent));
}

.cateros-dish-row__thumb-wrap {
	width: 76px;
	height: 76px;
	border-radius: var(--cateros-ui-radius);
	overflow: hidden;
	background: color-mix(in srgb, var(--cateros-text-strong) 5%, transparent);
	flex-shrink: 0;
}

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

.cateros-dish-row__thumb-ph {
	display: grid;
	width: 100%;
	height: 100%;
	place-items: center;
	font-size: 22px;
	color: color-mix(in srgb, var(--cateros-text-strong) 20%, transparent);
	line-height: 1;
	font-weight: 700;
}

.cateros-dish-row__main {
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.cateros-dish-row__title {
	font-size: 15px;
	font-weight: 750;
	line-height: 1.25;
	color: color-mix(in srgb, var(--cateros-text-strong) 92%, transparent);
	margin: 0;
}

.cateros-dish-row__var-label {
	font-size: 12px;
	color: color-mix(in srgb, var(--cateros-text-strong) 55%, transparent);
	margin: 0;
	line-height: 1.35;
	max-width: 100%;
	word-break: break-word;
}

.cateros-dish-row__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px 10px;
	row-gap: 6px;
}

.cateros-dish-row__price {
	font-size: 14px;
	font-weight: 800;
	color: color-mix(in srgb, var(--cateros-text-strong) 72%, transparent);
}

.cateros-dish-row__price--muted {
	opacity: 0.78;
	font-weight: 700;
	font-size: 13px;
}

.cateros-dish-row__var-fs {
	border: 0;
	padding: 0;
	margin: 6px 0 0;
	min-inline-size: 0;
	width: 100%;
	align-self: stretch;
}

.cateros-dish-row__var-picker {
	display: flex;
	flex-wrap: wrap;
	gap: 6px 12px;
	width: 100%;
	max-width: 100%;
}

.cateros-dish-row__var-radio {
	display: inline-flex;
	align-items: flex-start;
	gap: 7px;
	margin: 0;
	font-size: 11px;
	font-weight: 700;
	line-height: 1.35;
	color: color-mix(in srgb, var(--cateros-text-strong) 75%, transparent);
	cursor: pointer;
	min-width: 0;
	flex: 0 1 calc(50% - 12px);
}

.cateros-dish-row__var-radio-input {
	margin: 3px 0 0;
	flex-shrink: 0;
	accent-color: var(--cateros-primary, #2271B1);
}

.cateros-dish-row__var-radio-text {
	word-break: break-word;
	min-width: 0;
	font-weight: 650;
	color: color-mix(in srgb, var(--cateros-text-strong) 80%, transparent);
}

@media (min-width: 720px) {
	.cateros-dish-row__var-radio {
		flex-basis: auto;
	}
}

.cateros-dish-row__actions {
	justify-self: end;
	align-self: center;
}

.cateros-dish-row__add {
	min-width: 72px;
	padding: 8px 14px;
	font-size: 13px;
	justify-content: center;
}

.cateros-dish-row__qty-wrap {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	gap: 4px;
}

.cateros-dish-row__qty {
	display: flex;
	align-items: center;
	gap: 6px;
	border-radius: var(--cateros-ui-radius);
	border: 1px solid color-mix(in srgb, var(--cateros-text-strong) 10%, transparent);
	padding: 4px;
	background: rgba(255, 255, 255, 0.9);
	box-shadow: 0 1px 0 color-mix(in srgb, var(--cateros-text-strong) 4%, transparent);
}

/* Same fix as the Step 1 guest stepper: the glyphs were U+2212 MINUS and U+002B
   ASCII — different Unicode blocks, different metrics, and U+2212 triggers
   per-character font fallback, so neither vertical nor horizontal centring was
   reliable. Inline SVG + flex centring is deterministic. Outer dimensions
   unchanged (min-width 32px / height 34px). */
.cateros-wizard .cateros-dish-row__qty-btn {
	min-width: 32px;
	height: 34px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	border: 0;
	border-radius: var(--cateros-ui-radius);
	background: #fff;
	font-size: 18px;
	font-weight: 850;
	cursor: pointer;
	color: color-mix(in srgb, var(--cateros-text-strong) 82%, transparent);
	line-height: 1;
}

.cateros-dish-row__qty-btn:hover:not(:disabled) {
	background: var(--cateros-primary-subtle, color-mix(in srgb, #2271B1 8%, transparent));
	color: var(--cateros-primary, #2271B1);
}

.cateros-dish-row__qty-btn:disabled {
	opacity: 0.4;
	cursor: not-allowed;
	color: color-mix(in srgb, var(--cateros-text-strong) 45%, transparent);
}

/* The read-only .cateros-dish-row__qty-val span became a typeable input; this is
   its compact size variant. Everything else — border, radius, background, centred
   text, tabular numerals — comes from the shared .cateros-wizard__qty-input, so
   only the dimensions are restated. Reusing that class unmodified would apply
   Step 1's 4.5rem / 44px / 1rem sizing and visibly inflate every dish row.
   Height matches .cateros-dish-row__qty-btn (34px) so the three controls sit on
   one line. Prefixed to (0,2,0) so it beats the shared class regardless of where
   either rule ends up in the file. */
.cateros-wizard .cateros-dish-row__qty-input {
	width: 3.5rem;
	min-height: 34px;
	padding-block: 4px;
	padding-inline: 2px;
	font-size: 14px;
	font-weight: 900;
}

.cateros-wizard .cateros-dish-row__unlink {
	border: 0;
	background: transparent;
	padding: 2px 0;
	font-size: 11px;
	font-weight: 700;
	color: color-mix(in srgb, var(--cateros-text-strong) 45%, transparent);
	cursor: pointer;
	text-decoration: underline;
	text-underline-offset: 2px;
}

.cateros-dish-row__unlink:hover {
	color: color-mix(in srgb, var(--cateros-text-strong) 75%, transparent);
}

@media (max-width: 560px) {
	.cateros-dish-row {
		grid-template-columns: 56px minmax(0, 1fr);
		column-gap: 10px;
		row-gap: 8px;
		grid-template-areas:
			'dish-thumb dish-main'
			'dish-actions dish-actions';
	}

	.cateros-dish-row__thumb-wrap {
		grid-area: dish-thumb;
		width: 56px;
		height: 56px;
	}

	.cateros-dish-row__main {
		grid-area: dish-main;
		align-self: start;
	}

	.cateros-dish-row__actions {
		grid-area: dish-actions;
		justify-self: end;
	}

	.cateros-dish-row__add-wrap,
	.cateros-dish-row__qty-wrap {
		width: 100%;
		max-width: 100%;
		align-items: stretch;
	}

	.cateros-dish-row__qty-wrap {
		flex-direction: row;
		flex-wrap: wrap;
		justify-content: flex-end;
		align-items: center;
		gap: 8px;
	}

	.cateros-dish-row__unlink {
		margin-left: auto;
	}
}

/* Sidebar line items */
/* Prefixed for the same reason as .cateros-wizard__progress-list — see the note
   there about Astra's .entry-content ul/ol rule at (0,1,1). */
/* The ONLY scrolling region in the sidebar. flex: 1 + min-height: 0 lets it
   absorb the space the fixed regions don't use; min-height: 0 is required or the
   flex item refuses to shrink below its content and never scrolls. */
.cateros-wizard .cateros-pricing__lines {
	list-style: none;
	margin: 0 0 12px;
	padding: 12px;
	background: var(--cateros-primary-tint);
	border-radius: var(--cateros-radius-card);
	display: flex;
	flex-direction: column;
	gap: 10px;
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	overscroll-behavior: contain;
	/* Firefox / standards */
	scrollbar-width: thin;
	scrollbar-color: color-mix(in srgb, var(--cateros-primary) 38%, transparent) transparent;
}

/* WebKit / Blink — same thin, rounded, token-derived thumb on a transparent
   track. Deliberately visible, not hidden: the region must look scrollable. */
.cateros-wizard .cateros-pricing__lines::-webkit-scrollbar {
	width: 6px;
}

.cateros-wizard .cateros-pricing__lines::-webkit-scrollbar-track {
	background: transparent;
}

.cateros-wizard .cateros-pricing__lines::-webkit-scrollbar-thumb {
	background: color-mix(in srgb, var(--cateros-primary) 38%, transparent);
	border-radius: 999px;
}

.cateros-wizard .cateros-pricing__lines::-webkit-scrollbar-thumb:hover {
	background: color-mix(in srgb, var(--cateros-primary) 58%, transparent);
}

.cateros-pricing__line {
	display: grid;
	grid-template-columns: 42px minmax(0, 1fr) 28px;
	gap: 10px;
	align-items: start;
	padding: 10px 0;
	border-bottom: 1px solid color-mix(in srgb, var(--cateros-text-strong) 6%, transparent);
}

.cateros-pricing__line:last-child {
	border-bottom: 0;
}

.cateros-pricing__line-media {
	width: 42px;
	height: 42px;
	border-radius: var(--cateros-ui-radius);
	overflow: hidden;
	background: color-mix(in srgb, var(--cateros-text-strong) 5%, transparent);
	display: grid;
	place-items: center;
}

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

.cateros-pricing__line-ph {
	font-size: 14px;
	opacity: 0.35;
	font-weight: 800;
}

.cateros-pricing__line-main {
	min-width: 0;
}

.cateros-pricing__line-title {
	font-weight: 800;
	font-size: 13px;
	line-height: 1.25;
	color: color-mix(in srgb, var(--cateros-text-strong) 90%, transparent);
	word-break: break-word;
}

.cateros-pricing__line-sub {
	font-size: 12px;
	color: color-mix(in srgb, var(--cateros-text-strong) 55%, transparent);
	margin-top: 2px;
}

.cateros-pricing__line-meta {
	display: flex;
	justify-content: space-between;
	align-items: center;
	gap: 8px;
	margin-top: 6px;
	font-size: 12px;
	font-weight: 700;
	color: color-mix(in srgb, var(--cateros-text-strong) 65%, transparent);
}

.cateros-pricing__line-eq {
	font-weight: 900;
	color: color-mix(in srgb, var(--cateros-text-strong) 86%, transparent);
}

.cateros-wizard .cateros-pricing__line-remove {
	border: 0;
	background: transparent;
	font-size: 22px;
	line-height: 1;
	cursor: pointer;
	padding: 0 4px;
	color: color-mix(in srgb, var(--cateros-text-strong) 45%, transparent);
	justify-self: end;
	align-self: start;
	border-radius: var(--cateros-ui-radius);
}

.cateros-pricing__line-remove:hover {
	background: color-mix(in srgb, var(--cateros-text-strong) 6%, transparent);
	color: color-mix(in srgb, var(--cateros-text-strong) 80%, transparent);
}

/* Separated from the item list by a border on the same white surface — not by a
   nested container or a background fill. */
.cateros-pricing__rows {
	margin-block-start: 16px;
	padding-block-start: 16px;
	border-block-start: 1px solid var(--cateros-border, #e5e7eb);
	flex-shrink: 0;
}

/* ═════════════════════════════════════════════════════════════════════════
   U8 — Step 3 (Extras) redesign: section rows with round icon tiles, option
   cards with icons and fee pills. Markup hooks live in step-3-extras.php;
   everything here is scoped to step 3 (or to the s3- classes only it
   renders), so no other step changes. Tokens only — no new ones: tiles and
   pills ride --cateros-primary-tint, selection keeps --cateros-primary-subtle.
   ═════════════════════════════════════════════════════════════════════════ */

/* The wrapper's "Step N: Name" h2 stays the focus target and the panel's
   accessible name on EVERY step (U9) — CLIPPED, never display:none (focus()
   on a display:none node silently fails), while each step's own header
   paints below. */
.cateros-wizard .cateros-wizard__panel-title {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* ── Step header (no image) ── */
.cateros-wizard__s3-head {
	margin: 0 0 24px;
}

.cateros-wizard__s3-eyebrow {
	margin: 0 0 4px;
	/* U12 heading scale: 11px/600/0.08em. */
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase; /* style only — the catalogue string stays sentence case */
	/* U11: brand-tinted, mixed toward body text. 55% (not the sketched 75%) is
	   the contrast guard: with this site's light #ff9500 primary a 75% mix
	   lands at ~3.4:1 on white; 55% measures ≥4.5:1 (verified in-browser). A
	   darker primary only gains contrast from the same mix. */
	color: color-mix(in srgb, var(--cateros-primary, #2271B1) 55%, var(--cateros-text, #1f2937));
}

.cateros-wizard__s3-title {
	margin: 0 0 6px;
	/* U12 heading scale: 24px/600/1.2 (the Step 2 compact override below
	   keeps its 18px). */
	font-size: 24px;
	font-weight: 600;
	line-height: 1.2;
	color: var(--cateros-text-strong, var(--cateros-text, #1f2937));
}

/* U12: de-scoped from .cateros-wizard__step--3 — the subtitle scale (14px/400
   muted) applies on EVERY step; the old scope left Steps 1 and 4 at the
   15px .cateros-wizard__intro size. Same (0,2,0) specificity, later in the
   file, so it wins the intro tie everywhere. */
.cateros-wizard .cateros-wizard__s3-subtitle {
	margin: 0;
	font-size: 14px;
	font-weight: 400;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 72%, transparent);
}

/* U11: compact header, Step 2 only — eyebrow and title share one baseline
   ("STEP 2 OF 4 · Menu"), no subtitle, 12px below. The other steps keep the
   stacked header above. */
.cateros-wizard__s3-head--compact {
	display: flex;
	align-items: baseline;
	gap: 8px;
	margin: 0 0 12px;
}

.cateros-wizard__s3-head--compact .cateros-wizard__s3-eyebrow {
	margin: 0;
}

.cateros-wizard__s3-head--compact .cateros-wizard__s3-title {
	margin: 0;
	font-size: 18px;
}

/* The separator dot: presentational, neutral — the eyebrow's brand tint on a
   lone glyph would read as a control. */
.cateros-wizard__s3-dot {
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 45%, transparent);
	font-weight: 700;
}

/* ── Section pattern ── */
.cateros-wizard__step--3 .cateros-wizard__extras-block.cateros-wizard__s3sec {
	margin: 0 0 24px;
	padding: 0;
	border: 0;
}

/* The round section tiles and their row/label overrides are GONE (U10):
   Step 3's section labels are plain .cateros-wizard__label, exactly Step 1's
   voice; help lines are plain .cateros-wizard__hint. Icons live only inside
   the option cards below. */
.cateros-wizard__s3-ico {
	width: 20px;
	height: 20px;
}

/* The postcode help doubles as the success line: green once deliverable.
   U11: it sits UNDER the input row now — dictated 8px gap (the .cateros-
   wizard__hint default is 0.35rem). */
.cateros-wizard__s3-help {
	margin: 8px 0 0;
}

.cateros-wizard__s3-help--ok {
	color: #15803d;
	font-weight: 600;
}

/* ── Postcode input ── */
.cateros-wizard__step--3 .cateros-wizard__input--postcode {
	min-height: 48px;
	max-width: 420px;
	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='1.75' stroke-linecap='round' stroke-linejoin='round' viewBox='0 0 24 24'%3E%3Cpath d='M20 10.5c0 5-8 10.5-8 10.5S4 15.5 4 10.5a8 8 0 1 1 16 0Z'/%3E%3Ccircle cx='12' cy='10.5' r='3'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: 12px center;
	background-size: 16px 16px;
}

@media (max-width: 782px) {
	.cateros-wizard__step--3 .cateros-wizard__input--postcode {
		max-width: none;
		width: 100%;
	}
}

/* Out-of-area, BLOCK mode: the message and the pickup hint read as one soft
   red note under the input. The warn-mode notice keeps its quiet look. */
.cateros-wizard__step--3 .cateros-wizard__s3-danger {
	background: color-mix(in srgb, var(--cateros-danger, #b91c1c) 7%, #fff);
	border-radius: 10px;
	padding: 10px 14px;
	margin-top: 8px;
	max-width: 560px;
}

/* U5b: the note is now literally ONE box — a container around the message and
   the hint (they were two stacked .cateros-wizard__s3-danger boxes before).
   The children shed their own box chrome and stack 4px apart inside it. */
.cateros-wizard__step--3 .cateros-wizard__s3-blocknote > p {
	margin: 0;
	background: none;
	padding: 0;
}

.cateros-wizard__step--3 .cateros-wizard__s3-blocknote > p + p {
	margin-top: 4px;
}

/* ── Custom radio (visual only — the real radio stays the clipped input) ── */
.cateros-wizard__s3-radio {
	flex: 0 0 auto;
	width: 20px;
	height: 20px;
	border-radius: 50%;
	border: 2px solid color-mix(in srgb, var(--cateros-text, #1f2937) 30%, transparent);
	background: #fff;
	position: relative;
}

.cateros-wizard .cateros-wizard__fulfillment-option--active .cateros-wizard__s3-radio,
.cateros-wizard .cateros-wizard__serving-card.is-selected .cateros-wizard__s3-radio {
	border-color: var(--cateros-primary, #2271B1);
}

.cateros-wizard .cateros-wizard__fulfillment-option--active .cateros-wizard__s3-radio::after,
.cateros-wizard .cateros-wizard__serving-card.is-selected .cateros-wizard__s3-radio::after {
	content: '';
	position: absolute;
	inset: 3px;
	border-radius: 50%;
	background: var(--cateros-primary, #2271B1);
}

/* ── Card icon tile + text column + fee pill (shared by both card kinds) ── */
/* Card icon tiles = the Event occasion tiles (U10): same 44px disc, same
   --cateros-primary-subtle tint, brand-coloured artwork. (Event glyphs are
   dashicon font characters; these stay 1.75-stroke SVGs at the same size.) */
.cateros-wizard__s3-cardtile {
	flex: 0 0 auto;
	width: 44px;
	height: 44px;
	border-radius: 999px;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	background: var(--cateros-primary-subtle, color-mix(in srgb, var(--cateros-primary, #2271B1) 8%, transparent));
	color: var(--cateros-primary, #2271B1);
}

.cateros-wizard__s3-cardmain {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.cateros-wizard__s3-carddesc {
	font-size: 13px;
	line-height: 1.4;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 70%, transparent);
}

.cateros-wizard__step--3 .cateros-wizard__s3-pill {
	display: inline-flex;
	align-items: center;
	gap: 4px;
	background: var(--cateros-primary-tint, #fdf4ec);
	border-radius: 999px;
	padding: 5px 12px;
	font-size: 12.5px;
	white-space: nowrap;
	color: var(--cateros-text-strong, var(--cateros-text, #1f2937));
}

.cateros-wizard__s3-clamp {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* ── Method cards: one row — radio, tile, name + line, pill right. The row
   WRAPS: on a narrow panel (2-up cards at ~250px) the pill drops to its own
   line, where margin-left:auto keeps it bottom-right — the reference's own
   arrangement — instead of squeezing the name column to a letter a line. ── */
.cateros-wizard .cateros-wizard__fulfillment-option {
	flex-direction: row;
	flex-wrap: wrap;
	align-items: center;
	gap: 12px;
	min-height: 72px;
	/* U9: EXACTLY the Event cards' chrome — 1px border (the base rule's own
	   width stands) and the same radius token — so every selectable card in
	   the planner wears one border system. */
	border-radius: var(--cateros-radius-card);
	padding: 14px 16px;
}

/* The old column-era label rules (width: 100%, overflow-wrap: anywhere) are
   what shredded "Delivery" into a one-letter column in the row layout. */
.cateros-wizard__step--3 .cateros-wizard__fulfillment-label {
	font-size: 15px;
	font-weight: 600;
	width: auto;
	overflow-wrap: normal;
	word-break: normal;
}

/* Guarantees the wrap happens instead of the squeeze. */
.cateros-wizard__step--3 .cateros-wizard__fulfillment-option .cateros-wizard__s3-cardmain {
	min-width: 140px;
}

.cateros-wizard__step--3 .cateros-wizard__fulfillment-option .cateros-wizard__s3-pill {
	align-self: center;
	margin-left: auto;
	margin-top: 0; /* the old pill's margin-top:auto belonged to the column layout */
}

/* ── Serving cards: radio + tile on top, then text, pill at the bottom ── */
.cateros-wizard .cateros-wizard__serving-card {
	display: grid;
	grid-template-columns: auto 1fr;
	align-items: center;
	column-gap: 12px;
	row-gap: 8px;
	/* U9: Event-card chrome — 1px base border, shared radius token. */
	border-radius: var(--cateros-radius-card);
	padding: 14px 16px;
}

.cateros-wizard__serving-card .cateros-wizard__s3-radio {
	grid-column: 1;
	grid-row: 1;
}

.cateros-wizard__serving-card .cateros-wizard__s3-cardtile {
	grid-column: 2;
	grid-row: 1;
	justify-self: start;
}

.cateros-wizard__serving-card .cateros-wizard__s3-cardmain {
	grid-column: 1 / -1;
}

.cateros-wizard__step--3 .cateros-wizard__serving-card .cateros-wizard__s3-pill {
	grid-column: 1 / -1;
	justify-self: start;
}

/* Serving columns (U8): 2+1 on tablets, three-up from 1024. The base 720px
   three-up rule above is overridden here, later in the file. */
@media (min-width: 720px) and (max-width: 1023.98px) {
	.cateros-wizard__serving-cards {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/* ── Notes ── */
.cateros-wizard__step--3 .cateros-wizard__textarea--notes {
	min-height: 96px;
}

.cateros-wizard__s3-counter {
	margin: 4px 0 0;
	text-align: right;
	font-size: 12px;
	color: color-mix(in srgb, var(--cateros-text, #1f2937) 70%, transparent);
}

/* ── 390: smaller tiles, everything stacks, pills wrap under the names ── */
@media (max-width: 782px) {
	.cateros-wizard .cateros-wizard__fulfillment-option {
		flex-wrap: wrap;
	}

	.cateros-wizard__step--3 .cateros-wizard__fulfillment-option .cateros-wizard__s3-pill {
		margin-left: calc(20px + 12px); /* under the name column, past the radio */
	}
}

/* ── U9: focus-ring reinforcement ─────────────────────────────────────────
   End-of-file on purpose: these selectors re-pin the ONE brand ring on the
   controls whose own state rules (higher specificity or !important-free
   ties won by source order) would otherwise repaint focus — the shared rule
   at the top of the file covers everything else. Same declaration
   everywhere: white gap + var(--cateros-focus-ring). */
.cateros-wizard .cateros-wizard__btn:focus-visible,
.cateros-wizard .cateros-wizard__btn:not(.cateros-wizard__btn--primary):focus-visible,
.cateros-wizard .cateros-wizard__btn--primary:focus-visible,
.cateros-wizard .cateros-dish-show-more.cateros-wizard__btn:focus-visible,
.cateros-wizard .cateros-wizard__bar .cateros-wizard__bar-sum:focus-visible,
.cateros-wizard .cateros-pricing__drawer-close:focus-visible,
.cateros-wizard .cateros-dish-search-clear:focus-visible,
.cateros-wizard .cateros-wizard__change-link:focus-visible,
.cateros-wizard .cateros-wizard__menu-skip-link:focus-visible,
.cateros-wizard .cateros-wizard__input:focus-visible,
.cateros-wizard .cateros-wizard__textarea:focus-visible,
.cateros-wizard .cateros-dish-search:focus-visible,
.cateros-wizard .cateros-wizard__qty-btn:focus-visible,
.cateros-wizard .cateros-dish-row__qty-btn:focus-visible,
.cateros-wizard .cateros-catalog-card__qty-btn:focus-visible {
	outline: none;
	box-shadow: var(--cateros-focus-ring-offset);
}

/* A SELECTED card that is also keyboard-focused shows the ring, not its
   selected glow — these ties were being won by the later selected rules
   (U10). Same declaration, maximum source order. */
.cateros-wizard .cateros-wizard__event-card:has(.cateros-wizard__event-card-radio:focus-visible),
.cateros-wizard .cateros-wizard__fulfillment-option:has(.cateros-wizard__fulfillment-radio:focus-visible),
.cateros-wizard .cateros-wizard__serving-card:has(.cateros-wizard__serving-card-radio:focus-visible) {
	outline: none;
	box-shadow: var(--cateros-focus-ring-offset);
}

/* The time control keeps its one deliberate exception: the three selects
   suppress their own rings and the WRAPPER shows focus — re-pointed at the
   shared token so even that exception is brand-coloured. */
.cateros-wizard .cateros-wizard__time-pair:focus-within {
	outline: none;
	box-shadow: var(--cateros-focus-ring-offset);
}


/* ── U10: bar labels ─────────────────────────────────────────────────────
   Next carries the destination: "Next: Extras →" above 782px, the bare
   "Extras →" (or the next menu section's name) at phone widths. */
.cateros-wizard__bar-next-short {
	display: none;
}

@media (max-width: 782px) {
	.cateros-wizard__bar-next-full {
		display: none;
	}

	.cateros-wizard__bar-next-short {
		display: inline;
	}
}

/* Tight widths drop the centre summary's parts in order — the dish count
   first, then the "Total" word; the amount and the buttons never go. */
@media (max-width: 374px) {
	.cateros-wizard__bar-cpart {
		display: none;
	}
}

@media (max-width: 330px) {
	.cateros-wizard__bar-tword {
		display: none;
	}
}
