/* ==========================================================================
   GrowthStudioz, divisions

   A pinned deck. The panel holds in the middle of the screen while the cards
   advance through the deck, then releases once the last card has been shown.

   GSAP ScrollTrigger pins the panel, reserves the scroll, scrubs and snaps to
   whole cards (Adarsh, 25th September 2026; see divisions.js). It writes one
   number, --gs-div-progress (0 to 1); every transform below is still derived
   from it, so the motion stays declarative and lives in this file.
   ========================================================================== */

.gs-divisions {
	--gs-div-count: 4;
	--gs-div-progress: 0;

	/* How far the active card index has advanced: 0 to count-1. */
	--gs-div-active: calc(var(--gs-div-progress) * (var(--gs-div-count) - 1));
	/* Where this card sits relative to the active one. Negative means already
	   shown, positive means still stacked behind. */
	/* PERCENTAGES, so they scale with the card: translate percentages resolve
	   against the element's own size, so one value lands on the coloured strip
	   at every width. A fixed 40px was right on desktop but 21% of a
	   phone-sized card, which showed a band of artwork above each strip.

	   9.18% is the Figma step (40.07px on a 436.29px card). The design widens
	   the LAST gap to 31.88% rather than the 27.54% a straight multiple would
	   give, so a second term adds the extra 4.34% past the second step. */
	/* Figma's own step is 9.18% (40.07px on a 436.29px card). It cannot hold at
	   the rendered size: the coloured strip is 6.07% of the card, so 9.18%
	   leaves a 14px gap between strips, while cards 2 and 3 tilt in OPPOSITE
	   directions and their ends converge by 24px across a 714px card. 24 into
	   14 does not go, so the strips overlapped.
	
	   The spacing gives way rather than the rotation: the angles are a design
	   decision and the gap is not. 12.5% leaves 29px against that 24px of
	   convergence. */
	--gs-div-step: 12.5%;
	--gs-div-step-last: 5.9%;
	/* Enough to clear the pinned panel: at 125% a card that had been shown was
	   still hanging in the top of the frame. */
	--gs-div-lift: 210%;

	/* Screens of scroll for each card change while pinned, read by the
	   script. Shorter than a full screen: four full screens made the section
	   dominate the page for how little content it carries. */
	--gs-div-per-card: 0.72;

	/* When a shown card fades: fully there until --d passes -fade-at, gone
	   fade-len later. It starts fading as soon as it moves, so a leaving card
	   never sits solid over the next one (Adarsh, 25th September 2026); it
	   used to stay solid for the first 40% of its lift. The phone has its own
	   pair below. */
	--gs-div-fade-at: 0.05;
	--gs-div-fade-len: 0.35;
	/* Its half of the sitewide 80px gap, like every other band. It used to be
	   0, which left this section 40px from its neighbours where everything
	   else is 80. */
	padding-block: var(--gs-section-pad);
	/* CLIP, not hidden, and only on the x axis. Letting the panel overflow so
	   cards are never sliced means an exiting card, which travels 200% of its
	   own width sideways on phones, extends the document and the whole page
	   gains a horizontal scrollbar (measured 1749px wide against a 410px
	   screen). `overflow-x: clip` cuts that off without creating a scroll
	   container, so the vertical overflow the cards rely on still shows. */
	overflow-x: clip;
	/* NO inline padding. This section is not full bleed, so it already sits
	   inside main's gutter; adding its own doubled it to 120 and pulled the
	   content in to 1185 where the design is 1320. */
}

/* Pinned by ScrollTrigger, not sticky, and only as tall as its content: the
   script centres it in the screen while it holds. */
.gs-divisions__pin {
	display: grid;
	align-items: center;
	padding-block: var(--gs-space-5);
	/* VISIBLE, not hidden. On a short window the card is taller than the panel,
	   and clipping it sliced the artwork mid-phone. Letting it spill keeps the
	   card whole; the section around it is tall enough that the overspill lands
	   in its own space rather than over a neighbouring band, and an exiting
	   card has faded out before it travels far. */
	overflow: visible;
}

