/* ============================================================================
   MOBILE / TABLET RESPONSIVE LAYER — phones & tablets only (320px–1199px).
   Every rule in this file is wrapped in @media (max-width: 1199.98px) blocks,
   so desktop/laptop screens (>=1200px) are structurally unaffected.
   Loaded LAST on every layout so these rules win at small widths.
   ========================================================================== */

/* ────────────────────────────────────────────────────────────────────────────
   1. GLOBAL — applies to phone + tablet on every portal
   ──────────────────────────────────────────────────────────────────────────── */
@media (max-width: 1199.98px) {

    img,
    svg,
    video,
    canvas,
    iframe {
        max-width: 100%;
        height: auto;
    }

    /* Prevent accidental horizontal scroll from wide fixed-width blocks */
    html,
    body {
        overflow-x: clip;
    }

    /* Any bare table becomes swipeable instead of blowing out the page */
    .table-responsive,
    .dataTables_wrapper {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
}

/* ────────────────────────────────────────────────────────────────────────────
   2. TOUCH & FORM POLISH — phone + tablet
   ──────────────────────────────────────────────────────────────────────────── */
@media (max-width: 1199.98px) {

    /* 16px+ inputs stop iOS Safari auto-zoom on focus */
    input,
    select,
    textarea,
    .form-control,
    .form-select {
        font-size: 16px !important;
    }

    /* Apple HIG 44px minimum touch target for primary interactive elements */
    .btn,
    .btn-apex,
    button[type="submit"],
    a.nav-link,
    .cp-nav-item,
    .page-link {
        min-height: 44px;
    }

    .btn,
    .btn-apex {
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }

    /* Buttons read small on phone/tablet at their desktop sizes (Bootstrap's
       own --bs-btn-font-size is as low as 0.875rem/14px, and .btn-sm drops to
       ~12px) -- bump every button site-wide (marketing pages' .btn-apex,
       and every portal's Bootstrap .btn, including .btn-sm/.btn-lg variants
       which set their own --bs-btn-font-size) to one consistent, legible,
       thumb-friendly size. */
    .btn,
    .btn-apex,
    button[type="submit"] {
        --bs-btn-font-size: 1rem;
        font-size: 1.5rem;
    }
}

/* Touch devices: neutralise hover-only affordances (any width below desktop) */
@media (max-width: 1199.98px) and (hover: none) {

    [data-bs-toggle="tooltip"] {
        pointer-events: auto;
    }

    .nav-dropdown:hover .nav-dropdown-menu {
        /* hover dropdowns are unreliable on touch — JS click path still works */
        pointer-events: auto;
    }
}

/* ────────────────────────────────────────────────────────────────────────────
   3. MARKETING SITE + BOOKING FLOW  (layout/main.blade.php pages)
   ──────────────────────────────────────────────────────────────────────────── */

/* Tablet: 768–1199px */
@media (min-width: 768px) and (max-width: 1199.98px) {

    .container-apex {
        padding-left: 24px;
        padding-right: 24px;
    }
}

/* Header's compact "Book Now" button (nav-cta-group, next to the
   hamburger) reads small on tablet -- it only picks up style.css's
   font-size:1.15rem bump (shared with phone) and keeps its tiny
   12px/15px inline SVG icon otherwise. Scoped to 769-991.98px (769, not
   768, so it never overlaps the phone rule's max-width:768px boundary
   just below), the band where the compact header still shows instead
   of the full desktop nav (Bootstrap's lg breakpoint is 992px) -- phone
   already gets its own icon bump below, and desktop/large-tablet-
   landscape (992px+) shows a completely different header layout
   untouched by this rule.
   line-height is pinned explicitly (not left to the display font's own
   metrics, which run taller than the browser default) -- but padding
   alone still let the bumped font-size push this button visibly taller
   than the "All Services" pill right next to it (that pill has no
   line-height override of its own, so the two were sizing off two
   different mechanisms and drifted apart depending on the display
   font's real metrics). An explicit height pins both to the same
   value regardless of that -- 44px is this codebase's own Apple HIG
   touch-target minimum (see .btn-apex/.btn's min-height:44px further up
   this file), comfortably under the fixed 78px header. */
@media (min-width: 769px) and (max-width: 991.98px) {

    .nav-cta-group .btn-apex-lg {
        font-size: 1.35rem;
        line-height: 1.15;
        padding: 8px 28px;
        min-width: 220px;
        height: 44px;
    }

    .nav-cta-group .btn-apex-lg svg,
    .nav-cta-group .btn-apex-lg .bbd-chev {
        width: 24px;
        height: 24px;
    }
}

/* Phone + small tablet: sticky bottom CTA bar — visible up to 767px
   (extends the theme's own 720px cutoff to the full phone bucket) */
@media (min-width: 721px) and (max-width: 767.98px) {

    .mobile-cta-bar {
        display: flex;
    }

    body {
        padding-bottom: 76px;
    }
}

/* services.blade.php, book-now.blade.php and book-mobile.blade.php all set
   $hideMobileCta = true (layout/main.blade.php's own @if around
   includes.mobile-cta), so no bar ever renders there -- but both the
   720px rule above style.css:7629 and the 721-767.98px one right above
   reserve 76px of body padding-bottom unconditionally, purely off
   viewport width, with no way to know the bar didn't render. That left
   dead blank space below the footer on exactly these 3 pages, on every
   phone width, with nothing sitting in it. */
@media (max-width: 767.98px) {

    body[data-page="services"],
    body[data-page="book"],
    body[data-page="book-mobile"] {
        padding-bottom: 0;
    }
}

/* Phone: 320–767px */
@media (max-width: 767.98px) {

    /* CTA bar: exactly two equal buttons (Book Shop / Book Mobile), thumb-sized,
       with safe-area padding for notch / home-indicator devices */
    .mobile-cta-bar {
        gap: 10px;
        padding: 10px 14px calc(10px + env(safe-area-inset-bottom, 0px));
    }

    .mobile-cta-bar .btn-apex {
        min-height: 48px;
        font-size: 17px;
        white-space: nowrap;
        min-width: 0;
    }

    .mobile-cta-bar .btn-apex svg {
        width: 21px;
        height: 21px;
        flex-shrink: 0;
    }

    /* On very narrow phones (iPhone SE ~375px, Galaxy S8+ ~360px, Galaxy Z
       Fold5 cover screen ~344px) two buttons at 17px font + 21px icon need
       more width than the viewport has. flex items default to min-width:auto,
       which refuses to shrink below the button's own content size — the row
       overflowed and "Book Mobile" got pushed/clipped past the visible edge.
       Scale the bar down instead of just letting it overflow. */
    @media (max-width: 400px) {
        .mobile-cta-bar {
            gap: 8px;
            padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 0px));
        }

        .mobile-cta-bar .btn-apex {
            font-size: 14px;
            padding-left: 12px;
            padding-right: 12px;
            gap: 6px;
        }

        .mobile-cta-bar .btn-apex svg {
            width: 16px;
            height: 16px;
        }
    }

    /* Header's mobile Book Now button (nav-cta-group) already gets a
       bigger font via its own @media (max-width:1024px) rule -- just
       enlarge its icon here to match. */
    .nav-cta-group .btn-apex-lg svg,
    .nav-cta-group .btn-apex-lg .bbd-chev {
        width: 23px;
        height: 23px;
    }

    /* Slide-out drawer's own Book at Shop / Book Mobile buttons and the
       tap-to-open Book Now dropdown (both-modes-enabled businesses) --
       same small icons/text as everywhere else on phone. */
    .mobile-menu .btn-apex {
        font-size: 17px;
    }

    .mobile-menu .btn-apex svg {
        width: 20px;
        height: 20px;
    }

    .bbd-menu a {
        font-size: 1rem;
        padding: 13px 14px;
    }

    .bbd-menu a svg {
        width: 18px;
        height: 18px;
    }

    /* Every other "Book Now" button site-wide (partials/book-btn.blade.php
       and partials/book-cta-pair.blade.php, used in dozens of places --
       service cards, seasonal/packages/membership pages, the footer, FAQ,
       locations section, etc.) shares the same small chevron/arrow icon
       classes. Bump them here; the hero CTA and the sticky mobile-cta-bar
       above both already set a larger size on more specific selectors
       (.hero-cta .btn-apex svg / .mobile-cta-bar .btn-apex svg), so they
       keep their own bigger icons rather than being pulled back down to
       this general size. */
    .bbd-chev,
    .bkbtn-arrow {
        width: 16px;
        height: 16px;
    }

    /* Hero "Book Now" CTA -- the single most important button on the whole
       site (first thing a mobile visitor sees), so it gets a bigger, bolder
       treatment than the general button bump above. */
    .hero-cta .btn-apex {
        font-size: 19px;
        padding: 16px 20px;
        /* .hero-cta's buttons stack on phone (flex-wrap) but each one
           still only sizes to its own label's width -- "Book mobile
           slot" and "Check my ZIP" ended up two different widths,
           reading as a staggered, unbalanced pair instead of a matched
           set of stacked CTAs. */
        width: 100%;
        text-align: center;
    }

    .hero-cta .btn-apex svg {
        width: 20px;
        height: 20px;
    }

    /* Homepage hero only: on phone the sticky bottom Book at Shop/Book
       Mobile bar is already always on screen, so the in-hero "Book Now"
       button, the trust badges (Fully insured / IDA certified / No-scratch
       guarantee) and the live-activity ticker are redundant clutter above
       the fold here. Scoped to data-page="home" -- .hero-cta/.hero-trust
       are shared with other pages (membership, ceramic-coating, mobile-
       detailing, app-page) where they're still the only booking CTA and
       stay visible. */
    body[data-page="home"] .hero-cta,
    body[data-page="home"] .hero-trust,
    body[data-page="home"] .hero-ticker-wrap {
        display: none;
    }

    /* "Every service your car needs, under one roof" services grid -- each
       card's "Book now" pill/link reads too small on phone at its desktop
       size (as low as 0.8rem/12.8px). */
    .sc-learn,
    .sc-learn-pill,
    .sc-back-cta {
        font-size: 15px;
        padding: 12px 22px;
    }

    /* Content-section button pairs (Book at Shop/Book Mobile, etc.) are
       plain flex-wrap rows with no explicit width -- side by side when
       there's room, otherwise each button just wraps at its own natural
       (now-larger, since the button font-size bump above widened them)
       content width, which can leave two differently-sized buttons
       stacked with uneven, slightly odd-looking edges instead of a clean
       stack. Force a deliberate full-width stack here instead of leaving
       it to organic wrap.
       .gc-cta-row (Buy a gift card / Amount Check) is deliberately NOT
       in this list -- style.css's own @media (max-width:767.98px) block
       right after .gc-promo-section's rules sizes those two to content
       instead, since their labels are close enough in length that a
       forced 100% stack just reads as two oversized, oval-shaped
       buttons rather than the clean stack this rule is for. */
    .wcu-cta,
    .sd-cta-row,
    .abt-cta-row {
        flex-direction: column;
        align-items: stretch;
    }

    .wcu-cta .btn-apex,
    .sd-cta-row .btn-apex,
    .abt-cta-row .btn-apex {
        width: 100%;
    }

    /* Membership page: the plan-card CTA ("Start Detail plan"), the
       private-events CTA ("Book a Private Event") and the
       approach-section CTA ("View Membership Plans") each sit alone in
       a single-column grid item on phone (.mem-card in .mem-grid,
       etc). .btn-apex's desktop padding (14px 50px) plus its own
       mobile font-size bump above (1.5rem) makes labels this long
       wider than the column -- and a grid item's automatic minimum
       width defaults to its content's min-content size, so the button was
       forcing the whole column past the edge of the phone screen (silently
       clipped by body's overflow-x:hidden/clip rather than causing a visible
       scrollbar). Let these columns shrink to the viewport, then give their
       buttons a phone-sized width/padding instead of their desktop min-content. */
    .mem-card,
    .mem-private-content,
    .mem-approach-content {
        min-width: 0;
    }

    .mem-card .btn-apex,
    .mem-private-content .btn-apex,
    .mem-approach-content .btn-apex,
    .bk11-cta-row .btn-apex {
        width: 100%;
        padding-left: 20px;
        padding-right: 20px;
        white-space: normal;
    }

    /* "View Membership Plans" (22 chars) still wrapped to 2-4 lines even
       full-width at the site-wide 1.5rem bump -- a pill-radius button
       that tall reads as a bloated blob, not a button. Sized down the
       same way .mem-card .btn-apex already is below, close to
       .btn-apex's own desktop 1.1rem, so the label fits one line down
       to the narrowest real phones (Galaxy Z Fold5 cover screen, 344px). */
    .mem-approach-content .btn-apex {
        font-size: 1rem;
        padding-top: 12px;
        padding-bottom: 12px;
    }

    /* Plan-card CTAs ("Start Shine/Detail/Elite plan") still wrapped to
       two lines even full-width, at the site-wide mobile bump to
       1.5rem (~30px tall glyphs) -- inside an 85%-wide card that's a
       much tighter column than the private-events/approach-section
       CTAs sharing the rule above, which stay full-container-width and
       have room for it. Sized back down close to .btn-apex's own
       desktop 1.1rem so the label fits one line at this width. */
    .mem-card .btn-apex {
        font-size: 1.05rem;
        padding-top: 12px;
        padding-bottom: 12px;
    }

    /* .mem-card itself (smart.css) is sized for a full desktop-width
       column: 32px padding, a 190px image, a 3.2rem price and 5 feature
       rows in a 0.93rem list -- fine at its original 3-up desktop grid
       width, but this same markup now also renders inside the 85%-wide
       phone slider (see the @media max-width:991.98px block further
       down). On the narrowest real devices (Galaxy Z Fold5 cover
       screen, 344px -- an 85% card is ~290px) every line of the
       tagline and each feature row wraps onto extra lines it never
       needed on desktop, stacking the card's total height well past
       the viewport and pushing its own CTA button down past the fold
       or under the sticky Book at Shop/Mobile bar. Scale every piece
       down together -- padding, image, name, price, tagline and
       feature rows -- so the card reads as a compact phone card
       instead of a shrunk desktop one. The tagline also gets a
       2-line clamp instead of relying on wrapping to stop naturally,
       since at this width even the shortest plan's description ran
       past 2 lines. */
    .mem-card {
        padding: 22px;
    }

    .mem-card-img {
        margin: -22px -22px 16px;
        height: 140px;
    }

    .mem-name {
        font-size: 14px;
        margin-bottom: 4px;
    }

    .mem-tagline {
        font-size: 0.82rem;
        line-height: 1.4;
        margin-bottom: 12px;
        min-height: 0;
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
    }

    .mem-price {
        font-size: 2.1rem;
    }

    .mem-features {
        margin: 14px 0;
    }

    .mem-features li {
        padding: 7px 0;
        font-size: 0.82rem;
        gap: 8px;
    }

    /* Below 400px (iPhone SE 375px, Galaxy S8+ 360px, Galaxy Z Fold5
       cover screen 344px) the 85%-wide card itself is only ~290-320px,
       so "Start Shine/Detail/Elite plan" at the 1.05rem size above
       still wrapped to 2 lines and doubled the button's height again.
       Trim font/padding/icon further so it fits one line even on the
       Fold5's cover screen -- the narrowest real device this site
       needs to render on. */
    @media (max-width: 400px) {
        .mem-card .btn-apex {
            font-size: 0.92rem;
            padding-left: 14px;
            padding-right: 14px;
            gap: 6px;
        }

        .mem-card .btn-apex svg {
            width: 14px;
            height: 14px;
        }

        .mem-card-img {
            height: 110px;
        }

        .mem-price {
            font-size: 1.85rem;
        }
    }

    /* Homepage before/after marquee CTA — see .ba-cta-text-short/-full in
       style.css for why the label itself swaps on phone instead of
       stretching this button full-width like the membership ones above:
       wrapping "See all 300+ before / after photos" onto two lines
       inside a fully-rounded pill just looked like a stretched oval, not
       a fix. Padding still needs trimming here even with the short
       label, since the mobile font-size bump above (1.5rem) still makes
       the desktop 50px side padding excessive. */
    .ba-marquee-section .btn-apex-dark {
        padding-left: 22px;
        padding-right: 22px;
    }

    /* Membership hero stats (47% / 3 / $180 / 2.4k) rely on flex-wrap to
       fall into rows, which only wraps 2-per-line if the fonts happen to be
       narrow enough -- on phone, force a real 2-column grid so it's always
       exactly 2 per row regardless of font metrics. */
    .mem-hero-stats {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        gap: 20px 16px;
    }

    /* Membership page: Monthly/Annual billing toggle. "Annual" carries an
       inline "Save 15%" pill that wraps onto its own line at phone widths,
       leaving it taller than the single-line "Monthly" button next to it;
       also give both a real touch target (no min-height of their own
       otherwise, unlike .btn-apex). [data-bill] only matches these two
       buttons -- .account-tab itself is shared with account.blade.php's
       unrelated tab group, so it's left alone. */
    [data-bill] {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 4px;
        min-height: 44px;
        white-space: nowrap;
        font-size: 13px;
    }

    /* Marketing sections: kill fixed side-by-side splits that survive the
       theme's own queries. Overrides BOTH padding-top and -bottom now
       (style.css's own max-width:768px rule set clamp(90px,20vw,130px)
       top / clamp(40px,5vw,60px) bottom -- a lot of empty dark space
       above/below a hero that's just a breadcrumb, heading and one
       line of copy on phone). */
    .page-header {
        padding: 56px 0 28px;
    }

    /* Reviews page quicknav (Overview/Google Reviews/Website Reviews):
       base rule is flex-wrap:wrap + justify-content:center, so on
       narrow phones the 3 pills wrap to 2-3 uneven centered rows
       instead of reading as one tab bar. Matches the gallery filter
       bar's own pattern (.glr-filter-inner) -- nowrap + horizontal
       scroll instead of wrapping, scrollbar hidden. flex-start (not
       center) so the scrollable content's start edge isn't pushed
       off-screen the way center+overflow can. */
    body[data-page="reviews"] .reviews-quicknav {
        flex-wrap: nowrap;
        justify-content: flex-start;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
    }

    body[data-page="reviews"] .reviews-quicknav::-webkit-scrollbar {
        display: none;
    }

    body[data-page="reviews"] .reviews-quicknav a {
        flex-shrink: 0;
    }

    /* Book at Shop (book-now.blade.php) and Mobile Booking
       (book-mobile.blade.php): the dark hero (badge/headline/subtext/
       cross-sell box or checkmarks) just repeats what the booking form
       right after it already says, and its own padding (~90-130px top)
       left a huge empty gap once everything but the breadcrumb was
       hidden. Hide the whole section on mobile instead -- style.css's
       .book-mobile-breadcrumb (a separate white, low-padding bar rendered
       right before this section on each page) takes over showing the
       breadcrumb there. */
    body[data-page="book"] .page-header,
    body[data-page="book-mobile"] .page-header {
        display: none;
    }

    /* Book at Shop: the live summary sidebar (Your Booking / Why book
       online?) and the trust strip below the form (Fully insured, IDA-
       certified, No-scratch guarantee, 4.9/5 reviews) just stack under the
       form on mobile with no real estate saved -- hide both, keeping only
       the form itself. */
    body[data-page="book"] .book-summary,
    body[data-page="book"] .section-tight.bg-paper {
        display: none;
    }

    /* Mobile Booking: same story for its own Booking Summary sidebar --
       book-mobile.blade.php's Review sub-step has its own #mb-overview-mobile
       card (mobile-only, see that file's <style> block) that takes over
       showing this same info inline in the last step instead. */
    body[data-page="book-mobile"] .mb-summary {
        display: none;
    }

    /* 3-step booking stepper (Details/Date/Confirm): min-width:0 (added in
       style.css) stops the 3rd step from overflowing off-screen, but at
       14px/18px padding + 13px font there still isn't enough room for
       "Confirm" to sit comfortably next to its number circle -- tighten
       both so all three fit with breathing room instead of just barely
       not overflowing. */
    .book-step {
        padding: 10px 8px;
        gap: 6px;
        font-size: 11.5px;
    }

    .book-step .n {
        width: 18px;
        height: 18px;
        font-size: 10px;
    }

    /* "Something else? RV, boat, motorcycle — contact us" vehicle-size tile
       (book-now.blade.php and book-mobile.blade.php) hidden on phones -- it's
       an edge case that just eats space in the 2-up mobile tile grid. */
    .book-tile-grid .book-tile.ist-361eeb9a {
        display: none;
    }

    /* Year / Make & Model row: .form-row-2's own max-width:600px rule
       collapses it to one field per line on phones, but these two fields
       are short enough to sit side by side comfortably -- keep them 2-up
       (scoped to this row only, not every .form-row-2 -- e.g. Full
       name/Phone needs the extra width and should keep stacking). */
    .form-row-2.ist-64e186c1 {
        grid-template-columns: 1fr 1fr;
        gap: 10px;
    }

    /* Booking pages: summary/cart panels stack under the form. .mb-summary
       (book-mobile.blade.php) carries Bootstrap's sticky-top utility class
       for a desktop "sticky sidebar that follows scroll" effect -- on phone
       that instead pins the summary card mid-scroll, where it visually
       overlaps the wizard's fixed bottom-nav "Next" button. Force it back
       into normal flow here. */
    .booking-summary,
    .cart-panel,
    .order-summary,
    .mb-summary {
        position: static !important;
        width: 100% !important;
        max-width: 100% !important;
        margin-top: 16px;
    }

    /* Step indicators become compact */
    .steps,
    .step-indicator,
    .booking-steps {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        flex-wrap: nowrap;
    }

    /* Package grids forced to 3-up via inline styles collapse to 1-col
       (!important is required to beat the inline declaration) */
    .pkg-grid {
        grid-template-columns: 1fr !important;
    }

    /* Booking calendar: comfortable touch cells (Shop booking's .bk-cal-*
       and Mobile booking's identically-structured .mb-cal-*) */
    .bk-cal-cell,
    .mb-cal-cell {
        min-height: 44px;
    }

    .bk-cal-nav,
    .mb-cal-nav {
        min-width: 44px;
        min-height: 44px;
    }

    /* Add-on tiles single column on phone (theme switches at 420px only) */
    #addon-tiles {
        grid-template-columns: 1fr !important;
    }

    /* Wizard nav buttons: full-width, thumb-friendly. .btn-apex's base
       padding (14px 50px = 100px just horizontally) plus white-space:nowrap
       gives each button a ~200px+ unshrinkable min-content width -- with no
       min-width:0, flex:1 alone can't shrink two of them below that floor,
       so "Continue" overflowed off-screen instead of sharing the row evenly
       with "Back" (same flex min-width:auto pitfall as .svp-filter-foot). */
    .bk-nav-btns .btn-apex,
    .book-nav .btn-apex {
        flex: 1;
        min-width: 0;
        min-height: 48px;
        padding: 14px 12px;
        font-size: 15px;
    }

    .bk-nav-btns .btn-apex svg,
    .book-nav .btn-apex svg {
        width: 21px;
        height: 21px;
    }
}

