/*
 * OCNARK Hero ribbon visual layer.
 *
 * Replaces the old right-hand composite: a pale teal background shape, a
 * platform screenshot in .hero-img-wrap, and three floating cards. All three
 * are gone from the widget markup as of 1.14.0. What remains on the right is
 * one uploaded image with real transparency, sitting directly on the white
 * page background.
 *
 * EVERY tunable below is a CSS custom property set on the Elementor wrapper by
 * the widget's control "selectors". Nothing in this file hard-codes a size,
 * offset or timing, and the widget never prints a per-control <style> block.
 * Elementor writes the desktop value on the wrapper and the tablet/mobile
 * values inside its own breakpoint media queries, so the responsive cascade is
 * handled for us and the rules here stay breakpoint-agnostic.
 *
 * The fallbacks in each var() are the shipped defaults, so the layer is
 * correctly placed and moving even before a single control is touched.
 */

/*
 * THE CLIP HAPPENS AT THE HERO, NOWHERE ELSE.
 *
 * The ribbon is an oversized, deliberately cropped composition: wider and
 * taller than the column it is anchored to, entering above the hero and
 * leaving past the right and bottom edges. For that to read as a crop rather
 * than as a picture in a box, every wrapper between the ribbon and the hero
 * has to let it through, and the hero itself has to cut it off.
 *
 * .hero is the full-bleed element, so clipping there puts the cut at the
 * viewport edge and guarantees no horizontal page overflow. Clipping at
 * .container instead would cut at the 1280px max-width and leave a visible
 * vertical seam on wide screens, which is the exact rectangular boundary this
 * composition is trying to avoid.
 *
 * These overflow declarations are scoped to this widget, so no other .hero or
 * .container on the site is affected. They set no size or position: the grid,
 * the columns and the left content are untouched.
 */
/*
 * .hero is the positioning context and nothing else.
 *
 * It deliberately does NOT clip. Clipping here is what produced the straight
 * horizontal seam: the hero's top border edge sits directly under the sticky
 * header, so the artwork was cut in a dead flat line exactly where the header
 * ends. Moving that boundary by growing the hero would have meant touching its
 * padding, and the theme sets a different .hero padding-top per breakpoint
 * (0px at 1440, 40px at 1024), so any single value would shift the left column
 * at some widths. Measured: it moved everything up 67px at 1024.
 *
 * Stripe solves it the other way round and so do we. Their hero section is
 * overflow:visible and the background layer clips itself, inset negatively at
 * the top. The hero's box is never involved, so the content cannot move.
 */
.elementor-widget-ocnark-hero .hero {
	position: relative;
	overflow: visible;
}

/*
 * The background layer. This is the element that clips.
 *
 * It spans the hero exactly on three sides and starts one header-height above
 * it, so the artwork continues up behind the navigation instead of stopping at
 * a cut. Right, bottom and left sit on the hero's edges, so those crops are
 * unchanged. overflow:hidden here also keeps the ribbon out of the document's
 * scrollable width, which is why .hero can safely stop clipping.
 *
 * --aqn-hero-rise is the header height. 67px is the measured live value for
 * header.site-header; override the property if the header ever changes height.
 *
 * NOTE ON SIZE: the ribbon's percentages resolve against this layer, which is
 * 67px taller than the hero, so the artwork renders about 6 to 7% larger than
 * before depending on viewport. That is compensated in the Elementor panel,
 * not here, because those are saved page values.
 */
.elementor-widget-ocnark-hero .aqn-ribbon-layer {
	position: absolute;
	top: calc( -1 * var( --aqn-hero-rise, 67px ) );
	right: 0;
	bottom: 0;
	left: 0;
	overflow: hidden;
	pointer-events: none;
	z-index: 0;
}

.elementor-widget-ocnark-hero .container,
.elementor-widget-ocnark-hero .hero-inner {
	overflow: visible;
}

.elementor-widget-ocnark-hero .hero::before,
.elementor-widget-ocnark-hero .hero::after {
	content: none;
}

/*
 * The single approved change on the left: a stacking context, so hero copy is
 * always painted above the ribbon. No layout, spacing, typography or colour
 * value is set here. Without it the ribbon, being a positioned element later
 * in the DOM, would paint over the headline whenever a wide width or a
 * negative right offset carried it across the column boundary.
 */
