/* ==========================================================================
   GrowthStudioz — case studies

   Carousel shell comes from carousel.css. This is the card and the header row.
   ========================================================================== */

/* Full bleed, so the grey band meets both viewport edges, with the gutter put
   back as padding so the heading and cards still line up with every other
   section.

   !important because core's constrained layout centres children of
   .wp-block-post-content with `margin-left: auto !important`, which a normal
   declaration cannot outrank at any specificity. The max-width cap has to be
   lifted too: the negative margin moves the section but cannot widen it, so
   without this it lands short by exactly two gutters. */
.gs-cases {
	/* Cards in view, stepping up a whole card per breakpoint. The card is a
	   FRACTION of the row rather than a fixed pixel width, so the count is the
	   thing that is declared and the width follows from it. The half card is
	   deliberate: a cut card is what says the row scrolls. */
	--gs-case-per-row: 3.5;
	--gs-case-gap: var(--gs-space-5);

	margin-inline: calc(var(--gs-gutter-now) * -1) !important;
	max-width: none !important;
	padding-block: var(--gs-section-pad);
	padding-inline: var(--gs-gutter-now);
	background: var(--gs-surface-alt);
}

/* On a division page the client logo band is the ONLY section carrying a fill
   (Adarsh, 24th September 2026), so the grey comes off this one. It keeps the
   full-bleed treatment: the negative margins are what let a card run to the
   screen edge and signal the row scrolls, and they are not the background.

   The home page keeps its grey, which is what separates the case studies from
   the white bands either side of it there. */
.page-template-page-division .gs-cases {
	background: none;
}

/* 3.5 is the default and holds all the way to 1920 inclusive; each breakpoint
   past that adds one more card. Ordered ascending so the later, narrower match
   wins without needing an upper bound on each. */
@media (min-width: 1921px) {
	.gs-cases {
		--gs-case-per-row: 4.5;
	}
}

@media (min-width: 2561px) {
	.gs-cases {
		--gs-case-per-row: 5.5;
	}
}

/* Between phone and desktop the same +1 rule is carried downwards: 3.5 cards
   in 704px of row would leave each one 184px wide, which the card's content
   cannot take. Adarsh specified 3.5 up to 1440 and did not state this band. */
@media (min-width: 768px) and (max-width: 1023.98px) {
	.gs-cases {
		--gs-case-per-row: 2.5;
	}
}

/* The row deliberately runs past the right gutter to the screen edge: a card
   cut by the viewport is what tells you there is more to scroll, where a row
   ending neatly inside the gutter reads as complete.

   padding-inline-end puts the gutter back inside the scroller, so the last
   card still stops clear of the edge once it is scrolled to. scroll-padding
   matches it, or snapping would park that card under the edge. */
/* Bleeds on BOTH sides, not just the end. The scroller's own box has to reach
   each viewport edge, or scrolled cards are clipped at the gutter and a strip
   of empty band shows beside a half-cut card.

   The padding puts the gutter back INSIDE the scroller, so at rest the first
   card still lines up with the heading, and scrolled content passes through
   that strip instead of being cut short of it. scroll-padding matches, or
   snapping parks a card under the edge. */
.gs-carousel--cases .gs-carousel__track {
	margin-inline: calc(var(--gs-gutter-now) * -1);
	padding-inline: var(--gs-gutter-now);
	scroll-padding-inline: var(--gs-gutter-now);
}

/* The shared carousel centres a row that does not overflow, with auto margins
   on the end cards. That is right for the width-capped testimonial rows, and
   wrong here: this row is anchored to the left gutter under the heading, so on
   a wide screen the slack gets split either side and pushes the first card in
   off the title's alignment. Only visible once the viewport is wide enough
   that the cards stop overflowing. */
.gs-carousel--cases .gs-carousel__track > :first-child { margin-inline-start: 0; }
.gs-carousel--cases .gs-carousel__track > :last-child { margin-inline-end: 0; }

/* The carousel wraps the heading, so it must not be a positioning context for
   the arrows the way the other rows are — here they sit in the header. */
.gs-carousel--cases {
	max-width: none;
}

.gs-cases__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--gs-space-5);
	margin-bottom: var(--gs-space-6);
}

.gs-cases__title {
	margin: 0;
}

.gs-cases__arrows {
	display: flex;
	gap: var(--gs-space-3);
	flex: none;
}

/* In this section the arrows live in the header rather than floating beside
   the track, so the absolute placement from carousel.css is undone. */
.gs-cases__arrows .gs-carousel__arrow {
	position: static;
	transform: none;
	inset: auto;
}

/* --- card ----------------------------------------------------------------- */

.gs-case {
	display: flex;
	flex-direction: column;
	/* 100% here is the track's content box, which is the 1320 section width at
	   1440, so the count above divides the row exactly. */
	width: calc(
		(100% - (var(--gs-case-per-row) - 1) * var(--gs-case-gap)) / var(--gs-case-per-row)
	);
	padding: var(--gs-space-3);
	border: var(--gs-border-width) solid var(--gs-border);
	border-radius: 12px;
	background: var(--gs-surface);
}

.gs-case__banner {
	margin-bottom: var(--gs-space-4);
}

.gs-case__img-wrap {
	display: block;
}

.gs-case__img {
	display: block;
	width: 100%;
	height: auto;
	/* A fixed ratio so a row of cards lines up whatever the source crop, and
	   nothing shifts as the images arrive. */
	aspect-ratio: 4 / 3;
	border-radius: var(--gs-radius);
	object-fit: cover;
}

