/*** Module: Steps ***/

/* No band padding — the module is transparent, so its vertical gap comes from the
   module_spacing margin. Padding-block belongs to modules that paint a background. */
.module.steps {
	overflow-x: clip;
}

.module.steps .grid {
	gap: 0;
}

.module.steps .headline {
	grid-column: 2 / span 10;
	text-align: center;
}

/* The header carries the gap down to the list — on the sub, or the heading when there's no sub. */
.module.steps .headline:not(:has(+ .sub)) {
	margin-bottom: var(--module-spacing-small);
}

.module.steps .sub {
	grid-column: 3 / span 8;
	margin: var(--text-spacing-small) 0 var(--module-spacing-xlarge);
	text-align: center;
}

/* No media column, so the list sits directly under the header — it needs far less
   gap than the full-bleed media layout. */
.module.steps:not(:has(.media)) .sub {
	margin-bottom: var(--module-spacing-medium);
}

/* JS measures --steps-spine-top/-height; ::after's scaleY tracks --steps-progress. */
.module.steps .list {
	display: grid;
	gap: var(--module-spacing-medium);
	grid-column: 1 / -1;
	grid-template-columns: 1fr;
	isolation: isolate;
	list-style: none;
	margin: 0;
	padding: 0;
	position: relative;
}

/* With no media on any step the copy has nothing beside it, so narrow + centre
   the list instead of letting it run the full grid width. */
.module.steps:not(:has(.media)) .list {
	grid-column: 2 / -2;
}

.module.steps .list::before,
.module.steps .list::after {
	content: "";
	height: var(--steps-spine-height, 0);
	left: 20px;
	position: absolute;
	top: var(--steps-spine-top, 0);
	width: 2px;
	z-index: -1;
}

.module.steps .list::before {
	background: var(--track-gray);
}

.module.steps .list::after {
	background: var(--orange);
	transform: scaleY(var(--steps-progress, 0));
	transform-origin: top;
}

.module.steps .step-card {
	align-items: flex-start;
	display: grid;
	gap: 0 var(--gap);
	grid-template-columns: var(--grid);
	isolation: isolate;
	position: relative;
}

/* Left padding clears the 40px number badge, plus an extra step of separation
   between the badge and the copy. */
.module.steps .content {
	grid-column: 1 / span 6;
	padding: var(--module-spacing-small) 0 var(--module-spacing-small) calc(40px + var(--text-spacing-small) * 2);
	position: relative;
}

.module.steps:not(:has(.media)) .step-card .content {
	grid-column: 1 / -1;
}

.module.steps .content > * {
	margin: 0;
}

.module.steps .content > .blurb {
	margin-top: var(--text-spacing-xsmall);
}

/* Outline via box-shadow (not outline) so the active-step pulse can stack on top in the same declaration; pulse-then-white order in keyframes paints the pulse over the static ring. */
.module.steps .step-card-number {
	align-items: center;
	aspect-ratio: 1;
	background: var(--lavender);
	border-radius: 50%;
	box-shadow: 0 0 0 16px var(--off-white);
	color: var(--black);
	display: flex;
	justify-content: center;
	left: 0;
	position: absolute;
	top: calc(var(--text-spacing-xsmall) + var(--module-spacing-small));
	transition: background 0.4s ease;
	width: 40px;
}

.module.steps .step-card.is-completed .step-card-number,
.module.steps .step-card.is-active .step-card-number {
	background: var(--orange);
}

/* Both ends of the pulse cycle are 0-opacity so it loops seamlessly; off-white shadow stays in every keyframe to restore the static ring. */
.module.steps .step-card.is-active .step-card-number {
	animation: steps-number-pulse 2.4s ease-in-out infinite;
}

@keyframes steps-number-pulse {
	0% {
		box-shadow:
			0 0 0 16px color-mix(in srgb, var(--orange) 0%, transparent),
			0 0 0 16px var(--off-white);
	}
	35% {
		box-shadow:
			0 0 0 22px color-mix(in srgb, var(--orange) 35%, transparent),
			0 0 0 16px var(--off-white);
	}
	100% {
		box-shadow:
			0 0 0 34px color-mix(in srgb, var(--orange) 0%, transparent),
			0 0 0 16px var(--off-white);
	}
}

@media (prefers-reduced-motion: reduce) {

	.module.steps .step-card-number {
		transition: none;
	}

	.module.steps .step-card.is-active .step-card-number {
		animation: none;
		box-shadow:
			0 0 0 28px color-mix(in srgb, var(--orange) 16%, transparent),
			0 0 0 16px var(--off-white);
	}

}

/* Media bleeds past the grid to the viewport edge. */
.module.steps .media {
	aspect-ratio: 540 / 612;
	background: var(--teal-gradient);
	grid-column: 7 / span 6;
	margin-right: var(--container-breakout);
	overflow: hidden;
}

.module.steps .media :is(img, video) {
	display: block;
	height: 100%;
	object-fit: cover;
	width: 100%;
}

