/* ==========================================================================
   Second Drive — Homepage Styles
   Shares CSS variables and verdict-badge-overlay classes with model-review.css
   — load both on the homepage, or move :root into a shared base stylesheet.
   ========================================================================== */

.homepage {
    max-width: 1400px; /* was 1100px, before that 960px — even 1100px still
        left large empty margins on wide screens once actually tested live.
        Matches header.css / footer.css, widened together this time so
        header/footer/content stay consistent rather than mismatched again. */
    margin: 0 auto;
}

/* ---------- Welcome video band ----------
   Permanent ambient background — plays on every visit, every page load,
   never collapses or disappears. This also removes the entire class of
   risk that caused an earlier "vibrating" bug (a transition on this
   element's own margin/height, combined with the 100vw full-bleed
   calculation recalculating whenever the scrollbar toggled, created a
   feedback loop). Since this element's size never changes now, that
   risk is gone by construction, not just patched around. */
.welcome-video-band {
    position: relative;
    height: 160px;
    overflow: hidden;
    background: var(--sd-navy); /* shows immediately, before/if video never loads */
    /* Full-bleed: breaks out of .homepage's max-width: 1400px container to
       span the full viewport width, regardless of viewport size — the
       standard "full-bleed inside a centered container" technique. */
    width: 100vw;
    margin-left: calc(-50vw + 50%);
    margin-right: calc(-50vw + 50%);
}

