/**
 * Split Slab and Comparison Ledger.
 *
 * Everything Elementor's controls cannot express lives here: the blend mode
 * that knocks the flow artwork out of its black plate, the mote drift, the
 * dashed ledger rules and the phone reflow. Colours, spacing and type come
 * from the panel as custom properties on .eexp, so a value set in Elementor
 * always wins over the fallback in this file.
 *
 * Both widgets share this sheet and the .eexp root, because they share the
 * tokens and are nearly always used together.
 */

.eexp {
	--eexp-green: #07864f;
	--eexp-green-light: #4dcf8d;
	--eexp-green-30: rgba(7, 134, 79, 0.3);
	--eexp-white-11: rgba(255, 255, 255, 0.11);
	--eexp-white-70: rgba(255, 255, 255, 0.7);
	--eexp-ink: #0d1b24;
	--eexp-offwhite: #f5f6f7;
	--eexp-navy: #0f3961;
	--eexp-navy-70: rgba(15, 57, 97, 0.7);
	--eexp-navy-80: rgba(15, 57, 97, 0.8);
	--eexp-radius: 52px;
	--eexp-bar: 6px;
	--eexp-dim: 0;

	/*
	 * How the two panels share the width, as a property rather than a
	 * grid-template-columns written straight onto .eexp-slab. The panel's
	 * "weight of the light panel" control has to beat this file's fallback,
	 * and a rule from the panel carries the element id, so it also beat the
	 * stacking rule at the bottom of this file -- which is why the slab used
	 * to stay in two columns on a phone and clip the ink panel. Written as a
	 * token, the control wins where it should and loses to the media query
	 * where it should.
	 */
	--eexp-split: 1.12fr;

	/* Spacing, all of it reachable from the panel. */
	/*
	 * Fluid rather than stepped, and set here rather than re-set inside a
	 * media query on .eexp-panel. A custom property set on a descendant beats
	 * the same one set here, which is where the panel's controls write, so the
	 * old media queries silently switched the padding control off below
	 * 1200px.
	 */
	--eexp-pad-y: clamp(28px, 3.4vw, 44px);
	--eexp-pad-x: clamp(20px, 3.8vw, 48px);
	--eexp-gap-title: 18px;
	--eexp-gap-body: 14px;
	--eexp-gap-stage: 28px;
	--eexp-gap-footer: 28px;
	--eexp-gap-label: 14px;
	--eexp-pill-gap: 8px;
	--eexp-pill-pad-y: 8px;
	--eexp-pill-pad-x: 16px;
	--eexp-pill-radius: 2000px;
	--eexp-spec-pad-y: 13px;
	--eexp-spec-pad-x: 18px;
	--eexp-spec-radius: 20px;
	--eexp-img-max: 620px;
	--eexp-title-measure: 16ch;
	--eexp-body-measure: 46ch;

	color: var(--eexp-white-70);

	/*
	 * A widget dropped into a half-width column is narrow at any viewport, so
	 * the stacking rule asks the slab's own box as well as the window's. The
	 * motes are unaffected: .eexp-flow is a container of its own and closer.
	 */
	container-type: inline-size;
}

.eexp *,
.eexp *::before,
.eexp *::after {
	box-sizing: border-box;
}

.eexp p {
	margin: 0;
}

.eexp img {
	display: block;
	max-width: 100%;
}

/*
 * The display face. Family inherited on purpose, so the kit's own heading
 * font carries through; this sets only what the shape needs.
 */
.eexp-heading {
	margin: 0;
	font-weight: 400;
	line-height: 1;
	text-transform: uppercase;
	letter-spacing: 0.01em;
	color: #fff;
}

.eexp-panel__title {
	font-size: clamp(24px, 2.2vw, 32px);
}

/* ── heading fill ───────────────────────────────────────────────────── */

/*
 * A gradient poured through the letters. The text stays real text -- it is
 * selectable, searchable and readable by a screen reader -- because the fill
 * is the element's own background clipped to its glyphs, not a picture of
 * words.
 */
.eexp-panel__title--gradient {
	/*
	 * The first stop defaults to currentColor, so the gradient runs out of
	 * whatever colour the heading already is -- navy on the light panel, white
	 * on the ink one -- instead of starting white and vanishing on the offwhite.
	 *
	 * Only text-fill-color is made transparent, never `color`. Blanking colour
	 * would take currentColor with it and the gradient would have nothing to
	 * start from.
	 */
	background-image: linear-gradient(
		var(--eexp-fill-angle, 95deg),
		var(--eexp-fill-from, currentColor),
		var(--eexp-fill-to, var(--eexp-green-light))
	);
	-webkit-background-clip: text;
	background-clip: text;
	-webkit-text-fill-color: transparent;
}