.gs-divisions__inner {
	display: grid;
	/* The deck takes the larger share: a bigger card fills more of the panel's
	   height, which is the only honest way to reduce the air around it. */
	grid-template-columns: minmax(0, 0.78fr) minmax(0, 1.22fr);
	align-items: center;
	gap: var(--gs-space-7);
	/* Capped and centred like the rest of the site. Without this the deck
	   stretches the full width of a large monitor and the cards lose the
	   proportions the mockup gives them. */
	width: 100%;
	/* No cap at all: the global gutter alone holds the section off the edge,
	   which is what makes it 1320 on a 1440 frame (1440 - 2 x 60), the Figma
	   width. The viewport-height cap that used to sit here existed only to stop
	   a tall deck being clipped by the panel; now the panel lets it overflow,
	   so the card can stay full size instead of shrinking on short windows. */
	max-width: 100%;
	margin-inline: auto;
}

/* --- intro ---------------------------------------------------------------- */

.gs-divisions__title {
	margin: 0 0 var(--gs-space-4);
	line-height: var(--gs-lh-heading);
}

.gs-divisions__title-line {
	display: block;
}

.gs-divisions__title-line--accent {
	color: var(--gs-red);
}

.gs-divisions__body {
	margin: 0;
	max-width: 42ch;
	color: var(--gs-body);
	font-size: var(--gs-b3);
	line-height: var(--gs-lh-body);
}

/* --- the deck ------------------------------------------------------------- */

/* One grid cell holding every card, rather than absolute positioning.
   Absolute cards size to their own content, so a division with no one-liner
   yet came out shorter and its coloured strip hid behind the card in front.
   Stacked in a single grid cell they all stretch to the tallest, so the strips
   step evenly however much copy each one carries. */
.gs-divisions__deck {
	display: grid;
	grid-template-columns: minmax(0, 1fr);
	margin: 0;
	/* Room for the tilt. A rotated card is wider than its own box, and the
	   stacked ones are nudged sideways as well, so without this they run past
	   the pinned panel and get clipped by its overflow. Padding narrows the
	   grid cell, so the cards themselves shrink to fit rather than spilling. */
	padding-inline: 4%;
	padding-block-end: 1%;
	list-style: none;
}

.gs-division {
	grid-area: 1 / 1;
	display: flex;
	flex-direction: column;
	max-width: none;

	--d: calc(var(--i) - var(--gs-div-active));

	/* One expression covers both halves of the deck, because CSS cannot branch:
	   max(--d, 0) is non-zero only for cards still stacked behind, and
	   min(--d, 0) only for cards already passed. Behind, each card drops by a
	   tab's height so its strip shows; passed, it lifts away above. */
	/* Depth comes from scale, NOT rotation. A per-card rotation was tried and
	   removed: even at 0.7deg the coloured strips cross each other, because
	   each card is a metre wide and tilts about a different amount, so the
	   right end of one lands under the left end of the next. Narrowing each
	   card behind reads as a deck and keeps every strip horizontal, which is
	   also what the mockup shows. */
	transform-origin: 50% 0;
	transform:
		translateY(calc(max(var(--d), 0) * var(--gs-div-step)))
		translateY(calc(max(calc(var(--d) - 2), 0) * var(--gs-div-step-last)))
		translateY(calc(min(var(--d), 0) * var(--gs-div-lift)))
		translateX(calc(clamp(0, var(--d), 1) * var(--gs-div-dx, 0%)))
		rotate(calc(clamp(0, var(--d), 1) * var(--gs-div-rot, 0deg)));

	/* Earlier cards sit in front, so the deck reads front-to-back. */
	z-index: calc(100 - var(--i));
	/* Clamped, and held at full until the card has visibly begun to leave.
	   A plain `1 + d * k` made the ACTIVE card 0.994 opaque the instant --d
	   went fractionally negative, and that 0.6% was enough for the card behind
	   to ghost through its white background. */
	opacity: clamp(0, calc(1 + (var(--d) + var(--gs-div-fade-at)) / var(--gs-div-fade-len)), 1);
	/* No transition: ScrollTrigger's scrub already smooths the progress, and a
	   CSS transition on top made the cards trail the finger. */
	will-change: transform;
}

/* The artwork card. The supplied image is the entire card, strip included, so
   it carries the radius and shadow the composed card would have. */
.gs-division__link,
.gs-division__art {
	display: block;
	width: 100%;
}

.gs-division__art {
	height: auto;
	aspect-ratio: 705 / 445;
}

/* Two crops, one shown. The phone card is 340x319 against the desktop's
   705x445, so this is a different composition rather than the same image
   scaled; each keeps its own ratio and the deck never reflows. A division with
   no phone crop yet keeps showing its desktop one at every width. */
