body { font-size: 10pt; color: #000000; font-family: sans-serif; background-color: #ffffff; margin: 4pt }
.site-banner {
	background-color: #ffde76;
	border-bottom: 1px solid #F5CD02;
	color: #333333;
	font-size: 11pt;
	text-align: center;
	padding: 8pt 13pt;
}
.site-banner a { color: #e72b2c; font-weight: bold; text-decoration: none; }
.site-banner a:hover { text-decoration: underline; }
.site-banner-details {
	margin-top: 8pt;
	padding-top: 8pt;
	border-top: 1px solid #F5CD02;
	font-size: 10pt;
	text-align: center;
}
.site-banner-details a { color: #e72b2c; font-weight: bold; text-decoration: none; }
.site-banner-details a:hover { text-decoration: underline; }

/* --- AJAX cascade busy state (js/main.js) ----------------------------------------------------
   The cascade no longer reloads the page, so the browser's own loading indicator never appears
   and a slow step would otherwise look like a dead click. Cursor only: no spinner and no overlay,
   because the swap is usually faster than a spinner's fade-in and an overlay would obscure the
   very ad the page is being kept alive to display. */
body.ro-cascade-busy { cursor: progress; }
body.ro-cascade-busy #selectForm { opacity: 0.6; transition: opacity 120ms linear; }
@media (prefers-reduced-motion: reduce) {
	body.ro-cascade-busy #selectForm { transition: none; }
}

/* --- Ad-gated navigation wait UI (js/ad-gate.js) ---------------------------------------------
   Lives in common.css because it is the only sheet loaded by BOTH head.jspf and index.jsp, and
   by both UI arms (head.jspf picks exactly one of style.css / style-v2.css).

   A determinate bar, not a spinner: the remaining hold is known exactly, so indeterminate motion
   would be a lie. position:fixed means it contributes zero CLS -- which matters, because the
   Playwire layout reserves no ad space and already has a layout-shift problem. Deliberately NOT
   a full-screen dimming overlay: that reads as broken and obscures the very creative we are
   holding the page to have viewed. */
.ro-navgate-bar {
	position: fixed;
	top: 0;
	left: 0;
	width: 100%;
	height: 3px;
	z-index: 2147483000;
	background: rgba(12, 24, 74, 0.12);
	opacity: 0;
	pointer-events: none;
	transition: opacity 120ms linear;
}
.ro-navgate-bar.is-active { opacity: 1; pointer-events: auto; cursor: pointer; }
.ro-navgate-bar > span {
	display: block;
	height: 100%;
	width: 100%;
	background: #e72b2c;
	transform: scaleX(0);
	transform-origin: 0 50%;
}
/* Visible within 100ms of the click even before the bar has moved perceptibly. */
body.ro-navgate-waiting { cursor: progress; }
.ro-lb-row.is-pending { background: rgba(231, 43, 44, 0.10); }
/* Announced to screen readers, invisible to everyone else. */
.ro-navgate-live {
	position: absolute;
	width: 1px;
	height: 1px;
	margin: -1px;
	padding: 0;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}
@media (prefers-reduced-motion: reduce) {
	.ro-navgate-bar { transition: none; }
	.ro-navgate-bar > span { transition: none !important; }
}

/* --- Reserved ad slot sizes (CLS) ------------------------------------------------------------
   Playwire's review found no reserved space for any ad slot, so every creative that landed
   pushed the page down. These rules hold each in-flow slot's height from first paint.

   Only applied when ads.explicitPlacement is on, because reserving space only helps if the
   creative actually lands in THIS container -- see ad-provider-ab.jspf, which stops Ramp
   auto-injecting these units so their includes can place them by selectorId instead.

   min-height (not height) on purpose: it is the shift-reducing direction.

   Each value is now the MAXIMUM creative the unit is trafficked for, per Playwire's size list
   (2026-08-03), so a fill of any size shifts nothing at all:

     standard_iab_head1   desktop 1200x250   mobile 320x100
     standard_iab_head2   desktop  970x90    mobile 320x100
     standard_iab_rght1   desktop  336x600   mobile 320x100

   That is the trade the earlier smallest-creative values deliberately deferred: reserving the max
   takes CLS to zero, at the cost of a taller gap on the pageviews where the slot goes unfilled.
   Reserve-the-max is the right side of that trade now the numbers are confirmed -- an unfilled
   slot is a static gap the visitor never sees move, where an under-reserved one moves the page
   under their finger on every single fill.

   The breakpoints below mirror roAdHeadType() in ad-provider-ab.jspf, which decides which head
   unit is actually requested. They have to stay in step: reserving head2's 90px on a viewport
   that requests head1's 250px re-creates exactly the shift this is here to remove.

   The sticky/overlay units (bottom_rail, corner_ad_video, flex) are outside the content flow and
   need nothing here. */
.ro-ad-reserve { min-height: var(--ro-ad-h, 0); }

/* Leaderboard. Mobile (<=971px, standard_iab_head3) tops out at 320x100 -- the old 50px came from
   Freestar's __320x50 and under-reserved every mobile fill by half. */
.ro-ad-lead { --ro-ad-h: 100px; }
/* 972-1299px -> standard_iab_head2, max 970x90. */
@media (min-width: 972px) { .ro-ad-lead { --ro-ad-h: 90px; } }
/* >=1300px -> standard_iab_head1, max 1200x250. */
@media (min-width: 1300px) { .ro-ad-lead { --ro-ad-h: 250px; } }

/* Footer unit, v2 only. */
.ro-ad-foot { --ro-ad-h: 90px; }

/* Right siderail, standard_iab_rght1, max 336x600. Only ever rendered where .gad-tall-right is
   wide enough to hold 336px without taking the width out of the content cell (style.css), so
   there is one height and no breakpoints. */
.ro-ad-rght1 { --ro-ad-h: 600px; }

/* 300x250 in-content medium rectangle (vehicles list). */
.ro-ad-mrec { --ro-ad-h: 250px; }