/*
 * Or the fill arrives as you reach it, a word at a time. The spans are
 * authored server side, so the heading is whole before any script runs and a
 * trademark sign keeps its own element.
 */
.eexp-panel__title--reveal span {
	display: inline-block;
	color: var(--eexp-fill-dim, rgba(120, 140, 160, 0.32));
	transition: color 620ms cubic-bezier(0.22, 1, 0.36, 1);
}

.eexp-panel__title--reveal.eexp-in span {
	color: inherit;
}

/* Never leave a heading unreadable because a script did not run. */
.eexp-no-js .eexp-panel__title--reveal span,
.elementor-editor-active .eexp-panel__title--reveal span {
	color: inherit;
}

.eexp-tm {
	font-style: normal;
	font-size: 0.5em;
	vertical-align: 0.9em;
	letter-spacing: 0;
}

.eexp-panel--light .eexp-panel__title {
	color: var(--eexp-navy);
}

.eexp-label {
	font-size: 13px;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
}

.eexp-panel__body,
.eexp-lold,
.eexp-lnew {
	font-size: 15px;
	line-height: 1.6;
}

.eexp-step__num {
	font-size: 28px;
	font-weight: 400;
	letter-spacing: 0.02em;
	color: var(--eexp-green);
}

.eexp-panel--ink .eexp-step__num {
	color: var(--eexp-green-light);
}

.eexp-panel--light .eexp-step {
	color: var(--eexp-navy-70);
}

.eexp-flow__caption,
.eexp-specs b,
.eexp-lhead span {
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
}

.eexp-lhead span,
.eexp-loads__label {
	font-weight: 700;
	letter-spacing: 0.08em;
}

.eexp-specs b {
	color: #fff;
}

.eexp-specs li span {
	font-size: 14px;
}

.eexp-loads__label {
	font-size: 12px;
	text-transform: uppercase;
	color: var(--eexp-navy-70);
}

.eexp-loads li {
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
}

.eexp-lnew {
	font-weight: 600;
	color: #fff;
}

/* ── the slab ───────────────────────────────────────────────────────── */

.eexp-slab {
	display: grid;
	/* 1fr, not auto: an auto track sizes to its contents and leaves the rest
	   of the width empty instead of filling the slab. */
	grid-template-columns: var(--eexp-split) var(--eexp-bar) 1fr;
	border: 1px solid var(--eexp-white-11);
	border-radius: var(--eexp-radius);
	overflow: hidden;
	background: var(--eexp-ink);
	box-shadow: 0 24px 70px rgba(0, 0, 0, 0.45);
}

.eexp-bar {
	background: var(--eexp-green);
}

.eexp-panel {
	padding: var(--eexp-pad-y) var(--eexp-pad-x);
	display: flex;
	flex-direction: column;
	min-height: 0;
	/*
	 * min-width, not just min-height: a grid item's automatic minimum size is
	 * its content, so without this a long spec value pushes the track wider
	 * than its share and the slab's overflow: hidden cuts the panel off.
	 */
	min-width: 0;
	position: relative;
}

.eexp-panel--light {
	background: var(--eexp-offwhite);
	color: var(--eexp-navy-80);
}

