/**
 * Sample Finder behavioural CSS.
 *
 * sample-finder.css is the design export's compiled Tailwind build and is
 * regenerated wholesale, so anything hand-written lives here. This file only
 * supplies the interaction affordances the reference got from Radix at runtime:
 * popover open/closed state for the native <details> pills, the view tooltip,
 * and the frozen-column stacking the table relies on.
 */

/* --- Page chrome --------------------------------------------------------- */

/*
 * Sample Finder must never hide the design-system header. Catalog CSS in the
 * classic archive targeted Beaver chrome only; keep an explicit exception here
 * so a future global header rule cannot collapse `.sb-site-header`.
 */
body.sb-sf-page header.sb-site-header,
body.single-product header.sb-site-header {
	display: block;
}

/*
 * sample-finder.css must not set :root tokens/font-family. Those leaked onto
 * the FAQ tab (and Overview) on product/master pages. Tokens live on `.sb-sf`.
 */

/*
 * Beaver Builder's theme outputs a "Skip to content" link and hides it via its
 * own skin stylesheet, which this page deliberately does not load. Restore the
 * visually-hidden treatment here so the link stays available to screen readers
 * and assistive tech without printing at the top of the page.
 *
 * Scoped to the catalog body class so no other route is affected.
 */
body.sb-sf-page .fl-screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

/* Keep it reachable: reveal on keyboard focus. */
body.sb-sf-page .fl-screen-reader-text:focus {
	position: static !important;
	width: auto;
	height: auto;
	margin: 0;
	overflow: visible;
	clip: auto;
	white-space: normal;
	padding: 8px 16px;
	background: #fff;
	color: #14204a;
	z-index: 100000;
}

/* --- Host-theme utility collision ----------------------------------------- */

/*
 * bb-theme's base.min.css (a Bootstrap-era base) ships:
 *
 *     .hidden { display: none !important }
 *
 * Tailwind's responsive display utilities are written as `hidden md:grid`, which
 * relies on `md:grid` overriding `hidden` by source order. The parent theme's
 * !important outranks any non-important rule regardless of specificity, so the
 * element stays hidden at every breakpoint -- this silently removed the table's
 * sortable header row and the toolbar divider.
 *
 * Auditing every bare `!important` class in the loaded host stylesheets against
 * the classes used in this page found exactly one such collision (`.hidden`).
 * These overrides restore the intended behaviour without touching the parent
 * theme, and are confined to `.sb-sf`.
 */
@media (min-width: 640px) {
	.sb-sf .sm\:block { display: block !important; }
	.sb-sf .sm\:flex { display: flex !important; }
	.sb-sf .sm\:grid { display: grid !important; }
	.sb-sf .sm\:inline { display: inline !important; }
	.sb-sf .sm\:inline-block { display: inline-block !important; }
	.sb-sf .sm\:inline-flex { display: inline-flex !important; }
	.sb-sf .sm\:hidden { display: none !important; }
}

@media (min-width: 768px) {
	.sb-sf .md\:block { display: block !important; }
	.sb-sf .md\:flex { display: flex !important; }
	.sb-sf .md\:grid { display: grid !important; }
	.sb-sf .md\:inline { display: inline !important; }
	.sb-sf .md\:inline-block { display: inline-block !important; }
	.sb-sf .md\:inline-flex { display: inline-flex !important; }
	.sb-sf .md\:table-cell { display: table-cell !important; }
	.sb-sf .md\:hidden { display: none !important; }
}

@media (min-width: 1024px) {
	.sb-sf .lg\:block { display: block !important; }
	.sb-sf .lg\:flex { display: flex !important; }
	.sb-sf .lg\:grid { display: grid !important; }
	.sb-sf .lg\:inline-flex { display: inline-flex !important; }
	.sb-sf .lg\:hidden { display: none !important; }
}

@media (min-width: 1280px) {
	.sb-sf .xl\:block { display: block !important; }
	.sb-sf .xl\:flex { display: flex !important; }
	.sb-sf .xl\:grid { display: grid !important; }
	.sb-sf .xl\:hidden { display: none !important; }
}

/* --- Filter pills (native <details> popovers) ------------------------------ */

.sb-sf details.sb-sf-pill > summary {
	cursor: pointer;
	list-style: none;
	min-height: 36px;
	padding: 8px 12px;
	font-size: 13px;
	line-height: 18px;
	font-weight: 500;
	color: #334155;
	background: #fff;
	border: 1px solid #dbdfe6;
	border-radius: 8px;
	box-shadow: none;
	box-sizing: border-box;
}

/* -------------------------------------------------------------------------
 * Filter-pill selected states
 *
 * AC1 wants a selected value to read as selected. The base rule above sets
 * `background:#fff; border:1px solid #dbdfe6` at (0,2,2), which out-ranks the
 * `border-primary/60` / `bg-primary/5` utilities at (0,2,0) -- so an included
 * pill measured border rgb(219,223,230) on rgba(0,0,0,0), pixel-identical to an
 * untouched one, even with the classes on the element.
 *
 * These sit at (0,3,2) and win. They belong in THIS sheet, not
 * sample-finder-catalog.css: that one is dequeued on the Sample Finder view,
 * which is where the pills live.
 * ---------------------------------------------------------------------- */

.sb-sf details.sb-sf-pill > summary.border-primary\/60 {
	/*
	 * `!important`, and not for convenience: the base rule in
	 * sample-finder-catalog.css sets `border: 1px solid #dbdfe6 !important`,
	 * and an important declaration beats specificity outright -- which is why
	 * this rule was present in the served sheet, matched the element, and still
	 * lost. Measured before: border rgb(219,223,230) on every state alike.
	 */
	border-color: rgba(7, 3, 140, 0.6) !important;
	background: rgba(7, 3, 140, 0.05) !important;
}

.sb-sf details.sb-sf-pill > summary.border-destructive\/60 {
	/* The design token's value, written literally: --destructive is 4 78% 51%,
	   which resolves to rgb(228,46,33). #dc2626 (Tailwind red-600) was 8/8/5
	   per channel off. Literal rather than hsl(var(--destructive)) because the
	   token is defined on .sb-sf, not :root, and a var() that fails to resolve
	   drops the whole declaration -- which would lose the tone entirely. */
	border-color: rgba(228, 46, 33, 0.6) !important;
	background: rgba(228, 46, 33, 0.1) !important;
}

/*
 * `.sb-sf details.sb-sf-pill[open] > summary{border-color:#cbd5e1 !important}`
 * and `:hover` are both (0,3,2) and both important, exactly like the two rules
 * above -- so a selected pill lost its tone the moment it was opened or hovered.
 * (0,4,2) settles it in both directions without touching the base file.
 */
.sb-sf details.sb-sf-pill[open] > summary.border-primary\/60,
.sb-sf details.sb-sf-pill > summary.border-primary\/60:hover {
	border-color: rgba(7, 3, 140, 0.6) !important;
}

.sb-sf details.sb-sf-pill[open] > summary.border-destructive\/60,
.sb-sf details.sb-sf-pill > summary.border-destructive\/60:hover {
	/* The design token's value, written literally: --destructive is 4 78% 51%,
	   which resolves to rgb(228,46,33). #dc2626 (Tailwind red-600) was 8/8/5
	   per channel off. Literal rather than hsl(var(--destructive)) because the
	   token is defined on .sb-sf, not :root, and a var() that fails to resolve
	   drops the whole declaration -- which would lose the tone entirely. */
	border-color: rgba(228, 46, 33, 0.6) !important;
}

/* The count badge is what tells include from exclude, so it must not be one
   colour for both: navy when including, destructive when excluding. */
.sb-sf details.sb-sf-pill > summary.border-primary\/60 span[class*="rounded-full"] {
	background: #07038c !important;
}

.sb-sf details.sb-sf-pill > summary.border-destructive\/60 span[class*="rounded-full"] {
	background: rgb(228, 46, 33) !important;
}

.sb-sf details.sb-sf-pill > summary::-webkit-details-marker,
.sb-sf details.sb-sf-pill > summary::marker {
	display: none;
	content: "";
}

.sb-sf details.sb-sf-pill > summary:focus-visible {
	outline: 2px solid hsl(var(--ring));
	outline-offset: 2px;
}

/* Rotate the chevron while open, matching the reference's data-state styling. */
.sb-sf details.sb-sf-pill[open] > summary .lucide-chevron-down {
	transform: rotate(180deg);
}

.sb-sf details.sb-sf-pill > summary .lucide-chevron-down {
	transition: transform 150ms ease;
}

/* Nested locus lists inside the HLA pill. */
.sb-sf .sb-sf-pill__panel details > summary {
	cursor: pointer;
	list-style: none;
}

.sb-sf .sb-sf-pill__panel details > summary::-webkit-details-marker,
.sb-sf .sb-sf-pill__panel details > summary::marker {
	display: none;
	content: "";
}

/* --- View toggle tooltip: visuals live in sample-finder-catalog.css ------ */

/* --- In-Stock table ------------------------------------------------------- */

/*
 * The table itself carries `border-separate border-spacing-0` from the design
 * export -- required, because border-collapse drops the borders on sticky
 * cells -- so no override is needed here.
 *
 * Draggable top scrollbar.
 */
.sb-sf [data-sb-sf-topscroll] {
	user-select: none;
}

.sb-sf [data-sb-sf-topscroll-thumb] {
	min-width: 40px;
	cursor: grab;
}

.sb-sf [data-sb-sf-topscroll-thumb]:active {
	cursor: grabbing;
}

/* Hide the native horizontal scrollbar; the custom strips replace it. */
.sb-sf [data-sb-sf-scroller] {
	scrollbar-width: none;
}

/* --- Filter bar layout --------------------------------------------------- */

.sb-sf .sb-sf-card {
	overflow: visible;
}

.sb-sf .sb-sf-card > [data-sb-sf-stage] {
	overflow: hidden;
	border-radius: 0 0 8px 8px;
}

.sb-sf details.sb-sf-pill[open] {
	z-index: 60;
}

.sb-sf .sb-sf-filter-bar {
	/* The design's chip container opens 6px below the card edge, not 12px. */
	padding: 6px 10px 8px;
}

/* ── All Products: inline row (pills + Clear all + count) ── */

.sb-sf .sb-sf-filter-bar__inline {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
}

.sb-sf .sb-sf-filter-bar__inline .sb-sf-pill {
	position: relative;
	flex: 0 0 auto;
}

.sb-sf .sb-sf-filter-bar__count {
	margin-left: auto;
	font-size: 13px;
	font-weight: 500;
	color: #647690;
	white-space: nowrap;
}

/* ── In Stock: dense grid ── */

.sb-sf .sb-sf-filter-bar__grid {
	/*
	 * The design lays these filters out as an auto-width wrapping row -- each
	 * pill is exactly as wide as its label. An equal-width grid forced every
	 * pill to the same ~137px, which truncated the longer labels
	 * ("Country of Collectior", "Recreational Drug Us").
	 */
	display: flex;
	flex-wrap: wrap;
	/* Design: 6px between rows, 8px between pills -- a 32px row step. */
	gap: 6px 8px;
	align-items: center;
}



.sb-sf .sb-sf-filter-bar__grid .sb-sf-pill {
	min-width: 0;
	width: auto;
	flex: 0 0 auto;
	position: relative;
}