.gs-division__art--phone {
	display: none;
	aspect-ratio: 340 / 319;
	object-fit: contain;
	/* No radius and no shadow here, deliberately. The exported PNG already
	   carries the card's rounded corners AND the Figma drop shadow, and it has
	   transparent margin around them. Styling the IMG box therefore drew a
	   second frame around that transparent margin rather than around the
	   artwork, which read as a box floating outside the card. */
}

.gs-division__link {
	transition: transform 220ms cubic-bezier(0.23, 1, 0.32, 1);
}

/* The whole card is the target, so the press needs to read on the card itself
   rather than on a button inside it. */
.gs-division__link:active {
	transform: scale(0.99);
}

.gs-division__link:focus-visible {
	outline: 3px solid var(--gs-division-color);
	outline-offset: 3px;
}

/* Straight from the Figma inspector. Applied through clamp(0, --d, 1) so they
   describe the STACKED state only: the card in front is always square to the
   page and unshifted, which is what the design shows. Scale is deliberately
   not used: the design keeps every card the same size and separates them by
   offset and rotation instead. */
.gs-division:nth-child(2) {
	--gs-div-dx: 2.62%;
	--gs-div-rot: 2.12deg;
}

.gs-division:nth-child(3) {
	--gs-div-dx: -0.97%;
	--gs-div-rot: -1.73deg;
}

.gs-division:nth-child(4) {
	--gs-div-dx: 2.05%;
	--gs-div-rot: 0deg;
}

.gs-division__card {
	flex: 1;
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 0.8fr);
	align-items: center;
	gap: var(--gs-space-5);
	padding: var(--gs-space-6);
	border: var(--gs-border-width) solid var(--gs-border);
	border-radius: 11px;
	background: var(--gs-surface);
	box-shadow: 0 2.79px 4.18px rgba(0, 0, 0, 0.25);
}

/* No artwork yet: the card collapses to one column rather than leaving an
   empty half that stretches it to twice the width it should be. */
.gs-division__card--no-shot {
	grid-template-columns: minmax(0, 1fr);
}

.gs-division__logo {
	display: block;
	width: auto;
	height: 52px;
	max-width: 100%;
	object-fit: contain;
	object-position: left center;
}

.gs-division__name {
	margin: 0;
	max-width: none;
	font-size: var(--gs-h3);
	font-weight: var(--gs-weight-semibold);
}

.gs-division__liner {
	margin: var(--gs-space-4) 0 0;
	max-width: 32ch;
	color: var(--gs-body);
	font-size: var(--gs-b3);
	line-height: var(--gs-lh-body);
}

/* .gs-btn--solid gives the ink fill. The hover is the one thing this section
   changes: each card hovers to its OWN division colour, which is set per card
   as --gs-division-color. */
.gs-division__cta {
	--btn-fill-hover: var(--gs-division-color);

	margin-block-start: var(--gs-space-5);
}

.gs-division__cta-icon {
	flex: none;
}

.gs-division__shot-img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: var(--gs-radius);
}

/* The strip that stays visible when the card is stacked behind. */
.gs-division__tab {
	margin: 0;
	padding: 6px var(--gs-space-5);
	border-radius: 0 0 11px 11px;
	background: var(--gs-division-color);
	/* Narrativ's accent is black and UX19's is yellow, so the label cannot be a
	   fixed colour. The readable ink is worked out in PHP from the accent's
	   luminance and passed in; `color-contrast()` would express this in CSS
	   but is still unsupported in every shipping browser. */
	color: var(--gs-division-ink, var(--gs-white));
	font-size: var(--gs-b5);
	font-weight: var(--gs-weight-semibold);
	letter-spacing: 0.18em;
	text-align: center;
	text-transform: uppercase;
}

/* --- editor-only empty state ---------------------------------------------- */

.gs-divisions--empty {
	display: grid;
	place-items: center;
	min-height: 160px;
	padding: var(--gs-space-6);
	border: 1px dashed var(--gs-border);
	background: var(--gs-surface-alt);
	color: var(--gs-body);
}

.gs-divisions--empty p {
	margin: 0;
	max-width: none;
}

/* ==========================================================================
   Phones
   ========================================================================== */

