/**
 * Studio SRP — mobile-first stylesheet.
 *
 * Pairs with template/srp/studio/studio.php + studio-js.php. Everything is
 * scoped under .da-srp (page) / .srp-studio-card (cards, also used on the
 * flip faces) so nothing leaks into the theme.
 *
 * Config-driven values arrive as --srp-* custom properties emitted by
 * srp_studio_style_tokens() (modules/studio-config.php) — the same token
 * names the Nexus WP studio preview reads.
 *
 * ── Responsive convention ─────────────────────────────────────────────────
 * Mobile-first: base rules target the smallest screen; larger screens are
 * layered on with `min-width` queries only. Breakpoints (match the studio
 * preview / Tailwind scale):
 *
 *   640px  1 → 2 column grid; footer goes side-by-side
 *   768px  the mobile ⇄ desktop line — header layout, page/header background,
 *          and the da-mobile-only / da-desktop-only visibility utilities
 *   992px  sidebar becomes a static column (below it, it's an off-canvas
 *          drawer); the header is already in its desktop form from 768
 *   1280px 2 → 3 column grid
 *
 * NOTE the header and the sidebar switch at DIFFERENT widths: 768 → 991 is a
 * tablet tier with the desktop header but the sidebar still a drawer.
 *
 * Two `max-width` blocks are intentional exceptions, not desktop-first debt:
 *   - the mobile header (search box overlays the row and animates in) is a
 *     self-contained mobile-only interaction; expressing it as a min-width
 *     reset would duplicate the tablet+desktop header and needs the
 *     .is-search-open state rules, which out-specificity a plain reset.
 *   - .da-desktop-only / .da-mobile-only are a symmetric show-on-one-viewport
 *     pair (the config's mobileOnly/desktopOnly visibility) — a max-width half
 *     is correct there, not a smell.
 *
 * The bottom section is a curated utility-class subset (Tailwind-compatible
 * names) so studio-authored Mustache templates (vehicle titles, pricing
 * blocks) render styled on WordPress. Templates should stick to these
 * classes or plain inline styles.
 */

/* ── Page scaffold ─────────────────────────────────────────────────── */
.da-srp {
	/* Horizontal inset lives on the CHILDREN (--srp-gutter), not here, so the
	   sticky header can run full-bleed edge-to-edge while its content, the body
	   and the disclaimer all stay aligned to the same gutter. Only the bottom
	   space stays on the container. Was `padding: 0 12px 24px`, which inset the
	   header too and left the page background showing in a gutter beside it. */
	--srp-gutter: 16px;
	/* Site nav clearance —
	   Resolution order, first one that exists wins:
	     1. --srp-header-offset — MEASURED at runtime by studio/js/interactions.php
	     2. --mobile-header-height / --header-height — the Redux options the
	        framework header.php publishes on :root. First-paint value only, so
	        the bar isn't sitting at 0
	     3. 0px — theme publishes neither (non-framework header). */
	--srp-nav-clearance: var(--srp-header-offset, var(--mobile-header-height, 0px));
	margin: 0 auto;
	padding: 0 0 24px;
	/* Mobile-first: the base is the mobile background (which falls back to the
	   shared --srp-bg when a dealer hasn't set a distinct mobile colour); the
	   desktop background is layered on at the 768 breakpoint below. */
	background: var(--srp-bg-mobile, var(--srp-bg, transparent));
	font-size: 15px;
	line-height: 1.4;
}