/* Membership plans (#plans): the 3-card grid (smart.css) collapses to a
   single stacked column below 980px, which meant scrolling through 3
   full-height cards stacked one under another -- brutal on a phone,
   where each card runs most of a screen tall. Turn the stack into a
   swipeable, auto-advancing slider (one card, with the next peeking in)
   instead, on both tablet and phone -- same overflow-x + scroll-snap +
   hidden-scrollbar pattern as .stat-strip-inner and .bk-slot-pills
   elsewhere in this file. main.js's wireMemPlansAutoSlide() drives the
   actual autoplay/pause-on-touch/loop; it reads this CSS's computed
   display/scrollWidth rather than hardcoding a breakpoint of its own,
   so widening this range to cover phone is the only change needed to
   turn autoplay on there too. */
@media (max-width: 991.98px) {

    body[data-page="membership"] #plans .mem-grid {
        display: flex !important;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        gap: 16px;
        margin: 0 -24px;
        padding: 4px 24px 12px;
    }

    body[data-page="membership"] #plans .mem-grid::-webkit-scrollbar {
        display: none;
    }

    body[data-page="membership"] #plans .mem-card {
        flex: 0 0 85%;
        max-width: 85%;
        scroll-snap-align: center;
    }
}

/* Tablet: inline 3-up package grids go 2-up */
@media (min-width: 768px) and (max-width: 991.98px) {

    .pkg-grid {
        grid-template-columns: repeat(2, 1fr) !important;
    }

    /* Book at Shop / Mobile Booking: same reasoning as the phone-only
       rule above (~120 lines up) -- the dark hero just repeats what the
       booking form right after it already says. style.css's
       .book-mobile-breadcrumb (widened to this same 991.98px upper
       bound) takes over showing the breadcrumb here too. */
    body[data-page="book"] .page-header,
    body[data-page="book-mobile"] .page-header {
        display: none;
    }

    /* Book at Shop: the live summary sidebar (.book-summary, "Your
       Booking" -- Location/Service/Vehicle/Date + Estimate) just
       stacks full-width under the form on tablet (col-lg-4 only
       becomes a real sidebar column at Bootstrap's lg breakpoint,
       992px) with no real estate saved. Same reasoning as the
       phone-only rule further up this file -- hide it here too;
       book-now.blade.php's own .bk-review-summary-card (widened to
       this same 991.98px upper bound) takes over showing the same
       info inline at the Confirm step instead. */
    body[data-page="book"] .book-summary {
        display: none;
    }

    /* Mobile Booking: same story for its own Booking Summary sidebar
       -- book-mobile.blade.php's #mb-overview-mobile (widened to this
       same 991.98px upper bound) takes over showing this same info
       inline in the last step instead. */
    body[data-page="book-mobile"] .mb-summary {
        display: none;
    }

    /* Membership page hero: desktop's 64px top padding, 40px inner gap
       and 56px bottom padding are sized for the 2-column layout -- once
       .mem-hero-inner drops to a single stacked column (existing
       max-width:900px rule in style.css), the same values leave a lot
       of dead air above the eyebrow pill, between the CTA and the
       badge row, and before the trust strip below. */
    .mem-hero {
        padding-top: 32px;
    }

    .mem-hero-inner {
        gap: 24px;
        padding-bottom: 28px;
    }

    /* Membership plans (#plans) heading/toggle spacing -- see the
       standalone @media (max-width: 991.98px) block further down for
       the slider itself (.mem-grid/.mem-card), which covers phone as
       well as this tablet range. */
    body[data-page="membership"] #plans .section-head {
        margin-bottom: 28px;
    }

    body[data-page="membership"] #plans .ist-c828b933 {
        margin-bottom: 24px !important;
    }

    /* "A New Approach to Car Care" (Safety First / Proven Results /
       Curated Experience + View Membership Plans CTA) sits between the
       hero and the plans grid -- on tablet it's just restating trust
       points the hero copy and the plan cards right after it already
       cover, same reasoning as the dark booking hero hidden above.
       Hidden here rather than removed so desktop/phone (where it has
       real room and isn't sandwiched between two other sections making
       the same points) keep it as-is. */
    body[data-page="membership"] .mem-approach-section {
        display: none;
    }

    /* Gallery hero: the shared <=900px block (style.css) stacks copy then
       preview as two big blocks, each carrying its own desktop-sized
       margin-bottom on top of the stack's own 48px gap -- badge, h1, sub
       and stats each add 20-32px of their own, so tablet accumulated a
       lot of dead air top to bottom. The h1's two forced <br>s also cost
       a full extra line here that the copy doesn't need at this width.
       And copy-then-preview as two undivided blocks buries the actual
       before/after photo -- the point of this whole page -- below a full
       screen of text. Unwrap .glr-hero-copy so every element becomes an
       ordinable flex child of .glr-hero-inner directly: tighten the
       spacing with one flex gap instead of five separate margins, drop
       the forced line breaks and font-size the h1 to fit on one line,
       and move the preview up to right after the headline/subtext
       instead of dead last. */
    body[data-page="gallery"] .glr-hero-inner {
        display: flex;
        flex-direction: column;
        /* The base rule (style.css) sets align-items:center for the
           desktop 2-column grid, where it only centers each column
           vertically against the other. In a column-direction flex
           container that same property centers every child
           *horizontally* instead -- left-align everything here, same as
           the original stacked layout. */
        align-items: flex-start;
        gap: 10px;
        padding-bottom: 20px;
    }

    body[data-page="gallery"] .glr-hero-copy {
        display: contents;
    }

    body[data-page="gallery"] .breadcrumbs {
        order: 1;
        /* Base rule's own margin-bottom:18px stacked on top of the flex
           gap above -- 32px total to the badge, more than double every
           other gap in this stack. */
        margin-bottom: 0;
    }

    body[data-page="gallery"] .glr-badge {
        order: 2;
        margin-bottom: 0;
    }

    body[data-page="gallery"] .glr-hero-h1 {
        order: 3;
        margin-bottom: 0;
        font-size: 1.7rem;
        white-space: nowrap;
    }

    body[data-page="gallery"] .glr-hero-h1 br {
        display: none;
    }

    /* .glr-hero-accent (the "100% real results." span) is display:block
       in the base rule -- hiding the <br>s above still left this on its
       own forced line regardless, since display:block does that on its
       own independent of white-space. Needs to be inline for the
       headline to actually run as one line. */
    body[data-page="gallery"] .glr-hero-accent {
        display: inline;
    }

    /* The descriptive paragraph ("Shot in our shop on the day of
       service...") isn't in either reference the request was based on --
       both show the photo landing right under the headline -- and at
       ~90px tall it was the single biggest gap in this stack, more than
       every other element's own spacing combined. Hidden here rather
       than removed so desktop/phone (where the 2-column/stacked layouts
       have the room and copy still reads as a paragraph, not a single
       run-on line) keep it as-is. */
    body[data-page="gallery"] .glr-hero-sub {
        display: none;
    }

    body[data-page="gallery"] .glr-hero-preview {
        order: 4;
        padding-bottom: 0;
        /* Same fix as style.css's <=900px block, needed again here since
           that block's own width:100%/max-width:560px doesn't reach
           901-991.98px: without an explicit width, "margin:0 auto"
           shrinks a flex/grid item to fit-content, but every image here
           is a background on an absolutely-positioned div with no
           intrinsic size of its own -- fit-content had nothing to
           measure and the preview collapsed to 0x0 in that sliver. */
        width: 100%;
        max-width: 560px;
        /* margin:0, not the shared block's "0 auto" -- everything else in
           this stack (badge/title/stats/CTA) is left-aligned, so
           centering just the photo made it the one element visibly out
           of line with the rest. */
        margin: 0;
    }

    body[data-page="gallery"] .glr-stats {
        order: 5;
        margin-bottom: 0;
    }

    body[data-page="gallery"] .glr-hero-copy > .bbd-wrap,
    body[data-page="gallery"] .glr-hero-copy > .glr-hero-cta {
        order: 6;
    }

    /* Category sections (Full Detail, Ceramic Coating, etc.) only had a
       ≤760px phone override; tablet fell through to the desktop values
       (30px/56px section padding + 40px head margin), which reads as far
       too much empty space above/below each category on tablet. */
    body[data-page="gallery"] .gallery-cat-section {
        padding: 24px 0 32px;
    }

    body[data-page="gallery"] .gallery-cat-head {
        margin-bottom: 20px;
    }
}