.sb-sf .sb-sf-filter-bar__grid .sb-sf-pill > summary,
.sb-sf .sb-sf-filter-bar__inline .sb-sf-pill > summary {
	width: 100%;
	box-sizing: border-box;
	justify-content: space-between;
	min-height: 26px;
	padding: 4px 10px;
	font-size: 12px;
	line-height: 16px;
	/*
	 * The design's filter control is lighter than the base pill: regular
	 * weight, a 6px corner, a hairline at 60% and no fill. At 500 on solid
	 * white with an 8px corner the row read noticeably heavier than the mock.
	 */
	font-weight: 400;
	color: rgba(20, 29, 46, 0.8);
	background: transparent;
	border-color: rgba(219, 223, 230, 0.6);
	border-radius: 6px;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.sb-sf .sb-sf-toolbar-meta {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 8px;
	/* Design: px-2.5 pb-1.5 pt-0.5. Round four put these values on
	   .sb-sf-panel-foot by mistake -- the wrong one of the two bars. */
	padding: 2px 10px 6px;
}

.sb-sf .sb-sf-toolbar-meta .sb-sf-clear {
	margin-right: auto;
}

.sb-sf .sb-sf-clear {
	flex: 0 0 auto;
	height: 34px;
	padding: 0 8px;
	border: 0;
	background: transparent;
	color: #647690;
	font-size: 13px;
	line-height: 18px;
	text-decoration: underline;
	cursor: pointer;
	white-space: nowrap;
}

.sb-sf .sb-sf-clear:hover {
	color: #141d2e;
}

/* --- Filter dropdowns: fixed height + scroll, no Apply ------------------ */

.sb-sf .sb-sf-pill__panel {
	position: absolute;
	left: 0;
	top: 100%;
	z-index: 50;
	margin-top: 4px;
	width: 260px;
	max-width: calc(100vw - 24px);
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	padding: 8px;
	border: 1px solid #dbdfe6;
	border-radius: 8px;
	background: #fff;
	box-shadow: 0 8px 24px rgba(20,29,46, 0.12);
}

.sb-sf .sb-sf-pill__panel.is-flip {
	left: auto;
	right: 0;
}

.sb-sf .sb-sf-pill__panel--hla {
	width: 280px;
}

.sb-sf .sb-sf-pill__search {
	flex: 0 0 auto;
	box-sizing: border-box;
	width: 100%;
	height: 32px;
	margin: 0 0 8px;
	padding: 0 8px;
	border: 1px solid #dbdfe6;
	border-radius: 6px;
	background: #f8f5f2;
	font-size: 12px;
	line-height: 16px;
	color: #141d2e;
}

.sb-sf .sb-sf-pill__mode {
	display: flex;
	gap: 4px;
	margin: 0 0 8px;
	padding: 3px;
	border: 1px solid #dbdfe6;
	border-radius: 6px;
	background: #f8fafc;
}

.sb-sf .sb-sf-pill__mode-btn {
	flex: 1 1 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 4px;
	height: 26px;
	padding: 0 6px;
	border: 0;
	border-radius: 4px;
	background: transparent;
	color: #647690;
	font-size: 10px;
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	cursor: pointer;
}

.sb-sf .sb-sf-pill__mode-btn.is-on {
	background: #fff;
	color: #141d2e;
	box-shadow: 0 1px 2px rgba(20,29,46, 0.08);
}

.sb-sf .sb-sf-pill__mode-btn.is-on.is-exclude {
	background: rgb(228, 46, 33);
	color: #fff;
}

.sb-sf .sb-sf-pill__option.is-excluded {
	color: rgb(228, 46, 33);
}

.sb-sf .sb-sf-pill__list {
	flex: 1 1 auto;
	max-height: 220px;
	overflow-x: hidden;
	overflow-y: auto;
	overscroll-behavior: contain;
	-webkit-overflow-scrolling: touch;
	scrollbar-width: thin;
}

.sb-sf .sb-sf-pill__list--hla {
	max-height: 260px;
}

.sb-sf .sb-sf-pill__empty {
	margin: 0;
	padding: 8px 4px;
	font-size: 12px;
	line-height: 18px;
	color: #647690;
}

.sb-sf .sb-sf-pill__option {
	display: flex;
	align-items: flex-start;
	gap: 8px;
	padding: 6px 4px;
	border-radius: 4px;
	font-size: 12px;
	line-height: 16px;
	font-weight: 600;
	color: #141d2e;
	cursor: pointer;
}

.sb-sf .sb-sf-pill__option:hover {
	/* v3 `--card: 0 0% 100%`; the beige predates the token set. */
	background: #ffffff;
}

.sb-sf .sb-sf-pill__option input {
	flex: 0 0 auto;
	width: 14px;
	height: 14px;
	margin-top: 1px;
}

.sb-sf .sb-sf-pill__option span {
	min-width: 0;
	flex: 1 1 auto;
	overflow-wrap: anywhere;
}

.sb-sf .sb-sf-pill__count {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 16px;
	height: 16px;
	padding: 0 4px;
	border-radius: 999px;
	background: #eb743d;
	color: #fff;
	font-size: 11px;
	font-weight: 600;
}

.sb-sf .sb-sf-hla-locus {
	border-bottom: 1px solid #dbdfe6;
}

.sb-sf .sb-sf-hla-locus:last-child {
	border-bottom: 0;
}

.sb-sf .sb-sf-hla-locus > summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 8px 4px;
	font-size: 12px;
	font-weight: 600;
}

.sb-sf .sb-sf-hla-locus__body .sb-sf-pill__list {
	max-height: 180px;
}

/* --- In-Stock table: viewport height + frozen price column --------------- */

.sb-sf .sb-sf-instock {
	position: relative;
	display: flex;
	flex-direction: column;
	height: calc(100vh - 210px);
	min-height: 360px;
	scroll-margin-top: 88px;
}

.sb-sf [data-sb-sf-panel] {
	scroll-margin-top: 88px;
}

.sb-sf .sb-sf-hscroll {
	display: none;
	align-items: center;
	box-sizing: border-box;
	height: 6px;
	padding: 1px 8px;
	border: 0;
	background: transparent;
	cursor: pointer;
	z-index: 34;
}

.sb-sf .sb-sf-hscroll[data-sb-sf-topscroll] {
	position: absolute;
	left: 0;
	right: 0;
	/*
	 * BRIAN 14 SEP, third pass: BELOW the header, in a band of its own, styled
	 * like a conventional scrollbar.
	 *
	 * First attempt sat at exactly `--sb-sf-thead-h`, which is the TOP of the
	 * first body row -- the 6px bar spanned 429-435 while the row started at
	 * 429, so it lay over the row and crowded the Add to Cart button. Second
	 * attempt pulled it onto the header's bottom edge: no overlap, but no room
	 * of its own either.
	 *
	 * The band comes from the `tbody::before` spacer row further down. An
	 * absolutely positioned bar occupies no space, so no amount of adjusting
	 * `top` can create any -- something in normal flow has to make the gap.
	 */
	top: var(--sb-sf-thead-h, 36px);
	height: 12px;
	padding: 3px 8px;
	background: #edeff2;
	border-bottom: 1px solid rgba(219, 223, 230, 0.9);
}

.sb-sf .sb-sf-hscroll--bottom {
	flex: 0 0 auto;
	height: 6px;
	padding: 1px 8px;
	border-top: 1px solid rgba(219,223,230, 0.45);
}

.sb-sf .sb-sf-hscroll__thumb {
	height: 3px;
	min-width: 32px;
	border-radius: 999px;
	background: rgba(148, 163, 184, 0.32);
	transform: translateX(0);
	will-change: transform;
	cursor: grab;
	transition: background 120ms ease, height 120ms ease;
}

.sb-sf .sb-sf-hscroll--bottom .sb-sf-hscroll__thumb {
	height: 3px;
}

.sb-sf .sb-sf-hscroll__thumb:hover,
.sb-sf .sb-sf-hscroll__thumb:active {
	background: rgba(100,118,144, 0.7);
	cursor: grabbing;
}

.sb-sf .sb-sf-hscroll[data-sb-sf-topscroll] .sb-sf-hscroll__thumb {
	background: hsl(0 0% 100% / 0.45);
}

.sb-sf .sb-sf-hscroll[data-sb-sf-topscroll] .sb-sf-hscroll__thumb:hover,
.sb-sf .sb-sf-hscroll[data-sb-sf-topscroll] .sb-sf-hscroll__thumb:active {
	height: 4px;
	background: hsl(0 0% 100% / 0.68);
}

.sb-sf .sb-sf-scroller {
	flex: 1 1 auto;
	min-height: 0;
	overflow-x: auto;
	overflow-y: auto;
	max-height: none;
	scrollbar-width: none;
	scrollbar-color: rgba(148, 163, 184, 0.4) transparent;
}

.sb-sf .sb-sf-scroller::-webkit-scrollbar {
	width: 6px;
	height: 0;
}

.sb-sf .sb-sf-scroller::-webkit-scrollbar:horizontal {
	height: 0;
	display: none;
}

.sb-sf .sb-sf-scroller::-webkit-scrollbar-thumb {
	background: rgba(148, 163, 184, 0.4);
	border-radius: 999px;
}

.sb-sf .sb-sf-scroller::-webkit-scrollbar-thumb:hover {
	background: rgba(100,118,144, 0.65);
}

.sb-sf .sb-sf-scroller::-webkit-scrollbar:vertical {
	width: 6px;
}

.sb-sf [data-sb-sf-instock] thead th {
	position: sticky;
	top: 0;
}

.sb-sf .sb-sf-lot-condition,
.sb-sf [data-sb-sf-instock] .sb-sf-lot-condition,
.sb-sf [data-sb-sf-instock] td a .sb-sf-lot-condition {
	font-size: 14px !important;
	/*
	 * The design sets this line in the heading face at 14/20, and its rows are
	 * a uniform 49px. Real condition names are longer than the mock's, so the
	 * name is clipped rather than allowed to wrap the row taller -- the full
	 * text stays in the link's title.
	 */
	line-height: 20px !important;
	font-weight: 700;
	font-family: Inter, system-ui, sans-serif;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.sb-sf .sb-sf-freeze {
	background-clip: padding-box;
}

.sb-sf [data-sb-sf-instock] thead th.sb-sf-freeze--left,
.sb-sf [data-sb-sf-instock] thead th.sb-sf-freeze--lot {
	background-color: hsl(var(--brand-navy)) !important;
}

.sb-sf [data-sb-sf-instock] tbody td.sb-sf-freeze--left,
.sb-sf [data-sb-sf-instock] tbody td.sb-sf-freeze--lot {
	background-color: #fff !important;
}

.sb-sf [data-sb-sf-instock] tr.group:hover td.sb-sf-freeze--left,
.sb-sf [data-sb-sf-instock] tr.group:hover td.sb-sf-freeze--lot {
	background-color: #f8fafc !important;
}

/*
 * Opaque left wall (no blur) hides cells sliding under Price/Action
 * without making the frozen pane look like a floating card.
 */
.sb-sf [data-sb-sf-instock] thead th.sb-sf-freeze--right {
	z-index: 40 !important;
	background-color: hsl(var(--brand-navy)) !important;
	border-left: 1px solid hsl(0 0% 100% / 0.2) !important;
	box-shadow: -14px 0 0 0 hsl(var(--brand-navy));
}

.sb-sf [data-sb-sf-instock] tbody td.sb-sf-freeze--right {
	z-index: 30 !important;
	background-color: #fff !important;
	border-left: 1px solid #dbdfe6 !important;
	box-shadow: -14px 0 0 0 #fff;
}

.sb-sf [data-sb-sf-instock] tr.group:hover td.sb-sf-freeze--right {
	background-color: #f8fafc !important;
	box-shadow: -14px 0 0 0 #f8fafc;
}

.sb-sf .sb-sf-atc-btn,
.sb-sf .sb-sf-quote-btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	width: 110px;
	min-width: 110px;
	height: 28px;
	padding: 0 8px;
	border-radius: 4px;
	font-size: 12px;
	font-weight: 600;
	line-height: 1;
	white-space: nowrap;
	cursor: pointer;
	transition: background 120ms ease, color 120ms ease;
}

.sb-sf .sb-sf-atc-btn {
	border: 0;
	background: #eb743d;
	color: #fff;
}

.sb-sf .sb-sf-atc-btn:hover {
	/*
	 * `hover:bg-accent/90` -- the ACCENT token at 90% alpha, not a darkened
	 * variant of it (critic 8, F2). Two different darkenings had been invented:
	 * #d56a28 here, which the PDP used, and #d9652f in the catalog-only sheet,
	 * which the catalog used -- so the same button hovered two different colours
	 * depending on which page it was rendered on.
	 */
	background: rgba(235, 116, 61, 0.9);
}

.sb-sf .sb-sf-quote-btn {
	border: 1px solid #eb743d;
	background: transparent;
	color: #eb743d;
}

.sb-sf .sb-sf-quote-btn:hover {
	background: #eb743d;
	color: #fff;
}

/* --- Quote modal (catalog CSS is dequeued on Sample Finder) -------------- */

#quote-popup.sb-quote-hubspot-shell {
	position: fixed !important;
	inset: 0;
	display: none;
	align-items: center;
	justify-content: center;
	z-index: 999999 !important;
	padding: 16px;
	box-sizing: border-box;
}

#quote-popup.sb-quote-hubspot-shell.sb-modal-open {
	display: flex !important;
}

#quote-popup .sb-quote-hubspot-shell__backdrop {
	position: absolute !important;
	inset: 0;
	border: 0 !important;
	padding: 0 !important;
	margin: 0 !important;
	background: rgba(0, 0, 0, 0.8);
	cursor: pointer;
}

#quote-popup .sb-quote-hubspot-shell__panel {
	position: relative;
	z-index: 2;
	width: 100%;
	max-width: 460px;
	max-height: 90vh;
	overflow: auto;
	/* v3 `--card: 0 0% 100%`; the beige predates the token set. */
	background: #ffffff;
	border: 1px solid #dbdfe6;
	border-radius: 8px;
	padding: 22px 24px 24px;
	box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
	box-sizing: border-box;
}

#quote-popup .sb-quote-hubspot-shell__close {
	position: absolute;
	top: 5px;
	right: 15px;
	border: none;
	background: transparent;
	font-size: 25px;
	line-height: 1;
	color: #555;
	cursor: pointer;
	padding: 0;
}

#quote-popup .sb-quote-hubspot-shell__close:hover {
	color: #000;
}

#quote-popup .sb-quote-hubspot-shell__title {
	margin: 0 32px 16px 0 !important;
	font-size: 20px !important;
	line-height: 26px !important;
	font-weight: 700;
	color: #141d2e !important;
}

#quote-popup .sb-quote-hubspot-shell__form-mount .hs-form-field > label {
	display: none;
}

#quote-popup .sb-quote-hubspot-shell__form-mount .hs-form-field {
	margin-bottom: 10px;
}

#quote-popup .sb-quote-hubspot-shell__form-mount fieldset {
	max-width: 100%;
	border: 0;
	margin: 0;
	padding: 0;
}

#quote-popup .sb-quote-hubspot-shell__form-mount fieldset.form-columns-2 {
	display: flex;
	gap: 10px;
}

#quote-popup .sb-quote-hubspot-shell__form-mount fieldset.form-columns-2 .hs-form-field {
	flex: 1 1 0;
	min-width: 0;
	width: auto !important;
	float: none !important;
}

#quote-popup .sb-quote-hubspot-shell__form-mount .legal-consent-container ul,
#quote-popup .sb-quote-hubspot-shell__form-mount .legal-consent-container li,
#quote-popup .sb-quote-hubspot-shell__form-mount .legal-consent-container ul.inputs-list {
	list-style: none !important;
	padding-left: 0 !important;
	margin-left: 0 !important;
}

