/*
 * Home: Growth Journey (رحلة النمو).
 *
 * Three layers, each only ADDING to the one before:
 * 1. Baseline (no JS, STATIC_ACCESSIBLE, any failure): normal flow, readable
 *    chapter list beside the fully composed illustration.
 * 2. [data-gb-mode="light"] (LIGHT): same layout, one short reveal per block,
 *    driven by IntersectionObserver + CSS transitions. No GSAP.
 * 3. [data-gb-scene] (FULL / OPTIMIZED): tall track + sticky stage; GSAP
 *    ScrollTrigger only scrubs progress. CSS position: sticky does the "pin",
 *    so there are no pin-spacers and no layout recalculation while scrolling.
 *
 * Layers 2 and 3 are switched on by JS only after it has successfully set
 * itself up, so a failure can never leave an empty tall region or hidden text.
 */

.gb-journey {
	/* Dark scene: the light focus ring stays visible. */
	--gb-focus: var(--gb-focus-inverse);

	padding-block: var(--gb-space-2xl);
	background-color: var(--gb-scene-bg);
	color: var(--gb-scene-text);
}

/* ---------- Baseline layout ---------- */

.gb-journey__stage {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
	align-items: center;
	gap: var(--gb-space-xl) var(--gb-space-l);
}

.gb-journey__title {
	font-size: var(--gb-step-4);
	color: var(--gb-scene-text);
}

/* The chapter list carries the Growth Line language as a simple logical border. */
.gb-journey__chapters {
	display: grid;
	gap: var(--gb-space-m);
	margin: 0;
	margin-block-start: var(--gb-space-m);
	padding: 0;
	padding-inline-start: var(--gb-space-m);
	border-inline-start: 2px solid var(--gb-root-color);
	list-style: none;
}

/*
 * Chapters must NOT be positioned or transformed: on wide scene layouts the
 * concept labels inside them are absolutely positioned against the sticky stage.
 */
.gb-journey__chapter-title {
	font-family: var(--gb-font-display);
	font-size: var(--gb-step-3);
	color: var(--gb-scene-text);
}

.gb-journey__chapter-title::before {
	content: "";
	display: inline-block;
	inline-size: 0.45em;
	block-size: 0.45em;
	margin-inline-end: 0.5em;
	border-radius: 50%;
	/* A light orange touch, like every eyebrow's dot (owner, 2026-10-06; the seed's colour from 2026-10-05). */
	background-color: var(--gb-dot);
	vertical-align: middle;
}

.gb-journey__concepts {
	display: flex;
	flex-wrap: wrap;
	gap: var(--gb-space-2xs);
	margin: 0;
	margin-block-start: var(--gb-space-xs);
	padding: 0;
	list-style: none;
}

.gb-journey__concept {
	font-size: var(--gb-step--1);
	white-space: nowrap;
}

/* The pill is the link itself, so the whole label is the click/tap target (≥ 44px tall). */
.gb-journey__concept-link {
	display: inline-flex;
	align-items: center;
	gap: var(--gb-space-3xs);
	min-block-size: 2.75rem;
	padding-block: var(--gb-space-3xs);
	padding-inline: var(--gb-space-s);
	border: 1px solid var(--gb-root-color);
	border-radius: var(--gb-radius-pill);
	background-color: var(--gb-scene-bg);
	color: var(--gb-scene-text);
	text-decoration: none;
	transition:
		border-color var(--gb-duration-fast) linear,
		background-color var(--gb-duration-fast) linear;
}

/* A small seed-coloured dot signals "this opens something". */
.gb-journey__concept-link::before {
	content: "";
	inline-size: 0.4em;
	block-size: 0.4em;
	border-radius: 50%;
	background-color: var(--gb-seed);
}

.gb-journey__concept-link:hover,
.gb-journey__concept-link:focus-visible {
	border-color: var(--gb-primary);
	background-color: var(--gb-color-turquoise-a20);
}