.welcome-video {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.welcome-video-overlay {
    position: absolute;
    inset: 0;
    /* Animated version of the darkening overlay that sits on top of the
       welcome video — was a static navy gradient, now cycles through
       black and red tones matching the new palette. Opacity range kept
       close to the original (was 0.55-0.75 navy) so the overlay still
       does its real job: darkening the busy video footage enough for
       the white tagline text on top to stay legible, regardless of
       which color the gradient happens to be cycling through at any
       given moment. */
    background: linear-gradient(
        135deg,
        rgba(13, 13, 13, 0.65),
        rgba(74, 15, 15, 0.6),
        rgba(26, 20, 20, 0.7),
        rgba(107, 20, 20, 0.6),
        rgba(13, 13, 13, 0.65)
    );
    background-size: 300% 300%;
    animation: sd-hero-gradient-move 14s ease-in-out infinite;
}

@keyframes sd-hero-gradient-move {
    0%   { background-position: 0% 50%; }
    50%  { background-position: 100% 50%; }
    100% { background-position: 0% 50%; }
}

/* Some visitors have this OS-level setting on for genuine vestibular/
   motion-sensitivity reasons — freeze to a single still frame rather
   than making the animation smaller or slower, which wouldn't actually
   address why the setting exists. */
@media (prefers-reduced-motion: reduce) {
    .welcome-video-overlay {
        animation: none;
        background-position: 50% 50%;
    }
}

/* ---------- Welcome text overlay ----------
   Two tiers: .welcome-greeting fades after a few seconds, first-visit
   only (see initWelcomeVideo() in homepage.js — same JS as before,
   unchanged, since it just queries [data-welcome-text] wherever that
   attribute lives). .hero-permanent-tagline never fades — it's the
   page's actual H1 and needs to survive every visit, every session,
   since a page with zero H1s for returning visitors is a real SEO
   problem, and Section 4.1 wants this line persistently in the hero. */
.welcome-video-content {
    position: relative;
    z-index: 1;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
}

.welcome-greeting {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    opacity: 1;
    transition: opacity 0.6s ease;
}

.welcome-greeting.dismissing {
    opacity: 0;
}

.welcome-logo {
    width: 40px;
    height: 40px;
    object-fit: contain; /* the old logo file was perfectly square (1024x1024)
        so a plain square box never distorted it — the updated logo is a
        slightly different ratio (923x809), and without object-fit an img
        just stretches to fill its given width/height, which would squish
        it. contain keeps the correct proportions regardless of exact
        file dimensions, so this won't need touching again if the logo
        file changes again later either. */
}

.welcome-tagline {
    color: #fff;
    font-size: 0.95rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    margin: 0;
}

.hero-permanent-tagline {
    color: #fff;
    -webkit-text-fill-color: #fff; /* Safari-specific fix — confirmed this
        text was rendering black in Safari specifically while every other
        browser showed the correct white (color:#fff alone wasn't being
        respected there). -webkit-text-fill-color can silently override
        color in WebKit's rendering in certain compositing situations;
        setting both explicitly pins it regardless of the exact cause. */
    font-family: var(--sd-font-heading);
    font-style: italic; /* the one deliberately louder heading on the
        site — every other h1-h6 gets plain (non-italic) Oswald via the
        global rule in model-review.css. Italic reserved for just this
        signature hero moment so it doesn't get diluted by being used
        everywhere else too */
    font-size: 1.3rem;
    font-weight: 800;
    letter-spacing: -0.01em;
    margin: 0;
    text-align: center;
}

/* No-video fallback: JS adds this class when prefers-reduced-motion,
   Save-Data, or a slow connection is detected — video element is
   removed from the flow entirely, poster shows via the section's
   background-image instead (set inline by JS from the <video poster>
   attribute), so there's no layout shift and no wasted video request. */
.welcome-video-band.no-video .welcome-video {
    display: none;
}

@media (prefers-reduced-motion: reduce) {
    .welcome-video {
        display: none;
    }

    .welcome-greeting {
        transition: none;
    }
}

/* Reusable across any section: wrap a set of .bg-icon elements (each
   holding one of our body-type SVGs) in a container with class
   "bg-icons", positioned absolutely, sitting behind that section's
   real content (z-index: 0 vs content at z-index: 1+).
   Icon color is set via `color` on .bg-icons — currentColor in the
   SVG paths inherits it, so the same markup works on both navy and
   light section backgrounds by just changing one CSS rule. */
.bg-icons {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    z-index: 0;
}

.bg-icon {
    position: absolute;
    opacity: 0.32;
    animation: sd-icon-drift 9s ease-in-out infinite;
}

.bg-icon:nth-child(2) { animation-duration: 11s; animation-delay: -3s; }
.bg-icon:nth-child(3) { animation-duration: 8s; animation-delay: -5s; }
.bg-icon:nth-child(4) { animation-duration: 10s; animation-delay: -1.5s; }

/* Smooth horizontal glide only — no rotation or vertical jump, so it
   reads as a car gliding past rather than jittering/bumping in place. */
@keyframes sd-icon-drift {
    0%   { transform: translateX(0); }
    50%  { transform: translateX(36px); }
    100% { transform: translateX(0); }
}

/* Content sitting above a .bg-icons layer needs explicit stacking */
.email-capture-content,
.site-footer-content {
    position: relative;
    z-index: 1;
}

@media (prefers-reduced-motion: reduce) {
    .bg-icons {
        display: none;
    }
}

/* ---------- Featured Fact Sheets ---------- */
.featured-factsheets {
    padding: 0 1rem;
    margin-bottom: 2.5rem;
}

.featured-factsheets h2 {
    color: var(--sd-navy);
    font-size: 1.25rem;
    font-weight: 700;
    margin-bottom: 1rem;
}

.featured-card {
    display: block;
    text-decoration: none;
    color: inherit;
    border: 1px solid var(--sd-border);
    border-radius: 10px;
    overflow: hidden;
    background: #fff;
}

.featured-card-thumb {
    position: relative;
    aspect-ratio: 4 / 3;
    background: var(--sd-bg);
    overflow: hidden;
}

.featured-card-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.featured-card-body {
    padding: 0.85rem 1rem 1rem;
}

.featured-card-body h3 {
    font-size: 1rem;
    color: #1a1a1a;
    margin-bottom: 0.4rem;
}

.featured-card-excerpt {
    font-size: 0.82rem;
    color: var(--sd-text-secondary);
    line-height: 1.45;
    margin: 0 0 0.6rem;
    /* Cap at 2 lines so cards stay a consistent height regardless of
       how long a given excerpt runs — matches the reference's tidy,
       uniform card row rather than letting one long excerpt make its
       card taller than its neighbors. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.featured-card-time {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.75rem;
    color: var(--sd-text-secondary);
    margin: 0;
}

.featured-card-clock {
    flex-shrink: 0;
}

.see-all-link {
    display: inline-block;
    color: var(--sd-navy);
    font-weight: 600;
    text-decoration: none;
    font-size: 0.9rem;
}

/* ---------- Content placeholders (no Models/Makes/body_types yet) ----------
   Featured Report Cards, Category tiles, and Browse by Make each fall
   back to placeholder content when their real data doesn't exist yet —
   reusing the SAME classes and marquee mechanics as real content (see
   front-page.php), so no separate skeleton/shimmer system is needed.
   These small modifiers just mark them as non-interactive and slightly
   muted, since they're <span> elements, not links, and shouldn't invite
   a click. Partner strip deliberately has no placeholder — see the
   file header comment in front-page.php for why. */
.featured-card-placeholder,
.category-tile-placeholder,
.make-tile-placeholder {
    cursor: default;
    opacity: 0.85;
}

.placeholder-text-line {
    color: var(--sd-text-secondary);
    font-style: italic;
}

/* ---------- Category tiles ---------- */
.category-tiles {
    padding: 0 1rem;
    margin-bottom: 2.5rem;
}

.category-tiles h2 {
    color: var(--sd-navy);
    font-size: 1.25rem;
    font-weight: 700;
    margin-bottom: 1rem;
}

.tiles-subheading {
    color: var(--sd-text-secondary);
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin: 0 0 0.6rem;
}

/* Space between the Body Type row and the Budget row below it — only
   applies when a budget row actually follows the marquee above it, so
   a page with just one row (e.g. no budget terms at all) doesn't get
   an orphaned gap at the bottom. Targets .marquee now, not .tiles-grid
   — these rows became marquees so a lone stranded tile in the last
   row/column can never recur, regardless of how many terms exist. */
.marquee + .tiles-subheading {
    margin-top: 1.75rem;
}

.marquee-track .category-tile {
    flex: 0 0 320px; /* was 240px — read as small once real photos filled
        the tiles, especially given these are the primary "browse by
        category" entry points on the homepage */
}

.category-tile {
    display: flex;
    flex-direction: column;
    text-decoration: none;
    color: var(--sd-navy);
    border-radius: 8px;
    overflow: hidden;
    background: #fff;
    border: 1px solid var(--sd-border);
}

.tile-photo {
    aspect-ratio: 2 / 1; /* matches the actual car photos being uploaded
        exactly (confirmed 750x375px = 2:1) — was 4/3, then 16/9 as an
        initial guess before checking a real uploaded file. Paired with
        object-fit: contain below, this means zero letterboxing for any
        photo at this same ratio, and no cropping even if a future one
        doesn't match exactly. Make tiles are unaffected — they override
        this with their own 1:1 square ratio via .tile-photo-square. */
    background: var(--sd-bg);
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.tile-photo img {
    width: 100%;
    height: 100%;
    object-fit: contain; /* was cover — guarantees the full car is always
        visible regardless of a given photo's exact aspect ratio, using
        the tile's own neutral background as a clean letterbox instead of
        risking a crop into the roofline/wheels like before. Since these
        are plain-background product-style car photos, the letterboxing
        blends in rather than looking like an error. */
    display: block;
}

.tile-photo-pending {
    font-size: 0.7rem;
    color: var(--sd-text-secondary);
    text-align: center;
    padding: 0 0.5rem;
}

.tile-photo-budget {
    /* Removed the rgba(200,16,46,0.06) pink wash — inconsistent with
       every other tile type (Body Type, Make), which are all plain
       white cards with a light grey photo area. Now matches .tile-photo
       exactly, just via this class for markup/targeting continuity. */
    background: var(--sd-bg);
    display: flex;
    align-items: center;
    justify-content: center;
}

.budget-tile-icon {
    color: var(--sd-red); /* red as a small accent, matching how it's
        used everywhere else on the site (the verdict gauge dot, CTA
        buttons) — never as a large fill, so this stays consistent
        rather than introducing a new, heavier use of the color */
}

.tile-photo-budget {
    position: relative; /* anchors .budget-tile-count below when a
        real listing photo is showing instead of the icon fallback */
}

.tile-photo-budget img {
    width: 100%;
    height: 100%;
    object-fit: cover; /* cover here, not contain like other tile
        photos — this is a real listing's own photo (not a clean
        product-style shot on a neutral background), so cropping
        slightly is preferable to letterboxing an outdoor/varied photo */
}

.budget-tile-count {
    position: absolute;
    bottom: 8px;
    left: 8px;
    background: rgba(20, 20, 20, 0.85);
    color: #fff;
    font-family: var(--sd-font-heading);
    font-weight: 700;
    font-size: 0.65rem;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    padding: 4px 9px;
    border-radius: 999px;
    max-width: calc(100% - 16px); /* same width-safety fix as the
        verdict badge — never grow wide enough to overwhelm the photo */
}

.tile-photo-square {
    aspect-ratio: 4 / 3; /* was 1/1 — the actual brand logo files being
        uploaded are 240x180px (4:3), not square. With object-fit:contain
        already in place, a 4:3 logo forced into a 1:1 box was filling
        the full width but leaving empty space above/below, making the
        logo look smaller than the tile size actually allowed. */
    padding: 0.5rem;
}

.tile-label {
    font-size: 0.82rem;
    font-weight: 600;
    text-align: center;
    padding: 0.6rem 0.4rem;
}

/* Body Type and Budget tiles are much wider (320px) than Make tiles
   (130px) — the larger label size below is scoped to just these two,
   so Make's tile-label (shared class) stays at the size appropriate
   for its narrower tile. */
.category-tile .tile-label {
    font-size: 0.95rem;
    padding: 0.75rem 0.5rem;
}

/* .category-tile-budget intentionally has no color overrides anymore —
   it now inherits the exact same white-card, navy-label styling as
   every other tile type (.category-tile base, .tile-label base), for
   full visual consistency rather than a one-off red-tinted variant
   that stood out against the site's otherwise clean white/grey tiles. */

/* ---------- Email capture ----------
   Navy background, matching the footer's exact palette (var(--sd-navy),
   #fff headings, #C7D2E0 secondary text) since this section sits
   directly above the footer as the last content block on the page —
   reads as one continuous navy block with it. Redesigned from an
   earlier version that had drifting background car icons overlapping
   directly through the heading/checkbox text, and an email input that
   was overflowing past the card's right edge on wider screens. This
   version drops the icons and wraps everything in a max-width inner
   column (.email-capture-content) so nothing can stretch edge-to-edge
   regardless of how wide .homepage itself is — the overflow can't
   recur since nothing in here is sized relative to the full-width
   card anymore, only to this much narrower inner column. */
.email-capture {
    background: var(--sd-navy);
    border-radius: 16px;
    padding: 3rem 1.5rem;
    margin: 0 1rem 2.5rem;
    text-align: center;
}

.email-capture-content {
    max-width: 440px;
    margin: 0 auto;
}

.email-capture h2 {
    color: #fff;
    font-size: 1.3rem;
    font-weight: 800;
    margin-bottom: 0.5rem;
    line-height: 1.25;
}

.email-capture p {
    color: #C7D2E0;
    font-size: 0.88rem;
    margin-bottom: 1.5rem;
}

/* Input and button combined into one pill — a single clear action
   rather than a stacked input-then-button-then-checkbox column, which
   is what read as cluttered before. */
.email-capture-input-row {
    display: flex;
    align-items: center;
    background: #fff;
    border-radius: 999px;
    padding: 0.3rem;
    margin-bottom: 1.1rem;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
}

.email-capture-input-row input[type="email"] {
    flex: 1 1 auto;
    min-width: 0; /* lets the input shrink below its content size instead
        of forcing the flex row (and the pill) wider than its container —
        this, combined with the max-width wrapper above, is what actually
        fixes the overflow rather than just hiding its symptom */
    border: none;
    background: transparent;
    padding: 0.7rem 0.9rem;
    font-size: 0.88rem;
    color: var(--sd-navy);
}

.email-capture-input-row input[type="email"]:focus {
    outline: none;
}

.email-capture-input-row .cta-button {
    flex-shrink: 0;
    border-radius: 999px;
    padding: 0.7rem 1.4rem;
    margin: 0;
    font-size: 0.85rem;
    white-space: nowrap;
}

.consent-label {
    display: flex;
    align-items: flex-start;
    gap: 0.45rem;
    font-size: 0.72rem;
    line-height: 1.4;
    color: #8A9AB5;
    text-align: left;
}

.consent-label input[type="checkbox"] {
    flex-shrink: 0;
    margin-top: 0.2rem;
}

.consent-label a {
    color: #fff;
    text-decoration: underline;
}

/* Below ~360px, the pill gets too cramped for both the email
   placeholder and the button to sit comfortably side by side — stack
   them instead rather than letting either get squeezed unreadably. */
@media (max-width: 360px) {
    .email-capture-input-row {
        flex-direction: column;
        border-radius: 16px;
        gap: 0.4rem;
    }

    .email-capture-input-row .cta-button {
        width: 100%;
    }
}

/* ---------- Partner strip ---------- */
.partner-strip {
    padding: 0 1rem;
    margin-bottom: 2.5rem;
    text-align: center;
}

.partner-strip h3 {
    color: var(--sd-text-secondary);
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    margin-bottom: 1rem;
}

.partner-strip-logo {
    width: 60px;
    height: 60px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    color: var(--sd-navy);
    font-size: 0.7rem;
    flex-shrink: 0;
}

.partner-strip-logo img {
    max-width: 100%;
    max-height: 100%;
}

/* ---------- Trust statement ---------- */
.trust-statement {
    padding: 0 1rem 2rem;
    text-align: center;
}

.trust-statement p {
    color: var(--sd-text-secondary);
    font-size: 0.8rem;
    max-width: 30rem;
    margin: 0 auto;
}

/* ==========================================================================
   JS-driven interactions: scroll-reveal, sticky header, image fade, carousels
   ========================================================================== */

/* ---------- Scroll reveal ----------
   REMOVED the JS-dependent hiding (.js-ready .reveal { opacity: 0 })
   that lived here previously. That pattern already caused one serious
   bug (content stuck invisible when JS didn't load) and had a second,
   worse failure mode: if JS runs PARTIALLY — adds the .js-ready class
   (which activates the hidden state) but then throws before reaching
   initScrollReveal() (which would reveal it again) — content stays
   hidden forever with no way to recover client-side. Given that risk,
   .reveal content now just shows normally, always. The scroll fade-in
   animation is gone; correctness comes first. Revisit as a pure
   opt-in enhancement later if wanted (e.g. only animate elements
   that are confirmed to already be visible, never hide-by-default). */
.reveal {
    opacity: 1;
}

.reveal-visible {
    opacity: 1;
    transform: none;
}

/* ---------- Image fade-in ----------
   Same reasoning as .reveal above — images show immediately rather
   than depending on JS to reveal them after a fade transition. */
img.fade-img {
    opacity: 1;
}

img.fade-img.img-loaded {
    opacity: 1;
}

/* ---------- Card hover lift ---------- */
.featured-card,
.review-card,
.category-tile {
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.featured-card:hover,
.review-card:hover,
.category-tile:hover {
    transform: translateY(-4px);
    box-shadow: 0 8px 20px rgba(11, 37, 69, 0.1);
}

@media (prefers-reduced-motion: reduce) {

    .featured-card,
    .review-card,
    .category-tile {
        transition: none;
    }

    .featured-card:hover,
    .review-card:hover,
    .category-tile:hover {
        transform: none;
    }
}

/* ---------- Continuous marquee ----------
   Genuinely continuous motion, not JS-stepped scrolling: the track's
   content is rendered TWICE in the markup (see front-page.php), and
   this animates it from translateX(0) to translateX(-50%) — since the
   second half is identical to the first, the loop point is invisible
   and it reads as an infinite strip rather than a carousel that
   "arrives" somewhere and pauses.
   Usage: wrap a .marquee-track (rendered with doubled content) in a
   .marquee container with overflow hidden. */
.marquee {
    overflow: hidden;
}

/* The second, duplicated set of cards inside every marquee (required for
   the desktop auto-scroll loop point to be invisible) is wrapped in this
   div. display:flex with a matching gap makes it continue the parent
   row visually and for the width math the animation depends on (total
   track width must be exactly double the "real" content's width) —
   deliberately NOT using display:contents here, which has a long
   history of inconsistent, buggy behavior in Safari/WebKit specifically
   around switching to display:none across a media query, which is
   exactly what this needs to do reliably on mobile (see below). */
.marquee-duplicate {
    display: flex;
    gap: 0.75rem; /* must match .marquee-track's own gap exactly, or the
        spacing where the duplicate set begins won't match the spacing
        between every other card, breaking the illusion of one
        continuous row */
}

.marquee-track {
    display: flex;
    gap: 0.75rem;
    width: max-content;
    animation: sd-marquee-scroll 14s linear infinite;
}

.marquee:hover .marquee-track {
    animation-play-state: paused;
}

.marquee-track .featured-card {
    flex: 0 0 300px; /* was 220px — too narrow once excerpt + timestamp
        were added; forced 4+ lines of wrapped text and looked cramped
        compared to the reference's more spacious cards */
}

/* Static fallback for Browse by Make when there are too few brands
   (under 3) to make a scrolling marquee look smooth rather than
   glitchy — see the count check in front-page.php. Plain flex row,
   no animation, no doubled content. Reuses .make-tile's own sizing
   (200px) so tiles look identical whether shown here or in the
   marquee — only the container behavior differs. */
.tiles-row-static {
    display: flex;
    flex-wrap: wrap; /* without this, 2 tiles at 200px each + gap
        (~412px total) overflows narrow mobile viewports (320-375px) —
        only shows up when there are exactly 2 brands, which is why
        this got missed until now. Wraps to a second row instead of
        overflowing horizontally with no way to scroll to it. */
    gap: 0.75rem;
}

.marquee-track-square .make-tile,
.tiles-row-static .make-tile {
    flex: 0 0 200px; /* was 130px — small compared to every other tile type
        on the site by this point (Featured Report Cards at 300px,
        category tiles at 320px) */
}

.marquee-track-logos {
    gap: 1.5rem;
    animation-duration: 10s;
}

.marquee-track-logos .partner-strip-logo {
    flex: 0 0 auto;
}

@keyframes sd-marquee-scroll {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}

/* Under reduced motion, freeze on the first copy and let the section
   scroll normally instead of animating — the doubled content would
   otherwise just sit there statically doubled-up, which looks broken. */
@media (prefers-reduced-motion: reduce) {
    .marquee-track {
        animation: none;
        overflow-x: auto;
        width: auto;
    }
}

/* ---------- Search bar — floats over the Welcome video band's bottom
   edge (the hero photo carousel it used to overlap was removed; the
   Featured Report Cards marquee below already covers "latest reviews",
   so having both was redundant), same overlap technique as
   .review-filters-card / .partners-filters-card.
   Overlap kept deliberately modest (-1rem, not -3rem) — the Welcome
   band collapses to 0 height after a few seconds, and at that point
   this negative margin pulls the card up toward whatever now precedes
   it (the sticky header, z-index 100). A small overlap never reaches
   the header regardless of what's above it; a large one did, clipping
   the card's label text underneath it. ---------- */
.hero-search {
    padding: 0 1rem;
    margin: -1rem 0 2.5rem;
    position: relative;
    z-index: 3;
}

.hero-search form {
    background: #fff;
    border: 1px solid var(--sd-border);
    border-radius: 12px;
    box-shadow: 0 8px 28px rgba(11, 37, 69, 0.18);
    padding: 1.25rem;
    max-width: 640px;
    margin: 0 auto;
}

.hero-search-label {
    font-weight: 700;
    color: var(--sd-navy);
    font-size: 0.9rem;
    margin-bottom: 0.75rem;
}

.hero-search-row {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0.6rem;
}

.hero-search-row select,
.hero-search-row input[type="text"] {
    padding: 0.65rem;
    border: 1px solid var(--sd-border);
    border-radius: 6px;
    font-size: 0.85rem;
    color: var(--sd-text-secondary);
}

.hero-search-row button {
    border: none;
    cursor: pointer;
}

/* ---------- Browse by Make ---------- */
.browse-by-make {
    padding: 0 1rem;
    margin-bottom: 2.5rem;
}

.section-heading-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 1rem;
}

.section-heading-row h2 {
    color: var(--sd-navy);
    font-size: 1.25rem;
    font-weight: 700;
    margin: 0;
}

.make-tile {
    display: flex;
    flex-direction: column;
    text-decoration: none;
    color: var(--sd-navy);
    background: #fff;
    border: 1px solid var(--sd-border);
    border-radius: 8px;
    overflow: hidden;
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.make-tile:hover {
    transform: translateY(-3px);
    box-shadow: 0 6px 16px rgba(11, 37, 69, 0.08);
}

/* ---------- Trust / FAQ accordion ---------- */
.trust-faq {
    padding: 0 1rem 2.5rem;
    max-width: 640px;
    margin: 0 auto;
}

.trust-faq h2 {
    color: var(--sd-navy);
    font-size: 1.25rem;
    font-weight: 700;
    margin-bottom: 1rem;
    text-align: center;
}

.faq-item {
    border-bottom: 1px solid var(--sd-border);
    padding: 0.9rem 0;
}

.faq-item summary {
    font-weight: 600;
    color: var(--sd-navy);
    font-size: 0.9rem;
    cursor: pointer;
    list-style: none;
}

.faq-item summary::-webkit-details-marker {
    display: none;
}

.faq-item summary::after {
    content: "+";
    float: right;
    font-size: 1.1rem;
    color: var(--sd-red);
}

.faq-item[open] summary::after {
    content: "\2212"; /* minus sign */
}

.faq-item p {
    margin-top: 0.6rem;
    font-size: 0.85rem;
    color: var(--sd-text-secondary);
    line-height: 1.5;
}

/* ==========================================================================
   Tablet and up
   ========================================================================== */
@media (min-width: 640px) {
    .email-capture {
        max-width: 480px;
        margin-left: auto;
        margin-right: auto;
    }

    .hero-search-row {
        grid-template-columns: 1fr 1fr auto;
        align-items: center;
    }
}

/* ==========================================================================
   Desktop
   ========================================================================== */
@media (min-width: 1024px) {
    .welcome-video-band {
        height: 220px;
    }

    .welcome-logo {
        width: 52px;
        height: 52px;
    }

    .welcome-tagline {
        font-size: 1.2rem;
    }
}

/* ==========================================================================
   Mobile carousel override — Latest Report Cards, Body Type, Budget, and
   Browse Popular Brands all switch from an auto-scrolling marquee to a
   manual, swipeable, one-card-at-a-time carousel below 640px. Desktop's
   auto-scroll behavior is completely untouched above this breakpoint —
   these rules only apply below it.

   Three things change together here:
   1. .marquee-duplicate (the second copy of cards, needed for the desktop
      auto-loop) gets hidden entirely. Swiping through the same cards
      twice would be confusing in a manually-driven carousel, unlike the
      desktop auto-scroll case where the loop point is never actually
      seen by the user.
   2. .marquee-track's animation is turned off — motion should now be
      entirely user-driven (swipe), not automatic.
   3. .marquee itself becomes the horizontally-scrollable, snapping
      element, and each tile gets scroll-snap-align so a swipe settles
      cleanly on one card rather than stopping at an arbitrary halfway
      point between two.
   ========================================================================== */
@media (max-width: 639px) {
    .marquee-duplicate {
        display: none;
    }

    .marquee-track {
        animation: none;
    }

    .marquee {
        overflow-x: auto;
        overflow-y: hidden;
        scroll-snap-type: x mandatory;
        -webkit-overflow-scrolling: touch;
        /* Hide the scrollbar itself — swipe is the intended interaction,
           a visible scrollbar here would just look like clutter under
           a card row on a touchscreen. */
        scrollbar-width: none;
    }

    .marquee::-webkit-scrollbar {
        display: none;
    }

    /* One card at a time, sized in vw (viewport width) rather than a
       percentage. This matters: .marquee-track has width:max-content
       (required for the desktop auto-scroll animation), and a
       percentage flex-basis can't resolve cleanly against a
       max-content parent — that's a circular dependency (the parent's
       size depends on its children, the children's size depends on
       the parent), which browsers resolve by falling back to each
       card's natural content size instead of the intended 85%. vw
       units resolve against the actual browser viewport directly,
       completely independent of any parent's computed width, so this
       sidesteps the problem entirely rather than fighting it. */
    .marquee-track .featured-card,
    .marquee-track .category-tile,
    .marquee-track-square .make-tile {
        flex: 0 0 85vw;
        scroll-snap-align: center;
    }

    /* The static (non-marquee) fallback for under 3 brands doesn't need
       any of the above — it's already a short, non-scrolling row that
       fits fine as-is. Explicitly excluded here for clarity, not because
       anything would otherwise break it. */
    .tiles-row-static {
        overflow-x: visible;
    }
}