/* Global scroll-reveal, ONE system for every page. Each top-level Elementor section glides in
   from an alternating side (left / right) as it enters the viewport. Critical hide is inlined
   in <head> (FOUC-safe, opacity only); this file adds the directional offset + smooth glide. */

/* ============================================================================
   NO SIDEWAYS SCROLL, EVER.
   Three separate things push content past the right edge of the page:
     1. the reveal start-state below, translate3d(+56px) on any section that has
        not been scrolled into view yet, so the page is 56px too wide from load;
     2. the off-canvas drawers in mev_counters_showcase (aside.mev-cs-panel),
        parked at translateX(576px) while closed, worth ~520px on the service pages;
     3. a few absolutely positioned images and buttons that spill at tablet/mobile.
   All three are decoration parked outside the viewport on purpose, so the fix is
   to stop the page from scrolling to them rather than to move each one.
   overflow-x:clip (not hidden) because hidden on html/body kills position:sticky,
   which the counters scroll-spy index and the drawer footer both rely on.
   ============================================================================ */
html, body { overflow-x: clip; }
@supports not (overflow-x: clip) {
	/* older Safari: hidden is the only option, and it does cost sticky */
	html, body { overflow-x: hidden; }
}

html.mev-anim .e-con.e-parent,
html.mev-anim .elementor-top-section {
	opacity: 0;
	/* long, decelerating glide so sections flow in like a calm river (no snap / stutter) */
	transition: opacity .9s ease, transform 1.1s cubic-bezier(.22, 1, .36, 1);
	will-change: opacity, transform;
}
/* Start positions (class added by mev-reveal.js while still invisible).
   These sections are full-bleed, so sliding the section box sideways exposed a bare 56px strip
   down one edge for the first ~400ms of the 1.1s glide: the cream background and its paisley
   stopped short of the viewport edge. Most visible on a fast scroll or a full-page screenshot.
   The glide is now vertical, which cannot uncover a side gutter. The left/right feel is kept by
   the inner-element stagger below, which moves content, not the full-width background. */
html.mev-anim .e-con.e-parent.mev-rl,
html.mev-anim .elementor-top-section.mev-rl,
html.mev-anim .e-con.e-parent.mev-rr,
html.mev-anim .elementor-top-section.mev-rr { transform: translate3d(0, 18px, 0); }
/* revealed state */
html.mev-anim .e-con.e-parent.mev-in,
html.mev-anim .elementor-top-section.mev-in { opacity: 1 !important; transform: none !important; }

/* inner-element stagger: content inside a revealed section rises + fades in a gentle cascade
   (added by mev-reveal.js), so sections feel alive instead of like one sliding block. */
html.mev-anim .mev-el {
	opacity: 0;
	transform: translateY(14px);
	transition: opacity .7s ease, transform .8s cubic-bezier(.16, 1, .3, 1);
	will-change: opacity, transform;
}
html.mev-anim .mev-el.mev-el-in { opacity: 1; transform: none; }

/* never hide / transform / stack the theme header or footer: they hold the nav dropdowns.
   A transform or will-change here creates a stacking context that buries the dropdown. */
html.mev-anim .elementor-location-header .e-con.e-parent,
html.mev-anim .elementor-location-header .elementor-top-section,
html.mev-anim .elementor-location-footer .e-con.e-parent,
html.mev-anim .elementor-location-footer .elementor-top-section {
	opacity: 1 !important; transform: none !important; transition: none !important; will-change: auto !important;
}

/* ============================================================================
   SQUARE IMAGE CAROUSELS.
   Elementor's image carousel renders every slide at the photo's own aspect ratio, so a mix of
   landscape, portrait and square uploads gives slides of wildly different heights. That is what
   threw the homepage service rows out of alignment: a 1.5 landscape sat short next to its text
   while a 0.67 portrait ran long and opened a gap underneath.
   Force every slide to a 1:1 box and crop to fill. Per-image focal point is set further down.
   ============================================================================ */
.elementor-widget-image-carousel .swiper-slide,
.elementor-widget-image-carousel .swiper-slide-inner,
.elementor-widget-image-carousel figure.swiper-slide-inner {
	display: block;
	width: 100%;
}
.elementor-widget-image-carousel .swiper-slide img,
.elementor-widget-image-carousel .swiper-slide-image {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 1 / 1;
	object-fit: cover;        /* fill the square, crop the overflow, never squash */
	object-position: center;  /* default focal point, overridden per image below */
}

