/* ============================================================
 *  perf-fixes.css — small, render-blocking CLS reservations.
 *  Loaded FIRST so layout dimensions are known before the rest
 *  of the cascade arrives. Target keep-size: under 4 KB.
 *  ============================================================ */

/* ---- 1. Sticky header height reservation -----------------------
   Header is position:fixed in Impreza. Reserving its height on
   .l-canvas (the wrapper that holds <main>) means the first paint
   already has the correct main-content offset — no shift when the
   header's sticky state JS kicks in.
   ------------------------------------------------------------- */
:root {
    --vif-header-h:        130px;
    --vif-header-h-laptop: 120px;
    --vif-header-h-tablet: 100px;
    --vif-header-h-mobile:  80px;
    /* Plus the top sub-bar (40px) when displayed */
    --vif-subheader-h:      40px;
}

/* Don't double-pad on WooCommerce cart/checkout/account (Impreza handles those) */
.l-canvas {
    --vif-top-offset: calc(var(--vif-header-h) + var(--vif-subheader-h));
}

#page-content.l-main {
    /* Reserve at least one viewport-row of space so the first
       paint has a stable bottom edge before sliders mount. */
    min-height: 60vh;
}

#page-header.pos_fixed {
    /* Stop the header from "growing" sideways during JS init */
    contain: layout;
    will-change: transform;
}

@media (max-width: 1380px) {
    .l-canvas { --vif-top-offset: calc(var(--vif-header-h-laptop) + var(--vif-subheader-h)); }
}
@media (max-width: 1024px) {
    .l-canvas { --vif-top-offset: calc(var(--vif-header-h-tablet) + var(--vif-subheader-h)); }
}
@media (max-width: 600px) {
    .l-canvas { --vif-top-offset: var(--vif-header-h-mobile); }
}

/* ---- 2. Section-with-background CLS reservation ---------------
   Inline style="background-image:..." sections have no inherent
   height. Reserve a sensible aspect ratio so the first paint
   already accounts for them, eliminating the largest CLS source.
   ------------------------------------------------------------- */
.l-section.with_img,
section[style*="background-image"],
.l-section[style*="background-image"] {
    background-size: cover;
    background-position: center center;
    background-repeat: no-repeat;
}

/* Hero/full-bleed section variants — taller reservation */
.l-section.height_full[style*="background-image"]   { min-height: 100vh; }
.l-section.height_large[style*="background-image"]  { min-height: 70vh; }
.l-section.height_medium[style*="background-image"] { min-height: 50vh; }
.l-section.height_small[style*="background-image"]  { min-height: 30vh; }

/* ---- 3. Swiper + Owl container reservations -------------------
   Before JS mounts, swiper/owl wrappers are display:block height:0.
   Reserve a vertical envelope so mounting doesn't shift the page.
   ------------------------------------------------------------- */
.swiper:not([data-vif-mounted]) {
    /* Default reservation — tuned per-section via overrides below */
    min-height: 360px;
    overflow: hidden;
}

.associates-swiper:not([data-vif-mounted]),
.associates-swiper-ar:not([data-vif-mounted]),
.clients-swiper:not([data-vif-mounted]),
.clients-swiper-ar:not([data-vif-mounted]) {
    min-height: 140px;        /* logo strip */
}

.testimonials-swiper:not([data-vif-mounted]),
.testimonials-swiper-ar:not([data-vif-mounted]) {
    min-height: 320px;
}

.mySwiper:not([data-vif-mounted]),
.mySwiperAr:not([data-vif-mounted]) {
    min-height: 480px;        /* coverflow */
}


/* Hide pre-mount FOUC of swipers (raw stacked slides briefly visible) */
.swiper:not([data-vif-mounted]) .swiper-wrapper {
    display: flex;
    visibility: hidden;
}

/* ---- 3a. Pre-mount Owl banner CLS ------------------------------
   Before owl-carousel JS mounts, all slides are visible stacked
   vertically — the section's actual height balloons to N×slide_height.
   When owl mounts, it collapses to single-slide height — Lighthouse
   logs this contraction as a layout shift.
   Fix: until .owl-loaded is applied, show only the first slide.
   ------------------------------------------------------------- */
