/* ==========================================================================
   Portfolio / "See Our Recent Work"
   Owns the Work Card (loop-item template 13201) and the Loop Carousel that
   shows it. Loads last, so it can override Elementor's kit/widget CSS at
   equal specificity without !important except where noted.

   Replaces four legacy alignment hacks that were removed in this pass:
     - style.css       .portfolio-section{margin-left:calc(...1639px...)}
     - style.css       .portfolio-listing .elementor-loop-container{margin-right:-250px}
     - mm-fixes.css    .portfolio-section{margin-left:calc(...1320px...)}
     - site.js         inline margin-left on .portfolio-section .elementor-container
   Each one hand-shifted a full-width section instead of centering its
   contents, so the section drifted further right the wider the screen got.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Layout: center the carousel on the site's 1300px content column
   The band itself stays full-bleed (background lives on .portfolio-section);
   only the track and the arrows are constrained.
   -------------------------------------------------------------------------- */
.portfolio-listing > .elementor-widget-container {
	/* 1300px, not 1320px. mm-fixes.css caps boxed containers at 1320px, but Elementor's
	   column then adds 10px each side, so every heading and content block on these pages
	   actually occupies 1300px (310->1610 at a 1920 viewport). This section's own wrapper
	   is `section_full_width`, so it spans the viewport and there is no column to inherit
	   that inset from — matching 1300px here is what puts the first card's left edge and
	   the arrows' right edge exactly on the h2's. */
	max-width: 1300px;
	margin-inline: auto;
	/* Loop Carousel renders its arrows as SIBLINGS of .swiper (its own selector uses
	   `:is(.swiper,.swiper-container) ~ .elementor-swiper-button-next`), so without a
	   positioning context here they anchor to the nearest positioned ancestor and land
	   on the viewport edge instead of the 1300px content edge. */
	position: relative;
}

/* The band stays full-bleed; this is its inner gutter.
   !important is required because the per-page Elementor CSS
   (`.elementor-509 .elementor-element.elementor-element-5b05e0a`, specificity 0,3,0) sets
   an asymmetric `padding-left:10px` — a leftover paired with the shift hacks removed above,
   which pushed the track off centre. Matches how mm-fixes.css already forces this
   section's vertical padding.

   One 20px value covers every width: above ~1340px the 1300px max-width is what constrains
   the track, so this padding is inert; below that it is what keeps the cards off the screen
   edges, at the same 20px inset the headings already use. */
.portfolio-section {
	padding-left: 20px !important;
	padding-right: 20px !important;
}

/* Homepage only: the band goes white.
   The heading section above it is already transparent on the homepage, so whitening just
   the band gives one clean white block. City and service pages deliberately keep their
   beige -- there the beige runs continuously through the heading section and often the
   section after, so whitening only the band would leave a white stripe inside it.
   Keyed on `body.home` rather than `.page-id-509` so the intent follows the front page if
   it is ever reassigned. !important is needed to beat mm-fixes.css's own !important. */
body.home .portfolio-section {
	background-color: #FFFFFF !important;
}

/* Some pages also put a `padding-left:10px` on the carousel's column, which offset the
   track by another 5px. Zero it and let the max-width above own the alignment.
   :has() keeps this off post 1441 (Roof Insurance Claims), which reuses .portfolio-section
   around a reviews slider with its own padding. */
.portfolio-section .elementor-widget-wrap:has(> .portfolio-listing) {
	padding-left: 0 !important;
	padding-right: 0 !important;
}

/* Swiper reads slides-to-show/gap from data-settings; these vars are the
   presentation side of the same numbers. 24px matches the script's
   image_spacing_custom, --swiper-padding-bottom is what actually reserves
   room for the dots (a plain padding-bottom here loses to Elementor's var). */
.portfolio-listing .swiper,
.portfolio-listing .elementor-loop-container {
	--swiper-slides-gap: 24px;
	--swiper-padding-bottom: 40px;
}

/* --------------------------------------------------------------------------
   2. Arrows
   Loop Carousel positions arrows through its own custom properties at
   specificity 0,4,1 and leaves a residual translateY(-50%). Setting the vars
   cooperates with that instead of fighting it, which is why the old rules
   needed !important on every line and still landed 23px off.
   Anchored to right:0 of the now-1300px track = the content edge.
   -------------------------------------------------------------------------- */