/* Gallery hero on short-viewport landscape tablets/smart displays (e.g.
   Nest Hub, 1024x600) -- the block above only reaches 991.98px wide, so
   at 992-1199.98px style.css's own 2-column grid (its only stacking
   breakpoint is max-width:900px) stays active with full desktop padding
   and the 3-line headline. That's fine on a genuinely tall viewport, but
   on a short one the copy column alone fills the whole screen height,
   pushing the before/after photo -- the actual point of the page --
   below a full scroll on first load. Scoped by max-height (not just
   width) so real desktop-height windows and tall tablets in this width
   band keep the normal 2-column layout; only short/landscape viewports
   get the same stack-and-tighten treatment as the block above. */
@media (min-width: 992px) and (max-width: 1199.98px) and (max-height: 700px) {
    body[data-page="gallery"] .glr-hero-inner {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        gap: 10px;
        padding-bottom: 20px;
    }

    body[data-page="gallery"] .glr-hero-copy {
        display: contents;
    }

    body[data-page="gallery"] .breadcrumbs {
        order: 1;
        margin-bottom: 0;
    }

    body[data-page="gallery"] .glr-badge {
        order: 2;
        margin-bottom: 0;
    }

    body[data-page="gallery"] .glr-hero-h1 {
        order: 3;
        margin-bottom: 0;
        font-size: 1.9rem;
        white-space: nowrap;
    }

    body[data-page="gallery"] .glr-hero-h1 br {
        display: none;
    }

    body[data-page="gallery"] .glr-hero-accent {
        display: inline;
    }

    /* Same reasoning as the 768-991.98px block: at ~90px tall this is the
       single biggest gap in the stack, and the photo/CTA/browse-tabs
       below already carry the page. */
    body[data-page="gallery"] .glr-hero-sub {
        display: none;
    }

    body[data-page="gallery"] .glr-hero-preview {
        order: 4;
        padding-bottom: 0;
        width: 100%;
        max-width: 480px;
        margin: 0;
    }

    body[data-page="gallery"] .glr-stats {
        order: 5;
        margin-bottom: 0;
    }

    body[data-page="gallery"] .glr-hero-copy > .bbd-wrap,
    body[data-page="gallery"] .glr-hero-copy > .glr-hero-cta {
        order: 6;
    }

    body[data-page="gallery"] .gallery-cat-section {
        padding: 24px 0 32px;
    }

    body[data-page="gallery"] .gallery-cat-head {
        margin-bottom: 20px;
    }
}

