/* ═══════════════════════════════════════════════════════════════════
   PREVIOUS PROJECTS — desktop is a 3 x 3 grid (563/562/563 columns,
   330 rows, 20px gaps, outer corners square); mobile stacks the cards
   (390 x 222.53, 10px gaps) with a 52px "+" per card that becomes a
   white circle holding a red X when the card is open.

   Flex throughout - there is no display:grid in this theme.
   ═══════════════════════════════════════════════════════════════════ */

.projects-section__head { text-align: center; }
.projects-section__head .eyebrow { margin-bottom: clamp(10px, 8.54px + 0.374vw, 15px); }

/* H2 box ends 3874, grid starts 3904 (desktop) / 4506 -> 4526 (mobile) */
.projects-section__title { margin-bottom: clamp(20px, 17.09px + 0.747vw, 30px); }

/* A fixed column count, pinned with a basis computed from --per-row
   rather than left to a plain wrap. */
.projects-section__grid {
	--per-row: 3;
	--col-gap: 20px;
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var(--col-gap);
}

/* The card stacks two layers in one place: a full-width basis pulled back
   by an equal negative margin, so both start where the card starts and the
   card still measures the TALLER of them. The ::before carries the design's
   aspect ratio and the overlay sits in flow, so the row is
   max(drawn height, height the copy actually needs) - which is what stops
   the blurb being clipped in the 900-1200px band where a third of the
   viewport is shorter than the text. */
.projects-section__card {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	display: flex;
	flex: 0 1 calc((100% - (var(--per-row) - 1) * var(--col-gap)) / var(--per-row));
	min-width: 0;
}

.projects-section__card::before {
	content: "";
	flex: 0 0 100%;
	/* NOT stretched. A stretched flex item's cross size is the line's, and
	   aspect-ratio then computes the WIDTH from that height - so on a card
	   whose copy runs past the drawn ratio the spacer grew to 498px and its
	   negative margin no longer cancelled it. */
	align-self: flex-start;
	margin-right: -100%;
	aspect-ratio: 563 / 330;
}

/* Only the inner corners are rounded - the outer ones run off the viewport. */
.projects-section__card:nth-child(3n + 1) { border-radius: 0 var(--radius) var(--radius) 0; }
.projects-section__card:nth-child(3n + 2) { border-radius: var(--radius); }
.projects-section__card:nth-child(3n)     { border-radius: var(--radius) 0 0 var(--radius); }