#quote-popup .sb-quote-hubspot-shell__form-mount .legal-consent-container li::before,
#quote-popup .sb-quote-hubspot-shell__form-mount .legal-consent-container li::marker {
	content: none !important;
	display: none !important;
}

#quote-popup .sb-quote-hubspot-shell__form-mount input,
#quote-popup .sb-quote-hubspot-shell__form-mount textarea,
#quote-popup .sb-quote-hubspot-shell__form-mount select {
	width: 100%;
	padding: 5px 12px;
	border: 1px solid #ccc;
	border-radius: 6px;
	font-size: 16px;
	background: #fff;
	box-sizing: border-box;
}

#quote-popup .sb-quote-hubspot-shell__form-mount textarea {
	height: 65px !important;
}

#quote-popup .sb-quote-hubspot-shell__form-mount .hs-button,
#quote-popup .sb-quote-hubspot-shell__form-mount input.hs-button,
#quote-popup .sb-quote-hubspot-shell__form-mount .hs-submit .hs-button {
	background: #eb743d !important;
	color: #fff !important;
	padding: 12px 16px !important;
	border-radius: 6px !important;
	border: none !important;
	cursor: pointer;
	font-weight: 700 !important;
	font-size: 16px !important;
	width: 100% !important;
	height: auto !important;
	min-height: 42px;
}

#quote-popup .sb-quote-hubspot-shell__form-mount .hs-button:hover,
#quote-popup .sb-quote-hubspot-shell__form-mount input.hs-button:hover {
	background: #d9652f !important;
}

/*
 * The same reset the export shell was missing: without it HubSpot's own
 * markup renders a raw list bullet beside every validation message and beside
 * the consent row.
 */
#quote-popup .sb-quote-hubspot-shell__form-mount ul.hs-error-msgs,
#quote-popup .sb-quote-hubspot-shell__form-mount ul.inputs-list,
#quote-popup .sb-quote-hubspot-shell__form-mount .legal-consent-container ul,
#quote-popup .sb-quote-hubspot-shell__form-mount .legal-consent-container li,
#export-popup .sb-quote-hubspot-shell__form-mount ul.hs-error-msgs,
#export-popup .sb-quote-hubspot-shell__form-mount ul.inputs-list,
#export-popup .sb-quote-hubspot-shell__form-mount .legal-consent-container ul,
#export-popup .sb-quote-hubspot-shell__form-mount .legal-consent-container li,
#export-popup ul.hs-error-msgs,
#export-popup ul.inputs-list {
	list-style: none;
	padding: 0;
	margin: 0;
}

#quote-popup .sb-quote-hubspot-shell__form-mount ul.hs-error-msgs {
	margin-top: 3px;
	font-size: 14px;
	color: #c8102e;
}

#quote-popup .sb-quote-hubspot-shell__form-mount .legal-consent-container {
	margin: 8px 0 4px;
}

#quote-popup .sb-quote-hubspot-shell__form-mount .legal-consent-container .hs-form-booleancheckbox-display {
	display: flex;
	align-items: flex-start;
	gap: 8px;
}

#quote-popup .sb-quote-hubspot-shell__form-mount .legal-consent-container .hs-form-booleancheckbox-display > span {
	display: inline !important;
	margin-left: 0 !important;
	font-size: 14px !important;
	line-height: 20px !important;
}

#quote-popup .sb-quote-hubspot-shell__form-mount .legal-consent-container a {
	color: #eb743d !important;
	text-decoration: none;
}

#quote-popup .sb-quote-hubspot-shell__form-mount input[type="checkbox"] {
	margin-top: 3px;
	width: auto !important;
	flex: 0 0 auto;
}

#quote-popup .sb-quote-hubspot-shell__form-mount .hs-recaptcha,
#quote-popup .sb-quote-hubspot-shell__form-mount .grecaptcha-badge,
#quote-popup .sb-quote-hubspot-shell__form-mount .hs-recaptcha > div {
	margin: 4px 0 10px;
	transform: scale(0.92);
	transform-origin: left top;
	max-width: 100%;
}

@media (max-width: 767px) {
	#quote-popup .sb-quote-hubspot-shell__panel {
		padding: 20px 15px;
	}

	#quote-popup .sb-quote-hubspot-shell__form-mount fieldset.form-columns-2 {
		flex-direction: column;
		gap: 0;
	}
}

/* Export CSV modal — catalog archive CSS is dequeued on Sample Finder. */
#export-popup.sb-quote-hubspot-shell {
	position: fixed !important;
	inset: 0;
	display: none;
	align-items: center;
	justify-content: center;
	z-index: 999999 !important;
	padding: 16px;
	box-sizing: border-box;
}

#export-popup.sb-quote-hubspot-shell.sb-modal-open,
#export-popup.sb-quote-hubspot-shell[style*="flex"] {
	display: flex !important;
}

#export-popup .sb-quote-hubspot-shell__backdrop {
	position: absolute !important;
	inset: 0;
	border: 0 !important;
	padding: 0 !important;
	margin: 0 !important;
	background: rgba(0, 0, 0, 0.8);
	cursor: pointer;
}

#export-popup .sb-quote-hubspot-shell__panel {
	position: relative;
	z-index: 2;
	width: 100%;
	max-width: 460px;
	max-height: 90vh;
	overflow: auto;
	/* v3 `--card: 0 0% 100%`; the beige predates the token set. */
	background: #ffffff;
	border: 1px solid #dbdfe6;
	border-radius: 8px;
	padding: 22px 24px 24px;
	box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
	box-sizing: border-box;
}

#export-popup .sb-quote-hubspot-shell__close {
	position: absolute;
	top: 5px;
	right: 15px;
	border: none;
	background: transparent;
	font-size: 25px;
	line-height: 1;
	color: #555;
	cursor: pointer;
	padding: 0;
}

#export-popup .sb-quote-hubspot-shell__close:hover {
	color: #000;
}

#export-popup .sb-quote-hubspot-shell__title {
	margin: 0 32px 16px 0 !important;
	font-size: 20px !important;
	line-height: 26px !important;
	font-weight: 700;
	color: #141d2e !important;
}

#export-popup .sb-export-hubspot-shell__lead {
	margin: 0 0 16px !important;
	font-family: Inter, system-ui, sans-serif !important;
	font-size: 14px !important;
	line-height: 22px !important;
	color: #334155 !important;
}

#export-popup .sb-quote-hubspot-shell__form-mount .hs-form-field > label {
	display: none;
}

#export-popup .sb-quote-hubspot-shell__form-mount .hs-form-field {
	margin-bottom: 10px;
}

/*
 * NOT the checkbox (Brian, 28 Sep -- reported three times).
 *
 * Unqualified, this caught the consent checkbox and gave it the full 410px of
 * the flex row, so the sentence beside it was squeezed to zero width and wrapped
 * one character per line. `:not()` here rather than a counter-rule below,
 * because `width: 100% !important` on a checkbox is simply wrong and any
 * override would have to out-shout it forever.
 *
 * Matches what css/product-catalog-archive.css and css/single-product-modern.css
 * already do for their copies of this block, and what #quote-popup already does
 * a few rules above.
 */
#export-popup .sb-quote-hubspot-shell__form-mount input:not([type="checkbox"]):not([type="radio"]),
#export-popup .sb-quote-hubspot-shell__form-mount textarea,
#export-popup .sb-quote-hubspot-shell__form-mount select {
	width: 100% !important;
	padding: 5px 12px !important;
	border: 1px solid #ccc !important;
	border-radius: 6px !important;
	font-size: 16px !important;
	font-family: Inter, system-ui, sans-serif !important;
	box-sizing: border-box;
}

/* The checkbox keeps its own size, exactly as #quote-popup's already does. */
#export-popup .sb-quote-hubspot-shell__form-mount input[type="checkbox"] {
	margin-top: 3px;
	width: auto !important;
	flex: 0 0 auto;
}

#export-popup .sb-quote-hubspot-shell__form-mount textarea {
	height: 65px !important;
}

#export-popup .sb-quote-hubspot-shell__form-mount .hs-button,
#export-popup .sb-quote-hubspot-shell__form-mount input.hs-button,
#export-popup .sb-quote-hubspot-shell__form-mount .hs-submit .hs-button {
	width: 100%;
	margin-top: 8px;
	padding: 12px 16px !important;
	border: none !important;
	border-radius: 6px !important;
	background: #eb743d !important;
	color: #fff !important;
	font-size: 16px !important;
	font-weight: 600 !important;
	font-family: Inter, system-ui, sans-serif !important;
	cursor: pointer;
}

#export-popup .sb-quote-hubspot-shell__form-mount .hs-button:hover,
#export-popup .sb-quote-hubspot-shell__form-mount input.hs-button:hover {
	background: #d8652f !important;
}

#export-popup .hs-button.is-sb-export-loading,
.sb-export-hubspot-shell .hs-button.is-sb-export-loading {
	position: relative;
	cursor: wait;
	opacity: 0.85;
	pointer-events: none;
}

#export-popup .sb-export-submit__spinner,
.sb-export-hubspot-shell .sb-export-submit__spinner {
	display: inline-block;
	width: 14px;
	height: 14px;
	margin-left: 8px;
	border: 2px solid rgba(255, 255, 255, 0.35);
	border-top-color: #fff;
	border-radius: 50%;
	vertical-align: middle;
	animation: sb-export-spin 0.65s linear infinite;
}

@keyframes sb-export-spin {
	to {
		transform: rotate(360deg);
	}
}

@media (max-width: 767px) {
	#export-popup .sb-quote-hubspot-shell__panel {
		padding: 20px 15px;
	}
}

/* --- Pagination (single border, arrow nav) ------------------------------- */

/*
 * Panel footer under the table: page size on the left, pagination on the right.
 * The pagination keeps its own margin-top for the single-page case, where the
 * footer holds only the page-size control.
 */
/*
 * The design's results bar is a carded strip -- 1390x57 tinted
 * rgba(237,239,242,.3) on a 1px rgba(219,223,230,.6) hairline with 12/16
 * padding -- not a bare flex row. Live measured 1392x36, transparent, no
 * border, no padding.
 */
/*
 * "Showing 1-25 of 3,928 lots" -- TablePagination.tsx's first element:
 * `text-xs text-muted-foreground`, with the two numbers
 * `font-semibold text-foreground`. The footer is a flex row in the component
 * (`flex-col sm:flex-row items-center justify-between`), so the line takes the
 * left and the controls the right.
 */
.sb-sf .sb-sf-showing {
	margin: 0;
	margin-right: auto;
	font-size: 12px;
	line-height: 16px;
	color: #647690;                     /* text-muted-foreground */
	font-variant-numeric: tabular-nums;
}

.sb-sf .sb-sf-showing__num {
	font-weight: 600;                   /* font-semibold */
	color: #141d2e;                     /* text-foreground */
}

@media (max-width: 639px) {
	.sb-sf .sb-sf-showing {
		margin-right: 0;
		order: 2;                       /* order-2 sm:order-1 */
		width: 100%;
		text-align: center;
	}
}

.sb-sf .sb-sf-panel-foot {
	background: rgba(237, 239, 242, 0.3);
	border: 1px solid rgba(219, 223, 230, 0.6);
	border-radius: 6px;
	/* Design: the pagination bar is the card's bottom band -- 12/16 padding,
	   no radius of its own. The 2/6/10 that was here belongs to
	   .sb-sf-toolbar-meta, and applying it here made both bars wrong. */
	padding: 12px 16px;
	box-sizing: border-box;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	margin-top: 12px;
}

.sb-sf .sb-sf-panel-foot .sb-sf-per-page {
	flex: 0 0 auto;
}

.sb-sf .sb-sf-panel-foot [data-sb-sf-pagination] {
	margin-top: 0;
	margin-left: auto;
}

.sb-sf [data-sb-sf-pagination] {
	margin-top: 12px;
	display: flex;
	justify-content: flex-end;
}

@media (max-width: 639px) {
	.sb-sf .sb-sf-panel-foot {
		justify-content: center;
	}

	.sb-sf .sb-sf-panel-foot [data-sb-sf-pagination] {
		margin-left: 0;
	}
}

.sb-sf .sb-sf-pagination {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: flex-end;
	/* The design's container is `flex items-center gap-1` = 4px. */
	gap: 4px;
	margin: 0;
	padding: 0;
	border: 0;
	background: transparent;
}

.sb-sf .sb-sf-page {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	min-width: 36px;
	height: 36px;
	margin: 0;
	padding: 0 10px;
	border: 1px solid #dbdfe6;
	border-radius: 8px;
	background: #fff;
	font-size: 14px;
	font-weight: 600;
	line-height: 1;
	color: #14204a;
	cursor: pointer;
	box-shadow: none;
}

.sb-sf .sb-sf-page svg {
	width: 16px;
	height: 16px;
}

.sb-sf .sb-sf-page:hover:not(:disabled):not(.is-current):not(.sb-sf-page--dots) {
	background: #f1f5f9;
}

/*
 * Navy, not accent. The design's current page is
 * `bg-primary text-primary-foreground` -- `--primary: 242 96% 28%` =
 * rgb(7,3,140) -- and AC7 is explicit that "orange is reserved for calls to
 * action; non-CTA accents are navy or muted". A current-page marker is a state
 * indicator, not a call to action: there is nothing to click, which is why this
 * same rule sets `cursor: default`.
 *
 * Every other orange element on the catalog is a genuine CTA (Add to Cart,
 * Request Quote) or design-sanctioned (the strip dot is `bg-brand-orange` in
 * the export too); this chip was the only one that was neither.
 */