.gb-journey__hint {
	margin-block-start: var(--gb-space-3xs);
	font-size: var(--gb-step--1);
	color: var(--gb-scene-text-muted);
}

.gb-journey__frame {
	justify-self: center;
	inline-size: min(100%, 32rem);
	/* Reserves the illustration's space before it paints: no layout shift. */
	aspect-ratio: 600 / 720;
}

.gb-journey__art {
	display: block;
	inline-size: 100%;
	block-size: 100%;
	overflow: visible;
}

/* ---------- SVG parts (decorative) ---------- */

.gb-journey__root,
.gb-journey__rootlet {
	fill: none;
	stroke-linecap: round;
}

.gb-journey__root {
	stroke: var(--gb-root-color);
	stroke-width: var(--gb-root-width);
}

.gb-journey__rootlet {
	stroke: var(--gb-rootlet-color);
	stroke-width: var(--gb-rootlet-width);
}

/*
 * RTL: mirror ONLY the roots (about the point's axis, x = 300) so the first
 * concept in reading order sits at the reading start, matching the labels'
 * logical positioning. Point, growth line and brand mark are never mirrored.
 * transform-box: view-box makes "300px" mean SVG user units.
 */
[dir="rtl"] .gb-journey__roots {
	transform: scaleX(-1);
	transform-box: view-box;
	transform-origin: 300px 0;
}

/* Foundation nodes: one per concept, at the end of each line. */
.gb-journey__node {
	fill: var(--gb-scene-bg);
	stroke: var(--gb-node-color);
	stroke-width: 2.5px;
	transition: fill var(--gb-duration-fast) linear;
}

/* Hover/focus on a concept link lights its node (attribute set by growth-journey.js). */
.gb-journey[data-gb-concept-active="strategy"] [data-gb-node="strategy"],
.gb-journey[data-gb-concept-active="research"] [data-gb-node="research"],
.gb-journey[data-gb-concept-active="audience"] [data-gb-node="audience"],
.gb-journey[data-gb-concept-active="data"] [data-gb-node="data"],
.gb-journey[data-gb-concept-active="insight"] [data-gb-node="insight"] {
	fill: var(--gb-seed);
}

/* The growth point's resting look and pivots live in components/growth-point.css (shared with the hero). */

/* ---------- LIGHT: one short reveal per block ---------- */

/* Kept off phones and weak devices: fewer strokes to paint during the reveal. */
.gb-journey[data-gb-mode="light"] .gb-journey__rootlet {
	display: none;
}

.gb-journey[data-gb-mode="light"] .gb-draw {
	stroke-dasharray: 1;
	transition:
		stroke-dashoffset var(--gb-duration-reveal) var(--gb-ease-organic),
		opacity var(--gb-duration-fast) linear;
}

/* Pivots come from components/growth-point.css (point-centred user space); only timing is set here. */
.gb-journey[data-gb-mode="light"] :is(.gb-point__glow, .gb-journey__node) {
	transition: opacity var(--gb-duration-reveal) var(--gb-ease-out);
}

.gb-journey[data-gb-mode="light"] .gb-point__body {
	transition:
		opacity var(--gb-duration-reveal) var(--gb-ease-out),
		transform var(--gb-duration-reveal) var(--gb-ease-out);
}

.gb-journey[data-gb-mode="light"] [data-gb-mark-part] > :not(.gb-draw) {
	transition: opacity var(--gb-duration-reveal) linear;
}

/* Sequence: point → lines → growth line → arrow → frame (about 1.3 s in total). */
.gb-journey[data-gb-mode="light"] .gb-journey__root {
	transition-delay: calc(var(--gb-duration-reveal) * 0.2);
}

.gb-journey[data-gb-mode="light"] .gb-journey__node {
	transition-delay: calc(var(--gb-duration-reveal) * 0.6);
}

.gb-journey[data-gb-mode="light"] [data-gb-journey-stem] {
	transition-delay: calc(var(--gb-duration-reveal) * 0.55);
}

