/*!
 * service-tiles.css — the four homepage service tiles (Aerial LiDAR, Subdivisions,
 * Boundary Surveys, Historical Restorations).
 *
 * These were Elementor Pro "Call to Action" widgets. They are now plain free-Elementor
 * containers, so the geometry that used to come from Pro's widget-call-to-action.min.css has
 * to live here. Every value is a direct port of the Pro rule it replaces, measured on the live
 * site on 2026-08-06.
 *
 * DOM, and how it maps back to the Pro widget:
 *
 *   .mls-tile            container   <- .elementor-cta            (clips the zoom)
 *     .mls-tile__media   container   <- .elementor-cta__bg-wrapper (holds the background image)
 *       ::before                     <- .elementor-cta__bg         (the layer that scales)
 *       ::after                      <- .elementor-cta__bg-overlay (the hover scrim)
 *     .mls-tile__caption container   <- .elementor-cta__content
 *       h2.mls-tile__title           <- .elementor-cta__title
 *
 * The image layer is a pseudo-element rather than a fourth container for a reason: Pro scaled
 * .elementor-cta__bg *inside* the bg-wrapper, so the zoom was clipped at the image box and
 * never crept over the caption bar. Scaling .mls-tile__media itself would clip at .mls-tile
 * instead and bleed across the caption. ::before inherits the container's background-image, so
 * the image stays editable in Elementor while the transform happens on a layer of its own.
 *
 * Unlike the pro-fallback/ stylesheets this one loads unconditionally: the tiles are rebuilt in
 * the page's saved Elementor data, so the new markup is live whether or not Pro is.
 *
 * WHY THE CONTAINER RULES ARE PREFIXED WITH .e-con
 * ------------------------------------------------
 * Elementor's frontend.css declares
 *     .e-con { --overflow: visible; --min-height: initial;
 *              overflow: var(--overflow); min-height: var(--min-height);
 *              position: var(--position); width: var(--width); z-index: var(--z-index) }
 * — the same (0,1,0) specificity as a bare .mls-tile__media, so which one wins comes down to
 * stylesheet order. And that order is NOT stable: deactivating Elementor Pro flipped it.
 *
 *     Pro active:   elementor-frontend.css  ->  service-tiles.css   (these rules won)
 *     Pro inactive: service-tiles.css       ->  elementor-frontend.css (.e-con won)
 *
 * When .e-con wins, `overflow: var(--overflow)` is not simply discarded in favour of the rule
 * below it — an unresolved var is invalid at computed-value time, so the property computes to
 * its initial value. The tiles collapsed from 298px to 118px exactly this way. Prefixing with
 * .e-con takes these to (0,2,0) so they win on specificity and never depend on load order.
 */

.e-con.mls-tile {
	display: flex;
	flex-direction: column;
	position: relative;
	overflow: hidden;
	transition: 0.5s;
}

.e-con.mls-tile__media {
	position: relative;
	width: 100%;
	min-height: 200px;
	overflow: hidden;
	z-index: 1;
	/* The container's own background-image is set in Elementor; ::before inherits it. */
	background-repeat: no-repeat;
}

.e-con.mls-tile__media::before,
.e-con.mls-tile__media::after {
	content: "";
	position: absolute;
	inset: 0;
	/*
	 * Pro's stylesheet said `transition: all .4s`, but the generated per-widget CSS overrode
	 * transition-duration to 1500ms on all four tiles. 1500ms is what the site actually does.
	 */
	transition: all 1500ms;
}

.e-con.mls-tile__media::before {
	background-image: inherit;
	background-position: 50%;
	background-size: cover;
	background-repeat: no-repeat;
	z-index: 1;
	will-change: transform;
}

.e-con.mls-tile__media::after {
	z-index: 2;
}

.mls-tile:hover .e-con.mls-tile__media::after {
	background-color: rgba( 0, 0, 0, 0.3 );
}

.mls-tile--zoom:hover .e-con.mls-tile__media::before {
	transform: scale( 1.2 );
}

.e-con.mls-tile__caption {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	align-content: center;
	width: 100%;
	overflow: hidden;
	/*
	 * position/z-index are load-bearing, not decoration: the image layer is transformed on
	 * hover, which promotes it into the positioned paint layer. Without its own stacking
	 * context the caption bar would be painted underneath the zooming image.
	 */
	position: relative;
	z-index: 3;
	transition: 0.5s;
	/*
	 * skin-classic put this on the content bar, NOT on the card. Moving it to .mls-tile instead
	 * looks the same at a glance but leaves a 1px seam of tile background along the card's top
	 * and bottom edges, because the tile's height is fractional (298.8px).
	 */
	background-color: #f9fafa;
}

/*
 * .mls-tile__title lands on the heading widget's *wrapper* div — Elementor puts a widget's CSS
 * classes there, not on the <h2>.
 */
.mls-tile__title {
	width: 100%;
	position: relative;
	transition: 0.5s;
}

.mls-tile__title .elementor-heading-title {
	margin: 0;
	/*
	 * Hello Biz's theme.css sets `h1,h2,…{ line-height: 1.2 }`, which is what the Pro CTA title
	 * rendered at (28.8px at 24px). The free heading widget adds `.elementor-heading-title{
	 * line-height: 1 }`, which the Pro title never carried — left alone it shortens every tile
	 * by ~4.8px and the whole page with it. Restore the theme's value.
	 */
	line-height: 1.2;
}

@media ( max-width: 1024px ) {
	.mls-tile {
		/* Pro turned the whole card into a tap target below 1024px. */
		cursor: pointer;
	}
}