/* Book at Shop / Mobile Booking hero on short-viewport landscape
   tablets/smart displays (Nest Hub 1024x600 and similar): the block
   above (768-991.98px) hides the full dark hero and lets the compact
   white .book-mobile-breadcrumb bar take over, but that only reaches
   991.98px wide. Above it, style.css's own .bkh-visual only stacks the
   ticket below the copy once the section drops under 1150px -- so
   992-1149.98px renders the FULL hero (badge/h1/subtext/checklist/CTA)
   with the ticket card stacked underneath as well, taller than a short
   viewport can show without a full scroll before the actual booking
   form appears. Same fix as the block above, just widened to cover the
   gap: hide the hero, show the breadcrumb bar instead. */
@media (min-width: 992px) and (max-width: 1199.98px) and (max-height: 700px) {
    body[data-page="book"] .page-header,
    body[data-page="book-mobile"] .page-header {
        display: none;
    }

    .book-mobile-breadcrumb {
        display: block;
    }
}

/* Rewards hero on short-viewport landscape tablets/smart displays: unlike
   the gallery/book pages above, style.css already stacks .rwh-visual
   (the points-ring card) under the copy at this width -- its own
   breakpoint is max-width:1150px, comfortably wider than this gap. The
   problem here isn't which breakpoint fires, it's that the stacked total
   (badge/h1/subtext + the ~340px-tall card) is taller than a short
   viewport, leaving only the copy visible and the ring cut off at the
   bottom edge on first load. Tighten the hero padding/spacing and drop
   the subtext (same reasoning as .glr-hero-sub above: the card and the
   page's own body copy below already carry the "how it works" message)
   so the ring fits mostly or fully in view instead. */
@media (min-width: 768px) and (max-width: 1149.98px) and (max-height: 700px) {
    body[data-page="rewards"] .page-header {
        padding-top: 56px;
        padding-bottom: 24px;
    }

    body[data-page="rewards"] .rwh-left p {
        display: none;
    }

    body[data-page="rewards"] .rwh-visual {
        margin-top: 12px;
    }
}

