/* =========================================================================
   builder.css — /pc-builder/.

   THREE BLOCKS, AND THE SPLIT IS STRUCTURAL RATHER THAN STYLISTIC.

     .bedi-build        the page: the rail, the groups, the slot rows.
     .bedi-buildsheet   the picker dialog, which builder.js MOVES to <body>.
     .bedi-buildbar     reserved, unused. See the note in section 7.

   The sheet is a separate block and not `.bedi-build__sheet` because it does
   not live inside `.bedi-build` once the script has run. cart.js records why it
   has to move: mini-cart.php rendered inside `.bedi-header`, which is a
   stacking context, so `z-index: 200` resolved INSIDE the header at 100 and the
   drawer painted under the page — and any `transform` on an ancestor re-roots
   `position: fixed` to that ancestor, so it stopped covering the viewport at
   all. A block that is reparented cannot be named as a child of where it
   started.

   TWO MEDIA QUERIES, TWO PURPOSES, AND NEITHER IS A THIRD SPELLING OF THE
   OTHER. `47.9375em` / `48em` is THE theme's mobile breakpoint and is used here
   only for genuinely mobile behaviour — the bottom bar, the bottom sheet.
   `64em` is this page's own LAYOUT breakpoint, the width at which a 21rem rail
   beside the slot list stops being cramped. Six spellings of the mobile
   breakpoint already exist in this tree; this file adds none of them.

   NO BARE ELEMENT SELECTORS ANYWHERE. theme.json prints
   `:root :where(h1,…h6)` and `:root :where(a…)` at (0,1,0), and a bare `h2` at
   (0,0,1) loses to it whatever the load order — which is the entire reason
   base.css section 8 exists. Every rule below is on a class.
   ========================================================================= */

.bedi-build__grid,
.bedi-build,
.bedi-build__rail {
	/*
	 * Local tokens, declared on EVERY block that reads them.
	 *
	 * `.bedi-build__grid` is on this list because it is the PARENT of
	 * `.bedi-build`, not a descendant, and it reads `--bedi-build-rail` in its
	 * two-column `grid-template-columns`. Declaring the token on the form alone
	 * put it out of scope for the grid, the whole declaration parsed as invalid,
	 * and the page silently stayed one column at every width — which is exactly
	 * the `--bedi-prod-rail-top` failure the next paragraph warns about, made
	 * while writing the warning.
	 * `--bedi-prod-rail-top` is the cautionary tale: product.css declares it on
	 * `.bedi-product`, filters.css and account.css read it from outside that
	 * component, and both have always silently resolved to the literal
	 * fallback. A token declared on a component root is readable only inside
	 * that component.
	 */
	--bedi-build-rail: 21rem;
	--bedi-build-rail-top: calc(var(--bedi-header-height) + var(--bedi-space-4));
	--bedi-build-row: 4.25rem;
	--bedi-build-icon: 3rem;
	--bedi-build-progress: 0%;
}

/* =========================================================================
   1. HEAD
   ====================================================================== */

.bedi-build__intro {
	margin-block: var(--bedi-space-7) var(--bedi-space-5);
	max-inline-size: 62ch;
}

.bedi-build__title {
	font-family: var(--bedi-font-display);
	font-size: var(--bedi-text-3xl);
	font-weight: var(--bedi-weight-bold);
	letter-spacing: -0.01em;
	margin: 0 0 var(--bedi-space-2);
}

.bedi-build__lede {
	color: var(--bedi-ink-muted);
	margin: 0;
}

.bedi-build__notice {
	border: var(--bedi-border-width) solid var(--bedi-rule);
	border-radius: var(--bedi-radius-lg);
	font-size: var(--bedi-text-base);
	margin-block-end: var(--bedi-space-5);
	padding: var(--bedi-space-3) var(--bedi-space-4);
}

.bedi-build__notice--ok {
	background-color: color-mix(in srgb, var(--bedi-ok) 8%, transparent);
	border-color: color-mix(in srgb, var(--bedi-ok) 34%, transparent);
}

.bedi-build__notice--warn {
	background-color: color-mix(in srgb, var(--bedi-danger) 7%, transparent);
	border-color: color-mix(in srgb, var(--bedi-danger) 30%, transparent);
}

/* =========================================================================
   2. THE GRID
   ====================================================================== */

.bedi-build__grid {
	display: grid;
	gap: var(--bedi-space-7);
	grid-template-columns: minmax(0, 1fr);
}

@media (min-width: 64em) {
	/*
	 * COMPONENTS LEFT, MACHINE RIGHT — AND THE DOM ORDER IS NOT TOUCHED.
	 *
	 * The columns are swapped with `grid-column` rather than by moving the
	 * `<aside>` after the `<form>` in the template, because the two orders want
	 * different things. On a phone this collapses to one column and the machine
	 * should come FIRST: it is the thing that says what this page is, and a
	 * visitor who lands on eighteen form rows has to scroll to find out. On a
	 * desktop the list is what the eye reads first and the machine is the
	 * reference beside it. Source order stays mobile-correct; the grid does the
	 * rest, and a screen reader still meets the summary before the controls.
	 */
	.bedi-build__grid {
		align-items: start;
		grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	}

	.bedi-build__grid > .bedi-build {
		grid-column: 1;
		grid-row: 1;
	}

	.bedi-build__rail {
		grid-column: 2;
		grid-row: 1;
		inset-block-start: var(--bedi-build-rail-top);
		position: sticky;
	}
}

/* =========================================================================
   3. THE RAIL
   ====================================================================== */

.bedi-build__panel {
	background-color: var(--bedi-surface);
	border: var(--bedi-border-width) solid var(--bedi-rule);
	border-radius: var(--bedi-radius-xl);
	padding: var(--bedi-space-4);
}

/* ---- the machine ---- */

/*
 * A FLAT 2D SCHEMATIC, AND THAT IS WHY THE MAPPING IS EXACT.
 *
 * Two versions came before this one. Nine filled rectangles read as nine blue
 * rectangles. A 3D render with polygons traced over it looked better and mapped
 * badly — it had to, because a three-quarter view turns every bay into a
 * foreshortened quadrilateral whose corners are a judgement call. The drawing
 * is now the map: each bay is a real `<rect>`, so the highlight and the shape
 * are one element and cannot drift apart.
 */
.bedi-build__machine {
	block-size: auto;
	color: var(--bedi-rule-strong);
	display: block;
	inline-size: 100%;
	margin: 0 auto var(--bedi-space-4);
	max-inline-size: 17rem;
}

/* The case outline. */
.bedi-build__shell {
	fill: var(--bedi-surface);
	stroke: currentColor;
	stroke-width: 2;
	transition-duration: var(--bedi-dur);
	transition-property: fill, stroke;
	transition-timing-function: var(--bedi-ease-in);
}

.bedi-build__bay--case[data-filled="1"] .bedi-build__shell {
	fill: color-mix(in srgb, var(--bedi-accent) 5%, var(--bedi-surface));
	stroke: var(--bedi-accent);
}

/* The vented front panel. Decoration: no bay, no pointer events. */
.bedi-build__trim {
	pointer-events: none;
}

.bedi-build__trim rect {
	fill: none;
	stroke: currentColor;
	stroke-opacity: 0.55;
	stroke-width: 1.5;
}

.bedi-build__trim line {
	stroke: currentColor;
	stroke-linecap: round;
	stroke-opacity: 0.4;
	stroke-width: 2;
}

.bedi-build__bay {
	cursor: pointer;
}

.bedi-build__bay-fill {
	fill: var(--bedi-surface-2);
	stroke: currentColor;
	stroke-opacity: 0.7;
	stroke-width: 1.5;
	/*
	 * Longhands, never the `transition` shorthand. motion.css records what the
	 * shorthand costs: it resets `transition-delay` to 0s, which outranked
	 * hero.css's 90ms request "and is why the hero arrived as one slab".
	 */
	transition-duration: var(--bedi-dur);
	transition-property: fill, stroke, stroke-opacity;
	transition-timing-function: var(--bedi-ease-in);
}