.gb-journey[data-gb-mode="light"] [data-gb-mark-part="arrow"] .gb-draw {
	transition-delay: calc(var(--gb-duration-reveal) * 0.95);
}

.gb-journey[data-gb-mode="light"] [data-gb-mark-part="body"] .gb-draw,
.gb-journey[data-gb-mode="light"] [data-gb-mark-part] > :not(.gb-draw) {
	transition-delay: calc(var(--gb-duration-reveal) * 1.15);
}

/* Pending = below the fold and not yet revealed (set by JS only). */
.gb-journey[data-gb-mode="light"] .gb-journey__frame.is-pending .gb-draw {
	opacity: 0;
	stroke-dashoffset: 1;
}

.gb-journey[data-gb-mode="light"] .gb-journey__frame.is-pending :is(.gb-point__glow, .gb-journey__node) {
	opacity: 0;
}

.gb-journey[data-gb-mode="light"] .gb-journey__frame.is-pending .gb-point__body {
	opacity: 0;
	transform: scale(0.6);
}

.gb-journey[data-gb-mode="light"] .gb-journey__frame.is-pending [data-gb-mark-part] > :not(.gb-draw) {
	opacity: 0;
}

.gb-journey[data-gb-mode="light"] .gb-journey__chapter {
	transition:
		opacity var(--gb-duration-reveal) var(--gb-ease-out),
		translate var(--gb-duration-reveal) var(--gb-ease-out);
}

.gb-journey[data-gb-mode="light"] .gb-journey__chapter.is-pending {
	opacity: 0;
	translate: 0 0.75rem;
}

/*
 * LIGHT (phones): the concepts at their root tips too. growth-journey.js
 * measures the picture inside the stage (--gb-tips-x/-y/-w/-h, px) and sets
 * data-gb-tips; each label adds its own tip (--gb-tip-u/-v). Roots are
 * mirrored in RTL, so the tip's share across is 1 − u there. The labels
 * arrive one by one once the picture has drawn its roots.
 */
.gb-journey[data-gb-mode="light"][data-gb-tips] .gb-journey__stage {
	position: relative;
}

.gb-journey[data-gb-mode="light"][data-gb-tips] .gb-journey__concept {
	--gb-tip-x: var(--gb-tip-u);

	position: absolute;
	left: calc(var(--gb-tips-x) + var(--gb-tips-w) * var(--gb-tip-x));
	top: calc(var(--gb-tips-y) + var(--gb-tips-h) * var(--gb-tip-v));
	translate: -50% 0.7rem;
	font-size: 0.8125rem;
	transition: opacity 0.4s var(--gb-ease-out) calc(var(--gb-duration-reveal) * 0.9 + var(--gb-tip-i, 0) * 90ms);
}

[dir="rtl"] .gb-journey[data-gb-mode="light"][data-gb-tips] .gb-journey__concept {
	--gb-tip-x: calc(1 - var(--gb-tip-u));
}

.gb-journey[data-gb-mode="light"][data-gb-tips] .gb-journey__concept-link {
	min-block-size: 1.9rem;
	padding-inline: 0.6rem;
}

/* Waiting for the picture: the labels come with their roots. */
.gb-journey[data-gb-mode="light"][data-gb-tips]:has(.gb-journey__frame.is-pending) .gb-journey__concept {
	opacity: 0;
	transition-delay: 0s;
}

/* The chapters only fade here (a moving chapter would carry the labels with it). */
.gb-journey[data-gb-mode="light"][data-gb-tips] .gb-journey__chapter.is-pending {
	translate: none;
}

/* Room under the picture for the lowest labels. */
.gb-journey[data-gb-mode="light"][data-gb-tips] .gb-journey__frame {
	margin-block-end: 2.25rem;
}

/* ---------- FULL / OPTIMIZED: sticky stage + scrubbed scene ---------- */