/* Transparent UI image (screenshot/logo): center it within the frame at its own
   size instead of cover-cropping. The base image is absolutely positioned to fill
   the frame (global .media > img), so recenter it with top/left + translate rather
   than flex, and cap it with max-width/height for breathing room on the teal field. */
.module.steps .media.ui-image :is(img, video) {
	height: auto;
	left: 50%;
	max-height: 80%;
	max-width: 80%;
	object-fit: contain;
	top: 50%;
	translate: -50% -50%;
	width: auto;
}

/* Sticky media stage (desktop) — the timeline scrolls in the left 6 columns while
   one pinned frame stays in the last 5, crossfading to the active step's media. The
   inline .media in each card is the ≤950px fallback (hidden here). */
.module.steps.has-media .list {
	grid-column: 1 / span 6;
}

/* Stack the content over the (invisible) inline media in one cell: the media
   reserves its 540/612 height to space the steps out, while the content (and its
   top-anchored badge) sit at the top — the sticky stage shows the image itself. */
.module.steps.has-media .step-card {
	display: grid;
	grid-template-columns: 1fr;
}

.module.steps.has-media .content {
	align-self: start;
	grid-area: 1 / 1;
}

.module.steps.has-media .step-card .media.inline {
	align-self: start;
	grid-area: 1 / 1;
	margin-right: 0;
	opacity: 0;
	pointer-events: none;
}

.module.steps.has-media .media-stage {
	align-self: start;
	aspect-ratio: 540 / 612;
	background: var(--teal-gradient);
	display: grid;
	grid-column: 8 / span 5;
	margin-right: var(--container-breakout);
	overflow: hidden;
	position: sticky;
	top: calc(var(--header-height) + var(--module-spacing-medium));
}

/* Frames stack in one cell; the active one fades in over the teal stage. */
.module.steps .media-stage .media {
	aspect-ratio: auto;
	background: none;
	grid-area: 1 / 1;
	height: 100%;
	margin: 0;
	opacity: 0;
	width: 100%;
}

.module.steps .media-stage .media.is-active {
	opacity: 1;
}

/* Progressive reveal — each step's media fades in once its card reaches the
   active position (and stays visible while completed). Reduced-motion users
   see all media immediately. */
@media (prefers-reduced-motion: no-preference) {

	.module.steps .media {
		opacity: 0;
		transition: opacity 0.6s ease;
	}

	.module.steps .step-card.is-active .media,
	.module.steps .step-card.is-completed .media {
		opacity: 1;
	}

}

/***************************************************************************************************************************************************************************************/
/* MQ MAX-WIDTH 1400 - Smaller Desktop Sizes */
/***************************************************************************************************************************************************************************************/

@media only screen and (max-width: calc(1400rem / 16)) {

	.module.steps .headline:not(:has(+ .sub)),
	.module.steps .sub {
		margin-bottom: var(--module-spacing-medium);
	}

}

/***************************************************************************************************************************************************************************************/
/* MQ MAX-WIDTH 950 - Tablet Sizes */
/***************************************************************************************************************************************************************************************/

@media only screen and (max-width: calc(950rem / 16)) {

	/* :not(:has(.media)) echoed — the no-media rule above is (0,4,0) and would
	   otherwise freeze the gap here. */
	.module.steps .headline:not(:has(+ .sub)),
	.module.steps .sub,
	.module.steps:not(:has(.media)) .sub {
		margin-bottom: var(--text-spacing-large);
	}

	.module.steps .headline,
	.module.steps .sub,
	.module.steps:not(:has(.media)) .list,
	.module.steps.has-media .list {
		grid-column: 1 / -1;
	}

	.module.steps .step-card,
	.module.steps.has-media .step-card {
		display: block;
	}

	.module.steps .step-card-number {
		top: 44px;
	}

	.module.steps .content {
		padding-block: var(--text-spacing-large);
	}

	/* Drop the sticky stage; each step shows its media inline (visible) again. */
	.module.steps .media-stage {
		display: none !important;
	}

	.module.steps.has-media .step-card .media.inline {
		opacity: 1;
		pointer-events: auto;
	}

	.module.steps .media {
		margin: 0 0 0 calc(40px + var(--text-spacing-small));
	}

}

/***************************************************************************************************************************************************************************************/
/* MQ MAX-WIDTH 650 - Mobile Sizes */
/***************************************************************************************************************************************************************************************/

@media only screen and (max-width: calc(650rem / 16)) {

	.module.steps .headline:not(:has(+ .sub)),
	.module.steps .sub,
	.module.steps:not(:has(.media)) .sub {
		margin-bottom: var(--text-spacing-small);
	}

	.module.steps .list {
		gap: var(--text-spacing-small);
	}

	/* Tighter badge clearance — the desktop 40px + 2×24px crowds the copy at this width. */
	.module.steps .content {
		padding-left: 64px;
	}

}