.bedi-build__bay:hover .bedi-build__bay-fill,
.bedi-build__bay:focus-visible .bedi-build__bay-fill {
	fill: color-mix(in srgb, var(--bedi-accent) 12%, var(--bedi-surface));
	stroke: var(--bedi-accent);
	stroke-opacity: 1;
}

.bedi-build__bay[data-filled="1"] .bedi-build__bay-fill {
	fill: var(--bedi-accent);
	stroke: var(--bedi-accent);
	stroke-opacity: 1;
}

/*
 * THE BOARD IS A BACKPLANE. Everything else is drawn on top of it, so a filled
 * tray stays a tint — a solid one swallows the processor, the memory and the
 * graphics card sitting inside it. This is the single most removable-looking
 * rule in the file and it is the reason the drawing reads at all.
 */
.bedi-build__bay--tray .bedi-build__bay-fill {
	fill: var(--bedi-surface);
}

.bedi-build__bay--tray[data-filled="1"] .bedi-build__bay-fill {
	fill: color-mix(in srgb, var(--bedi-accent) 14%, var(--bedi-surface));
}

.bedi-build__bay:focus-visible {
	outline: var(--bedi-focus-width) solid var(--bedi-accent);
	outline-offset: 2px;
}

.bedi-build__bay-legend {
	fill: var(--bedi-ink-muted);
	font-family: var(--bedi-font-body);
	font-size: 11px;
	font-weight: var(--bedi-weight-bold);
	letter-spacing: 0.04em;
	pointer-events: none;
	transition-duration: var(--bedi-dur);
	transition-property: fill;
	transition-timing-function: var(--bedi-ease-in);
}

.bedi-build__bay[data-filled="1"] .bedi-build__bay-legend {
	fill: var(--bedi-on-accent);
}

/*
 * Two legends do not sit on their own fill: the tray's, because the tray stays
 * pale by design, and the memory's, because `RAM` does not fit inside an
 * 8-pixel slat and is drawn under them instead. Both land on a near-white
 * ground, so both keep ink rather than taking the on-accent white the others
 * need.
 */
.bedi-build__bay--tray[data-filled="1"] .bedi-build__bay-legend,
.bedi-build__bay[data-filled="1"] .bedi-build__bay-legend--outside {
	fill: var(--bedi-accent-strong);
}

@media (prefers-reduced-motion: reduce) {
	.bedi-build__shell,
	.bedi-build__bay-fill,
	.bedi-build__bay-legend {
		transition-duration: 1ms;
	}
}

/* ---- the tray of non-core slots ---- */

.bedi-build__tray {
	display: flex;
	flex-wrap: wrap;
	gap: var(--bedi-space-1);
	margin-block-end: var(--bedi-space-4);
}

.bedi-build__chip {
	appearance: none;
	background: none;
	border: var(--bedi-border-width) dashed var(--bedi-rule-strong);
	border-radius: var(--bedi-radius-pill);
	color: var(--bedi-ink-muted);
	cursor: pointer;
	font-family: var(--bedi-font-body);
	font-size: var(--bedi-text-xs);
	padding: 4px 10px;
	transition-duration: var(--bedi-dur-micro);
	transition-property: background-color, border-color, color;
	transition-timing-function: var(--bedi-ease-out);
}

.bedi-build__chip:hover {
	border-color: var(--bedi-accent);
	color: var(--bedi-accent-strong);
}

/*
 * `--bedi-accent-strong` (#0668FC), not `--bedi-accent` (#2D81FF). base.css
 * names accent-2/accent-strong as "the brand blue to reach for when something
 * small has to be read", and a 12px chip is exactly that: white on #2D81FF is
 * 3.4:1, on #0668FC it is 5.1:1.
 */
.bedi-build__chip[data-filled="1"] {
	background-color: var(--bedi-accent-strong);
	border-color: var(--bedi-accent-strong);
	border-style: solid;
	color: var(--bedi-on-accent);
}

/* ---- progress ---- */

/* ---- the required-parts meter, in the bar ---- */

/*
 * 13rem, measured rather than guessed. `აუცილებელი ნაწილები` renders at 148px
 * at this size and `4 / 6` takes another 27; at 11.5rem the label was clipping
 * to `აუცილებელი ნაწ…`, which is a truncated Georgian word and not a label.
 * Georgian runs wider than the English these numbers are usually eyeballed in —
 * measure before setting a fixed width on a Georgian string.
 */
.bedi-build__meter {
	display: grid;
	gap: 7px;
	inline-size: 13rem;
}

.bedi-build__meter-head {
	align-items: baseline;
	color: var(--bedi-ink-muted);
	display: flex;
	font-size: var(--bedi-text-xs);
	gap: var(--bedi-space-2);
	justify-content: space-between;
	line-height: 1.2;
}

