/**
 * RSI Toolkit — Milestones Timeline widget ("أبرز محطات الإنجاز").
 *
 * Baked to the 2026 Figma node 10543:593. Each entry is a year marker followed
 * by a tall photo card whose copy sits over a gradient scrim at the bottom
 * inner edge.
 *
 * ── Two things worth knowing before editing ──────────────────────────────────
 *
 * 1. EVERYTHING IS LOGICAL, NOT LEFT/RIGHT. The Figma is Arabic, and the code
 *    Figma hands back is LTR-normalised ("items-end", "pr-[32px]") — so taken
 *    literally it puts the copy on the WRONG edge in RTL. Every inline axis
 *    value here is therefore logical (`padding-inline-start`, `text-align:
 *    start`, `flex-start`), which lands the copy on the reading edge in Arabic
 *    AND mirrors it for English with no work. Consequence: rtl.css needs no
 *    entry for this widget, so the "every LTR breakpoint must be mirrored in
 *    rtl.css" trap (see the handoff §7) cannot apply here. Keep it that way —
 *    do not introduce a bare `left`/`right` or a `[dir=rtl]` override.
 *
 * 2. THE SPINE IS THE MARKERS, NOT A SEPARATE ELEMENT. On desktop the marker
 *    column stretches to the item's full height and its two pseudo-rules take
 *    `flex: 1` above and below the year, so consecutive items' rules meet at
 *    the item boundary and read as one continuous line. That is why the list
 *    row-gap is 0 on desktop and the card carries the vertical breathing room
 *    instead: add a row-gap back and the spine breaks into dashes.
 */

.rsi-ms {
	--rsi-ms-card-h: 650px;
	--rsi-ms-card-w: 620px;
	--rsi-ms-radius: 8px;
	--rsi-ms-scrim: 42;
	--rsi-ms-year: #83939c;
	--rsi-ms-year-active: #bf0031;
	--rsi-ms-line: #83939c;
	--rsi-ms-text: #ffffff;
	--rsi-ms-body-w: 327px;

	/* Entrance animation. --rsi-ms-rtl is the inline-axis sign: JS flips it to
	   -1 on Arabic so each card still slides in from ITS OWN side of the spine.
	   It defaults to 1 here so the calc() is never invalid before JS runs. */
	--rsi-ms-rtl: 1;
	--rsi-ms-slide: 64px;
	--rsi-ms-rise: 32px;

	/* Opacity an entering card starts from. Kept high on purpose: the cards are
	   photographs and this is a 14,000px page, so a deep fade left them reading
	   as washed-out placeholders for most of the scroll.
	   This file is mobile-first, so THIS is the mobile value and it is lighter
	   than desktop's: on mobile one card fills the screen, so a dim card is the
	   whole view rather than one element among several, and the same fade depth
	   reads as much heavier. Desktop's value is in the min-width:768px block. */
	--rsi-ms-fade: 0.88;

	/* No inline padding on mobile ON PURPOSE. Woodmart's
	   main.wd-content-layout already supplies a 15px gutter, and adding our own
	   16px on top of it left the card at 84% of the viewport where the Figma
	   has it at 92% (370 of 402) — visibly narrower than designed. Relying on
	   the theme gutter reproduces the design proportion. If this widget is ever
	   used somewhere with no ancestor gutter, the cards will touch the screen
	   edge and this needs a padding value back. */
	padding: 24px 0;
}

/* -------------------------------- list --------------------------------- */
.rsi-ms__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 24px;
}

.rsi-ms__item {
	list-style: none;
	margin: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	width: 100%;

	/* ⚠️ BOTH DEFAULTS ARE THE SETTLED STATE, ON PURPOSE. --rsi-ms-p is the
	   entrance progress (0 = off-stage, 1 = in place) and it defaults to 1, so a
	   card with no JS — script deferred, blocked, still parsing — paints fully
	   visible and in position rather than blank. JS only ever lowers it for
	   cards that are still off-screen, where the change can't be seen. Never
	   flip this default to 0 "so the animation always plays from the start":
	   that trades a working page for a first frame full of invisible cards. */
	--rsi-ms-p: 1;
	--rsi-ms-dir: 0; /* 0 = rise only; the spine layout sets a side per item. */

	/* Connector-rule fill, above (l1) and below (l2) the year. Same reasoning as
	   --rsi-ms-p: default to 1 (fully drawn) so the timeline reads as a complete
	   line with no JS, and let the script scale it back only where it hasn't
	   been reached yet. */
	--rsi-ms-l1: 1;
	--rsi-ms-l2: 1;
}