.sb-sf .sb-sf-page.is-current,
.sb-sf .sb-sf-page[aria-current="page"] {
	background: #07038C;
	border-color: #07038C;
	color: #fff;
	cursor: default;
}

.sb-sf .sb-sf-page--dots {
	border: 0;
	background: transparent;
	cursor: default;
	min-width: 24px;
	color: #647690;
}

.sb-sf .sb-sf-page:focus,
.sb-sf .sb-sf-page:focus-visible {
	outline: 2px solid #07038c;
	outline-offset: 2px;
}

/* --- All Products sort buttons: no focus fill ---------------------------- */

.sb-sf .sb-sf-sort {
	background: transparent !important;
	border: 0 !important;
	box-shadow: none !important;
	padding: 0;
	cursor: pointer;
	color: inherit;
}

.sb-sf .sb-sf-sort:hover,
.sb-sf .sb-sf-sort:focus,
.sb-sf .sb-sf-sort:active,
.sb-sf .sb-sf-sort:focus-visible {
	background: transparent !important;
	box-shadow: none !important;
}

.sb-sf .sb-sf-sort:focus-visible {
	outline: 2px solid #07038c;
	outline-offset: 2px;
}

/* --- AJAX skeleton (catalog + product/master) ---------------------------- */

.sb-sf [data-sb-sf-panel].is-loading {
	pointer-events: none;
}

.sb-sf [data-sb-sf-stage] {
	width: 100%;
	box-sizing: border-box;
}

.sb-sf .sb-sf-skeleton {
	width: 100%;
	min-width: 100%;
	box-sizing: border-box;
	min-height: 320px;
}

.sb-sf-skeleton-row {
	display: grid;
	grid-template-columns: minmax(0, 2fr) minmax(0, 1.1fr) minmax(0, 1.3fr) minmax(90px, 130px) minmax(110px, 150px);
	gap: 16px;
	align-items: center;
	width: 100%;
	box-sizing: border-box;
	padding: 16px;
	border-bottom: 1px solid #dbdfe6;
}

.sb-sf .sb-sf-skeleton[data-sb-sf-skeleton="catalog"] .sb-sf-skeleton-row {
	grid-template-columns: minmax(0, 2fr) minmax(0, 1.1fr) minmax(0, 1.3fr) minmax(90px, 130px) minmax(110px, 150px);
}

.sb-sf .sb-sf-skeleton[data-sb-sf-skeleton="instock"] .sb-sf-skeleton-row {
	grid-template-columns: repeat(8, minmax(0, 1fr));
}

.sb-sf-skeleton-bar {
	display: block;
	height: 12px;
	max-width: 100%;
	border-radius: 4px;
	background: linear-gradient(90deg, #dbdfe6 0%, #f1f5f9 50%, #dbdfe6 100%);
	background-size: 200% 100%;
	animation: sb-sf-shimmer 1.1s ease-in-out infinite;
}

.sb-sf-skeleton-bar--primary {
	height: 16px;
	width: 62%;
}

.sb-sf-skeleton-bar--action {
	width: 120px;
	max-width: 100%;
	height: 36px;
	margin-left: auto;
	border-radius: 8px;
}

@keyframes sb-sf-shimmer {
	0% { background-position: 100% 0; }
	100% { background-position: -100% 0; }
}

@media (max-width: 1199px) {
	
}

@media (max-width: 767px) {

	.sb-sf [data-sb-sf-pagination] {
		justify-content: center;
	}
}

/* --- Navy In-Stock table headers ----------------------------------------- */

/*
 * v2 design: the header row is solid brand navy with white, bold, uppercase
 * 12px labels. `--table-header` is redefined so compiled `.bg-table-header`
 * and the header-under scroller follow together.
 *
 * The utility classes the flat export uses for this -- `.text-table-header-
 * foreground`, `.border-primary-foreground/20`, `.border-border/60` -- are
 * NOT in this theme's partial Tailwind build, so the values are set here
 * explicitly rather than relying on markup classes that compile to nothing.
 */
.sb-sf {
	--table-header: var(--brand-navy);
}

.sb-sf .sb-sf-th,
.sb-sf .sb-sf-thead {
	background-color: hsl(var(--brand-navy));
	/* Solid white. AC2/AC7: the 88% used before failed the AA contrast check. */
	color: hsl(var(--brand-navy-foreground));
	border-color: hsl(0 0% 100% / 0.2);
}

/*
 * AC5: the Product cell keeps the neutral `border/60` underline of the export;
 * every other header cell divides with white at 20%.
 */
.sb-sf [data-sb-sf-instock] thead th.sb-sf-freeze--left {
	border-bottom-color: hsl(var(--border) / 0.6);
}

.sb-sf .sb-sf-th a,
.sb-sf .sb-sf-th button,
.sb-sf .sb-sf-thead a,
.sb-sf .sb-sf-thead button {
	color: inherit;
}

/*
 * AC3: the sort affordance carries the emphasis, not the colour -- the active
 * column reads at full opacity, inactive columns at 90%. Both are white, so a
 * label can never go navy-on-navy the way a `text-foreground` utility would.
 */
.sb-sf .sb-sf-th .sb-sf-sort,
.sb-sf .sb-sf-thead .sb-sf-sort {
	color: hsl(var(--brand-navy-foreground));
	opacity: 0.9;
	transition: opacity 120ms ease;
}

.sb-sf .sb-sf-th .sb-sf-sort.is-sorted,
.sb-sf .sb-sf-thead .sb-sf-sort.is-sorted,
.sb-sf .sb-sf-th .sb-sf-sort:hover,
.sb-sf .sb-sf-thead .sb-sf-sort:hover,
.sb-sf .sb-sf-th .sb-sf-sort:focus-visible,
.sb-sf .sb-sf-thead .sb-sf-sort:focus-visible {
	color: hsl(var(--brand-navy-foreground));
	opacity: 1;
}

.sb-sf .sb-sf-th svg,
.sb-sf .sb-sf-thead svg {
	color: inherit;
	stroke: currentColor;
}

/* Inactive chevron sits back at 50%; the sorted one is full strength. */
.sb-sf .sb-sf-th .sb-sf-sort .sb-sf-sort-icon,
.sb-sf .sb-sf-thead .sb-sf-sort .sb-sf-sort-icon {
	opacity: 0.5;
}

.sb-sf .sb-sf-th .sb-sf-sort.is-sorted .sb-sf-sort-icon,
.sb-sf .sb-sf-thead .sb-sf-sort.is-sorted .sb-sf-sort-icon {
	opacity: 1;
}

/*
 * AC8-AC11: Export CSV is an outline button -- white fill, navy border, navy
 * bold label. The orange accent is reserved for Add to Cart and other primary
 * commerce actions, so this must not compete with them.
 */
.sb-sf #export-samples-csv {
	background: hsl(var(--card));
	border: 1px solid hsl(var(--primary));
	color: hsl(var(--primary));
	box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
}

.sb-sf #export-samples-csv svg {
	color: hsl(var(--primary));
}

/* AC9: only the fill changes on hover; border and label hold their colour. */
.sb-sf #export-samples-csv:hover:not(:disabled),
.sb-sf #export-samples-csv:focus-visible:not(:disabled) {
	background: hsl(var(--primary) / 0.1);
	border-color: hsl(var(--primary));
	color: hsl(var(--primary));
}

/*
 * The product page renders this same component as `.sb-sf--embedded`, and the
 * design gives Export CSV the larger `h-9 / text-sm` treatment there rather
 * than the catalog toolbar's compact `h-7 / text-xs`.
 *
 * This lives here, not in sample-finder-catalog.css: that sheet is only
 * enqueued on the catalog archive, so a rule placed there never reaches the
 * product page at all.
 */
/*
 * REMOVED, not overridden. These two rules made the product page's Export CSV a
 * different button from the catalog's -- 134x36 with a 14px label against
 * 121x28 at 12px -- which breaks Brian's standing requirement that the two
 * in-stock table surfaces match, and the catalog is the one that agrees with
 * html/product-detail.html. Deleting the divergence at its source is better
 * than counter-patching it from the product page's own stylesheet, which is
 * where I first put the fix.
 *
 * .sb-sf--embedded #export-samples-csv { height: 36px; font-size: 14px;
 *                                        line-height: 20px }
 * .sb-sf--embedded #export-samples-csv svg { margin-right: 6px }
 */



/* AC10: disabled keeps the outline, at reduced opacity, and is not clickable. */
.sb-sf #export-samples-csv:disabled,
.sb-sf #export-samples-csv[aria-disabled="true"] {
	background: hsl(var(--card));
	border-color: hsl(var(--primary));
	color: hsl(var(--primary));
	opacity: 0.5;
	pointer-events: none;
	cursor: not-allowed;
}

/*
 * AC6: the header cells are already `position: sticky; top: 0`, but sticky is
 * relative to the nearest scrolling ancestor -- and with `max-height: none`
 * the scroller never scrolls vertically, so the header simply left with the
 * page and nothing was ever pinned.
 *
 * The design wraps the lot table in `max-h-[70vh] overflow-auto`; matching that
 * cap is what makes the sticky header real. Scoped to the In Stock view so the
 * All Products grid keeps growing with the page as before.
 */
.sb-sf [data-sb-sf-instock] .sb-sf-scroller {
	max-height: 70vh;
}

.sb-sf [data-sb-sf-instock] .sb-sf-instock-table {
	/*
	 * `fixed` + `min-content` is what makes the <col> widths below binding:
	 * under `auto`/`max-content` the browser sized every column to its longest
	 * cell (Medications reached 1565px and the table 4928px against the
	 * design's 2518), so half the columns fell off the right edge at 1440.
	 */
	table-layout: fixed;
	width: min-content;
	min-width: min-content;
	max-width: none;
	border-collapse: separate;
	border-spacing: 0;
}

.sb-sf [data-sb-sf-instock] .sb-sf-instock-table th,
.sb-sf [data-sb-sf-instock] .sb-sf-instock-table td,
.sb-sf [data-sb-sf-instock] .sb-sf-td {
	box-sizing: border-box;
	padding: 10px 14px;
	vertical-align: middle;
}

/*
 * Brian, 15 Sep: the product page's in-stock table must match /products/
 * EXACTLY. It did in every measured dimension but two -- body-cell line-height
 * came out 22px on the PDP against 16px on the catalog, and body-cell colour
 * #334155 against #141d2e.
 *
 * Cause, from matched.py rather than a guess: a PROSE rule in
 * css/single-product-modern.css --
 * `.tab-pane:not(#faq):not(#overview):not(#protocols) p, li, td` -- styles tab
 * copy, and this data table merely happens to sit inside one of those panes.
 * The catalog has no such wrapper, and its values were themselves inherited, so
 * the two surfaces agreed only by accident of their ancestors.
 *
 * Declaring them on the cells makes the two surfaces agree BY CONSTRUCTION.
 *
 * Scoped to `tbody td` on purpose: the shared th/td rule above also covers the
 * navy header, which carries white text and its own type, and must not be
 * dragged to the body colour.
 *
 * The `!important` is load-bearing and measured, not defensive. Those three
 * `:not(#id)` clauses give the prose rule three ids of specificity, so no sane
 * selector outranks it -- but it does not mark either property important, so
 * one `!important` here wins outright. Narrowing the prose rule instead would
 * mean editing a minified file to put a `:not()` around a descendant.
 */
.sb-sf [data-sb-sf-instock] .sb-sf-instock-table tbody td {
	line-height: 16px !important;
	color: #141d2e !important;          /* --foreground 220 40% 13% */
}

.sb-sf [data-sb-sf-instock] .sb-sf-instock-table thead th {
	/* Design: px-2 py-2.5 on every header cell... */
	padding: 10px 8px;
	white-space: nowrap;
}

.sb-sf [data-sb-sf-instock] .sb-sf-instock-table thead th.sb-sf-freeze--left {
	/* ...except Product, which is px-2.5. */
	padding: 10px 10px;
}

.sb-sf [data-sb-sf-instock] .sb-sf-instock-table thead th .sb-sf-sort {
	white-space: nowrap;
	gap: 6px;
}

.sb-sf [data-sb-sf-instock] .sb-sf-instock-table tbody td {
	white-space: nowrap;
}

.sb-sf [data-sb-sf-instock] .sb-sf-freeze--left,
.sb-sf [data-sb-sf-instock] .sb-sf-freeze--left a,
.sb-sf [data-sb-sf-instock] .sb-sf-td--wrap {
	white-space: normal;
	overflow-wrap: anywhere;
	word-break: break-word;
}

/*
 * Column widths, measured off the design's own table (v3 /tmp/cols.py):
 *   Product 240  Lot 88  Patient 84  Gender 72  Age 58  Race 112  Format 104
 *   Volume 74  Vials 50  Meds 130  Comorbid 130  Country 100  Collected 84
 *   HLA 116 each  Price/Action 148        row height 49, cell padding 6px
 *
 * `max-width` matters as much as `width`: with only width/min-width the
 * Medications column stretched to 1565px on real data and the table came out
 * 4928px wide against the design's 2518, which pushed Country and everything
 * after it off the right edge at 1440.
 */