.portfolio-listing .elementor-widget-container {
	--arrow-next-right-align: 0px;
	--arrow-next-right-position: 0px;
	--arrow-next-top-align: 0px;
	--arrow-prev-top-align: 0px;
	--arrow-next-translate-y: -92px;
	--arrow-prev-translate-y: -92px;
	--arrow-next-translate-x: 0px;
	--arrow-prev-translate-x: 0px;
}

/* Both arrows sit together at the top right, as they do in production. Elementor anchors
   the NEXT arrow from `right` (so the vars above place it), but the PREV arrow from `left`
   — which pinned it to the opposite edge of the track. Releasing `left` lets it take a
   `right` offset and sit beside next. The !important is unavoidable: Elementor's own
   `left: calc(...)` rule is specificity 0,4,1. */
.portfolio-listing .elementor-swiper-button-prev {
	left: auto !important;
	right: 56px;
}

.portfolio-listing .elementor-swiper-button-next,
.portfolio-listing .elementor-swiper-button-prev {
	width: 45px;
	height: 45px;
	border: none;
	border-radius: 50%;
	background: #161616;
	color: #fff;
	font-size: 16px;
	display: flex;
	align-items: center;
	justify-content: center;
	transition: background .2s ease;
	z-index: 3;
}
.portfolio-listing .elementor-swiper-button-next:hover,
.portfolio-listing .elementor-swiper-button-prev:hover {
	background: #3FAA6C;
}
.portfolio-listing .elementor-swiper-button-next svg,
.portfolio-listing .elementor-swiper-button-prev svg {
	fill: #fff;
	width: 16px;
	height: 16px;
}
.portfolio-listing .elementor-swiper-button-next:focus-visible,
.portfolio-listing .elementor-swiper-button-prev:focus-visible {
	outline: 3px solid #3FAA6C;
	outline-offset: 3px;
}

/* Pagination bullets */
.portfolio-listing .swiper-pagination-bullet {
	width: 9px;
	height: 9px;
	background: #B4B0A7;
	opacity: 1;
}
.portfolio-listing .swiper-pagination-bullet-active {
	background: #3FAA6C;
}

/* --------------------------------------------------------------------------
   3. The Work Card (loop-item template 13201)
   Scoped to .elementor-13201 so it applies in BOTH the Loop Carousel and the
   /recent-works/ Loop Grid, and can never reach the blog card (13199).

   The template is image-then-title in normal flow. Rather than restructure it
   in Elementor (which would risk the dynamic-tag bindings), the frame is made
   a positioning context and the title is lifted onto the photo in CSS.
   -------------------------------------------------------------------------- */
/* The card's outer container. Elementor gives boxed containers a default 10px inline
   padding, which insets each card inside its slide — that made cards 404px instead of
   424px, pushed the row 10px in from the line the arrows sit on, and inflated the
   visual gap between cards to 44px. Zero it (vars and shorthand, since the padding comes
   from custom properties) so the card fills its slide exactly. */
.elementor-13201 > .e-con {
	--padding-block-start: 0px;
	--padding-block-end: 0px;
	--padding-inline-start: 0px;
	--padding-inline-end: 0px;
	padding: 0;
}

.elementor-13201 .e-con-inner {
	position: relative;
	display: block;
	width: 100%;
	max-width: 100%;
	padding: 0;
	aspect-ratio: 4 / 3;
	border-radius: 10px;        /* site card convention; ~= production's 29px on its 1070px image */
	overflow: hidden;
	background: #294932;        /* holds the card shape while the photo loads */
}

/* Photo fills the frame. Stretching the image's own <a> makes the whole card
   one click target without adding markup. */
.elementor-13201 .elementor-widget-theme-post-featured-image,
.elementor-13201 .elementor-widget-theme-post-featured-image .elementor-widget-container,
.elementor-13201 .elementor-widget-theme-post-featured-image a {
	position: absolute;
	inset: 0;
	display: block;
	margin: 0;
}
.elementor-13201 .elementor-widget-theme-post-featured-image img {
	width: 100%;
	height: 100%;
	aspect-ratio: auto;         /* overrides the old 3/2 rule */
	border-radius: 0;           /* radius belongs to the frame now */
	object-fit: cover;
	object-position: center 55%;/* favours the roofline over the sky */
	display: block;
	transition: transform .6s cubic-bezier(.2, .6, .2, 1);
}