@media (min-width: 768px) and (max-width: 991.98px) {
    /* Locations page hero: min-height:460px + 72px top/bottom padding on
       .locx-hero-inner is sized for desktop; on tablet the actual copy
       (badge/title/lead/stats) is far shorter than 460px, so the flex
       centering pads the difference in equally on top and bottom, on top
       of the already-large 72px padding -- reads as excessive top/bottom
       whitespace. Drop the min-height floor and tighten the padding so
       the section hugs its real content. */
    body[data-page="locations"] .locx-hero {
        min-height: auto;
    }

    body[data-page="locations"] .locx-hero-inner {
        padding: 36px 24px;
    }

    /* Locations list/map: the base breakpoint (max-width:980px) that
       stacks .locx-explore-grid to a single column doesn't reach the
       981-991.98px sliver, so that narrow strip reverted to the desktop
       380px-list/rest-map two-column layout -- squeezing both. Force the
       single-column stack across the FULL tablet range, and turn the
       list itself into a 2-up grid (it was a single-column vertical
       stack of full-width cards, one per row) now that it has the full
       container width to work with. */
    body[data-page="locations"] .locx-explore-grid {
        grid-template-columns: 1fr;
    }

    body[data-page="locations"] .locx-list {
        display: grid;
        grid-template-columns: repeat(2, 1fr);
        gap: 14px;
        max-height: none;
        overflow-y: visible;
        padding-right: 0;
    }

    body[data-page="locations"] .locx-map {
        min-height: 380px;
    }

    /* Gift card tiles ("Pick an amount"): the existing .gift-grid 2-up
       rule only reaches max-width:820px, so 821-991.98px reverted to
       the desktop 4-up grid -- narrower/shorter tiles with no room for
       the new dummy content below. Force 2-up across the full tablet
       range so every tile has consistent real estate to work with. */
    body[data-page="gift"] .gift-grid {
        grid-template-columns: repeat(2, 1fr);
    }

    /* 1.6/1 was tuned for the desktop 4-up tile. At 2-up the tiles are
       nearly twice as wide, so the same ratio made them tall enough to
       dominate the page. The stacked column is capped in style.css;
       this just takes a little more height back off. */
    body[data-page="gift"] .gift-tile {
        aspect-ratio: 1.7 / 1;
    }

    /* Tablet's 2-up grid gives each tile a lot more real estate than
       the label+amount alone fills, so it read as sparse/empty compared
       to a real card. Show the dummy chip/number/expiry markup
       (present in the DOM at every breakpoint, hidden by default in
       style.css) only here. Scoped to .gift-tile specifically -- the
       gift-tile-chip partial is reused on .gift-preview-card (the "Pick
       an amount" tile markup and the real preview card share the same
       partial/class), and an unscoped `.gift-tile-chip` selector here
       used to reposition the preview card's own chip too, landing it
       directly on top of the "GIFT" badge in the card header. */
    body[data-page="gift"] .gift-tile .gift-tile-chip {
        display: block;
        position: absolute;
        top: 18px;
        right: 18px;
        z-index: 2;
    }

    body[data-page="gift"] .gift-tile-number {
        display: block;
        margin-top: auto;
        margin-bottom: 14px;
        font-size: .95rem;
        letter-spacing: .08em;
        color: var(--apex-grey-300);
        position: relative;
        z-index: 2;
    }

    body[data-page="gift"] .gift-tile-footer {
        display: flex;
        align-items: flex-end;
        justify-content: space-between;
        gap: 8px;
    }

    body[data-page="gift"] .gift-tile-expiry {
        display: block;
        font-size: 9px;
        letter-spacing: .08em;
        text-transform: uppercase;
        color: var(--apex-grey-300);
        position: relative;
        z-index: 2;
    }


    /* "The car-person gift problem, solved." dark section: .section's
       own padding clamps down to near-nothing at these widths (max
       25px), which reads as cramped against the panels directly above
       and below it. A little breathing room, this page only. */
    body[data-page="gift"] .feature-grid {
        padding-top: 20px;
        padding-bottom: 20px;
    }

    /* Contact page info cards (Phone/Email/Headquarters/Live Chat):
       .ct-info-col is a plain single-column flex stack (style.css's own
       max-width:1024px rule keeps it that way through tablet), which on
       this wider band leaves 4 cards each stretched edge-to-edge with a
       lot of empty horizontal space inside every row. 2-up instead --
       .ct-section-head keeps its own full-width row above them. */
    body[data-page="contact"] .ct-info-col {
        flex-direction: row;
        flex-wrap: wrap;
    }

    body[data-page="contact"] .ct-section-head {
        flex: 1 1 100%;
    }

    body[data-page="contact"] .ct-card {
        flex: 1 1 calc(50% - 6px);
        min-width: 0;
    }

    /* Business Hours card: desktop's 40px vertical card padding, the
       header's own 48px combined margin+padding-bottom, and the
       section's 96px bottom padding only shrink at phone widths (see
       style.css's max-width:768px rule) -- tablet was still getting
       the full desktop spacing. Trim it, and use some of what that
       frees up to make the day/time rows read a little larger and
       sit a little closer together. */
    body[data-page="contact"] .ct-hours-section {
        padding-bottom: 56px;
    }

    body[data-page="contact"] .ct-hours-card {
        padding: 28px 28px;
    }

    body[data-page="contact"] .ct-hours-top {
        margin-bottom: 18px;
        padding-bottom: 14px;
    }

    body[data-page="contact"] .ct-hours-row {
        padding: 10px 0;
    }

    body[data-page="contact"] .ct-hours-day,
    body[data-page="contact"] .ct-hours-time {
        font-size: 1.02rem;
    }

    /* Dark page-header hero (Rewards, Services, Careers, Story, etc.):
       only got a smaller clamp at phone widths (see style.css's own
       max-width:768px rule right below the base .page-header rule) --
       tablet was still stuck with desktop's clamp(100px,12vw,160px)
       top / clamp(50px,6vw,90px) bottom, a lot of dead dark space
       above/below a hero that's just a breadcrumb, eyebrow pill,
       heading and one line of copy. */
    .page-header {
        padding: clamp(64px, 9vw, 96px) 0 clamp(32px, 4vw, 48px);
    }

    /* Rewards "Tiers" section (Garage/Driveway/Concierge): reuses the
       same .mem-grid/.mem-card as the membership page's plan cards
       (smart.css), which collapses to a single stacked column below
       980px -- 3 tall cards (price + 4-5 features + CTA each) end up
       one under another. Slider instead, same swipeable/scroll-snap
       pattern as #plans .mem-grid on the membership page, plus tighter
       internal spacing so each card itself reads shorter too. */
    body[data-page="rewards"] .mem-grid {
        display: flex !important;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        gap: 16px;
        margin: 0 -24px;
        padding: 20px 24px 28px;
    }

    body[data-page="rewards"] .mem-grid::-webkit-scrollbar {
        display: none;
    }

    body[data-page="rewards"] .mem-card {
        flex: 0 0 82%;
        max-width: 82%;
        scroll-snap-align: center;
        padding: 22px;
    }

    body[data-page="rewards"] .mem-tagline {
        margin-bottom: 12px;
        min-height: 0;
    }

    body[data-page="rewards"] .mem-price {
        font-size: 2.4rem;
    }

    body[data-page="rewards"] .mem-features {
        margin: 14px 0;
    }

    body[data-page="rewards"] .mem-features li {
        padding: 7px 0;
    }

    /* "Join free" section (#join): the two columns (copy+list / form
       card) stack on tablet, and Bootstrap's g-5 row gutter alone adds
       48px of margin-top above the form -- same fix as the gift cards
       page's form/preview columns. */
    body[data-page="rewards"] #join .row.g-5 {
        --bs-gutter-y: 1.5rem;
    }

    /* The 3 checklist items ("500 bonus points…", etc.) inherit
       .ist-13c4836d's color:var(--apex-grey-700) !important
       (extracted-inline.css) -- a dark slate meant for a light
       background, but #join is a .section.bg-paper (dark) section.
       style.css's own .section.bg-paper text-color overrides cover
       h2-h4/.muted/.feature p but never anticipated this hashed class,
       so it's rendered dull/low-contrast grey-on-dark. Match the same
       lighter grey the rest of this dark section already uses, and
       lay out 2-up instead of stacked, with the orphaned 3rd item
       centered -- same grid + last-child-spans-and-centers technique
       as the gift cards page's .feature-grid fix above. */
    body[data-page="rewards"] #join .ist-13c4836d {
        color: var(--apex-grey-300) !important;
        display: grid !important;
        grid-template-columns: repeat(2, 1fr);
        gap: 4px 20px;
    }

    body[data-page="rewards"] #join .ist-13c4836d > li:last-child {
        grid-column: 1 / -1;
        max-width: calc(50% - 10px);
        margin: 0 auto;
    }
}