.gb-journey[data-gb-scene] {
	--gb-journey-pad: var(--gb-space-l);
	/*
	 * Illustration width inside the sticky stage. Container units resolve against
	 * the stage (container-type: size), so the frame AND the label positions
	 * below use the same numbers. 1.2 = the 600×720 viewBox aspect.
	 */
	--gb-frame-w: min(56cqi, 100cqb / 1.2);

	padding-block: 0;
}

.gb-journey[data-gb-scene="full"] .gb-journey__track {
	block-size: var(--gb-journey-length-full);
}

.gb-journey[data-gb-scene="optimized"] .gb-journey__track {
	block-size: var(--gb-journey-length-optimized);
}

.gb-journey[data-gb-scene] .gb-journey__stage {
	position: sticky;
	inset-block-start: 0;
	block-size: 100vh;
	block-size: 100svh;
	container-type: size;
	grid-template-columns: minmax(0, 1fr) auto;
	gap: var(--gb-space-l);
	padding-block: var(--gb-journey-pad);
}

.gb-journey[data-gb-scene] .gb-journey__frame {
	justify-self: end;
	inline-size: var(--gb-frame-w);
}

/* FULL keeps the richer detail and the halo; OPTIMIZED drops both. */
.gb-journey[data-gb-scene="optimized"] .gb-journey__rootlet {
	display: none;
}

.gb-journey[data-gb-scene="full"] .gb-growth-line--glow {
	display: inline;
}

/* Chapters share one cell and cross-fade with scroll progress (data-gb-chapter). */
.gb-journey[data-gb-scene] .gb-journey__chapters {
	padding-inline-start: 0;
	border-inline-start: 0;
}

.gb-journey[data-gb-scene] .gb-journey__chapter {
	grid-area: 1 / 1;
}

/*
 * opacity (not visibility/display) on purpose: inactive chapters stay in the
 * accessibility tree, so screen-reader users can read every chapter regardless
 * of scroll position.
 */
.gb-journey[data-gb-scene] .gb-journey__chapter > * {
	opacity: 0;
	translate: 0 0.75rem;
	transition:
		opacity var(--gb-duration-base) linear,
		translate var(--gb-duration-slow) var(--gb-ease-out);
}

.gb-journey[data-gb-scene] .gb-journey__chapter-title {
	font-size: var(--gb-step-5);
}

.gb-journey[data-gb-chapter="1"] [data-gb-chapter-index="1"] > *,
.gb-journey[data-gb-chapter="2"] [data-gb-chapter-index="2"] > *,
.gb-journey[data-gb-chapter="3"] [data-gb-chapter-index="3"] > *,
.gb-journey[data-gb-chapter="4"] [data-gb-chapter-index="4"] > * {
	opacity: 1;
	translate: 0 0;
}

/*
 * Every scene layout: concept labels sit at their root tips (owner,
 * 2026-10-05: «يبقوا عند الجذع زي اللاب»). Each label's --gb-tip-u / --gb-tip-v
 * (set from the same geometry as the paths) are fractions of the
 * illustration, which is the inline-end column of the stage. Logical insets
 * + mirrored roots keep this correct in RTL and LTR; --gb-dir only flips the
 * centring translate. Portrait stages override the frame's position below.
 */

/* No translate here: a transform would become the labels' containing block. */
.gb-journey[data-gb-scene] .gb-journey__chapter > .gb-journey__concepts {
	opacity: 1;
	translate: none;
}

.gb-journey[data-gb-scene] .gb-journey__concept {
	position: absolute;
	inset-inline-end: calc(var(--gb-frame-w) * (1 - var(--gb-tip-u)));
	inset-block-start: calc(var(--gb-journey-pad) + (100cqb - var(--gb-frame-w) * 1.2) / 2 + var(--gb-frame-w) * 1.2 * var(--gb-tip-v));
	/* Below the node: centred on the tip, pushed down past the node's ring. */
	translate: calc(var(--gb-dir) * 50%) var(--gb-space-m);
}