/* Only one banner is shown at a time; the pair swaps by media query so the
   browser fetches just the file it needs. */
.gs-case__img--mobile {
	display: none;
}

.gs-case__body {
	display: flex;
	flex-direction: column;
	gap: var(--gs-space-4);
	/* Fills the card below the banner, which is what gives the `margin-block-
	   start: auto` on the rows and the Explore button something to push
	   against. Without it auto resolves to zero and both sit straight under
	   the copy, so the buttons across a row never line up. */
	flex: 1;
	padding-inline: var(--gs-space-2);
	padding-bottom: var(--gs-space-2);
}

.gs-case__client {
	display: block;
	width: auto;
	/* Height-capped like the logo wall: client marks vary wildly in aspect
	   ratio and matching heights is what keeps a row of cards even. */
	height: 32px;
	max-width: 70%;
	object-fit: contain;
	object-position: left center;
}

.gs-case__client-name {
	margin: 0;
	max-width: none;
	color: var(--gs-ink);
	font-size: var(--gs-b2);
	font-weight: var(--gs-weight-semibold);
}

.gs-case__text {
	color: var(--gs-body-soft);
	font-size: var(--gs-b4);
	line-height: var(--gs-lh-body);
}

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

.gs-case__text p + p {
	margin-block-start: var(--gs-space-3);
}

/* The stat is the point of the paragraph, so bold inside a case study reads as
   the brand red. Editors get it from the normal bold button rather than
   needing a colour picker they would have to apply consistently by hand. */
.gs-case__text strong,
.gs-case__text b {
	color: var(--gs-red-highlight);
	font-weight: var(--gs-weight-semibold);
}

/* --- explore -------------------------------------------------------------- */

/* Fill and ink come from .gs-btn--solid. Placement is all that lives here.
   Full width because a card is a narrow column and a 176px button in it reads
   as a stray chip; stretching it makes the base of every card line up. */
.gs-case__cta {
	width: 100%;
	/* Pushed to the card's base so the buttons align across a row whatever
	   length of copy each case study carries. The rows above also claim `auto`,
	   so this only takes effect when there are no division rows; the margin
	   below is the floor that keeps it clear of them either way. */
	margin-block-start: auto;
}

/* Flex margins do not collapse, so this gap always survives rather than being
   eaten by the `auto` above. */
.gs-case__rows + .gs-case__cta {
	margin-block-start: var(--gs-space-4);
}

/*
 * The whole card opens the case study (Adarsh, 8th October 2026). The button
 * stays the one real link (one tab stop, one name for a screen reader); its
 * ::after is stretched over the card, so a click anywhere on it is a click on
 * the link, middle and ctrl click included. Nothing else in the card is
 * interactive, so the layer covers nothing that needs its own click.
 *
 * Hovering anywhere is hovering the link, so the button shows its hover state
 * and turns its arrow (base.css) on its own; the card adds a darker edge.
 *
 * The button must not shrink on press here: a transform would make it the
 * box its ::after is measured from, the layer would collapse to the button
 * mid-click, and a press that started elsewhere on the card would be lost.
 * The card gives the press feedback instead.
 */
.gs-case {
	position: relative;
	transition:
		border-color var(--gs-dur-hover) ease,
		box-shadow var(--gs-dur-hover) ease,
		transform var(--gs-dur-press) var(--gs-ease-out);
}

.gs-case__cta::after {
	content: "";
	position: absolute;
	inset: 0;
}

.gs-case .gs-case__cta:active {
	transform: none;
}

.gs-case:active {
	transform: scale(0.99);
}

@media (hover: hover) and (pointer: fine) {
	.gs-case:hover {
		border-color: var(--gs-ink);
	}
}

/* --- division rows -------------------------------------------------------- */

.gs-case__rows {
	display: flex;
	flex-direction: column;
	gap: var(--gs-space-3);
	margin: 0;
	margin-block-start: auto;
	padding: 0;
	list-style: none;
}

.gs-case__row {
	display: grid;
	/* Fixed logo column so every row's tags start on the same line, however
	   wide the individual marks are. */
	grid-template-columns: 96px minmax(0, 1fr);
	align-items: center;
	gap: var(--gs-space-3);
	max-width: none;
}

.gs-case__brand {
	min-width: 0;
}

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

.gs-case__brand-name {
	color: var(--gs-ink);
	font-size: var(--gs-b5);
	font-weight: var(--gs-weight-medium);
}

.gs-case__tags {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.gs-case__tag {
	max-width: none;
	padding: 5px 10px;
	border-radius: 999px;
	background: var(--gs-grey-l);
	color: var(--gs-ink);
	font-size: var(--gs-b5);
	line-height: 1.3;
}

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

.gs-cases--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-cases--empty p {
	margin: 0;
	max-width: none;
}

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

@media (max-width: 767px) {

	.gs-cases {
		/* 1.2 cards in view, matching the testimonial row. Same mechanism as
		   every other width, just a different count and a tighter gap. */
		--gs-case-per-row: 1.2;
		--gs-case-gap: 6px;
	}

	/* Swap to the phone banner when one is set. */
	.gs-case__img--mobile {
		display: block;
	}

	.gs-case__img-wrap--desktop {
		display: none;
	}

	.gs-case__row {
		grid-template-columns: 80px minmax(0, 1fr);
	}
}
