/*!
 * Tewido Quote List - front end.
 *
 * Logical properties throughout (margin-inline, inset-inline) so the same
 * sheet lays out correctly under dir="rtl"; quote-rtl.css only carries the
 * handful of rules a logical property cannot express.
 */

/*
 * Visually hidden, owned here rather than borrowed.
 *
 * `.screen-reader-text` is a theme's to provide on the front end - core only
 * guarantees it in the admin - and on a theme that does not ship it, every
 * element relying on it renders in full view: the live region would print each
 * announcement into the footer as the visitor worked. So the front end uses
 * this class, and only the admin, where core defines it, uses the other.
 */
.tewido-quote-sr {
	position: absolute !important;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	border: 0;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
	word-wrap: normal;
}

/* --------------------------------------------------------------- toast ---
 *
 * Top centre, above everything, and never in the way: pointer-events are off
 * so a toast landing over a product card cannot swallow the next click.
 */
.tewido-quote-toast-host {
	position: fixed;
	inset-block-start: 24px;
	/* Centred with auto margins rather than a 50% offset and a translate:
	   under dir="rtl" the offset anchors to the right edge while the translate
	   still pulls left, which puts the toast off centre. This reads the same
	   in both directions and needs no rule in quote-rtl.css. */
	inset-inline: 0;
	margin-inline: auto;
	z-index: 99999;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 8px;
	width: max-content;
	max-width: calc(100vw - 32px);
	pointer-events: none;
}