@media (max-width: 900px) {
	/* ---- A swipe deck, not a pinned one (Adarsh, 26th September 2026) ----
	   Pinned, the deck held the whole screen for about 500px of content,
	   and however it was arranged that left a third of a phone blank. So on a
	   phone nothing is pinned: the section scrolls like any other, and the
	   front card is swiped away (or stepped with the arrows) and tucks in at
	   the back, so the cards cycle. See divisions.js. */
	.gs-divisions__inner {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--gs-space-6);
	}

	/* No pin, so no pin padding: the section's own padding is the rhythm. */
	.gs-divisions__pin {
		padding-block: 0;
	}

	.gs-divisions__deck {
		/* Less room kept for the tilt than desktop, so the cards are bigger. */
		padding-inline: 2%;
		/* Vertical scrolling stays the browser's; a sideways drag is the
		   deck's. */
		touch-action: pan-y;
		/* The cards behind are moved down by transforms, which take no
		   layout space, so the stack hangs about 36% of its width below the
		   deck's own box and sat on top of the arrows. This reserves it.
		   Percent padding is of the width, which is what the overhang scales
		   with. */
		padding-block-end: 36%;
	}

	/* A phone crop is a taller card, so its stack hangs further. */
	.gs-divisions:has(.gs-division__art--phone) .gs-divisions__deck {
		padding-block-end: 52%;
	}

	/* The deck settles with a transition here (on desktop the scroll drives
	   it frame by frame, so it has none). A card being dragged follows the
	   finger with no delay. */
	.gs-division {
		transition:
			transform 420ms cubic-bezier(0.23, 1, 0.32, 1),
			translate 420ms cubic-bezier(0.23, 1, 0.32, 1),
			rotate 420ms cubic-bezier(0.23, 1, 0.32, 1),
			opacity 320ms ease-out;
	}

	.gs-division.is-dragging,
	.gs-division.is-parking {
		transition: none;
	}

	/* Dragging a card must not select its text or pick up its picture. */
	.gs-divisions__deck {
		user-select: none;
		-webkit-user-select: none;
	}

	.gs-divisions__deck img {
		-webkit-user-drag: none;
	}

	.gs-division__card {
		grid-template-columns: minmax(0, 1fr);
		padding: var(--gs-space-5);
	}

	/* On a phone a shown card leaves SIDEWAYS, not upwards, alternating left,
	   right, left, right. Lifting a card up its own height reads badly here:
	   the deck already sits low in a tall narrow frame, so an upward exit
	   crosses the heading above it. Sliding out of the side it entered from
	   keeps the motion inside the card's own lane.

	   translateX percentages resolve against the element's own WIDTH, so 200%
	   clears the viewport whatever the card measures. */
	/* Swap to the phone crop where one exists. */
	.gs-division__art--phone {
		display: block;
	}

	.gs-division:has(.gs-division__art--phone) .gs-division__art--desktop {
		display: none;
	}

	.gs-division {
		--gs-div-exit: 200%;

		transform:
			translateY(calc(max(var(--d), 0) * var(--gs-div-step)))
			translateY(calc(max(calc(var(--d) - 2), 0) * var(--gs-div-step-last)))
			translateX(calc(clamp(0, var(--d), 1) * var(--gs-div-dx, 0%)))
			translateX(calc(min(var(--d), 0) * var(--gs-div-exit)))
			rotate(calc(clamp(0, var(--d), 1) * var(--gs-div-rot, 0deg)));
	}

	/* Phone geometry from the Figma inspector, on its 334px card. The angles
	   and horizontal offsets are the design's; only the vertical step is ours,
	   for the reason below. */
	.gs-division:nth-child(2) {
		--gs-div-rot: 2.53deg;
		--gs-div-dx: 0.6%;
	}

	.gs-division:nth-child(3) {
		--gs-div-rot: -3.96deg;
		--gs-div-dx: -3.59%;
	}

	.gs-division:nth-child(4) {
		--gs-div-rot: 0.91deg;
		--gs-div-dx: 2.99%;
	}

	/* The design's own steps are 15.24 / 9.29 / 17.47% of the card, but the
	   middle one cannot hold: cards 2 and 3 tilt opposite ways at 2.53 and
	   3.96deg, so their ends converge by 16.8px, against a strip 11.3px tall.
	   9.29% leaves 6px of gap, so those two strips collide, as they very
	   nearly do in the comp. 18% clears the worst pair with room to spare. */
	.gs-divisions {
		--gs-div-step: 18%;
		--gs-div-step-last: 2%;
	}

	/* Cards 2 and 4 leave to the RIGHT; 1 and 3 to the left, giving the left,
	   right, left, right Adarsh asked for. */
	.gs-division:nth-child(even) {
		--gs-div-exit: -200%;
	}
}