/* Per-image focal point.
   object-fit:cover crops from the centre, which is wrong when the subject sits high or low in
   the frame. Add one line per image that needs a different crop, keyed on its filename.
   Values are x y: "center 20%" keeps the top, "center 80%" keeps the bottom.
   To find the filename, right-click the image in the Elementor media library and copy its URL. */
.elementor-widget-image-carousel img[src*="IMG-20250727-WA0104"] { object-position: center 30%; }
.elementor-widget-image-carousel img[src*="ChatGPT-Image-Jul-24-2026-01_00_06"] { object-position: center 25%; }
.elementor-widget-image-carousel img[src*="ChatGPT-Image-Jul-24-2026-01_16_27"] { object-position: center 25%; }
.elementor-widget-image-carousel img[src*="ChatGPT-Image-Jul-24-2026-01_23_14"] { object-position: center 30%; }

/* retire the old, half-working animations so this is the single source of truth */
.animate-fade-up { animation: none !important; }
/* The transform reset is what stops a card being stuck mid-animation, but it must not out-shout
   the hover lift, so it only applies while the element is not hovered. */
.mev-loc .reveal, .mev-about .reveal, .mev-kw .reveal, .mev-cnd .reveal, .mev-dlv .reveal, .mev-vr .reveal { opacity: 1 !important; }
.mev-loc .reveal:not(:hover), .mev-about .reveal:not(:hover), .mev-kw .reveal:not(:hover),
.mev-cnd .reveal:not(:hover), .mev-dlv .reveal:not(:hover), .mev-vr .reveal:not(:hover) { transform: none !important; }

@media (prefers-reduced-motion: reduce) {
	html.mev-anim .e-con.e-parent,
	html.mev-anim .elementor-top-section,
	html.mev-anim .mev-el { opacity: 1 !important; transform: none !important; transition: none !important; }
}

/* ============================================================================
   HOVER LIFE on every content element (headings, copy, numbers, counters, stat
   cards, images, buttons). Scoped to page content, NEVER the header/footer nav.
   ============================================================================ */
.elementor:not(.elementor-location-header):not(.elementor-location-footer) :where(h1,h2,h3,h4,p,li,img,.btn,.button,[data-count],.mev-badge,.mev-badge-n,.mev-cs-card,.mev-cs-tile,.mev-cs-pill,.glass,.abs-photo,.vr-logo-tile,.cg-chip,.tile,.s,.g-row){
	transition: transform .38s cubic-bezier(.16,1,.3,1), color .3s ease, box-shadow .35s ease, opacity .6s ease;
}
/* headings: gentle directional nudge */
.elementor:not(.elementor-location-header):not(.elementor-location-footer) :is(h1,h2,h3,h4):hover{ transform: translateX(5px); }
/* copy: subtle lift */
.elementor:not(.elementor-location-header):not(.elementor-location-footer) :is(p,li):hover{ transform: translateY(-2px); }
/* numbers / counters: pop */
.elementor:not(.elementor-location-header):not(.elementor-location-footer) :is([data-count],.mev-badge-n):hover{ transform: scale(1.12); }
/* stat cards / tiles / info cards: lift + shadow */
.elementor:not(.elementor-location-header):not(.elementor-location-footer) :is(.mev-badge,.mev-cs-card,.mev-cs-tile,.mev-cs-pill,.glass,.abs-photo,.vr-logo-tile,.tile,.s,.g-row):hover{ transform: translateY(-6px); box-shadow: 0 20px 44px -20px rgba(0,0,0,.40); }
/* images: gentle zoom */
.elementor:not(.elementor-location-header):not(.elementor-location-footer) img:hover{ transform: scale(1.04); }
/* buttons + chips */
.elementor:not(.elementor-location-header):not(.elementor-location-footer) :is(.btn,.button,.cg-chip):hover{ transform: translateY(-3px); box-shadow: 0 14px 30px -14px rgba(0,0,0,.40); }
@media (prefers-reduced-motion: reduce){
	.elementor:not(.elementor-location-header):not(.elementor-location-footer) :hover{ transform: none !important; }
}