/* Contact page "Live Chat" card: shares one flex row (icon + body) with
   every other info card, but is the only one with a 4th item
   (.ct-online-badge, the green "Online" pill) competing for the same
   row -- phones don't have the width to spare, so .ct-card-body got
   squeezed down to ~100px wide, "Chat on Website" wrapped onto 2 lines,
   and the card ended up visibly taller and misaligned next to its three
   siblings (confirmed down to 344px, the Galaxy Z Fold5 cover screen).
   Let the badge drop to its own line below the text instead of fighting
   it for space -- still a taller card than the other three (the badge
   has to go somewhere), but the text itself renders the same single
   line as everywhere else, instead of an uneven wrap. */
@media (max-width: 767.98px) {
    body[data-page="contact"] .ct-card:has(.ct-online-badge) {
        flex-wrap: wrap;
    }

    /* flex-basis:100% on the badge alone (not the body) is what forces
       *it* onto a new line -- the icon and body both keep their normal
       flex sizing (body's flex:1 basis:0 already fills exactly what's
       left after the icon on one line), so they stay side by side on
       row one exactly like every other card, and only the badge wraps. */
    body[data-page="contact"] .ct-card:has(.ct-online-badge) .ct-online-badge {
        /* basis is a % of the container's content width, resolved before
           margins are added on top -- plain 100% + the margin-left below
           together exceeded that width and pushed the pill past the card's
           right edge (and off narrow viewports entirely). Subtracting the
           margin from the basis keeps the two in budget. */
        flex-basis: calc(100% - 60px);
        margin-left: 60px; /* icon width (44px) + its gap (16px) -- lines up under the label/value text above */
        /* No margin-top here — the parent's own `gap: 16px` (ct-card's flex
           gap, which applies to wrapped rows too) already spaces this from
           the row above; adding more on top of that pushed the card taller
           than necessary. */
    }

}

/* Overrides the tablet 2-up card rule (min-width:768px/max-width:991.98px,
   near the top of this file) for devices whose *physical* screen is
   phone-sized but whose CSS layout viewport is being reported as
   tablet-sized -- iOS Safari's per-site "Request Desktop Website" toggle
   does exactly this, and no max-width media query can ever catch it
   since the viewport it measures has been spoofed larger. Not wrapped in
   a media query itself -- data-real-phone (set in layout/main.blade.php
   from window.screen.width, which that spoofing doesn't touch) is the
   only gate, and !important + the extra attribute selector make sure
   this wins over the tablet rule regardless of which viewport width CSS
   thinks it's looking at. */
html[data-real-phone="1"] body[data-page="contact"] .ct-info-col {
    flex-direction: column !important;
    flex-wrap: nowrap !important;
}

html[data-real-phone="1"] body[data-page="contact"] .ct-card {
    flex: 1 1 auto !important;
}

/* Contact form card: style.css's own 768px rule already trims its
   padding to 28px/24px, but that still stacks with .container-apex's
   24px side gutter -- 48px of combined padding on each side before the
   inputs' own 14px, which on narrow phones (down to the Galaxy Z
   Fold5's 344px cover screen) reads as a lot of dead space hugging
   fields that end up looking cramped by comparison. Tighten the card's
   own side padding further here -- the container gutter alone already
   keeps the card off the screen edge, so this doesn't need to match it. */
@media (max-width: 480px) {
    .ct-form-card {
        padding: 24px 16px;
    }
}

/* Everything below matches the gift preview card to the "Pick an
   amount" tile cards' look -- originally tablet-only, now covers
   phone too (max-width:991.98px, no min-width) since the card itself
   should look the same at every width even though the amount tiles
   above it only get their own tablet-specific chip/number/expiry
   treatment (see the .gift-tile-chip block above, still scoped to
   768-991.98px on purpose -- that one's about the tiles, not this
   card). */