.rsi-ms__item::before,
.rsi-ms__item::marker {
	content: none;
}

/* ------------------------------- marker -------------------------------- */
.rsi-ms__marker {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 20px;
	width: 160px;
	flex: 0 0 auto;
}

/* The two connector rules. ::before is the run above the year, ::after the
   run down into the card — so the first entry drops its ::before, matching
   the design (the timeline begins at the newest year). */
.rsi-ms__marker::before,
.rsi-ms__marker::after {
	content: "";
	display: block;
	width: 3px;
	height: 80px;
	flex: 0 0 auto;
	background: var(--rsi-ms-line);
}

.rsi-ms__item--first .rsi-ms__marker::before {
	display: none;
}

.rsi-ms__year {
	font-family: 'Alexandria', sans-serif;
	font-weight: 400;
	font-size: 60px;
	line-height: 72px;
	letter-spacing: -0.5px;
	text-align: center;
	color: var(--rsi-ms-year);
	transition: color .45s ease;
}

/* The year of whichever card is on screen. Item 1 ships with is-active from
   the render so the first painted frame already matches the design — the JS
   only ever moves it. */
.rsi-ms__item.is-active .rsi-ms__year {
	color: var(--rsi-ms-year-active);
}

/* -------------------------------- card --------------------------------- */
.rsi-ms__card {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	justify-content: flex-end;
	width: 100%;
	height: var(--rsi-ms-card-h);
	padding-block-end: 48px;
	padding-inline-start: 32px;
	border-radius: var(--rsi-ms-radius);
	overflow: hidden;
}

/* ------------------------- scroll-linked entrance ----------------------- */
/* Driven entirely by scroll POSITION rather than enter/leave events, which is
   what makes it reversible for free: scrolling back up re-runs the same
   interpolation backwards, and a card parked mid-transition stays exactly where
   its position says it should be. There is no CSS transition on the transform
   for the same reason — the scroll position IS the timeline, and a transition
   on top of it would lag behind the finger and fight every direction change. */
.rsi-ms-anim-on .rsi-ms__card {
	opacity: calc(var(--rsi-ms-fade) + (1 - var(--rsi-ms-fade)) * var(--rsi-ms-p));
	transform: translate(
		calc(var(--rsi-ms-dir) * (1 - var(--rsi-ms-p)) * var(--rsi-ms-slide)),
		calc((1 - var(--rsi-ms-p)) * var(--rsi-ms-rise))
	);
}

/* The rules draw DOWNWARD — scaled from their top edge, so the line appears to
   be pulled down the page as you scroll. Scaling rather than animating `height`
   is what keeps the layout still: the pseudo-element's box keeps its full size,
   so the year and card never shift while the line grows into place. */
.rsi-ms-anim-on .rsi-ms__marker::before {
	transform: scaleY(var(--rsi-ms-l1));
	transform-origin: top center;
}

.rsi-ms-anim-on .rsi-ms__marker::after {
	transform: scaleY(var(--rsi-ms-l2));
	transform-origin: top center;
}

.rsi-ms__media {
	position: absolute;
	inset: 0;
	border-radius: inherit;
	overflow: hidden;
	pointer-events: none;
}

/* ⚠️ Two classes, deliberately. Elementor's frontend.min.css ships
   `.elementor img { height: auto }` — specificity 0,1,1, which BEATS a single
   class (0,1,0). A plain `.rsi-ms__img { height: 100% }` loses, the image falls
   back to its intrinsic ratio, and the card shows a photo across its top third
   with bare scrim below. `.rsi-ms__media .rsi-ms__img` is 0,2,0 and wins
   without needing !important (which would take the height away from the
   Elementor Style tab). Any image rule in this plugin needs to clear 0,1,1. */
.rsi-ms__media .rsi-ms__img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
}

/* Transparent at the top, darkening to the scrim value at the bottom, so the
   copy reads without flattening the photograph. */
.rsi-ms__media::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(
		to bottom,
		rgba(0, 0, 0, 0) 0%,
		rgba(0, 0, 0, calc(var(--rsi-ms-scrim) / 100)) 100%
	);
}

.rsi-ms__body {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 18px;
	width: 100%;
	max-width: var(--rsi-ms-body-w);
	text-align: start;
	color: var(--rsi-ms-text);
	overflow-wrap: break-word;
}

.rsi-ms__title,
.rsi-ms__loc,
.rsi-ms__text {
	margin: 0;
	color: inherit;
	font-family: 'Alexandria', sans-serif;
}

.rsi-ms__title {
	font-weight: 700;
	font-size: 20px;
	line-height: 24px;
	letter-spacing: .15px;
}

