/**
 * CART-DESIGN-001 v3 - gated preview styling.
 *
 * ELEMENTOR-FIRST (v3 principle 2). This file is deliberately much smaller than
 * v2's. Everything Elementor can own now lives in Elementor: the card action row
 * is a real Shortcode widget inside listings 1301 / 3982 / 3915, so its position,
 * spacing and alignment are Aaron's to edit. What is left here is the stuff a
 * widget cannot express - a compound stepper, three controls adjoining with zero
 * gap, hover and focus states, a runtime-injected drawer and toast, and the nav
 * wrap behaviour.
 *
 * THREE RULES THIS FILE KEEPS TO:
 *
 * 1. NO !important, anywhere. Grep it: there are none.
 * 2. Lowest specificity that still works. Most rules are `.vri-cart .thing`,
 *    which is (0,2,0) - the MINIMUM that beats the kit's own
 *    `.elementor-kit-3633 button { background-color }` at (0,1,1).
 *
 *    FORM CONTROLS ARE THE ONE EXCEPTION, and they are marked in place below.
 *    Kit 3633 also ships `.elementor-kit-3633 input:not([type="button"])...`,
 *    and `:not()` carries its argument's specificity, so that rule lands at
 *    (0,2,1) and beat every (0,2,0) rule here: the quantity field rendered as
 *    white-on-white with a stray border. Those specific rules are therefore
 *    written as `.vri-cart .component .component__part` = (0,3,0). Measured,
 *    not guessed, and lifted only where the collision is real.
 *
 *    Two tiers are needed, both measured against the kit's real selectors:
 *      - buttons collide with `.elementor-kit-3633 button` (0,1,1)  -> (0,2,0)
 *      - form fields collide with
 *        `.elementor-kit-3633 input:not([type="button"]):not([type="submit"])`,
 *        which is (0,3,1) because each :not() carries its attribute's weight.
 *        Those rules are written as (0,4,1) so they win deterministically
 *        rather than by source order.
 *    This is not override-proof - no !important is used and Elementor or any
 *    later rule can still win. It is simply enough to beat a site-wide default
 *    on controls Aaron cannot reach from Elementor anyway.
 * 3. NO literal colours, font stacks or type sizes. Every value references an
 *    Elementor global, so a change Aaron makes in Site Settings propagates here
 *    automatically. Literals appear only as var() fallbacks, so a kit-load
 *    failure degrades to something readable rather than invisible.
 *
 * Card sizes are expressed as a RATIO of the Accent global rather than as fixed
 * px: `calc(var(--e-global-typography-accent-font-size) * 0.7)`. Accent is
 * already Montserrat 700 / 1.5px / uppercase - the button style - so if Aaron
 * retypes it, the cards scale with it instead of drifting out of step.
 */

/* ------------------------------------------------------------------- tokens */