.elementor-widget-ocnark-hero .hero-content {
	position: relative;
	z-index: 1;
}

.elementor-widget-ocnark-hero .aqn-ribbon {
	position: absolute;
	display: var( --aqn-ribbon-display, block );
	top: var( --aqn-ribbon-top, -26% );
	right: var( --aqn-ribbon-right, -10% );
	width: var( --aqn-ribbon-width, 50% );
	height: var( --aqn-ribbon-height, 155% );
	opacity: var( --aqn-ribbon-opacity, 1 );
	/* Below .hero-content above, and inert: the ribbon is pure decoration. */
	z-index: 0;
	pointer-events: none;
}

.elementor-widget-ocnark-hero .aqn-ribbon-img {
	display: block;
	width: 100%;
	height: 100%;
	/*
	 * cover by default, which is the crop. The wrapper is larger than the
	 * column, so cover fills it and pushes the artwork past the edges instead
	 * of shrinking it to fit. contain is still available per breakpoint for
	 * anyone who wants the whole ribbon visible.
	 */
	object-fit: var( --aqn-ribbon-fit, cover );
	object-position: var( --aqn-ribbon-anchor, right top );
	filter: saturate( var( --aqn-ribbon-saturate, 100% ) );
}

/*
 * One keyframe pair for the whole feature, transforms only.
 *
 * Nothing here touches width, height, object-fit or any paint property, so the
 * browser composites the same rasterised image throughout: the ribbon is never
 * warped or redrawn, only moved. alternate + ease-in-out means the pair also
 * serves the return journey, so there is no seam at the loop point.
 *
 * Scale arrives as a plain percentage (0 to 6) and is converted here rather
 * than in PHP, so the control reads as "how much bigger, in percent" while the
 * transform still gets a proper multiplier.
 */
/*
 * A CLOSED LOOP, NOT AN ALTERNATING A-TO-B.
 *
 * The previous version was a two-keyframe from/to played `ease-in-out
 * alternate`. That cannot avoid a dead stop: when an animation reverses
 * direction its velocity has to pass through zero, so the ribbon halted at
 * both ends of every cycle. Easing only changed how long the halt lasted;
 * `linear alternate` would have replaced it with a visible kink as the
 * direction snapped over.
 *
 * So the reversal is gone rather than softened. 0% and 100% are the same
 * state, which makes the cycle seamless, and the four steps trace an ellipse:
 * X swings full width while Y arcs out and back. Played `linear infinite`
 * there is no acceleration anywhere and no turn to see, which is what reads
 * as a current rather than a pendulum.
 *
 * HOW THE PANEL VALUES MAP. The controls stay in "total travel" terms, so
 * numbers tuned against the old animation still mean roughly what they meant:
 *
 *   Drift X   full horizontal span, split as +dx/2 and -dx/2
 *   Drift Y   arc depth, reaching dy/2 at the halfway point
 *   Scale     percent, peaking at the halfway point
 *   Rotate    counter-rotates +rot then -rot, which stops the loop reading
 *             as a flat orbit
 *
 * At the tuned 14s / 24px / -18px / 3% / 1.5deg that gives the ribbon a
 * 12px swing either side, a 9px arc, a 3% swell and a 1.5deg roll.
 *
 * Individual translate/scale/rotate rather than the transform shorthand:
 * they compose independently, so nothing here clobbers a transform set
 * elsewhere on the element.
 */
.elementor-widget-ocnark-hero .aqn-ribbon.is-animated {
	animation: aqn-ribbon-drift var( --aqn-ribbon-duration, 14s ) linear infinite;
	will-change: translate, scale, rotate;
}

@keyframes aqn-ribbon-drift {
	0%, 100% {
		translate: 0 0;
		scale: 1;
		rotate: 0deg;
	}
	25% {
		translate: calc( var( --aqn-ribbon-dx, 24px ) / 2 ) calc( var( --aqn-ribbon-dy, -18px ) / 4 );
		scale: calc( 1 + ( var( --aqn-ribbon-scale, 3 ) / 200 ) );
		rotate: var( --aqn-ribbon-rot, 1.5deg );
	}
	50% {
		translate: 0 calc( var( --aqn-ribbon-dy, -18px ) / 2 );
		scale: calc( 1 + ( var( --aqn-ribbon-scale, 3 ) / 100 ) );
		rotate: 0deg;
	}
	75% {
		translate: calc( var( --aqn-ribbon-dx, 24px ) / -2 ) calc( var( --aqn-ribbon-dy, -18px ) / 4 );
		scale: calc( 1 + ( var( --aqn-ribbon-scale, 3 ) / 200 ) );
		rotate: calc( -1 * var( --aqn-ribbon-rot, 1.5deg ) );
	}
}