.eexp-panel--ink {
	background-color: var(--eexp-ink);
	background-image: radial-gradient(120% 90% at 85% 0%, #14382a 0%, var(--eexp-ink) 62%);
	background-position: center;
	background-size: cover;
	background-repeat: no-repeat;
	color: var(--eexp-white-70);
}

/*
 * The darkening veil for a background image. It sits under the content and
 * over the picture, so white text and the green accents keep their contrast
 * whatever gets uploaded. At the default 0 it costs nothing.
 */
.eexp-panel--ink::before {
	content: "";
	position: absolute;
	inset: 0;
	background: #000;
	opacity: var(--eexp-dim);
	pointer-events: none;
}

.eexp-panel > * {
	position: relative;
	z-index: 1;
}

.eexp-step {
	display: flex;
	align-items: baseline;
	gap: 14px;
	margin: 0;
}

/* An empty number closes its own gap rather than leaving one behind. */
.eexp-step--bare {
	gap: 0;
}

.eexp-step__num {
	line-height: 1;
	flex: 0 0 auto;
}

.eexp-panel__title {
	margin: var(--eexp-gap-title) 0 0;
	max-width: var(--eexp-title-measure);
}

.eexp-panel__body {
	margin-top: var(--eexp-gap-body);
	max-width: var(--eexp-body-measure);
}

.eexp-stage {
	padding-top: var(--eexp-gap-stage);
	padding-bottom: var(--eexp-gap-footer);
}

.eexp-stage__img {
	width: 100%;
	height: auto;
	max-width: var(--eexp-img-max);
	margin-inline: auto;
}

/* ── the flow plate ─────────────────────────────────────────────────── */

.eexp-flow {
	position: relative;
	margin: 0;
	border: 1px solid var(--eexp-white-11);
	border-radius: 20px;
	padding: 20px 18px;
	overflow: hidden;
	background: #04090d;
	container-type: inline-size;
}

/*
 * The artwork is drawn on black. Screened over the plate, the black falls
 * away and only the coils and arrows remain. Elementor has no control for a
 * blend mode, so it is fixed here.
 */
.eexp-flow__img {
	width: 100%;
	height: auto;
	mix-blend-mode: screen;
}

/*
 * No plate: artwork that brings a background of its own, so there is nothing
 * to knock out and nothing to knock it out of.
 */
.eexp-flow--bare {
	border: 0;
	padding: 0;
	background: none;
}

.eexp-flow--bare .eexp-flow__img {
	mix-blend-mode: normal;
	border-radius: 20px;
}

/*
 * The motes are the argument in miniature: particles arriving with the air and
 * leaving with it, never settling on anything. So they are not five identical
 * dots on a straight line.
 *
 * Each one has its own size, speed, brightness and wander, which the server
 * writes as custom properties, and each carries a thin trail behind it so the
 * direction of travel reads even when a single mote is caught mid-frame.
 * Depth comes from size and brightness together -- a small dim one looks far
 * off, a large bright one close -- rather than from a blur, which would cost
 * a filter pass per mote for the same impression.
 *
 * The travel is measured in container units, so a mote crosses the plate
 * whatever width the plate happens to be. The old fixed 560px either stopped
 * short or overshot on every screen but one.
 */
.eexp-mote {
	--eexp-mote-size: 5px;
	--eexp-mote-wander: 9px;
	--eexp-mote-peak: 0.75;
	--eexp-mote-dur: 8s;

	position: absolute;
	left: calc(var(--eexp-mote-size) * -2);
	width: calc(var(--eexp-mote-size) * var(--eexp-mote-scale, 1));
	height: calc(var(--eexp-mote-size) * var(--eexp-mote-scale, 1));
	border-radius: 50%;
	background: radial-gradient(
		circle at 35% 35%,
		#fff 0%,
		var(--eexp-mote-colour, rgba(255, 255, 255, 0.92)) 45%,
		rgba(255, 255, 255, 0) 72%
	);
	opacity: 0;
	pointer-events: none;
	animation-name: eexp-drift;
	animation-timing-function: linear;
	animation-iteration-count: infinite;
	animation-duration: calc(var(--eexp-mote-dur) / var(--eexp-mote-speed, 1));
}

/* The trail. Short, soft, and behind the head rather than through it. */
.eexp-mote::before {
	content: "";
	position: absolute;
	top: 50%;
	right: 45%;
	height: 42%;
	width: calc(var(--eexp-mote-size) * var(--eexp-mote-scale, 1) * 9);
	transform: translateY(-50%);
	border-radius: 2000px;
	background: linear-gradient(
		270deg,
		var(--eexp-mote-colour, rgba(255, 255, 255, 0.9)),
		rgba(255, 255, 255, 0)
	);
	opacity: 0.7;
}

.eexp-flow--no-trails .eexp-mote::before {
	display: none;
}

/*
 * The wander is what stops it reading as a conveyor belt. Each mote rises and
 * falls on its own amplitude as it crosses, and the amounts are deliberately
 * uneven so no two ever line up.
 */
@keyframes eexp-drift {
	0% {
		translate: 0 0;
		opacity: 0;
	}

	7% {
		opacity: var(--eexp-mote-peak);
	}

	22% {
		translate: calc((100cqw + var(--eexp-mote-size) * 4) * 0.22)
			calc(var(--eexp-mote-wander) * -1);
	}

	46% {
		translate: calc((100cqw + var(--eexp-mote-size) * 4) * 0.46)
			calc(var(--eexp-mote-wander) * 0.85);
	}

	71% {
		translate: calc((100cqw + var(--eexp-mote-size) * 4) * 0.71)
			calc(var(--eexp-mote-wander) * -0.55);
	}

	90% {
		opacity: var(--eexp-mote-peak);
	}

	100% {
		translate: calc(100cqw + var(--eexp-mote-size) * 4) 0;
		opacity: 0;
	}
}

.eexp-flow__caption {
	margin-top: var(--eexp-gap-caption, 14px);
	color: var(--eexp-caption-colour, rgba(255, 255, 255, 0.72));
	display: flex;
	justify-content: space-between;
	gap: 16px;
}

/*
 * No font-style here. It used to force normal, so an italic set in the panel
 * applied to the left half of the caption and not the right.
 */
.eexp-flow__caption i {
	color: var(--eexp-caption-accent, var(--eexp-green-light));
}

/* ── panel footers, bottom-aligned ──────────────────────────────────── */

.eexp-specs {
	list-style: none;
	margin: auto 0 0;
	padding: 0;
	display: grid;
	gap: 1px;
	background: var(--eexp-white-11);
	border: 1px solid var(--eexp-white-11);
	border-radius: var(--eexp-spec-radius);
	overflow: hidden;
}

.eexp-specs li {
	background: var(--eexp-ink);
	padding: var(--eexp-spec-pad-y) var(--eexp-spec-pad-x);
	display: flex;
	justify-content: space-between;
	align-items: center;
	gap: 18px;
}

.eexp-loads {
	margin: auto 0 0;
	/*
	 * No padding-top. A panel with no picture has no stage to carry the gap,
	 * and the auto margin above already separates the footer from whatever is
	 * over it.
	 */
}

.eexp-loads__label {
	margin-bottom: var(--eexp-gap-label);
}

.eexp-loads ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	gap: var(--eexp-pill-gap);
}