.projects-section__image {
	position: absolute;
	inset: 0;
	z-index: -1;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.projects-section__overlay {
	position: relative;
	flex: 0 0 100%;
	margin-right: -100%;
	min-width: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	padding: 20px clamp(30px, 23.44px + 1.682vw, 53.5px);
	background: var(--red-overlay); /* rgba(204,44,50,.9) */
	color: var(--white);
	text-align: center;
	opacity: 0;
	transition: opacity .3s ease;
}

.projects-section__card.is-open .projects-section__overlay { opacity: 1; }

/* Hover and focus-within are gated on a real pointer AND on the width where the
   "+" is hidden - both halves are needed, for two different reports:

   - On a touch screen a tap leaves both sticky. The overlay stayed lit after
     the X had removed .is-open and the glyph had turned back to a "+", so the
     card looked stuck open and the next tap appeared to do nothing.
   - Below 768 the "+" is DRAWN (the mobile frame's control), so on a
     narrowed desktop window hover lit the overlay while the control still read
     "+" - two states claiming the same card. min-width matches the query below
     that hides the control, so exactly one mechanism is live at any width.

   Either way the card's state is single-valued. */
@media (hover: hover) and (pointer: fine) and (min-width: 768px) {
	.projects-section__card:hover .projects-section__overlay,
	.projects-section__card:focus-within .projects-section__overlay { opacity: 1; }
}

.projects-section__overlay > * { min-width: 0; }

/* The cap goes on the WRAPPER, not the heading inside it. The wrapper is the
   flex item `align-items: center` centres; a capped child inside a full-width
   wrapper is just a narrow block sitting at its left edge - which put the
   blurb's centre at x195 in a 683px card whose centre is 342. Design: both
   blocks 456 wide at 1728, 330 at 390. */
.projects-section__cardTitle,
.projects-section__body { max-width: min(456px, 100%); }

.projects-section__cardTitle > * { font-weight: 600; }
.projects-section__body      > * { margin-top: 10px; font-weight: 400; }

/* The "+" / "x" control - 52px at 390, 20px in from the corner. */
.projects-section__toggle {
	position: absolute;
	z-index: 2;
	top: 20px;
	right: 20px;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	border-radius: 50%;
	background: var(--red);
	transition: background-color .2s ease;
}

/* The plus is two 2px bars, 22px long (the same drawing as
   the services card's). Both are pseudo-elements of ONE box so the 45-degree
   turn into the close X rotates them together - a pseudo-element is
   transformed with its host.

   They are centred with `inset: 0; margin: auto`, NOT left to their static
   position: an absolutely positioned ::before with `left: auto` resolves to
   the END of a 22x2 host box, which drew the vertical bar 11px right of
   centre and made the glyph read as "-|" rather than "+". */
.projects-section__toggleGlyph {
	position: relative;
	width: 22px;
	height: 22px;
	transition: transform .25s ease;
}
.projects-section__toggleGlyph::before,
.projects-section__toggleGlyph::after {
	content: "";
	position: absolute;
	inset: 0;
	margin: auto;
	background: var(--white);
	transition: background-color .2s ease;
}
.projects-section__toggleGlyph::before { width: 22px; height: 2px; }
.projects-section__toggleGlyph::after  { width: 2px;  height: 22px; }

.projects-section__card.is-open .projects-section__toggle { background: var(--white); }
.projects-section__card.is-open .projects-section__toggleGlyph::before,
.projects-section__card.is-open .projects-section__toggleGlyph::after { background: var(--red); }
.projects-section__card.is-open .projects-section__toggleGlyph { transform: rotate(45deg); }

@media (min-width: 768px) {
	/* The design shows no control on desktop - hover does the work - but the
	   button stays in the tab order so the overlay is reachable by keyboard. */
	.projects-section__toggle {
		width: 1px; height: 1px; padding: 0;
		margin: -1px; overflow: hidden; background: none;
		clip-path: inset(50%);
	}
	.projects-section__toggle:focus-visible {
		width: 52px; height: 52px; margin: 0;
		clip-path: none; background: var(--red);
	}
}

@media (max-width: 1199px) {
	/* Below 1200 a third of the viewport is shorter than the blurb needs, so
	   the grid drops to two columns rather than stretching the cards. */
	.projects-section__grid { --per-row: 2; }
	.projects-section__card:nth-child(3n + 1),
	.projects-section__card:nth-child(3n + 2),
	.projects-section__card:nth-child(3n) { border-radius: var(--radius); }
	.projects-section__card:nth-child(2n + 1) { border-radius: 0 var(--radius) var(--radius) 0; }
	.projects-section__card:nth-child(2n)     { border-radius: var(--radius) 0 0 var(--radius); }

	/* A last card with nothing beside it is centred by justify-content, so neither
	   of its edges runs off the viewport - it gets all four corners. */
	.projects-section__card:last-child:nth-child(2n + 1) { border-radius: var(--radius); }
}

/* Same case on the 3-column layout: a short final row is centred, so the edges
   that would have bled off the viewport are now inside it. */
@media (min-width: 1200px) {
	.projects-section__card:last-child:nth-child(3n + 1) { border-radius: var(--radius); }
	.projects-section__card:last-child:nth-child(3n + 2) { border-radius: var(--radius); }
	.projects-section__card:nth-last-child(2):nth-child(3n + 1) { border-radius: var(--radius); }
}

@media (max-width: 767px) {
	.projects-section__grid { --per-row: 1; gap: 10px; }
	.projects-section__card { border-radius: 0 !important; } /* full-bleed rows */
	.projects-section__card::before { aspect-ratio: 390 / 222.53; }
	.projects-section__cardTitle,
	.projects-section__body { max-width: min(330px, 100%); }
	/* A closed card is just its photograph, and the design draws every one of
	   them at the same 222.53. Taking the invisible
	   overlay out of flow is what holds that: in flow, a long blurb made an
	   unopened card 60px taller than its neighbours. It goes back into flow
	   when opened, so the copy is still never clipped. */
	.projects-section__overlay {
		position: absolute;
		inset: 0;
		/* The base rule's -100% pull is for a flex item. On an absolutely
		   positioned box left/right/margin are over-constrained, so `right` is
		   dropped instead and the used width became 2x the card. */
		margin-right: 0;
	}
	.projects-section__card.is-open .projects-section__overlay {
		position: relative;
		inset: auto;
	}

	/* Mobile is the only frame that shows the control, and a full-width title
	   would run under it - so the copy is centred in what is left BELOW the
	   button, not in the whole card. Both insets come straight off the frame:
	   72 at the top is where the title starts, which is also the
	   button's bottom edge (20 + 52), and 48.5 at the foot is where the blurb
	   ends. At 390 that leaves the copy exactly the height it is
	   drawn at, so centring lands on the frame's own position; on a taller card
	   it shares the extra height instead of pooling all of it at the foot -
	   188px of it on a 683px card, which is what flex-start did. */
	.projects-section__overlay {
		padding: calc(20px + 52px) 30px 48.5px;
	}
}