.sb-sf [data-sb-sf-instock] .sb-sf-col--product { width: 240px; min-width: 240px; max-width: 240px; }
.sb-sf [data-sb-sf-instock] .sb-sf-col--lot { width: 96px; min-width: 96px; max-width: 96px; }
.sb-sf [data-sb-sf-instock] .sb-sf-col--patient { width: 108px; min-width: 108px; max-width: 108px; }
.sb-sf [data-sb-sf-instock] .sb-sf-col--gender { width: 84px; min-width: 84px; max-width: 84px; }
.sb-sf [data-sb-sf-instock] .sb-sf-col--age { width: 64px; min-width: 64px; max-width: 64px; }
.sb-sf [data-sb-sf-instock] .sb-sf-col--race { width: 112px; min-width: 112px; max-width: 112px; }
.sb-sf [data-sb-sf-instock] .sb-sf-col--format { width: 104px; min-width: 104px; max-width: 104px; }
.sb-sf [data-sb-sf-instock] .sb-sf-col--volume { width: 88px; min-width: 88px; max-width: 88px; }
.sb-sf [data-sb-sf-instock] .sb-sf-col--vials { width: 74px; min-width: 74px; max-width: 74px; }
.sb-sf [data-sb-sf-instock] .sb-sf-col--cells { width: 84px; min-width: 84px; max-width: 84px; }
.sb-sf [data-sb-sf-instock] .sb-sf-col--meds { width: 130px; min-width: 130px; max-width: 130px; }
.sb-sf [data-sb-sf-instock] .sb-sf-col--comorbid { width: 138px; min-width: 138px; max-width: 138px; }
.sb-sf [data-sb-sf-instock] .sb-sf-col--country { width: 100px; min-width: 100px; max-width: 100px; }
/*
 * AC2's first bullet -- "no header label is clipped" -- beats its width
 * list here. Measured on the DESIGN's own table at 1440: COLLECTED needs
 * 91px of label inside an 87px content box at the listed 104, so the design
 * clips it by 4px. 112 clears it and matches the RACE column beside it.
 */
/* Index.tsx's 14th <col> is 104, not 112 (critic 6, F1). Before C5V4-B
 * inserted the missing --cells col, this 112 was being WORN by a different
 * column, so the number looked plausible on the wrong one -- an off-by-one
 * in a colgroup shifts values, it does not obviously break them. */
.sb-sf [data-sb-sf-instock] .sb-sf-col--collected { width: 104px; min-width: 104px; max-width: 104px; }
.sb-sf [data-sb-sf-instock] .sb-sf-col--hla { width: 124px; min-width: 124px; max-width: 124px; }
.sb-sf [data-sb-sf-instock] .sb-sf-col--action { width: 148px; min-width: 148px; max-width: 148px; }

/*
 * A fixed layout is what makes those widths binding; without it the browser
 * still grows a column to fit its longest cell. Anything too long is clipped
 * with an ellipsis, as in the design ("African Ameri...").
 */
.sb-sf [data-sb-sf-instock] .sb-sf-td,
.sb-sf [data-sb-sf-instock] .sb-sf-th {
	/*
	 * Every cell clips. Excluding the wrapping cells let Medications and
	 * Comorbidities spill their nowrap text straight across Country and the
	 * price column; the design truncates instead ("African Ameri...").
	 */
	overflow: hidden;
	text-overflow: ellipsis;
}

/*
 * The design's rows are 49px on 6px/8px cell padding; locally they were
 * 10px/14px. The horizontal half matters as much as the vertical: with 14px
 * gutters the 58px Age column had only 30px of content box and "31-45"
 * truncated to "31-...".
 */
.sb-sf [data-sb-sf-instock] .sb-sf-instock-table td.sb-sf-td,
.sb-sf [data-sb-sf-instock] .sb-sf-instock-table th.sb-sf-th {
	padding-top: 6px;
	padding-bottom: 6px;
	padding-left: 8px;
	padding-right: 8px;
}

.sb-sf [data-sb-sf-instock] .sb-sf-freeze--left {
	left: 0 !important;
	width: 240px;
	min-width: 240px;
	max-width: 240px;
}

.sb-sf [data-sb-sf-instock] .sb-sf-freeze--lot {
	left: 240px !important;
	width: 88px;
	min-width: 88px;
	max-width: 88px;
}

.sb-sf [data-sb-sf-instock] .sb-sf-freeze--right {
	width: 148px;
	min-width: 148px;
	max-width: 148px;
}


/* -------------------------------------------------------------------------
 * In-stock table: the Price / Action cell
 *
 * Measured on the design (/tmp/price.py): the 148px cell carries 6px/8px
 * padding, an 8px gap, and an 82x24 button at 0/8px padding on a 4px radius.
 * Locally the parent theme's button rules inflated it to 110x30 at 0/12px
 * with 14px cell padding -- 158px of content in a 120px box, so the price read
 * "30" instead of "$530".
 * ---------------------------------------------------------------------- */

.sb-sf [data-sb-sf-instock] tbody td.sb-sf-freeze--right,
.sb-sf [data-sb-sf-instock] thead th.sb-sf-freeze--right {
	padding-left: 8px !important;
	padding-right: 8px !important;
}

.sb-sf [data-sb-sf-instock] .sb-sf-atc-btn,
.sb-sf [data-sb-sf-instock] .sb-sf-quote-btn,
.sb-sf [data-sb-sf-instock] button.sb-sf-atc-btn,
.sb-sf [data-sb-sf-instock] button.sb-sf-quote-btn {
	width: 82px !important;
	min-width: 82px !important;
	height: 24px !important;
	min-height: 24px !important;
	padding: 0 8px !important;
	border-radius: 4px !important;
	font-size: 12px !important;
	line-height: 16px !important;
}

/*
 * The PDP In Stock tab's heading (the catalog page's panel carries none).
 * The tab-pane heading rule in the product styles is `!important`, so this
 * has to be too or the title renders at the pane's 20px/28.
 */
/*
 * The `html` prefix and the matching `:not()` chain are not decoration. The
 * rule that was winning is
 *
 *   body.single-product .sb-product-tabs .tabs-content
 *     .tab-pane:not(#faq):not(#overview):not(#protocols) h2
 *
 * and those three `:not(#id)` count as THREE IDs, putting it at (3,4,2) --
 * matching `!important` does nothing against that. Measured before: 20px/28 at
 * 1440 and 18px/26 at 375, against the design's 24px/32 in navy.
 */
.sb-sf-panel-title,
body.single-product .sb-product-tabs .tabs-content .tab-pane .sb-sf-panel-title,
html body.single-product .sb-product-tabs .tabs-content .tab-pane:not(#faq):not(#overview):not(#protocols) h2.sb-sf-panel-title {
	margin: 0 0 16px;
	font-size: 24px !important;
	line-height: 32px !important;
	font-weight: 700 !important;
	/* v3 AC4 supersedes the v2 heading face: one typeface, Inter. */
	font-family: Inter, system-ui, sans-serif;
	/* The design's heading is navy at normal tracking, not ink at -0.025em. */
	letter-spacing: normal !important;
	color: #07038c !important;
}

/* -------------------------------------------------------------------------
 * "Show N per page"
 *
 * Sits in the toolbar meta row beside the result count and Export CSV, and
 * borrows the filter pill's hairline so the row reads as one set of controls.
 * ---------------------------------------------------------------------- */

.sb-sf .sb-sf-per-page {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	white-space: nowrap;
	font-size: 12px;
	line-height: 16px;
	color: #647690;
}

.sb-sf .sb-sf-per-page__label {
	font-size: 12px;
	line-height: 16px;
	font-weight: 400;
	color: #647690;
}

.sb-sf .sb-sf-per-page__select {
	appearance: none;
	-webkit-appearance: none;
	height: 26px;
	min-height: 26px;
	width: auto;
	margin: 0;
	padding: 4px 26px 4px 10px;
	border: 1px solid rgba(219, 223, 230, 0.6);
	border-radius: 6px;
	background-color: transparent;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23647690' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 8px center;
	background-size: 12px 12px;
	font-family: Inter, system-ui, sans-serif;
	font-size: 12px;
	line-height: 16px;
	font-weight: 400;
	color: rgba(20, 29, 46, 0.8);
	box-shadow: none;
	cursor: pointer;
	box-sizing: border-box;
}

.sb-sf .sb-sf-per-page__select:focus {
	outline: none;
	border-color: #eb743d;
	box-shadow: none;
}

/*
 * The orange border stays, and a keyboard user also gets the ring the rest of
 * the catalog's controls show (C3-4). A border colour change alone is not a
 * focus indicator: it is the same 1px edge in a different hue, and it was the
 * only signal on this control.
 */
.sb-sf .sb-sf-per-page__select:focus-visible {
	outline: 2px solid #07038c;   /* --ring 242 96% 28% */
	outline-offset: 2px;
	border-color: #eb743d;
	box-shadow: none;
}

@media (max-width: 639px) {
	/* The count and Export CSV take priority on a narrow toolbar. */
	.sb-sf .sb-sf-per-page__label {
		display: none;
	}
}

/* -------------------------------------------------------------------------
 * Filter-pill state utilities
 *
 * AC1 wants a selected value to read as selected. The pill markup asked for
 * `border-accent/60 bg-accent-soft` when including and
 * `border-destructive/60 bg-destructive/10` when excluding, and
 * css/sample-finder.css defines none of those four -- so an included pill, an
 * excluded pill and an untouched pill all rendered the same.
 *
 * Defined here rather than there because this sheet loads on both the catalog
 * and the product page, and because the include state is navy now: a selected
 * filter is a state, and AC7 keeps orange for calls to action.
 * ---------------------------------------------------------------------- */

.sb-sf .border-primary\/60 { border-color: hsl(var(--primary) / 0.6); }
.sb-sf .border-destructive\/60 { border-color: hsl(var(--destructive) / 0.6); }
.sb-sf .bg-primary\/5 { background-color: hsl(var(--primary) / 0.05); }
.sb-sf .bg-destructive\/10 { background-color: hsl(var(--destructive) / 0.1); }
.sb-sf .bg-destructive { background-color: hsl(var(--destructive)); }
.sb-sf .text-destructive-foreground { color: hsl(var(--destructive-foreground, 0 0% 100%)); }
.sb-sf .bg-primary { background-color: hsl(var(--primary)); }
.sb-sf .text-primary-foreground { color: hsl(var(--primary-foreground)); }

/*
 * R4-27, second attempt: `.sb-sf table td` did not land -- still 8px when
 * re-measured. The design is `px-2.5` on both axes.
 */
/*
 * 8px on the data cells, 10px on the first column only.
 *
 * Round five applied 10px to everything on a reading that only covered the
 * first column. Round six measured the design as 6/8 on data cells and 6/10 on
 * the Product column -- and the blanket 10px cost real text: "Cryopreserved"
 * needs 84.7px and had 84.
 */
.sb-sf .sb-sf-table td,
.sb-sf table.sb-sf-table td,
.sb-sf .sb-sf-scroller table td {
	padding-left: 8px !important;
	padding-right: 8px !important;
}

.sb-sf .sb-sf-table td:first-child,
.sb-sf table.sb-sf-table td:first-child,
.sb-sf .sb-sf-scroller table td:first-child {
	padding-left: 10px !important;
	padding-right: 10px !important;
}

/* 12: the table head's outer corner is rounded with the card. */
.sb-sf .sb-sf-table thead th:first-child,
.sb-sf table.sb-sf-table thead th:first-child {
	border-top-left-radius: 8px;
}

/*
 * R4-28: the All Products / In Stock segmented control measured 194x40 against
 * the design's 190x40 at every width -- 2px of padding each side.
 */
.sb-sf .sb-sf-viewtabs,
.sb-sf [role="tablist"].sb-sf-viewtabs {
	padding-left: 0;
	padding-right: 0;
}

/*
 * R6-15: the segmented control sits 24px under the hero in the design and 28
 * live, which also left only 20px to the card below instead of 24.
 */
.sb-sf .sb-sf-tabs {
	margin-top: 24px;
	margin-bottom: 24px;
}

/*
 * R5-16: the table head's outer corners are rounded with the card. The rule
 * added in round five targeted `.sb-sf-table`, which is not this table's class
 * -- the catalog renders `.sb-sf-instock-table`, which is why it never landed.
 */
.sb-sf .sb-sf-instock-table thead th:first-child {
	border-top-left-radius: 8px;
}

.sb-sf .sb-sf-instock-table thead th:last-child {
	border-top-right-radius: 8px;
}

/*
 * The design's pagination controls are 32 tall at 12px; live rendered 36 at
 * 14px, which is 4px of the panel foot's 62-against-57.
 */
/*
 * `.sb-sf-page` rather than `button, a`. The ellipsis is a <span> carrying the
 * same class, so enumerating tag names missed it: measured 33.4x36 at 14px
 * against every real chip's 36x32 at 12px, and because the row is
 * `align-items:center` that one span held the whole bar at 36.
 *
 * The design makes every control in this band h-8 (32px) text-xs (12px), the
 * ellipsis included. Scoping by the class that defines the thing, not by the
 * tags that happen to use it today, is the same lesson as the promo Apply
 * border -- which was scoped to a row and missed every other accent button.
 */
.sb-sf .sb-sf-panel-foot [data-sb-sf-pagination] .sb-sf-page,
.sb-sf .sb-sf-panel-foot [data-sb-sf-pagination] button,
.sb-sf .sb-sf-panel-foot [data-sb-sf-pagination] a {
	min-height: 32px;
	height: 32px;
	font-size: 12px;
	line-height: 16px;
}