.tewido-quote-toast {
	display: flex;
	align-items: center;
	gap: 12px;
	max-width: 100%;
	padding: 12px 16px;
	border: 1px solid var(--tq-border-soft, #e8e8e8);
	border-radius: var(--tq-radius-lg, 12px);
	background: var(--tq-surface, #fff);
	box-shadow: 0 10px 30px rgba(17, 24, 39, .12), 0 2px 6px rgba(17, 24, 39, .06);
	/* The host turns pointer events off so a toast cannot swallow a click
	   meant for the page behind it; the card turns them back on for its own
	   link, which is the only thing in here worth clicking. */
	pointer-events: auto;
	opacity: 0;
	transform: translateY(-10px);
	transition: opacity .22s ease, transform .22s ease;
}

.tewido-quote-toast.is-in {
	opacity: 1;
	transform: translateY(0);
}

.tewido-quote-toast__icon {
	display: grid;
	place-items: center;
	flex: 0 0 auto;
	width: 28px;
	height: 28px;
	border-radius: 50%;
	background: var(--tq-success-soft, rgba(22, 163, 74, .12));
	color: var(--tq-success, #16a34a);
}

.tewido-quote-toast__body {
	min-width: 0;
	text-align: start;
}

.tewido-quote-toast__title {
	display: block;
	overflow: hidden;
	max-width: 32ch;
	color: var(--tq-text, #111827);
	font-size: 14px;
	font-weight: 600;
	line-height: 1.35;
	white-space: nowrap;
	text-overflow: ellipsis;
}

.tewido-quote-toast__meta {
	display: block;
	color: var(--tq-muted, #666);
	font-size: 12.5px;
	line-height: 1.4;
}

.tewido-quote-toast__link {
	flex: 0 0 auto;
	margin-inline-start: 4px;
	padding: 6px 12px;
	border-radius: var(--tq-radius-sm, 6px);
	background: var(--tq-primary-soft, #f2fafd);
	color: var(--tq-primary, #1d91b8);
	font-size: 13px;
	font-weight: 600;
	line-height: 1.3;
	text-decoration: none;
	white-space: nowrap;
	transition: background .15s ease;
}

.tewido-quote-toast__link:hover,
.tewido-quote-toast__link:focus-visible {
	background: var(--tq-primary, #1d91b8);
	color: var(--tq-on-primary, #fff);
}

/* The undo button on a removal toast. A <button>, so it is reachable by
   keyboard - unlike the View Full List link beside it, which is a shortcut
   to somewhere permanent and is deliberately skipped in the tab order. */
.tewido-quote-toast__undo {
	border: 0;
	font-family: inherit;
	font-weight: 600;
	cursor: pointer;
}

.tewido-quote-toast--removed .tewido-quote-toast__icon {
	background: var(--tq-error-soft, rgba(220, 38, 38, .1));
	color: var(--tq-error, #dc2626);
}

@media (max-width: 480px) {
	.tewido-quote-toast__title {
		max-width: 18ch;
	}
}

@media (prefers-reduced-motion: reduce) {
	.tewido-quote-toast {
		transition: none;
		transform: none;
	}

	.tewido-quote-toast.is-in {
		transform: none;
	}
}

@media (forced-colors: active) {
	.tewido-quote-toast {
		border: 1px solid CanvasText;
	}
}

/*
 * Every colour comes from Tewido Elementra's Colors tab, which publishes
 * `--tewido-elementra-color-*` on the document. The literal after each one is
 * only the fallback for a site running this plugin on its own - edit the
 * palette in the Colors tab, not here.
 */
.tewido-quote-add-wrap,
.tewido-quote-toast-host,
.tewido-quote-cart,
.tewido-quote-btn,
.tewido-quote-section,
.tewido-quote-form,
.tewido-quote-search,
.tewido-quote-bundles,
.tewido-quote-drawer {
	--tq-primary: var(--tewido-elementra-color-primary, #1d91b8);
	--tq-primary-hover: var(--tewido-elementra-color-primary-600, #197b9c);
	--tq-primary-soft: var(--tewido-elementra-color-primary-50, #f2fafd);
	--tq-on-primary: var(--tewido-elementra-color-on-brand, #fff);

	--tq-surface: var(--tewido-elementra-color-surface, #fff);
	--tq-surface-soft: var(--tewido-elementra-color-gray-50, #f7f7f7);
	--tq-border: var(--tewido-elementra-color-gray-200, #d1d1d1);
	--tq-border-soft: var(--tewido-elementra-color-gray-100, #e8e8e8);

	--tq-text: var(--tewido-elementra-color-heading, #292929);
	--tq-text-body: var(--tewido-elementra-color-body, #474747);
	--tq-muted: var(--tewido-elementra-color-gray-500, #666);
	--tq-disabled-bg: var(--tewido-elementra-color-gray-200, #d1d1d1);
	--tq-disabled-text: var(--tewido-elementra-color-gray-500, #666);

	--tq-error: var(--tewido-elementra-color-error, #dc2626);
	--tq-error-soft: rgba(220, 38, 38, .1);
	--tq-success: var(--tewido-elementra-color-success, #16a34a);
	--tq-success-soft: rgba(22, 163, 74, .12);
	--tq-on-success: var(--tewido-elementra-color-on-brand, #fff);

	--tq-check-border: var(--tewido-elementra-color-gray-300, #bababa);
	--tq-check-hover: var(--tewido-elementra-color-gray-500, #666);
	--tq-empty-art: var(--tewido-elementra-color-gray-300, #bababa);
	--tq-empty-badge: var(--tewido-elementra-color-gray-400, #a3a3a3);

	--tq-radius-sm: 6px;
	--tq-radius: 8px;
	--tq-radius-lg: 12px;

	/* Declared twice on purpose: a browser that cannot parse `color-mix()`
	   drops that declaration and keeps the literal above it, rather than
	   losing the focus ring entirely. */
	--tq-focus: 0 0 0 3px rgba(29, 145, 184, .3);
	--tq-focus: 0 0 0 3px color-mix(in srgb, var(--tewido-elementra-color-primary, #1d91b8) 35%, transparent);
}

/* ----------------------------------------------------------------- buttons */

.tewido-quote-btn,
.tewido-quote-add {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	padding: 11px 20px;
	border: 1px solid transparent;
	border-radius: var(--tq-radius, 8px);
	background: var(--tq-primary, #1d91b8);
	color: var(--tq-on-primary, #fff);
	font-family: inherit;
	/* Fixed, not inherited: a theme that sizes body text at 18px turns every
	   button in here into a slab. */
	font-size: 14px;
	font-weight: 600;
	line-height: 1.2;
	text-decoration: none;
	cursor: pointer;
	transition: background .2s ease, transform .15s ease;
}

.tewido-quote-btn .tewido-quote-icon,
.tewido-quote-add .tewido-quote-icon {
	width: 18px;
	height: 18px;
}

/* Wrapper around a button icon that the script swaps for another. A span,
   because `hidden` on an inline-flex child is overridden by the display the
   SVG would otherwise inherit - and flex here keeps it on the text baseline
   the bare SVG sat on. */
.tewido-quote-btn__ico {
	display: inline-flex;
	align-items: center;
}

.tewido-quote-btn__ico[hidden] {
	display: none;
}

.tewido-quote-btn:hover,
.tewido-quote-add:hover {
	background: var(--tq-primary-hover, #197b9c);
	color: var(--tq-on-primary, #fff);
}

.tewido-quote-btn:focus-visible,
.tewido-quote-add:focus-visible,
.tewido-quote-cart:focus-visible,
.tewido-quote-field__input:focus-visible,
.tewido-quote-stepper__btn:focus-visible,
.tewido-quote-stepper__input:focus-visible,
.tewido-quote-row__remove:focus-visible,
.tewido-quote-drawer__close:focus-visible {
	outline: 2px solid var(--tq-primary, #1d91b8);
	outline-offset: 2px;
	box-shadow: var(--tq-focus, 0 0 0 3px rgba(29, 145, 184, .3));
}

.tewido-quote-btn--ghost {
	background: transparent;
	border-color: var(--tq-border, #d1d1d1);
	color: var(--tq-text, #292929);
}

.tewido-quote-btn--ghost:hover {
	background: var(--tq-surface-soft, #f7f7f7);
	color: var(--tq-text, #292929);
}

/* WhatsApp's own green and white mark, because the button is recognised by
   that pairing rather than by its label. Not a design-system colour, so it
   does not read from the Colors tab.

   Both greens are WhatsApp's: the dark teal is the brand's own `#128c7e` and
   the bright `#25d366` is the one it uses for its primary action. Resting on
   the darker of the two and brightening on hover is the right way round for
   a button sitting beside the form's own submit - it clears contrast on
   white at rest, and the lighter green reads as a response to the pointer
   rather than as the louder of two competing buttons. */
.tewido-quote-btn--whatsapp {
	background: #128c7e;
	border-color: transparent;
	color: #fff;
}

.tewido-quote-btn--whatsapp:hover,
.tewido-quote-btn--whatsapp:focus-visible {
	background: #25d366;
	color: #fff;
}

.tewido-quote-btn--whatsapp:focus-visible {
	outline-color: #128c7e;
	box-shadow: 0 0 0 3px rgba(18, 140, 126, .35);
}

.tewido-quote-btn--whatsapp .tewido-quote-icon {
	width: 17px;
	height: 17px;
}

/* Grey, not a translucent brand colour - a half-faded brand button reads as a
   rendering fault rather than as "not yet". */
.tewido-quote-btn[disabled],
.tewido-quote-btn:disabled,
.tewido-quote-add[disabled],
.tewido-quote-add:disabled {
	background: var(--tq-disabled-bg, #d1d1d1);
	border-color: transparent;
	color: var(--tq-disabled-text, #666);
	cursor: not-allowed;
	box-shadow: none;
}

.tewido-quote-btn[disabled]:hover,
.tewido-quote-btn:disabled:hover {
	background: var(--tq-disabled-bg, #d1d1d1);
	color: var(--tq-disabled-text, #666);
}

.tewido-quote-add-wrap {
	display: inline-flex;
	align-items: stretch;
	gap: 8px;
}

/* The stepper matches whatever height the editor gave the button, rather
   than setting one of its own - the pair has to read as one control even
   after the Button tab has been through its padding and typography. */
.tewido-quote-add__stepper {
	align-self: stretch;
}

/* Icon only. The label is still in the markup, carrying the editor's
   wording to the title and aria-label the server put on the button, so it
   is hidden rather than dropped. Square padding, because the horizontal
   padding of a text button around a lone 18px glyph reads as a mistake. */
.tewido-quote-add--icon .tewido-quote-add__label {
	display: none;
}

.tewido-quote-add--icon {
	padding-inline: 11px;
}

.tewido-quote-add--icon .tewido-quote-add__state--added {
	gap: 0;
}

.tewido-quote-add .tewido-quote-icon {
	flex: 0 0 auto;
}

/* -------------------------------------------------------------- cart icon */

.tewido-quote-cart {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: 8px;
	color: var(--tq-text, #292929);
	text-decoration: none;
	line-height: 1;
	-webkit-tap-highlight-color: transparent;
}

/* The pill, shared by the two layouts that carry a visible label: an
   outlined capsule holding the glyph, the wording and the count. It reads
   as one control at a glance, which a bare glyph in a header does not -
   a quote list is not a shopping cart anyone has met before, and the icon
   on its own was being asked to teach that. */
.tewido-quote-cart--icon,
.tewido-quote-cart--text {
	gap: 8px;
	/* Less on the end the chip sits at: a pill with equal padding looks
	   right-heavy once a round dot is tucked into that corner. */
	padding: 6px 6px 6px 14px;
	/* A brand tint, not a grey card and not an outline. A white pill on a
	   white header is only its border, which is what made it read as a tag
	   with a box drawn round it; a neutral grey field reads as disabled.
	   The tint says "ours" and "clickable" in one move, and the whole
	   control - field, icon, label, dot - is then one colour family instead
	   of three. */
	border: 1px solid transparent;
	border-radius: 999px;
	background: var(--tq-primary-soft, #f2fafd);
	color: var(--tq-primary, #1d91b8);
	/* Not bold and not large: this is a standing control in a header, not a
	   call to action. Weight is what made it shout. */
	font-size: 14px;
	font-weight: 500;
	line-height: 1.2;
	transition: background .18s ease, color .18s ease, border-color .18s ease;
}

/* No dot to leave room for. */
.tewido-quote-cart--text:not(:has(.tewido-quote-cart__count)),
.tewido-quote-cart--icon:not(:has(.tewido-quote-cart__count)) {
	padding-inline-end: 14px;
}

/* One step deeper, same family. `color-mix` with a literal fallback above
   it, so a browser that cannot parse it keeps a visible hover rather than
   losing the declaration. */
.tewido-quote-cart--icon:hover,
.tewido-quote-cart--text:hover {
	background: rgba(29, 145, 184, .14);
	background: color-mix(in srgb, var(--tq-primary, #1d91b8) 14%, var(--tq-surface, #fff));
	color: var(--tq-primary-hover, #197b9c);
}

/* The glyph is the quieter half of the pair - the wording carries it - so
   it sits a shade back rather than matching the label stroke for stroke. */
.tewido-quote-cart--icon .tewido-quote-cart__icon {
	opacity: .75;
}

.tewido-quote-cart--icon:hover .tewido-quote-cart__icon {
	opacity: 1;
}

/* One ring, not two. The shared focus style puts a 2px outline AND a 3px
   glow on everything it covers - fine on a square button, but on a 999px
   pill the two radii are concentric and it reads as a selected tag that
   will not let go. A single crisp outline says the same thing. */
.tewido-quote-cart:focus-visible {
	outline: 2px solid var(--tq-primary, #1d91b8);
	outline-offset: 2px;
	box-shadow: none;
}

/* The field is the only thing giving this control an edge, and a forced
   palette throws background colours away. */
@media (forced-colors: active) {
	.tewido-quote-cart--icon,
	.tewido-quote-cart--text {
		border-color: ButtonBorder;
	}

	.tewido-quote-cart__count {
		border: 1px solid ButtonBorder;
	}
}

/* Icon-only layout: a round button sized like the header's other icon
   controls, with the count riding its top corner. For a header that is
   already a row of bare glyphs and would look wrong with one pill in it. */
.tewido-quote-cart--icon-only {
	justify-content: center;
	width: 42px;
	height: 42px;
	border: 1px solid var(--tq-border, #d1d1d1);
	border-radius: 999px;
	background: var(--tq-surface, #fff);
	transition: border-color .18s ease, background .18s ease, transform .18s ease, box-shadow .18s ease;
}

.tewido-quote-cart--icon-only:hover {
	border-color: var(--tq-primary, #1d91b8);
	color: var(--tq-primary, #1d91b8);
	transform: translateY(-1px);
	box-shadow: 0 4px 14px rgba(17, 24, 39, .1);
}

.tewido-quote-cart--icon-only:active {
	transform: translateY(0);
}

.tewido-quote-cart__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
}

.tewido-quote-cart__icon svg {
	display: block;
	width: 1.25em;
	height: 1.25em;
}

.tewido-quote-cart__label {
	white-space: nowrap;
}

.tewido-quote-cart__count {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	min-width: 22px;
	height: 22px;
	padding: 0 6px;
	border-radius: 999px;
	background: var(--tq-primary, #1d91b8);
	color: var(--tq-on-primary, #fff);
	font-size: 12px;
	font-weight: 600;
	line-height: 1;
	font-variant-numeric: tabular-nums;
	transition: transform .18s ease, background .18s ease, color .18s ease;
}

/* A solid dot on the tinted field: the one saturated element in the
   control, so the eye lands on the number rather than on the chrome. */
.tewido-quote-cart--icon .tewido-quote-cart__count,
.tewido-quote-cart--text .tewido-quote-cart__count {
	min-width: 21px;
	height: 21px;
	padding: 0 6px;
	background: var(--tq-primary, #1d91b8);
	color: var(--tq-on-primary, #fff);
	font-size: 11.5px;
}

/* Riding the corner, and only when there is something to say. The badge is
   absolutely positioned here, so hiding it shifts nothing. */
.tewido-quote-cart--icon-only .tewido-quote-cart__count {
	position: absolute;
	inset-block-start: -3px;
	inset-inline-end: -3px;
	min-width: 18px;
	height: 18px;
	padding: 0 5px;
	font-size: 11px;
	/* A ring in the page background, so the badge reads as sitting on top of
	   the button rather than punched into it. */
	box-shadow: 0 0 0 2px var(--tq-surface, #fff);
}

.tewido-quote-cart--icon-only .tewido-quote-cart__count[data-empty="1"] {
	display: none;
}

/* Inside a pill the number is part of the control and always shown, so an
   empty list gets a plain dot cut out of the field rather than a saturated
   one announcing nothing. */
.tewido-quote-cart--icon .tewido-quote-cart__count[data-empty="1"],
.tewido-quote-cart--text .tewido-quote-cart__count[data-empty="1"] {
	background: var(--tq-surface, #fff);
	color: var(--tq-muted, #666);
	font-weight: 500;
}

.tewido-quote-cart__count[data-empty="0"] {
	animation: tewido-quote-pop .28s ease;
}

@keyframes tewido-quote-pop {
	0%   { transform: scale(1); }
	45%  { transform: scale(1.22); }
	100% { transform: scale(1); }
}

@media (prefers-reduced-motion: reduce) {
	.tewido-quote-cart__count[data-empty="0"] {
		animation: none;
	}

	.tewido-quote-cart--icon-only:hover {
		transform: none;
	}
}

/* ----------------------------------------------------------------- drawer */

.tewido-quote-locked {
	overflow: hidden;
}

.tewido-quote-drawer {
	position: fixed;
	inset: 0;
	z-index: 99990;
}

.tewido-quote-drawer[hidden] {
	display: none;
}

.tewido-quote-drawer__overlay {
	position: absolute;
	inset: 0;
	background: rgba(17, 24, 39, .5);
	opacity: 0;
	transition: opacity .25s ease;
}

.tewido-quote-drawer.is-open .tewido-quote-drawer__overlay {
	opacity: 1;
}

.tewido-quote-drawer__panel {
	position: absolute;
	inset-block: 0;
	inset-inline-end: 0;
	display: flex;
	flex-direction: column;
	width: min(420px, 100%);
	background: var(--tq-surface, #fff);
	box-shadow: -8px 0 40px rgba(0, 0, 0, .18);
	transform: translateX(100%);
	transition: transform .25s ease;
}

.tewido-quote-drawer.is-open .tewido-quote-drawer__panel {
	transform: translateX(0);
}

/* The panel takes focus when the drawer opens - see openDrawer() - and a ring
   around the whole dialog is noise rather than information. The controls
   inside keep theirs. */
.tewido-quote-drawer__panel:focus {
	outline: none;
}

.tewido-quote-drawer__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	padding: 18px 20px;
	border-bottom: 1px solid var(--tq-border, #d1d1d1);
}

.tewido-quote-drawer__title {
	margin: 0;
	font-size: 17px;
	font-weight: 600;
	color: var(--tq-text, #292929);
}

.tewido-quote-drawer__close,
/* A real button, not a loose glyph. It sat fully transparent until the
   pointer found it, which left a bare cross floating at the end of the row
   with nothing to say it was pressable - and next to the stepper it read
   as a stray character. A round surface in the row's own grey gives it a
   footprint; the red is held back for hover and focus, so a list of five
   rows is not five red warnings. */
.tewido-quote-row__remove {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 32px;
	height: 32px;
	margin-inline-start: 2px;
	padding: 0;
	border: 1px solid transparent;
	border-radius: 999px;
	background: var(--tq-surface-soft, #f7f7f7);
	color: var(--tq-muted, #666);
	cursor: pointer;
	transition: background .15s ease, color .15s ease, border-color .15s ease;
}

.tewido-quote-row__remove:hover,
.tewido-quote-row__remove:focus-visible {
	border-color: var(--tq-error, #dc2626);
	background: var(--tq-error-soft, rgba(220, 38, 38, .1));
	color: var(--tq-error, #dc2626);
}

/* Neutral, not red: closing the panel destroys nothing, and it shared the
   remove button's hover only because the two rules were written together. */
.tewido-quote-drawer__close:hover {
	background: var(--tq-surface-soft, #f7f7f7);
	color: var(--tq-text, #292929);
}

@media (prefers-reduced-motion: reduce) {
	.tewido-quote-row__remove {
		transition: none;
	}
}

.tewido-quote-drawer__body {
	flex: 1 1 auto;
	padding: 12px 20px;
	overflow-y: auto;
}

/* ---- the drawer's rows ----------------------------------------------
 *
 * 420px of panel, minus a 48px thumbnail, a stepper and a remove button,
 * is not much left for a product name - and the name is the only part of
 * the row the visitor is reading. Everything else is pulled in: a smaller
 * frame, a narrower stepper, tighter gaps, and the two controls grouped so
 * they take one gap between them rather than two.
 */
.tewido-quote-drawer .tewido-quote-row {
	gap: 10px;
	padding: 12px 0;
}

.tewido-quote-drawer .tewido-quote-row__media {
	width: 48px;
	height: 48px;
}

/* The quantity, stated rather than edited. */
.tewido-quote-row__qty {
	flex: 0 0 auto;
	color: var(--tq-text-body, #474747);
	font-size: 14px;
	font-variant-numeric: tabular-nums;
	white-space: nowrap;
}

.tewido-quote-drawer .tewido-quote-row__remove {
	width: 30px;
	height: 30px;
}

.tewido-quote-drawer .tewido-quote-skeleton--stepper {
	width: 46px;
	height: 18px;
}

.tewido-quote-drawer__foot {
	display: flex;
	gap: 10px;
	padding: 16px 20px;
	border-top: 1px solid var(--tq-border, #d1d1d1);
}

.tewido-quote-drawer__foot .tewido-quote-btn {
	flex: 1 1 auto;
}

/* ------------------------------------------------------------------- rows */

.tewido-quote-row {
	display: flex;
	align-items: center;
	gap: 12px;
	padding: 14px 0;
	border-bottom: 1px solid var(--tq-border-soft, #e8e8e8);
}

.tewido-quote-row:last-child {
	border-bottom: 0;
}

.tewido-quote-row__media {
	flex: 0 0 auto;
	width: 56px;
	height: 56px;
	overflow: hidden;
	border: 1px solid var(--tq-border, #d1d1d1);
	border-radius: var(--tq-radius, 8px);
	background: var(--tq-surface-soft, #f7f7f7);
}

.tewido-quote-row__media img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* The frame with no photo in it. Drawn anyway, so every row's text starts
   on the same vertical line. */
.tewido-quote-row__media--blank {
	display: grid;
	place-items: center;
	border-style: dashed;
	color: var(--tq-empty-art, #bababa);
}

.tewido-quote-row__main {
	flex: 1 1 auto;
	min-width: 0;
}

/* Two lines, then an ellipsis. `overflow-wrap: anywhere` is kept for the
   part code that is one 40-character token with nowhere to break, but the
   clamp is what stops a long name pushing the stepper around. */
.tewido-quote-row__title {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	color: var(--tq-text, #292929);
	font-weight: 600;
	line-height: 1.35;
	text-decoration: none;
	overflow-wrap: anywhere;
}

.tewido-quote-row__title:hover {
	color: var(--tq-primary, #1d91b8);
}

.tewido-quote-row__meta {
	margin: 3px 0 0;
	overflow: hidden;
	color: var(--tq-muted, #666);
	font-size: 12px;
	line-height: 1.4;
	white-space: nowrap;
	text-overflow: ellipsis;
}

/* ------------------------------------------------------- skeleton rows
 *
 * Shown while the names are fetched, one per line already in storage, so
 * the panel opens at its real height and nothing reflows when they land.
 */
.tewido-quote-skeleton {
	border-radius: var(--tq-radius-sm, 6px);
	background: var(--tq-border-soft, #e8e8e8);
	background-image: linear-gradient(90deg, transparent, rgba(255, 255, 255, .65), transparent);
	background-repeat: no-repeat;
	background-size: 160px 100%;
	background-position: -160px 0;
	animation: tewido-quote-shimmer 1.2s ease-in-out infinite;
}

@keyframes tewido-quote-shimmer {
	to { background-position: calc(100% + 160px) 0; }
}

.tewido-quote-row--skeleton .tewido-quote-row__media {
	border-style: solid;
	border-color: transparent;
}

.tewido-quote-skeleton--title,
.tewido-quote-skeleton--meta {
	display: block;
	height: 12px;
}

.tewido-quote-skeleton--title {
	width: min(100%, 180px);
}

.tewido-quote-skeleton--meta {
	width: min(100%, 120px);
	height: 10px;
	margin-block-start: 8px;
}

.tewido-quote-skeleton--stepper {
	flex: 0 0 auto;
	width: 104px;
	height: 36px;
}

@media (prefers-reduced-motion: reduce) {
	.tewido-quote-skeleton {
		animation: none;
	}
}

/* --------------------------------------------------------------- stepper */

.tewido-quote-stepper {
	display: inline-flex;
	align-items: stretch;
	flex: 0 0 auto;
	border: 1px solid var(--tq-border, #d1d1d1);
	border-radius: var(--tq-radius, 8px);
	overflow: hidden;
}

.tewido-quote-stepper__btn {
	width: 32px;
	padding: 0;
	border: 0;
	background: var(--tq-surface-soft, #f7f7f7);
	color: var(--tq-text, #292929);
	font-size: 16px;
	line-height: 1;
	cursor: pointer;
}

.tewido-quote-stepper__btn:hover {
	background: var(--tq-border-soft, #e8e8e8);
}

.tewido-quote-stepper__input {
	width: 52px;
	padding: 8px 4px;
	border: 0;
	border-inline: 1px solid var(--tq-border, #d1d1d1);
	background: var(--tq-surface, #fff);
	font: inherit;
	text-align: center;
	-moz-appearance: textfield;
	appearance: textfield;
}

.tewido-quote-stepper__input::-webkit-outer-spin-button,
.tewido-quote-stepper__input::-webkit-inner-spin-button {
	-webkit-appearance: none;
	margin: 0;
}

/* -------------------------------------------------------------- list page */

/* The heading row. The margin moved here from the title so the row still
   spaces correctly on a list with Clear and no heading. */
.tewido-quote-section__bar {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	margin: 0 0 16px;
}

.tewido-quote-section__title {
	margin: 0;
}

/* ---- clear the whole list -------------------------------------------
 *
 * Quiet on purpose, in both places it appears. It is not what the visitor
 * came to the list to do, and it must not read as the primary action next
 * to Continue or Close - but it is destructive, so it takes the error
 * colour on hover rather than the brand one, and it offers Undo instead of
 * asking a question first.
 */
.tewido-quote-clear {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	flex: 0 0 auto;
	padding: 6px 10px;
	border: 1px solid transparent;
	border-radius: var(--tq-radius-sm);
	background: none;
	color: var(--tq-muted);
	font: inherit;
	font-size: 13px;
	line-height: 1.2;
	cursor: pointer;
	transition: color .15s ease, border-color .15s ease, background-color .15s ease;
}

.tewido-quote-clear:hover {
	border-color: var(--tq-error);
	background: var(--tq-error-soft);
	color: var(--tq-error);
}

.tewido-quote-clear:focus-visible {
	outline: none;
	box-shadow: var(--tq-focus);
}

/* In the drawer head the title takes the slack, so Clear and Close sit
   together on the end instead of the three being spread across the row by
   the head's own `justify-content: space-between`. */
.tewido-quote-drawer__head .tewido-quote-clear {
	margin-inline-start: auto;
}

.tewido-quote-rows {
	margin: 0 0 20px;
}

/* ------------------------------------------------------------ empty state */

.tewido-quote-empty {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 6px;
	margin: 0;
	padding: 40px 24px;
	text-align: center;
}

.tewido-quote-empty__art {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 64px;
	height: 64px;
	margin-block-end: 6px;
	border-radius: 999px;
	background: var(--tq-surface-soft, #f7f7f7);
	color: var(--tq-empty-art, #bababa);
}

.tewido-quote-empty__art svg {
	width: 30px;
	height: 30px;
}

.tewido-quote-empty__title {
	margin: 0;
	color: var(--tq-text, #292929);
	font-size: 15px;
	font-weight: 600;
}

.tewido-quote-empty__hint {
	margin: 0;
	max-width: 32ch;
	color: var(--tq-muted, #666);
	font-size: 13px;
	line-height: 1.5;
}

/* The two routes out of an empty list, side by side under the message:
   browse the catalogue, or send the details as an enquiry without
   products. They wrap to a column on a narrow panel rather than shrinking
   into two stubs. */
.tewido-quote-empty__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 10px;
	margin-block-start: 16px;
}

/* The margin belongs to the row now. A lone button - the drawer's empty
   state, or a list with no Browse URL set - keeps its own. */
.tewido-quote-empty > .tewido-quote-btn {
	margin-block-start: 14px;
}

@media (max-width: 420px) {
	.tewido-quote-empty__actions {
		flex-direction: column;
		align-self: stretch;
	}

	.tewido-quote-empty__actions .tewido-quote-btn {
		justify-content: center;
		width: 100%;
	}
}

.tewido-quote-noscript {
	margin: 0;
	padding: 20px 0;
	color: var(--tq-muted, #666);
}

.tewido-quote-noscript {
	padding: 14px 16px;
	border: 1px solid var(--tq-border, #d1d1d1);
	border-radius: var(--tq-radius, 8px);
	background: var(--tq-surface-soft, #f7f7f7);
}

.tewido-quote-empty-state {
	padding: 28px 0;
	text-align: center;
	color: var(--tq-muted, #666);
}

.tewido-quote-empty-state[hidden] {
	display: none;
}

/* ------------------------------------------------------------------- form */

.tewido-quote-form__grid {
	display: grid;
	gap: 16px;
	margin: 0 0 16px;
}

.tewido-quote-form--cols-2 .tewido-quote-form__grid {
	grid-template-columns: repeat(2, minmax(0, 1fr));
}

.tewido-quote-form--cols-2 .tewido-quote-field--notes {
	grid-column: 1 / -1;
}

@media (max-width: 640px) {
	.tewido-quote-form--cols-2 .tewido-quote-form__grid {
		grid-template-columns: 1fr;
	}
}

.tewido-quote-field {
	margin: 0;
}

.tewido-quote-field__label {
	display: block;
	margin-block-end: 6px;
	font-size: 13px;
	font-weight: 600;
	color: var(--tq-text, #292929);
}

.tewido-quote-field__req {
	color: var(--tq-error, #dc2626);
}

.tewido-quote-field__input {
	display: block;
	width: 100%;
	box-sizing: border-box;
	min-height: 44px;
	padding: 10px 14px;
	border: 1px solid var(--tq-border, #d1d1d1);
	border-radius: var(--tq-radius, 8px);
	background: var(--tq-surface, #fff);
	color: var(--tq-text, #292929);
	font: inherit;
}

textarea.tewido-quote-field__input {
	min-height: 110px;
	resize: vertical;
}

.tewido-quote-field__input[aria-invalid="true"] {
	border-color: var(--tq-error, #dc2626);
}

.tewido-quote-field__error:empty {
	display: none;
}

.tewido-quote-field__error {
	display: block;
	margin-block-start: 5px;
	color: var(--tq-error, #dc2626);
	font-size: 12px;
}

.tewido-quote-field__hint {
	display: block;
	margin-block-start: 5px;
	color: var(--tq-muted, #666);
	font-size: 12px;
}

/* Checkbox and file input follow the host Form widget's treatment exactly -
   same box, same tick geometry, same upload button - so the two forms are
   indistinguishable on a page that carries both. */

.tewido-quote-consent {
	display: inline-flex;
	align-items: flex-start;
	gap: 10px;
	cursor: pointer;
	font-size: 14px;
	line-height: 1.5;
	user-select: none;
}

.tewido-quote-consent input[type="checkbox"] {
	appearance: none;
	-webkit-appearance: none;
	display: grid;
	place-content: center;
	flex-shrink: 0;
	width: 18px;
	height: 18px;
	margin: 2px 0 0;
	border: 2px solid var(--tq-check-border, #bababa);
	border-radius: 4px;
	background: var(--tq-surface, #fff);
	cursor: pointer;
	transition: .2s;
}

.tewido-quote-consent:hover input[type="checkbox"] {
	border-color: var(--tq-check-hover, #666);
}

.tewido-quote-consent input[type="checkbox"]:checked {
	border-color: var(--tq-primary, #1d91b8);
	background: var(--tq-primary, #1d91b8);
}

.tewido-quote-consent input[type="checkbox"]:checked::after {
	content: "";
	width: 5px;
	height: 9px;
	margin-top: -1px;
	border: solid #fff;
	border-width: 0 2px 2px 0;
	transform: rotate(45deg);
}

.tewido-quote-consent input[type="checkbox"]:focus-visible {
	outline: 0;
	border-color: var(--tq-primary, #1d91b8);
	box-shadow: var(--tq-focus, 0 0 0 3px rgba(29, 145, 184, .3));
}

/* The privacy link is a sibling of the label rather than a child of it, so it
   needs to be told to read as part of the same sentence. */
.tewido-quote-consent__privacy {
	font-size: 14px;
	line-height: 1.5;
	margin-inline-start: 4px;
}

/*
 * Forced colours (Windows High Contrast and friends) replace background,
 * border and box-shadow with system values, which takes out both the tick and
 * the focus ring on a checkbox drawn from those three properties. Handing the
 * control back to the platform is more reliable than restyling it: the native
 * box already has a contrast-correct checked and focused state.
 */
@media (forced-colors: active) {
	.tewido-quote-consent input[type="checkbox"] {
		appearance: auto;
		-webkit-appearance: auto;
	}

	.tewido-quote-consent input[type="checkbox"]:checked::after {
		content: none;
	}

	.tewido-quote-consent input[type="checkbox"]:focus-visible,
	.tewido-quote-btn:focus-visible,
	.tewido-quote-add:focus-visible,
	.tewido-quote-cart:focus-visible,
	.tewido-quote-field__input:focus-visible,
	.tewido-quote-stepper__btn:focus-visible,
	.tewido-quote-stepper__input:focus-visible,
	.tewido-quote-row__remove:focus-visible,
	.tewido-quote-steps__btn:focus-visible,
	.tewido-quote-drawer__close:focus-visible {
		outline: 2px solid CanvasText;
		outline-offset: 2px;
	}
}

.tewido-quote-field__file {
	width: 100%;
	font-size: 14px;
	color: var(--tq-text-body, #474747);
}

.tewido-quote-field__file::-webkit-file-upload-button,
.tewido-quote-field__file::file-selector-button {
	margin-inline-end: 12px;
	padding: 8px 14px;
	border: 0;
	border-radius: var(--tq-radius-sm, 6px);
	background: var(--tq-primary, #1d91b8);
	color: var(--tq-on-primary, #fff);
	font-size: 13px;
	font-weight: 500;
	cursor: pointer;
	transition: opacity .15s;
}

.tewido-quote-field__file::-webkit-file-upload-button:hover,
.tewido-quote-field__file::file-selector-button:hover {
	opacity: .85;
}

.tewido-quote-files {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin-block-start: 8px;
}

.tewido-quote-files__chip {
	padding: 4px 10px;
	border-radius: 999px;
	background: var(--tq-surface-soft, #f7f7f7);
	border: 1px solid var(--tq-border, #d1d1d1);
	font-size: 12px;
	color: var(--tq-muted, #666);
}

.tewido-quote-form__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
	margin-block-start: 20px;
}

/* WhatsApp sits at the far end of the row, not shoulder to shoulder with the
   submit. They are not a pair of equal choices: one sends the request that
   was just filled in, the other abandons the form for a chat. The auto margin
   is logical, so "the end" follows the text direction. */
.tewido-quote-btn--whatsapp {
	margin-inline-start: auto;
}

@media (max-width: 560px) {
	/* Stacked, the auto margin would only add a gap above. Full width reads
	   as two stacked choices instead of a short button adrift. */
	.tewido-quote-form__actions > .tewido-quote-btn {
		flex: 1 1 100%;
		margin-inline-start: 0;
	}
}

.tewido-quote-form__summary,
.tewido-quote-form__done,
.tewido-quote-form__empty {
	margin: 0 0 16px;
	padding: 12px 16px;
	border-radius: var(--tq-radius, 8px);
	font-size: 14px;
}

.tewido-quote-form__summary {
	border: 1px solid var(--tq-error, #dc2626);
	background: rgba(220, 38, 38, .06);
	color: var(--tq-error, #dc2626);
}

.tewido-quote-form__done {
	border: 1px solid var(--tq-success, #16a34a);
	background: rgba(22, 163, 74, .08);
	color: #14532d;
	font-weight: 600;
}

.tewido-quote-form__empty {
	border: 1px solid var(--tq-border, #d1d1d1);
	background: var(--tq-surface-soft, #f7f7f7);
	color: var(--tq-muted, #666);
}

/* A hint now, not a blocker, so it stays quiet - and its paragraph takes
   the box's own spacing rather than the theme's. */
.tewido-quote-form__empty p {
	margin: 0;
	line-height: 1.5;
}

.tewido-quote-form__summary[hidden],
.tewido-quote-form__done[hidden],
.tewido-quote-form__empty[hidden] {
	display: none;
}

/* The honeypot is moved off-screen rather than hidden: display:none is the
   shape bots look for, and a hidden input they skip is a free pass. */
.tewido-quote-hp {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* ------------------------------------------------------------ preferences */

@media (prefers-reduced-motion: reduce) {
	.tewido-quote-drawer__panel,
	.tewido-quote-drawer__overlay,
	.tewido-quote-btn,
	.tewido-quote-add {
		transition: none;
	}
}

/* The editor's stand-in for a widget that renders nothing on a page with no
   product behind it. Never emitted on the front end. */
.tewido-quote-ghost {
	padding: 18px;
	border: 1px dashed var(--tq-border, #d1d1d1);
	border-radius: var(--tq-radius, 8px);
	background: var(--tq-surface-soft, #f7f7f7);
	color: var(--tq-muted, #666);
	font-size: 13px;
	text-align: center;
}

/* Hydration is one batched request per change of the id set; a quantity step
   repaints from the cache with no round trip at all. */
.tewido-quote-drawer__body.is-loading,
.tewido-quote-rows.is-loading {
	min-height: 80px;
	opacity: .55;
	background-image: linear-gradient(90deg, transparent 0%, rgba(0, 0, 0, .04) 50%, transparent 100%);
	background-size: 200% 100%;
	animation: tewido-quote-shimmer 1.1s ease-in-out infinite;
}

@keyframes tewido-quote-shimmer {
	from { background-position: 200% 0; }
	to   { background-position: -200% 0; }
}

@media (prefers-reduced-motion: reduce) {
	.tewido-quote-drawer__body.is-loading,
	.tewido-quote-rows.is-loading {
		animation: none;
	}
}

/* ------------------------------------------------------------------ steps */

.tewido-quote-request {
	--tq-primary: var(--tewido-elementra-color-primary, #1d91b8);
	--tq-primary-hover: var(--tewido-elementra-color-primary-600, #197b9c);
	--tq-on-primary: var(--tewido-elementra-color-on-brand, #fff);
	--tq-surface: var(--tewido-elementra-color-surface, #fff);
	--tq-surface-soft: var(--tewido-elementra-color-gray-50, #f7f7f7);
	--tq-border: var(--tewido-elementra-color-gray-200, #d1d1d1);
	--tq-border-soft: var(--tewido-elementra-color-gray-100, #e8e8e8);
	--tq-text: var(--tewido-elementra-color-heading, #292929);
	--tq-muted: var(--tewido-elementra-color-gray-500, #666);
	--tq-radius: 8px;
}

.tewido-quote-steps {
	display: flex;
	align-items: flex-start;
	justify-content: center;
	margin: 0 0 32px;
	padding: 0;
	list-style: none;
}

.tewido-quote-steps__item {
	position: relative;
	flex: 0 0 auto;
	width: 150px;
	text-align: center;
}

/* The rail between two circles. It runs from the previous circle's centre to
   just before this one, and the circles sit on top of its ends. */
.tewido-quote-steps__item + .tewido-quote-steps__item::before {
	content: "";
	position: absolute;
	inset-block-start: 16px;
	/* Circle edge to circle edge: half an item each side, less the 17px
	   radius and a 5px breath, or the rail pokes out past the first circle. */
	inset-inline-end: calc(50% + 22px);
	width: calc(100% - 44px);
	height: 2px;
	background: var(--tq-border, #d1d1d1);
	transition: background .2s ease;
}

.tewido-quote-steps__item.is-active::before,
.tewido-quote-steps__item.is-done::before {
	background: var(--tq-primary, #1d91b8);
}

.tewido-quote-steps__btn {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 10px;
	width: 100%;
	padding: 0;
	border: 0;
	background: none;
	color: var(--tq-muted, #666);
	font-family: inherit;
	font-size: 13px;
	font-weight: 600;
	line-height: 1.3;
	cursor: default;
}

/* Enabled means completed, which is the only step you can jump back to. */
.tewido-quote-steps__btn:not([disabled]) {
	cursor: pointer;
}

.tewido-quote-steps__btn:not([disabled]):hover .tewido-quote-steps__label {
	color: var(--tq-primary, #1d91b8);
}

.tewido-quote-steps__btn:focus-visible {
	outline: none;
}

.tewido-quote-steps__btn:focus-visible .tewido-quote-steps__num {
	box-shadow: var(--tq-focus, 0 0 0 3px rgba(29, 145, 184, .3));
}

.tewido-quote-steps__num {
	position: relative;
	z-index: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	border: 2px solid var(--tq-border, #d1d1d1);
	border-radius: 999px;
	background: var(--tq-surface, #fff);
	color: var(--tq-muted, #666);
	font-size: 14px;
	font-weight: 700;
	transition: border-color .2s ease, background .2s ease, color .2s ease;
}

.tewido-quote-steps__item.is-active .tewido-quote-steps__num,
.tewido-quote-steps__item.is-done .tewido-quote-steps__num {
	border-color: var(--tq-primary, #1d91b8);
	background: var(--tq-primary, #1d91b8);
	color: var(--tq-on-primary, #fff);
}

/* A finished step shows a tick instead of its number. */
.tewido-quote-steps__item.is-done .tewido-quote-steps__num {
	font-size: 0;
}

.tewido-quote-steps__item.is-done .tewido-quote-steps__num::after {
	content: "";
	width: 6px;
	height: 11px;
	margin-block-start: -2px;
	border: solid var(--tq-on-primary, #fff);
	border-width: 0 2px 2px 0;
	transform: rotate(45deg);
}

.tewido-quote-steps__label {
	display: block;
	color: inherit;
	transition: color .2s ease;
}

.tewido-quote-steps__item.is-active .tewido-quote-steps__label {
	color: var(--tq-text, #292929);
}

@media (max-width: 480px) {
	.tewido-quote-steps__item {
		width: 120px;
	}

	.tewido-quote-steps__label {
		font-size: 12px;
	}
}

.tewido-quote-panel:focus {
	outline: none;
}

.tewido-quote-panel[hidden] {
	display: none;
}

.tewido-quote-panel__nav {
	display: flex;
	justify-content: flex-end;
	margin-block-start: 20px;
	padding-block-start: 20px;
	border-top: 1px solid var(--tq-border-soft, #e8e8e8);
}

/* A real control rather than a line of text with an arrow next to it: it sits
   above the form with nothing else around it, so it needs an edge to read as
   something you can press. */
.tewido-quote-back {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	margin: 0 0 22px;
	padding: 8px 14px 8px 12px;
	border: 1px solid var(--tq-border-soft, #e8e8e8);
	border-radius: 999px;
	background: var(--tq-surface, #fff);
	color: var(--tq-text-body, #474747);
	font-family: inherit;
	font-size: 14px;
	font-weight: 600;
	line-height: 1.2;
	cursor: pointer;
	transition: background .15s ease, border-color .15s ease, color .15s ease;
}

.tewido-quote-back .tewido-quote-icon {
	/* Nudged on hover, in the direction the button actually goes - which is
	   mirrored under dir="rtl", so the transform is set in quote-rtl.css. */
	transition: transform .15s ease;
}

.tewido-quote-back:hover,
.tewido-quote-back:focus-visible {
	border-color: var(--tq-primary, #1d91b8);
	background: var(--tq-primary-soft, #f2fafd);
	color: var(--tq-primary, #1d91b8);
}

.tewido-quote-back:hover .tewido-quote-icon {
	transform: translateX(-2px);
}

.tewido-quote-back:focus-visible {
	outline: 2px solid var(--tq-primary, #1d91b8);
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	.tewido-quote-back,
	.tewido-quote-back .tewido-quote-icon {
		transition: none;
	}

	.tewido-quote-back:hover .tewido-quote-icon {
		transform: none;
	}
}

@media (max-width: 480px) {
	.tewido-quote-steps__label {
		display: none;
	}
}

.tewido-quote-panel__nav[hidden] {
	display: none;
}

/* Both set `display` in a class rule above, which beats the UA sheet's
   single-attribute `[hidden]` rule - so without these they would stay on
   screen with the attribute correctly set. */
.tewido-quote-section__title[hidden],
.tewido-quote-section__bar[hidden],
.tewido-quote-clear[hidden] {
	display: none;
}

/* ------------------------------------------------------- product search ---
 *
 * One bar: the two filter selects, the input and the submit, sharing a border
 * so they read as a single control. The dropdown is positioned against
 * `.tewido-quote-search`, not the bar, so the Popular row underneath does not
 * push it out of alignment.
 */
.tewido-quote-search {
	--tewido-quote-search-height: 56px;
	/* The icon-only submit's width on a phone. Read twice in the narrow
	   layout below - as the button's size and as what the input leaves it on
	   the row - so the two cannot drift apart. */
	--tq-search-icon-width: 52px;
	position: relative;
	width: 100%;
}

.tewido-quote-search__form {
	margin: 0;
}

.tewido-quote-search__bar {
	display: flex;
	align-items: stretch;
	min-height: var(--tewido-quote-search-height);
	background: var(--tq-surface);
	/* The host's own input border, not a hard black: this bar sits beside
	   Elementra's controls and has to read as one of them. */
	border: 1px solid var(--tq-border);
	border-radius: var(--tq-radius);
	/* The children sit flush to the border, and the submit fills the end
	   cap, so anything overflowing has to be clipped to the radius. */
	overflow: hidden;
}

.tewido-quote-search__bar:focus-within {
	border-color: var(--tq-primary);
	box-shadow: var(--tq-focus);
}

.tewido-quote-search__filter {
	display: flex;
	align-items: stretch;
	border-inline-end: 1px solid var(--tq-border);
}

.tewido-quote-search__select {
	appearance: none;
	border: 0;
	background: transparent;
	padding-block: 0;
	padding-inline: 16px 34px;
	max-width: 190px;
	color: var(--tq-text-body);
	font: inherit;
	cursor: pointer;
	/* The native arrow is what `appearance: none` just removed. Drawn as a
	   background so it mirrors with the padding under RTL. */
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8' fill='none' stroke='%23666' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m1 1 5 5 5-5'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 14px center;
	background-size: 12px 8px;
}

.tewido-quote-search__select:focus-visible {
	outline: none;
	box-shadow: var(--tq-focus);
}

.tewido-quote-search__field {
	flex: 1 1 auto;
	display: flex;
	min-width: 0;
}

.tewido-quote-search__input {
	flex: 1 1 auto;
	min-width: 0;
	border: 0;
	background: transparent;
	padding-block: 0;
	padding-inline: 20px;
	color: var(--tq-text);
	font: inherit;
	/* The UA's own clear button sits under the dropdown and clears the field
	   without telling the script, leaving stale results on screen. */
	appearance: none;
}

.tewido-quote-search__input::-webkit-search-cancel-button,
.tewido-quote-search__input::-webkit-search-decoration {
	display: none;
}

.tewido-quote-search__input:focus {
	outline: none;
}

/*
 * The clear button, inside the field rather than beside it: it belongs to the
 * text, not to the bar. Shown by the script only once there is something to
 * clear, so it never sits there doing nothing.
 */
.tewido-quote-search__clear {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	align-self: center;
	width: 28px;
	height: 28px;
	margin-inline-end: 10px;
	padding: 0;
	border: 0;
	border-radius: 999px;
	background: transparent;
	color: var(--tq-muted);
	cursor: pointer;
	transition: background-color .15s ease, color .15s ease;
}

.tewido-quote-search__clear:hover {
	background: var(--tq-border-soft);
	color: var(--tq-text);
}

.tewido-quote-search__clear:focus-visible {
	outline: none;
	box-shadow: var(--tq-focus);
	color: var(--tq-text);
}

.tewido-quote-search__clear svg {
	width: 16px;
	height: 16px;
	pointer-events: none;
}

.tewido-quote-search__submit {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	min-width: 120px;
	padding-inline: 24px;
	border: 0;
	background: var(--tq-primary);
	color: var(--tq-on-primary);
	font: inherit;
	font-weight: 600;
	cursor: pointer;
	transition: background-color .15s ease;
}

/* Icon only. The label is still in the markup - it is the button's accessible
   name and its tooltip - so it is hidden here rather than left out there.
   `display:none` and not a visually-hidden box, because an off-screen span
   inside a flex row still counts as a child and would leave the `gap` above
   sitting beside the glyph. */
.tewido-quote-search__submit--icon .tewido-quote-search__submit-label {
	display: none;
}

/* Square, not a 120px bar holding one glyph. `min-width` is what the widget's
   Width control writes, so an editor who sets one still wins on specificity. */
.tewido-quote-search__submit--icon {
	min-width: 0;
	padding-inline: 18px;
}

.tewido-quote-search__submit:hover {
	background: var(--tq-primary-hover);
}

.tewido-quote-search__submit:focus-visible {
	outline: none;
	box-shadow: inset var(--tq-focus);
}

/* ---------------------------------------------------- the popular chips */

.tewido-quote-search__popular {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin-block-start: 14px;
}

.tewido-quote-search__popular-label {
	color: var(--tq-muted);
	font-size: 14px;
}

.tewido-quote-search__chip {
	padding: 7px 14px;
	background: var(--tq-surface-soft);
	border: 1px solid var(--tq-border-soft);
	border-radius: var(--tq-radius-sm);
	color: var(--tq-text-body);
	font: inherit;
	font-size: 14px;
	cursor: pointer;
	/* Padding and radius are in the list because the widget can now set both
	   for the hover state. Without them a chip that changes size on hover
	   snaps rather than moves, which reads as a glitch next to the colours
	   easing beside it. */
	transition:
		background-color .15s ease,
		border-color .15s ease,
		color .15s ease,
		padding .15s ease,
		border-radius .15s ease;
}

/* `:focus-visible` carried with `:hover`, which is the rule the widget's own
   hover controls follow and this one did not. An editor who sets only the
   hover BACKGROUND gets a selector pairing both states, so a keyboard focus
   took the new background from that rule while the border and text colours
   stayed at rest here - a half-applied state no pointer user ever sees, and
   on a dark custom background the unreadable one. */
/* Three classes deep deliberately, where one would read better. The widget's
   Normal tab generates `{{WRAPPER}} .tewido-quote-search__chip`, which is at
   least (0,3,0), and `background-color` from it beat `background` here on
   specificity alone - so an editor who set the chips' resting background and
   never opened the Hover tab silently lost this state entirely, leaving a
   chip with no pointer and no keyboard feedback at all. At (0,4,0) the
   default outranks the generated resting rule and still loses to the
   generated hover one, which is the order that was intended. */
.tewido-quote-search .tewido-quote-search__popular .tewido-quote-search__chip:hover,
.tewido-quote-search .tewido-quote-search__popular .tewido-quote-search__chip:focus-visible {
	background: var(--tq-primary-soft);
	border-color: var(--tq-primary);
	color: var(--tq-primary);
}

/* The ring is focus-only: hover does not get one. */
.tewido-quote-search__chip:focus-visible {
	outline: none;
	box-shadow: var(--tq-focus);
}

/* -------------------------------------------------------- the dropdown */

.tewido-quote-search__results {
	position: absolute;
	inset-inline: 0;
	/* Anchored to the bar's height rather than to the form, so the Popular
	   row below never shifts it. */
	inset-block-start: calc(var(--tewido-quote-search-height) + 6px);
	z-index: 50;
	/* Capped by the room the script measured, where it measured any: a panel
	   taller than the viewport scrolls its own list off the screen. */
	max-height: min(420px, var(--tq-search-space, 420px));
	overflow-y: auto;
	background: var(--tq-surface);
	border: 1px solid var(--tq-border);
	border-radius: var(--tq-radius);
	box-shadow: 0 12px 32px rgba(0, 0, 0, .12);
}

/*
 * Opening above the bar: the editor's choice, or what the script settles on
 * under Automatic when the room below would cut the list off. The panel is
 * anchored to the bar's own top edge - `100%` of the widget plus the gap - so
 * the Popular row underneath never moves it, the same reason the downward
 * anchor is the bar's height rather than the form's.
 */
.tewido-quote-search--results-above .tewido-quote-search__results,
.tewido-quote-search.is-results-above .tewido-quote-search__results {
	inset-block-start: auto;
	inset-block-end: calc(100% + 6px);
	box-shadow: 0 -12px 32px rgba(0, 0, 0, .12);
}

.tewido-quote-search__result {
	display: flex;
	align-items: center;
	gap: 14px;
	padding: 10px 14px;
	border-block-end: 1px solid var(--tq-border-soft);
	cursor: default;
}

.tewido-quote-search__result:last-child {
	border-block-end: 0;
}

.tewido-quote-search__result:hover,
.tewido-quote-search__result.is-active {
	background: var(--tq-surface-soft);
}

.tewido-quote-search__thumb {
	flex: 0 0 auto;
	width: 44px;
	height: 44px;
	object-fit: cover;
	border-radius: var(--tq-radius-sm);
	background: var(--tq-surface-soft);
}

/* A plain soft tile, not a dashed outline: a catalogue with no featured
   images shows one of these on every row, and dashes read as "broken" when
   they are the normal case. */
.tewido-quote-search__thumb--empty {
	display: block;
	background: var(--tq-surface-soft);
	border: 1px solid var(--tq-border-soft);
}

.tewido-quote-search__body {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	flex-direction: column;
	gap: 2px;
}

.tewido-quote-search__name {
	color: var(--tq-text);
	font-weight: 600;
	line-height: 1.3;
	text-decoration: none;
	/* A long product name must not push the Add button off the row. */
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.tewido-quote-search__name:hover {
	color: var(--tq-primary);
	text-decoration: underline;
}

.tewido-quote-search__meta {
	color: var(--tq-muted);
	font-size: 13px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

/* A square icon button: the cart glyph while the product is off the list,
   a tick once it is on. Sized from one number so the row height never
   changes between the two states. */
.tewido-quote-search__add {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: 38px;
	height: 38px;
	padding: 0;
	background: var(--tq-primary);
	border: 1px solid var(--tq-primary);
	border-radius: var(--tq-radius-sm);
	color: var(--tq-on-primary);
	font: inherit;
	cursor: pointer;
	transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}

/* `line-height: 0` so the inline SVG contributes no text leading and sits
   dead centre in the square. The on-list rule further down hides the cart
   in its turn - it is later in the sheet at the same specificity, which is
   what makes the swap work. */
.tewido-quote-search__add .tewido-quote-add__label,
.tewido-quote-search__add.is-on-list .tewido-quote-add__state--added {
	display: inline-flex;
	align-items: center;
	line-height: 0;
}

.tewido-quote-search__add:hover {
	background: var(--tq-primary-hover);
	border-color: var(--tq-primary-hover);
}

.tewido-quote-search__add:focus-visible {
	outline: none;
	box-shadow: var(--tq-focus);
}

/* ----------------------------------------------- the added-state toggle ---
 *
 * The Add control once its product is on the list: the same button, with
 * its cart icon and label swapped for a tick and "Added" in green. The
 * label is in the markup and swapped here, so the state needs no scripting
 * and the string comes from the catalogue.
 *
 * Shared by the Add to Quote widget and the Product Search rows.
 */
.tewido-quote-add__state {
	display: none;
	align-items: center;
	gap: 6px;
	white-space: nowrap;
}

/* ---- the confirmation, ~300ms of motion and no waiting --------------
 *
 * Adding writes to localStorage and returns in the same tick, so there is
 * nothing to spin for. The problem a spinner would have been reaching for
 * is real though - the change lands so fast it does not register - and the
 * answer is to make the change itself legible, not to invent a delay. The
 * click stays instant and a second one lands immediately.
 */
@keyframes tewido-quote-pop {
	0%   { transform: scale(1); }
	35%  { transform: scale(.96); }
	100% { transform: scale(1); }
}

@keyframes tewido-quote-draw {
	to { stroke-dashoffset: 0; }
}

@keyframes tewido-quote-bump {
	0%   { transform: scale(1); }
	40%  { transform: scale(1.35); }
	100% { transform: scale(1); }
}

.tewido-quote-add.is-just-added,
.tewido-quote-search__add.is-just-added {
	animation: tewido-quote-pop .22s ease-out;
}

.tewido-quote-add__tick path {
	/* 24 units of viewBox is longer than the path, which only has to be
	   enough to hide it; the exact length does not matter for a dash this
	   short. */
	stroke-dasharray: 24;
	stroke-dashoffset: 24;
}

.is-just-added .tewido-quote-add__tick path {
	animation: tewido-quote-draw .26s .06s ease-out forwards;
}

/* Settled state - the tick is simply there, with no animation to replay
   on a later repaint or after a reload. */
.is-on-list:not(.is-just-added) .tewido-quote-add__tick path {
	stroke-dashoffset: 0;
}

/* The badge the item just flew into. Bumped only when the count rises, so
   removing something does not celebrate. */
.tewido-quote-cart__count.is-bumped {
	animation: tewido-quote-bump .3s ease-out;
}

@media (prefers-reduced-motion: reduce) {
	.tewido-quote-add.is-just-added,
	.tewido-quote-search__add.is-just-added,
	.tewido-quote-cart__count.is-bumped {
		animation: none;
	}

	/* Still drawn, just not animated into place. */
	.tewido-quote-add__tick path {
		stroke-dashoffset: 0;
	}

	.is-just-added .tewido-quote-add__tick path {
		animation: none;
	}
}

/* Added: the cart icon and the resting label give way to a tick and
   "Added". Nothing else about the button moves - the background, border,
   radius, padding and size the editor set stay exactly as they were, so the
   control does not appear to have been replaced by a different one. */
.is-on-list .tewido-quote-add__label,
.is-on-list .tewido-quote-icon {
	display: none;
}

.is-on-list .tewido-quote-add__state--added {
	display: inline-flex;
}

/* Solid green, white label. `!important` because this has to beat the
   Button tab's own Normal AND Hover colours, and Elementor writes those as
   `.elementor-NNN .elementor-element-XXX .tewido-quote-add(:hover)` - four
   levels of specificity in a sheet that loads after this one. The state is
   not a style choice the editor overrides; it is the control reporting what
   happened. Everything else - size, radius, border width, padding,
   typography - is still the editor's and is left alone. */
.tewido-quote-add.is-on-list,
.tewido-quote-add.is-on-list:hover,
.tewido-quote-add.is-on-list:focus-visible,
.tewido-quote-search__add.is-on-list,
.tewido-quote-search__add.is-on-list:hover,
.tewido-quote-search__add.is-on-list:focus-visible,
.tewido-quote-bundle__add.is-on-list,
.tewido-quote-bundle__add.is-on-list:hover,
.tewido-quote-bundle__add.is-on-list:focus-visible {
	background: var(--tq-success, #16a34a) !important;
	border-color: var(--tq-success, #16a34a) !important;
	color: var(--tq-on-success, #fff) !important;
	/* Said its piece. The stepper beside it is what changes the line now,
	   so the button no longer advertises itself as clickable. */
	cursor: default;
}

/* The exception to the line above: a complete bundle's button still has
   work to do - pressing it puts back any line that was removed - so it
   keeps the pointer even while it is reporting the bundle is on the list. */
.tewido-quote-bundle__add.is-on-list {
	cursor: pointer;
}

.tewido-quote-search__none,
.tewido-quote-search__more {
	margin: 0;
	padding: 14px;
	color: var(--tq-muted);
	font-size: 14px;
	text-align: center;
}

.tewido-quote-search__more {
	border-block-start: 1px solid var(--tq-border-soft);
}

/* The two selects stop being usable long before the bar does, so they move
   above the input rather than shrinking with it. */
@media (max-width: 782px) {
	.tewido-quote-search__bar {
		flex-wrap: wrap;
	}

	.tewido-quote-search__filter {
		flex: 1 1 50%;
		border-inline-end: 0;
		border-block-end: 1px solid var(--tq-border);
	}

	.tewido-quote-search__filter + .tewido-quote-search__filter {
		border-inline-start: 1px solid var(--tq-border);
	}

	.tewido-quote-search__select {
		width: 100%;
		max-width: none;
		padding-block: 12px;
	}

	.tewido-quote-search__field {
		flex: 1 1 100%;
	}

	/* The icon button is one glyph wide, so it shares the input's row rather
	   than wrapping under it - which left the button in the corner with the
	   rest of that row empty beside it. The wording-only button keeps the
	   whole row to itself: at this width there is not room for both. The
	   `:has` is the same arrangement the cart button uses above; without it
	   the layout falls back to the stacked one.

	   The basis is the row less the button exactly, not `auto`: it has to
	   leave the button room on this line while still being wide enough that
	   a filter above - 50% of the row, or 100% once it grows - cannot pull
	   the field up beside it. */
	.tewido-quote-search__bar:has(.tewido-quote-search__submit--icon)
		.tewido-quote-search__field {
		flex: 1 1 calc(100% - var(--tq-search-icon-width));
	}

	.tewido-quote-search__input {
		padding-block: 14px;
		/* 4px back from the desktop inset: the button now shares this row,
		   and the placeholder is the first thing the narrower field clips. */
		padding-inline: 16px;
	}

	.tewido-quote-search__submit {
		flex: 1 1 100%;
		padding-block: 14px;
	}

	.tewido-quote-search__submit--icon {
		flex: 0 0 auto;
		/* Square against the input beside it, and no smaller than a finger.
		   `min-width` is still what the widget's Width control writes, so an
		   editor who sets one keeps winning on specificity - and a button
		   they have widened wraps to its own row again, which is the right
		   answer for one they asked to be wide. */
		align-self: stretch;
		min-width: var(--tq-search-icon-width);
		padding-inline: 14px;
	}

	/* The bar is now taller than the variable says, so the dropdown is
	   placed by flow instead of by that measurement. */
	/* The panel follows the bar in the flow here, so neither the flip nor the
	   measured cap applies - there is nothing to overlap and nowhere to flip
	   to. Both are reset rather than left to win by specificity. */
	.tewido-quote-search__results,
	.tewido-quote-search--results-above .tewido-quote-search__results,
	.tewido-quote-search.is-results-above .tewido-quote-search__results {
		position: static;
		margin-block-start: 8px;
		max-height: 60vh;
		box-shadow: 0 12px 32px rgba(0, 0, 0, .12);
	}

	/* At this width a single ellipsised line leaves about twelve characters
	   of a product name - "4021 membran..." - which is not enough to choose
	   by. Two wrapped lines and a narrower button give it room. */
	.tewido-quote-search__name {
		white-space: normal;
		display: -webkit-box;
		-webkit-line-clamp: 2;
		-webkit-box-orient: vertical;
		overflow: hidden;
	}

	.tewido-quote-search__result {
		align-items: flex-start;
		gap: 10px;
	}

	.tewido-quote-search__add {
		width: 34px;
		height: 34px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.tewido-quote-search__chip,
	.tewido-quote-search__submit,
	.tewido-quote-search__add {
		transition: none;
	}
}

/* ------------------------------------------------------------- bundles ---
 *
 * The ready-made systems, as a grid of cards. The grid's column count comes
 * from the widget, so the rule here is only the fallback for a theme that
 * renders the template without one.
 */
.tewido-quote-bundles__grid {
	display: grid;
	/* auto-fill and not auto-fit: with one card on a wide screen auto-fit
	   collapses the empty tracks and stretches it to the full width, which
	   on a three-column section is a card four times the size of the ones
	   beside it the day a second bundle is added. */
	grid-template-columns: repeat(auto-fill, minmax(min(100%, 260px), 1fr));
	gap: 20px;
}

/* A column, so the button sits on the bottom edge of every card in a row
   whatever its description runs to. */
.tewido-quote-bundle {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	border: 1px solid var(--tq-border);
	border-radius: var(--tq-radius-lg);
	background: var(--tq-surface);
	transition: border-color .15s ease, box-shadow .15s ease;
}

.tewido-quote-bundle:hover {
	border-color: var(--tq-primary);
	box-shadow: 0 8px 24px rgba(0, 0, 0, .07);
}

/* Complete: the whole bundle is on the list. A tinted edge rather than a
   dimmed card - the thing is still perfectly usable, and the button below
   says the rest. */
.tewido-quote-bundle.is-complete {
	border-color: var(--tq-success);
}

/* The image frame. It carries nothing of its own until Blend is switched on,
   at which point it becomes the tinted card the picture blends against - the
   widget's Blend switcher writes `isolation` and the background colour here.
   Drawn either way so turning Blend on shifts no geometry. */
.tewido-quote-bundle__frame {
	display: block;
	margin: 0;
}

/* A fixed ratio by default, so a catalogue of mixed image sizes still lays
   out in even rows, and `cover` crops rather than letterboxing.

   All three go through a custom property rather than being written straight
   in, because that is the only way the "Natural" ratio can win: the widget's
   Image controls write the properties on {{WRAPPER}}, and an Elementor SELECT
   whose value is empty emits no declaration at all - so a hardcoded
   `aspect-ratio` here would have been unreachable from the panel. Natural is
   therefore the explicit value `auto`. */
.tewido-quote-bundle__thumb {
	display: block;
	width: 100%;
	aspect-ratio: var(--tq-bundle-ratio, 16 / 10);
	object-fit: var(--tq-bundle-fit, cover);
	object-position: var(--tq-bundle-pos, 50% 50%);
	background: var(--tq-surface-soft);
}

.tewido-quote-bundle__body {
	flex: 1 1 auto;
	padding: 18px 18px 12px;
}

.tewido-quote-bundle__title {
	margin: 0 0 4px;
	color: var(--tq-text);
	font-size: 17px;
	line-height: 1.3;
}

.tewido-quote-bundle__count {
	margin: 0 0 10px;
	color: var(--tq-muted);
	font-size: 13px;
}

.tewido-quote-bundle__desc {
	margin: 0 0 12px;
	color: var(--tq-text-body);
	font-size: 14px;
	line-height: 1.55;
}

.tewido-quote-bundle__items {
	margin: 0;
	padding: 0;
	list-style: none;
	color: var(--tq-text-body);
	font-size: 13px;
	line-height: 1.6;
}

.tewido-quote-bundle__items li {
	display: flex;
	align-items: baseline;
	gap: 6px;
	/* A long product name wraps instead of pushing the model code out of
	   the card - these are part numbers off a nameplate and half of one is
	   no use at all. */
	min-width: 0;
}

.tewido-quote-bundle__qty {
	flex: 0 0 auto;
	color: var(--tq-text);
	font-weight: 600;
	font-variant-numeric: tabular-nums;
}

.tewido-quote-bundle__name {
	min-width: 0;
	overflow-wrap: anywhere;
}

.tewido-quote-bundle__sku {
	flex: 0 0 auto;
	color: var(--tq-muted);
	font-size: 12px;
}

/* With thumbnails the rows need breathing room and the baseline alignment
   has to go: a 32px tile next to one line of text sits wrong on a baseline. */
.tewido-quote-bundle__items--with-thumbs li {
	align-items: center;
	gap: 8px;
	padding-block: 3px;
}

/* The tile. One custom property sizes it, so the widget's size control, the
   empty-tile case and the "and N more" indent all move together - a mismatch
   there leaves one row's text starting somewhere else.

   It is a real element rather than a background on the image because Blend
   needs something behind the photo to blend INTO: a white studio backdrop on
   a white card is already white, and darkening white with white changes
   nothing. The tint lands here. */
.tewido-quote-bundle__item-frame {
	display: block;
	flex: 0 0 auto;
	width: var(--tq-item-thumb, 32px);
	height: var(--tq-item-thumb, 32px);
	/* So the Blend tab's thumbnail padding insets the photo instead of
	   growing the tile past the size control and pushing every row's text
	   out of line with the one above it. */
	box-sizing: border-box;
	overflow: hidden;
	border-radius: var(--tq-radius-sm);
	background: var(--tq-surface-soft);
}

.tewido-quote-bundle__item-thumb {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* No photo for this product. A plain soft tile rather than a dashed outline -
   on a catalogue with few images that is most rows, and dashes read as broken
   when they are the normal case. */
.tewido-quote-bundle__item-frame.is-empty {
	border: 1px solid var(--tq-border-soft);
}

.tewido-quote-bundle__items--with-thumbs .tewido-quote-bundle__more {
	/* Clears the tile column, so the line reads as a note under the list
	   rather than as a nameless row of it. Derived from the tile size plus
	   the row gap, so it follows the size control instead of being a second
	   number to remember to change. */
	padding-inline-start: calc(var(--tq-item-thumb, 32px) + 8px);
}

.tewido-quote-bundle__more {
	margin-block-start: 4px;
	color: var(--tq-muted);
	font-style: italic;
}

/* ---- the description-only card -------------------------------------
 *
 * Same card, two fewer things in it: no product count and no product list,
 * because it has no products. The only geometry that needs saying is the gap
 * under the title - on a products card the count sits in it, and 4px of air
 * between a heading and a paragraph is not a gap, it is a collision.
 */
.tewido-quote-bundle--info .tewido-quote-bundle__title {
	margin-block-end: 8px;
}

.tewido-quote-bundle--info .tewido-quote-bundle__desc:last-child {
	margin-block-end: 0;
}

/* ---- the Build your own card ---------------------------------------
 *
 * A BAND under the grid, not a card in it. It was a card, and the shape was
 * wrong in a way no styling fixes: the grid wraps, so with three bundles
 * across it landed alone on a second row - the widest, emptiest thing on the
 * page being the one that is not a bundle - and in the row it read as a
 * fourth bundle until you had read it. The band is the same shape whether
 * there are two bundles or eight, and says plainly that it is what to do when
 * none of them fit.
 *
 * Still the quieter of the routes: picking a ready-made system is the better
 * outcome for both sides. Dashed edge, soft fill, ghost button.
 */
.tewido-quote-bundle--custom {
	border-style: dashed;
	background: transparent;
}

.tewido-quote-bundle--custom:hover {
	box-shadow: none;
}

.tewido-quote-bundle--band {
	flex-direction: row;
	align-items: center;
	gap: 24px;
	/* Matches the grid gap, so the band is one more row of the same rhythm
	   rather than a block that happens to be underneath. */
	margin-block-start: 20px;
	padding: 20px 22px;
	background: var(--tq-surface-soft);
}

/* With no bundles yet there is no grid above it, and the margin would be air
   against the top of the section. */
.tewido-quote-bundle--band:first-child {
	margin-block-start: 0;
}

.tewido-quote-bundle--band .tewido-quote-bundle__body {
	display: flex;
	flex-direction: row;
	align-items: center;
	gap: 18px;
	flex: 1 1 auto;
	min-width: 0;
	padding: 0;
}

.tewido-quote-bundle__custom-copy {
	display: flex;
	flex-direction: column;
	gap: 4px;
	min-width: 0;
}

/* Side by side, and sized to their content: in a band they are two actions at
   the end of a line, not two stacked blocks filling a 260px column. */
.tewido-quote-bundle--band .tewido-quote-bundle__foot {
	flex-direction: row;
	align-items: center;
	flex-wrap: wrap;
	gap: 14px;
	flex: 0 0 auto;
	padding: 0;
}

.tewido-quote-bundle--band .tewido-quote-bundle__add {
	width: auto;
}

.tewido-quote-bundle--band .tewido-quote-bundle__desc {
	margin: 0;
	max-width: 62ch;
}

.tewido-quote-bundle--band .tewido-quote-bundle__title {
	margin: 0;
}

/* Solid primary, not the soft tint it used to be. The background behind it is
   the editor's to set, and a pale wash on a pale surface is a circle nobody
   can see - which is what happened the moment one was chosen. A solid fill
   reads on anything, and `--tq-on-primary` keeps the glyph legible on
   whatever the Colors tab makes the brand. */
.tewido-quote-bundle__custom-art {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 52px;
	height: 52px;
	border-radius: 50%;
	background: var(--tq-primary);
	color: var(--tq-on-primary);
}

/* One column once the row would start squeezing the copy. The grid's own
   track floor is 260px, so this is the width at which two cards stop fitting
   side by side - the band folds at the same moment the grid does. */
@media (max-width: 720px) {
	.tewido-quote-bundle--band {
		flex-direction: column;
		align-items: flex-start;
		gap: 18px;
	}

	.tewido-quote-bundle--band .tewido-quote-bundle__foot {
		width: 100%;
	}

	.tewido-quote-bundle--band .tewido-quote-bundle__add {
		width: 100%;
		justify-content: center;
	}
}

/* A column, so the Build your own card's two actions stack rather than
   splitting a 260px card into two cramped halves. */
.tewido-quote-bundle__foot {
	display: flex;
	flex-direction: column;
	gap: 8px;
	padding: 0 18px 18px;
}

/* Full width inside the card: on a bundle it is the only control there, and
   a shrink-to-fit button in a grid of cards gives every card a different
   looking action. */
.tewido-quote-bundle__add {
	width: 100%;
	justify-content: center;
}

/* The second action on the Build your own card: borderless, so the two read
   as a primary and a way out rather than as two equal choices. Picking
   products is still the better outcome - the quote comes back with something
   on it - and sending an empty request is for the visitor who found neither
   a bundle nor a part. Same order and same weighting as the quote list's
   empty state. */
.tewido-quote-bundle__request {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 7px;
	/* Matches the bordered button above it, so the two line up as one stack
	   rather than one control and a caption. */
	min-height: 40px;
	padding: 8px 12px;
	border: 1px solid transparent;
	border-radius: var(--tq-radius-sm);
	/* Brand-coloured and semibold, not grey. Grey read as disabled text
	   rather than as the second of two actions, and this one is the whole
	   route for a visitor who found neither a bundle nor a part. The missing
	   border is what keeps it below the bordered button; the colour is what
	   keeps it a control. */
	color: var(--tq-primary);
	font-size: 14px;
	font-weight: 600;
	line-height: 1.3;
	text-decoration: none;
	transition: color .15s ease, background-color .15s ease, border-color .15s ease;
}

.tewido-quote-bundle__request:hover {
	border-color: var(--tq-primary);
	background: var(--tq-primary-soft);
	color: var(--tq-primary-hover);
}

/* The glyph is the quieter half of the pair - the wording carries it. */
.tewido-quote-bundle__request .tewido-quote-icon {
	opacity: .75;
}

.tewido-quote-bundle__request:focus-visible {
	outline: none;
	box-shadow: var(--tq-focus);
}

@media (prefers-reduced-motion: reduce) {
	.tewido-quote-bundle {
		transition: none;
	}
}

/*
 * The UA sheet's `[hidden] { display: none }` is a single-attribute selector,
 * so any class rule setting `display` beats it and the element stays on screen
 * with its hidden attribute set. Every element this plugin toggles that way
 * needs its own guard.
 */
.tewido-quote-search__results[hidden],
.tewido-quote-search__clear[hidden],
.tewido-quote-search__add[hidden],
.tewido-quote-add[hidden],
.tewido-quote-add__qty[hidden],
.tewido-quote-add__qty-label[hidden],
.tewido-quote-drawer__foot[hidden],
.tewido-quote-panel__nav[hidden],
.tewido-quote-section__title[hidden],
.tewido-quote-section__bar[hidden],
.tewido-quote-clear[hidden],
.tewido-quote-empty-state[hidden],
/* The drawer's own empty block, which paintCounts() hides by the attribute
   alongside .tewido-quote-empty-state. It was the one element in that pass
   missing from this list, and `.tewido-quote-empty { display: flex }` above
   beats the UA rule, so that write did nothing - the message only ever left
   the screen because render() wipes the host before the panel is shown. */
.tewido-quote-empty[hidden],
.tewido-quote-form__empty[hidden],
.tewido-quote-form__summary[hidden],
.tewido-quote-form__done[hidden],
/* The three the post-submit teardown hides. Each sets `display` by class -
   grid, flex and inline-flex - so without these the confirmation appeared
   beside the form that produced it, still populated, with its submit button
   re-enabled and its render token still valid: pressing Send again wrote a
   second record and sent a second notification. */
.tewido-quote-form__grid[hidden],
.tewido-quote-form__actions[hidden],
.tewido-quote-back[hidden],
.tewido-quote-panel[hidden],
.tewido-quote-drawer[hidden] {
	display: none;
}