/* Arch-shaped mask for the photo stage. Generated by make_arch_clip.py from the alpha
   channel of arch-frame.png, so it follows the artwork exactly. Regenerate if the frame
   art or the stage box percentages ever change. */
.mev-arch .mev-arch-stage {
	-webkit-clip-path: polygon(51.03% 0.00%, 50.38% 0.79%, 49.40% 1.59%, 48.26% 2.38%, 46.95% 3.17%, 45.16% 3.96%, 42.87% 4.76%, 39.29% 5.55%, 35.05% 6.34%, 32.27% 7.13%, 30.48% 7.93%, 29.34% 8.72%, 28.19% 9.51%, 27.54% 10.31%, 26.73% 11.10%, 21.18% 11.89%, 18.24% 12.68%, 16.94% 13.48%, 15.96% 14.27%, 15.15% 15.06%, 14.66% 15.85%, 14.17% 16.65%, 14.00% 17.44%, 13.84% 18.23%, 10.25% 19.03%, 8.95% 19.82%, 8.13% 20.61%, 7.64% 21.40%, 7.32% 22.20%, 6.99% 22.99%, 6.83% 23.78%, 6.99% 24.57%, 7.32% 25.37%, 7.48% 26.16%, 7.32% 26.95%, 4.87% 27.75%, 3.73% 28.54%, 2.91% 29.33%, 2.10% 30.12%, 1.77% 30.92%, 1.44% 31.71%, 1.12% 32.50%, 0.95% 33.29%, 0.95% 34.09%, 0.95% 34.88%, 0.95% 35.67%, 0.95% 36.47%, 0.95% 37.26%, 0.95% 38.05%, 0.95% 38.84%, 0.95% 39.64%, 0.95% 40.43%, 0.95% 41.22%, 0.95% 44.39%, 0.95% 49.94%, 0.95% 55.49%, 0.95% 61.04%, 0.95% 66.59%, 0.95% 72.14%, 0.95% 77.69%, 0.95% 83.24%, 0.95% 88.78%, 0.95% 94.33%, 0.95% 99.88%, 92.40% 99.88%, 99.40% 94.33%, 99.40% 88.78%, 99.25% 83.24%, 99.25% 77.69%, 99.40% 72.14%, 99.40% 66.59%, 99.40% 61.04%, 99.40% 55.49%, 99.40% 49.94%, 99.40% 44.39%, 99.40% 41.22%, 99.40% 40.43%, 99.40% 39.64%, 99.40% 38.84%, 99.40% 38.05%, 99.40% 37.26%, 99.40% 36.47%, 99.40% 35.67%, 99.40% 34.88%, 99.40% 34.09%, 99.40% 33.29%, 99.25% 32.50%, 99.09% 31.71%, 98.77% 30.92%, 98.44% 30.12%, 97.79% 29.33%, 96.97% 28.54%, 95.67% 27.75%, 93.22% 26.95%, 92.89% 26.16%, 93.22% 25.37%, 93.22% 24.57%, 93.38% 23.78%, 93.22% 22.99%, 93.22% 22.20%, 92.89% 21.40%, 92.57% 20.61%, 91.75% 19.82%, 90.45% 19.03%, 86.21% 18.23%, 86.04% 17.44%, 85.88% 16.65%, 85.39% 15.85%, 84.90% 15.06%, 84.09% 14.27%, 83.11% 13.48%, 81.64% 12.68%, 74.46% 11.89%, 73.97% 11.10%, 73.32% 10.31%, 72.50% 9.51%, 71.36% 8.72%, 70.06% 7.93%, 67.94% 7.13%, 65.16% 6.34%, 60.92% 5.55%, 57.82% 4.76%, 55.70% 3.96%, 54.07% 3.17%, 52.77% 2.38%, 51.46% 1.59%, 50.65% 0.79%, 49.83% 0.00%);
	clip-path: polygon(51.03% 0.00%, 50.38% 0.79%, 49.40% 1.59%, 48.26% 2.38%, 46.95% 3.17%, 45.16% 3.96%, 42.87% 4.76%, 39.29% 5.55%, 35.05% 6.34%, 32.27% 7.13%, 30.48% 7.93%, 29.34% 8.72%, 28.19% 9.51%, 27.54% 10.31%, 26.73% 11.10%, 21.18% 11.89%, 18.24% 12.68%, 16.94% 13.48%, 15.96% 14.27%, 15.15% 15.06%, 14.66% 15.85%, 14.17% 16.65%, 14.00% 17.44%, 13.84% 18.23%, 10.25% 19.03%, 8.95% 19.82%, 8.13% 20.61%, 7.64% 21.40%, 7.32% 22.20%, 6.99% 22.99%, 6.83% 23.78%, 6.99% 24.57%, 7.32% 25.37%, 7.48% 26.16%, 7.32% 26.95%, 4.87% 27.75%, 3.73% 28.54%, 2.91% 29.33%, 2.10% 30.12%, 1.77% 30.92%, 1.44% 31.71%, 1.12% 32.50%, 0.95% 33.29%, 0.95% 34.09%, 0.95% 34.88%, 0.95% 35.67%, 0.95% 36.47%, 0.95% 37.26%, 0.95% 38.05%, 0.95% 38.84%, 0.95% 39.64%, 0.95% 40.43%, 0.95% 41.22%, 0.95% 44.39%, 0.95% 49.94%, 0.95% 55.49%, 0.95% 61.04%, 0.95% 66.59%, 0.95% 72.14%, 0.95% 77.69%, 0.95% 83.24%, 0.95% 88.78%, 0.95% 94.33%, 0.95% 99.88%, 92.40% 99.88%, 99.40% 94.33%, 99.40% 88.78%, 99.25% 83.24%, 99.25% 77.69%, 99.40% 72.14%, 99.40% 66.59%, 99.40% 61.04%, 99.40% 55.49%, 99.40% 49.94%, 99.40% 44.39%, 99.40% 41.22%, 99.40% 40.43%, 99.40% 39.64%, 99.40% 38.84%, 99.40% 38.05%, 99.40% 37.26%, 99.40% 36.47%, 99.40% 35.67%, 99.40% 34.88%, 99.40% 34.09%, 99.40% 33.29%, 99.25% 32.50%, 99.09% 31.71%, 98.77% 30.92%, 98.44% 30.12%, 97.79% 29.33%, 96.97% 28.54%, 95.67% 27.75%, 93.22% 26.95%, 92.89% 26.16%, 93.22% 25.37%, 93.22% 24.57%, 93.38% 23.78%, 93.22% 22.99%, 93.22% 22.20%, 92.89% 21.40%, 92.57% 20.61%, 91.75% 19.82%, 90.45% 19.03%, 86.21% 18.23%, 86.04% 17.44%, 85.88% 16.65%, 85.39% 15.85%, 84.90% 15.06%, 84.09% 14.27%, 83.11% 13.48%, 81.64% 12.68%, 74.46% 11.89%, 73.97% 11.10%, 73.32% 10.31%, 72.50% 9.51%, 71.36% 8.72%, 70.06% 7.93%, 67.94% 7.13%, 65.16% 6.34%, 60.92% 5.55%, 57.82% 4.76%, 55.70% 3.96%, 54.07% 3.17%, 52.77% 2.38%, 51.46% 1.59%, 50.65% 0.79%, 49.83% 0.00%);
}

/* ---- counter-showcase pills: two corrections to the hover life above ----
   1) The pill grid gap is 10px and the lift is 6px. Hovering in the gap lifts the lower pill
      into the cursor, which re-fires mouseenter, which lifts it again: the pills flicker
      violently between the two rows. Pills get no transform. They already signal hover
      strongly, mouseenter turns them green with white text.
   2) background-color was missing from the transition list, so the green snapped in instantly
      while the label colour crawled over .3s, leaving dark text on a dark pill. Colour,
      background and border now move together in one short step. */
.elementor:not(.elementor-location-header):not(.elementor-location-footer) .mev-cs-pill:hover,
.elementor:not(.elementor-location-header):not(.elementor-location-footer) .mev-cs-pill.is-active {
	transform: none !important;
	box-shadow: none !important;
}
.elementor:not(.elementor-location-header):not(.elementor-location-footer) .mev-cs-pill {
	transition: background-color .18s ease, border-color .18s ease, color .18s ease !important;
}