/* -------------------------------------------------------------------------
 * C1R14-4: the pagination band, read off the design's own classes.
 *
 * Round thirteen fixed the HEIGHT of these controls and nothing else, so they
 * were still too wide and the wrong colours. The design spells every one out:
 *
 *   page chip        h-8 min-w-8 px-2 text-xs font-semibold
 *                    non-current: border border-input bg-background
 *                    current:     bg-primary text-primary-foreground, NO border
 *   prev / next      h-8 w-8 p-0
 *   per-page         h-8 w-[74px] text-xs
 *
 * `min-w-8` is 32px and `px-2` is 8px; live had min-width 36 and padding 0 10px,
 * which is the 36-vs-32 and the 38-wide chevrons. The current chip carried a 1px
 * border in its own navy -- invisible, but the same latent trap as the promo
 * Apply and the Retrieve a Quote buttons, and the third time it has appeared.
 *
 * The per-page control is a SIBLING of [data-sb-sf-pagination] inside the panel
 * foot, so the pagination-scoped rule never reached it -- the same "scoped to
 * the container that happens to hold them today" shape as the ellipsis. Scoped
 * to the foot here.
 * ---------------------------------------------------------------------- */
.sb-sf .sb-sf-panel-foot [data-sb-sf-pagination] .sb-sf-page {
	min-width: 32px;
	padding: 0 8px;
}

/* `w-8 p-0`: the chevron buttons are exactly square. */
.sb-sf .sb-sf-panel-foot [data-sb-sf-pagination] .sb-sf-page--nav {
	width: 32px;
	min-width: 32px;
	padding: 0;
}

/* The design's non-current chip sits on the page ground, not on white. */
.sb-sf .sb-sf-panel-foot [data-sb-sf-pagination] .sb-sf-page:not(.is-current):not(.sb-sf-page--dots) {
	background: #f6f7f9;
	color: #141d2e;
}

/* `bg-primary text-primary-foreground` carries no border class at all. */
.sb-sf .sb-sf-panel-foot [data-sb-sf-pagination] .sb-sf-page.is-current,
.sb-sf .sb-sf-panel-foot [data-sb-sf-pagination] .sb-sf-page[aria-current="page"] {
	border-width: 0;
}

/* `h-8 w-[74px]` -- the native select rendered 61x26. */
.sb-sf .sb-sf-panel-foot .sb-sf-per-page__select {
	/*
	 * `box-sizing: border-box` is not optional here. This is a native <select>,
	 * and without it `height: 32px` is the CONTENT box -- its padding and border
	 * are added outside.
	 *
	 * CORRECTION: an earlier version of this comment claimed the select was the
	 * foot's tallest child and that this alone took the foot 63 -> 58. It is
	 * not. The tallest OUTER child is `label.sb-sf-per-page`, which picks up
	 * `margin-bottom: 5px` from the parent theme's bare `label` reset; as a flex
	 * item that margin counts, making the line 37 rather than 32. The select
	 * itself is now exactly 74x32, the design's `h-8 w-[74px]`.
	 */
	box-sizing: border-box;
	width: 74px;
	height: 32px;
	min-height: 32px;
	font-size: 12px;
	line-height: 16px;
}

/*
 * The panel foot's height is `padding 12+12` + `border 1+1` + the tallest
 * child. That child is the per-page LABEL, not the select inside it: the parent
 * theme's reset puts `margin-bottom: 5px` on every bare <label>, and on a flex
 * item that margin is part of the outer size, so the line measured 37 and the
 * foot 63 against the design's 57.
 *
 * why.py named the winning rule; no theme rule zeroed it.
 */
.sb-sf .sb-sf-panel-foot .sb-sf-per-page {
	margin-bottom: 0;
}

/* -------------------------------------------------------------------------
 * Round fifteen, the pagination band -- three values read off the design's own
 * classes rather than inferred.
 *
 * C2R15-1  the container is `flex items-center gap-1` = 4px, not 6. At 6px an
 *          8-chip page is 14px wider than the design draws it. C1R14-4
 *          enumerated every CHIP property and never the CONTAINER's gap.
 * C1R15-3  every control is `rounded-md` = calc(var(--radius) - 2px) = 6px.
 *          The chips were 8px while the per-page <select> beside them was
 *          already 6 -- two adjacent controls in one band with different radii.
 *          Same 8-vs-6 trap R7-12 fixed on the Retrieve-a-Quote card.
 * C2R15-2  the design's end-stop chevron is `disabled` at `opacity: .5`. Live
 *          had no disabled-state opacity on .sb-sf-page at all, so rendering
 *          the button disabled would not have reproduced it.
 * ---------------------------------------------------------------------- */
/*
 * (The gap is corrected at its source above rather than overridden here. An
 * equal-specificity override in the same sheet wins only on source order,
 * which is the shape that has silently lost on this project before -- a future
 * reorder would have quietly restored 6px.)
 */
.sb-sf .sb-sf-panel-foot [data-sb-sf-pagination] .sb-sf-page {
	border-radius: 6px;
}

.sb-sf .sb-sf-panel-foot [data-sb-sf-pagination] .sb-sf-page--nav:disabled {
	opacity: .5;
	cursor: default;
}

/*
 * C3R16-1: the in-stock table's pre-JS height on the PRODUCT page.
 *
 * `.sb-sf-instock { height: calc(100vh - 210px) }` is the fallback until
 * `fitViewport()` measures the real space. The 210px assumes the catalog, where
 * the table sits near the top of the document. On the PDP it starts far lower,
 * so the same expression overshoots by 330-430px -- measured at 790px against
 * an intended 360px at 1440x1000.
 *
 * The Rocket exclusion added alongside this makes fitViewport() run again for
 * anonymous visitors, which is the real cure. This is the belt: a page-scoped
 * fallback that is roughly right even if the script never runs at all, so the
 * failure mode is a slightly wrong height rather than 430px of empty space.
 */
body.single-product .sb-sf .sb-sf-instock {
	height: calc(100vh - 520px);
}

/* =========================================================================
 * BRIAN 14 SEP -- tighter in-stock table, smaller filter pills, and the
 * white line around the frozen header columns
 *
 * On the table scale: measured, the cells already matched the v3 design export
 * exactly (6px/8px padding, 12px/16px, 49px rows, verified at six widths). The
 * instruction to tighten it is therefore a DELIBERATE DEVIATION from that
 * export, made on Brian's direct call after he raised it twice. Recorded so
 * nobody "fixes" it back to the export later.
 * ====================================================================== */

/* Rows 49 -> 41: vertical padding 6 -> 2 on a 16px line box, plus the 1px
   border. Horizontal stays 8px, because the Age column only has 30px of
   content box at 14px and "31-45" truncates below that. */
.sb-sf [data-sb-sf-instock] .sb-sf-instock-table td.sb-sf-td,
.sb-sf [data-sb-sf-instock] .sb-sf-instock-table th.sb-sf-th {
	padding-top: 2px;
	padding-bottom: 2px;
}

/* The header carried 10px all round from the freeze rules; match the body. */
.sb-sf [data-sb-sf-instock] .sb-sf-instock-table thead th,
.sb-sf [data-sb-sf-instock] .sb-sf-instock-table thead th.sb-sf-freeze--left {
	padding-top: 6px;
	padding-bottom: 6px;
}

/* The product cell wraps to two lines, so it keeps a little more room. */
.sb-sf [data-sb-sf-instock] tbody td.sb-sf-freeze--left {
	padding-top: 4px;
	padding-bottom: 4px;
}

/*
 * The white line around the frozen header columns.
 *
 * Every header cell carries `border-r border-primary-foreground/20` --
 * rgba(255,255,255,0.2) on the navy fill. On the scrolling columns that reads
 * as a faint divider, which is what the design intends. On the two STICKY
 * columns it sits at the seam where the frozen pane meets the scrolling one,
 * so it renders as a bright vertical rule that follows the scroll -- measured
 * `border-right: 1px rgba(255,255,255,0.2)` on .sb-sf-freeze--lot.
 *
 * Drop it on the frozen pair only. The columns are still separated: the body
 * cells keep their own border and the sticky pane sits above the scrolling one.
 */
.sb-sf [data-sb-sf-instock] thead th.sb-sf-freeze--left,
.sb-sf [data-sb-sf-instock] thead th.sb-sf-freeze--lot {
	border-right-color: transparent;
}

/* Filter pills: 26px tall on 4px/10px padding -> 22px on 2px/8px. */
.sb-sf .sb-sf-pill > summary,
.sb-sf details.sb-sf-pill > summary {
	padding-top: 2px;
	padding-bottom: 2px;
	padding-left: 8px;
	padding-right: 8px;
}

/* -------------------------------------------------------------------------
 * All Products row -- explicit sizes, because the utility classes do not work
 *
 * This theme carries a HAND-WRITTEN SUBSET of Tailwind, not the real thing.
 * `h-8`, `text-base` and `w-32` exist because something already used them;
 * `h-7` and `w-28` do not exist at all, so swapping the markup to them styled
 * nothing -- measured, the button stayed 40px on 13px after the class change.
 * `text-sm` on the title likewise lost to `.font-heading`.
 *
 * So the sizes are declared here rather than guessed at through utilities, and
 * the row carries a real class to hang them on.
 *
 * Target is the In Stock table on the same page: 14px bold titles, 12px body,
 * and an action button in the same family as its 24px Add to Cart.
 * ---------------------------------------------------------------------- */

/*
 * `body` prefix for weight, and `.font-heading` alone rather than the full
 * class chain: `text-sm` and `text-base` are NOT defined in any stylesheet
 * here, so chaining on them selects nothing useful and the 16px was coming
 * from elsewhere entirely.
 */
/* `py-1.5` is not a real class in this theme either -- state the padding. */
/*
 * v4, 15 Sep -- "Starting at" is `text-xs uppercase tracking-wide
 * text-muted-foreground leading-none` in GroupedProductTable.tsx.
 *
 * The uppercase and the tracking were REMOVED on 14 Sep, when Brian reported
 * this table's text as too big and the label was one of the things that looked
 * heavy. The v4 package is the updated design and restores both; the rest of
 * the row is now at the component's own sizes, so the label no longer sits in
 * an oversized row. Recorded in the register as superseding B22-1.
 */
.sb-sf .sb-sf-catalog-row .sb-sf-starting-at,
.sb-sf .sb-sf-catalog-row .text-xs.leading-none {
	text-transform: uppercase;
	letter-spacing: 0.025em;                /* tracking-wide */
}

body .sb-sf-catalog-row {
	/* v4: GroupedProductTable.tsx rows are `px-4 py-2`. */
	padding-top: 8px !important;
	padding-bottom: 8px !important;
}

.sb-sf-catalog-row .text-xs,
.sb-sf-catalog-row span.text-xs {
	font-size: 12px !important;
	line-height: 16px !important;
}

.sb-sf-catalog-row button {
	height: 32px !important;                /* v4: h-8 */
	min-height: 32px !important;
	/*
	 * BRIAN 14 SEP: 112px fixed CLIPPED the label -- measured scrollWidth 114
	 * against clientWidth 112, so "View Inventory" lost 2px at each end. Sized
	 * to content with a floor instead, because the labels differ ("Quote" is
	 * much shorter) and any fixed width is one label change from clipping again.
	 */
	/*
	 * v4: the component fixes this at `w-32` = 128px. That is SAFE where the old
	 * 112px was not -- the clipping recorded above was scrollWidth 114 against
	 * clientWidth 112, and 128 clears the longest label ("View Inventory") with
	 * room to spare. Re-measure if a longer label is ever added.
	 */
	width: 128px !important;
	min-width: 128px !important;
	padding: 0 !important;
	font-size: 12px !important;
	line-height: 16px !important;
}

/*
 * Pills: the summary carries `px-2.5 py-1` and my first attempt scoped the
 * override to `.sb-sf ...`, which the pill is not inside. Target the element
 * that actually exists.
 */
details.sb-sf-pill > summary {
	padding: 2px 8px !important;
}

/*
 * The frozen header's white edge. `border-primary-foreground/20` beat a plain
 * colour override, so state it at the same weight.
 */
.sb-sf [data-sb-sf-instock] thead th.sb-sf-freeze--left,
.sb-sf [data-sb-sf-instock] thead th.sb-sf-freeze--lot {
	border-right-color: transparent !important;
}

/*
 * BRIAN 14 SEP -- the "white border" around the frozen column headers.
 *
 * NOT a border and NOT an outline: measured, border-right is already
 * transparent from the earlier attempt and `outline-style` is `none`, so
 * neither was ever painting. It is the sticky seam -- the frozen cells are
 * `position: sticky` over the scrolling ones, and a subpixel gap at their edge
 * lets the page ground show through as a hairline that tracks the scroll.
 *
 * Covered with a box-shadow in the header's own navy, which paints across the
 * seam without adding a layout box. The body cells get the same treatment in
 * the card colour.
 */
.sb-sf [data-sb-sf-instock] thead th.sb-sf-freeze--left,
.sb-sf [data-sb-sf-instock] thead th.sb-sf-freeze--lot {
	box-shadow: 1px 0 0 0 #07038c, -1px 0 0 0 #07038c;
}

.sb-sf [data-sb-sf-instock] tbody td.sb-sf-freeze--left,
.sb-sf [data-sb-sf-instock] tbody td.sb-sf-freeze--lot {
	box-shadow: 1px 0 0 0 #ffffff, -1px 0 0 0 #ffffff;
}

/*
 * The band the top scrollbar sits in. A generated table-row, because the bar
 * is absolutely positioned and occupies no space of its own.
 */
.sb-sf [data-sb-sf-instock] .sb-sf-instock-table tbody::before {
	content: "";
	display: table-row;
	height: 12px;
}

/* Conventional colours: grey track above, darker grey rounded thumb. */
.sb-sf .sb-sf-hscroll[data-sb-sf-topscroll] .sb-sf-hscroll__thumb,
.sb-sf .sb-sf-hscroll[data-sb-sf-topscroll] .sb-sf-hscroll__thumb:hover,
.sb-sf .sb-sf-hscroll[data-sb-sf-topscroll] .sb-sf-hscroll__thumb:active {
	height: 6px;
	border-radius: 999px;
	background: rgba(100, 118, 144, 0.55);
}

