/**
 * Quote flow styles.
 *
 * Consumes the Fischer Bell theme's design tokens, with fallbacks after each var() so the plugin
 * still renders sensibly if it is ever activated under a different theme.
 */

/* ------------------------------------------------------------------ notices ---- */

.fb-notice {
	padding: var(--space-4, 16px);
	border-radius: var(--radius-md, 4px);
	border-left: 3px solid transparent;
	font-size: var(--text-body-sm, 14px);
	margin-bottom: var(--space-6, 24px);
}

.fb-notice--success { background: var(--status-success-bg, #E6F4EA); color: var(--status-success, #12803C); border-left-color: currentColor; }
.fb-notice--warning { background: var(--status-warning-bg, #FDF1DF); color: var(--status-warning, #B36A00); border-left-color: currentColor; }
.fb-notice--danger  { background: var(--status-danger-bg, #FDECEA); color: var(--status-danger, #B32318); border-left-color: currentColor; }
.fb-notice--info    { background: var(--status-info-bg, #E8F0F8); color: var(--status-info, #15558F); border-left-color: currentColor; }

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

.fb-empty-state {
	text-align: center;
	padding: var(--space-16, 64px) var(--space-6, 24px);
	border: 1px dashed var(--border-default, #D2D4DA);
	border-radius: var(--radius-lg, 8px);
	color: var(--text-secondary, #4B4F58);
}

.fb-empty-state .fb-icon { color: var(--steel-300, #B3B6BF); }

.fb-empty-state h2 {
	font-family: var(--font-display, sans-serif);
	font-size: var(--text-h3, 22px);
	margin: var(--space-4, 16px) 0 var(--space-2, 8px);
	color: var(--text-primary, #2C2E35);
}

.fb-empty-state p {
	max-width: 46ch;
	margin: 0 auto var(--space-6, 24px);
	font-size: var(--text-body-sm, 14px);
	text-wrap: pretty;
}

/* --------------------------------------------------------------- line items ---- */

.fb-quote-table {
	width: 100%;
	border-collapse: collapse;
	margin-bottom: var(--space-6, 24px);
}

.fb-quote-table th {
	text-align: left;
	font-size: var(--text-micro, 11px);
	font-weight: 600;
	letter-spacing: var(--ls-eyebrow, 0.09em);
	text-transform: uppercase;
	color: var(--text-muted, #676B76);
	padding: var(--space-3, 12px) var(--space-3, 12px);
	border-bottom: 1px solid var(--border-default, #D2D4DA);
}

.fb-quote-table td {
	padding: var(--space-4, 16px) var(--space-3, 12px);
	border-bottom: 1px solid var(--border-subtle, #E7E8EC);
	vertical-align: middle;
}

.fb-quote-table__media { width: 72px; }

.fb-quote-table__media img {
	width: 64px;
	height: 64px;
	object-fit: contain;
	background: var(--surface-subtle, #F3F4F6);
	border-radius: var(--radius-md, 4px);
	display: block;
}

.fb-quote-table__name {
	display: block;
	font-weight: 600;
	font-size: var(--text-body-sm, 14px);
	color: var(--text-primary, #2C2E35);
	text-decoration: none;
	text-wrap: pretty;
}

.fb-quote-table__name:hover { text-decoration: underline; }

.fb-quote-table__sku {
	display: block;
	font-family: var(--font-mono, monospace);
	font-size: var(--text-micro, 11px);
	color: var(--text-muted, #676B76);
	margin-top: 2px;
}

.fb-quote-table__on-request {
	font-size: var(--text-caption, 13px);
	color: var(--status-info, #15558F);
	font-weight: 500;
}

.fb-quote-table__qty { width: 84px; }

.fb-quote-items__actions {
	display: flex;
	justify-content: flex-end;
	margin-bottom: var(--space-12, 48px);
}

/* Quote-only products on the catalogue never show an empty price slot. */
.fb-price__on-request {
	font-size: var(--text-body-sm, 14px);
	font-weight: 600;
	color: var(--status-info, #15558F);
}

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

.fb-quote-form {
	border-top: 1px solid var(--border-default, #D2D4DA);
	padding-top: var(--space-10, 40px);
}

.fb-quote-form__title {
	font-family: var(--font-display, sans-serif);
	font-size: var(--text-h2, 28px);
	margin: 0 0 var(--space-2, 8px);
}

.fb-quote-form__lede {
	color: var(--text-secondary, #4B4F58);
	font-size: var(--text-body-sm, 14px);
	max-width: 62ch;
	margin: 0 0 var(--space-6, 24px);
	text-wrap: pretty;
}

.fb-quote-form__grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: var(--space-4, 16px);
	margin-bottom: var(--space-6, 24px);
}

.fb-quote-form__grid .fb-field { margin: 0; }
.fb-field--wide { grid-column: 1 / -1; }

/* Off-screen rather than display:none — bots skip hidden inputs but fill positioned ones. */
.fb-quote-form__hp {
	position: absolute !important;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* ------------------------------------------------------- add-to-quote button ---- */

.fb-quote-add { margin: 0; display: inline-block; }
.fb-quote-add.is-added .fb-btn { background: var(--fb-green-100, #EDF7E1); color: var(--fb-green-700, #4E7D1E); border-color: transparent; }

/* Toast confirming an AJAX add, so the page never has to reload to acknowledge the click. */
.fb-quote-toast {
	position: fixed;
	right: 20px;
	bottom: 88px;
	z-index: 70;
	display: flex;
	align-items: center;
	gap: var(--space-3, 12px);
	max-width: 320px;
	padding: var(--space-3, 12px) var(--space-4, 16px);
	background: var(--fb-ink, #2C2E35);
	color: #fff;
	border-radius: var(--radius-md, 4px);
	box-shadow: var(--shadow-lg, 0 12px 32px rgba(44, 46, 53, .12));
	font-size: var(--text-body-sm, 14px);
	transform: translateY(8px);
	opacity: 0;
	transition: opacity 200ms ease, transform 200ms ease;
}

.fb-quote-toast.is-visible { opacity: 1; transform: translateY(0); }
.fb-quote-toast a { color: var(--fb-green, #88C946); font-weight: 600; }
.fb-quote-toast--error { background: var(--status-danger, #B32318); }

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

/* --------------------------------------------------------------- responsive ---- */

@media (max-width: 720px) {
	.fb-quote-form__grid { grid-template-columns: 1fr; }

	/* Reflow the table into stacked cards; a 5-column table is unusable at 375px. */
	.fb-quote-table thead { display: none; }
	.fb-quote-table,
	.fb-quote-table tbody,
	.fb-quote-table tr,
	.fb-quote-table td { display: block; width: 100%; }

	.fb-quote-table tr {
		position: relative;
		display: grid;
		grid-template-columns: 72px 1fr;
		gap: var(--space-2, 8px) var(--space-3, 12px);
		align-items: center;
		padding: var(--space-4, 16px) 0;
		border-bottom: 1px solid var(--border-subtle, #E7E8EC);
	}

	.fb-quote-table td { border: 0; padding: 0; }
	.fb-quote-table__media { grid-row: span 3; }
	.fb-quote-table__qty { width: 100%; max-width: 120px; }

	.fb-quote-table tr > td:last-child {
		position: absolute;
		top: var(--space-4, 16px);
		right: 0;
		/*
		 * Overrides the blanket `td { width: 100% }` above. Without it this cell is absolutely
		 * positioned AND full-width, so `right: 0` is satisfied by a box spanning the whole card
		 * while the bin inside it sits against the card's LEFT edge — which is where it had been
		 * rendering, on top of the thumbnail. Found when the select column landed underneath it.
		 */
		width: auto;
	}
}

/* ---------------------------------------------------------- two-panel layout ---- */

.fb-quote-intro { margin-bottom: var(--space-6, 24px); }

.fb-quote-layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 340px;
	gap: var(--space-10, 40px);
	align-items: start;
}

.fb-quote-main { min-width: 0; }

/*
 * Offset accounts for the sticky site header, so the panel never slides under it.
 *
 * One shared token rather than a second hand-written number (responsive audit R-5). This said
 * 140px while the catalogue sidebar said 150px, both claiming to clear the same header — which
 * computes to 158px, so this one was clipping its first row by about eighteen pixels.
 */
.fb-quote-summary { position: sticky; top: var(--sticky-offset, 160px); }

.fb-quote-summary__rows {
	margin: var(--space-4, 16px) 0 0;
	display: grid;
	gap: var(--space-2, 8px);
}

.fb-quote-summary__row {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-3, 12px);
	font-size: var(--text-body-sm, 14px);
}

.fb-quote-summary__row dt { color: var(--text-secondary, #4B4F58); margin: 0; }
.fb-quote-summary__row dd { margin: 0; font-weight: var(--fw-semibold, 600); }

.fb-quote-summary__note {
	font-size: var(--text-caption, 13px);
	color: var(--text-muted, #676B76);
	margin: var(--space-4, 16px) 0 0;
	line-height: var(--lh-relaxed, 1.65);
	text-wrap: pretty;
}

/* The send button belongs with the contact fields it validates, not in the sticky panel. */
.fb-quote-form { border-top: 0; padding-top: 0; margin-top: var(--space-12, 48px); }

@media (max-width: 1024px) {
	.fb-quote-layout { grid-template-columns: 1fr; gap: var(--space-8, 32px); }

	/* Once stacked, a sticky summary would just cover the form it summarises. */
	.fb-quote-summary { position: static; }
}

/* =============================================================== list builder ==== */
/*
 * The three ways to fill a quote list without browsing for each product.
 *
 * Named `fb-quote-builder`, not `fb-quote-add`, because `.fb-quote-add` is already taken: it is the
 * add-to-quote FORM on a product card, and it is `display: inline-block` (see gotcha 48). Reusing
 * the name shrank this whole panel to its content width with nothing in the stylesheet to explain
 * why — the rule sits 120 lines above and reads as if it belongs to something else entirely.
 *
 * The panels are <details name="fb-quote-builder">, so the browser makes them mutually exclusive with
 * no JavaScript. Styled as a tab-less accordion rather than a tab strip on purpose: a real tab
 * strip needs a script to move the active state, and this flow exists for buyers who may not have
 * one.
 */

.fb-quote-builder {
	border: 1px solid var(--border-default, #D2D4DA);
	border-radius: var(--radius-lg, 8px);
	background: var(--surface-card, #FFF);
	margin-bottom: var(--space-8, 32px);
	overflow: hidden;
}

.fb-quote-builder__head {
	padding: var(--space-5, 20px) var(--space-6, 24px);
	border-bottom: 1px solid var(--border-subtle, #E5E7EB);
	background: var(--surface-subtle, #F7F8FA);
}

.fb-quote-builder__title {
	font-family: var(--font-display, sans-serif);
	font-size: var(--text-h4, 18px);
	line-height: var(--lh-tight, 1.25);
	margin: 0;
	color: var(--text-primary, #2C2E35);
}

.fb-quote-builder__lede {
	margin: var(--space-1, 4px) 0 0;
	font-size: var(--text-body-sm, 14px);
	color: var(--text-secondary, #4B4F58);
	text-wrap: pretty;
}

/* The report sits between the heading and the panels, where the eye lands after a reload. */
.fb-quote-builder__report {
	margin: var(--space-5, 20px) var(--space-6, 24px);
}

.fb-quote-builder__report p { margin: 0; }
.fb-quote-builder__report-head { font-weight: var(--fw-semibold, 600); }

.fb-quote-builder__report-note {
	margin-top: var(--space-2, 8px) !important;
	font-size: var(--text-caption, 13px);
	opacity: .9;
}

.fb-quote-builder__skipped {
	list-style: none;
	margin: var(--space-2, 8px) 0 0;
	padding: 0;
	display: grid;
	gap: var(--space-1, 4px);
	font-size: var(--text-caption, 13px);
}

.fb-quote-builder__skipped li {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: var(--space-2, 8px);
}

.fb-quote-builder__skipped code {
	font-family: var(--font-mono, monospace);
	font-size: var(--text-caption, 13px);
	background: rgba(0, 0, 0, .06);
	padding: 1px var(--space-1, 4px);
	border-radius: var(--radius-sm, 2px);
}

.fb-quote-builder__skipped-why { opacity: .85; }
.fb-quote-builder__skipped-search { color: inherit; text-decoration: underline; }

/* ------------------------------------------------------------------- panels ---- */

.fb-quote-builder__panel { border-top: 1px solid var(--border-subtle, #E5E7EB); }
.fb-quote-builder__panel:first-of-type { border-top: 0; }

.fb-quote-builder__summary {
	display: flex;
	align-items: center;
	gap: var(--space-3, 12px);
	padding: var(--space-4, 16px) var(--space-6, 24px);
	cursor: pointer;
	list-style: none;
	font-size: var(--text-body-sm, 14px);
	font-weight: var(--fw-semibold, 600);
	color: var(--text-primary, #2C2E35);
	user-select: none;
}

.fb-quote-builder__summary::-webkit-details-marker { display: none; }
.fb-quote-builder__summary::marker { content: ""; }
.fb-quote-builder__summary:hover { background: var(--surface-subtle, #F7F8FA); }

.fb-quote-builder__summary:focus-visible {
	outline: none;
	box-shadow: var(--focus-ring, 0 0 0 3px rgba(21, 85, 143, .35));
}

.fb-quote-builder__summary .fb-icon { color: var(--text-muted, #676B76); flex: none; }
.fb-quote-builder__panel[open] > .fb-quote-builder__summary { background: var(--surface-subtle, #F7F8FA); }
/* Same on-light green as the checkbox - one token, one fallback (UIUX U-1/U-6). */
.fb-quote-builder__panel[open] > .fb-quote-builder__summary .fb-icon { color: var(--fb-green-700, #4E7D1E); }

.fb-quote-builder__summary-label { flex: 1 1 auto; }

.fb-quote-builder__summary-hint {
	font-size: var(--text-caption, 13px);
	font-weight: 400;
	color: var(--text-muted, #676B76);
}

.fb-quote-builder__body {
	padding: var(--space-5, 20px) var(--space-6, 24px) var(--space-6, 24px);
	border-top: 1px solid var(--border-subtle, #E5E7EB);
}

.fb-quote-builder__body .fb-field { margin: 0 0 var(--space-3, 12px); }
.fb-quote-builder__textarea { font-family: var(--font-mono, monospace); font-size: var(--text-body-sm, 14px); }

.fb-quote-builder__help {
	list-style: disc;
	margin: 0 0 var(--space-5, 20px);
	padding-left: var(--space-5, 20px);
	font-size: var(--text-caption, 13px);
	color: var(--text-muted, #676B76);
	display: grid;
	gap: var(--space-1, 4px);
	text-wrap: pretty;
}

.fb-quote-builder__help code {
	font-family: var(--font-mono, monospace);
	font-size: inherit;
	color: var(--text-secondary, #4B4F58);
}

.fb-quote-builder__file { padding: var(--space-2, 8px); height: auto; }

.fb-quote-builder__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-4, 16px);
}

.fb-quote-builder__template {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2, 8px);
	font-size: var(--text-body-sm, 14px);
	color: var(--text-secondary, #4B4F58);
}

.fb-quote-builder__template:hover { color: var(--text-primary, #2C2E35); }

/* ------------------------------------------------------------------- search ---- */

.fb-quote-find__row {
	display: flex;
	gap: var(--space-2, 8px);
	margin-top: var(--space-1, 4px);
}

.fb-quote-find__row .fb-input { flex: 1 1 auto; min-width: 0; }
.fb-quote-find__row .fb-btn { flex: none; }

.fb-quote-find__none,
.fb-quote-find__more {
	margin: var(--space-4, 16px) 0 0;
	font-size: var(--text-caption, 13px);
	color: var(--text-muted, #676B76);
	text-wrap: pretty;
}

.fb-quote-find__results {
	list-style: none;
	margin: var(--space-5, 20px) 0 0;
	padding: 0;
	border-top: 1px solid var(--border-subtle, #E5E7EB);
}

.fb-quote-find__result {
	display: flex;
	align-items: center;
	gap: var(--space-4, 16px);
	padding: var(--space-3, 12px) 0;
	border-bottom: 1px solid var(--border-subtle, #E5E7EB);
}

.fb-quote-find__media { flex: none; width: 48px; }
.fb-quote-find__media img { width: 48px; height: 48px; object-fit: contain; display: block; }

.fb-quote-find__detail { flex: 1 1 auto; min-width: 0; }

.fb-quote-find__name {
	display: block;
	font-size: var(--text-body-sm, 14px);
	font-weight: var(--fw-medium, 500);
	color: var(--text-primary, #2C2E35);
	text-decoration: none;
	overflow-wrap: anywhere;
}

.fb-quote-find__name:hover { text-decoration: underline; }

.fb-quote-find__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: var(--space-3, 12px);
	margin-top: 2px;
	font-size: var(--text-caption, 13px);
	color: var(--text-muted, #676B76);
}

.fb-quote-find__sku {
	font-family: var(--font-mono, monospace);
	color: var(--text-secondary, #4B4F58);
}

.fb-quote-find__meta .price,
.fb-quote-find__meta .fb-price__on-request { font-size: var(--text-caption, 13px); }

.fb-quote-find__add {
	flex: none;
	display: flex;
	align-items: center;
	gap: var(--space-2, 8px);
}

/*
 * Two classes, not one. The plugin's stylesheet is enqueued BEFORE the theme's components.css,
 * so `.fb-input { width: 100% }` wins any tie on specificity and a lone `.fb-quote-find__qty`
 * rule is silently ignored — the quantity box stretched across the whole row. The table's own
 * `.fb-quote-table__qty` looks like a counter-example but is not: a table cell constrains it.
 */
.fb-input.fb-quote-find__qty { width: 72px; text-align: center; flex: none; }

@media (max-width: 640px) {
	.fb-quote-builder__head,
	.fb-quote-builder__summary,
	.fb-quote-builder__body { padding-inline: var(--space-4, 16px); }

	.fb-quote-builder__report { margin-inline: var(--space-4, 16px); }

	.fb-quote-builder__summary-hint { display: none; }

	.fb-quote-find__row { flex-wrap: wrap; }
	.fb-quote-find__row .fb-btn { width: 100%; }

	/*
	 * The result becomes two rows: the product, then its quantity and button. Anything narrower
	 * than this squeezes the name to two words per line.
	 */
	.fb-quote-find__result { flex-wrap: wrap; }
	.fb-quote-find__detail { flex-basis: calc(100% - 64px); }
	.fb-quote-find__add { flex-basis: 100%; justify-content: flex-end; }
}


/* ============================================================== row selection ==== */
/*
 * Ticking rows to remove several at once.
 *
 * The checkbox column and the Remove selected button are server-rendered and work with no script.
 * `.fb-quote-bulk` — select all, the running count, Clear selection — is revealed by quote.js and
 * carries the `hidden` attribute until then, so it is never on screen unable to do its job.
 */

/*
 * `.fb-quote-check`, NOT `.fb-check` (audit V-2).
 *
 * This is a checkbox input for the quote list's row selector. The THEME uses `.fb-check` for the
 * catalogue facet anchors, and a bare class name shared across a plugin and a theme collided: this
 * rule's `width: 18px; height: 18px` applied to the facet links too, because the theme's
 * `.fb-filters .fb-check` overrides display and min-height but never width or height. Every one of
 * the 48 facet rows in the catalogue sidebar rendered 30-34px wide instead of 260, with the label
 * overflowing 42-84px into the row below and painting over it — "Environmental Protection" on top
 * of "Equipment)". Specificity, not load order, so it survived every stylesheet reshuffle.
 *
 * Third collision between quote.css and the theme's CSS (gotchas 72, 73). Do not reintroduce a
 * bare, generic class name here: this plugin's classes are `fb-quote-*` for exactly this reason.
 */
.fb-quote-check {
	width: 18px;
	height: 18px;
	margin: 0;
	flex: none;
	cursor: pointer;
	/*
	 * A native control, tinted. The kit's own checkbox mark (.fb-choice__mark) is built for the
	 * recommender's full-width choice cards and brings their padding and border with it; in a table
	 * cell the native box is the right size already and comes with the platform's focus ring,
	 * keyboard behaviour and indeterminate state for free.
	 *
	 * `--fb-green-700`, NOT `--cta-quote-bg` (audit 2026-09-17, UIUX U-1). The brand green
	 * (#88C946) is 2.00:1 against a white row, under the 3:1 WCAG 2.1 SC 1.4.11 asks of a control's
	 * visual state - and the checked box is the only signal that a row is selected. #4E7D1E is
	 * 4.91:1. This is the project's own rule, recorded in AUDIT-FULL-2026-08-28: the brand green
	 * stays on dark grounds and fb-green-700 is the on-light value.
	 */
	accent-color: var(--fb-green-700, #4E7D1E);
}

.fb-quote-check:focus-visible { outline: 2px solid var(--fb-green-700, #4E7D1E); outline-offset: 2px; }

.fb-quote-table__select { width: 36px; vertical-align: middle; position: relative; }

/*
 * The tappable area (audit 2026-09-17, UIUX U-4). Stretched over the cell so the target is ~36x72
 * on a wide screen and ~28x90 in a mobile card, rather than the checkbox's own 18px. Transparent,
 * so the checkbox and its focus ring show through underneath.
 */
.fb-quote-table__pick {
	position: absolute;
	inset: 0;
	cursor: pointer;
}

/* Both halves of the toolbar under the table. */
.fb-quote-items__actions {
	flex-wrap: wrap;
	justify-content: space-between;
	align-items: center;
	gap: var(--space-3, 12px);
}

.fb-quote-items__buttons {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-2, 8px);
	margin-left: auto;
}

.fb-quote-bulk {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-4, 16px);
}

.fb-quote-bulk__all {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2, 8px);
	font-size: var(--text-body-sm, 14px);
	color: var(--text-secondary, #4B4F58);
	cursor: pointer;
	user-select: none;
}

.fb-quote-bulk__count {
	font-size: var(--text-caption, 13px);
	color: var(--text-muted, #676B76);
	font-variant-numeric: tabular-nums;
}

.fb-quote-bulk__count.is-active {
	color: var(--text-primary, #2C2E35);
	font-weight: var(--fw-semibold, 600);
}

/*
 * Styled on `aria-disabled`, not `[disabled]` (audit 2026-09-17, UIUX U-2). The attribute version
 * keeps the control focusable, so a keyboard user can still find Remove selected and read its
 * state; `disabled` removed it from the tab order entirely.
 *
 * No `pointer-events: none` for the same reason — the control stays operable and the server answers
 * "Nothing was ticked, so nothing was removed", which is what the no-JS path already does.
 */
.fb-quote-items__actions .fb-btn[aria-disabled="true"] {
	opacity: .55;
	cursor: not-allowed;
}

.fb-quote-items__actions .fb-btn[data-fb-remove-selected] .fb-icon { color: var(--status-danger, #B32318); }

@media (max-width: 720px) {
	/*
	 * The table is a stack of cards at this width, so the checkbox takes a column of its own to the
	 * left of the thumbnail and spans the card's rows. Absolute positioning was the alternative and
	 * would have collided with the delete bin, which already owns the top-right corner.
	 */
	.fb-quote-table tr { grid-template-columns: 28px 72px 1fr; }
	.fb-quote-table__select { width: auto; grid-row: span 3; }

	/*
	 * The row-select target measured 28x24 here (audit V-16) — it is 42x101 on a wide screen, where
	 * the overlay fills a table cell, but the grid cell is short at this width so `inset: 0` had
	 * little to stretch into. A floor of 44px puts it back above the guideline on the one screen
	 * where it is tapped rather than clicked. The visible checkbox stays 18px and centred.
	 */
	.fb-quote-table__pick {
		min-height: 44px;
		display: flex;
		align-items: center;
		justify-content: center;
	}

	/*
	 * Keep the product name clear of the delete bin, which is absolutely positioned in the card's
	 * top-right corner. Only this cell needs it: padding on the row itself would move the bin too,
	 * because `right: 0` resolves against the containing block's padding box.
	 */
	.fb-quote-table__detail { padding-right: 44px !important; }

	.fb-quote-items__actions { flex-direction: column; align-items: stretch; }
	.fb-quote-items__buttons { margin-left: 0; }
	.fb-quote-items__buttons .fb-btn { flex: 1 1 auto; justify-content: center; }

	/*
	 * Stacked and full-width, a ghost button reads as a line of text rather than a control — and
	 * this is the destructive one. It keeps the ghost treatment beside Update quantities on a wide
	 * screen, where the contrast is deliberate hierarchy.
	 */
	.fb-quote-items__buttons .fb-btn[data-fb-remove-selected] {
		border-color: var(--border-default, #D2D4DA);
	}
}

/* ============================================================ variation choice ==== */
/*
 * The size / colour control on a quote line, and the chosen options beneath the name.
 *
 * 342 of the 977 products in this catalogue are variable, and before this every one of them
 * reached the list as its parent — a placeholder part number with no size on it. See
 * FB_Quote_Variations.
 */

.fb-quote-table__options {
	display: block;
	font-size: var(--text-micro, 11px);
	color: var(--text-secondary, #4B4F58);
	margin-top: 2px;
}

.fb-quote-table__options--many a { color: var(--text-link, #15558F); }

.fb-quote-table__variation {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--space-1, 4px) var(--space-2, 8px);
	margin-top: var(--space-2, 8px);
}

/*
 * Capped rather than left to fill the cell. The longest labels here are dimensional `pa_size`
 * terms ("100mm x 25m" — 84 of the 207 terms are this shape), and an unbounded select stretches
 * the Product column until the quantity and price columns have nothing left.
 */
.fb-quote-table__variation-select {
	max-width: 100%;
	width: min(260px, 100%);
	font-size: var(--text-body-sm, 14px);
}

/*
 * An outstanding choice is coloured, not just worded.
 *
 * `--status-warning` on the border rather than the text: the label inside the select is the
 * buyer's own wording once they pick something, and recolouring it would then be wrong. This
 * fades out by itself the moment a variation is chosen, because the class goes with it.
 */
.fb-quote-table__variation--needed .fb-quote-table__variation-select {
	border-color: var(--status-warning, #B36A00);
}

.fb-quote-table__variation-hint {
	font-size: var(--text-micro, 11px);
	color: var(--status-warning, #B36A00);
	font-weight: var(--fw-medium, 500);
}

/* The summary panel's count of lines still waiting on a choice. */
.fb-quote-summary__note--warn { color: var(--status-warning, #B36A00); }

/* The search panel's own variation select, beside the quantity box. */
.fb-quote-find__variation {
	width: min(200px, 100%);
	font-size: var(--text-body-sm, 14px);
}

/* =============================================================== attachments ==== */
/*
 * Purchase orders, drawings and RFQ paperwork.
 *
 * Its own section above the list rather than a field inside the request form, because the upload
 * has to be its own <form> — see FB_Quote_Attachments::render() for why that is not a layout
 * preference.
 */

.fb-quote-attach {
	margin: 0 0 var(--space-8, 32px);
	padding: var(--space-5, 20px);
	border: 1px solid var(--border-subtle, #E7E8EC);
	border-radius: var(--radius-md, 4px);
	background: var(--surface-card, #FFF);
}

.fb-quote-attach__title {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: var(--space-2, 8px);
	margin: 0 0 var(--space-2, 8px);
	font-family: var(--font-display, sans-serif);
	font-size: var(--text-h4, 20px);
	line-height: var(--lh-tight, 1.25);
}

/* Said in the heading, so nobody has to read the paragraph to learn it is optional. */
.fb-quote-attach__optional {
	font-family: var(--font-body, sans-serif);
	font-size: var(--text-micro, 11px);
	font-weight: var(--fw-medium, 500);
	text-transform: uppercase;
	letter-spacing: .06em;
	color: var(--text-muted, #676B76);
}

.fb-quote-attach__lede {
	margin: 0 0 var(--space-4, 16px);
	font-size: var(--text-body-sm, 14px);
	color: var(--text-secondary, #4B4F58);
	line-height: var(--lh-relaxed, 1.65);
	text-wrap: pretty;
}

.fb-quote-attach__list {
	list-style: none;
	margin: 0 0 var(--space-4, 16px);
	padding: 0;
	display: grid;
	gap: var(--space-2, 8px);
}

.fb-quote-attach__item {
	display: flex;
	align-items: center;
	gap: var(--space-2, 8px);
	padding: var(--space-2, 8px) var(--space-3, 12px);
	border: 1px solid var(--border-subtle, #E7E8EC);
	border-radius: var(--radius-sm, 2px);
	background: var(--surface-sunken, #F7F8F9);
	font-size: var(--text-body-sm, 14px);
}

.fb-quote-attach__item svg { flex: 0 0 auto; color: var(--text-muted, #676B76); }

/*
 * `min-width: 0` so a long filename can shrink and ellipsise. A flex item defaults to
 * `min-width: auto`, which refuses to go below its content and pushes the size and the remove
 * button off the row instead.
 */
.fb-quote-attach__name {
	flex: 1 1 auto;
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	font-weight: var(--fw-medium, 500);
}

.fb-quote-attach__size {
	flex: 0 0 auto;
	font-family: var(--font-mono, monospace);
	font-size: var(--text-micro, 11px);
	color: var(--text-muted, #676B76);
}

.fb-quote-attach__remove { flex: 0 0 auto; margin: 0; display: flex; }

.fb-quote-attach__help {
	list-style: disc;
	margin: 0 0 var(--space-4, 16px);
	padding-left: var(--space-5, 20px);
	font-size: var(--text-caption, 13px);
	color: var(--text-muted, #676B76);
	display: grid;
	gap: var(--space-1, 4px);
	text-wrap: pretty;
}

.fb-quote-attach__file { padding: var(--space-2, 8px); height: auto; }

.fb-quote-attach__full {
	margin: 0;
	font-size: var(--text-caption, 13px);
	color: var(--text-secondary, #4B4F58);
}

/* The named failures inside the upload notice — "PO-4471.pdf — larger than the 10 MB limit." */
.fb-quote-attach__errors {
	list-style: disc;
	margin: var(--space-2, 8px) 0 0;
	padding-left: var(--space-5, 20px);
	display: grid;
	gap: var(--space-1, 4px);
	font-size: var(--text-caption, 13px);
}

@media (max-width: 640px) {
	/*
	 * The filename gets the whole width and the size and bin sit under it. At 375px a 30-character
	 * purchase-order name ellipsises down to about eight characters when it has to share the row,
	 * which is not enough to tell two POs apart.
	 */
	.fb-quote-attach__item { flex-wrap: wrap; }
	.fb-quote-attach__name { flex-basis: calc(100% - 26px); }
	.fb-quote-attach__remove { margin-left: auto; }
}

/*
 * The variation selects' own status line.
 *
 * Sits above the table and is empty until something is applied, so it takes no space until it has
 * something to say — `:empty` rather than a `hidden` attribute the script would have to manage.
 */
.fb-quote-variation-status {
	margin: 0 0 var(--space-2, 8px);
	font-size: var(--text-caption, 13px);
	color: var(--text-muted, #676B76);
}

.fb-quote-variation-status:empty { display: none; }
.fb-quote-variation-status.is-error { color: var(--status-danger, #B3261E); font-weight: var(--fw-medium, 500); }

/* A select mid-flight is dimmed rather than disabled, so focus is never taken off it. */
.fb-quote-table__variation-select[aria-busy="true"] { opacity: .6; }
