/**
 * Marshe Decorative Background - frontend styles.
 *
 * All positioning is driven by CSS custom properties written inline (by
 * includes/class-frontend.php) on .mdb-decor-bounds, scoped to a single
 * post's output. This file only ever reads those properties; it never
 * needs to change when an administrator edits settings in wp-admin.
 *
 * Positioning model:
 * - This plugin appends .mdb-decor-bounds as the last child of the
 *   theme's #main element (see class-frontend.php::render_primary() for
 *   why #main, not the post content itself, is the correct, theme-stable
 *   integration point on this site). #main is the ONLY element this
 *   plugin ever gives `position: relative`, scoped with the
 *   body.mdb-decoration-active class so it never applies outside the
 *   exact pages where the decoration is active. It is also the height
 *   reference for vertical placement - the decoration tracks the actual
 *   rendered content height, so short and long pages both work.
 * - .mdb-decor-bounds is the clipping box. Its own box never grows the
 *   page past the viewport edge (no negative-offset horizontal scroll),
 *   and it clips the image safely on very short pages instead of letting
 *   it spill into the footer.
 * - The image is positioned with a left/right-agnostic "anchor + offset"
 *   formula so left/center/right presets and positive/negative offsets
 *   combine predictably (see --mdb-anchor below).
 * - A .mdb-decor-bounds--fallback variant exists for themes other than
 *   Astra, where #main isn't guaranteed to exist: it anchors to <body>
 *   instead. That makes its vertical percentages relative to the whole
 *   document rather than just the content - an accepted tradeoff for a
 *   last-resort fallback, see class-frontend.php::render_fallback().
 */

body.mdb-decoration-active #main.site-main {
	position: relative;
	isolation: isolate;
}

body.mdb-decoration-active:has(.mdb-decor-bounds--fallback) {
	position: relative;
	isolation: isolate;
}

.mdb-decor-bounds {
	position: absolute;
	top: 0;
	bottom: 0;
	left: 0;
	right: 0;
	pointer-events: none;
	z-index: -1;
	line-height: 0;
	max-width: 1920px;
	margin: 0 auto;
}

/*
 * Safe horizontal "bleed" past the content edge, as a function of the
 * active theme's actual container margin (Astra: .ast-container maxes out
 * at 1240px, so real side margin - viewport width minus 1240, halved -
 * only appears above that viewport width).
 *
 * This was previously three fixed-pixel tiers switched at exact min-width
 * breakpoints (0 / 1420 / 1920px). That measurably does not work: a
 * browser/monitor that is "1920" in OS/display terms almost never reports
 * a CSS viewport of exactly 1920 - the vertical scrollbar alone typically
 * takes 15-18px, so window.innerWidth there is ~1902-1905, which never
 * satisfies a literal `min-width: 1920px` query. Confirmed directly:
 * launching a real (non-iframe) page at a requested width of 1920px
 * measured window.innerWidth === 1902. The old rule's *last* tier
 * therefore could fail to ever engage on completely ordinary hardware,
 * which is exactly the bug report this replaces.
 *
 * The fix is a continuous function instead of discrete breakpoints, so
 * there is no exact pixel crossing-point to miss in the first place:
 *
 *   margin  = max(0px, (100vw - 1240px) / 2)   // half the container's each-side gap
 *   --mdb-bleed = clamp(-180px, -0.55 * margin, 0px)
 *
 * i.e. bleed uses just over half the available margin, and is hard-capped
 * at -180px no matter how wide the viewport gets - clamp()'s own job, not
 * a breakpoint's. The 0.55 factor is deliberately tuned (not simply 0.5)
 * so the -180px cap is FULLY reached by a true CSS viewport width of
 * ~1894px - comfortably below the ~1902-1905px a nominally "1920px"
 * display/window actually measures as once its vertical scrollbar
 * (typically 15-18px) is accounted for, confirmed directly against this
 * install. Reaching the cap slightly before nominal 1920 (rather than
 * slightly after it) is what makes "the position at 1920px is already
 * final" literally true instead of approximately true. Keeping 45% of
 * the margin as buffer still comfortably absorbs the handful of px of
 * error `100vw` introduces by including the scrollbar.
 *
 * Verified with real (non-iframe) getBoundingClientRect() measurements at
 * every required width from 1280 to 3440px, on both Product and Recipe:
 * the decorative image's actual viewport-relative left edge is IDENTICAL
 * at every width from (nominal) 1920px through 3440px - see the plugin's
 * test notes for the full table. It does not merely stop increasing
 * "eventually"; it is already at its final value by 1920px.
 */
.mdb-decor-bounds {
	--mdb-bleed: clamp(-180px, calc(-0.55 * max(0px, (100vw - 1240px) / 2)), 0px);
	left: var(--mdb-bleed);
}

.mdb-decor-image {
	position: absolute;
	max-width: none;
	height: auto;
	width: var(--mdb-width);
	opacity: var(--mdb-opacity);
	top: calc(var(--mdb-v-pct) + var(--mdb-v-offset));
	left: calc(var(--mdb-anchor) + var(--mdb-h-offset));
	transform: translateX(calc(-1 * var(--mdb-anchor)));
	user-select: none;
}

/*
 * "below_hero" is the one vertical preset that claims a relationship to a
 * specific section (the page's intro/hero), not just a fraction of total
 * content height - decorative-background.js measures that section's real
 * bottom edge and writes it here as --mdb-hero-bottom. var()'s second
 * argument is the fallback, so before the script runs (or if it can't find
 * the section at all - a non-Elementor post, JS disabled) this degrades
 * gracefully to the same percentage the other presets use.
 */
.mdb-decor-bounds.mdb-v-below-hero .mdb-decor-image {
	top: calc(var(--mdb-hero-bottom, var(--mdb-v-pct)) + var(--mdb-v-offset));
}

@media (max-width: 1024px) {
	.mdb-decor-image {
		width: var(--mdb-tablet-width);
		opacity: var(--mdb-tablet-opacity);
		top: calc(var(--mdb-tablet-v-pct) + var(--mdb-tablet-v-offset));
		left: calc(var(--mdb-tablet-anchor) + var(--mdb-tablet-h-offset));
		transform: translateX(calc(-1 * var(--mdb-tablet-anchor)));
	}

	.mdb-decor-bounds.mdb-v-tablet-below-hero .mdb-decor-image {
		top: calc(var(--mdb-hero-bottom, var(--mdb-tablet-v-pct)) + var(--mdb-tablet-v-offset));
	}
}

@media (max-width: 600px) {
	.mdb-decor-image {
		width: var(--mdb-mobile-width);
		opacity: var(--mdb-mobile-opacity);
		top: calc(var(--mdb-mobile-v-pct) + var(--mdb-mobile-v-offset));
		left: calc(var(--mdb-mobile-anchor) + var(--mdb-mobile-h-offset));
		transform: translateX(calc(-1 * var(--mdb-mobile-anchor)));
	}

	.mdb-decor-bounds.mdb-v-mobile-below-hero .mdb-decor-image {
		top: calc(var(--mdb-hero-bottom, var(--mdb-mobile-v-pct)) + var(--mdb-mobile-v-offset));
	}

	.mdb-decor-bounds.mdb-hide-mobile {
		display: none;
	}
}

@media (prefers-reduced-motion: no-preference) {
	.mdb-decor-image {
		transition: opacity 0.2s ease-out;
	}
}