/* --- desktop: bigger cards --------------------------------------------------
   Adarsh, 26th September 2026: less blank around the pinned deck, and the
   cards may overflow. The deck column takes more of the row and runs 45px into
   the right-hand margin, and each card is as wide as that allows, but:

     never wider than 705px, the artwork's own width. Wider is a stretched
     picture (it was drawn at 975px on a 1920 screen, and looked it).

     never so tall that the stack (the front card plus the three stepped
     below it, about 0.91 of the card's width in all) leaves less than 64px
     of air above and below on a short laptop.

   The script reserves the room the stack hangs below the front card, so the
   pin centres the whole stack rather than just the front card. */
@media (min-width: 901px) {
	/* The text column gives up room to the deck, but never so much that a
	   heading line breaks: each line stays whole ("under 1 roof", not
	   "under / 1 roof") and the column is at least that wide. */
	.gs-divisions__inner {
		grid-template-columns: minmax(min-content, 0.65fr) minmax(0, 1.35fr);
	}

	.gs-divisions__title-line {
		white-space: nowrap;
	}

	.gs-divisions__deck {
		container-type: inline-size;
		margin-inline-end: calc(var(--gs-gutter-now) * -0.75);
		padding-inline: 0;
		justify-items: center;
	}

	.gs-division {
		width: min(705px, 96cqw, calc((100vh - 128px) / 0.91));
	}

	/* The cards run 45px into the right-hand margin, and the section's
	   sideways clip (there for the phone, where cards leave sideways) was
	   cutting them off at its own edge. Here they only ever leave upwards,
	   and stay inside the screen, so nothing needs clipping. */
	.gs-divisions {
		overflow-x: visible;
	}

	/* ---- The deck CYCLES (Adarsh, 26th September 2026) -----------------
	   A card that leaves no longer leaves for good: once it has lifted away
	   and faded, it comes back in at the very back of the stack. So there
	   are always four cards, the stack never gets shorter, and the space
	   under it never grows as the cards go.

	   --d-raw is the plain place in the deck (negative once passed). Past
	   the point where a leaving card has fully faded (-(fade-at + fade-len),
	   -0.4), a step adds one whole deck to it, which puts it one place
	   BEHIND the last card; from there it slides forward into the last slot
	   as the deck moves on. clamp(0, x * 1000, 1) is the step: CSS has no
	   if, and this is 0 before the threshold and 1 a hair after it. */
	.gs-division {
		--d-raw: calc(var(--i) - var(--gs-div-active));
		--d: calc(var(--d-raw) + var(--gs-div-count) * clamp(0, calc((var(--d-raw) * -1 - var(--gs-div-fade-at) - var(--gs-div-fade-len)) * 1000), 1));

		/* The order on screen follows the place in the deck, not the card's
		   number, or a card sent to the back would still be drawn in front.
		   Rounded to a whole number, as z-index requires. */
		z-index: calc(100 - var(--d) * 10);

		/* Leaving: fades as it lifts (as before). Coming back in at the back:
		   fades up over the last 0.6 of its slide into the last slot. */
		opacity: min(
			clamp(0, calc(1 + (var(--d) + var(--gs-div-fade-at)) / var(--gs-div-fade-len)), 1),
			clamp(0, calc((var(--gs-div-count) - 0.4 - var(--d)) / 0.6), 1)
		);
	}
}

/* ==========================================================================
   Reduced motion

   No pin and no deck: the cards become a plain list. A scroll-driven stack is
   exactly the kind of motion this setting exists to switch off, and a section
   that hijacks four screens of scroll is worse than one that does not.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
	.gs-divisions {
		min-height: 0;
	}

	.gs-divisions__pin {
		position: static;
		min-height: 0;
		overflow: visible;
	}

	.gs-divisions__deck {
		display: grid;
		gap: var(--gs-space-5);
		min-height: 0;
	}

	.gs-division {
		grid-area: auto;
		translate: none;
		transform: none;
		rotate: 0deg;
		opacity: 1;
		transition: none;
	}
}