/*
 * Reduced motion wins over the Animate switch, by design. The switch is an
 * editorial preference; this is an accessibility setting the visitor has
 * already expressed at OS level, so it is not negotiable from the panel.
 */
@media ( prefers-reduced-motion: reduce ) {
	.elementor-widget-ocnark-hero .aqn-ribbon.is-animated {
		animation: none;
	}
}

/*
 * MOBILE HERO SPACING.
 *
 * The 56px phantom row this block used to fix is gone at the source. It came
 * from .hero-visual, an empty grid item that cost nothing beside the content
 * but became its own 0px-tall row with a full 56px row-gap once stacked. That
 * placeholder has been removed entirely: grid columns are declared by
 * grid-template-columns rather than derived from the children, so dropping it
 * changed nothing. Verified live at both 1440 and 768: identical columns,
 * content width, content left, headline top, facepile top and hero height.
 *
 * What remains here is the stats gap and the hero's bottom padding.
 */
@media ( max-width: 767px ) {
	.elementor-widget-ocnark-hero .hero-stats {
		gap: 13px;
	}

	.elementor-widget-ocnark-hero .hero {
		padding-bottom: 50px;
	}
}

/* ========================================================================
 * HERO AND TRUST BAND AS ONE COMPOSITION (1.21.1)
 *
 * The structure Stripe uses was already here. Measured on the live homepage,
 * the hero widget and the "Listed on AquaNetica" widget are ALREADY siblings
 * inside one Elementor container (.e-con-full): hero, ribbon layer and logo
 * strip share a parent exactly as the reference does. Nothing needed moving,
 * and nothing here moves it. The strip was never a disconnected section; it
 * only looked like one because of how much empty space sat above it.
 *
 * WHERE THE SPACE WAS. Two rules owned the hero's vertical padding and they
 * stacked, differently per breakpoint:
 *
 *     .hero        40px top / 60px bottom at 1024, 16/32 at 640  (!important)
 *     .hero-inner  100px top / 100px bottom at desktop
 *
 * Measured before: header to first hero content was 100px at 1440 and 76px
 * at 1024, and the run from the last hero element to the logo band was 211px
 * at 1440. That is the "big empty space", and it is ordinary padding stacked
 * twice, not a missing structure.
 *
 * .hero now keeps NO vertical padding and .hero-inner keeps all of it, so
 * there is one owner and one number to reason about per breakpoint. The
 * !important below is not decoration: the theme declares .hero padding
 * !important at 1024, 640 and 600, and an !important can only be answered
 * with one. It is scoped to this widget, so no other .hero anywhere is
 * touched, and no theme, Elementor or third-party file is edited.
 * ===================================================================== */

.elementor-widget-ocnark-hero .hero {
	padding-top: 0;
	padding-bottom: 0;
	/*
	 * The hero no longer has to be a screenful on its own. It was min-height
	 * 100vh, which on a large display bought empty white in the middle to
	 * reach a height the content did not need. The composition now ends at
	 * the trust band, so the hero is as tall as what is in it.
	 */
	min-height: 0;
}
@media (max-width: 1024px) {
	.elementor-widget-ocnark-hero .hero { padding-top: 0 !important; padding-bottom: 0 !important; }
}
@media (max-width: 640px) {
	.elementor-widget-ocnark-hero .hero { padding-top: 0 !important; padding-bottom: 0 !important; }
}
@media (max-width: 600px) {
	.elementor-widget-ocnark-hero .hero { padding-top: 0 !important; padding-bottom: 0 !important; }
}

/* The one owner. Measured after: 44px at 1440, 36px at 1024 and 768, 28px at
 * 390, from the bottom of the sticky header to the first hero element. */