.sb-sf .sb-sf-hscroll[data-sb-sf-topscroll] .sb-sf-hscroll__thumb:hover,
.sb-sf .sb-sf-hscroll[data-sb-sf-topscroll] .sb-sf-hscroll__thumb:active {
	background: rgba(100, 118, 144, 0.8);
}

/*
 * BRIAN 14 SEP -- the All Products table header "looks different" to the design.
 *
 * Size and weight were ALREADY right: both headers compute 12px/700/uppercase.
 * The visible difference is tracking -- the catalog header measured 0.72px
 * (0.06em) against the design-verified In Stock header's 0.3px, and wider
 * letter-spacing at that size is exactly what reads as a different typeface.
 *
 * 0.3px is Tailwind's `tracking-wide` (0.025em) at 12px, which is what the
 * design's own markup asks for; something else was widening it here.
 */
.sb-sf .sb-sf-catalog-head,
.sb-sf .sb-sf-catalog-head .sb-sf-sort {
	letter-spacing: 0.3px !important;
}

/*
 * v4: GroupedProductTable.tsx uses six tracks --
 * `md:grid-cols-[2fr,110px,1.1fr,1.3fr,130px,150px]` -- the 110px one being the
 * new Available Lots column.
 *
 * These arbitrary-value classes are NOT generated by anything here: this theme
 * carries a hand-written SUBSET of Tailwind, and the five-track version is
 * spelled out by hand in css/sample-finder.css. Adding the class to the markup
 * without adding this rule collapsed the row to a single 253px-tall column --
 * measured. The five-track rule stays where it is; this is the six-track one.
 */
.sb-sf .grid-cols-\[2fr\,110px\,1\.1fr\,1\.3fr\,130px\,150px\] {
	grid-template-columns: 2fr 110px 1.1fr 1.3fr 130px 150px;
}

@media (min-width: 768px) {
	.sb-sf .md\:grid-cols-\[2fr\,110px\,1\.1fr\,1\.3fr\,130px\,150px\] {
		grid-template-columns: 2fr 110px 1.1fr 1.3fr 130px 150px;
	}
}

/*
 * Section 9: in the card view the action is full width -- ProductCard.tsx gives
 * it `w-full`. Above md the grouped row keeps the design's fixed `w-32`.
 *
 * We collapse the grouped ROW to one column rather than rendering a separate
 * ProductCard component, so this is the card view's button; recorded as a
 * structural deviation in the register (V4-17).
 */
@media (max-width: 1023px) {
	.sb-sf .sb-sf-catalog-row button {
		width: 100% !important;
		min-width: 0 !important;
	}

	.sb-sf .sb-sf-catalog-row .flex.md\:justify-end {
		display: block;
	}
}

/* =========================================================================
 * Critic 1, 15 Sep -- the grouped catalog table against
 * GroupedProductTable.tsx line 178. Eight findings, all re-measured first.
 *
 * The header was the big one: the design gives it `bg-table-header
 * rounded-t-lg text-table-header-foreground`, and `--table-header: 242 96% 28%`
 * is NAVY with white labels -- the same treatment the in-stock table already
 * uses. Ours rendered `bg-muted/50` with muted-foreground text, so the two
 * catalog tables carried opposite header treatments where the design uses one.
 *
 * The type scale had drifted small throughout: the row is `text-sm` (14px) in
 * the design and was 12px here, the price is `text-base` and was 14px, and two
 * `leading-*` classes were being overridden by blanket line-height rules.
 * ====================================================================== */

/* --- header: navy, white, 12px, 10px vertical padding, top corners --- */
.sb-sf [data-sb-sf-stage] .sb-sf-catalog-head,
.sb-sf .sb-sf-catalog-head {
	background: #07038c !important;            /* --table-header 242 96% 28% */
	color: #ffffff !important;                 /* --table-header-foreground */
	font-size: 12px !important;                /* text-xs, not 11px */
	padding-top: 10px !important;              /* py-2.5, not 12px */
	padding-bottom: 10px !important;
	border-top-left-radius: 8px;               /* rounded-t-lg */
	border-top-right-radius: 8px;
}

/* Sort buttons and the plain Action label inherit the header's white. */
.sb-sf .sb-sf-catalog-head,
.sb-sf .sb-sf-catalog-head button,
.sb-sf .sb-sf-catalog-head a,
.sb-sf .sb-sf-catalog-head span,
.sb-sf .sb-sf-catalog-head div {
	color: #ffffff !important;
	font-size: 12px !important;
}

.sb-sf .sb-sf-catalog-head svg {
	color: #ffffff !important;
	opacity: 0.7;
}

/* --- row type scale --- */

/* `text-sm` on the data cells: lots, format, ships label.
 *
 * `!important` because an older blanket rule in this file sets
 * `.sb-sf-catalog-row .text-xs { font-size: 12px !important }` for the whole
 * row, and the markup still carries `text-xs` on these cells. Measured: without
 * it these stayed 12px. The "Starting at" label keeps its own 12px below --
 * that one really IS text-xs in the design. */
/* `[data-sb-row-href]`, not `a.contents`: C3V4-C turned that anchor into a div
 * so the row could be reached from the keyboard, and these rules were left
 * pointing at a node that no longer exists -- so every data cell silently fell
 * back to the blanket 12px (critic 5, F1). The attribute is the stable hook;
 * the element name is not. */
.sb-sf .sb-sf-catalog-row [data-sb-row-href] > div,
.sb-sf .sb-sf-catalog-row [data-sb-row-href] > div > span {
	font-size: 14px !important;
	line-height: 20px !important;
}

/* ...but the price block's two children keep their designed sizes. */
/*
 * `.leading-none` ONLY -- critic 7, F4.
 *
 * This also listed `.text-xs`, which is the class the availability cell's span
 * carries too ("Ships in 2 business days"). Both live at
 * `[data-sb-row-href] > div > span`, so the exception caught a cell it was never
 * meant for and held it at 12px while its two siblings -- carrying the SAME
 * utility classes -- rendered 14px. GroupedProductTable.tsx L209 gives it
 * `text-sm`.
 *
 * The only child that genuinely stays 12px is the "Starting at" label, and that
 * one is identified by `.leading-none`.
 */
.sb-sf .sb-sf-catalog-row [data-sb-row-href] > div > .leading-none {
	font-size: 12px !important;
}

/* The price keeps `text-base font-bold`. */
.sb-sf .sb-sf-catalog-row .font-heading.text-sm.font-bold,
.sb-sf .sb-sf-catalog-row .font-heading.font-bold {
	font-size: 16px !important;
	line-height: 24px !important;
}

/* `leading-none` on "Starting at": 12px, not the blanket 16px. */
.sb-sf .sb-sf-catalog-row .leading-none,
.sb-sf .sb-sf-catalog-row .text-xs.leading-none {
	line-height: 12px !important;
}

/* The filter bar's product count is `text-xs font-medium text-foreground`. */
.sb-sf .sb-sf-filter-bar__count {
	font-size: 12px !important;
	line-height: 16px !important;
	color: #141d2e !important;                 /* --foreground, not muted */
}

/* =========================================================================
 * Critic 1 #37, #36 -- utilities the markup uses that this theme never
 * defined, so they measured as 'no change'.
 *
 * `md:text-center` on the Available Lots cell returned ZERO matching rules
 * from matched.py: the value is left-aligned under a centred header. This
 * theme carries a hand-written SUBSET of Tailwind, and that class is not in
 * it -- the same class of bug as the six-track grid that collapsed every row.
 *
 * The product title's `hover:text-primary/70` was likewise never emitted:
 * forcing :hover with CSS.forcePseudoState left the colour unchanged.
 * ====================================================================== */

@media (min-width: 768px) {
	.sb-sf .md\:text-center { text-align: center; }
	.sb-sf .md\:text-right  { text-align: right; }
	.sb-sf .md\:text-left   { text-align: left; }
}

/* hover:text-primary/70 on the grouped product title. */
.sb-sf .sb-sf-catalog-row [data-sb-row-href]:hover .font-heading.text-primary,
.sb-sf .sb-sf-catalog-row .font-heading.text-primary:hover {
	color: rgba(7, 3, 140, 0.7) !important;
}


/* ---------------------------------------------------------------------------
 * The in-stock table's Product link: hover and focus (critic 8, F1/F6/F7).
 *
 * Index.tsx L956-958 is `<Link className="block min-w-0">` wrapping
 * `<span className="... text-primary hover:text-primary/70 ...">`. The LINK has
 * no colour, no underline and no weight of its own; the SPAN carries the hover.
 *
 * `.sb-sf a { color: inherit }` already neutralises the parent theme's `a` at
 * REST -- but there was no hover variant, so the parent theme's `a:hover`
 * (#da291c with an underline) took over on both surfaces, and nothing set an
 * outline at all. Measured with matched.py: `outline-style` returned ZERO rules,
 * so the catalog's 25 Product links had no focus indicator whatsoever, and the
 * PDP fell back to the UA ring -- the two surfaces differing in the focus state
 * while matching at rest, which is why four rounds of parity testing passed.
 *
 * So: pin the link inert in every state, put the hover on the heading span where
 * the component puts it, and give the link the catalog's own focus ring.
 * ------------------------------------------------------------------------- */
.sb-sf [data-sb-sf-instock] tbody a,
.sb-sf [data-sb-sf-instock] tbody a:hover,
.sb-sf [data-sb-sf-instock] tbody a:focus,
.sb-sf [data-sb-sf-instock] tbody a:active {
	color: inherit;
	text-decoration: none;
}

/*
 * `.sb-sf-lot-condition`, NOT `.font-heading` (critic 9, F1).
 *
 * I copied this rule from the grouped table, where the title DOES carry
 * `.font-heading`. The in-stock condition span does not -- its live class list
 * is `sb-sf-lot-condition font-bold text-primary hover:text-accent` -- so the
 * rule matched nothing and the markup's own `hover:text-accent` won, hovering
 * the link ORANGE on both surfaces where Index.tsx L957 says
 * `hover:text-primary/70`.
 *
 * Parity held throughout, because both surfaces were equally wrong. The third
 * time this pass a fix has been bound to a class the element does not have.
 */
.sb-sf [data-sb-sf-instock] tbody a:hover .sb-sf-lot-condition,
.sb-sf [data-sb-sf-instock] tbody a:hover .font-heading {
	color: rgba(7, 3, 140, 0.7) !important;   /* hover:text-primary/70 */
}

.sb-sf [data-sb-sf-instock] tbody a:focus-visible {
	outline: 2px solid #07038c;         /* --ring 242 96% 28% */
	outline-offset: 2px;
	border-radius: 2px;
}


/*
 * Lot # and Patient ID are `text-muted-foreground` in Index.tsx (critic 9, F4).
 *
 * `tbody td { color: #141d2e !important }` was painting every cell the
 * foreground colour, and `.text-muted-foreground` is not in this theme's
 * hand-written Tailwind subset, so the utility the markup carries had nothing
 * behind it -- the sixth finding this pass from that subset.
 *
 * Targeted by column position because neither cell has a class of its own. The
 * colgroup order is asserted by qa/xf_parity.py and by the 24-width check, so a
 * column inserted before these would fail a gate rather than silently recolour
 * the wrong cell.
 */
/*
 * ONLY Lot # is muted. Column 3 (Patient ID) is not.
 *
 * An earlier round muted both, reading them as a pair of identifier columns.
 * product-detail.html -- the export that actually carries this table -- spells
 * them out differently:
 *
 *   Lot #       td class="... text-muted-foreground"
 *   Patient ID  td class="... text-ellipsis text-foreground"
 *
 * and every column to the right of Patient ID is text-foreground too. So the
 * mute stops at column 2. Patient ID now comes from the markup, which
 * inc/product-catalog-sf-render.php emits as text-foreground; it only needed
 * this `!important` to stop overriding it.
 */
.sb-sf [data-sb-sf-instock] tbody td:nth-child(2) {
	color: #647690 !important;                /* --muted-foreground 216 18% 48% */
}


/*
 * The In Stock Samples heading carries its lot count on the same line
 * (01-product-page.md section 6). The reference is a baseline-aligned flex row
 * with a 12px gap and the count at 14px/600 in --muted-foreground:
 *
 *     <h2>In Stock Samples</h2><span>1 sample</span>
 *
 * The 16px below the row is the title's own margin, which is left alone: it is
 * set by a (3,5,3) selector further up this file, and re-stating that whole
 * prefix here just to move the margin onto the wrapper would buy nothing --
 * inside a flex row the gap below the row is the same either way.
 */
.sb-sf-panel-head {
	display: flex;
	align-items: baseline;
	column-gap: 12px;
	flex-wrap: wrap;
}

.sb-sf-panel-count {
	font-size: 14px;
	line-height: 20px;
	font-weight: 600;
	color: #647690;                           /* --muted-foreground 216 18% 48% */
	font-family: Inter, system-ui, sans-serif;
	white-space: nowrap;
}


/* ==========================================================================
   v5 surface 1 -- the read-only critic's findings on the shared table
   --------------------------------------------------------------------------
   Both in-stock surfaces share this file, so these move together -- which is
   what Brian's standing requirement asks for.
   ========================================================================== */