@media (max-width: 991.98px) {
    /* Gift preview card ("$250 / APEX AUTO DETAILING GIFT" panel): flat
       black gradient + plain outlined "GIFT" chip read as a placeholder
       next to the homepage promo section's mock card (glowing cyan
       border, solid chip badge). Match that same treatment here. extracted-inline.css's .chip.cyan and .ist-* rules use
       !important, so this needs matching specificity (attribute
       selector + !important) to actually win. */
    body[data-page="gift"] .gift-preview-card {
        /* Matches .gift-tile's own base gradient exactly (var(--apex-black)
           -> var(--apex-ink)), not the card's usual desktop gradient --
           the tiles just above this card on tablet use that pairing, and
           the diagonal cyan glow below is tuned to sit on top of it. */
        background: linear-gradient(135deg, var(--apex-black) 0%, var(--apex-ink) 100%) !important;
        border: 1.5px solid rgba(0, 212, 255, .35);
        box-shadow: 0 28px 64px rgba(0, 0, 0, .6), 0 0 0 1px rgba(0, 212, 255, .12);
        /* position:relative reactivates the desktop-only `top: 120px`
           left on .gift-preview-card by its sticky rule -- the
           max-width:991px rule only swapped position to static, which
           made that leftover top harmless, but relative honors it
           again. Zero it out explicitly instead of leaving it to
           whichever position rule happens to win. */
        top: 0;
        position: relative;
        z-index: 2;
        /* visible, not hidden -- .gift-preview-card-back (see style.css)
           needs this to peek out past this card's own edges here too,
           same as every other width. overflow:hidden here used to
           silently clip that peek at tablet width specifically. */
        overflow: visible;
    }

    /* Compact "Apex Gift" brand-line treatment, matching .gift-tile-label
       on the "Pick an amount" tiles just above this card on tablet --
       the desktop two-line "APEX / AUTO DETAILING" + separate cyan
       "GIFT" chip read as busier/bigger than the tiles right next to it
       at this width. Folds it into one small uppercase line ("APEX
       GIFT") the same way the tiles do, and hides the now-redundant
       cyan chip since the label already says "GIFT" -- keeping both
       said it twice in the same header row. The full "Apex Auto
       Detailing Gift" wording isn't lost, just no longer duplicated
       here -- it's still shown in the caption under the amount. */
    /* font-size/weight match .gift-tile-label's own COMPUTED values at
       this width, not its base rule -- .gift-tile-label has its own
       max-width:820px override down to 10px (see style.css), and
       carries no explicit font-weight of its own (so it inherits
       normal/400, not the bold treatment this label used elsewhere).
       12px/600 read visibly bigger and heavier than the tiles' own
       label right next to it. */
    body[data-page="gift"] .gift-preview-card .ist-216f9f67 {
        font-family: inherit !important;
        font-weight: 400 !important;
        font-size: 10px !important;
        letter-spacing: .14em !important;
        text-transform: uppercase;
        color: var(--apex-grey-300) !important;
    }

    body[data-page="gift"] .gift-preview-card .ist-216f9f67::after {
        content: " Gift";
    }

    body[data-page="gift"] .gift-preview-card .ist-e67d50ea {
        display: none;
    }

    body[data-page="gift"] .gift-preview-card .chip.cyan {
        display: none;
    }

    /* Matches .gift-tile-expiry's small-caps treatment on the tiles --
       keeps the real "Never expires" wording (this card states the
       actual policy, unlike the tiles' placeholder "Valid Thru" dates)
       but in the same compact style so the footer row reads like the
       tiles' footer instead of noticeably larger body text next to
       them. */
    body[data-page="gift"] .gift-preview-card .ist-1b30ab15 span:last-child {
        font-size: 9px;
        letter-spacing: .08em;
        text-transform: uppercase;
    }

    /* Chip moves up into the same row as the "APEX GIFT" label instead
       of sitting in its own row below it -- matches .gift-tile-chip's
       placement on the tiles (top-right corner, level with the label)
       and closes the vertical gap that row used to take up. top/
       right:18px matches .gift-tile-chip's own inset exactly -- same
       values, and now the same 24px padding on both cards' padding-box,
       so the two chips sit the identical distance from their card's
       edge. (0/0 briefly crowded it flush into the very corner instead
       of sitting this small amount inboard, the way the tile's own
       chip does.) */
    body[data-page="gift"] .gift-preview-card .gift-preview-chip {
        position: absolute;
        top: 18px;
        right: 18px;
        margin-bottom: 0;
    }

    /* Full layout rebuild to match .gift-tile's structure at this width:
       header row, masked number, then amount + expiry sharing one
       bottom row. The card's own markup doesn't nest the amount and
       the expiry text together the way the tile's .gift-tile-footer
       does (there's a caption line and a "Code ..." line between them
       that the tile doesn't have at all), so a plain flex column can't
       reproduce that shared row -- CSS grid can, since grid-area lets
       non-adjacent DOM children share a row without moving them in the
       markup. The caption and the placeholder code text are hidden
       below rather than restyled: neither has a home in the tile's
       layout, and the code is a static placeholder pre-purchase anyway
       (the real code goes out by email), so there's nothing lost by
       leaving them for the fuller desktop/phone layouts to show. */
    /* THE thing that actually made this look nothing like the tiles: the
       card was stretching to the full column width (~592px) while its
       content only needed ~168px of height, so it rendered as a wide
       letterbox strip at roughly 3.5:1 -- the tiles are 1.6:1, an
       actual credit-card shape. Capping the width and pinning the same
       1.6:1 aspect-ratio the tiles use is what makes it read as the
       same kind of object. Centered since it no longer fills the
       column. */
    body[data-page="gift"] .gift-preview-card {
        max-width: 420px;
        aspect-ratio: 1.6 / 1;
        margin-inline: auto;
    }

    body[data-page="gift"] .gift-preview-card-inner {
        /* Matches .gift-tile's own padding (24px) -- 16px read cramped
           against the tiles right above it, which give their content
           noticeably more breathing room top and bottom. */
        padding: 24px;
        /* Fills the aspect-ratio'd parent above, so the grid's 1fr
           number row absorbs the extra height and pushes the amount
           row to the bottom the way .gift-tile's own space-between
           flex column does. */
        height: 100%;
        display: grid;
        grid-template-areas:
            "header header"
            "number number"
            "amount expiry";
        grid-template-columns: 1fr auto;
        grid-template-rows: auto 1fr auto;
        row-gap: 12px;
    }

    /* Every grid cell also gets position:relative + a z-index above the
       diagonal glow pseudo-element below -- same mechanism .gift-tile's
       own text uses against its own ::after glow. Without it the glow
       (position:absolute, painted like any other positioned box
       regardless of DOM order) would sit visually on top of this plain,
       non-positioned text instead of behind it. */
    body[data-page="gift"] .gift-preview-card .ist-bfcbf540 {
        grid-area: header;
        margin-bottom: 0 !important;
        position: relative;
        z-index: 2;
    }

    body[data-page="gift"] .gift-preview-card .gift-preview-number {
        grid-area: number;
        align-self: end;
        margin: 0;
        position: relative;
        z-index: 2;
    }

    /* Plain white, matching .gift-tile-amount -- the gradient-filled
       gold/cyan treatment this uses elsewhere was another big part of
       why it didn't read as the same component as the tiles. Needs
       the gradient's background-clip/transparent-color trio explicitly
       unset, not just a new color: with background-clip:text still
       active, color alone stays invisible behind the clipped
       background. */
    body[data-page="gift"] .gift-preview-card .gift-preview-amount {
        grid-area: amount;
        align-self: end;
        margin-bottom: 0;
        position: relative;
        z-index: 2;
        background: none;
        -webkit-background-clip: border-box;
        background-clip: border-box;
        color: var(--apex-white);
        animation: none;
        font-size: clamp(1.8rem, 5vw, 2.8rem);
    }

    body[data-page="gift"] .gift-preview-card .ist-96cbc0b1 {
        display: none !important;
    }

    body[data-page="gift"] .gift-preview-card .ist-1b30ab15 {
        grid-area: expiry;
        align-self: end;
        justify-content: flex-end;
        padding-top: 0 !important;
        border-top: none !important;
        position: relative;
        z-index: 2;
    }

    body[data-page="gift"] .gift-preview-card .ist-1b30ab15 span:first-child {
        display: none;
    }

    /* Diagonal cyan glow, matching .gift-tile::after exactly -- this is
       most of what visually distinguishes the tiles' card face from
       this card's own plain gradient. */
    body[data-page="gift"] .gift-preview-card-inner::before {
        content: "";
        position: absolute;
        top: -50%;
        right: -20%;
        width: 60%;
        height: 200%;
        background: linear-gradient(135deg, rgba(0, 212, 255, 0.4), transparent);
        transform: rotate(20deg);
        pointer-events: none;
    }

    /* No card-stack peek on tablet -- the tile cards this card is now
       matching the look of are each a single flat card with no second
       card behind them, so keep this one the same way here instead of
       the layered/3D look .gift-preview-card-back gives it everywhere
       else. */
    body[data-page="gift"] .gift-preview-card-back {
        display: none;
    }

    /* The form/preview columns (.row.g-5) stack on tablet -- Bootstrap's
       g-5 gutter alone puts 48px of margin-top above .col-lg-5, and
       .gift-preview-stack's own margin-top stacks on top of that again,
       leaving a lot of dead air between the "Buy gift card" button and
       the card below it. */
    body[data-page="gift"] #panel-buy .row.g-5 {
        --bs-gutter-y: 1.25rem;
    }

    body[data-page="gift"] .gift-preview-stack {
        display: block;
        position: relative;
        margin-top: 8px;
    }

    /* "The car-person gift problem, solved." dark section: .section's
       own padding clamps down to near-nothing at these widths (max
       25px), which reads as cramped against the panels directly above
       and below it. A little breathing room, this page only. */
    body[data-page="gift"] .feature-grid {
        padding-top: 20px;
        padding-bottom: 20px;
    }

    /* Contact page info cards (Phone/Email/Headquarters/Live Chat):
       .ct-info-col is a plain single-column flex stack (style.css's own
       max-width:1024px rule keeps it that way through tablet), which on
       this wider band leaves 4 cards each stretched edge-to-edge with a
       lot of empty horizontal space inside every row. 2-up instead --
       .ct-section-head keeps its own full-width row above them. */
    body[data-page="contact"] .ct-info-col {
        flex-direction: row;
        flex-wrap: wrap;
    }

    body[data-page="contact"] .ct-section-head {
        flex: 1 1 100%;
    }

    body[data-page="contact"] .ct-card {
        flex: 1 1 calc(50% - 6px);
        min-width: 0;
    }

    /* Business Hours card: desktop's 40px vertical card padding, the
       header's own 48px combined margin+padding-bottom, and the
       section's 96px bottom padding only shrink at phone widths (see
       style.css's max-width:768px rule) -- tablet was still getting
       the full desktop spacing. Trim it, and use some of what that
       frees up to make the day/time rows read a little larger and
       sit a little closer together. */
    body[data-page="contact"] .ct-hours-section {
        padding-bottom: 56px;
    }

    body[data-page="contact"] .ct-hours-card {
        padding: 28px 28px;
    }

    body[data-page="contact"] .ct-hours-top {
        margin-bottom: 18px;
        padding-bottom: 14px;
    }

    body[data-page="contact"] .ct-hours-row {
        padding: 10px 0;
    }

    body[data-page="contact"] .ct-hours-day,
    body[data-page="contact"] .ct-hours-time {
        font-size: 1.02rem;
    }

    /* Dark page-header hero (Rewards, Services, Careers, Story, etc.):
       only got a smaller clamp at phone widths (see style.css's own
       max-width:768px rule right below the base .page-header rule) --
       tablet was still stuck with desktop's clamp(100px,12vw,160px)
       top / clamp(50px,6vw,90px) bottom, a lot of dead dark space
       above/below a hero that's just a breadcrumb, eyebrow pill,
       heading and one line of copy. Tightened further still -- the
       first clamp(64,9vw,96)/clamp(32,4vw,48) pass wasn't enough. */
    .page-header {
        padding: clamp(48px, 6vw, 64px) 0 clamp(24px, 3vw, 32px);
    }

    /* Rewards "Tiers" section (Garage/Driveway/Concierge): reuses the
       same .mem-grid/.mem-card as the membership page's plan cards
       (smart.css), which collapses to a single stacked column below
       980px -- 3 tall cards (price + 4-5 features + CTA each) end up
       one under another. Slider instead, same swipeable/scroll-snap
       pattern as #plans .mem-grid on the membership page, plus tighter
       internal spacing so each card itself reads shorter too. */
    body[data-page="rewards"] .mem-grid {
        display: flex !important;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        gap: 16px;
        margin: 0 -24px;
        padding: 20px 24px 28px;
    }

    body[data-page="rewards"] .mem-grid::-webkit-scrollbar {
        display: none;
    }

    body[data-page="rewards"] .mem-card {
        flex: 0 0 82%;
        max-width: 82%;
        scroll-snap-align: center;
        padding: 22px;
    }

    body[data-page="rewards"] .mem-tagline {
        margin-bottom: 12px;
        min-height: 0;
    }

    body[data-page="rewards"] .mem-price {
        font-size: 2.4rem;
    }

    body[data-page="rewards"] .mem-features {
        margin: 14px 0;
    }

    body[data-page="rewards"] .mem-features li {
        padding: 7px 0;
    }

    /* "Join free" section (#join): the two columns (copy+list / form
       card) stack on tablet, and Bootstrap's g-5 row gutter alone adds
       48px of margin-top above the form -- same fix as the gift cards
       page's form/preview columns. */
    body[data-page="rewards"] #join .row.g-5 {
        --bs-gutter-y: 1.5rem;
    }

    /* The 3 checklist items ("500 bonus points…", etc.) inherit
       .ist-13c4836d's color:var(--apex-grey-700) !important
       (extracted-inline.css) -- a dark slate meant for a light
       background, but #join is a .section.bg-paper (dark) section.
       style.css's own .section.bg-paper text-color overrides cover
       h2-h4/.muted/.feature p but never anticipated this hashed class,
       so it's rendered dull/low-contrast grey-on-dark. Match the same
       lighter grey the rest of this dark section already uses, and
       lay out 2-up instead of stacked, with the orphaned 3rd item
       centered -- same grid + last-child-spans-and-centers technique
       as the gift cards page's .feature-grid fix above. */
    body[data-page="rewards"] #join .ist-13c4836d {
        color: var(--apex-grey-300) !important;
        display: grid !important;
        grid-template-columns: repeat(2, 1fr);
        gap: 4px 20px;
    }

    body[data-page="rewards"] #join .ist-13c4836d > li:last-child {
        grid-column: 1 / -1;
        max-width: calc(50% - 10px);
        margin: 0 auto;
    }
}