.bedi-build__meter-label {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.bedi-build__meter-head b {
	color: var(--bedi-ink);
	flex: none;
	font-size: var(--bedi-text-sm);
	font-variant-numeric: tabular-nums;
	font-weight: var(--bedi-weight-bold);
}

/* Complete is a state worth seeing without counting. */
.bedi-build__actions[data-complete="1"] .bedi-build__meter-head b {
	color: var(--bedi-ok);
}

.bedi-build__bar {
	background-color: var(--bedi-rule);
	block-size: 5px;
	border-radius: var(--bedi-radius-pill);
	display: block;
	overflow: hidden;
}

.bedi-build__actions[data-complete="1"] .bedi-build__bar-fill {
	background-color: var(--bedi-ok);
}

.bedi-build__bar-fill {
	background-color: var(--bedi-accent);
	border-radius: var(--bedi-radius-pill);
	display: block;
	/*
	 * Driven by a custom property the template sets, not by a width JavaScript
	 * writes into a style attribute. The inline `style` carries one CUSTOM
	 * PROPERTY, which is a value rather than a declaration, and that keeps the
	 * `style-src` half of the Content-Security-Policy goal reachable.
	 */
	inline-size: var(--bedi-build-progress, 0%);
	min-block-size: 100%;
	transition-duration: var(--bedi-dur);
	transition-property: inline-size;
	transition-timing-function: var(--bedi-ease-in);
}

/* ---- money and actions ---- */

.bedi-build__total {
	display: block;
	margin: 0;
}

.bedi-build__total span {
	color: var(--bedi-ink-muted);
	display: block;
	font-size: var(--bedi-text-xs);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.bedi-build__total strong {
	font-family: var(--bedi-font-display);
	font-size: var(--bedi-text-2xl);
	font-variant-numeric: tabular-nums;
	font-weight: var(--bedi-weight-bold);
	letter-spacing: -0.02em;
}

.bedi-build__buttons {
	display: flex;
	flex: none;
	gap: var(--bedi-space-2);
	padding-inline-start: var(--bedi-space-5);
}

.bedi-build__cart {
	min-inline-size: 15rem;
}

/* Both labels ship; the breakpoint picks one. Neither is ever truncated. */
.bedi-build__cart-short {
	display: none;
}

/* =========================================================================
   3b. THE BOTTOM BAR — AT EVERY WIDTH

   The money and the primary action are fixed to the bottom of the viewport on
   a desktop exactly as they are on a phone. A total that scrolls away is a
   total the visitor has to go looking for at the moment they are deciding to
   spend, and every shipped build-your-own screen worth copying keeps the price
   inside the CTA and the CTA on screen.

   FULL-BLEED, WITH THE CONTENT CENTRED BY PADDING RATHER THAN BY A WRAPPER.
   `max(gutter, (100vw - content-width) / 2)` lines the bar's contents up with
   `.bedi-container` above it without a second element to carry the measure —
   and it degrades to a plain gutter on anything narrower than the shell.

   NOTHING IN ITS ANCESTOR CHAIN MAY CARRY A TRANSFORM. A transform on an
   ancestor re-roots `position: fixed` to that ancestor and the bar stops
   covering the viewport — the same failure cart.js records for the drawer. In
   particular: never put `.bedi-reveal` on `.bedi-build__panel`, on
   `.bedi-build__rail` or on the container.
   ====================================================================== */

.bedi-build__actions {
	align-items: center;
	background-color: var(--bedi-surface);
	border-block-start: var(--bedi-border-width) solid var(--bedi-rule);
	box-shadow: 0 -10px 30px -18px var(--bedi-shadow-soft);
	display: flex;
	inset-block-end: calc(var(--bedi-bottombar-h, 0px) + env(safe-area-inset-bottom, 0px));
	inset-inline: 0;
	margin: 0;
	min-block-size: 76px;
	padding-block: var(--bedi-space-2);
	padding-inline: max(var(--bedi-gutter), calc((100vw - var(--bedi-content-width)) / 2));
	position: fixed;
	z-index: var(--bedi-z-buybar);
}

/*
 * THREE GROUPS, TWO HAIRLINES, ONE BASELINE.
 *
 * The bar started as three left-aligned blocks of different heights with a wide
 * empty middle and the price printed twice — once large and again inside the
 * button. What it is now: progress, money, actions, separated by rules rather
 * than by distance, every group vertically centred on the same axis, and the
 * price stated once.
 */
.bedi-build__meter,
.bedi-build__total {
	flex: none;
	padding-inline-end: var(--bedi-space-5);
	position: relative;
}

.bedi-build__meter::after,
.bedi-build__total::after {
	background-color: var(--bedi-rule);
	block-size: 2.25rem;
	content: "";
	inline-size: var(--bedi-border-width);
	inset-block-start: 50%;
	inset-inline-end: 0;
	position: absolute;
	transform: translateY(-50%);
}

/* The money takes the slack, so the buttons stay pinned to the end. */
.bedi-build__total {
	align-items: baseline;
	column-gap: var(--bedi-space-2);
	display: flex;
	flex: 1 1 auto;
	flex-wrap: wrap;
	margin: 0;
	min-inline-size: 0;
	padding-inline-start: var(--bedi-space-5);
}

.bedi-build__total strong {
	font-family: var(--bedi-font-display);
	font-size: var(--bedi-text-2xl);
	font-variant-numeric: tabular-nums;
	font-weight: var(--bedi-weight-bold);
	letter-spacing: -0.02em;
	line-height: 1.1;
	white-space: nowrap;
}

.bedi-build__total span {
	color: var(--bedi-ink-muted);
	display: inline;
	font-size: var(--bedi-text-sm);
	white-space: nowrap;
}

/*
 * And tell the consultation dock the bar is here. dock.css reads
 * `--bedi-dock-offset`, which mobile-bar.css computes as
 * bottombar-h + buybar-h + space-3 — so publishing a height into
 * `--bedi-buybar-h` is the one line that stops the dock's bubble landing on
 * the total. 76px is this bar's measured height: a 48px button plus its
 * padding. A constant rather than a measurement because, unlike the product
 * buy bar, nothing in this bar changes height.
 *
 * builder.css loads on this URL alone, so a :root rule here cannot reach
 * another page — which is exactly how mobile-bar.css scopes its own.
 */
:root {
	--bedi-buybar-h: 76px;

	/*
	 * AND THE OFFSET ITSELF, because mobile-bar.css only recomputes
	 * `--bedi-dock-offset` inside ITS mobile query — on a desktop the dock is
	 * still reading base.css's `var(--bedi-space-md)` and lands on top of this
	 * bar. Recomputed here with the same arithmetic so the two agree.
	 */
	--bedi-dock-offset: calc(var(--bedi-bottombar-h, 0px) + var(--bedi-buybar-h) + var(--bedi-space-3));
}

/*
 * ROOM FOR THE BAR, AND ONLY THE ROOM THE BAR NEEDS.
 *
 * Three things were reserving the same space at the bottom of this page: this
 * padding at 104px, a 48px margin on the grid, and layout.css's own 64px on
 * `#bedi-main`. Measured against the live page that left 236 pixels of nothing
 * between the last slot row and the footer.
 *
 * The margin is gone and this is now the smallest value that does the job. What
 * the job actually is: the bar covers the last 76 pixels of the viewport, so
 * the document needs at least that much space below its last element or the
 * final row cannot be scrolled clear of it. 20 here plus the 20 the last group
 * carries plus main's 64 comes to 104 — the bar cleared with 28 to spare, and
 * the page ending where a page should.
 */
.bedi-build__grid {
	padding-block-end: var(--bedi-space-5);
}

/*
 * AND THE SAME ROOM AT THE END OF THE DOCUMENT, WHICH IS NOT THE END OF THE
 * GRID.
 *
 * The reserve above clears the bar for the BUILDER — grid padding plus
 * layout.css's 64px on `#bedi-main` — and then the footer renders after
 * `#bedi-main` with 24px of its own. So the last 76 pixels of the footer sat
 * under the bar permanently: the payment strip and the Keepz line could not be
 * scrolled into view at all, because there was nothing below them to scroll.
 *
 * The padding goes on the footer rather than on `body` so the footer's own
 * background fills the reserved strip — the bar is an opaque surface with a
 * top hairline, and a gap of page background between the two would read as a
 * seam.
 *
 * `--bedi-bottombar-h` is 0 on a desktop and the phone bar's height below
 * 48em, so this is correct at both without a media query; the safe-area inset
 * covers the home indicator on an iPhone.
 *
 * builder.css is enqueued on this URL alone — see the :root note above — so a
 * bare `.bedi-footer` here cannot reach any other page.
 */
.bedi-footer {
	padding-block-end: calc(
		var(--bedi-buybar-h)
		+ var(--bedi-bottombar-h, 0px)
		+ env(safe-area-inset-bottom, 0px)
		+ var(--bedi-space-5)
	);
}

/*
 * THE BUTTON SKIN HAS TO BE RESTATED HERE, AND THIS IS NOT DUPLICATION.
 *
 * account.css declares the fill only under `.bedi-woo`, `.woocommerce`,
 * `.bedi-auth` and `.bedi-authmodal` — at (0,3,0) each — so on a page that is
 * none of those, `.bedi-btn--primary` has a transparent background and a
 * transparent border. This matches that shape exactly, at the same (0,3,0), and
 * bedi-builder is enqueued after bedi-account so the tie goes to source order.
 * Widening account.css's selector list instead would mean editing a shared file
 * four other surfaces depend on.
 */
.bedi-build .bedi-btn.bedi-btn--primary,
.bedi-build__panel .bedi-btn.bedi-btn--primary {
	background-color: var(--bedi-accent);
	border-color: transparent;
	color: var(--bedi-on-accent);
}

.bedi-build .bedi-btn.bedi-btn--primary:hover,
.bedi-build__panel .bedi-btn.bedi-btn--primary:hover,
.bedi-build .bedi-btn.bedi-btn--primary:focus-visible,
.bedi-build__panel .bedi-btn.bedi-btn--primary:focus-visible {
	background-color: var(--bedi-accent-strong);
	box-shadow: 0 10px 24px -14px rgba(45, 129, 255, 0.8);
	color: var(--bedi-on-accent);
	transform: translateY(-1px);
}

.bedi-build .bedi-btn.bedi-btn--ghost,
.bedi-build__panel .bedi-btn.bedi-btn--ghost {
	background-color: var(--bedi-surface);
	border-color: var(--bedi-rule);
	color: var(--bedi-ink);
}

.bedi-build .bedi-btn.bedi-btn--ghost:hover,
.bedi-build__panel .bedi-btn.bedi-btn--ghost:hover {
	border-color: var(--bedi-navy);
	color: var(--bedi-navy);
}

.bedi-build__panel .bedi-btn[disabled] {
	background-color: var(--bedi-rule);
	box-shadow: none;
	color: var(--bedi-ink-muted);
	cursor: not-allowed;
	transform: none;
}

.bedi-build__cart-sum {
	font-size: var(--bedi-text-sm);
	font-variant-numeric: tabular-nums;
	font-weight: var(--bedi-weight-medium);
	opacity: 0.85;
}

.bedi-build__cart-sum:empty {
	display: none;
}

/*
 * account.css only hides `.bedi-btn__label` while a button is loading, and the
 * cart button carries three spans: the long label, the short label and the sum.
 * Without these two the spinner's dots animate straight over live text.
 *
 * `visibility`, NOT `display`. The mobile bar swaps the two labels with
 * `display`, and a later media query would win; visibility also holds the
 * button's width so it cannot resize under the pointer mid-request.
 */
.bedi-build__cart.is-loading .bedi-build__cart-short,
.bedi-build__cart.is-loading .bedi-build__cart-sum {
	visibility: hidden;
}

/* ---- the request form ---- */

.bedi-build__request {
	display: grid;
	gap: var(--bedi-space-3);
	margin-block-start: var(--bedi-space-4);
}

/*
 * Collapsed only once the script is live. Without it the fields are the only
 * way to reach a human, so they stay open — and they are hidden with a class
 * rather than [hidden] because an author `display` rule outranks the
 * user-agent rule for [hidden] at any specificity, which cart.css records
 * having shipped once already.
 */
.bedi-build__panel.is-live .bedi-build__request {
	display: none;
}

.bedi-build__panel.is-live .bedi-build__request.is-open {
	display: grid;
}

.bedi-build__request-lede {
	color: var(--bedi-ink-muted);
	font-size: var(--bedi-text-sm);
	margin: 0;
}

.bedi-build__field {
	display: grid;
	gap: 4px;
}

.bedi-build__field span {
	color: var(--bedi-ink-muted);
	font-size: var(--bedi-text-xs);
}

.bedi-build__field input,
.bedi-build__field textarea {
	appearance: none;
	background-color: var(--bedi-surface);
	border: var(--bedi-border-width) solid var(--bedi-rule-strong);
	border-radius: var(--bedi-radius-md);
	color: var(--bedi-ink);
	font-family: var(--bedi-font-body);
	font-size: var(--bedi-text-base);
	inline-size: 100%;
	min-block-size: 42px;
	padding: 9px var(--bedi-space-3);
}

.bedi-build__field textarea {
	min-block-size: 5rem;
	resize: vertical;
}

.bedi-build__field input:focus-visible,
.bedi-build__field textarea:focus-visible {
	border-color: var(--bedi-accent);
	outline: var(--bedi-focus-width) solid var(--bedi-accent);
	outline-offset: 1px;
}

/* The honeypot. Off-screen rather than display:none, which some bots skip. */
.bedi-build__pot {
	block-size: 1px;
	inline-size: 1px;
	inset-inline-start: -9999px;
	overflow: hidden;
	position: absolute;
}

/* ---- advisories ---- */

.bedi-build__advice {
	display: grid;
	gap: var(--bedi-space-2);
	margin-block-start: var(--bedi-space-4);
}

.bedi-build__advice:empty {
	display: none;
}

.bedi-build__note {
	border: var(--bedi-border-width) solid var(--bedi-rule);
	border-radius: var(--bedi-radius-md);
	font-size: var(--bedi-text-sm);
	line-height: 1.45;
	margin: 0;
	padding: var(--bedi-space-2) var(--bedi-space-3);
}

.bedi-build__note b {
	display: block;
	font-weight: var(--bedi-weight-bold);
}

.bedi-build__note--warn {
	background-color: color-mix(in srgb, var(--bedi-alert) 6%, transparent);
	border-color: color-mix(in srgb, var(--bedi-alert) 30%, transparent);
}

.bedi-build__note--ok {
	background-color: color-mix(in srgb, var(--bedi-ok) 7%, transparent);
	border-color: color-mix(in srgb, var(--bedi-ok) 28%, transparent);
}

.bedi-build__note--info {
	background-color: var(--bedi-surface-2);
}

.bedi-build__disclaimer {
	color: var(--bedi-ink-muted);
	font-size: var(--bedi-text-xs);
	line-height: 1.45;
	margin: var(--bedi-space-4) 0 0;
}

/* =========================================================================
   4. THE GROUPS AND THE SLOT ROWS
   ====================================================================== */

/*
 * EACH GROUP IS A BAND, AND THE ROWS STAY WHITE INSIDE IT.
 *
 * Eighteen identical white cards in one column read as one very long list; the
 * client's four groups were headings floating in it rather than sections. The
 * band is `--bedi-bg-2`, which base.css describes in as many words as "the ONE
 * deliberate blue band a section may opt into" — so this is the token that
 * already exists for exactly this, rather than a new grey invented for the
 * page. The rows keep `--bedi-surface`, so they lift off the band instead of
 * dissolving into it, and the separation costs no rule, no shadow and no line.
 */
.bedi-build__group {
	background-color: var(--bedi-bg-2);
	border-radius: var(--bedi-radius-xl);
	margin-block-end: var(--bedi-space-5);
	min-inline-size: 0;
	padding: var(--bedi-space-5);
}

/*
 * The laptop group is the alternative to everything above it rather than
 * another part of the same machine, so it is the one band that is not blue —
 * it reads as a footnote to the page instead of a fifth helping of it.
 */
.bedi-build__group[data-bedi-group="laptop"] {
	background-color: var(--bedi-surface-2);
}

.bedi-build__group-head {
	align-items: baseline;
	display: flex;
	flex-wrap: wrap;
	gap: var(--bedi-space-3);
	margin-block-end: var(--bedi-space-1);
}

.bedi-build__group-title {
	font-family: var(--bedi-font-display);
	font-size: var(--bedi-text-xl);
	font-weight: var(--bedi-weight-bold);
	letter-spacing: -0.005em;
	margin: 0;
}

.bedi-build__group-count {
	background-color: var(--bedi-surface);
	border: var(--bedi-border-width) solid var(--bedi-rule);
	border-radius: var(--bedi-radius-pill);
	color: var(--bedi-ink-muted);
	font-size: var(--bedi-text-xs);
	font-variant-numeric: tabular-nums;
	font-weight: var(--bedi-weight-bold);
	padding: 2px 9px;
}

.bedi-build__group-count[data-done="1"] {
	background-color: color-mix(in srgb, var(--bedi-ok) 8%, transparent);
	border-color: color-mix(in srgb, var(--bedi-ok) 36%, transparent);
	color: var(--bedi-ok);
}

/*
 * `--bedi-ink-soft` is 4.29:1 on white but this sits on the blue band
 * (`--bedi-bg-2`), where `--bedi-ink-muted` computes to 3.91:1. The band lifts
 * the background, so the text has to come down to meet it: `--bedi-ink` reads
 * at 13.6:1 here and the size already separates it from the heading.
 */
.bedi-build__group-note {
	color: var(--bedi-ink);
	opacity: 0.72;
	font-size: var(--bedi-text-sm);
	margin: 0 0 var(--bedi-space-3);
}

.bedi-build__slots {
	display: grid;
	gap: var(--bedi-space-2);
}

.bedi-build__slot {
	align-items: center;
	background-color: var(--bedi-surface);
	border: var(--bedi-border-width) solid var(--bedi-rule);
	border-radius: var(--bedi-radius-lg);
	column-gap: var(--bedi-space-3);
	display: grid;
	grid-template-columns: auto minmax(0, 1fr) auto;
	min-block-size: var(--bedi-build-row);
	padding: var(--bedi-space-3);
	transition-duration: var(--bedi-dur-micro);
	transition-property: border-color, box-shadow;
	transition-timing-function: var(--bedi-ease-out);
}

.bedi-build__slot:hover {
	border-color: var(--bedi-accent);
	box-shadow: var(--bedi-shadow-1);
}

.bedi-build__slot[data-filled="1"] {
	border-color: color-mix(in srgb, var(--bedi-accent) 42%, var(--bedi-rule));
}

/*
 * NO FRAME. The empty state is a white 3D render of the component itself, which
 * carries its own shadow — a bordered grey square around it puts back exactly
 * the placeholder the render replaced. The filled state is the product's own
 * photograph, which is also on white in this catalogue, so the two sit in the
 * same visual box without one being drawn.
 */
/*
 * NO `position: relative` HERE. Nothing inside needs it, and a positioned
 * element paints in a later step than ordinary content — so with it the 3D
 * render of the next unfilled part punched straight through the fixed bottom
 * bar and sat between the total and the cart button. A row's icon is flow
 * content; leave it in the flow.
 */
.bedi-build__slot-icon {
	align-items: center;
	block-size: var(--bedi-build-icon);
	display: flex;
	flex: none;
	inline-size: var(--bedi-build-icon);
	justify-content: center;
}

.bedi-build__slot-thumb,
.bedi-build__slot-blank {
	block-size: 100%;
	inline-size: 100%;
	object-fit: contain;
}

/* [hidden] restated: an author display rule outranks the UA rule at any specificity. */
.bedi-build__slot-thumb[hidden],
.bedi-build__slot-blank[hidden] {
	display: none;
}

/*
 * FULL OPACITY, AND THE CONTRAST IS BAKED INTO THE FILE.
 *
 * These renders are a white object on a transparent ground, sitting on a white
 * row: the first cut held them at 0.72 and they disappeared completely at
 * 44px. The greys were deepened in the asset itself rather than with a CSS
 * filter, so the icon reads the same in a row, in a print-out and anywhere else
 * it is ever used, and no rule has to be remembered alongside it.
 */
.bedi-build__slot-blank {
	opacity: 1;
}

.bedi-build__slot-body {
	min-inline-size: 0;
}

.bedi-build__slot-name {
	align-items: center;
	color: var(--bedi-ink);
	display: flex;
	flex-wrap: wrap;
	font-size: var(--bedi-text-base);
	font-weight: var(--bedi-weight-bold);
	gap: var(--bedi-space-2);
}

/*
 * RED WHILE MISSING, GREEN WITH A TICK ONCE CHOSEN — AS COLOURED TEXT ON A
 * WASH OF ITS OWN COLOUR, NOT AS A SOLID CHIP.
 *
 * TWO COLOUR CHOICES HERE ARE MEASURED RATHER THAN PICKED.
 *
 * The red is `--bedi-alert` (#D50045) and NOT `--bedi-danger` (#F2442C), the
 * theme's usual "wrong" colour, and the tint is 9% rather than a rounder 10%.
 * Both follow from the same arithmetic: coloured text on a wash of itself is a
 * much tighter contrast problem than white on a solid fill, because the wash
 * lifts the background toward the text. Danger on its own 10% wash measures
 * about 3.3:1 — unreadable at this size. Alert on a 10% wash is about 4.5:1,
 * right on the line; at 9% the background is a shade lighter and it clears it.
 * `--bedi-ok` on a 10% wash of itself measures about 4.6:1 and needs no
 * adjustment.
 *
 * The border is what gives the badge its edge back now that the fill is nearly
 * white. It carries no text, so its opacity is free.
 */
.bedi-build__req {
	align-items: center;
	background-color: color-mix(in srgb, var(--bedi-alert) 9%, transparent);
	border: var(--bedi-border-width) solid color-mix(in srgb, var(--bedi-alert) 26%, transparent);
	border-radius: var(--bedi-radius-pill);
	color: var(--bedi-alert);
	display: inline-flex;
	font-size: var(--bedi-text-xs);
	font-style: normal;
	font-weight: var(--bedi-weight-bold);
	gap: 3px;
	letter-spacing: 0.01em;
	line-height: 1;
	padding: 3px 8px;
	transition-duration: var(--bedi-dur);
	transition-property: background-color, border-color, color;
	transition-timing-function: var(--bedi-ease-in);
}

.bedi-build__slot[data-filled="1"] .bedi-build__req {
	background-color: color-mix(in srgb, var(--bedi-ok) 10%, transparent);
	border-color: color-mix(in srgb, var(--bedi-ok) 28%, transparent);
	color: var(--bedi-ok);
}

/* The tick belongs to the filled state alone. */
.bedi-build__req-tick {
	display: none;
	flex: none;
}

.bedi-build__slot[data-filled="1"] .bedi-build__req-tick {
	display: block;
}

@media (prefers-reduced-motion: reduce) {
	.bedi-build__req {
		transition-duration: 1ms;
	}
}

/*
 * ONE ELEMENT, TWO CONTENTS, ONE HEIGHT. The help sentence when the slot is
 * empty and the product name when it is filled, clamped to two lines and
 * reserving that height either way — so a row does not change height when a
 * choice is made and the prices down the column stay on their baselines. The
 * product card's docblock calls the equivalent declaration "the single most
 * removable-looking declaration in the file and the point of the whole design".
 */
.bedi-build__slot-chosen {
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	color: var(--bedi-ink-muted);
	display: -webkit-box;
	font-size: var(--bedi-text-sm);
	line-height: 1.35;
	margin-block-start: 2px;
	min-block-size: calc(var(--bedi-text-sm) * 1.35 * 2);
	overflow: hidden;
}

.bedi-build__slot[data-filled="1"] .bedi-build__slot-chosen {
	color: var(--bedi-ink);
}

/*
 * `--bedi-alert`, not `--bedi-danger`. base.css measures danger at 3.72:1 on
 * white, and this is 12px — the same arithmetic that chose the required
 * badge's red. Alert is 5.9:1.
 */
.bedi-build__slot-oos {
	color: var(--bedi-alert);
	display: block;
	font-size: var(--bedi-text-xs);
	font-weight: var(--bedi-weight-bold);
	margin-block-start: 2px;
}

.bedi-build__slot-side {
	align-items: center;
	column-gap: var(--bedi-space-3);
	display: flex;
	flex-wrap: wrap;
	justify-content: flex-end;
	row-gap: var(--bedi-space-2);
}

.bedi-build__slot-price {
	font-size: var(--bedi-text-base);
	font-variant-numeric: tabular-nums;
	font-weight: var(--bedi-weight-bold);
	text-align: end;
	white-space: nowrap;
}

/* ---- the two control sets ---- */

/*
 * The no-script controls are the DEFAULT and the scripted ones are hidden, so a
 * page whose script never arrives shows a working form rather than a stepper
 * that cannot step. builder.js flips this by adding `.is-live` to the form —
 * LAST, after everything else has bound, so a throw above it leaves the
 * fallback visible. pricelist.js states the contract; archive.js and filters.js
 * follow it.
 */
.bedi-build__live {
	align-items: center;
	display: none;
	gap: var(--bedi-space-2);
}

.bedi-build.is-live .bedi-build__nojs {
	display: none;
}

.bedi-build.is-live .bedi-build__live {
	display: flex;
}

.bedi-build.is-live .bedi-build__apply {
	display: none;
}

.bedi-build__nojs {
	align-items: center;
	display: flex;
	gap: var(--bedi-space-2);
}

.bedi-build__select {
	appearance: none;
	background-color: var(--bedi-surface);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23777777' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
	background-position: right 10px center;
	background-repeat: no-repeat;
	background-size: 16px 16px;
	border: var(--bedi-border-width) solid var(--bedi-rule-strong);
	border-radius: var(--bedi-radius-pill);
	color: var(--bedi-ink);
	font-family: var(--bedi-font-body);
	font-size: var(--bedi-text-sm);
	max-inline-size: 13rem;
	min-block-size: 40px;
	padding-inline: var(--bedi-space-3) 32px;
}

.bedi-build__qty {
	background-color: var(--bedi-surface);
	border: var(--bedi-border-width) solid var(--bedi-rule-strong);
	border-radius: var(--bedi-radius-pill);
	color: var(--bedi-ink);
	font-family: var(--bedi-font-body);
	font-size: var(--bedi-text-sm);
	inline-size: 4rem;
	min-block-size: 40px;
	padding-inline: var(--bedi-space-3);
	text-align: center;
}

.bedi-build__apply {
	align-items: center;
	border-block-start: var(--bedi-border-width) solid var(--bedi-rule);
	display: flex;
	flex-wrap: wrap;
	gap: var(--bedi-space-3);
	padding-block-start: var(--bedi-space-5);
}

.bedi-build__apply p {
	color: var(--bedi-ink-muted);
	font-size: var(--bedi-text-sm);
	margin: 0;
}

/* ---- stepper, pick, clear ---- */

.bedi-build__stepper {
	align-items: center;
	background-color: var(--bedi-surface);
	border: var(--bedi-border-width) solid var(--bedi-rule);
	border-radius: var(--bedi-radius-md);
	display: inline-flex;
	overflow: hidden;
}

/* [hidden] restated: an author display rule outranks the UA rule at any specificity. */
.bedi-build__stepper[hidden],
.bedi-build__clear[hidden] {
	display: none;
}

.bedi-build__step {
	align-items: center;
	appearance: none;
	background: none;
	block-size: 30px;
	border: 0;
	color: var(--bedi-ink-muted);
	cursor: pointer;
	display: flex;
	inline-size: 30px;
	justify-content: center;
}

.bedi-build__step:hover {
	background-color: var(--bedi-surface-2);
	color: var(--bedi-accent-strong);
}

.bedi-build__step-value {
	font-size: var(--bedi-text-sm);
	font-variant-numeric: tabular-nums;
	font-weight: var(--bedi-weight-bold);
	min-inline-size: 24px;
	text-align: center;
}

.bedi-build__pick {
	align-items: center;
	appearance: none;
	background-color: var(--bedi-surface);
	border: var(--bedi-border-width) solid var(--bedi-rule-strong);
	border-radius: var(--bedi-radius-pill);
	color: var(--bedi-ink);
	cursor: pointer;
	display: inline-flex;
	font-family: var(--bedi-font-body);
	font-size: var(--bedi-text-sm);
	font-weight: var(--bedi-weight-bold);
	gap: 4px;
	min-block-size: 38px;
	padding-inline: var(--bedi-space-4) var(--bedi-space-3);
	transition-duration: var(--bedi-dur-micro);
	transition-property: background-color, border-color, color;
	transition-timing-function: var(--bedi-ease-out);
	white-space: nowrap;
}

.bedi-build__pick:hover {
	background-color: var(--bedi-accent);
	border-color: var(--bedi-accent);
	color: var(--bedi-on-accent);
}

.bedi-build__clear {
	align-items: center;
	appearance: none;
	background: none;
	block-size: 30px;
	border: var(--bedi-border-width) solid var(--bedi-rule);
	border-radius: var(--bedi-radius-md);
	color: var(--bedi-ink-muted);
	cursor: pointer;
	display: inline-flex;
	inline-size: 30px;
	justify-content: center;
}

.bedi-build__clear:hover {
	border-color: var(--bedi-danger);
	color: var(--bedi-danger);
}

/* =========================================================================
   5. THE PICKER SHEET
   ====================================================================== */

.bedi-buildsheet {
	inset: 0;
	position: fixed;
	z-index: var(--bedi-z-sheet);
}

/*
 * Restated, for the reason cart.css gives: the rules above set `position`, and
 * an author rule outranks the user-agent `[hidden]` rule at any specificity.
 * Without this the picker is visible over the whole page from first paint,
 * before builder.js has run.
 */
.bedi-buildsheet[hidden] {
	display: none;
}

.bedi-buildsheet__scrim {
	background-color: var(--bedi-scrim);
	inset: 0;
	opacity: 0;
	position: absolute;
	transition-duration: var(--bedi-dur);
	transition-property: opacity;
	transition-timing-function: var(--bedi-ease-out);
}

.bedi-buildsheet.is-open .bedi-buildsheet__scrim {
	opacity: 1;
}

.bedi-buildsheet__panel {
	background-color: var(--bedi-surface);
	border-radius: var(--bedi-radius-2xl);
	box-shadow: var(--bedi-glass-shadow);
	display: flex;
	flex-direction: column;
	inline-size: min(46rem, calc(100% - var(--bedi-gutter) * 2));
	inset-block-start: 50%;
	inset-inline-start: 50%;
	max-block-size: min(86vh, 44rem);
	opacity: 0;
	overflow: hidden;
	position: absolute;
	transform: translate(-50%, calc(-50% + 14px)) scale(0.985);
	transition-duration: var(--bedi-dur);
	transition-property: opacity, transform;
	transition-timing-function: var(--bedi-ease-in);
}

.bedi-buildsheet.is-open .bedi-buildsheet__panel {
	opacity: 1;
	transform: translate(-50%, -50%);
}

/* The panel takes focus on open so the dialog is announced; no ring for that. */
.bedi-buildsheet__panel:focus {
	outline: none;
}

.bedi-buildsheet__head {
	align-items: flex-start;
	border-block-end: var(--bedi-border-width) solid var(--bedi-rule);
	display: flex;
	gap: var(--bedi-space-3);
	justify-content: space-between;
	padding: var(--bedi-space-4);
}

.bedi-buildsheet__title {
	font-family: var(--bedi-font-display);
	font-size: var(--bedi-text-xl);
	font-weight: var(--bedi-weight-bold);
	margin: 0;
}

.bedi-buildsheet__help {
	color: var(--bedi-ink-muted);
	font-size: var(--bedi-text-sm);
	margin: 3px 0 0;
	max-inline-size: 54ch;
}

.bedi-buildsheet__help:empty {
	display: none;
}

.bedi-buildsheet__close {
	align-items: center;
	appearance: none;
	background: none;
	block-size: 36px;
	border: var(--bedi-border-width) solid var(--bedi-rule);
	border-radius: var(--bedi-radius-md);
	color: var(--bedi-ink-muted);
	cursor: pointer;
	display: flex;
	flex: none;
	inline-size: 36px;
	justify-content: center;
}

.bedi-buildsheet__close:hover {
	border-color: var(--bedi-danger);
	color: var(--bedi-danger);
}

.bedi-buildsheet__controls {
	align-items: center;
	border-block-end: var(--bedi-border-width) solid var(--bedi-rule);
	display: flex;
	flex-wrap: wrap;
	gap: var(--bedi-space-2);
	padding: var(--bedi-space-3) var(--bedi-space-4);
}

.bedi-buildsheet__control {
	min-inline-size: 0;
	position: relative;
}

.bedi-buildsheet__control--search {
	flex: 1 1 12rem;
}

.bedi-buildsheet__search-icon {
	color: var(--bedi-ink-muted);
	inset-block-start: 50%;
	inset-inline-start: 13px;
	pointer-events: none;
	position: absolute;
	transform: translateY(-50%);
}

.bedi-buildsheet__controls input[type="search"],
.bedi-buildsheet__controls select {
	appearance: none;
	background-color: var(--bedi-surface);
	border: var(--bedi-border-width) solid var(--bedi-rule-strong);
	border-radius: var(--bedi-radius-pill);
	color: var(--bedi-ink);
	font-family: var(--bedi-font-body);
	font-size: var(--bedi-text-sm);
	inline-size: 100%;
	min-block-size: 40px;
	padding-inline: var(--bedi-space-4);
}

.bedi-buildsheet__controls input[type="search"] {
	padding-inline-start: 36px;
}

.bedi-buildsheet__controls select {
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23777777' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
	background-position: right 12px center;
	background-repeat: no-repeat;
	background-size: 16px 16px;
	padding-inline-end: 34px;
}

.bedi-buildsheet__controls input[type="search"]:focus-visible,
.bedi-buildsheet__controls select:focus-visible {
	border-color: var(--bedi-accent);
	outline: var(--bedi-focus-width) solid var(--bedi-accent);
	outline-offset: 1px;
}

.bedi-buildsheet__toggle {
	align-items: center;
	color: var(--bedi-ink-muted);
	cursor: pointer;
	display: inline-flex;
	font-size: var(--bedi-text-sm);
	gap: 6px;
	user-select: none;
}

.bedi-buildsheet__toggle input {
	accent-color: var(--bedi-accent);
	block-size: 16px;
	inline-size: 16px;
}

/* ---- the list ---- */

.bedi-buildsheet__list {
	flex: 1;
	min-block-size: 0;
	overflow-y: auto;
	overscroll-behavior: contain;
}

.bedi-buildsheet__row {
	align-items: center;
	appearance: none;
	background: none;
	border: 0;
	border-block-end: var(--bedi-border-width) solid var(--bedi-rule);
	column-gap: var(--bedi-space-3);
	cursor: pointer;
	display: grid;
	grid-template-columns: 52px minmax(0, 1fr) auto auto;
	inline-size: 100%;
	padding: var(--bedi-space-3) var(--bedi-space-4);
	text-align: start;
}

.bedi-buildsheet__row:hover {
	background-color: var(--bedi-surface-2);
}

.bedi-buildsheet__row[data-selected="1"] {
	background-color: color-mix(in srgb, var(--bedi-accent) 7%, transparent);
}

.bedi-buildsheet__row-media {
	align-items: center;
	background-color: var(--bedi-surface-2);
	block-size: 52px;
	border: var(--bedi-border-width) solid var(--bedi-rule);
	border-radius: var(--bedi-radius-sm);
	color: var(--bedi-ink-muted);
	display: flex;
	inline-size: 52px;
	justify-content: center;
	overflow: hidden;
}

.bedi-buildsheet__row-img {
	block-size: 100%;
	inline-size: 100%;
	object-fit: contain;
}

.bedi-buildsheet__row-img[hidden],
.bedi-buildsheet__row-glyph[hidden],
.bedi-buildsheet__row-stock[hidden],
.bedi-buildsheet__row-tick[hidden] {
	display: none;
}

.bedi-buildsheet__row-name {
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	color: var(--bedi-ink);
	display: -webkit-box;
	font-size: var(--bedi-text-base);
	line-height: 1.35;
	overflow: hidden;
}

.bedi-buildsheet__row-badges {
	display: flex;
	flex-wrap: wrap;
	gap: 4px;
	margin-block-start: 5px;
}

.bedi-buildsheet__row-badges:empty {
	display: none;
}

.bedi-buildsheet__badge {
	background-color: var(--bedi-surface-2);
	border: var(--bedi-border-width) solid var(--bedi-rule);
	border-radius: var(--bedi-radius-sm);
	color: var(--bedi-ink-muted);
	font-size: 10.5px;
	font-weight: var(--bedi-weight-bold);
	padding: 1px 5px;
	white-space: nowrap;
}

/*
 * SO-DIMM is the one badge drawn as a warning rather than a fact, because it is
 * the one that tells a desktop buyer the part will not fit. Advice repeats it
 * as a sentence when a desktop is being built; this is what makes it visible
 * one step earlier, while the list is still being scanned.
 */
.bedi-buildsheet__badge--warn {
	background-color: color-mix(in srgb, var(--bedi-alert) 8%, transparent);
	border-color: color-mix(in srgb, var(--bedi-alert) 38%, transparent);
	color: var(--bedi-alert);
}

.bedi-buildsheet__row-side {
	text-align: end;
}

.bedi-buildsheet__row-price {
	display: block;
	font-size: var(--bedi-text-base);
	font-variant-numeric: tabular-nums;
	font-weight: var(--bedi-weight-bold);
	white-space: nowrap;
}

.bedi-buildsheet__row-stock {
	display: block;
	font-size: 10.5px;
	margin-block-start: 2px;
}

.bedi-buildsheet__row-stock--in {
	color: var(--bedi-ok);
}

.bedi-buildsheet__row-stock--out {
	color: var(--bedi-alert);
}

.bedi-buildsheet__row-tick {
	align-items: center;
	color: var(--bedi-accent);
	display: flex;
}

/* ---- empty states and the loading veil ---- */

.bedi-buildsheet__empty {
	padding: var(--bedi-space-9) var(--bedi-space-4);
	text-align: center;
}

.bedi-buildsheet__empty-title {
	color: var(--bedi-ink);
	font-size: var(--bedi-text-lg);
	font-weight: var(--bedi-weight-bold);
	margin: 0 0 var(--bedi-space-1);
}

.bedi-buildsheet__empty-text {
	color: var(--bedi-ink-muted);
	font-size: var(--bedi-text-sm);
	margin: 0 0 var(--bedi-space-3);
}

.bedi-buildsheet__empty-action,
.bedi-buildsheet__more {
	appearance: none;
	background: none;
	border: 0;
	color: var(--bedi-link-brand);
	cursor: pointer;
	font-family: var(--bedi-font-body);
	font-size: var(--bedi-text-sm);
	text-decoration: underline;
	text-underline-offset: 2px;
}

.bedi-buildsheet__empty-action[hidden] {
	display: none;
}

.bedi-buildsheet__more {
	display: block;
	inline-size: 100%;
	padding: var(--bedi-space-4);
	text-align: center;
}

/*
 * `is-pending` rather than a spinner, which is the position wishlist.css
 * records: 0.55 opacity and a wait cursor say "working" without adding a third
 * shimmer timing to a theme that already has one in search.css.
 */
.bedi-buildsheet__list.is-pending {
	cursor: wait;
	opacity: 0.55;
	transition-duration: var(--bedi-dur-micro);
	transition-property: opacity;
	transition-timing-function: var(--bedi-ease-out);
}

.bedi-buildsheet__foot {
	align-items: center;
	background-color: var(--bedi-surface-2);
	border-block-start: var(--bedi-border-width) solid var(--bedi-rule);
	display: flex;
	gap: var(--bedi-space-3);
	justify-content: space-between;
	padding: var(--bedi-space-3) var(--bedi-space-4);
}

.bedi-buildsheet__meta,
.bedi-buildsheet__running {
	color: var(--bedi-ink-muted);
	font-size: var(--bedi-text-sm);
	margin: 0;
}

.bedi-buildsheet__running b {
	color: var(--bedi-ink);
	font-variant-numeric: tabular-nums;
}

/* =========================================================================
   6. PHONE
   ====================================================================== */

/* =========================================================================
   5b. THE BAR ON A NARROW DESKTOP — 768px TO 1023px

   A GAP THIS FILE HAD AND NOTHING REPORTED. Every rule that makes the bar fit a
   narrow viewport lived in the phone block at 47.9375em, and the two-column
   layout starts at 64em — so between 768 and 1023 the bar was using its full
   desktop shape: a 13rem meter, the total, a 15rem-minimum primary button and a
   second `აწყობის მოთხოვნა` button beside it. That is wider than 768px, so the
   total was painted over or pushed out at exactly the widths a tablet uses.

   The fix is the smallest one that makes it fit, and it is not a shrink: the
   SECOND button leaves. The request form opens in the rail at these widths
   instead, which is where it already goes on a phone — so nothing is
   duplicated, no Georgian label is truncated, and the bar keeps the price and
   the primary action it exists for.
   ====================================================================== */

@media (max-width: 63.9375em) {
	.bedi-build__ask {
		display: none;
	}

	.bedi-build__cart {
		min-inline-size: 0;
	}

	.bedi-build__panel.is-live .bedi-build__request {
		display: grid;
		margin-block-start: var(--bedi-space-5);
	}
}

@media (max-width: 47.9375em) {
	/*
	 * The actions become the fixed bottom bar. `position: fixed` rather than a
	 * sticky rail, because on a phone the rail is at the TOP of the page and a
	 * sticky element stops sticking when its own box scrolls past.
	 *
	 * NOTHING IN ITS ANCESTOR CHAIN MAY CARRY A TRANSFORM. A transform on an
	 * ancestor re-roots `position: fixed` to that ancestor and this bar would
	 * stop covering the viewport — the same failure cart.js records for the
	 * drawer. In particular: never put `.bedi-reveal` on `.bedi-build__panel`,
	 * `.bedi-build__rail` or the container.
	 */
	/*
	 * ABOVE THE SITE'S OWN BOTTOM BAR, NOT UNDER IT.
	 *
	 * mobile-bar.css pins `.bedi-bottombar` to the bottom at
	 * `--bedi-z-bottombar` (90) and publishes its height as
	 * `--bedi-bottombar-h`. This bar is at `--bedi-z-buybar` (40) — the same
	 * rung product-buy.css uses, and deliberately BELOW the site bar — so
	 * sitting at 0 put it behind five navigation tabs. It is offset by that
	 * height instead.
	 *
	 * The safe-area inset belongs to the site bar's own padding, and adding it
	 * here as well as in the offset would double-count it on a notched phone.
	 */
	.bedi-build__actions {
		background-color: var(--bedi-surface);
		border-block-start: var(--bedi-border-width) solid var(--bedi-rule);
		box-shadow: 0 -6px 24px -12px var(--bedi-shadow-soft);
		column-gap: var(--bedi-space-3);
		display: flex;
		inset-block-end: calc(var(--bedi-bottombar-h, 0px) + env(safe-area-inset-bottom, 0px));
		inset-inline: 0;
		margin: 0;
		padding: var(--bedi-space-2) var(--bedi-gutter);
		position: fixed;
		z-index: var(--bedi-z-buybar);
	}

	/*
	 * And tell the consultation dock this bar is here. dock.css reads
	 * `--bedi-dock-offset`, which mobile-bar.css computes as
	 * bottombar-h + buybar-h + space-3 — so publishing a height into
	 * `--bedi-buybar-h` is the one line that stops the dock's bubble landing on
	 * the total. 68px is this bar's measured height: a 44px button plus its
	 * padding. It is a constant rather than a measurement because, unlike the
	 * product buy bar, nothing in this bar changes height.
	 *
	 * builder.css loads on this URL alone, so a :root rule here cannot reach
	 * another page — which is exactly how mobile-bar.css scopes its own.
	 */
	:root {
		--bedi-buybar-h: 68px;
	}

	/*
	 * ON A PHONE THE BAR CARRIES THE MONEY AND ONE BUTTON.
	 *
	 * At 375px `კალათაში დამატება` and `აწყობის მოთხოვნა` take every pixel
	 * there is, the total is squeezed to about thirty, and `3 690,00 ₾` renders
	 * one character per line — a column of digits down the corner of the screen.
	 *
	 * Clipping a Georgian label to make it fit is not an option: these words are
	 * not abbreviable and a truncated verb is not a button. So the second button
	 * leaves the bar instead, and the request form is simply OPEN in the rail
	 * where there is room for it. Nothing is duplicated and no string is
	 * shortened.
	 */
	.bedi-build__actions {
		min-block-size: 0;
		padding-block: var(--bedi-space-2);
		padding-inline: var(--bedi-gutter);
	}

	/*
	 * One hairline, not two: at 375px the bar is the meter, the money and one
	 * button, and a rule between every pair of them is more lines than content.
	 */
	.bedi-build__total::after {
		display: none;
	}

	.bedi-build__meter,
	.bedi-build__total {
		padding-inline-end: var(--bedi-space-3);
	}

	.bedi-build__total {
		padding-inline-start: var(--bedi-space-3);
	}

	.bedi-build__buttons {
		padding-inline-start: 0;
	}

	.bedi-build__cart {
		min-inline-size: 0;
	}

	/*
	 * At 375px the bar holds the meter, the money and one button. The meter's
	 * LABEL is what goes: `1 / 6` beside a progress bar is already legible
	 * without `აუცილებელი ნაწილები` spelling it out, and the words are what
	 * would push the price off the row.
	 */
	.bedi-build__meter {
		inline-size: 3.75rem;
	}

	.bedi-build__meter-label {
		display: none;
	}

	.bedi-build__total {
		flex: 0 1 auto;
	}

	.bedi-build__total span {
		display: none;
	}

	.bedi-build__total strong {
		font-size: var(--bedi-text-xl);
	}

	.bedi-build__total {
		flex: 1 1 auto;
	}

	.bedi-build__buttons {
		flex: 1 1 auto;
		justify-content: flex-end;
		min-inline-size: 0;
	}

	.bedi-build__buttons .bedi-btn {
		block-size: 44px;
		font-size: var(--bedi-text-base);
		padding-inline: var(--bedi-space-4);
	}

	.bedi-build__cart {
		min-inline-size: 0;
	}

	.bedi-build__cart .bedi-btn__label {
		display: none;
	}

	.bedi-build__cart-short {
		display: inline;
		white-space: nowrap;
	}

	.bedi-build__cart-sum {
		display: none;
	}

	/* The opener has nothing to open: the form below is already open. */
	.bedi-build__ask {
		display: none;
	}

	.bedi-build__panel.is-live .bedi-build__request {
		display: grid;
		margin-block-start: var(--bedi-space-5);
	}

	/*
	 * On a phone there are TWO fixed bars stacked: this one and the site's own
	 * navigation below it. The clearance has to cover both, so the bottom bar's
	 * published height is added to it here and nowhere else.
	 */
	.bedi-build__grid {
		padding-block-end: calc(var(--bedi-bottombar-h, 0px) + var(--bedi-space-7));
	}

	.bedi-build__machine {
		max-inline-size: 13rem;
	}

	.bedi-build__group {
		padding: var(--bedi-space-4) var(--bedi-space-3);
	}

	.bedi-build__slot {
		grid-template-columns: auto minmax(0, 1fr);
		row-gap: var(--bedi-space-2);
	}

	.bedi-build__slot-side {
		grid-column: 1 / -1;
		justify-content: space-between;
	}

	.bedi-build__select {
		max-inline-size: 100%;
	}

	/* The picker becomes a bottom sheet. */
	.bedi-buildsheet__panel {
		border-radius: var(--bedi-radius-2xl) var(--bedi-radius-2xl) 0 0;
		inline-size: 100%;
		inset-block-end: 0;
		inset-block-start: auto;
		inset-inline-start: 0;
		max-block-size: 92dvh;
		transform: translateY(100%);
	}

	.bedi-buildsheet.is-open .bedi-buildsheet__panel {
		transform: translateY(0);
	}

	.bedi-buildsheet__row {
		grid-template-columns: 44px minmax(0, 1fr) auto;
	}

	.bedi-buildsheet__row-media {
		block-size: 44px;
		inline-size: 44px;
	}

	/*
	 * The tick moves rather than disappearing. Hiding it left a 7% background
	 * wash as the only sign of which product is currently chosen — invisible to
	 * anyone who cannot separate those two whites, and gone entirely in forced
	 * colours. It becomes an inline mark beside the price instead, which the
	 * three-column phone grid has room for.
	 */
	.bedi-buildsheet__row {
		grid-template-columns: 44px minmax(0, 1fr) auto;
	}

	.bedi-buildsheet__row-tick {
		display: none;
	}

	.bedi-buildsheet__row[data-selected="1"] .bedi-buildsheet__row-price::after {
		content: " \2713";
		color: var(--bedi-accent-strong);
		font-weight: var(--bedi-weight-bold);
	}
}

@media (prefers-reduced-motion: reduce) {
	.bedi-buildsheet__panel,
	.bedi-buildsheet__scrim {
		transition-duration: var(--bedi-dur-micro);
	}

	.bedi-buildsheet__panel {
		transform: translate(-50%, -50%);
	}

	.bedi-build__bar-fill {
		transition-duration: 1ms;
	}
}

/* =========================================================================
   7. PRINT

   A build is a document people take to a showroom or send to an accountant, so
   the page prints as a parts list: the rail's furniture, the controls and the
   dialog go, the rows and the total stay.

   Specificity matches the screen rules these override. @media print does NOT
   raise specificity — base.css records `layout.css`'s print `body` rule at
   (0,0,1) losing outright to its own `:root body` at (0,1,1), which would have
   printed the whole catalogue at the wrong size.
   ====================================================================== */

@media print {
	.bedi-build__machine,
	.bedi-build__tray,
	.bedi-build__bar,
	.bedi-build__buttons,
	.bedi-build__bar,
	.bedi-build__request,
	.bedi-build__apply,
	.bedi-build__live,
	.bedi-build__nojs,
	.bedi-buildsheet {
		display: none !important;
	}

	.bedi-build__grid {
		display: block;
		padding-block-end: 0;
	}

	/*
	 * The print block's contract is "the rows and the total stay". The total
	 * lives in the action bar, which is `position: fixed` — and a fixed element
	 * prints once, on page one, over whatever is under it. Unfixing it is what
	 * makes the promise true.
	 */
	.bedi-build__actions {
		border: 0;
		box-shadow: none;
		display: flex;
		padding: 0;
		position: static;
	}

	.bedi-build__meter,
	.bedi-build__total {
		padding-inline: 0 var(--bedi-space-5);
	}

	.bedi-build__meter::after,
	.bedi-build__total::after {
		display: none;
	}

	.bedi-build__panel {
		border: 0;
		padding: 0;
	}

	.bedi-build__group {
		background: none;
		padding: 0;
	}

	.bedi-build__slot,
	.bedi-build__panel {
		break-inside: avoid;
	}

	.bedi-build__slot {
		border-color: var(--bedi-print-ink);
	}
}