.owl-carousel.main-banner:not(.owl-loaded),
.owl-carousel.main-banner-ar:not(.owl-loaded) {
    display: block !important;
    overflow: hidden;
}
.owl-carousel.main-banner:not(.owl-loaded) > *,
.owl-carousel.main-banner-ar:not(.owl-loaded) > * {
    display: none !important;
}
.owl-carousel.main-banner:not(.owl-loaded) > *:first-child,
.owl-carousel.main-banner-ar:not(.owl-loaded) > *:first-child {
    display: block !important;
}
.owl-carousel:not(.main-banner):not(.main-banner-ar):not(.owl-loaded) > *:not(:first-child) {
    display: none !important;
}

/* ---- 3b. Text-rotator width reservation -----------------------
   The .vif-text-rotator inside the H1 swaps words of varying widths.
   Without a fixed width, surrounding content (period, button, etc.)
   shifts on each rotation — measured as CLS.
   Fix: stack all words in an inline-grid so the container sizes
   to the widest word; only the active one is visible.
   ------------------------------------------------------------- */
.vif-text-rotator {
    display: inline-grid !important;
    grid-template-columns: 1fr;
    align-items: baseline;
    vertical-align: bottom;
    line-height: 1.4;
}
.vif-text-rotator > * {
    grid-column: 1;
    grid-row: 1;
    transition: opacity 500ms ease, transform 500ms ease;
}
.vif-text-rotator > :not(.rotator-text--active) {
    opacity: 0;
    pointer-events: none;
}

/* ---- 4. Image hard-bound dimensions ----------------------------
   For <img> with width/height attrs, ensure CSS doesn't accidentally
   break aspect ratio. Defensive.
   ------------------------------------------------------------- */
img[width][height] {
    max-width: 100%;
}

/* ---- 5. Font-fallback metric matching --------------------------
   Reduces CLS from web-font swap by sizing the local fallback
   closer to Open Sans + Inter (the two families we keep). Values
   sourced from Bram Stein's font-metric tables. Combined with the
   reduced font request in header.php, swap shift is barely visible.
   Does NOT use !important so existing per-element font-family
   declarations in main.css (which use !important) still win.
   ------------------------------------------------------------- */
@font-face {
    font-family: 'Open Sans Fallback';
    src: local('Arial');
    size-adjust: 102%;
    ascent-override: 100%;
    descent-override: 27%;
    line-gap-override: 0%;
}
@font-face {
    font-family: 'Inter Fallback';
    src: local('Arial');
    size-adjust: 107%;
    ascent-override: 90%;
    descent-override: 22%;
    line-gap-override: 0%;
}

body, .l-body {
    font-family: 'Open Sans', 'Open Sans Fallback', system-ui, -apple-system, 'Segoe UI', Arial, sans-serif;
}
h1, h2, h3, h4, h5, h6 {
    font-family: 'Inter', 'Inter Fallback', 'Open Sans', system-ui, -apple-system, Arial, sans-serif;
}

/* ---- 6. Animation throttling for users that opt out -----------
   Honors prefers-reduced-motion at first paint, before main.css
   loads. Prevents heavy keyframe animations from starting.
   ------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
}

/* ---- 7. Content-visibility for offscreen sections --------------
   `content-visibility: auto` lets the browser skip rendering
   work for offscreen sections — the single largest "main-thread
   work" reduction available without a JS rewrite.
   Excludes the hero (first .l-section) so LCP isn't deferred.
   ------------------------------------------------------------- */
.l-main > .l-section:nth-of-type(n+3),
main > .l-section:nth-of-type(n+3),
#page-content > .l-section:nth-of-type(n+3) {
    content-visibility: auto;
    contain-intrinsic-size: 800px;     /* size hint so scrollbar is correct */
}

/* ---- 8. Composited animations only -----------------------------
   `transition: all` and transitioning width/height/top/left causes
   non-composited animations (the Lighthouse warning). Cap any
   "transition: all" to transform+opacity at the document level.
   ------------------------------------------------------------- */
.us_animate_this,
.w-grid-item,
.w-image,
.w-btn,
.w-iconbox {
    will-change: auto;            /* don't promote until animating */
}

/* Smooth-scroll JS in $us.canvasOptions is 1500ms — replace with
   native scroll-behavior: smooth and let the compositor handle it. */
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
}