.elementor-widget-ocnark-hero .hero-inner { padding-top: 44px; padding-bottom: 36px; }
@media (max-width: 1024px) { .elementor-widget-ocnark-hero .hero-inner { padding-top: 36px; padding-bottom: 32px; } }
@media (max-width: 640px)  { .elementor-widget-ocnark-hero .hero-inner { padding-top: 28px; padding-bottom: 26px; } }

/* Internal rhythm. Only the gaps are touched; no element is resized. */
.elementor-widget-ocnark-hero .hero-desc  { margin-bottom: 22px; }
.elementor-widget-ocnark-hero .hero-ctas  { margin-bottom: 18px; }
.elementor-widget-ocnark-hero .hero-proof { margin-bottom: 18px; }

/* ========================================================================
 * The trust band, joined to the hero above it
 *
 * Reached as the hero widget's next sibling, which is what it already is, so
 * the logo component itself is not modified and not duplicated. Its markup,
 * its three-track loop, its 57 logos and their links and alt text, its
 * animation and its reduced-motion behaviour are all left exactly as they
 * are; only the space around and inside the band is set here.
 *
 * --pull is the component's own variable, used as intended and modestly: 32px
 * on a desktop, which absorbs the 20px Elementor container row-gap and leaves
 * a 12px overlap so the band reads as the bottom of the hero rather than the
 * top of the next thing. It is NOT being used to cancel a layout mistake; the
 * padding above was fixed first, at its source.
 * ===================================================================== */

.elementor-widget-ocnark-hero + .elementor-widget .an-logos { --pull: 32px; }
@media (max-width: 640px) {
	/* Smaller on a phone, where a real overlap would crowd the last hero line
	 * for no compositional gain. Measured at 390: an 8px gap, not an overlap. */
	.elementor-widget-ocnark-hero + .elementor-widget .an-logos { --pull: 12px; }
}

/*
 * The band's own height. It was 206px at 1440 for 68px of logos, because the
 * label carried 30px of padding-bottom AND 30px of margin-bottom under an
 * 18px line, and the strip added 30px top and bottom. That is the "large
 * empty gap above the label". Spacing only: the logos keep their own size.
 */
.elementor-widget-ocnark-hero + .elementor-widget .an-strip {
	padding-top: 10px;
	padding-bottom: 10px;
}
.elementor-widget-ocnark-hero + .elementor-widget .an-logos-label {
	padding-bottom: 0;
	margin-bottom: 14px;
}

/* ========================================================================
 * THE RIBBON STOPS AT 768 (1.23.0)
 *
 * FINAL DECISION: there is no mobile ribbon. Not a narrower one, not an
 * adaptive channel, not fragments between the text blocks. Below 768px the
 * hero is white.
 *
 * Everything that used to live here has been deleted, not disabled: the
 * 1.21.3 headline window, the 1.22.0 is-flowing geometry, and the clip-path
 * the flow script wrote. widgets/hero-ribbon-flow.js is gone from the plugin
 * and from register_scripts(), so below 768 there is no measuring pass, no
 * exclusion polygon and no ResizeObserver running for the ribbon.
 *
 * THREE LAYERS, ALL AT 768, AND THEY MUST AGREE:
 *
 *   1. this rule                     nothing is painted
 *   2. the <source media> in
 *      class-hero-widget.php         nothing is downloaded
 *   3. mu-plugins/aquanetica-ribbon   nothing is initialised, because 1.1.0
 *      .php                          refuses to boot on a zero-sized host
 *
 * WHY !important AND WHY NOT THE PANEL ALONE. The saved Elementor value for
 * this page is already Ribbon > Mobile > Hide, and nothing here forces it back
 * on. But the panel is a per-page setting and this is now a product decision,
 * so it is enforced rather than trusted: any page using this widget gets a
 * white hero on a phone whether or not someone remembers the control. The
 * !important answers Elementor's own inline --aqn-ribbon-display, which is
 * itself emitted as a declaration on the widget wrapper.
 * ===================================================================== */

@media (max-width: 767px) {
	.elementor-widget-ocnark-hero .aqn-ribbon,
	.elementor-widget-ocnark-hero .aqn-ribbon-layer {
		display: none !important;
	}
}

/*
 * Tablet and up keep the editor's own composition, and only gain the left-edge
 * guarantee, because from 768px the hero has room and the saved art direction
 * is the right one. Unchanged since 1.21.3.
 */