@media (min-width: 768px) {
	.da-srp {
		background: var(--srp-bg, transparent);
		/* Same chain, desktop Redux option. 768px is the framework's own
		   header breakpoint — _subnav-tpl.php and top-nav.php both switch
		   there — not the 992px the SRP sidebar drawer uses. */
		--srp-nav-clearance: var(--srp-header-offset, var(--header-height, 0px));
	}
	.da-srp-header { background: var(--srp-header-bg, #fff); }
}

.da-srp *, .da-srp *::before, .da-srp *::after { box-sizing: border-box; }

/* Top banner — first thing in the results column (sidebar unaffected).
   Dealer banner markup (Redux top-banner-* content, shortcodes) often
   carries fixed inline sizes — force everything to fit and scale with
   the column, like the legacy SRP rendered it. */
.da-srp-top-banner { margin: 0 0 16px; overflow: hidden; }

.da-srp-top-banner * {
	max-width: 100% !important;
	min-width: 0 !important;
	box-sizing: border-box;
}

/* …except slick's own scaffolding. The [dv-offers …] shortcodes drop a slick
   carousel in here, and slick lays one out with INLINE PIXEL widths:
   slick.min.js does slideTrack.width(slideWidth * slideCount), making the track
   deliberately far wider than the column, then translate3d()s it sideways to
   the current slide (already offset past the prepended clones when
   infinite:true).

   The blanket max-width above clamps that track to the column, so the floated
   slides wrap instead of sitting in a row and the negative translate drags them
   out of .slick-list's overflow:hidden viewport. The carousel initialises,
   keeps its .slick-initialized class, throws no error — and paints nothing
   while still reserving height. A blank banner, not a squashed one.

   Slide CONTENT is still clamped by the rule above, and .slick-list's own
   overflow keeps the widened track from escaping the column. */
.da-srp-top-banner .slick-list,
.da-srp-top-banner .slick-track,
.da-srp-top-banner .slick-slide {
	max-width: none !important;
}

/* slick-theme parks the arrows at left/right -25px — outside the box this
   wrapper clips — while the shortcode asks for arrows:true and gives them a
   solid dark background. Bring them inside rather than dropping the wrapper's
   overflow, which is what stops oversized dealer banner markup escaping the
   results column. */
.da-srp-top-banner .slick-prev { left: 10px; }
.da-srp-top-banner .slick-next { right: 10px; }

.da-srp-top-banner img,
.da-srp-top-banner svg {
	width: 100% !important;
	height: auto !important;
	display: block;
}

.da-srp-top-banner video,
.da-srp-top-banner iframe {
	width: 100% !important;
	display: block;
}

/* Dealers often wrap content in the legacy .srp-top-banner box — neutralize
   its padding/border/margins inside the studio column */
.da-srp-top-banner .srp-top-banner { padding: 0; border: none; margin: 0; background: transparent; }

/* ── Page H1 ───────────────────────────────────────────────────────────
   Sits between the top banner and the results grid. Deliberately small —
   it is the SEO/document heading, not a display headline, and its text is
   rebuilt from the active refinements on every render (js/seo.php). Theme
   stylesheets style bare h1 heavily, so scope to .da-srp to out-specify.
   The hiddenH1 config option adds an inline clip style that wins over this. */
.da-srp .da-srp-h1 {
	margin: 0 0 16px;
	font-size: 24px;
	line-height: 1.25;
}

/* ── Header ────────────────────────────────────────────────────────── */
.da-srp-header {
	position: sticky;
	/* Clears the theme's fixed nav stack — see --srp-nav-clearance on .da-srp
	   for how the value is resolved. NOTE: sticky pins as soon as the element's
	   natural position is above this value, so a value LARGER than the actual
	   nav height pushes the header down from page load; that's why the runtime
	   measure takes max(bottom edges) rather than summing heights. */
	top: var(--srp-nav-clearance, 0px);
	/* Must beat everything that scrolls under it — the desktop sidebar and
	   results are z-index 1 so they slide BEHIND the stuck header. */
	z-index: 60;
	/* Mobile-first: base is the mobile header background (falls back to the
	   shared --srp-header-bg); the 768 breakpoint above restores the desktop
	   background. Widgets inside carry their own white boxes. */
	background: var(--srp-header-bg-mobile, var(--srp-header-bg, #fff));
	/* Full-bleed bar (the element spans the full-width container); the gutter
	   insets only the CONTENT, so the controls line up with the body below. */
	padding: 12px var(--srp-gutter, 16px);
	margin-bottom: 16px;
}

.da-srp-header-row {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	align-items: center;
}

/* min-height matches the stats pill's rendered height (24px, h-6) so the
   row doesn't collapse vertically when the widget is off (statsTopEnabled
   false) or when no filters are active (Clear Filters/chips are both
   hidden then) — height only; content still shifts left to fill the freed
   width. */
.da-srp-header-row-2 { margin-top: 8px; min-height: 24px; }

/* Below 992px the sidebar is an off-canvas drawer (see .da-srp-sidebar),
   so stats/Clear Filters/chips move there instead — mirrors Nexus hiding
   the whole stats+refinements row below its own drawer breakpoint. See
   .da-srp-sidebar-refinements for the mobile equivalent. */
@media (max-width: 991px) {
	.da-srp-header-row-2 { display: none; }
}

/* Header divider — mirrors Nexus SearchNADA.tsx: an absolutely positioned
   strip pinned to the header's bottom edge (translateY(100%) so it doesn't
   add to the header's own height/sticky box), overridden per-dealer by the
   headerDivider config rules srp_studio_style_tokens() emits into the inline
   <style> block (modules/studio-config.php). Default here matches the TSX
   fallback when no headerBackground color is configured: a soft white fade,
   as if the cards scroll away under the sticky header.
   - type "fade" (default): gradient only, this rule is enough on its own.
   - type "line": PHP overrides this to a headerBackground-colored strip with
     top padding, and un-hides .da-srp-header-divider-line as the actual bar. */
.da-srp-header-divider {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 24px;
	transform: translateY(100%);
	pointer-events: none;
	/* Stops hit transparent at 70% (not 100%) so the fade is fully gone
	   before its last pixel — a plain 3-stop gradient only reaches true
	   transparency at the very edge, which read as a faint tint bleeding
	   onto the card row underneath. */
	background: linear-gradient(to bottom, #fff 0%, rgba(255, 255, 255, .6) 45%, transparent 70%);
}

.da-srp-header-divider-line { display: none; width: 100%; }

/* Condition toggle — count-first segments, active segment uses the
   configured activeColor (falls back to --accent, then dark). Spacing/type
   mirrors Nexus ConditionToggle.tsx exactly: outer px-1 py-1 (4px) + gap-2
   (8px); each segment h-8 (32px) + px-8 (32px) + inner gap-2 (8px), label
   text-sm (14px), count ambient text-base (16px, unbolded until active —
   the whole Link goes font-semibold on the active segment, not just the
   count). flex-1 on each segment (matched to a FIXED-width outer, not
   content-sized) is what stops the New/Used counts shifting the layout as
   they load in — the segments split the fixed width evenly regardless of
   digit count. That same fixed width (320px, Tailwind w-80) is also why it
   lines up with the stats pill below it, which is fixed to the same width. */
/* Hidden below 992px — see the min-width block after this one. Mobile-first,
   so the base state is the hidden one and the desktop query reveals it. */
.da-srp-condition {
	display: none;
	gap: 8px;
	background: #f3f4f6;
	border: 1px solid #e5e7eb;
	border-radius: var(--srp-condition-radius, 8px);
	padding: 4px;
	flex-shrink: 0;
}

.da-srp-condition-btn {
	display: flex;
	flex: 1;
	align-items: center;
	justify-content: center;
	gap: 8px;
	height: 32px;
	padding: 0 32px;
	border-radius: calc(var(--srp-condition-radius, 8px) - 3px);
	font-size: 14px;
	font-weight: 400;
	text-decoration: none;
	color: #4b5563;
	white-space: nowrap;
}

.da-srp-condition-btn b { font-size: 16px; font-weight: 400; }

.da-srp-condition-btn.is-active {
	background: var(--srp-condition-active, var(--accent, #111827));
	color: #fff;
	font-weight: 600;
}

/* Appears at 992px, the same line where the sidebar stops being an off-canvas
   drawer and becomes a static column (.da-srp-sidebar). Between 768 and 991 the
   header is already in its desktop form but filters are still behind the
   Filters button, so the row is [Filters] [search] [Sort] [pager] — the 320px
   New/Used toggle would crowd it, and New/Used is reachable from the nav.
   320px = w-80, matching the sidebar and the stats pill below it. */
@media (min-width: 992px) {
	.da-srp-condition { display: flex; width: 320px; }
}

/* Search box — icon inside on the left, radius from config */
.da-srp-searchbox { flex: 1 1 200px; min-width: 0; position: relative; }

.da-srp-search-icon {
	position: absolute;
	left: 13px;
	top: 50%;
	transform: translateY(-50%);
	color: #6b7280;
	font-size: 14px;
	z-index: 2;
	pointer-events: none;
}

.da-srp .ais-SearchBox-form { position: relative; display: block; }

.da-srp .ais-SearchBox-input {
	width: 100%;
	/* h-10. Was padding-driven and landed at 38px — a hair short of every
	   other control in the row. Horizontal padding still clears the leading
	   icon and the trailing reset/spinner. */
	height: 40px;
	padding: 0 38px;
	border: 1px solid #d1d5db;
	border-radius: var(--srp-searchbox-radius, 8px);
	font-size: 15px;
	background: #fff;
	appearance: none;
}

.da-srp .ais-SearchBox-input:focus { outline: 2px solid var(--srp-filters-accent, #2563eb); outline-offset: -1px; }

.da-srp .ais-SearchBox-submit { display: none; } /* icon rendered by the template instead */

/* Chrome/Safari draw their own clear "×" inside input[type="search"] */
.da-srp .ais-SearchBox-input::-webkit-search-cancel-button,
.da-srp .ais-SearchBox-input::-webkit-search-decoration {
	display: none;
}

.da-srp .ais-SearchBox-reset,
.da-srp .ais-SearchBox-loadingIndicator {
	position: absolute;
	right: 10px;
	top: 50%;
	transform: translateY(-50%);
	background: none;
	border: none;
	cursor: pointer;
	padding: 4px;
}

.da-srp .ais-SearchBox-reset svg { width: 14px; height: 14px; fill: #6b7280; }

/* Sort — mirrors nada sort-by.tsx: the trigger always reads "Sort" (never
   the selected option's own label), which is what keeps it a fixed size —
   a real <select> showing its current value sizes to that value's text, so
   "Most Relevant" made the box visibly bigger than the Filters button next
   to it no matter what CSS padding/height was set on it. The real <select>
   still does the work (options, native picker, change events — see
   renderSortSelect in widgets-header.php) but sits invisible (opacity:0)
   over the fixed-size label; a dot appears next to "Sort" once the
   refinement isn't the default (.has-active-sort, toggled in the same JS). */
.da-srp-sort {
	position: relative;
	flex-shrink: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	height: 40px; /* h-10 */
	border: 1px solid #d1d5db;
	border-radius: var(--srp-sortby-radius, 8px);
	background: #fff;
	padding: 0 16px;
}

.da-srp-sort > i { color: #374151; font-size: 13px; pointer-events: none; }

.da-srp-sort-label {
	font-size: 14px;
	font-weight: 600;
	color: #111827;
	white-space: nowrap;
	pointer-events: none;
}

/* opacity, not display — the dot's box (+ its gap in the flex row) is
   always reserved, so toggling has-active-sort only changes what's visible
   in that space instead of adding/removing width and shifting "Sort". */
.da-srp-sort-dot {
	width: 6px;
	height: 6px;
	flex-shrink: 0;
	border-radius: 50%;
	background: #000;
	opacity: 0;
	pointer-events: none;
}

.da-srp-sort.has-active-sort .da-srp-sort-dot { opacity: 1; }

/* Real control: invisible, but still the actual clickable/focusable element
   (native picker on mobile, native dropdown on desktop) — sized to cover
   the whole button so a tap/click anywhere on it opens the picker. */
.da-srp-sort select {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	margin: 0;
	padding: 0;
	border: none;
	background: transparent;
	opacity: 0;
	cursor: pointer;
	appearance: none;
}

.da-srp-sort select:focus { outline: none; }
.da-srp-sort select:focus-visible ~ .da-srp-sort-label { outline: 2px solid #000; outline-offset: 2px; }

/* Compact pager: ‹ Page X of Y › (same widget in header and footer) */
.da-srp-pager-box {
	flex-shrink: 0;
	display: flex;
	align-items: center;
	gap: 4px;
	height: 40px; /* h-10 */
	border: 1px solid #d1d5db;
	border-radius: var(--srp-pagination-radius, 8px);
	background: #fff;
	padding: 0 8px;
}

.da-srp-pager-btn {
	background: none;
	border: none;
	cursor: pointer;
	color: #6b7280;
	padding: 5px 8px;
	font-size: 13px;
	border-radius: 4px;
}

.da-srp-pager-btn:hover:not(:disabled) { background: #f3f4f6; color: #111827; }
.da-srp-pager-btn:disabled { opacity: .35; cursor: default; }

.da-srp-pager-label { font-size: 13px; font-weight: 600; white-space: nowrap; padding: 0 2px; }

/* Accent numbers (stats + pager) */
.da-srp .da-srp-accent { color: var(--srp-stats-accent, var(--srp-pagination-accent, var(--accent, #111827))); font-weight: 700; font-style: normal; }

/* Filter toggle (mobile) */
.da-srp-filter-toggle {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 6px;
	height: 40px; /* h-10 — was padding-driven, so it rendered 34px here */
	padding: 0 16px;
	border: 1px solid #d1d5db;
	border-radius: 6px;
	background: #fff !important;
	color: #111827 !important;
	font-size: 14px;
	font-weight: 600;
	cursor: pointer;
}

/* Same reserved-space dot as .da-srp-sort-dot (opacity, not display) — its
   box is always in the flex row so toggling has-active-filters never
   resizes/shifts the button or the "Filters" label next to it. */
.da-srp-filter-dot {
	width: 6px;
	height: 6px;
	flex-shrink: 0;
	border-radius: 50%;
	background: #000;
	opacity: 0;
	pointer-events: none;
}

.da-srp-filter-toggle.has-active-filters .da-srp-filter-dot { opacity: 1; }

/* Circular search trigger + overlay close (mobile-only, hidden ≥768px) */
.da-srp-search-toggle {
	display: none;
	width: 40px;
	height: 40px;
	flex-shrink: 0;
	align-items: center;
	justify-content: center;
	border: 1px solid #d1d5db;
	border-radius: 50%;
	background: #fff !important;
	color: #374151 !important;
	font-size: 15px;
	cursor: pointer;
}

.da-srp-search-close {
	display: none;
	position: absolute;
	right: 8px;
	top: 50%;
	transform: translateY(-50%);
	background: none !important;
	border: none !important;
	color: #374151 !important;
	font-size: 17px;
	cursor: pointer;
	padding: 6px;
	z-index: 3;
}

/* ── Mobile header: [Filters] [Sort] [○ search] — search expands over ── */
@media (max-width: 767px) {
	.da-srp-header-row { position: relative; }

	/* Equal-width, matching the search circle (.da-srp-sort carries its height
	   unconditionally now — see its base rule — so only filter-toggle needs it
	   here). */
	.da-srp-filter-toggle, .da-srp-sort { flex: 1; }
	.da-srp-filter-toggle { order: 1; }
	.da-srp-sort { order: 2; }
	.da-srp-search-toggle { display: flex; order: 3; }
	.da-srp-pager-box#da-srp-pagination-top { display: none; }

	/* Search box hidden until opened, then overlays the whole row and
	   scales in from the right (mirrors nada searchbox.tsx) */
	.da-srp-searchbox {
		display: none;
		position: absolute;
		inset: 0;
		z-index: 5;
		background: #fff;
		transform: scaleX(0);
		opacity: 0;
		transform-origin: right;
		transition: transform .25s ease-out, opacity .25s ease-out;
	}

	.da-srp-header.is-search-open .da-srp-searchbox { display: block; }
	.da-srp-header.is-search-anim .da-srp-searchbox { transform: scaleX(1); opacity: 1; }

	/* No height override: the input carries a fixed 40px now, which is exactly
	   the height of the row this overlay covers. `height: 100%` used to be
	   needed when the input was padding-sized, but its containing block
	   (.ais-SearchBox-form) is auto-height, so a percentage resolves to auto
	   and would collapse the input to its line box. */
	.da-srp-header.is-search-open .da-srp-searchbox .ais-SearchBox-input {
		box-shadow: 0 2px 10px rgba(0, 0, 0, .12);
	}

	.da-srp-header.is-search-open .da-srp-search-close { display: block; }
	.da-srp-header.is-search-open .da-srp-searchbox .ais-SearchBox-reset { right: 36px; }
}

/* Stats pill: "Showing 1 - 16 of 437". Spacing mirrors the Nexus
   SRPStatsWidget call in SearchNADA.tsx (px="px-12" py="py-1" h="h-6"
   fontSize="text-sm"): 48px horizontal / 4px vertical padding, 24px
   fixed height, 14px text. */
.da-srp-stats {
	font-size: 14px;
	font-weight: 500;
	color: #374151;
	white-space: nowrap;
}

#da-srp-stats .ais-Stats,
#da-srp-stats-bottom .ais-Stats {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	height: 24px;
	border: 1px solid #d1d5db;
	border-radius: var(--srp-stats-radius, 8px);
	background: #fff;
	padding: 4px 48px;
}

/* Fixed width (320px, Tailwind w-80) so the top stats pill lines up with
   the condition toggle above it — both are content-agnostic boxes at this
   width in Nexus, not shrink-to-fit. Desktop only (768px+, where the
   condition toggle also becomes fixed-width) so mobile keeps shrinking to
   its text. */
@media (min-width: 768px) {
	#da-srp-stats .ais-Stats { width: 320px; }
}

.da-srp-clear { flex-shrink: 0; }

/* Chips: one PER refined value (built manually in widgets-header.php from
   the connectCurrentRefinements connector, not the currentRefinements
   widget) — white pill, black text, bordered so it reads against the
   white header background. Value only, no attribute label prefix. */
.da-srp-chips {
	display: flex;
	gap: 8px; /* gap-2 on the scroller */
	flex-wrap: nowrap;
	flex: 1;
	min-width: 0;
	/* Scrolls, but the bar itself is never drawn — React hides it with
	   [&::-webkit-scrollbar]:hidden + the two standards properties. */
	overflow-x: auto;
	scrollbar-width: none;
	-ms-overflow-style: none;
}

.da-srp-chips::-webkit-scrollbar { display: none; }

/* The chip itself IS the button (whole pill is the click target, not just
   the × glyph) — reset button UA styles explicitly so nothing (theme-wide
   button:hover/:focus rules, UA default appearance) can paint a background
   behind just the icon. */
/* Geometry is the shadcn Button, variant "outline" size "sm", as the desktop
   CurrentRefinements overrides it: `h-6 px-2 py-1 text-sm font-medium
   rounded-[5px]`. Note these are NOT pills in Nexus — 5px, the house radius. */
.da-srp-chip {
	appearance: none;
	display: flex;
	align-items: center;
	gap: 6px; /* gap-1.5, from size="sm" */
	flex-shrink: 0;
	height: 24px;
	background: #fff;
	border: 1px solid #d1d5db;
	border-radius: 5px;
	padding: 0 8px;
	font: inherit;
	font-size: 14px;
	font-weight: 500;
	color: #111827;
	white-space: nowrap;
	cursor: pointer;
	transition: background-color .15s ease;
}

.da-srp-chip:hover, .da-srp-chip:focus-visible { background: #f5f5f5; }

.da-srp-chip i { font-size: 16px; color: #6b7280; }

/* In the drawer the same chips are size="sm" WITHOUT the h-6/px-2 overrides
   and with `rounded-none`, so they're taller, wider and square. */
#da-srp-chips-mobile .da-srp-chip {
	height: 32px;
	padding: 0 12px;
	border-radius: 0;
}

#da-srp-chips-mobile .da-srp-chip i { font-size: 20px; }

/* ── Body layout: sidebar + results ──────────────────────────────────
   Carries the horizontal gutter that used to live on .da-srp, so the content
   below the full-bleed header keeps its inset (sidebar + hits on desktop, hits
   on mobile — the drawer sidebar is position:fixed and unaffected). */
/* gap is React's `mr-4` (16px) on the <aside>, not a design choice of ours. */
.da-srp-body { display: flex; gap: 16px; align-items: flex-start; padding: 0 var(--srp-gutter, 16px); }

.da-srp-results-wrap { flex: 1; min-width: 0; }

/* Sidebar: off-canvas drawer on mobile, static column ≥ 992px. z-index is
   1000 (not just above the SRP's own header at 60) because the theme's
   global nav (#navbarwrapper in globalStyle.css) is position:fixed with
   z-index:100 — the drawer used to match that exactly, so which one
   painted on top was a coin flip. 1000 clears it outright. */
.da-srp-sidebar {
	position: fixed;
	/* Was `inset: 0 auto 0 0` — the drawer ran the full viewport height, so its
	   "Filters" title/close row (.da-srp-sidebar-sticky, top: 0) opened UNDER
	   the theme's fixed nav on every dealer with one. Starts below the chrome
	   now, same clearance the sticky header uses; bottom: 0 keeps it filling
	   whatever height is left. The 992px block below resets all four for the
	   desktop static column. */
	top: var(--srp-nav-clearance, 0px);
	right: auto;
	bottom: 0;
	left: 0;
	/* Sheet's `w-[85vw] max-w-[320px] sm:max-w-[360px] md:max-w-[540px]` —
	   the wider tiers only ever apply between 640 and 991, since the drawer
	   stops existing at 992 (see the desktop block below). */
	width: min(320px, 85vw);
	z-index: 1000;
	background: #fff;
	/* SheetContent is `p-0`; the 16px inset belongs to the facet list
	   (`px-4 pb-4`). The sticky header and refinements bar cancel it with
	   their own -16px margins so they stay full-bleed. */
	padding: 0 16px 16px;
	overflow-y: auto;
	transform: translateX(-105%);
	transition: transform .25s ease;
	box-shadow: 2px 0 12px rgba(0, 0, 0, .15);
}

.da-srp-sidebar.is-open { transform: translateX(0); }

@media (min-width: 640px) { .da-srp-sidebar { width: min(360px, 85vw); } }
@media (min-width: 768px) { .da-srp-sidebar { width: min(540px, 85vw); } }

.da-srp-sidebar-backdrop {
	display: none;
	position: fixed;
	inset: 0;
	background: rgba(0, 0, 0, .4);
	z-index: 999;
}

.da-srp-sidebar-backdrop.is-visible { display: block; }
body.da-srp-drawer-open { overflow: hidden; }

/* Pins the "Filters" title/close and (once active) the Clear Filters/chips
   bar together as one unit while the facets below scroll — mirrors
   mobile-filter-drawer.tsx's sticky SheetHeader + CurrentRefinements bar.
   Desktop unsets this (992px query below): the static sidebar column has no
   title/close row to pin, and Clear Filters/chips live in the header there. */
.da-srp-sidebar-sticky {
	position: sticky;
	top: 0;
	z-index: 3;
	background: #fff;
}

/* SheetHeader: `px-4 py-3 border-b border-gray-200`. The negative margin
   cancels the drawer's own 16px inset so the hairline spans edge to edge. */
.da-srp-sidebar-head {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin: 0 -16px;
	padding: 12px 16px;
	border-bottom: 1px solid #e5e7eb;
}

/* SheetTitle is text-lg + font-semibold */
.da-srp-sidebar-title { font-size: 18px; font-weight: 600; color: #111827; }

/* `p-2 rounded-full hover:bg-gray-100 -mr-2`, X icon at h-5 w-5 */
.da-srp-sidebar-close {
	display: flex;
	align-items: center;
	justify-content: center;
	background: none;
	border: none;
	font-size: 20px;
	line-height: 1;
	cursor: pointer;
	padding: 8px;
	margin-right: -8px;
	border-radius: 50%;
	transition: background-color .15s ease;
}

.da-srp-sidebar-close:hover { background: #f3f4f6; }

/* Clear Filters + chips bar inside the drawer — only shows once a filter is
   refined (.has-refinements, toggled by widgets-header.php), matching
   canRefine in the Nexus component. Negative margin cancels the sidebar's
   own 14px padding so the bar spans edge-to-edge like the Sheet's
   full-bleed version. */
.da-srp-sidebar-refinements {
	display: none;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
	margin: 0 -16px;
	/* `py-3` + `min-h-[64px]`; only a bottom hairline, since the header row
	   directly above already draws its own. */
	padding: 12px 16px;
	min-height: 64px;
	border-bottom: 1px solid #e5e7eb;
}

.da-srp-sidebar-refinements.has-refinements { display: flex; }

@media (min-width: 992px) {
	/* Desktop sidebar is a static column, not a drawer — no title/close row
	   to pin, and Clear Filters/chips live in the header row instead. */
	.da-srp-sidebar-sticky { position: static; background: none; }
	.da-srp-sidebar-refinements { display: none !important; }
}

@media (min-width: 992px) {
	.da-srp-sidebar {
		/* Scroll-then-stick: sticky with a JS-measured top (studio-js.php
		   updateSidebarStickyTop) — scrolls with the page until its end is
		   in view, then pins while results keep scrolling. */
		position: sticky;
		top: 0;
		bottom: auto;
		left: auto;
		right: auto;
		/* Mobile drawer uses z-index 1000; on desktop the sidebar must sit
		   BELOW the sticky header (60) so it scrolls behind it. */
		z-index: 1;
		align-self: flex-start;
		transform: none;
		/* w-80 (320px) — the same width as the condition toggle and the stats
		   pill in the header above, so the three share a right edge. Do not
		   change one without the other two. */
		width: 320px;
		flex-shrink: 0;
		box-shadow: none;
		/* React only pads the sidebar when a border is configured
		   (`padding: "0.5rem"` alongside `border: {width}px solid`), which CSS
		   can't branch on — so srp_studio_style_tokens() emits the token only
		   in that case. */
		padding: var(--srp-filters-padding, 0);
		overflow: visible;
		/* Transparent when unbordered, so the facets float as separate cards on
		   the SRP background; white once filtersSidebar.borderWidth draws a
		   frame, so the gutter inside that frame reads as a panel instead of a
		   gap. The token is emitted ONLY in the bordered case — see
		   srp_studio_style_tokens() in modules/studio-config.php. border-radius
		   below clips it, so a rounded frame gets a rounded fill. */
		background: var(--srp-filters-bg, transparent);
		border-radius: var(--srp-filters-radius, 0);
		border: var(--srp-filters-border-width, 0) solid var(--srp-filters-border-color, transparent);
		transition: none;
	}
	.da-srp-sidebar-head, .da-srp-filter-toggle, .da-srp-sidebar-backdrop { display: none; }
}

/* Clear filters button — lives in .da-srp-header-row-2, before the current-
   refinement chips; sized to match the stats pill it sits beside and only
   shown once a filter is actually refined (InstantSearch marks the button
   --disabled instead of removing it, so hide that state entirely). */
.da-srp .ais-ClearRefinements-button {
	/* `bg-black text-white h-6 px-1 rounded-[5px] text-sm font-medium`.
	   Literal 5px, not --srp-stats-radius: Nexus hard-codes this one rather
	   than reading the stats widget's configured radius. */
	display: inline-flex;
	align-items: center;
	height: 24px;
	padding: 0 4px;
	border: none;
	border-radius: 5px;
	background: #000;
	color: #fff;
	font-size: 14px;
	font-weight: 500;
	white-space: nowrap;
	cursor: pointer;
}

/* Drawer copy is the plain size="sm" button: h-8 px-3. */
#da-srp-clear-mobile .ais-ClearRefinements-button {
	height: 32px;
	padding: 0 12px;
}

.da-srp .ais-ClearRefinements-button--disabled { display: none; }

/* ── Facets ──────────────────────────────────────────────────────────
   Frame ported from Nexus nada/facet.tsx, which has THREE states. The outer
   element is only ever a frame; the white card is .da-srp-facet-inner.

     1. facetLabel.borderColor configured (.has-facet-border, added in
        markup/sidebar.php) — a 1px pad filled with the border color. That's
        React's "fake border": Tailwind can't take a dynamic border color, so
        it does `backgroundColor: borderColor; padding: 1px`. A real 1px border
        would look identical, but keeping the same mechanism keeps the inner
        radius math (r - 1px) honest.
     2. no border configured, open — a single top hairline, nothing else.
     3. no border configured, collapsed — a 1px gradient bevel that fades
        gray-300 → gray-200 (by 10%) → white down the box.

   Radius default is 0, not 8px: the Nexus default config ships facetLabel
   WITHOUT a borderRadius, so `rPx` is undefined there and React renders the
   box square. An unconfigured dealer should look the same on both stacks. */
.da-srp-facet {
	border: none;
	border-radius: var(--srp-facet-label-radius, 0);
	margin-bottom: 12px;
}

/* State 1 — configured border color */
.da-srp-facet.has-facet-border {
	background: var(--srp-facet-label-border, #d1d5db);
	padding: 1px;
}

/* State 2 — no configured border, expanded */
.da-srp-facet:not(.has-facet-border):not(.is-collapsed) {
	border-top: 1px solid #d1d5db;
}

/* State 3 — no configured border, collapsed */
.da-srp-facet:not(.has-facet-border).is-collapsed {
	background: linear-gradient(to bottom, #d1d5db 0%, #e5e7eb 10%, #fff 100%);
	padding: 1px;
}

/* The white card inside the frame. max() guards the inner radius against
   going negative when the configured radius is 0 (React sidesteps this with a
   `rPx != null ? … : "0px"` ternary); overflow lives here, not on the frame,
   so the frame itself is never clipped. */
.da-srp-facet-inner {
	background: #fff;
	border-radius: max(0px, calc(var(--srp-facet-label-radius, 0px) - 1px));
	overflow: hidden;
}

/* Facet header — !important guards against the theme's global button
   styles (dark backgrounds / white text / hover inversions) */
.da-srp .da-srp-facet-label {
	display: flex;
	justify-content: space-between;
	align-items: center;
	width: 100%;
	padding: 8px; /* px-2 py-2 */
	/* facetLabel.fillColor colors ONLY this header row, not the whole box;
	   --srp-facet-label-text is computed server-side (white on dark fills) */
	background: var(--srp-facet-label-fill, transparent) !important;
	background-image: none !important;
	color: var(--srp-facet-label-text, #111827) !important;
	border: none !important;
	box-shadow: none !important;
	text-shadow: none;
	text-transform: none;
	letter-spacing: normal;
	/* 16px here, 14px from 992 (see the query below the refinement list) —
	   see that block for why the two viewports differ. */
	font-size: 16px;
	font-weight: 600;
	line-height: 24px;
	cursor: pointer;
	text-align: left;
}

/* React uses hover:opacity-90 here, which fades the row without touching the
   configured fill color. (This used to be a translucent black gradient overlay
   — same intent, but it darkened rather than faded.) */
.da-srp .da-srp-facet-label:hover,
.da-srp .da-srp-facet-label:focus {
	opacity: .9;
	color: var(--srp-facet-label-text, #111827) !important;
}

/* Facets whose refinement list has no values are hidden entirely
   (is-empty is toggled per render in studio-js.php) */
.da-srp-facet.is-empty { display: none; }

/* Config-driven responsive visibility (mirrors nada's md:hidden /
   hidden md:block — 768px breakpoint) */
@media (min-width: 768px) {
	.da-srp .da-mobile-only { display: none !important; }
}
@media (max-width: 767px) {
	.da-srp .da-desktop-only { display: none !important; }
}

.da-srp .da-srp-facet-label span { color: inherit; }
/* w-4 h-4 = 16px, text-gray-500. The fallback differs from the label's
   (#111827) on purpose: React colors the chevron gray-500 and the label
   gray-900 when no fill is set, and both flip to white when one is. */
.da-srp .da-srp-facet-label i { transition: transform .2s; font-size: 16px; color: var(--srp-facet-label-text, #6b7280) !important; }
.da-srp-facet.is-collapsed .da-srp-facet-label i { transform: rotate(180deg); }
.da-srp-facet.is-collapsed .da-srp-facet-body { display: none; }

/* px-2 pb-3 pt-2 on the refinement-list root */
.da-srp-facet-body { padding: 8px 8px 12px; }

/* Full list, no inner scrollbar */
.da-srp .ais-RefinementList-list { list-style: none; margin: 0; padding: 0; }

/* space-y-1 */
.da-srp .ais-RefinementList-item + .ais-RefinementList-item { margin-top: 4px; }

/* Each row is `-mx-2 py-2 rounded hover:bg-gray-50` in React: the negative
   margin lets the hover background bleed out to the facet's inner edge while
   the padding puts the text back at the list's 8px inset. (React also reserves
   a 24px + 16px check-icon column ahead of the label; we deliberately don't —
   selection here is shown by weight alone, so the labels stay flush left.) */
.da-srp .ais-RefinementList-label {
	display: flex;
	align-items: center;
	gap: 8px;
	margin: 0 -8px;
	padding: 8px;
	border-radius: 4px;
	/* Ambient body text in the React drawer: 16px on Tailwind preflight's
	   `html { line-height: 1.5 }`. .da-srp's own 1.4 would give 22.4px and
	   the rows would creep ~1.6px shallower each — pin it. */
	font-size: 16px;
	line-height: 24px;
	color: #374151;
	cursor: pointer;
	transition: background-color .15s ease;
}

.da-srp .ais-RefinementList-label:hover { background: #f9fafb; }

/* Facet labels and filter rows are 16px in the drawer and 14px in the desktop
   sidebar. That asymmetry is real in Nexus, but it is not deliberate: the
   drawer passes textSize="md" to Facet/RefinementList, which interpolate it as
   `text-md` — NOT a Tailwind class, so nothing is emitted and the rows fall
   back to the ambient 16px body size. Desktop passes the default "sm" and gets
   a real text-sm. Replicated here so the two stacks look the same on a phone;
   if Nexus ever fixes the typo, drop the 16px base rather than this query.
   Counts stay 14px at both sizes — 16px counts next to 16px labels read as
   noise, and they're the one place the difference is purely decorative. */
@media (min-width: 992px) {
	/* text-sm is 14px on a FIXED 1.25rem line box, not a ratio. */
	.da-srp .da-srp-facet-label,
	.da-srp .ais-RefinementList-label { font-size: 14px; line-height: 20px; }
}

/* No visible checkbox — selection is shown by bold text (rows stay
   clickable; the hidden input still drives the refinement) */
.da-srp .ais-RefinementList-checkbox { display: none; }
.da-srp .ais-RefinementList-labelText { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }

/* Counts: plain accent-colored text, same as the nada refinement list */
.da-srp .ais-RefinementList-count {
	font-size: 14px;
	background: none;
	border-radius: 0;
	padding: 0;
	/* React sets this inline as 400, going to 700 only on refined rows —
	   the count is ambient text, not a badge. */
	font-weight: 400;
	/* React falls back to a bare var(--accent), whose stock value is a
	   near-white oklch; --accent isn't defined in this theme at all, so we
	   keep the darker literal behind it. */
	color: var(--srp-filters-accent, var(--accent, #374151));
}

/* Selected rows bold, like nada */
.da-srp .ais-RefinementList-item--selected .ais-RefinementList-labelText { font-weight: 700; color: #111827; }
.da-srp .ais-RefinementList-item--selected .ais-RefinementList-count { font-weight: 700; }

/* ── Tiered model facet ───────────────────────────────────────────────────
   Rendered by makeTieredModelRenderer() in studio/js/widgets-sidebar.php when
   the Model filter has config.modelSubCategory on. Reuses the refinement-list
   rules above; these only add the family/variant hierarchy.

   The family row is a plain label — no chevron, no tick — and reads exactly
   like any other facet row. Variants sit below it, indented, with a tick that
   only appears on the refined ones. */

/* Indent variants under their family. The tick slot is reserved on every
   variant row (empty when unrefined) so the names stay on one column. */
/* 8px past the row's own 8px inset — the indent is relative, so it has to
   track .ais-RefinementList-label's padding. */
.da-srp .da-srp-tier-child .ais-RefinementList-label { padding-left: 16px; }

.da-srp .da-srp-tier-check {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 18px;
	font-size: 14px;
	line-height: 1;
	color: #111827;
}

/* Variants sit a step heavier than the family row that owns them; the
   --selected rules above take the refined ones the rest of the way to bold */
.da-srp .da-srp-tier-child .ais-RefinementList-labelText { font-weight: 500; }

/* ── Range slider ─────────────────────────────────────────────────────────
   Visual parity with the Nexus Radix slider, in plain CSS:
     libs/ui-kit/src/templates/srp/instantsearch/range-slider.tsx
     libs/ui-kit/src/templates/srp/nada/range-menu.tsx

   The DOM here is rheostat's (what instantsearch.js rangeSlider renders), so
   the Radix parts map across as: Track → .rheostat-background,
   Range → .rheostat-progress, Thumb → .rheostat-handle.

   Mobile-first: the base rules are Radix's size="mobile" (24px track / 32px
   thumb) for comfortable touch targets, and the desktop query steps down to
   the default size (16px / 24px). --track-h and --thumb drive every
   measurement so the two sizes stay consistent.                            */
/* range-menu.tsx's root is `px-4 pb-4 pt-2`. The pt-2 lives on the label row
   below (which sits outside this element), so only px-4/pb-4 land here. */
.da-srp-facet-range .da-srp-facet-body { padding: 0 16px 16px; }

/* Current from/to values above the track (range-menu.tsx label row) */
.da-srp .da-srp-range-labels {
	display: flex;
	justify-content: space-between;
	gap: 8px;
	/* Carries the range root's pt-2 + px-4, since this row has to live outside
	   .da-srp-facet-body (InstantSearch owns that element's contents); mb-3
	   below it, exactly as in range-menu.tsx. */
	padding: 8px 16px 0;
	margin-bottom: 12px;
	font-size: 12px;
	line-height: 1.4;
	color: #4b5563; /* gray-600 */
}
/* Always on the page: these are the slider's only readout, and holding a fixed
   left/right position is the point — they never travel with the handles. The
   row keeps its height before values land, so nothing jumps. */
.da-srp-facet.is-collapsed .da-srp-range-labels { display: none; }
.da-srp .da-srp-range-labels span { min-height: 1em; }

/* The margin/box-shadow resets below are defensive: media/css/srpCSS/
   algolia.css ships its own rheostat theme at the same two-class specificity
   as ours (`.ais-RangeSlider .rheostat { margin: 40px 0 }`, an inset handle
   shadow), so anything we don't declare would leak through if it ever loaded
   alongside us. header.php:510-516 now skips algolia.css entirely in studio
   mode, so this can't bite today — but keep the resets, they're one line each
   and the enqueue condition is not ours to depend on. */
.da-srp .rheostat {
	--track-h: 24px;
	--thumb: 32px;
	position: relative;
	height: var(--thumb);
	margin: 0 4px 16px; /* the slider wrapper's `mb-4 px-1` */
}

/* Track: white, thin grey outline, softly rounded */
.da-srp .rheostat-background {
	position: absolute;
	top: calc((var(--thumb) - var(--track-h)) / 2);
	width: 100%;
	height: var(--track-h);
	box-sizing: border-box;
	background: #fff;
	border: 1px solid #e5e7eb; /* gray-200 */
	border-radius: 5px;
}

/* Selected range: neutral fill, inset by the track border so it doesn't
   overlap it (Radix clips this with overflow-hidden; rheostat can't, because
   the handles overflow the track and would be clipped too) */
.da-srp .rheostat-progress {
	position: absolute;
	top: calc((var(--thumb) - var(--track-h)) / 2 + 1px);
	height: calc(var(--track-h) - 2px);
	background: #f5f5f5; /* neutral-100 */
	border-radius: 0;
}

/* Thumb: squared-off, black outline, grip lines. rheostat renders a <button>,
   hence the appearance/padding resets. */
.da-srp .rheostat-handle {
	position: absolute;
	top: 0;
	width: var(--thumb);
	height: var(--thumb);
	margin-left: calc(var(--thumb) / -2);
	padding: 0;
	box-sizing: border-box;
	-webkit-appearance: none;
	appearance: none;
	background: #fff;
	border: 2px solid #000;
	border-radius: 5px;
	box-shadow: none; /* algolia.css puts an inset shadow on .rheostat-handle */
	cursor: grab;
	z-index: 2;
	transition: transform .15s ease;
	touch-action: none;
}
.da-srp .rheostat-handle:hover { transform: scale(1.1); }
.da-srp .rheostat-handle:active { cursor: grabbing; }
.da-srp .rheostat-handle:focus-visible { outline: 2px solid #000; outline-offset: 2px; }

/* Two vertical grip bars, 2px wide with a 2px gap (Radix: w-0.5 + gap-0.5) */
.da-srp .rheostat-handle::before,
.da-srp .rheostat-handle::after {
	content: "";
	position: absolute;
	top: 50%;
	width: 2px;
	height: 12px;
	margin-top: -6px;
	background: #9ca3af; /* gray-400 */
	border-radius: 1px;
}
.da-srp .rheostat-handle::before { left: calc(50% - 3px); }
.da-srp .rheostat-handle::after { left: calc(50% + 1px); }

/* Belt and braces: the widget is configured with tooltips:false, but if a
   rheostat version ever renders them anyway they must not reappear over the
   handles — the fixed labels above the track are the readout. */
.da-srp .rheostat-tooltip { display: none; }

/* Only the track and thumb step down for desktop — the grip bars are h-3
   (12px) at both Radix sizes. */
@media (min-width: 992px) {
	.da-srp .rheostat { --track-h: 16px; --thumb: 24px; }
}

/* ── Results grid + cards ──────────────────────────────────────────────
   InstantSearch renders #da-srp-results > .ais-Hits > .ais-Hits-list >
   .ais-Hits-item. The grid lives ONLY on .ais-Hits-list (and on the
   server-rendered skeleton via .da-srp-grid) — the wrapper layers must
   stay full-width blocks or the whole list collapses into one column. */
#da-srp-results,
.da-srp .ais-Hits,
.da-srp .ais-InfiniteHits {
	display: block;
	width: 100%;
	min-width: 0;
}

.da-srp-grid,
.da-srp .ais-Hits-list {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	gap: 16px;
	list-style: none;
	margin: 0;
	padding: 0;
	width: 100%;
}

@media (min-width: 640px) {
	.da-srp-grid, .da-srp .ais-Hits-list { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 20px; }
}

@media (min-width: 1280px) {
	.da-srp-grid, .da-srp .ais-Hits-list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Wide-desktop tiers, ported from the Nexus client's `.srp-hits-grid`
   (libs/ui-kit/src/styles/globals.css): 4 columns from 1800, 5 from 2400, on a
   24px gap from 1450 up. Both stacks carry a 320px sidebar at these widths, so
   the card lands at the same size on each — ~340px at 1800, ~387px at 2400.

   The LOW end deliberately does NOT follow Nexus (which steps at 1075/1450).
   Its sidebar appears at 768px and ours at 992px, so its ladder assumes a
   narrower results column than we actually have down there; copying it would
   put a single ~1040px-wide card across the whole 640-1074 range. Ours stays
   2-up from 640 and 3-up from 1280. */
@media (min-width: 1450px) {
	.da-srp-grid, .da-srp .ais-Hits-list { gap: 24px; }
}

@media (min-width: 1800px) {
	.da-srp-grid, .da-srp .ais-Hits-list { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}

@media (min-width: 2400px) {
	.da-srp-grid, .da-srp .ais-Hits-list { grid-template-columns: repeat(5, minmax(0, 1fr)); }
}

.da-srp .ais-Hits-item {
	margin: 0;
	padding: 0;
	min-width: 0;
	display: flex;
	flex-direction: column;
}

/* The card stretches to fill its grid cell so rows align */
.da-srp .ais-Hits-item > .srp-studio-card { flex: 1; }

/* The card container is a TRANSPARENT positioning box — all visible card
   chrome (background, border, radius, shadow) lives on the faces below so
   the whole card visibly rotates during the flip and the page background
   shows behind it mid-turn.
   The root card element keeps the "listing" class (legacy quick-form/
   analytics selectors need it — see studio-hit-template.php). algolia.css
   is no longer loaded in studio mode (header.php gates it on
   $srpStudioModeActive), so its `.listing` border and hover-lift no longer
   reach these cards and nothing here is fighting it — but the border is
   still declared explicitly, because the class is a public contract and the
   card must not depend on that file staying absent. */
.da-srp .srp-studio-card {
	background: transparent;
	display: flex;
	flex-direction: column;
	border: none;
	/* Scoped, never `all`: this is 16+ cards on the hottest re-render path,
	   and transform is the only property that animates here. */
	transition: transform .3s ease-in-out;
}

/* ── Card hover lift (port of algolia.styl's `.listing:hover`) ──────────
   The legacy SRP lifted the card 8px and dropped a soft shadow under it.
   Split across two elements because the studio card is built differently
   from the legacy one: .srp-studio-card is a TRANSPARENT, border-radius-less
   positioning box, so a shadow on it would paint a hard rectangle behind a
   rounded card. The shadow therefore goes on .srp-card-face (the element
   that actually has the background, border and radius) while the movement
   stays on the root, which carries both faces with it.

   `hover: hover` keeps it off touch devices, where :hover latches on tap and
   would leave a card stuck 8px up until you tapped elsewhere.

   The shadow is the legacy `0 1px 30px #d2d2d2` re-expressed in rgba. That
   flat grey was designed against a white page; the studio background is
   configurable (--srp-bg), and a solid grey glow reads as a halo rather than
   a shadow on anything dark. rgba multiplies correctly on any background and
   is visually indistinguishable on the default near-white. */
@media (hover: hover) {
	.da-srp .srp-studio-card:hover {
		transform: translateY(-8px);
	}

	.da-srp .srp-studio-card:hover .srp-card-face {
		box-shadow: 0 1px 30px rgba(0, 0, 0, .18);
	}
}

/* Flip — dual-face rotation: each face rotates independently inside the
   flip container's perspective. This is robust where a single rotating
   wrapper is not: CSS perspective only reaches DIRECT children, and
   ancestor overflow/border-radius can flatten preserve-3d — both of which
   made the old flip read as a flat squish instead of a 3D turn.
   Visibility swaps at the animation midpoint (faces cross at 90°) so the
   hidden face can never intercept clicks or paint over the visible one. */
/* display/height are pinned, not incidental: this element also carries the
   legacy `listing-container` class (for Carfax Snapshot's node_selector), and
   every legacy stylesheet that styles that class sets `display:flex` +
   `height:100%` on it (algolia-grid.css:30, styles.css, list.css). None of
   them load in studio mode any more (header.php skips them), so this is
   belt-and-braces — but the class is now part of our public contract with
   Carfax, so pin the browser defaults and keep the flip immune if one of
   those files ever comes back. */
.da-srp .srp-card-flip {
	position: relative;
	flex: 1;
	perspective: 1200px;
	display: block;
	height: auto;
	/* No background: a face is edge-on for the frame it crosses 90°, and the
	   page should show through then — see .srp-studio-card below. Nothing
	   between here and .da-srp paints, so --srp-bg already comes through. */
}

.da-srp .srp-card-face {
	/* Full card chrome on each face — this IS the visible card */
	background: #fff;
	border-radius: var(--srp-card-radius-top, 8px) var(--srp-card-radius-top, 8px) var(--srp-card-radius-bottom, 8px) var(--srp-card-radius-bottom, 8px);
	border: var(--srp-card-border-width, 1px) solid var(--srp-card-border-color, #e5e7eb);
	box-shadow: 0 1px 3px rgba(0, 0, 0, .07);
	overflow: hidden;
	backface-visibility: hidden;
	-webkit-backface-visibility: hidden;
	/* Keep the easing symmetric and the visibility delay at exactly half the
	   duration. backface-visibility hides a face by geometry the instant it
	   passes 90°; the visibility swap below fires at a fixed time. They must
	   land on the same frame or the card is briefly invisible mid-turn — the
	   old cubic-bezier(.4,.1,.2,1) crossed 90° at 201ms of 600ms while
	   visibility swapped at 300ms, a 99ms hole. Change one of these three
	   numbers and you change all three. */
	/* box-shadow is appended for the hover lift below. The transform/visibility
	   numbers above are load-bearing for the flip — do not retime them here. */
	transition: transform .85s cubic-bezier(.45, 0, .55, 1), visibility 0s .425s, box-shadow .3s ease-in-out;
}

.da-srp .srp-card-front { transform: rotateY(0deg); }
.da-srp .srp-studio-card.is-flipped .srp-card-front {
	transform: rotateY(180deg);
	visibility: hidden;
}

/* ── Tooltips inside a card (.dv-tooltip / .dv-tooltip-content) ─────────
   globalStyle.css reveals these on hover with z-index:1000 — and, for the
   .reserved-vehicle variant, position:fixed + z-index:2000. That works on
   the legacy SRP, whose card is an ordinary box.

   The studio card is not. .srp-card-front carries transform: rotateY(0deg)
   for the flip, on the same element as .srp-card-face's overflow:hidden, and
   a transformed element does three things at once:
     1. opens a stacking context — so NO z-index inside the card, however
        large, can lift the tooltip above a neighbouring card,
     2. becomes the containing block for position:fixed descendants — so the
        .reserved-vehicle rule pins the panel to the card, not the viewport,
     3. pairs with overflow:hidden to clip whatever still hangs outside.
   Raising the tooltip's own z-index cannot fix any of that; it is the same
   trap da-flyout.js escapes by relocating its panel to document.body.

   CSS-only escape, scoped to the moment a tooltip is actually hovered so the
   flip keeps its clean rounded clip the rest of the time: stop clipping the
   face, and lift the whole grid item so the card — and the tooltip now
   overflowing it — paints above its neighbours.

   :has() is Baseline; where it is unsupported the whole selector is dropped
   and behaviour falls back to today's, so this cannot make things worse. */
.da-srp .srp-card-face:has(.dv-tooltip:hover) {
	overflow: visible;
}

.da-srp .ais-Hits-item:has(.dv-tooltip:hover) {
	position: relative;
	z-index: 20;
}

/* position:fixed resolves against the transformed face here rather than the
   viewport, so globalStyle.css's .reserved-vehicle override would park the
   panel over the card's own top-left corner (its photo). Put it back to
   absolute and let the .dv-tooltip anchor place it. */
.da-srp .reserved-vehicle .dv-tooltip .dv-tooltip-content {
	position: absolute;
}

/* ── Flip smoothness ───────────────────────────────────────────────────
   .is-animating is carried by js/interactions.php only while a card is
   actually turning, and removed on transitionend.

   will-change promotes both faces to their own compositor layers for the
   duration, which is what lets a rounded, shadowed, overflow-hidden box
   rotate without repainting every frame. It is scoped to the animation on
   purpose: held permanently across a grid of cards it is memory spent on
   layers nothing is animating.

   The back face also stops being a scroll container while it turns.
   Rotating a scrollable element in 3D is materially slower than rotating a
   plain one, and there is nothing to scroll mid-flip anyway. */
.da-srp .srp-studio-card.is-animating .srp-card-face {
	will-change: transform;
}

.da-srp .srp-studio-card.is-animating .srp-card-back {
	overflow-y: hidden;
}

/* A column so the disclaimer list is the only scroller and the VDP link stays
   pinned at the bottom. overflow-y stays as the safety net for the title. */
.da-srp .srp-card-back {
	position: absolute;
	inset: 0;
	transform: rotateY(-180deg);
	overflow-y: auto;
	background: #fff;
	padding: 14px;
	visibility: hidden;
	cursor: pointer; /* tap anywhere (except links/buttons) to flip back */
	display: flex;
	flex-direction: column;
}
.da-srp .srp-studio-card.is-flipped .srp-card-back {
	transform: rotateY(0deg);
	visibility: visible;
}

/* Faces swap instantly instead of turning. No transitionend fires, so the
   backstop timer in js/interactions.php clears is-animating. */
@media (prefers-reduced-motion: reduce) {
	.da-srp .srp-card-face {
		transition: none;
	}

	/* The hover shadow still appears, it just stops sliding. */
	.da-srp .srp-studio-card,
	.da-srp .srp-studio-card:hover {
		transition: none;
		transform: none;
	}
}

.da-srp .srp-flip-trigger {
	background: none;
	border: none;
	cursor: pointer;
	padding: 6px 12px 10px;
	font-size: 13px;
	color: #374151;
}

.da-srp .srp-flip-close {
	position: absolute;
	top: 8px;
	right: 8px;
	background: none;
	border: none;
	font-size: 18px;
	cursor: pointer;
	z-index: 2;
}

/* Disclaimer panel (nada/flip-hit.tsx PricingView). min-height:0 on both is
   what lets the list scroll — a flex item's default min-height:auto will not
   shrink below its content, so the paragraphs would push past the face. */
.da-srp .srp-flip-disclaimers {
	flex: 1;
	min-height: 0;
	display: flex;
	flex-direction: column;
	margin-top: 10px;
}
.da-srp .srp-flip-disclaimers-title {
	margin: 0 0 8px;
	font-size: 15px;
	font-weight: 600;
	color: #111827;
}
.da-srp .srp-flip-disclaimer-list {
	flex: 1;
	min-height: 0;
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
	border: 1px solid #e5e7eb;
	border-radius: 5px;
	background: #f9fafb;
	padding: 12px;
}
.da-srp .srp-flip-disclaimer + .srp-flip-disclaimer { margin-top: 14px; }
.da-srp .srp-flip-disclaimer h4 {
	margin: 0 0 3px;
	font-size: 11px;
	font-weight: 600;
	color: #111827;
}
.da-srp .srp-flip-disclaimer p {
	margin: 0;
	font-size: 11px;
	line-height: 1.5;
	color: #4b5563;
}

/* A button, not a text link — easy to miss on a face of legal prose.
   flex-shrink:0 because the disclaimer list is the sibling that scrolls. */
.da-srp .srp-flip-vdp-link {
	display: block;
	flex-shrink: 0;
	margin-top: 10px;
	padding: 10px 12px;
	background: #000;
	color: #fff;
	border-radius: 5px;
	text-align: center;
	text-decoration: none;
	font-weight: 600;
	font-size: 13px;
	line-height: 1.2;
	transition: background-color .15s ease;
}
/* Black cannot be brightened with a filter, so lift the background instead. */
.da-srp .srp-flip-vdp-link:hover,
.da-srp .srp-flip-vdp-link:focus {
	background: #333;
	color: #fff;
	text-decoration: none;
}

/* Card sections (markup from modules/studio-hit-template.php) */
.da-srp .srp-studio-title { padding: 10px 12px 4px; cursor: pointer; }
/* min-height, not height: the configured value is a floor that equalises short
   stacks so the CTAs below them line up across a row — it never crops a tall
   one. Value from srpConfig.pricing.priceBlockHeight_{condition}. */
.da-srp .card-pricing { padding: 4px 12px; min-height: var(--srp-price-block-height, 0); }
.da-srp .card-details { padding: 4px 12px; font-size: 13px; }

/* Specs rows (SpecsConfig — port of ui-kit nada/card-specs.tsx) */
.da-srp .da-card-specs { padding: 8px 12px; }
.da-srp .da-spec-row {
	display: flex;
	align-items: center;
	gap: 6px;
	min-width: 0;
	font-size: 12px;
	line-height: 1.5;
	color: #374151;
}
.da-srp .da-spec-label { color: #6b7280; font-weight: 500; flex-shrink: 0; }
.da-srp .da-spec-value {
	min-width: 0;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.da-srp .da-spec-swatch {
	display: inline-block;
	width: 12px;
	height: 12px;
	border-radius: 9999px;
	border: 1px solid #e5e7eb;
	flex-shrink: 0;
}
.da-srp .card-vin-stock {
	display: flex;
	justify-content: space-between;
	gap: 8px;
	font-size: 11px;
	color: #374151;
	padding: 6px 12px;
	overflow: hidden;
}
.da-srp .da-vin-badge {
	background: #fff;
	padding: 3px 8px;
	font-weight: 500;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	max-width: 55%;
}
.da-srp .da-vin-badge + .da-vin-badge { max-width: 42%; }

/* Carfax / AutoCheck badge row — from algolia.css:1483, which studio does not
   load. Dealers write this class in their Redux content fields, so it reaches
   a card through the specs section or a custom container. The height cap is
   the point: a vendor-CDN badge arrives at natural size. */
.da-srp .carfax-autocheck {
	display: inline-flex;
}
.da-srp .carfax-autocheck img:not([src*='/bucket.dealeralchemist.com/']) {
	height: 50px;
}

/* Dealer footer bar (cardBottomArea — mirrors nada hit.tsx) */
.da-srp .srp-card-front { display: flex; flex-direction: column; min-height: 100%; }
.da-srp .da-card-bottom {
	margin-top: auto;
	display: flex;
	justify-content: space-between;
	align-items: center;
	gap: 8px;
	padding: 10px 12px;
	font-size: 13px;
	/* NO radius of its own — .srp-card-face rounds this bar for us, and it must
	   be the only thing that does. The face carries the border, the radius and
	   overflow:hidden, so the bar is already clipped to the face's PADDING box:
	   a curve of (radius - border-width), tighter than the radius the border
	   itself draws. */
	border-radius: 0;
}

/* Tooltip open — .srp-card-face is overflow:visible for as long as one is
   hovered (see the tooltip escape above), so nothing is clipping the bar and
   it has to round itself. The inner curve, not the card's: the bar sits inside
   the border, so its corners follow (radius - border-width). max() keeps it
   valid when a dealer configures a radius smaller than the border width. */
.da-srp .srp-card-face:has(.dv-tooltip:hover) .da-card-bottom {
	border-radius: 0 0
		max(0px, calc(var(--srp-card-radius-bottom, 8px) - var(--srp-card-border-width, 1px)))
		max(0px, calc(var(--srp-card-radius-bottom, 8px) - var(--srp-card-border-width, 1px)));
}
.da-srp .da-card-bottom-left { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.da-srp .da-card-bottom-phone {
	display: flex;
	align-items: center;
	gap: 6px;
	text-decoration: none;
	white-space: nowrap;
	font-weight: 600;
}
.da-srp .da-card-bottom-phone:hover { opacity: .8; }

.da-srp .srp-studio-cta-wrap { padding-left: 12px; padding-right: 12px; margin: 4px 0; }

.da-srp .srp-studio-cta {
	display: block;
	text-align: center;
	padding: 11px 10px;
	border-radius: 5px;
	font-weight: 600;
	font-size: 14px;
	text-decoration: none;
	cursor: pointer;
	transition: filter .15s;
}
.da-srp .srp-studio-cta:hover { filter: brightness(.92); }

.da-srp .srp-card-divider { padding-left: 12px; padding-right: 12px; }

/* Custom containers get the card gutter automatically — same 12px + 4px as
   .srp-studio-cta-wrap, the section a custom container most resembles.
   (Legacy's .srp-custom uses 0 25px; that is the legacy card's gutter.)
   The numbered class is untouched for per-container overrides. */
.da-srp .srp-studio-custom-container {
	padding-left: 12px;
	padding-right: 12px;
	margin: 4px 0;
}

/* Image carousel (Swiper 11 — bundle is loaded globally in header.php)
   The slide box is sized by aspect-ratio and the <img> carries width/height,
   so lazy slides occupy their final space before they load. Nothing here may
   depend on Swiper having initialized: carousels are built on scroll, and a
   card must look correct in the window before that happens. */
.da-srp .vehicle-slider-container { cursor: pointer; }
/* 8px inset on every side, matching the nada card (CardContent's
   px-2/px-3 + the Card's own gap-2 read as an even ~8px gutter around the
   image) — the swiper itself stays edge-to-edge with overflow:hidden, this
   just pulls its box in from the card's border. */
.da-srp .card-vehicle-image { position: relative; padding: 8px; }

/* Geometry comes from srpConfig.general.srpImageAspectRatio via
   srp_studio_style_tokens() — 4.3 → 4/3 + contain, else 16/9 + cover. */
.da-srp .da-srp-swiper {
	width: 100%;
	aspect-ratio: var(--srp-image-aspect, 16 / 9);
	overflow: hidden;
	background: var(--srp-image-bg, #f1f3f5);
}
/* !important guards against algolia.css's legacy
   `.ais-Hits-item .listing .swiper .swiper-slide img { height: auto; }` —
   the studio card root keeps the "listing" class (legacy quick-form/
   analytics selectors need it, see studio-hit-template.php), so that old
   rule matches here too, and at 4 classes it out-specifies the 2 classes
   below regardless of load order. With height:auto the image sized itself
   off its OWN native ratio instead of stretching to fill the slide box,
   which is what made object-fit (contain especially) look like it wasn't
   doing anything — it never got the chance to. */
.da-srp .da-srp-slide-img {
	display: block;
	width: 100%;
	height: 100% !important;
	object-fit: var(--srp-image-fit, cover);
}

/* Trailing "View More" slide (mirrors nada image-carousel.tsx's
   hasMoreImages slide) — reuses the first image's <img> under a dark
   overlay + a centered link to the VDP, shown once a vehicle has more
   photos than maxFeedImagesToDisplay keeps. */
.da-srp .da-srp-slide-viewmore { position: relative; }

.da-srp .da-srp-slide-viewmore-overlay {
	position: absolute;
	inset: 0;
	background: rgba(0, 0, 0, .4);
}

.da-srp .da-srp-slide-viewmore-btn {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	white-space: nowrap;
	background: var(--accent, #2563eb);
	color: #fff;
	padding: 10px 20px;
	border-radius: 6px;
	font-weight: 600;
	font-size: 14px;
	text-decoration: none;
	box-shadow: 0 4px 10px rgba(0, 0, 0, .25);
}

.da-srp .da-srp-slide-viewmore-btn:hover { filter: brightness(.92); }

/* Pre-init: the wrapper isn't a flex track yet, so pin it to the first slide
   instead of letting every slide stack down the page. */
.da-srp .da-srp-swiper:not([data-swiper-ready]) .swiper-slide:not(:first-child) { display: none; }

/* NOTE on selector depth below: the studio card root keeps the legacy
   "listing" class (quick-form/analytics still key off it), so algolia.css's
   `.ais-Hits-item .listing .swiper .swiper-button-next` (4 classes, loaded
   globally in <head>) matches these same buttons and otherwise wins — same
   leak pattern as the rheostat range slider. Selectors here are deliberately
   5 classes deep (via .srp-studio-card + .vehicle-slider-container) to
   out-specify it outright rather than rely on load-order tiebreaks, and every
   property algolia.css sets (border, flush right/left, zeroed corners,
   display) is explicitly re-declared here so nothing leaks through. */
.da-srp .srp-studio-card .vehicle-slider-container .da-srp-swiper:not([data-swiper-ready]) .swiper-button-next,
.da-srp .srp-studio-card .vehicle-slider-container .da-srp-swiper:not([data-swiper-ready]) .swiper-button-prev,
.da-srp .srp-studio-card .vehicle-slider-container .da-srp-swiper-static .swiper-button-next,
.da-srp .srp-studio-card .vehicle-slider-container .da-srp-swiper-static .swiper-button-prev { display: none; }

.da-srp .srp-studio-card .vehicle-slider-container .da-srp-swiper .swiper-button-next,
.da-srp .srp-studio-card .vehicle-slider-container .da-srp-swiper .swiper-button-prev {
	width: 32px;
	height: 32px;
	background: #6b7280;
	border: none;
	border-radius: 10px;
	opacity: 0;
	transition: opacity .15s, background-color .15s;
}
.da-srp .srp-studio-card .vehicle-slider-container .da-srp-swiper .swiper-button-next { right: 10px; }
.da-srp .srp-studio-card .vehicle-slider-container .da-srp-swiper .swiper-button-prev { left: 10px; }
.da-srp .srp-studio-card .vehicle-slider-container .da-srp-swiper .swiper-button-next:hover,
.da-srp .srp-studio-card .vehicle-slider-container .da-srp-swiper .swiper-button-prev:hover { background: #565b64; }

/* Thin two-stroke chevron (Swiper's default icon-font glyph reads heavier
   than the target design) drawn with a bordered box rotated to a corner,
   same technique as the legacy algolia.css arrows. */
.da-srp .srp-studio-card .vehicle-slider-container .da-srp-swiper .swiper-button-next::after,
.da-srp .srp-studio-card .vehicle-slider-container .da-srp-swiper .swiper-button-prev::after {
	content: '';
	width: 8px;
	height: 8px;
	border: solid #fff;
	border-width: 0 2px 2px 0;
	display: inline-block;
}
.da-srp .srp-studio-card .vehicle-slider-container .da-srp-swiper .swiper-button-next::after { transform: rotate(-45deg); margin-left: -3px; }
.da-srp .srp-studio-card .vehicle-slider-container .da-srp-swiper .swiper-button-prev::after { transform: rotate(135deg); margin-right: -3px; }

/* Arrows on hover for pointers; always visible on touch, where there's no hover */
.da-srp .srp-studio-card .vehicle-slider-container:hover .da-srp-swiper .swiper-button-next,
.da-srp .srp-studio-card .vehicle-slider-container:hover .da-srp-swiper .swiper-button-prev,
.da-srp .srp-studio-card .vehicle-slider-container .da-srp-swiper .swiper-button-next:focus-visible,
.da-srp .srp-studio-card .vehicle-slider-container .da-srp-swiper .swiper-button-prev:focus-visible { opacity: 1; }

@media (hover: none) {
	.da-srp .srp-studio-card .vehicle-slider-container .da-srp-swiper .swiper-button-next,
	.da-srp .srp-studio-card .vehicle-slider-container .da-srp-swiper .swiper-button-prev { opacity: .9; }
}

/* ── Footer: same stats pill + compact pager as the header ─────────── */
/* Mobile-first: stacks and centres by default; goes side-by-side at 640. */
.da-srp-footer {
	display: flex;
	flex-wrap: wrap;
	flex-direction: column;
	justify-content: center;
	align-items: center;
	gap: 10px;
	padding: 22px 0 8px;
}

@media (min-width: 640px) {
	.da-srp-footer { flex-direction: row; justify-content: space-between; }
}

/* ── Skeleton ──────────────────────────────────────────────────────── */
.da-srp-skeleton-card {
	background: #e5e7eb;
	border-radius: 8px;
	min-height: 380px;
	animation: da-srp-pulse 1.6s ease-in-out infinite;
}

@keyframes da-srp-pulse {
	0%, 100% { opacity: 1; }
	50% { opacity: .55; }
}

/* ── No results / disclaimer ───────────────────────────────────────── */
.da-srp-no-results { grid-column: 1 / -1; text-align: center; padding: 48px 12px; }
.da-srp-no-results h2 { font-size: 22px; color: #6b7280; margin: 0 0 8px; }
.da-srp-no-results-form { max-width: 560px; margin: 20px auto 0; text-align: left; }

.da-srp-disclaimer {
	font-size: 11px;
	color: #6b7280;
	line-height: 1.5;
	padding: 20px var(--srp-gutter, 16px) 8px;
}

/* ── Utility subset for studio Mustache templates ──────────────────────
   Tailwind-compatible names, scoped to .da-srp. Keep in sync with the
   classes used by the default vehicleTitle / pricing templates in
   ui-kit searchResultsConfig.ts. */
.da-srp .flex { display: flex; }
.da-srp .flex-1 { flex: 1 1 0%; }
.da-srp .relative { position: relative; }
.da-srp .w-full { width: 100%; }
.da-srp .min-w-0 { min-width: 0; }
.da-srp .overflow-hidden { overflow: hidden; }
.da-srp .items-center { align-items: center; }
.da-srp .justify-between { justify-content: space-between; }
.da-srp .justify-center { justify-content: center; }
.da-srp .text-center { text-align: center; }
.da-srp .uppercase { text-transform: uppercase; }
.da-srp .underline { text-decoration: underline; }
.da-srp .line-through { text-decoration: line-through; }
.da-srp .decoration-red-500 { text-decoration-color: #ef4444; }
.da-srp .decoration-2 { text-decoration-thickness: 2px; }
.da-srp .text-xs { font-size: 12px; }
.da-srp .text-sm { font-size: 13px; }
.da-srp .text-base { font-size: 15px; }
.da-srp .text-lg { font-size: 17px; }
.da-srp .text-xl { font-size: 19px; }
.da-srp .text-2xl { font-size: 23px; }
.da-srp .font-normal { font-weight: 400; }
.da-srp .font-medium { font-weight: 500; }
.da-srp .font-semibold { font-weight: 600; }
.da-srp .font-bold { font-weight: 700; }
.da-srp .text-white { color: #fff; }
.da-srp .text-black { color: #111827; }
.da-srp .text-gray-500 { color: #6b7280; }
.da-srp .text-gray-600 { color: #4b5563; }
.da-srp .text-gray-900 { color: #111827; }
.da-srp .text-green-700 { color: #15803d; }
.da-srp .text-red-600 { color: #dc2626; }
.da-srp .text-blue-600 { color: #2563eb; }
.da-srp .bg-neutral-100 { background: #f5f5f5; }
.da-srp .bg-red-500 { background: #ef4444; }
.da-srp .rounded { border-radius: 4px; }
.da-srp .h-4 { height: 16px; }
.da-srp .h-6 { height: 24px; }
.da-srp .my-2 { margin-top: 8px; margin-bottom: 8px; }
.da-srp .mt-2 { margin-top: 8px; }
.da-srp .mt-4 { margin-top: 16px; }
.da-srp .mb-2 { margin-bottom: 8px; }
.da-srp .py-1 { padding-top: 4px; padding-bottom: 4px; }
.da-srp .py-4 { padding-top: 16px; padding-bottom: 16px; }
.da-srp .p-4 { padding: 16px; }
.da-srp .space-y-2 > * + * { margin-top: 8px; }
.da-srp .line-clamp-2 {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}
.da-srp .hover\:underline:hover { text-decoration: underline; }