/* ── the pills ──────────────────────────────────────────────────────── */

/*
 * Not a plain outlined chip. Each one carries a lit dot, sits on a soft
 * gradient rather than flat white, and lifts under the pointer -- so a row of
 * them reads as a set of things the unit handles, not as tags.
 */
.eexp-loads li {
	position: relative;
	display: inline-flex;
	align-items: center;
	gap: 9px;
	border: 1px solid var(--eexp-green-30);
	background: linear-gradient(180deg, #fff, #eef3f0);
	color: var(--eexp-navy);
	border-radius: var(--eexp-pill-radius);
	padding: var(--eexp-pill-pad-y) var(--eexp-pill-pad-x);
	box-shadow: 0 1px 2px rgba(15, 57, 97, 0.06), inset 0 1px 0 #fff;
	transition: transform 220ms cubic-bezier(0.22, 1, 0.36, 1),
		border-color 220ms cubic-bezier(0.22, 1, 0.36, 1),
		box-shadow 220ms cubic-bezier(0.22, 1, 0.36, 1);
}

.eexp-loads li::before {
	content: "";
	flex: 0 0 auto;
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background: var(--eexp-green);
	box-shadow: 0 0 0 3px var(--eexp-green-08, rgba(7, 134, 79, 0.12));
	transition: box-shadow 220ms cubic-bezier(0.22, 1, 0.36, 1);
}

.eexp-loads li:hover {
	transform: translateY(-2px);
	border-color: var(--eexp-green);
	box-shadow: 0 6px 18px rgba(7, 134, 79, 0.16), inset 0 1px 0 #fff;
}

.eexp-loads li:hover::before {
	box-shadow: 0 0 0 5px rgba(7, 134, 79, 0.16);
}

/* Without the dot, for a plainer row. */
.eexp-loads--plain li::before {
	display: none;
}

.eexp-loads--plain li {
	gap: 0;
}

/* Filled, for when the row should carry more weight than the body under it. */
.eexp-loads--solid li {
	background: linear-gradient(180deg, #0a9a5c, #07864f);
	border-color: transparent;
	color: #fff;
	box-shadow: 0 2px 10px rgba(7, 134, 79, 0.28);
}

.eexp-loads--solid li::before {
	background: #fff;
	box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.22);
}

.eexp-loads--solid li:hover {
	box-shadow: 0 8px 22px rgba(7, 134, 79, 0.34);
}

/* Glass, for a pill row that sits over a picture. */
.eexp-loads--glass li {
	background: rgba(255, 255, 255, 0.55);
	backdrop-filter: blur(10px);
	-webkit-backdrop-filter: blur(10px);
	border-color: rgba(255, 255, 255, 0.7);
	box-shadow: 0 2px 14px rgba(15, 57, 97, 0.1);
}

/* ── the ledger ─────────────────────────────────────────────────────── */

.eexp-ledger {
	border: 1px solid var(--eexp-white-11);
	border-radius: 25px;
	overflow: hidden;
	background: rgba(255, 255, 255, 0.02);
}

.eexp-lrow {
	display: grid;
	grid-template-columns: 1.1fr 1fr 1.25fr;
	align-items: center;
	border-top: 1px dashed rgba(255, 255, 255, 0.14);
}

.eexp-lrow:first-child {
	border-top: 0;
}

.eexp-lrow > * {
	padding: 20px 28px;
}

.eexp-lhead {
	background: rgba(255, 255, 255, 0.04);
	border-top: 0;
}

.eexp-lhead .eexp-win {
	color: var(--eexp-green-light);
}

.eexp-lold {
	color: rgba(255, 255, 255, 0.54);
}

.eexp-lnew {
	background: linear-gradient(90deg, rgba(77, 207, 141, 0.1), transparent 72%);
	display: flex;
	align-items: flex-start;
	gap: 12px;
}

/* A comparison with no winner keeps the rows and drops the claim. */
.eexp-lnew--plain {
	background: none;
	font-weight: inherit;
	color: inherit;
}

.eexp-lnew--plain::before {
	display: none;
}

.eexp-lnew::before {
	content: "";
	flex: 0 0 auto;
	width: 9px;
	height: 9px;
	border-radius: 50%;
	background: var(--eexp-green-light);
	margin-top: 8px;
}

/* ── reveal ─────────────────────────────────────────────────────────── */

.eexp-rise {
	opacity: 0;
	transform: translateY(22px);
	transition: opacity 700ms cubic-bezier(0.22, 1, 0.36, 1),
		transform 700ms cubic-bezier(0.22, 1, 0.36, 1);
}

.eexp-rise.eexp-in {
	opacity: 1;
	transform: none;
}

/*
 * Without the script -- and inside the editor, where the observer is set up
 * again on every redraw -- everything must simply be visible.
 */
.eexp-no-js .eexp-rise,
.elementor-editor-active .eexp-rise {
	opacity: 1;
	transform: none;
}

/* ── responsive ─────────────────────────────────────────────────────── */

/*
 * Stacked: one column, the bar lying across it as a rule between the two
 * panels rather than standing between them.
 *
 * Twice, because the two questions are different ones. The window is the
 * breakpoint a client expects -- it lines up with Elementor's own -- and the
 * container is the case a media query cannot see, a slab in a half-width
 * column that is narrow at any viewport. Whichever is true first wins, and
 * the threshold is set below a boxed 1140px container so a slab that fills
 * the page stays in two columns on the desktop.
 */
@media (max-width: 1200px) {

	.eexp-slab {
		grid-template-columns: 1fr;
		grid-template-rows: auto var(--eexp-bar) auto;
	}

}

@container (max-width: 1040px) {

	.eexp-slab {
		grid-template-columns: 1fr;
		grid-template-rows: auto var(--eexp-bar) auto;
	}

}

@media (max-width: 767px) {
	.eexp {
		--eexp-radius: 28px;
	}

	/* Two halves pushed apart do not fit one phone line. Let them sit. */
	.eexp-flow__caption {
		flex-wrap: wrap;
		gap: 6px 16px;
	}

	.eexp-stage__img {
		max-width: none;
		width: calc(100% + 24px);
		margin-left: -12px;
	}

	.eexp-lrow {
		grid-template-columns: 1fr;
		border-top: 0;
	}

	.eexp-lrow > * {
		padding: 14px 20px;
	}

	.eexp-lrow + .eexp-lrow {
		border-top: 1px solid var(--eexp-white-11);
	}

	.eexp-lhead {
		display: none;
	}

	.eexp-lkey {
		padding-bottom: 2px;
	}

	.eexp-lold {
		padding-top: 4px;
	}

	/*
	 * The header row is hidden here, so the middle value says what it is.
	 * Small, uppercase and set off by a middot, or it reads as one run-on
	 * sentence with the value after it.
	 */
	.eexp-lold::before {
		content: attr(data-eexp-label) " · ";
		font-size: 11px;
		font-weight: 700;
		letter-spacing: 0.06em;
		text-transform: uppercase;
		opacity: 0.7;
	}

	.eexp-lnew {
		background: none;
	}
}

@media (prefers-reduced-motion: reduce) {
	.eexp-loads li:hover {
		transform: none;
	}

	.eexp-panel__title--reveal span {
		color: inherit;
	}

.eexp *,
.eexp *::before,
.eexp *::after {
		animation-duration: 0.01ms !important;
		transition-duration: 0.01ms !important;
	}

	.eexp-mote {
		display: none;
	}

	.eexp-rise {
		opacity: 1;
		transform: none;
	}
}