@media (min-width: 768px) and (max-width: 1024px) {
	.elementor-widget-ocnark-hero .aqn-ribbon {
		width: min( var( --aqn-ribbon-width, 50% ), calc( 108% - 620px ) );
	}
}

/* ========================================================================
 * THE HERO CTA SYSTEM (1.23.0)
 *
 * Three controls that have to read as one system:
 *
 *   guest    Join Free  /  Continue with Google  /  Explore Marketplace
 *   member   Go to Community  /  Explore Marketplace
 *
 * DESKTOP is a row, and is left as the theme has it: display, flex-wrap and
 * the 14px gap are the theme's own and are not restated here. The only thing
 * added is vertical centring on the Google item, so it sits on the same line
 * as Join Free instead of stretching.
 *
 * MOBILE is a column of equal-width controls. This IS a change to the theme's
 * behaviour and it is deliberate: left alone the row wraps to auto-width
 * buttons, which measured 127px for Join Free against 242px for Explore
 * Marketplace and read as three unrelated links rather than one system.
 * ===================================================================== */

/*
 * ONE HEIGHT AND ONE CORNER FOR ALL THREE, AT EVERY WIDTH.
 *
 * MEASURED, BEFORE:
 *
 *     Join Free            358 x 54    radius 10px
 *     Continue with Google 358 x 40    radius  4px   (Google, rectangular)
 *     Explore Marketplace  358 x 58    radius 10px
 *
 * An 18px height spread and a 6px corner spread is why the middle control read
 * as something pasted in from another site. Google's 40px is a hard ceiling:
 * renderButton() takes a width and no height, and size:'large' is the largest
 * value there is. So the AquaNetica buttons move to meet Google rather than
 * the other way round, which is also the only direction available without
 * touching Google's internals.
 *
 * 46px is the target: 6px off Google, comfortably over the 44px tap minimum,
 * and inside the 44-48 band asked for. Type size is untouched at 16px; the
 * height comes out of vertical padding, which was 14px against a 26px line box
 * and is now flex centring against an explicit min-height. That also fixes the
 * 54-vs-58 split between the two buttons, which was never a style choice: the
 * arrow glyph in "Explore Marketplace" was raising its line box by 4px.
 *
 * SCOPED TO THE HERO, NOT GLOBAL. .btn and .btn-lg are used across the site,
 * and re-proportioning every button everywhere is not what was asked for and
 * not something to do as a side effect of a hero alignment pass.
 */
/*
 * SELECTOR NOTE. a.btn.btn-lg, not just .btn: four classes and an element
 * (0,4,1). The theme's own button rule sets padding and border-radius at what
 * appears to be equal specificity, and the theme stylesheet is served in a way
 * that makes it opaque to CSSOM here, so its exact selector cannot be read.
 * An equal-specificity tie would be decided by source order, and source order
 * between a plugin stylesheet and the theme's is not something to rely on -
 * especially with an optimiser combining and deferring CSS. Winning on
 * specificity removes the question. No !important is needed, and none is used.
 */
/*
 * CTA TOKENS. One place to change the CTA system, rather than three buttons
 * hand-tuned to each other and a fourth number living in the theme's PHP.
 *
 * --aqn-cta-w  248px. Sized from the longest label, "Explore Marketplace",
 *              which renders at 242px; 248 is that rounded up with a little
 *              slack, so a wording change of a character or two does not
 *              immediately break the set.
 * --aqn-cta-h  46px. Google renders 40px in its inline-DOM mode and 44px in
 *              its iframe mode, and picks between them without telling us.
 *              46 sits just above both, clears the 44px tap-target minimum,
 *              and is OUR number rather than a copy of whatever Google is
 *              doing this month.
 * --aqn-cta-r  4px, matching the corner Google draws for shape:'rectangular'.
 *
 * theme inc/google-auth.php reads --aqn-cta-w off the mount and passes that
 * exact integer to renderButton(), so the width is declared once, here.
 */
.elementor-widget-ocnark-hero .hero-ctas {
	--aqn-cta-w: 248px;
	--aqn-cta-h: 46px;
	--aqn-cta-r: 4px;
}