.rsi-ms__loc {
	font-weight: 700;
	font-size: 16px;
	line-height: 24px;
	letter-spacing: .15px;
}

.rsi-ms__text {
	font-weight: 400;
	font-size: 16px;
	line-height: 27px;
	letter-spacing: .5px;
}

/* ============================ DESKTOP SPINE ============================= */
/* The Figma has no desktop frame. A single 370px column would leave the
   1350px container almost empty, so the timeline opens into a centre spine
   with the cards alternating sides. */
@media (min-width: 768px) {

	.rsi-ms {
		--rsi-ms-card-h: 560px;
		--rsi-ms-body-w: 460px;
		--rsi-ms-fade: 0.72; /* Deeper than mobile — see the note on the base value. */

		padding: 40px 24px;
	}

	/* Row-gap 0 is load-bearing — see note 2 at the top of this file. */
	.rsi-ms__list {
		gap: 0;
		width: 100%;
		max-width: 1350px;
		margin-inline: auto;
	}

	.rsi-ms-layout--spine .rsi-ms__item {
		display: grid;
		grid-template-columns: 1fr auto 1fr;
		align-items: center;
		column-gap: 40px;
	}

	.rsi-ms-layout--spine .rsi-ms__marker {
		grid-column: 2;
		grid-row: 1;
		align-self: stretch;
		gap: 24px;
	}

	/* Fill the space above and below the year so the rules of adjacent items
	   meet and read as one line. */
	.rsi-ms-layout--spine .rsi-ms__marker::before,
	.rsi-ms-layout--spine .rsi-ms__marker::after {
		height: auto;
		flex: 1 1 auto;
		min-height: 40px;
	}

	/* padding-inline-end matters: without it the copy runs flush to the card's
	   far edge, because the body box is already card-width-minus-the-start-inset
	   and its max-width never bites. */
	.rsi-ms-layout--spine .rsi-ms__card {
		grid-row: 1;
		width: 100%;
		max-width: var(--rsi-ms-card-w);
		margin-block: 40px;
		padding-block-end: 48px;
		padding-inline-start: 40px;
		padding-inline-end: 40px;
	}

	/* Odd entries take the inline-start half, even ones the inline-end half —
	   logical, so Arabic starts on the right and English on the left. */
	.rsi-ms-layout--spine .rsi-ms__item--odd .rsi-ms__card {
		grid-column: 1;
		justify-self: end;
	}

	.rsi-ms-layout--spine .rsi-ms__item--even .rsi-ms__card {
		grid-column: 3;
		justify-self: start;
	}

	/* Slide direction = the side the card lives on, so it travels outward-in
	   rather than across the spine. Multiplied by --rsi-ms-rtl (JS: 1 for LTR,
	   -1 for RTL) because `translate` has no logical equivalent — there is no
	   translate-inline, so the sign has to be worked out rather than inherited.
	   Mobile deliberately keeps --rsi-ms-dir: 0 and rises only: there is one
	   column and no side to come from, and horizontal travel on a 390px screen
	   would push the card past the viewport edge. */
	.rsi-ms-layout--spine .rsi-ms__item--odd {
		--rsi-ms-dir: calc(-1 * var(--rsi-ms-rtl));
	}

	.rsi-ms-layout--spine .rsi-ms__item--even {
		--rsi-ms-dir: var(--rsi-ms-rtl);
	}

	/* Single centred column (the faithful-to-mobile alternative). */
	.rsi-ms-layout--centered .rsi-ms__card {
		max-width: 640px;
		--rsi-ms-card-h: 740px;
	}

	.rsi-ms-layout--centered .rsi-ms__marker::before,
	.rsi-ms-layout--centered .rsi-ms__marker::after {
		height: 96px;
	}
}

/* Wide desktop: a little more air and a longer measure. */
@media (min-width: 1200px) {
	.rsi-ms {
		padding: 56px 24px;
	}

	.rsi-ms-layout--spine .rsi-ms__item {
		column-gap: 56px;
	}
}

@media (prefers-reduced-motion: reduce) {
	.rsi-ms__year {
		transition: none;
	}

	/* Settle every card outright. JS still runs and still writes --rsi-ms-p,
	   but nothing reads it, so the cards simply stay put. */
	.rsi-ms-anim-on .rsi-ms__card {
		opacity: 1;
		transform: none;
	}

	/* Rules fully drawn. */
	.rsi-ms-anim-on .rsi-ms__marker::before,
	.rsi-ms-anim-on .rsi-ms__marker::after {
		transform: none;
	}
}