.vri-cart {
	/* Colours - Elementor globals, literal only as a last-resort fallback. */
	--vri-ec-black:  var(--e-global-color-primary, #000000);
	--vri-ec-blue:   var(--e-global-color-secondary, #25AAE2);
	--vri-ec-blue-text: var(--vri-blue, #25AAE2); /* DEFECT-BATCH-02: Text Blue retired (Aaron, 14 Oct 2026) - brand blue is the only blue */
	--vri-ec-white:  var(--e-global-color-accent, #FFFFFF);
	--vri-ec-text:   var(--vri-ec-black); /* was the kit Text global #3D3D3D - Standing Rule 1 (Aaron 25 Sep 2026): text is black */
	--vri-ec-soft:   var(--e-global-color-af5f5f5, #F5F5F5);
	--vri-ec-line:   var(--e-global-color-ad9dde6, #D9DDE6);

	/* Type - all from the Accent global, which IS the button style. */
	--vri-ec-font:   var(--e-global-typography-accent-font-family, Montserrat), sans-serif;
	--vri-ec-weight: var(--e-global-typography-accent-font-weight, 700);
	--vri-ec-track:  var(--e-global-typography-accent-letter-spacing, 1.5px);
	--vri-ec-caps:   var(--e-global-typography-accent-text-transform, uppercase);
	--vri-ec-base:   var(--e-global-typography-accent-font-size, 16px);

	/* Card controls run at the full Accent size: HUB-ALIGN-001 (Aaron, 16 Oct 2026) - every enquiry control's
	   text (ADD TO ENQUIRY, VIEW, the - N + stepper) matches the INFO SHEET / DWG FILE / PNG FILE download
	   buttons, 16px / 700 / Accent tracking. Was 70% (11.2px). Narrow cards step down: see section 11. */
	--vri-ec-card-size: var(--vri-ec-base);

	/* One control height everywhere. 44px is the site's own touch minimum. */
	--vri-ec-control: 44px;

	/*
	 * v-FINAL Phase 1.3: the two black end blocks (stepper + VIEW) share ONE
	 * width so the row reads balanced: [black stepper][blue add][black VIEW].
	 * Wide enough for the compound stepper ( - NN + ) at 24+24+24 = 72px (A11Y-SITEWIDE-001: 24px minimum target width).
	 */
	--vri-ec-endblock: 72px;
}

.vri-cart .vri-ec-sr {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* =====================================================================
   1. THE CARD ACTION ROW
   Markup comes from [vri_enquiry_actions], placed as an Elementor Shortcode
   widget in each listing template. This styles its internals only.
   ===================================================================== */

.vri-cart .vri-ec-actions {
	display: flex;
	align-items: stretch;
	/* The three controls must touch. No gap, no padding between them. */
	gap: 0;
	width: 100%;
}

/* Shared control chrome. */
.vri-cart .vri-ec-actions__qty,
.vri-cart .vri-ec-actions__add,
.vri-cart .vri-ec-actions__view {
	box-sizing: border-box;
	min-height: var(--vri-ec-control);
	margin: 0;
	border: 0;
	border-radius: 0;
	font-family: var(--vri-ec-font);
	font-weight: var(--vri-ec-weight);
	line-height: 1.2;
	transition: background-color 0.2s ease, color 0.2s ease;
}

/* --- quantity: black block, white text, reads as ( - N + ) ---------------
   Narrowed hard for the one-line row, but the number field still holds three
   digits without clipping - checked at 999, not just at 20. */
.vri-cart .vri-ec-actions__qty {
	display: flex;
	/* v-FINAL Phase 1.3: fixed to the shared end-block width, centred, so it
	   balances the VIEW block on the far side. */
	flex: 0 0 var(--vri-ec-endblock);
	align-items: stretch;
	justify-content: center;
	background-color: var(--vri-ec-black);
}

/* (0,3,0): beats the kit's own button and input rules. See header note 2.
   v3.3: narrowed to 22px so the whole stepper is just wide enough for a two
   digit quantity, per Aaron. */
.vri-cart .vri-ec-actions .vri-ec-actions__step {
	appearance: none;
	-webkit-appearance: none;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 24px;
	flex: 0 0 auto;
	min-height: var(--vri-ec-control);
	padding: 0;
	border: 0;
	border-radius: 0;
	background-color: transparent;
	color: var(--vri-ec-white);
	font-family: var(--vri-ec-font);
	font-size: var(--vri-ec-card-size); /* HUB-ALIGN-001: was 85% of Accent; the stepper matches ADD TO ENQUIRY */
	font-weight: var(--vri-ec-weight);
	line-height: 1;
	cursor: pointer;
}

.vri-cart .vri-ec-actions .vri-ec-actions__step:hover {
	color: var(--vri-ec-blue);
}

.vri-cart .vri-ec-actions .vri-ec-actions__qty input.vri-ec-actions__num {
	appearance: textfield;
	-moz-appearance: textfield;
	/* Just enough for a two-digit number (XX) at the card font size. */
	width: 24px;
	padding: 0;
	border: 0;
	border-radius: 0;
	background-color: transparent;
	color: var(--vri-ec-white);
	font-family: var(--vri-ec-font);
	font-size: var(--vri-ec-card-size);
	font-weight: var(--vri-ec-weight);
	line-height: 1;
	text-align: center;
}

.vri-cart .vri-ec-actions .vri-ec-actions__qty input.vri-ec-actions__num::-webkit-outer-spin-button,
.vri-cart .vri-ec-actions .vri-ec-actions__qty input.vri-ec-actions__num::-webkit-inner-spin-button {
	-webkit-appearance: none;
	margin: 0;
}

/* --- add: blue, white text. v-FINAL Phase 1.5: hover keeps the button BLUE
   and turns the TEXT black (previously the whole button went black). --------- */
.vri-cart .vri-ec-actions .vri-ec-actions__add {
	display: flex;
	flex: 1 1 auto;
	min-width: 0;
	/* Two centred lines with tight leading. A single-line label (the product
	   block builds one) simply renders as one centred line here. */
	flex-direction: column;
	align-items: center;
	justify-content: center;
	padding: 0 6px;
	background-color: var(--vri-ec-blue);
	color: var(--vri-ec-white);
	font-size: var(--vri-ec-card-size);
	line-height: 1.08;
	letter-spacing: var(--vri-ec-track);
	text-transform: var(--vri-ec-caps);
	text-align: center;
	white-space: normal;
	overflow: hidden;
	cursor: pointer;
}

/* The two label lines in listing cards. */
.vri-cart .vri-ec-actions__addl1,
.vri-cart .vri-ec-actions__addl2 {
	display: block;
}

.vri-cart .vri-ec-actions .vri-ec-actions__add:hover {
	background-color: var(--vri-ec-blue);
	color: var(--vri-ec-black);
}

/*
 * v3.3: the "already in cart" black underline is removed at Aaron's request -
 * it read as a stray black line under the button. In-cart state is still shown
 * by the label flipping to "Added" on the add itself, so nothing is lost.
 */

/* --- VIEW: the word, not an icon (v-FINAL Phase 1.1). Black box matching the
   stepper width, white text; the whole box turns blue on hover/focus, which is
   the existing end-block hover convention. The colour is set on the <a> itself
   AND re-asserted on the text via the box, but note the WPCode trap below.

   TRAP (Shared_10 guardrail 3): a WPCode snippet ships
   `.jet-listing-grid a:link { color: unset }` at (0,2,1), which outranks a
   (0,2,0) rule on the anchor and would render VIEW as unset (dark) on black.
   The old eye sidestepped this by colouring a child span. Here the anchor IS
   the text, so the colour rule is written at (0,3,0) via the component chain
   to clear the (0,2,1) :link rule deterministically, matching the form-control
   exception documented in the header note. No !important. */
.vri-cart .vri-ec-actions .vri-ec-actions__view {
	display: flex;
	flex: 0 0 var(--vri-ec-endblock);
	align-items: center;
	justify-content: center;
	background-color: var(--vri-ec-black);
	color: var(--vri-ec-white);
	font-size: var(--vri-ec-card-size);
	/* HUB-ALIGN-001: the weight is restated at (0,3,0) - the shared chrome rule (0,2,0) lost to WPCode 3742's
	   `.jet-listing-grid a:link { font-weight: unset }` (0,2,1), so VIEW rendered 500 beside a 700 ADD TO ENQUIRY. */
	font-weight: var(--vri-ec-weight);
	letter-spacing: var(--vri-ec-track);
	text-transform: var(--vri-ec-caps);
	text-decoration: none;
}

/* HUB-ALIGN-001 (Aaron, Outdoor_Fitness.pdf): VIEW stays black on hover and its text turns brand blue
   (was: the whole box turned blue). */
.vri-cart .vri-ec-actions .vri-ec-actions__view:hover,
.vri-cart .vri-ec-actions .vri-ec-actions__view:focus-visible {
	background-color: var(--vri-ec-black);
	color: var(--vri-ec-blue);
}

/* Focus ring, per Shared_10. */
.vri-cart .vri-ec-actions__add:focus-visible,
.vri-cart .vri-ec-actions__view:focus-visible,
.vri-cart .vri-ec-actions__step:focus-visible,
.vri-cart .vri-ec-actions__num:focus-visible {
	outline: 2px solid var(--vri-ec-blue);
	outline-offset: 2px;
}

/* =====================================================================
   2. CARD SPACING (v3 item 2)
   HONEST LIMIT: the existing title/SKU spacing is an Elementor column setting
   (space_between_widgets) on listings 1301 / 3915. Changing it there would
   apply with the flag OFF too, which breaks the gate. So while the preview
   gate exists it is tightened here, scoped to preview. At lock time, when the
   gate is dropped, this block is deleted and the same result comes from one
   Elementor setting Aaron owns.
   ===================================================================== */

.vri-cart .vri-card-title,
.vri-cart .vri-card-sku {
	margin-top: 0;
	margin-bottom: 0;
}

/* Halve the 20px inter-widget rhythm around the title and SKU. */
.vri-cart .vri-card .elementor-widget:not(:last-child) {
	margin-bottom: 10px;
}

/* Close the dead gap between the SKU and the action row entirely. */
.vri-cart .vri-card-sku {
	margin-bottom: 0;
}

/*
 * DEFECT 1 (v3.1): action rows must sit on a common baseline across a grid row.
 *
 * Titles wrap to two lines on plenty of products ("Stepping Stump with Painted
 * Top"), which pushed those cards' action rows lower than their neighbours' - a
 * ragged edge repeated down a 197-product grid.
 *
 * The site's own WPCode card CSS already makes the whole card chain a flex
 * column and pins the OLD button widget to the bottom with `margin-top:auto`.
 * The new row is a shortcode widget, so it never inherited that. Giving it the
 * same auto top margin drops it to the bottom of the card, and because the grid
 * stretches every item in a row to equal height, every row lands on the same
 * baseline whatever the title does.
 *
 * This overrides the widget's own Elementor margin (0), which is why it is CSS
 * and not a template setting - Elementor's margin control cannot express `auto`.
 */
.vri-cart .vri-card-actions {
	margin-top: auto;
}

/* The flex chain has to actually fill the card for `auto` to have room to push
   against. The site's CSS does this for the grid card; the hub card (3915) uses
   the same classes, so one rule covers both. */
.vri-cart .vri-card .elementor-widget-wrap,
.vri-cart .vri-card .elementor-column {
	display: flex;
	flex-direction: column;
	flex: 1;
}

/*
 * PARITY-PROTECTION RULES: DELETED (SOLIDIFY P4).
 *
 * `.vri-card-btn-view` and `.vri-card-btn-enquiry` were hidden here rather than
 * deleted, so that dropping the flag restored the old controls with no DOM
 * repair. The flag is gone and those two buttons have now been deleted from the
 * listing templates themselves (1301 widget 895ea7e; 3915 widgets a7l013 and
 * a7l014), so there is nothing left to hide - keeping the rule would only mask a
 * future accidental re-add.
 *
 * `.vri-ec-was-here` STAYS. It marks the product page's own ENQUIRE NOW button,
 * which lives in Theme Builder template 1312 and is replaced in P5, not here.
 * Removing this rule before that would put two competing enquiry controls on
 * every one of ~200 product pages.
 */
.vri-cart .vri-ec-was-here {
	display: none;
}

/* =====================================================================
   3. LIST VIEW (listing 3982) - LIST-VIEW-002 (Aaron, 25 Sep 2026: Option C
   base + Hub addenda 1-3, his marked-up prototype)
   One row per product, framed with even padding:
     [ image ] [SKU ] [Size   Fallzone   FHoF   Min age   Budget]  <- spec line
     [       ] [name] [short description, max two lines ........]  <- description
     [       ] [    ] [Info Sheet][DWG][PNG]      [- 1 +][ADD][eye] <- buttons
   The image spans the whole row: its top meets the SKU line and its bottom
   meets the bottom of the button row. SKU (above) and name fill the column
   beside it. Spec line, description and buttons share one left edge (the
   Info Sheet button's) and one right edge; the five spec columns spread
   evenly across that width, matched by the sortable header. Widths are
   shared through --vri-list-* (vri-filtering-ux.css).

   Below 1240px the list column is too narrow for that (it needs ~800px), so
   rows stack: image + SKU/name, spec cells, description, buttons.

   The rail itself is still built by buildListRails() in vri-ec-preview.js (a
   stopgap: converting it to an Elementor container in 3982 is a logged
   follow-up). _css_classes on 3982's containers never render, so the nested
   containers are dissolved into the row grid and the pieces placed directly.
   ===================================================================== */

.vri-cart .vri-ec-listrow {
	display: grid;
	grid-template-columns: var(--vri-list-cols, 118px minmax(0, 1fr) 520px);
	grid-template-rows: auto auto auto;
	/* .e-con-inner reads align-items from its own variable (the property
	   alone loses to Elementor's container rule), so set both. */
	--align-items: start;
	align-items: start;
	column-gap: var(--vri-list-gap, 12px);
	row-gap: 6px;
	/* PRODUCTS-POLISH-001 8 (SESSION-4b): top/bottom halved - 4px here + the item's own 8px = 12px (was 16 + 8 = 24). */
	padding: 4px 8px;
	/* No kit widget spacing inside the row: the grid owns every gap. */
	--kit-widget-spacing: 0px;
	--widgets-spacing: 0px 0px;
	--widgets-spacing-row: 0px;
}

.vri-cart .vri-ec-listrow .elementor-widget,
.vri-cart .vri-ec-listrow .elementor-heading-title {
	margin-block: 0;
}

/* Every container inside the row (the content column, the title row and
   their inner wrappers) dissolves into the row grid. Containers take display
   from their own variable, so set both. The title row's inner wrapper
   (.vri-ec-listhead, tagged by buildListRails()) stays: it holds SKU + name. */
.vri-cart .vri-ec-listrow .e-con {
	--display: contents;
	display: contents;
}

.vri-cart .vri-ec-listrow .e-con > .e-con-inner:not(.vri-ec-listhead) {
	display: contents;
}

/* Image: the full row height, from the SKU line to the bottom of the buttons. */
.vri-cart .vri-ec-listrow > .vri-list-card-image {
	grid-column: 1;
	grid-row: 1 / 4;
	align-self: stretch;
	width: var(--vri-list-img, 118px);
	height: auto;
	margin: 0;
}

.vri-cart .vri-ec-listrow > .vri-list-card-image .elementor-widget-container,
.vri-cart .vri-ec-listrow > .vri-list-card-image a {
	display: block;
	height: 100%;
	line-height: 0;
}

.vri-cart .vri-ec-listrow > .vri-list-card-image img {
	width: 100%;
	height: 100%;
	max-height: none;
	object-fit: contain;
}

/* SKU above name, alone in the column beside the image. */
.vri-cart .vri-ec-listhead {
	grid-column: 2;
	grid-row: 1 / 4;
	align-self: start;
	min-width: 0;
}

/* Elementor's `.e-con > .e-con-inner` sets gap, height, width and margin
   from container variables; flatten them so SKU and name sit tight. */
.vri-cart .vri-ec-listrow .e-con > .e-con-inner.vri-ec-listhead {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 2px;
	padding: 0;
	margin: 0;
	width: auto;
	height: auto;
	max-width: none;
}

.vri-cart .vri-ec-listhead > .vri-list-card-sku {
	order: -1;
}

/* Spec line, description and buttons: one column, one left and right edge. */
.vri-cart .vri-ec-listrow .vri-list-card-specline {
	grid-column: 3;
	grid-row: 1;
	margin: 0;
}

.vri-cart .vri-ec-listrow .vri-list-card-desc {
	grid-column: 3;
	grid-row: 2;
	margin: 0;
}

.vri-cart .vri-ec-listrail {
	grid-column: 3;
	grid-row: 3;
	display: flex;
	flex-direction: row;
	justify-content: space-between;
	align-items: stretch;
	gap: 8px;
	margin-top: 6px;
}

.vri-cart .vri-ec-listrail > .elementor-widget {
	width: auto;
	margin: 0;
}

.vri-cart .vri-ec-listrail .vri-list-card-downloads .vri-ec-dl {
	width: 300px;
}

@media (max-width: 1239px) {
	/* LIST-VIEW-RESPONSIVE-001 (Aaron, 22 Oct 2026): below 1240px the stats used to drop under a 150px image, leaving
	   an empty box beside a short title. Two tiers now, both with the image the desktop width (--vri-list-img) and
	   spanning a flexible spacer row, so a tall image never opens a gap between the rows beside it:
	     below 575:  [image] [SKU / name]          575-1239: [image] [SKU / name] [stats]
	                 [     ] [stats]                         [     ] [description ......]
	                 [description ...........]               [buttons ....................]
	                 [buttons ...............]
	   The NEW chip sits on the image's top-left corner, as everywhere else (Aaron, 25 Sep). */
	.vri-cart .vri-ec-listrow {
		grid-template-columns: var(--vri-list-img, 118px) minmax(0, 1fr);
		/* name, stats, spacer (takes any extra image height), description, buttons */
		grid-template-rows: auto auto 1fr auto auto;
		column-gap: var(--vri-list-gap, 12px);
		row-gap: 0;
		padding: 0; /* PRODUCTS-POLISH-001 8: halved - the item's own 8px alone (was 8 + 8 = 16) */
	}

	.vri-cart .vri-ec-listrow > .vri-list-card-image {
		grid-column: 1;
		grid-row: 1 / 4;
		align-self: start;
		width: var(--vri-list-img, 118px);
		height: var(--vri-list-img, 118px);
	}

	.vri-cart .vri-ec-listhead {
		grid-column: 2;
		grid-row: 1;
		align-self: start;
	}

	/* NEW chip: a grid item sharing the image's cell, pinned exactly to its
	   top-left corner - the same place as on the grid card and product page.
	   (Snippet 4096 floats it at 12px/12px from the item at (0,3,0), which
	   misses the corner in this grid; this is (0,4,0).) */
	.vri-cart .vri-ec-listrow > .elementor-widget.vri-new-chip-w {
		position: relative;
		top: auto;
		left: auto;
		grid-column: 1;
		grid-row: 1;
		justify-self: start;
		align-self: start;
		z-index: 2;
		width: auto;
		margin: 0;
	}

	/* Explicit rows keep the brief's order whatever the DOM order. Stats directly under the name (no gap: the
	   spacer row, not the stats row, takes the image's extra height); description and buttons the full width. */
	.vri-cart .vri-ec-listrow .vri-list-card-specline {
		grid-column: 2;
		grid-row: 2;
		margin-top: 6px;
	}

	.vri-cart .vri-ec-listrow .vri-list-card-desc {
		grid-column: 1 / -1;
		grid-row: 4;
		margin-top: 8px;
	}

	.vri-cart .vri-ec-listrail {
		grid-column: 1 / -1;
		grid-row: 5;
		flex-wrap: wrap;
		gap: 6px;
		margin-top: 8px;
	}

	.vri-cart .vri-ec-listrail > .vri-list-card-downloads {
		flex: 1 1 300px;
	}

	.vri-cart .vri-ec-listrail > .elementor-widget:not(.vri-list-card-downloads) {
		flex: 1 1 212px;
	}

	.vri-cart .vri-ec-listrail .vri-list-card-downloads .vri-ec-dl {
		width: 100%;
	}
}

/* LIST-VIEW-RESPONSIVE-001: 575-1239, the stats share the first line with the name (the row reads as one line, as at
   desktop). Name and stats share the space 1 : 4, so the stats get it first and the name column stays narrow like the
   desktop one (a longer name wraps, up to the 5-line clamp): no empty box beside a short name, and the stats line up
   from row to row. Minimums and why: --vri-list-name-min / --vri-list-stats-min in vri-filtering-ux.css. The
   description sits under both. */
@media (min-width: 575px) and (max-width: 1239px) {
	.vri-cart .vri-ec-listrow {
		grid-template-columns: var(--vri-list-img, 118px) minmax(var(--vri-list-name-min, 80px), 1fr) minmax(var(--vri-list-stats-min, 225px), 4fr);
		/* name + stats, description, spacer, buttons */
		grid-template-rows: auto auto 1fr auto;
	}

	.vri-cart .vri-ec-listrow .vri-list-card-specline {
		grid-column: 3;
		grid-row: 1;
		margin-top: 0;
	}

	.vri-cart .vri-ec-listrow .vri-list-card-desc {
		grid-column: 2 / -1;
		grid-row: 2;
		margin-top: 6px;
	}

	.vri-cart .vri-ec-listrail {
		grid-row: 4;
	}
}

/* LIST-VIEW-RESPONSIVE-002 (Aaron, 22 Oct 2026): where the buttons take two rows, the six controls are one grid of
   three equal columns - INFO SHEET | DWG FILE | PNG FILE, then directly beneath (- 1 +) | ADD TO ENQUIRY | VIEW, each
   filling its cell (the stepper and VIEW were fixed 72px blocks beside a stretched ADD TO ENQUIRY).
   The rail is the size container: it takes its width from the row grid (spanning every column), never from its
   content, so it cannot collapse the way a container on the enquiry bar itself did (the vri-ec-card rule further
   down this file). On its own the rail wraps below 518px (the downloads' 300px basis + 6px gap + the enquiry row's
   212px basis), but a one-line rail leaves ADD TO ENQUIRY too narrow for "ENQUIRY" at 16px (88px + 12px padding =
   100px) until the enquiry row reaches 244px (72 + 100 + 72); the row gets half of the width above 518px (both grow
   1 : 1), so that is 518 + 2 x 32 = 582px. Below 582px the two rows are forced. Desktop (1240+) is not a container
   and the one-line rails (582px and wider) are untouched. Container conditions cannot read var(), so the widths are
   restated here; .98 as at the other seams in this file. */
@media (max-width: 1239px) {
	.vri-cart .vri-ec-listrail {
		container-type: inline-size;
		container-name: vri-ec-listrail;
	}
}

@container vri-ec-listrail (max-width: 581.98px) {
	/* Two rows: the downloads take the whole first line. */
	.vri-cart .vri-ec-listrail > .vri-list-card-downloads {
		flex-basis: 100%;
	}

	/* The enquiry row on three equal columns, no gap: the downloads' own grid (vri-ec.css: one column per file,
	   gap 0) with its columns made strictly equal, so with three files the six controls share every edge. A product
	   with fewer files keeps the row filled (two files: halves), as before. */
	.vri-cart .vri-ec-listrail .vri-list-card-downloads .vri-ec-dl {
		grid-auto-columns: minmax(0, 1fr);
	}

	.vri-cart .vri-ec-listrail .vri-ec-actions {
		display: grid;
		grid-template-columns: repeat(3, minmax(0, 1fr));
		gap: 0;
	}

	/* - count + spread across the cell under INFO SHEET; VIEW and ADD TO ENQUIRY fill theirs. ADD TO ENQUIRY's side
	   padding 2px, so "ENQUIRY" at 16px (88px) fits a cell from 92px (a rail from 276px). */
	.vri-cart .vri-ec-listrail .vri-ec-actions .vri-ec-actions__qty {
		justify-content: space-between;
		min-width: 0;
	}

	.vri-cart .vri-ec-listrail .vri-ec-actions .vri-ec-actions__view {
		min-width: 0;
	}

	.vri-cart .vri-ec-listrail .vri-ec-actions .vri-ec-actions__add {
		padding: 0 2px;
	}
}

/* Cells under 92px (a rail under 276px: phones narrower than ~372px): the enquiry controls take the narrow-card step
   the grid card uses (the vri-ec-card rule further down); "ENQUIRY" at 12px needs 66px (a 320px phone's cell: 75px). */
@container vri-ec-listrail (max-width: 275.98px) {
	.vri-cart .vri-ec-listrail .vri-ec-actions .vri-ec-actions__add,
	.vri-cart .vri-ec-listrail .vri-ec-actions .vri-ec-actions__view,
	.vri-cart .vri-ec-listrail .vri-ec-actions .vri-ec-actions__step,
	.vri-cart .vri-ec-listrail .vri-ec-actions .vri-ec-actions__qty input.vri-ec-actions__num {
		font-size: calc(var(--vri-ec-base) * 0.75);
		letter-spacing: 1px;
	}
}

/* =====================================================================
   4. NAV CART CONTROL (v3 item 3)
   The control itself is injected by the shipped cart JS into a Theme Builder
   header that is on the do-not-touch list, so it cannot be an Elementor
   element. PLUGIN-OWNED, but every value below is a global.
   ===================================================================== */

/* The bag icon is deleted, per v3. Two-cart clarity now rests on the wording
   ("Enquiry" vs "Online Store"), which is why the icon can go. */
.vri-cart .vri-ec-mini__icon {
	display: none;
}

/* A little more air between the label and the count box. */
.vri-cart .vri-ec-mini {
	gap: 12px;
}

/* Blue when holding items, neutral when empty. The shipped JS already toggles
   .is-empty, so this needs no new behaviour. */
.vri-cart .vri-ec-mini__count {
	background-color: var(--vri-ec-blue);
	color: var(--vri-ec-white);
}

.vri-cart .vri-ec-mini.is-empty .vri-ec-mini__count {
	background-color: transparent;
	color: var(--vri-ec-white);
	box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.45);
}

/* =====================================================================
   4b. MOBILE PRODUCTS TAP-SPLIT CARET (v-FINAL Phase 2)
   Injected by setupNavTapSplit(). Desktop is untouched: the caret is hidden and
   the locked script's hover-open still runs. Mobile: the caret is the 44px toggle
   target and the label anchor navigates to /products/.
   ===================================================================== */

/* Hidden by default; revealed only at the mobile widths the locked nav uses. */
.vri-cart .vri-hdr .vri-has-mega .vri-ec-nav-caret {
	display: none;
}

@media (max-width: 1000px) {
	/* The item is position:relative already (locked nav CSS); overlay the caret on
	   the right of the label row as a comfortable 44px square. */
	.vri-cart .vri-hdr .vri-has-mega .vri-ec-nav-caret {
		display: flex;
		align-items: center;
		justify-content: center;
		position: absolute;
		top: 0;
		right: 0;
		width: var(--vri-ec-control);
		height: var(--vri-ec-control);
		padding: 0;
		margin: 0;
		border: 0;
		background: transparent;
		cursor: pointer;
		z-index: 2;
	}

	/* Chevron mirrors the locked template's ::after so the two read identically;
	   flips when the panel is open. */
	.vri-cart .vri-hdr .vri-has-mega .vri-ec-nav-caret::before {
		content: "";
		width: 9px;
		height: 9px;
		border-right: 2px solid var(--vri-ec-white);
		border-bottom: 2px solid var(--vri-ec-white);
		transform: translateY(-25%) rotate(45deg);
		transition: transform 0.2s ease;
	}

	.vri-cart .vri-hdr .vri-has-mega.vri-open .vri-ec-nav-caret::before {
		transform: translateY(25%) rotate(225deg);
	}

	/* Suppress the locked template's own ::after chevron so there is exactly one
	   caret. (0,4,0)+pseudo beats the template's (0,3,0)+pseudo; no !important. */
	.vri-cart .vri-hdr .vri-has-mega > a::after {
		display: none;
	}
}

/* =====================================================================
   5. NAV BANNER - CONSTANT HEIGHT ON WRAP (v3 item 3, the hard one)
   v2 fixed titles wrapping behind the logo by letting the banner grow. v3
   requires the banner NOT to grow: two rows must occupy the same total height
   as one, achieved by reducing type size on the wrapped rows.

   So the row height is halved (104 -> 52 per row) and the type steps down.
   The logo box is untouched at 245x104 and never moves. The Online Store
   block stays locked right at its fixed size.

   Breakpoint logic cannot live in Elementor - the header is a Theme Builder
   template on the do-not-touch list and this is viewport maths.
   ===================================================================== */

@media (min-width: 1001px) {
	/* Banner height is pinned. It cannot grow. */
	.vri-cart .vri-hdr .inner {
		display: flex;
		align-items: stretch;
		justify-content: space-between;
		gap: 20px;
		height: 104px;
	}

	/*
	 * order is load-bearing. In the source the logo comes AFTER .main-menu, so
	 * without explicit order values flex lays the nav out on the left and throws
	 * the logo to the right - which is exactly the "logo position NEVER changes"
	 * rule broken. Caught in a capture, not in review.
	 */
	.vri-cart .vri-hdr .logo {
		order: 0;
		flex: 0 0 245px;
		align-self: center;
	}

	/* nowrap: only the nav's own items may wrap. The CTA never drops. */
	.vri-cart .vri-hdr .main-menu {
		order: 1;
		float: none;
		display: flex;
		flex: 1 1 auto;
		flex-wrap: nowrap;
		align-items: stretch;
		justify-content: flex-end;
		min-width: 0;
	}

	.vri-cart .vri-hdr .main-menu .vri-nav-wrap {
		display: flex;
		flex: 0 1 auto;
		align-items: center;
		min-width: 0;
	}

	.vri-cart .vri-hdr .vri-nav {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
		justify-content: flex-end;
		max-height: 104px;
	}

	/*
	 * Each row is half the banner, so two rows total exactly 104px - the same
	 * as one row of the original 104px items. The type steps down to suit the
	 * shorter row, which is what makes two rows readable in the same space.
	 */
	.vri-cart .vri-hdr .vri-nav > li {
		display: flex;
		align-items: center;
		height: 52px;
	}

	/*
	 * v3.1: the header template's `!important` on this padding has now been
	 * deleted at source (Aaron authorised it - it was a defect in the template,
	 * not a design decision), so the padding can simply be set here with no
	 * `!important` and no fight.
	 *
	 * 10px of side padding, measured: the seven items totalled 907px at the
	 * template's 26px against ~862px of available track, so the nav wrapped even
	 * at 1440. 10px brings it to roughly 850px, so 1440 holds a single row and
	 * wrapping starts only where the space genuinely runs out.
	 *
	 * The vertical box is what keeps a wrapped nav inside the fixed banner: two
	 * 52px rows total the same 104px as one row, with the type stepping down.
	 */
	.vri-cart .vri-hdr .vri-nav > li > a {
		display: flex;
		align-items: center;
		height: 52px;
		padding: 0 10px;
		font-size: calc(var(--vri-ec-base) * 0.75);
		line-height: 1;
	}

	/* The CTA keeps its position and fills the fixed banner height. */
	.vri-cart .vri-hdr .main-menu .phone-number {
		display: flex;
		flex: 0 0 auto;
		align-items: center;
		align-self: stretch;
		height: auto;
	}

	/*
	 * The angled edge is now a fixed 104px again, so the shipped wedge geometry
	 * is correct as-is and is left completely alone.
	 */
}

/*
 * v3.3: PIN THE BLUE UNDERLINE TO THE BANNER BASE (single-row widths).
 *
 * The current/hover underline is the theme's `border-bottom: 6px` on the nav
 * <li> (design.css). With the item compressed to 52px and vertically centred,
 * that border floated in the middle of the 104px banner rather than sitting on
 * its bottom edge - which is what Aaron flagged.
 *
 * Fix: where the nav genuinely fits ONE row, give each item the full banner
 * height so its bottom border lands on the banner's bottom edge, with the text
 * still vertically centred. The single-row width was MEASURED at >=1250px
 * (content is a fixed 683px; it wraps at 1240). Below that the nav wraps to two
 * 52px rows and the underline is not pinned - Aaron explicitly allowed that for
 * the two-row case.
 */
@media (min-width: 1250px) {
	.vri-cart .vri-hdr .vri-nav > li {
		height: 104px;
	}

	.vri-cart .vri-hdr .vri-nav > li > a {
		height: 104px;
	}
}

/*
 * v3.3: the current page reads blue and two steps bolder (500 -> 700).
 * The theme paints nav links white at (0,1,3); this is (0,4,1) so it wins
 * without !important, and Elementor could still override it.
 */
.vri-cart .vri-hdr .vri-nav > li.current-menu-item > a {
	color: var(--vri-ec-blue);
	font-weight: 700;
}

/*
 * The Enquiry Cart control is not a "page", so it must never carry the current
 * underline or the blue current-text. On /products/ etc. under preview it could
 * pick both up when its href matches; suppress here. (The /enquiry/ page does
 * the same under .vri-submit, since that surface is not always in preview mode.)
 */
.vri-cart .vri-hdr .vri-nav > li.vri-ec-mini-item.current-menu-item {
	border-bottom-color: transparent;
}

.vri-cart .vri-hdr .vri-nav > li.vri-ec-mini-item.current-menu-item > a {
	color: var(--vri-ec-white);
	font-weight: 500;
}

/* =====================================================================
   6. DRAWER (v3 item 4)
   PLUGIN-OWNED by necessity: a runtime-injected overlay cannot be an Elementor
   element. Kept structural, all values from globals.
   ===================================================================== */

.vri-cart .vri-ec-drawer {
	position: fixed;
	inset: 0;
	z-index: 100000;
	visibility: hidden;
	pointer-events: none;
}

.vri-cart .vri-ec-drawer.is-open {
	visibility: visible;
	pointer-events: auto;
}

.vri-cart .vri-ec-drawer__backdrop {
	position: absolute;
	inset: 0;
	background-color: rgba(0, 0, 0, 0.45);
	opacity: 0;
	transition: opacity 0.25s ease;
}

.vri-cart .vri-ec-drawer.is-open .vri-ec-drawer__backdrop {
	opacity: 1;
}

.vri-cart .vri-ec-drawer__panel {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	display: flex;
	flex-direction: column;
	/* v3.3: back to 460 now the thumbnail is 72px again (was 560 for the 144px image). */
	width: min(460px, 100%);
	background-color: var(--vri-ec-white);
	transform: translateX(100%);
	transition: transform 0.25s ease;
}

.vri-cart .vri-ec-drawer.is-open .vri-ec-drawer__panel {
	transform: translateX(0);
}

@media (prefers-reduced-motion: reduce) {
	.vri-cart .vri-ec-drawer__panel,
	.vri-cart .vri-ec-drawer__backdrop {
		transition: none;
	}
}

.vri-cart .vri-ec-drawer__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	padding: 18px 20px;
	background-color: var(--vri-ec-black);
}

.vri-cart .vri-ec-drawer__title {
	margin: 0;
	color: var(--vri-ec-white);
	font-family: var(--vri-ec-font);
	font-size: calc(var(--vri-ec-base) * 0.95);
	font-weight: var(--vri-ec-weight);
	letter-spacing: var(--vri-ec-track);
	text-transform: var(--vri-ec-caps);
}

.vri-cart .vri-ec-drawer__count {
	color: var(--vri-ec-blue);
}

.vri-cart .vri-ec-drawer .vri-ec-drawer__close {
	appearance: none;
	width: 32px;
	height: 32px;
	padding: 0;
	border: 0;
	background-color: transparent;
	color: var(--vri-ec-white);
	font-size: calc(var(--vri-ec-base) * 1.4);
	line-height: 1;
	cursor: pointer;
}

.vri-cart .vri-ec-drawer .vri-ec-drawer__close:hover {
	color: var(--vri-ec-blue);
}

.vri-cart .vri-ec-drawer__body {
	flex: 1 1 auto;
	overflow-y: auto;
	padding: 4px 20px 20px;
}

.vri-cart .vri-ec-drawer__foot {
	flex: 0 0 auto;
	padding: 16px 20px;
	border-top: 1px solid var(--vri-ec-line);
}

.vri-cart .vri-ec-drawer__cta {
	display: block;
	padding: 15px 20px;
	background-color: var(--vri-ec-blue);
	color: var(--vri-ec-white);
	font-family: var(--vri-ec-font);
	font-size: calc(var(--vri-ec-base) * 0.85);
	font-weight: var(--vri-ec-weight);
	letter-spacing: var(--vri-ec-track);
	text-align: center;
	text-transform: var(--vri-ec-caps);
	text-decoration: none;
}

/* Aaron: text goes black on hover, the blue background stays put. */
.vri-cart .vri-ec-drawer__cta:hover {
	background-color: var(--vri-ec-blue);
	color: var(--vri-ec-black);
}

/* v3: ALL TEXT BLACK. No grey body copy anywhere in the drawer. The only
   lighter thing permitted is the comment placeholder. */
/* v3.1 defect 3: both were rendering grey because the drawer foot and sort row
   sit outside .vri-ec-line, so the theme's own colour reached them first. Typed
   explicitly and lifted 0.8 -> 0.875 of Accent. */
.vri-cart .vri-ec-drawer .vri-ec-drawer__attachnote,
.vri-cart .vri-ec-drawer .vri-ec-sort__label {
	color: var(--vri-ec-black);
	font-family: var(--vri-ec-font);
	font-size: calc(var(--vri-ec-base) * 0.875);
	font-weight: 500;
	line-height: 1.5;
}

.vri-cart .vri-ec-drawer__attachnote {
	margin: 10px 0 0;
	text-align: center;
}

/* --- sort control, shown only once the cart is big enough to need it ----- */
.vri-cart .vri-ec-sort {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 12px 0 4px;
}

.vri-cart .vri-ec-drawer .vri-ec-sort select.vri-ec-sort__select {
	flex: 0 1 auto;
	padding: 6px 8px;
	border: 1px solid var(--vri-ec-line);
	border-radius: 0;
	background-color: var(--vri-ec-white);
	color: var(--vri-ec-black);
	font-family: var(--vri-ec-font);
	font-size: calc(var(--vri-ec-base) * 0.8);
}

/* --- drawer lines ------------------------------------------------------- */

.vri-cart .vri-ec-lines {
	margin: 0;
	padding: 0;
	list-style: none;
}

/*
 * v3 layout: image column on the left carries the thumbnail, the stepper
 * underneath it constrained to the image width, and Remove centred beneath
 * that. The right column carries SKU + title on one line, then the comment
 * field on the next.
 */
/*
 * v3.2 fix 3: the row carried an obvious void.
 *
 * The left stack (144px image + stepper + Remove) is taller than the right
 * stack (one line of SKU/title + a fixed-height note), so everything beside the
 * stepper and Remove was empty. Given how tight the rest of the design now is,
 * that read as a hole rather than as breathing room.
 *
 * Fixed by letting the note claim the leftover height instead of trimming the
 * left stack: the note is the one element here that genuinely benefits from
 * being bigger, since it is where a specifier types a customisation request.
 * `align-items: stretch` on the row plus a column body that fills its track is
 * what gives the textarea something to grow into.
 */
/*
 * v3.3 drawer row (Aaron's markup):
 *   left  = smaller image, then a compact [- N +] stepper with a RED X beside it
 *   right = SKU + title, then a comment box sized to the left stack's height
 *
 * The image dropped 144 -> 72, so the panel returns to 460px and the whole row
 * is much tighter. The note fills whatever height the left stack sets, so no
 * dead space opens up - `align-items: stretch` plus the flex body is what makes
 * the textarea grow to match.
 */
.vri-cart .vri-ec-line {
	display: grid;
	grid-template-columns: 104px minmax(0, 1fr);
	align-items: stretch;
	gap: 14px;
	padding: 14px 0;
	border-bottom: 1px solid var(--vri-ec-line);
}

.vri-cart .vri-ec-line__body {
	display: flex;
	flex-direction: column;
	min-height: 0;
}

.vri-cart .vri-ec-line__media {
	width: 104px;
}

/*
 * v3.3 (Aaron): the image width matches the combined width of the stepper + red
 * X row beneath it, and scales square. Both are the full media-column width, so
 * `width: 100%` keeps them locked together if that column is ever retuned. The
 * taller image makes each row taller; the comment box follows automatically
 * because it is `flex: 1` inside a stretched row (see the note rule below).
 */
.vri-cart .vri-ec-line__media img {
	display: block;
	width: 100%;
	aspect-ratio: 1 / 1;
	object-fit: contain;
	background-color: var(--vri-ec-soft);
}

/* The stepper and the red X share one row beneath the image. */
.vri-cart .vri-ec-line__qtyrow {
	display: flex;
	align-items: stretch;
	gap: 4px;
	width: 104px;
	margin-top: 8px;
}

.vri-cart .vri-ec-line__qty {
	display: flex;
	align-items: stretch;
	flex: 1 1 auto;
	min-width: 0;
	background-color: var(--vri-ec-black);
}

.vri-cart .vri-ec-line .vri-ec-line__step {
	appearance: none;
	flex: 0 0 auto;
	/* SESSION-4 Step 0 (A11Y): 22 -> 24px, WCAG 2.5.8 AA minimum target width.
	   The quantity field beside it (flex 1 1 auto) absorbs the 4px. */
	width: 24px;
	min-height: 32px;
	padding: 0;
	border: 0;
	background-color: transparent;
	color: var(--vri-ec-white);
	font-family: var(--vri-ec-font);
	font-size: calc(var(--vri-ec-base) * 0.85);
	font-weight: var(--vri-ec-weight);
	line-height: 1;
	cursor: pointer;
}

.vri-cart .vri-ec-line .vri-ec-line__step:hover {
	color: var(--vri-ec-blue);
}

.vri-cart .vri-ec-drawer .vri-ec-line input.vri-ec-line__num {
	appearance: textfield;
	-moz-appearance: textfield;
	flex: 1 1 auto;
	width: 24px;
	min-width: 0;
	padding: 0;
	border: 0;
	background-color: transparent;
	color: var(--vri-ec-white);
	font-family: var(--vri-ec-font);
	font-size: calc(var(--vri-ec-base) * 0.8);
	font-weight: var(--vri-ec-weight);
	text-align: center;
}

.vri-cart .vri-ec-drawer .vri-ec-line input.vri-ec-line__num::-webkit-outer-spin-button,
.vri-cart .vri-ec-drawer .vri-ec-line input.vri-ec-line__num::-webkit-inner-spin-button {
	-webkit-appearance: none;
	margin: 0;
}

/*
 * The red X replaces the "Remove" text word entirely.
 *
 * NOTE ON THE COLOUR: the Elementor kit has no red token, and Aaron explicitly
 * asked for a RED remove control. So `--vri-ec-danger` is the ONE deliberate
 * literal in this file - there is no global to reference for it. If a red is
 * ever added to the kit, point this variable at it.
 */
.vri-cart .vri-ec-line {
	--vri-ec-danger: #d0021b;
}

.vri-cart .vri-ec-line .vri-ec-line__x {
	appearance: none;
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	/* SESSION-4: 32 -> 28px so the quantity field keeps 24px beside the 24px steppers (row stays 104px). */
	width: 28px;
	min-height: 32px;
	padding: 0;
	border: 1px solid var(--vri-ec-danger);
	border-radius: 0;
	background-color: transparent;
	color: var(--vri-ec-danger);
	font-family: var(--vri-ec-font);
	font-size: calc(var(--vri-ec-base) * 1.1);
	font-weight: var(--vri-ec-weight);
	line-height: 1;
	cursor: pointer;
	transition: background-color 0.2s ease, color 0.2s ease;
}

.vri-cart .vri-ec-line .vri-ec-line__x:hover,
.vri-cart .vri-ec-line .vri-ec-line__x:focus-visible {
	background-color: var(--vri-ec-danger);
	color: var(--vri-ec-white);
}

/* SKU inline and AHEAD of the title, at the same size as the title. */
.vri-cart .vri-ec-line__head {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: 8px;
	margin: 0 0 8px;
}

.vri-cart .vri-ec-line__sku,
.vri-cart .vri-ec-line__title {
	font-family: var(--vri-ec-font);
	font-size: calc(var(--vri-ec-base) * 0.875);
	line-height: 1.3;
}

/*
 * Aaron: the SKU is blue and now LINKS to the product (25 Jul), so its hover has
 * to mean something. text-decoration is forced off by default (the theme
 * underlines every anchor, and the cart underline-audit forbids it at rest); a
 * direct hover on the SKU underlines it and turns it black, which is the "this is
 * clickable" affordance. Row hover alone still turns it black to match the rest
 * of the row.
 */
.vri-cart a.vri-ec-line__sku {
	color: var(--vri-ec-blue-text);
	font-weight: var(--vri-ec-weight);
	letter-spacing: var(--vri-ec-track);
	text-decoration: none;
	transition: color 0.2s ease;
}

.vri-cart .vri-ec-line:hover a.vri-ec-line__sku {
	color: var(--vri-ec-black);
}

.vri-cart a.vri-ec-line__sku:hover,
.vri-cart a.vri-ec-line__sku:focus-visible {
	color: var(--vri-ec-black);
	text-decoration: underline;
}

/*
 * DEFECT 2 (v3.1): the drawer title rendered underlined.
 *
 * ROOT CAUSE, found by scanning every stylesheet as raw text after CSSOM
 * enumeration kept coming up empty: the site's Customizer "Additional CSS"
 * carries `p > a { text-decoration: underline !important }`. The title anchor
 * sat directly inside a <p>, so it matched, and no amount of specificity could
 * beat it - a plain inline style failed too.
 *
 * FIXED IN THE MARKUP, not here: the head element is now a <div>, so `p > a`
 * simply does not match. That site-wide rule is left alone; it is presumably
 * deliberate for body copy, and out-shouting it with another !important would
 * have been the wrong trade.
 *
 * The declaration below is kept as a plain guard so the title stays clean if
 * anyone ever re-wraps it. The hover underline is deliberate - it is a link.
 */
.vri-cart .vri-ec-drawer .vri-ec-line a.vri-ec-line__title {
	color: var(--vri-ec-black);
	font-weight: 600;
	text-decoration: none;
}

/* Aaron: the product NAME stays black. Underline on hover is the only affordance. */
.vri-cart .vri-ec-drawer .vri-ec-line a.vri-ec-line__title:hover {
	color: var(--vri-ec-black);
	text-decoration: underline;
}

/* Comment field to the right of the image, beside the title. */
.vri-cart .vri-ec-drawer .vri-ec-line textarea.vri-ec-line__note {
	display: block;
	box-sizing: border-box;
	width: 100%;
	/* Grows into the height the left stack sets, closing the dead space. */
	flex: 1 1 auto;
	min-height: 62px;
	padding: 8px 10px;
	border: 1px solid var(--vri-ec-line);
	border-radius: 0;
	background-color: var(--vri-ec-white);
	color: var(--vri-ec-black);
	font-family: var(--vri-ec-font);
	/* v3.1: was 0.8 (12.8px), i.e. very slightly SMALLER than v2's 13px. */
	font-size: calc(var(--vri-ec-base) * 0.875);
	font-weight: 500;
	line-height: 1.5;
	resize: vertical;
}

.vri-cart .vri-ec-drawer .vri-ec-line textarea.vri-ec-line__note:focus {
	border-color: var(--vri-ec-blue);
	outline: none;
}

/* The one permitted lighter tone. KIT-3633-TOKENS-001: Charcoal's own kit ID a54595f (8b5c6cd, which
   kit 3633 had listed as both Blue and Charcoal, is Blue alone now); the fallback keeps it charcoal pre-migration. */
.vri-cart .vri-ec-drawer .vri-ec-line textarea.vri-ec-line__note::placeholder {
	color: var(--e-global-color-a54595f, #54595F);
}

.vri-cart .vri-ec-drawer__empty {
	padding: 40px 0;
	text-align: center;
}

.vri-cart .vri-ec-drawer__empty p {
	margin: 0 0 16px;
	color: var(--vri-ec-black);
	font-family: var(--vri-ec-font);
	font-size: calc(var(--vri-ec-base) * 0.9);
}

/* =====================================================================
   7. CATALOGUE BLOCK - placeholder until the assets land
   ===================================================================== */

.vri-cart .vri-ec-cat {
	display: block;
	margin-top: 18px;
}

.vri-cart .vri-ec-cat__img {
	display: block;
	width: 100%;
	aspect-ratio: 3 / 4;
	object-fit: cover;
	background-color: var(--vri-ec-soft);
}

/* Deliberately unattractive: a placeholder that looks finished is a
   placeholder that quietly ships. */
.vri-cart .vri-ec-cat__ph {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	aspect-ratio: 3 / 4;
	padding: 10px;
	box-sizing: border-box;
	background-color: var(--vri-ec-soft);
	background-image: repeating-linear-gradient(45deg, rgba(0, 0, 0, 0.06) 0, rgba(0, 0, 0, 0.06) 10px, transparent 10px, transparent 20px);
	border: 1px dashed var(--e-global-color-a54595f, #54595F);
	color: var(--e-global-color-a54595f, #54595F);
	font-family: var(--vri-ec-font);
	font-size: calc(var(--vri-ec-base) * 0.7);
	font-weight: var(--vri-ec-weight);
	letter-spacing: var(--vri-ec-track);
	line-height: 1.4;
	text-align: center;
	text-transform: var(--vri-ec-caps);
}

.vri-cart .vri-ec-cat__btn {
	display: block;
	box-sizing: border-box;
	width: 100%;
	padding: 12px 14px;
	border: 0;
	background-color: var(--vri-ec-blue);
	color: var(--vri-ec-white);
	font-family: var(--vri-ec-font);
	font-size: calc(var(--vri-ec-base) * 0.75);
	font-weight: var(--vri-ec-weight);
	letter-spacing: var(--vri-ec-track);
	text-align: center;
	text-transform: var(--vri-ec-caps);
	text-decoration: none;
}

.vri-cart .vri-ec-cat__btn:hover {
	background-color: var(--vri-ec-black);
	color: var(--vri-ec-white);
}

/* CART-UX-002: the catalogue download under the drawer's primary CTA is the
   secondary (black) tier, as on /enquiry/ - two stacked blue buttons would
   compete. The empty-state Browse button keeps the blue above. */
.vri-cart .vri-ec-drawer__foot .vri-ec-cat__btn {
	background-color: var(--vri-ec-black);
}
.vri-cart .vri-ec-drawer__foot .vri-ec-cat__btn:hover {
	background-color: var(--vri-ec-blue);
}

/* v3.1 defect 3: was the muted grey. All drawer text is black except the
   comment placeholder. Size lifted 0.65 -> 0.75 of Accent for legibility. */
.vri-cart .vri-ec-cat__pending {
	display: block;
	margin-top: 6px;
	color: var(--vri-ec-black);
	font-family: var(--vri-ec-font);
	font-size: calc(var(--vri-ec-base) * 0.75);
	font-weight: 600;
	letter-spacing: var(--vri-ec-track);
	text-align: center;
	text-transform: var(--vri-ec-caps);
}

.vri-cart .vri-hdr .vri-mega .vri-ec-cat__ph {
	background-color: rgba(255, 255, 255, 0.06);
	border-color: rgba(255, 255, 255, 0.35);
	color: rgba(255, 255, 255, 0.75);
}

.vri-cart .vri-hdr .vri-mega .vri-ec-cat__pending {
	color: rgba(255, 255, 255, 0.6);
}

@media (min-width: 1001px) {
	.vri-cart .vri-hdr .vri-has-mega .vri-mega {
		/* INTEGRATION-QA-PRE-001: was width 660px + a 176px 3rd column (the old catalogue-cover column). MENU-002's 3rd
		   column is text links, so the fixed width spilled the links ~89px outside the black panel. Size to content. */
		width: max-content;
		max-width: calc(100vw - 32px);
		grid-template-columns: repeat(3, auto);
		transform: translateX(var(--vri-mega-shift, 0px));
	}

	.vri-cart .vri-hdr .vri-mega .vri-ec-mega-cat {
		padding-left: 24px;
		border-left: 1px solid rgba(255, 255, 255, 0.15);
	}
}

/* =====================================================================
   8. TOAST - runtime injected, cannot be an Elementor element
   ===================================================================== */

.vri-cart .vri-ec-toast {
	position: fixed;
	right: 20px;
	bottom: 58px;
	z-index: 100001;
	display: flex;
	align-items: center;
	gap: 10px;
	max-width: min(340px, calc(100vw - 40px));
	padding: 14px 18px;
	background-color: var(--vri-ec-black);
	color: var(--vri-ec-white);
	font-family: var(--vri-ec-font);
	font-size: calc(var(--vri-ec-base) * 0.8);
	font-weight: 600;
	line-height: 1.4;
	opacity: 0;
	transform: translateY(12px);
	transition: opacity 0.2s ease, transform 0.2s ease;
	pointer-events: none;
}

.vri-cart .vri-ec-toast.is-visible {
	opacity: 1;
	transform: translateY(0);
	pointer-events: auto;
}

.vri-cart .vri-ec-toast .vri-ec-toast__link {
	appearance: none;
	padding: 0;
	border: 0;
	background: transparent;
	color: var(--vri-ec-blue);
	font-family: var(--vri-ec-font);
	font-size: inherit;
	font-weight: var(--vri-ec-weight);
	text-decoration: underline;
	white-space: nowrap;
	cursor: pointer;
}

@keyframes vri-ec-bump {
	0%   { transform: scale(1); }
	40%  { transform: scale(1.35); }
	100% { transform: scale(1); }
}

.vri-cart .vri-ec-mini__count.is-bumping {
	animation: vri-ec-bump 0.4s ease;
}

@media (prefers-reduced-motion: reduce) {
	.vri-cart .vri-ec-mini__count.is-bumping {
		animation: none;
	}
}

/* =====================================================================
   9. PRODUCT PAGE BLOCK - STRUCTURAL DEFAULTS ONLY
   v3 item 5: Aaron styles this himself in Elementor later. Deliberately NOT
   polished here. Just enough for the controls to be usable and for the
   function (add, quantity, note, two-way sync) to be testable.
   ===================================================================== */

/*
 * Aaron's review (25 Jul): the block matches the download row above it.
 *
 * - Full width: the host container's padding is zeroed in the Elementor data
 *   (container vriecp01), so the block reaches the same left/right edges as the
 *   INFO SHEET / DWG FILE / PNG FILE row - no side padding, same width.
 * - Vertical gaps halved: margin-top 22 -> 11 to the download row, internal
 *   gap 10 -> 5.
 */
.vri-cart .vri-ec-product {
	display: flex;
	flex-direction: column;
	gap: 5px;
	width: 100%;
	margin-top: 11px;
}

/*
 * qty stepper + ADD TO ENQUIRY match the 52px height of the download buttons
 * above (Aaron). align-items: stretch on the row makes the input follow.
 */
.vri-cart .vri-ec-product .vri-ec-actions {
	min-height: 52px;
}

.vri-cart .vri-ec-product .vri-ec-actions .vri-ec-actions__step,
.vri-cart .vri-ec-product .vri-ec-actions__add {
	min-height: 52px;
}

.vri-cart .vri-ec-product .vri-ec-actions__add {
	font-size: var(--vri-ec-base); /* HUB-ALIGN-001: = the INFO SHEET text (16 / 700 / Accent tracking); was 85% */
}

/*
 * Comment field: the typed text is now BODY size (Aaron), matching the site body
 * global. The min-height is a floor only - vri-ec-preview.js grows it on load so
 * the block bottom lines up with the last Product Features bullet in the right
 * column (see autoSizeProductNote). resize:vertical still lets a visitor drag it.
 */
.vri-cart .vri-ec-product .vri-ec-product__field textarea.vri-ec-product__note {
	display: block;
	box-sizing: border-box;
	width: 100%;
	min-height: 96px;
	padding: 10px;
	border: 1px solid var(--vri-ec-line);
	border-radius: 0;
	background-color: var(--vri-ec-white);
	color: var(--vri-ec-black);
	font-family: var(--vri-ec-font);
	font-size: var(--vri-ec-base);
	font-weight: 500;
	line-height: 1.6;
	resize: vertical;
}

.vri-cart .vri-ec-product .vri-ec-product__field textarea.vri-ec-product__note:focus {
	border-color: var(--vri-ec-blue);
	outline: none;
}

/*
 * The general-question link is now BODY size (Aaron), blue reverting to black on
 * hover. It stays a 44px-tall hit target (SOLIDIFY P6: standalone link, so WCAG
 * 2.5.8's block-of-text exemption does not apply) - the height is padding, it
 * does not change how the link reads.
 */
.vri-cart .vri-ec-product__link {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	color: var(--vri-ec-blue-text);
	font-family: var(--vri-ec-font);
	font-size: var(--vri-ec-base);
	text-decoration: underline;
}

.vri-cart .vri-ec-product__link:hover {
	color: var(--vri-ec-black);
}

/* =====================================================================
   9b. MOBILE PRODUCTS TOOLBAR (v-FINAL Phase 3)
   Desktop is GOOD and untouched (this is all inside a max-width query). At
   mobile widths the toolbar's parent (.vri-toolbar) is flex row / nowrap, which
   crushes the "Showing X of Y" counter and the four controls into two ~153px
   columns - search clipped, counter colliding with sort. Rebuild for mobile:
   counter = its own quiet line; search = full-width row; sort + show + toggle =
   one tidy row of 44px targets. Gated under .vri-cart; permanent home is an
   Elementor per-breakpoint setting at Phase 6.
   ===================================================================== */

@media (max-width: 767px) {
	/* Stack the counter block and the controls block, each full width. */
	.vri-cart .vri-toolbar {
		flex-wrap: wrap;
		flex-direction: row;
		row-gap: 12px;
		align-items: stretch;
	}

	/* Quiet counter line above the controls, its own full-width row. */
	.vri-cart .vri-toolbar .vri-toolbar-left {
		order: -1;
		flex: 0 0 100%;
		width: 100%;
		max-width: 100%;
		text-align: left;
	}

	/* Controls block full width; its children lay out as rows below. On the last
	   row (Show + toggle) space-between pins Show left and the toggle right; the
	   full-width search/sort rows are unaffected (a single 100% item has no gap
	   to distribute). */
	.vri-cart .vri-toolbar .vri-toolbar-right {
		flex: 0 0 100%;
		width: 100%;
		max-width: 100%;
		display: flex;
		flex-wrap: wrap;
		align-items: stretch;
		justify-content: space-between;
		gap: 10px;
	}

	/* Search and Sort each take their own full-width row (the two dropdowns are
	   the primary controls and read best full width at ~305px). */
	.vri-cart .vri-toolbar-right .vri-search-widget,
	.vri-cart .vri-toolbar-right .vri-sort-widget {
		flex: 0 0 100%;
		width: 100%;
		max-width: 100%;
		margin: 0;
	}

	/* Show + view toggle - the two compact controls - pair on the last row,
	   left-aligned, with breathing room between them. Three-on-one-row was
	   rejected: at ~305px content width it leaves each control sub-100px with no
	   spacing, which fails the spec's own "consistent spacing" rule (D3.1). */
	.vri-cart .vri-toolbar-right .vri-per-page-wrap {
		flex: 0 1 auto;
		width: auto;
		max-width: none;
		margin: 0;
	}

	.vri-cart .vri-toolbar-right .vri-view-toggle-wrap {
		flex: 0 0 auto;
		width: auto;
		max-width: none;
		margin: 0;
	}

	/* 44px touch minimum on the two controls that render short (36px). */
	.vri-cart .vri-toolbar-right .jet-search-filter__input,
	.vri-cart .vri-toolbar-right .jet-sorting-select,
	.vri-cart .vri-toolbar-right .vri-per-page-select {
		min-height: 44px;
		box-sizing: border-box;
	}

	/* Search and Sort controls fill their full-width widgets so the two rows read
	   as one consistent block (the sort select otherwise renders narrow/centred). */
	.vri-cart .vri-toolbar-right .vri-search-widget .jet-search-filter__input,
	.vri-cart .vri-toolbar-right .vri-sort-widget .jet-sorting-select {
		width: 100%;
		max-width: 100%;
	}
}

/* =====================================================================
   PRODUCTS-POLISH-001 7 (SESSION-4b, target sheet panel 7): the shared grid
   card (listing 1301, every grid on the site) reads image -> SKU -> name ->
   buttons with tight spacing. The SKU sits above the name in the template
   itself (1301); here only the gaps: image -> SKU 8px (was 20), SKU -> name
   2px (was 20), name -> buttons at least 10px (was 20; the button row still
   drops to a common baseline across a grid row via margin-top:auto).
   The column's own 20px widget spacing prints at (0,4,0), hence !important.
   ===================================================================== */
/* keyed on the listing item: the card's own `vri-card` class is a section _css_classes and never renders */
.vri-cart .jet-listing-grid__item .elementor-widget.vri-card-image { margin-bottom: 8px !important; }
.vri-cart .jet-listing-grid__item .elementor-widget.vri-card-sku { margin-bottom: 2px !important; }
.vri-cart .jet-listing-grid__item .elementor-widget.vri-card-title { margin-bottom: 10px !important; }

/* =====================================================================
   11. HUB-ALIGN-001 - THE TWO DEFINITIVE CARDS (Aaron, 16 Oct 2026)
   Product card (listing 1301) and project card (listing 1586) share ONE
   bounding box so they read as a pair side by side (JetSearch results, hubs):
   - the card column is explicitly the smaller of 300px and its grid cell
     (it was already 300px, but only as a side effect of the 300px "medium"
     image shrink-wrapping the column);
   - the image frame is square, cover, full column width;
   - product: SKU line (Accent line height) + 2px + the name, which always
     reserves two lines; project: its title sits at the SKU line and reserves
     the same block (SKU line + 2px + two title lines), three lines at most;
   - then 10px and the 44px control bar / VIEW PROJECT button.
   Result: identical width and height for every product and project card.
   ===================================================================== */
.vri-cart .jet-listing-grid__item .elementor-1301 > .elementor-section > .elementor-container,
.vri-cart .jet-listing-grid__item .elementor-1586 > .elementor-section > .elementor-container {
	width: 100%;
	max-width: 300px;
}

/* Product art: vri-filtering-ux.css keeps object-fit: contain !important on .vri-card-image (square originals, the
   whole product shows - identical to cover on square art). Project photos are landscape, so they carry their own
   class (vri-pcard-image) and are cropped to the square. */
.vri-cart .jet-listing-grid__item .elementor-widget.vri-card-image img,
.vri-cart .jet-listing-grid__item .elementor-widget.vri-pcard-image img {
	width: 100%;
	height: auto;
	aspect-ratio: 1 / 1;
	object-fit: cover;
}

.vri-cart .jet-listing-grid__item .elementor-widget.vri-card-title .elementor-heading-title {
	min-height: 2.6em; /* two lines of the card title global (line height 1.3em) */
}

.vri-cart .jet-listing-grid__item .elementor-widget.vri-pcard-image { margin-bottom: 8px !important; } /* = the product card's image -> SKU gap */
.vri-cart .jet-listing-grid__item .elementor-widget.vri-pcard-title { margin-bottom: 10px !important; }

.vri-cart .jet-listing-grid__item .elementor-widget.vri-pcard-title .elementor-heading-title {
	/* = the product card's SKU line (Accent size x 1.5) + its 2px gap + two title lines */
	min-height: calc(var(--vri-ec-base) * 1.5 + 2px + 2.6em);
	display: -webkit-box;
	-webkit-line-clamp: 3;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* Narrow cards only (the 2- and 3-column grids beside the /products/ sidebar
   at 768px and 1025-1199px leave the ADD TO ENQUIRY cell 76-83px wide): the
   controls step down so "ENQUIRY" still fits. Everywhere the bar is 245px or
   wider (every grid at 1200px+, every carousel, every phone card) they stay
   at the full INFO SHEET size. Scoped to the grid card (1301): in the list row (3982) the bar is sized by its content,
   and a size container there collapses it to 0px. */
.vri-cart .elementor-1301 .vri-card-actions .vri-ec-actions {
	container-type: inline-size;
	container-name: vri-ec-card;
}

@container vri-ec-card (max-width: 244px) {
	.vri-cart .vri-ec-actions .vri-ec-actions__add,
	.vri-cart .vri-ec-actions .vri-ec-actions__view,
	.vri-cart .vri-ec-actions .vri-ec-actions__step,
	.vri-cart .vri-ec-actions .vri-ec-actions__qty input.vri-ec-actions__num {
		font-size: calc(var(--vri-ec-base) * 0.75);
		letter-spacing: 1px;
	}

	.vri-cart .vri-ec-actions .vri-ec-actions__view {
		flex-basis: 56px; /* VIEW at 12px is 36px wide; the 16px goes to ADD TO ENQUIRY */
	}

	.vri-cart .vri-ec-actions .vri-ec-actions__add {
		padding: 0 4px; /* the 1025px grid's 75px cell: ENQUIRY at 12px needs 66px */
	}
}


/* HUB-ALIGN-001: the project card's VIEW PROJECT button is exactly the 44px control bar of the product card
   (Elementor's inline-block .elementor-button rendered the 44px line-height as a 24px box). */
.vri-cart .jet-listing-grid__item .elementor-widget.vri-pcard-btn .elementor-button {
	display: flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	width: 100%;
	min-height: var(--vri-ec-control);
	padding: 0;
	line-height: 1.2;
}

/* EDITOR-CLEAN-001 item 12 (D-036, Aaron 16 Oct 2026): ONE even white perimeter. The card's top section (white on the
   project card 1586) spanned the whole grid cell with the 300px column centred in it, so the image sat flush at the top,
   VIEW PROJECT flush at the bottom and the sides took whatever the cell left over (26-37px). Now the section hugs its
   content: one padding on all four sides (15px, the grid cells' own perimeter) and at most 300px + 2 x 15px wide, centred.
   The padding is clamped by the room the cell has beyond the 300px column (a % padding reads the cell's width), so a
   narrow cell (the /products/ grid, JetSearch results at 1200-1516px) keeps its full content width at 0px rather than
   shrinking the art. Applied to the product card (1301) too, so the two bounding boxes stay identical. */
.vri-cart .jet-listing-grid__item .elementor-1301 > .elementor-section,
.vri-cart .jet-listing-grid__item .elementor-1586 > .elementor-section {
	box-sizing: border-box;
	width: 100%;
	max-width: calc(300px + 2 * 15px);
	margin-left: auto;
	margin-right: auto;
	padding: clamp(0px, calc((100% - 300px) / 2), 15px);
}

/* HUB-ALIGN-001: a listing carousel whose cards all fit in view (Swiper "locked") shows no arrows - Swiper flags them
   swiper-button-lock but the site never hid that class, so a 2-card Related projects row kept two dead arrows. */
.vri-cart .jet-listing-grid__slider-icon.swiper-button-lock {
	display: none;
}

/* HUB-ALIGN-001: list view, desktop rail (1240px+). The rule is "the enquiry controls match the download labels beside
   them": in this rail those labels are 11px / 700 / 1px (the fixed 520px rail holds the 300px download row too), so the
   controls take that size here; at 16px "ENQUIRY" needed 92px in an 85px cell. Stacked rows below 1240px keep 16px. */
@media (min-width: 1240px) {
	.vri-cart .vri-ec-listrail .vri-ec-actions .vri-ec-actions__add,
	.vri-cart .vri-ec-listrail .vri-ec-actions .vri-ec-actions__view,
	.vri-cart .vri-ec-listrail .vri-ec-actions .vri-ec-actions__step,
	.vri-cart .vri-ec-listrail .vri-ec-actions .vri-ec-actions__qty input.vri-ec-actions__num {
		font-size: 11px;
		letter-spacing: 1px;
	}

	.vri-cart .vri-ec-listrail .vri-ec-actions .vri-ec-actions__add {
		min-width: max-content; /* never shrink under its own label (it lost 1px to flex shrink) */
	}
}