.elementor-widget-ocnark-hero .hero-ctas > a.btn.btn-lg {
	min-height: var( --aqn-cta-h );
	padding-top: 0;
	padding-bottom: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;

	border-radius: var( --aqn-cta-r );
}

.elementor-widget-ocnark-hero .aqn-hero-google {
	/*
	 * align-self rather than align-items on the row: this centres the Google
	 * control without changing how the row treats the buttons that were
	 * already there.
	 */
	align-self: center;
	flex: 0 0 auto;
	width: var( --aqn-cta-w );
	max-width: 100%;
	line-height: 0;

	/* The slot matches the buttons so the row and the column both sit on one
	   baseline; Google's own control is centred inside it. */
	min-height: var( --aqn-cta-h );
	display: flex;
	align-items: center;
}

/*
 * THE RESERVED SLOT, BEFORE GOOGLE ARRIVES.
 *
 * The button is fetched from accounts.google.com after window.load; measured
 * on the live homepage it was requested at 2902ms and finished at 3139ms.
 * The box was already reserved by the height token, so nothing reflowed, but
 * a 46px hole sat in the middle of the CTA stack for that quarter second.
 *
 * This paints a neutral outline in the reserved box so the stack looks
 * complete while Google is in flight, and it disappears the instant the
 * iframe exists. It is NOT a fake Google button: no logo, no label, no
 * pointer affordance, and nothing here reaches inside Google's iframe.
 *
 * :has() does the real work; :empty is the fallback for browsers without it,
 * covering the window before the wrapper div is inserted.
 */
.elementor-widget-ocnark-hero .aqn-hero-google:empty,
.elementor-widget-ocnark-hero .aqn-hero-google:not(:has(iframe)) {
	border: 1px solid #dadce0;
	border-radius: var( --aqn-cta-r );
	background: #fff;
}

/*
 * border-box, or the placeholder defeats its own purpose: a 1px border on a
 * content-box element makes the slot 250x48 and then 248x46 once Google
 * replaces it, which is a 2px shift in both axes. Measured before this line
 * was added.
 */
.elementor-widget-ocnark-hero .aqn-hero-google {
	box-sizing: border-box;
}

.elementor-widget-ocnark-hero .aqn-hero-google iframe {
	margin: 0 !important;
}

@media (max-width: 767px) {
	/*
	 * THE STACK IS A COLUMN, CENTRED, AND NOT THE FULL SCREEN.
	 *
	 * Stretched edge to edge the buttons read as three full-width bars rather
	 * than a considered CTA group, and at 430 that is a 398px button. The
	 * 48px inset plus a 340px ceiling keeps obvious breathing room at every
	 * width: 272px at 320, and 340px from 388 upward.
	 *
	 * This container is also what decides Google's width. The mount below is
	 * width:100% of this box, and google-auth.php measures the mount, so all
	 * three controls resolve to one number without any of them being told what
	 * it is.
	 */
	.elementor-widget-ocnark-hero .hero-ctas {
		flex-direction: column;

		/*
		 * align-items:flex-start, not stretch. The stack is a fixed
		 * --aqn-cta-w wide and sits on the left margin with the headline and
		 * the body copy above it, rather than spanning the screen. The
		 * near-edge-to-edge version this replaces was calc(100% - 48px)
		 * centred, which read as three full-width bars rather than a group of
		 * controls.
		 */
		align-items: flex-start;
		width: auto;
		max-width: none;
		margin-left: 0;
		margin-right: 0;
	}

	/*
	 * One width for all three. The buttons stretch; the Google mount is given
	 * the same box and Google is told that pixel width by google-auth.php,
	 * which reads this element back with offsetWidth.
	 */
	.elementor-widget-ocnark-hero .hero-ctas > a.btn.btn-lg {
		/* max-width keeps it inside the content column on a 320 screen, where
		   the column is 288 and the token is 248, so it never actually binds
		   today; it is there so a future narrower phone cannot overflow. */
		width: var( --aqn-cta-w );
		max-width: 100%;
		text-align: center;
	}

	.elementor-widget-ocnark-hero .aqn-hero-google {
		/* Same token as the two buttons, so all three are one width and the
		   width passed to renderButton() is the width on screen. */
		align-self: flex-start;
		justify-content: stretch;
	}

	.elementor-widget-ocnark-hero .aqn-hero-google > * {
		width: 100%;
	}
}