/* Stages narrower than a laptop (side-by-side phones in landscape): smaller pills. */
@container (max-width: 59.99rem) {
	.gb-journey[data-gb-scene] .gb-journey__concept {
		translate: calc(var(--gb-dir) * 50%) 0.7rem;
		font-size: clamp(0.8125rem, 2.1cqi, 0.9375rem);
	}

	.gb-journey[data-gb-scene] .gb-journey__concept-link {
		min-block-size: 1.9rem;
		padding-inline: 0.6rem;
	}
}

/*
 * Portrait / narrow stages (tablets upright, narrow windows — owner
 * screenshot 2026-10-04): side by side, the text column became ~120px wide,
 * so «رحلة النمو» and the chapter names broke over two lines and the chapter
 * dot sat alone above its word. Here the text goes on top and the
 * illustration below, both full width (the labels follow, see below).
 */
@media (max-width: 59.99rem) and (max-aspect-ratio: 4 / 5) {
	.gb-journey[data-gb-scene] {
		/*
		 * Text block on top ≈ 11rem tall (the concepts are no longer in it,
		 * see below) + room under the roots for their labels (--gb-label-room);
		 * the illustration takes the rest, so it is larger and the empty gap
		 * between the text and the picture is gone.
		 */
		--gb-label-room: 3rem;
		--gb-frame-w: min(88cqi, (100cqb - 11rem - var(--gb-space-l) - var(--gb-label-room)) / 1.2);
	}

	.gb-journey[data-gb-scene] .gb-journey__stage {
		grid-template-columns: minmax(0, 1fr);
		grid-template-rows: auto minmax(0, 1fr);
		align-items: start;
		row-gap: var(--gb-space-l);
	}

	.gb-journey[data-gb-scene] .gb-journey__frame {
		justify-self: center;
		align-self: end;
		margin-block-end: var(--gb-label-room);
	}

	.gb-journey[data-gb-scene] .gb-journey__chapter-title {
		font-size: var(--gb-step-4);
	}

	/*
	 * Phones and tablets upright (owner, 2026-10-04: the concepts showed only
	 * in «الأساس» and vanished after — «مظلومين»): like the laptop, each
	 * concept now sits at the tip of its own root and stays for the rest of
	 * the journey (it arrives with its root, growth-journey-scene.js). The
	 * frame is centred and rests on the label room at the bottom:
	 *   inline: (100cqi − W) / 2 + W × (1 − u)   (roots mirrored in RTL, as above)
	 *   block:  pad + 100cqb − room − 1.2W + 1.2W × v
	 * Smaller pills so neighbouring labels never touch on a 375px screen.
	 */
	.gb-journey[data-gb-scene] .gb-journey__chapter > .gb-journey__concepts {
		opacity: 1;
		translate: none;
	}

	.gb-journey[data-gb-scene] .gb-journey__concept {
		position: absolute;
		inset-inline-end: calc((100cqi - var(--gb-frame-w)) / 2 + var(--gb-frame-w) * (1 - var(--gb-tip-u)));
		inset-block-start: calc(var(--gb-journey-pad) + 100cqb - var(--gb-label-room) - var(--gb-frame-w) * 1.2 + var(--gb-frame-w) * 1.2 * var(--gb-tip-v));
		translate: calc(var(--gb-dir) * 50%) 0.7rem;
		/* 13px on phones, up to 15px on tablets (cqi = the stage width). */
		font-size: clamp(0.8125rem, 2.1cqi, 0.9375rem);
	}

	.gb-journey[data-gb-scene] .gb-journey__concept-link {
		min-block-size: 1.9rem;
		padding-inline: 0.6rem;
	}
}

/* Titles in the stage stay on one line (they always have the full width now). */
.gb-journey[data-gb-scene] :is(.gb-journey__title, .gb-journey__chapter-title) {
	white-space: nowrap;
}