/* Scrim. Production has none at all — its white text is legible only because
   those particular photos are dark at the bottom. This reuses the site's own
   hero scrim colour (#0D2517, legacy-customizer.css .mm-hr/.mm-cr heroes) so
   the cards read as part of the same system, and guarantees contrast on any
   photo. pointer-events:none lets clicks fall through to the stretched link. */
.elementor-13201 .e-con-inner::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	pointer-events: none;
	/* Stops are tuned to where the title actually sits: the text block occupies roughly
	   the bottom 8-38% of the card, so the scrim is dense through 22% and then falls away
	   quickly. A slower ramp (e.g. .65 at 45%) dims the whole lower half of the photo and
	   reads as murky without buying any extra contrast where the words are. */
	background: linear-gradient(to top,
		rgba(13, 37, 23, .94) 0%,
		rgba(13, 37, 23, .78) 22%,
		rgba(13, 37, 23, .34) 46%,
		rgba(13, 37, 23, 0) 68%);
}

/* Title, sitting on the scrim at the bottom-left (production's placement,
   ~4.7% of card width in — 20px here vs its 50px on a 1070px image). */
.elementor-13201 .elementor-widget-theme-post-title {
	position: absolute;
	z-index: 2;
	left: 0;
	right: 0;
	bottom: 0;
	margin: 0;
	padding: 22px 24px;
	width: auto;
}
.elementor-13201 .elementor-widget-theme-post-title .elementor-widget-container {
	margin: 0;
}
.elementor-13201 .elementor-widget-theme-post-title .elementor-heading-title,
.elementor-13201 .elementor-widget-theme-post-title .elementor-heading-title a {
	/* Satoshi 700 white, matching production's title treatment. Satoshi loads
	   400/500/700 via mm-site-core/includes/fonts.php — do not ask for 600. */
	font-family: Satoshi, "Helvetica Neue", Helvetica, Arial, sans-serif;
	font-size: 20px !important;   /* beats mm-fixes' .elementor-kit-5 h3 clamp */
	line-height: 1.3 !important;
	font-weight: 700;
	color: #fff !important;
	text-decoration: none;
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* Hover / focus. The slide's own overflow:hidden clips the scale to the card. */
.elementor-13201 .e-con-inner:hover img {
	transform: scale(1.05);
}
.elementor-13201 .e-con-inner:has(a:focus-visible) {
	outline: 3px solid #3FAA6C;
	outline-offset: 3px;
}

/* Grid context (/recent-works/): give the cards the same rhythm as the
   carousel's 24px gap. */
.elementor-widget-loop-grid .elementor-loop-container.elementor-grid {
	--grid-column-gap: 24px;
	--grid-row-gap: 24px;
}

/* --------------------------------------------------------------------------
   4. Responsive
   Breakpoints are the kit's three active ones: 1600 / 1036 / 767.
   -------------------------------------------------------------------------- */
@media (max-width: 1036px) {
	.elementor-13201 .elementor-widget-theme-post-title { padding: 20px 22px; }
	.elementor-13201 .elementor-widget-theme-post-title .elementor-heading-title,
	.elementor-13201 .elementor-widget-theme-post-title .elementor-heading-title a {
		font-size: 18px !important;
	}
}

@media (max-width: 767px) {
	.elementor-13201 .elementor-widget-theme-post-title { padding: 18px 20px; }
	.elementor-13201 .elementor-widget-theme-post-title .elementor-heading-title,
	.elementor-13201 .elementor-widget-theme-post-title .elementor-heading-title a {
		font-size: 17px !important;
		-webkit-line-clamp: 3;
	}
	.portfolio-listing .elementor-widget-container {
		--arrow-next-translate-y: -64px;
		--arrow-prev-translate-y: -64px;
	}
	.portfolio-listing .elementor-swiper-button-next,
	.portfolio-listing .elementor-swiper-button-prev {
		width: 38px;
		height: 38px;
	}
	.portfolio-listing .elementor-swiper-button-prev { right: 48px; }
}

/* Respect reduced-motion preferences. */
@media (prefers-reduced-motion: reduce) {
	.elementor-13201 .elementor-widget-theme-post-featured-image img { transition: none; }
	.elementor-13201 .e-con-inner:hover img { transform: none; }
}