/* .feature-grid only drops to 2 columns at this exact width (see
   style.css) -- past it, all 3 features already fit on one row and
   there's nothing to center. Scoped to the same range so it doesn't
   silently stop matching if that breakpoint ever moves. */
@media (min-width: 768px) and (max-width: 820px) {

    /* 3rd feature ("Use anywhere") is left orphaned alone on its own
       row under the 2-column grid -- center it instead of leaving it
       stuck under column 1. */
    body[data-page="gift"] .feature-grid > .feature:last-child {
        grid-column: 1 / -1;
        max-width: calc(50% - 14px);
        margin: 0 auto;
    }
}

/* ────────────────────────────────────────────────────────────────────────────
   4. CUSTOMER PORTAL  (/my — customerportal/layout/app.blade.php)
   ──────────────────────────────────────────────────────────────────────────── */

/* Phone: app-style bottom tab bar */
@media (max-width: 767.98px) {

    .cp-tabbar {
        display: flex;
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        z-index: 950;
        background: var(--cp-card, #fff);
        border-top: 1px solid var(--cp-border, #e5e9f0);
        padding: 6px 4px calc(6px + env(safe-area-inset-bottom, 0px));
        justify-content: space-around;
        box-shadow: 0 -4px 16px rgba(0, 0, 0, .06);
    }

    .cp-tabbar a {
        flex: 1;
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 2px;
        padding: 6px 2px;
        min-height: 48px;
        font-size: 10.5px;
        font-weight: 600;
        color: var(--cp-text-muted, #8a93a3);
        text-decoration: none;
        border-radius: 10px;
    }

    .cp-tabbar a i {
        font-size: 20px;
        line-height: 1;
    }

    .cp-tabbar a.active {
        color: var(--cp-accent, #00d4ff);
    }

    /* Content clears the tab bar */
    .cp-content {
        padding-bottom: calc(76px + env(safe-area-inset-bottom, 0px)) !important;
    }

    .cp-content .table-responsive table {
        min-width: 560px;
        /* keeps columns readable; container scrolls */
    }
}

/* Tablet 768–991px: lg-only grids (which Bootstrap stacks to 1-col here)
   upgrade to a 2-col layout — better use of iPad width */
@media (min-width: 768px) and (max-width: 991.98px) {

    .cp-content .row>.col-lg-3,
    .cp-content .row>.col-lg-4 {
        flex: 0 0 50%;
        max-width: 50%;
    }
}

/* ────────────────────────────────────────────────────────────────────────────
   5. CLIENT ADMIN DASHBOARD + STAFF PORTAL (clientportal/layout/app.blade.php)
   Theme (Zenix) already collapses the sidebar; this fills the gaps.
   ──────────────────────────────────────────────────────────────────────────── */

/* Phone + tablet */
@media (max-width: 1199.98px) {

    /* Every admin table scrolls inside its card instead of breaking layout */
    .card .table,
    .content-body table.table {
        min-width: 640px;
    }

    .card-body:has(> .table),
    .card-body:has(> table) {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    /* Charts hug their container */
    .apexcharts-canvas,
    .apexcharts-canvas svg {
        max-width: 100% !important;
    }

}

/* Phone only */
@media (max-width: 767.98px) {

    /* Modals become full-screen sheets */
    .modal-dialog {
        margin: 0;
        max-width: 100%;
        min-height: 100%;
        display: flex;
        align-items: flex-end;
    }

    .modal-content {
        border-radius: 16px 16px 0 0;
        max-height: 92vh;
        overflow-y: auto;
        width: 100%;
    }

    /* Page title rows / filter toolbars wrap instead of overflowing */
    .page-titles,
    .card-header,
    .d-flex.justify-content-between {
        flex-wrap: wrap;
        gap: 8px;
    }

    /* Kanban boards become horizontal swipe lanes on phone — one ~85vw
       column at a time with the next peeking in (app-style), instead of a
       tall vertical stack of all four status columns */
    .kanban-board,
    .kb-wrap {
        display: flex !important;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scroll-snap-type: x mandatory;
        gap: 12px;
    }

    .kanban-board>.kanban-col,
    .kb-wrap>.kb-col {
        flex: 0 0 85vw;
        max-width: 85vw;
        scroll-snap-align: start;
    }

    /* Admin content padding tightens */
    .content-body .container-fluid {
        padding-left: 12px;
        padding-right: 12px;
    }

    /* Bare tables (no .table-responsive wrapper — ~27 admin pages) become
       self-scrolling blocks on phone instead of blowing out the viewport */
    .content-body table.table:not(.dataTable) {
        display: block;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    /* DataTables length/filter/info/pagination stack neatly */
    .dataTables_length,
    .dataTables_filter,
    .dataTables_info,
    .dataTables_paginate {
        float: none !important;
        text-align: left !important;
        margin-top: 8px;
    }

    .dataTables_filter input {
        width: 100%;
        margin-left: 0 !important;
    }
}

/* Staff live-track: action buttons stick to the bottom, thumb-reachable */
@media (max-width: 767.98px) {

    .lt-actions {
        position: sticky;
        bottom: 0;
        z-index: 40;
        background: inherit;
        padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
    }

    .lt-actions .btn,
    .lt-actions button,
    .lt-actions a {
        min-height: 48px;
    }
}

/* ────────────────────────────────────────────────────────────────────────────
   6. LIVE MAPS & TRACKING — full-bleed on phone
   ──────────────────────────────────────────────────────────────────────────── */
@media (max-width: 767.98px) {

    #map,
    #track-map,
    #lt-map,
    .track-map,
    .live-map,
    [id*="map-canvas"] {
        width: 100% !important;
        min-height: 55vh;
    }
}

/* ────────────────────────────────────────────────────────────────────────────
   7. MOBILE-DETAILING HERO — real fix for a defeated one
   ──────────────────────────────────────────────────────────────────────────── */
@media (max-width: 767.98px) {
    /* extracted-inline.css's .ist-b0c4daed (an auto-extracted copy of this
       hero section's original inline style) sets padding with !important:
       clamp(60px, 8vw, 100px) 0. That completely defeats BOTH style.css's
       .hero base rule AND its own already-fixed <=768px override (see the
       ".hero's top padding was clamp(70px,8vw,50px)..." comment in
       style.css) -- neither ever had a chance to apply here, since
       !important always wins regardless of which one is more specific or
       comes later. The 60px floor (8vw doesn't clear it below ~750px
       viewport width) was forcing dead space above and below the copy on
       every phone. mobile-responsive.css loads after extracted-inline.css,
       so an equally-!important, equally-specific rule here wins on source
       order and actually takes effect. */
    .ist-b0c4daed {
        padding: 28px 0 36px !important;
    }

    /* Hero booking card's 32px padding (style.css) was untouched on
       phone -- reasonable for its own two-column desktop width, heavier
       in a ~296px phone column. */
    .hero-card {
        padding: 22px;
    }

    /* Each info row (.ist-9e288e97, extracted-inline.css) lays label and
       value side by side with justify-content:space-between and no
       explicit widths -- on a ~296px phone card, longer values ("Tue ·
       10:30 AM", "Mercedes Sprinter") don't have room next to their
       label and wrap onto a second line, while shorter ones ("Silent
       inverter" next to the short "Power" label) don't, so rows ended
       up an inconsistent mix of ~54px and ~79px tall for no visible
       reason. Stacking label above value avoids the wrap gamble
       entirely and gives every row the same, tighter height. */
    .ist-9e288e97 {
        flex-direction: column !important;
        align-items: flex-start !important;
        gap: 3px;
        padding: 10px !important;
    }

    .ist-9e288e97 .ist-11c0b12e,
    .ist-9e288e97 .ist-e9600e9b {
        line-height: 1.25;
    }

    .ist-7f30e80b {
        gap: 6px !important;
    }

    /* Service-zone section (#zip-checker): Bootstrap's .g-5 gutter
       (--bs-gutter-y: 3rem, i.e. 48px) is meant for the horizontal gap
       between the two side-by-side columns on desktop -- once they
       stack on phone it becomes 48px of pure vertical dead space
       between the ZIP-check card and the zone card below it. */
    #zip-checker .row {
        --bs-gutter-y: 1.5rem;
    }

    /* Zone card's 32px padding (.ist-51871a8c, extracted-inline.css) --
       same oversized-for-phone desktop padding as the hero card above. */
    .ist-51871a8c {
        padding: 20px !important;
    }

    /* ZIP pill grid (.ist-f7d14262) is a hardcoded repeat(4,1fr) with no
       minmax(), so each column can't shrink below a 5-digit pill's own
       content width -- the grid overflowed its card by ~53px and the
       last column on each row was silently clipped. 3 columns gives
       each track enough room for a pill at this width. */
    .ist-f7d14262 {
        grid-template-columns: repeat(3, 1fr) !important;
    }
}