/*
 * F12 WITHDRAWN -- the tight rows are Brian's, not a defect.
 *
 * The critic measured the header row at 29px and body rows at 41px against the
 * reference's 37px and 49px, and I changed them to match the reference. That
 * reversed an explicit instruction: verify_all.py records it as a "DELIBERATE
 * DEVIATION from the v3 export, on Brian's instruction of 14 Sep ('table needs
 * to be tight like in design')" -- and the v3 export measured the same 6px/8px
 * padding and 49px rows the v5 reference does. So the design file has always
 * said 49px and Brian has twice said tighter.
 *
 * Reverted, and the two v4 checks that caught me (`cell padding (tightened)`
 * and `row height (tightened)`) are left exactly as they are. A gate that fails
 * when someone quietly undoes a decision is the gate working.
 */

/*
 * F16: the filter pills are the reference's size -- 30px tall on 6px/12px
 * padding (`px-3 py-1.5`), not 26px on 2px/8px. Nine pills at 4px narrower each
 * read as a visibly more cramped row than the approved render.
 */
.sb-sf-filter-bar__grid > details.sb-sf-pill > summary {
	padding: 6px 12px !important;
}

/*
 * F9: the "N lots available" line. The PRODUCT page already matches the
 * reference here -- 12px rgb(20,29,46) -- and the CATALOG is the deviant at
 * 13px rgb(100,118,144). So the catalog moves to the product page's value, not
 * the other way round.
 */
.sb-sf-toolbar-meta [data-sb-panel-count] {
	font-size: 12px !important;
	line-height: 16px;
	color: #141d2e !important;
}


/*
 * v5 surface 2 -- the All Products count sits on its own line, right-aligned,
 * between the filter pills and the table header. Measured on
 * html/catalog-home.html: the pill row ends at y=6 and "71 products" is at
 * y=338, hard right at x=1343.
 */
.sb-sf-filter-bar--catalog .sb-sf-filter-bar__countrow {
	display: flex;
	justify-content: flex-end;
	padding: 8px 10px 0;
}

/* =====================================================================
 * V6 CRITIC ROUND — catalog / inventory table.
 * Measured against qa/_design_v5/html/product-detail.html, which is the
 * export that actually carries CatalogInventoryTable (catalog-home.html
 * captures the card view and has no <table> in it at all).
 * ===================================================================== */

/*
 * The column headers carry no tracking class in the design --
 * `text-xs font-bold uppercase text-table-header-foreground`, and that is the
 * whole list. Live spread them 0.3px, which at 12px uppercase across 24
 * columns is the difference between the header row fitting and not.
 */
.sb-sf .sb-sf-th button,
.sb-sf thead th button,
.sb-sf thead th {
	letter-spacing: normal;
}

/*
 * "Results per page" belongs to the RIGHT of the footer, next to the pager.
 *
 * TablePagination.tsx puts the showing-line and the controls in two groups:
 *
 *   <p class="text-xs text-muted-foreground order-2 sm:order-1">Showing …</p>
 *   <div class="flex items-center gap-3 order-1 sm:order-2">
 *       <div class="flex items-center gap-2">Results per page <Select/></div>
 *       … page buttons …
 *   </div>
 *
 * Live had three flex children under `space-between`, so the per-page control
 * was pushed to the middle of a 1390px bar -- floating at x=599 with nothing
 * either side of it, while the design has it at x=1106 hard against the pager.
 */
.sb-sf .sb-sf-panel-foot .sb-sf-per-page {
	flex: 0 0 auto;
	margin-left: auto;
}
.sb-sf .sb-sf-panel-foot [data-sb-sf-pagination] {
	margin-top: 0;
	margin-left: 0;
}

/* The design's per-page control is a filled button, not a bare native select:
   `bg-muted` with `px-3 py-2`. */
.sb-sf .sb-sf-per-page__select {
	height: 32px;
	min-height: 32px;
	padding: 8px 30px 8px 12px;
	background-color: rgb(246, 247, 249);
}

/* Prev / next are `text-sm font-medium` in the design, not 12px/600. */
.sb-sf .sb-sf-page--nav {
	font-size: 14px;
	font-weight: 500;
}

/* =====================================================================
 * V7 CRITIC ROUND — catalog.
 * ===================================================================== */

/*
 * `font-bold`, not `font-extrabold`.
 *
 * Index.tsx: `font-heading text-3xl sm:text-4xl font-bold tracking-tight
 * text-primary`. The product page's H1 IS extrabold (ProductDetail.tsx says
 * `font-extrabold`), which is presumably how 800 got copied onto this one --
 * but the two pages differ here on purpose.
 */
/* The catalog H1 is corrected in the markup instead
   (inc/product-catalog-sf-render.php): it carries Tailwind utilities and no
   `sb-catalog-hero__title` class at all, so this selector matched nothing. */

/* The subtitle link's weight is corrected in sample-finder-catalog.css, which
   holds the (0,2,0) rule that wins. A bare class written here could not reach
   it -- the same trap that cost four fixes in the v6 round. */

/*
 * The filter pills' chevrons are `h-3.5 w-3.5` (14px) in FilterBar.tsx's
 * PillButton, measured at 14x14 in the export. Live drew them at 12.
 *
 * NOTE for the next round: the SORT chevrons in the table header are a
 * different control and ARE 12px (`h-3 w-3` in CatalogInventoryTable.tsx).
 * A critic reported those as too small by reading the export, where shadcn's
 * `Button` compiles `[&_svg]:size-4` and overrides the class. Live is right.
 */
.sb-sf .sb-sf-pill svg,
.sb-sf .sb-sf-pill__chev {
	width: 14px;
	height: 14px;
}

/* `SortHeader` renders inactive columns at `opacity-90`; the Action cell is
   opacity-90 unconditionally. Live painted them at full strength. */
.sb-sf .sb-sf-group-head .sb-sf-sort:not(.is-active),
.sb-sf .sb-sf-group-head__action {
	opacity: 0.9;
}

/*
 * LOT # FILTER — no styles of its own any more.
 *
 * It began as a bespoke text input with hand-written styling here. Brian asked
 * for it to "look like the comorbidities filter", so it is now rendered by
 * sb_sf_render_filter_pill() with `search_only` set, and it inherits the pill
 * styles above like every other facet. The rules that used to live here
 * (.sb-sf-lotfilter, .sb-sf-lotfilter__input) styled markup that is no longer
 * emitted, so they are deleted rather than left to rot.
 *
 * The filtering itself is unchanged and still server-side: see
 * sb_sf_lot_number_values() and sb_sf_apply_lot_filters_to_args().
 */

/*
 * EXPORT FORM CONSENT ROW — Brian, 18 Sep: "This on /products makes the consent
 * text and checkbox wrap to different lines."
 *
 * Read off the live modal rather than guessed, because HubSpot injects this form
 * at runtime and earlier fixes here shipped selectors that matched nothing:
 *
 *     div.hs_LEGAL_CONSENT...  display:block
 *       ul.inputs-list         display:block
 *         li.hs-form-booleancheckbox        display:list-item
 *           label.hs-form-booleancheckbox-display  display:inline-block
 *             input.hs-input[type=checkbox]        display:BLOCK   <-- the bug
 *             span                                 display:inline
 *
 * A block-level checkbox takes a line to itself, so the box sits centred above
 * its own label. Nothing is wrapping; the input is simply not inline.
 *
 * The label becomes a flex row so the box and the text share a baseline and the
 * text block can wrap normally beside it without sliding under the box.
 *
 * Scoped by body class as well as by shell: the same modal renders on the
 * catalog and on product pages, and .sb-quote-hubspot-shell alone was not worth
 * relying on for markup this file does not own.
 */
.sb-quote-hubspot-shell .hs-form-booleancheckbox-display,
body.sb-catalog-archive .hs-form-booleancheckbox-display,
body.single-product .hs-form-booleancheckbox-display {
	display: flex !important;
	align-items: flex-start;
	gap: 8px;
	text-align: left;
	margin: 0;
}

.sb-quote-hubspot-shell .hs-form-booleancheckbox-display > input[type="checkbox"],
body.sb-catalog-archive .hs-form-booleancheckbox-display > input[type="checkbox"],
body.single-product .hs-form-booleancheckbox-display > input[type="checkbox"] {
	display: inline-block !important;
	flex: 0 0 auto;
	width: 16px;
	height: 16px;
	/* Nudged to sit on the first text line rather than the box's top edge. */
	margin: 2px 0 0 !important;
}

.sb-quote-hubspot-shell .hs-form-booleancheckbox-display > span,
body.sb-catalog-archive .hs-form-booleancheckbox-display > span,
body.single-product .hs-form-booleancheckbox-display > span {
	display: block;
	margin: 0 !important;
	flex: 1 1 auto;
	min-width: 0;
}

/* The list wrapper carries a browser default bullet and indent it never wanted. */
.sb-quote-hubspot-shell ul.inputs-list,
body.sb-catalog-archive ul.inputs-list,
body.single-product ul.inputs-list {
	list-style: none;
	margin: 0;
	padding: 0;
}

.sb-quote-hubspot-shell li.hs-form-booleancheckbox,
body.sb-catalog-archive li.hs-form-booleancheckbox,
body.single-product li.hs-form-booleancheckbox {
	display: block;
	list-style: none;
}

/*
 * INVENTORY TABLE SCROLLBARS (AC-CAT-02).
 *
 * "a grabbable horizontal scrollbar ABOVE the table and a THICKER one BELOW it
 * ... both stay visible without hovering and are wide enough to grab easily."
 *
 * Measured before changing anything, the two were the wrong way round:
 *
 *     top     track 6px, thumb 6px
 *     bottom  track 6px, thumb 3px   <- thinner, and 3px is not grabbable
 *
 * The bottom bar is the primary one in the design, so it gets the height. The
 * top bar stays slim: it sits under the sticky header and a thick bar there eats
 * table rows.
 *
 * Both tracks are still shown/hidden by bindScrollbar() according to whether the
 * table actually overflows -- that is not a hover gate, and a bar that cannot
 * scroll anything should not be advertised.
 */
.sb-sf .sb-sf-hscroll--bottom {
	height: 14px !important;
	padding: 3px 8px !important;
}

.sb-sf .sb-sf-hscroll--bottom .sb-sf-hscroll__thumb {
	height: 8px !important;
	min-width: 48px;
	border-radius: 999px;
	background: rgba(100, 118, 144, 0.65);
	cursor: grab;
}

.sb-sf .sb-sf-hscroll--bottom .sb-sf-hscroll__thumb:hover {
	background: rgba(100, 118, 144, 0.85);
}

.sb-sf .sb-sf-hscroll--bottom .sb-sf-hscroll__thumb:active {
	background: rgba(7, 3, 140, 0.8);
	cursor: grabbing;
}

/* The top bar keeps its slim profile but becomes easier to hit. */
.sb-sf .sb-sf-hscroll[data-sb-sf-topscroll] .sb-sf-hscroll__thumb {
	min-width: 48px;
	cursor: grab;
}

.sb-sf .sb-sf-hscroll[data-sb-sf-topscroll] .sb-sf-hscroll__thumb:active {
	cursor: grabbing;
}

/*
 * ONE SCROLLBAR, NOT TWO (AC-PD-02 / AC-CAT-02, 22 Sep).
 *
 * "The In Stock Samples table shows exactly ONE horizontal scrollbar ... The
 *  browser's native horizontal scrollbar directly under the table rows is
 *  hidden."
 *
 * THIS REVERSES THE 21 SEP CRITERIA, which asked for two — a rail above the
 * table and a thicker one below — and which were built and verified a day
 * earlier. The top rail is hidden rather than deleted: the markup and its JS
 * sync in js/sample-finder.js stay intact, so restoring it is one rule, and
 * bindScrollbar() keeps working unchanged because it still finds both tracks.
 *
 * The native bar was already hidden (`scrollbar-width: none` plus a zero-height
 * ::-webkit-scrollbar:horizontal on .sb-sf-scroller), so that clause of the
 * criterion needed nothing.
 *
 * NOT DONE, deliberately: "positioned below the pagination row". The remaining
 * rail renders inside the table wrapper and the pagination renders in
 * .sb-sf-panel-foot three levels shallower, so they are not siblings and no
 * `order` can move one past the other. Repositioning it means moving the markup
 * out of the table wrapper while keeping it inside [data-sb-sf-instock], which
 * is where bindScrollbar() looks for it — a restructure of the table's scroll
 * plumbing, not a style change, and not worth risking the column sync for a
 * position clause. Flagged for Brian.
 */
.sb-sf .sb-sf-hscroll[data-sb-sf-topscroll] {
	display: none !important;
}


/*
 * THE CATALOG TABLE NEEDS MORE THAN 768px.
 *
 * The row is `grid-cols-1 md:grid-cols-[2fr,110px,1.1fr,1.3fr,130px,150px]` and
 * the header is `hidden md:grid`, so the six-column table engaged at exactly the
 * width where it stops fitting. Measured at 768 the PRODUCT column resolved to
 * 86px -- narrower than the fixed 110px Available Lots column -- and product
 * names shattered character by character ("Hea/lthy/PBM/C"). Worse, the row's
 * parent is overflow-x:hidden with scrollWidth 734 against clientWidth 718, so
 * 16px of every row was clipped with no scrollbar to reach it.
 *
 * The stacked single-column layout already exists for phones and reads fine on a
 * tablet, so it now runs to 1023px and the table starts at 1024, which is the
 * narrowest width the six columns actually fit.
 */
@media (max-width: 1023px) {
	.sb-sf .sb-sf-catalog-head {
		display: none !important;
	}

	.sb-sf .sb-sf-catalog-row {
		grid-template-columns: minmax(0, 1fr) !important;
	}
}
