/**
 * css/components/template-work.css — Website 2.0 Work portfolio landing
 * reskin (#62)
 *
 * template-work.php-scoped styles for the Work landing hero (`.cg-work-
 * hero`), text split (`.cg-work-split`, thin wrapper around the shared
 * `.cg-split`/`.cg-eyebrow`/`.cg-statement` primitives), the work-tile
 * grid (`.cg-work-grid`/`.cg-work-tile`, matching the `.cg-latest-work`
 * tile look shipped with the single-work case-study reskin, #63/#64) and
 * the related/latest-articles grid (`.cg-work-articles__grid`).
 *
 * No dedicated design HTML exists for this landing template (11 SEO
 * agency-landing Pages share it) — per docs/2.0-system-guide.md §8
 * ("don't guess the design"), this extrapolates the already-shipped
 * system (tokens, `.cg-band`/`.cg-split`/`.cg-eyebrow`/`.cg-statement`,
 * the `.cg-latest-work` tile's ink-scrim caption pattern) rather than
 * inventing new visual language.
 *
 * `.grid-items`/`.grid-items-section` (blocks/work_content/work.php) are
 * SHARED with blocks/social_impact_content/image_grid.php — every
 * selector below that touches them is scoped under the work-grid-only
 * `.js-ajax-items-holder` ancestor (present only on this template's
 * markup) so nothing here leaks onto the Social Impact page. Similarly
 * `.cg-work-tile__img`/`.cg-work-grid` etc. are NEW classes (added
 * alongside, never replacing, the legacy `.grid-items` class per
 * docs/2.0-system-guide.md §5.2), each qualified with the
 * `.js-ajax-items-holder` ancestor purely so its 2-class specificity
 * always beats the single-class-or-class+tag legacy `.grid-items …`
 * rules in style.css regardless of source order (same technique as
 * template-single-work.css's `.banner-img-section .cg-case-hero__holder`
 * override).
 *
 * Tokens only — no raw hex, no @layer, no !important. The one exception
 * (documented inline) is the `rgba(14, 14, 12, …)` scrim gradient, which
 * matches the literal precedent already shipped in
 * template-single-work.css `.cg-latest-work__ov` (#63) — `--cg-ink` is
 * `#0E0E0C` = `rgb(14, 14, 12)`, so this is that same token's channel
 * values used in a gradient stop where a solid `var(--cg-ink)` can't
 * express the fade.
 */

/* ------------------------------------------------------------------ *
 * Hero (blocks/work_content/intro.php)
 * ------------------------------------------------------------------ */

.cg-work-hero {
	overflow: hidden;
}

/* #347: brand-black surface for the hero band (docs/design/07-work-
   collection-redesign.md §1). This was the base surface under the hero
   media; #348 removed the media entirely, so it is now simply the band. */
.cg-work-hero--ink {
	background: var( --cg-ink );
}

/*
 * #348: two columns of text on ink, no media — the Figma's frame `499:1090`
 * (docs/design/07-work-collection-redesign.md §2). The media, scrim and
 * absolutely-positioned overlay body that used to live here are gone with
 * the markup that carried them; there is nothing left to sit over, so the
 * text is in normal flow.
 *
 * THE HERO SHARES THE GRID'S FRAME. It used to size its columns as
 * percentages of the whole viewport, which reproduced the 1920 measurements
 * exactly and then kept growing: at 2560 the headline sat at x192 and the
 * hairline ran to x1987 while the grid below stayed capped at its centred
 * 1682 — the two drifted visibly apart and the hero escaped the content
 * guardrails entirely. Both now share one `max()` frame, so they cap
 * together and stay aligned at any width.
 *
 * Geometry inside that 1682 frame, from the Figma (frame-relative, i.e. the
 * measured page x minus the grid's own 108 inset):
 *
 *    36 / 1682 =  2.1403%  → the headline's inset from the frame edge
 *   924 / 1682 = 54.9346%  → headline column
 *   563 / 1682 = 33.4721%  → hairline + body column
 *
 * The 159px that remains to the right is the design's own margin (the rule
 * ends at 1631, the grid frame at 1790) and is deliberately not symmetric
 * with the left inset — the design hangs the right column off the headline,
 * not off the page edge.
 */
.cg-work-hero--text .cg-work-hero__inner {
	display: grid;
	grid-template-columns: 2.1403% 54.9346% 33.4721%;
	align-items: start;
	/* Same frame as `.cg-work-grid-section` — keep the two in step. */
	padding-inline: max( clamp( 24px, 5vw, 84px ), calc( ( 100vw - 1682px ) / 2 ) );
	/*
	 * Vertical rhythm from the frame, with the header's 101px subtracted (the
	 * Figma draws its own mocked top bar, which we do not ship):
	 *
	 *   eyebrow y231 − 101 = 130px above the lockup   (130/1920 = 6.77vw)
	 *   grid    y581 − body bottom ≈411 = 169px below (169/1920 = 8.802vw)
	 *
	 * The BOTTOM half is why the gap was nearly double the design's: the grid
	 * band brings its own `--section-pad` and the list its own `margin-top`,
	 * so a bottom padding sized as if it owned the whole gap stacked on top
	 * of them (measured 404px against the design's 204px). Those two are
	 * zeroed below and this owns the gap outright.
	 */
	padding-block: clamp( 48px, 6.77vw, 130px ) clamp( 56px, 8.802vw, 169px );
}

/*
 * One source for the heading's size: the hairline's offset above is derived
 * from it, so the two cannot drift apart when the clamp is retuned.
 */
.cg-work-hero--text {
	--cg-wh-h1: clamp( 40px, 6.2859vw, 120.69px );
}

/*
 * TWO ROWS: the eyebrow sits alone above, the headline and the aside share
 * the second one. Putting them on the same row is what lets the hairline
 * track the headline instead of the column top — with the eyebrow inside a
 * wrapper the aside started at the wrapper's top and the alignment drifted
 * with the eyebrow's own height (measured 9px out at 1920, 2px at 1440, 0 at
 * 1280). It also means the 4 pages with no eyebrow need no special case: the
 * first row simply collapses to nothing.
 */
.cg-work-hero--text .cg-work-hero__eyebrow {
	grid-row: 1;
	grid-column: 2;
}

.cg-work-hero--text .cg-work-hero__title {
	grid-row: 2;
	grid-column: 2;
}

.cg-work-hero--text .cg-work-hero__aside {
	grid-row: 2;
	grid-column: 3;
	/*
	 * Drop the hairline onto the TOP OF THE PAINTED CAPITALS, not the top of
	 * the heading's box.
	 *
	 * This offset is derived, not eyeballed. For an inline box, the first
	 * baseline sits at `half-leading + ascent` below the line box's top, and
	 * the capitals start one cap-height above that baseline:
	 *
	 *   offset = (line-height − (ascent + descent)) / 2 + ascent − cap-height
	 *
	 * Tungsten Narrow, measured off the rendered face via canvas TextMetrics:
	 * ascent .960em, descent .240em, cap-height .700em, and this heading's
	 * unitless line-height is .8854. So:
	 *
	 *   (.8854 − 1.200) / 2 + .960 − .700 = −.1573 + .260 = +.103em
	 *
	 * POSITIVE — the capitals paint BELOW the box top, not above it. A short
	 * line-height pulls the box's top DOWN past the ascender, but not as far
	 * as the cap line. An earlier revision had this as −.166em, reasoning the
	 * caps overhung the box; that put the rule 32.5px high at 1920 and 21.7px
	 * at 1280 (it scales with the headline, so it looked close at small
	 * widths and wrong at large ones).
	 *
	 * Every term is a ratio of the font's own metrics, so expressing it
	 * against `--cg-wh-h1` holds at every step of the clamp. Verified level to
	 * within 1px at 1024, 1280, 1440, 1920 and 2560, on a page with an eyebrow
	 * and one without.
	 */
	margin-top: calc( 0.103 * var( --cg-wh-h1 ) );
	/*
	 * Freeze the column at its measured 1920 width, exactly as the headline's
	 * font-size is capped. Without it the rule keeps growing with the viewport
	 * while the 552px paragraph does not, so the hairline detaches from the
	 * copy it belongs to — 750px of rule over 552px of text at 2560. The 11px
	 * overhang at 1920 is the design's; anything beyond that is drift.
	 */
	max-width: 563px;
}

/* Figma: eyebrow y231, H1 y270 — 39px of air under the eyebrow's baseline
   box. Reuses the sitewide `.cg-eyebrow` for face, size, tracking and rust. */
.cg-work-hero__eyebrow {
	margin: 0 0 clamp( 10px, 1.15vw, 22px );
}


/*
 * Owns its own type styling entirely (font-family/weight/size/line-height/
 * letter-spacing) rather than combining with the generic `.h1` utility —
 * see the docblock in blocks/work_content/intro.php for why.
 *
 * 120.69 / 1920 = 6.2859vw, capped at the measured value so it never
 * exceeds the design above 1920. Line-height is unitless (106.86 / 120.69
 * = 0.8854) so the 1920 measurement holds at every size.
 */
.cg-work-hero__title {
	/* #399 — minus 20% of the box's own width; see the note in hero.css.
	   Percentage rather than px because this box scales 712px -> 924px
	   between 1440 and 1920. Released back to `none` below 680px, in the
	   media block directly after this rule. */
	max-width: 80%;
	/* #399 — same reason as the hero titles: keep the narrowed box from
	   stranding a word on the last line. No line-count change. */
	text-wrap: balance;
	margin: 0;
	font-family: var( --h1-font-family );
	font-weight: 700;
	font-size: var( --cg-wh-h1, clamp( 40px, 6.2859vw, 120.69px ) );
	line-height: 0.8854;
	letter-spacing: normal;
	text-transform: uppercase;
	color: var( --cg-white );
}

/*
 * #399 — released at 820px, this hero's own single-column breakpoint (the
 * `@media (max-width:820px)` block below switches `.cg-work-hero__inner` to
 * `display:block`). Same reasoning as the hero release in hero.css: once
 * the headline owns the full row there is no right-hand side to take 20%
 * off, and 80% would just leave a dead gutter beside a full-width rule.
 *
 * This selector has no base-rule counterpart to fall back on (unlike
 * `.cg-hero__title`), so without an explicit release the 80% would apply at
 * every width, including phones.
 */
@media ( max-width: 820px ) {
	.cg-work-hero__title {
		max-width: none;
	}
}

.cg-work-hero__rule {
	display: block;
	width: 100%;
	height: 1px;
	background: var( --cg-white );
	/* Figma: body top edge sits 42px below the hairline. */
	margin-bottom: 42px;
}

.cg-work-hero__desc {
	max-width: 552px;
	font-family: var( --font-body );
	font-weight: 400;
	/* 16px, not 14px (#398) — the same reviewer rule applied to `.cg-hero__lede`
	   in hero.css. This namespace is separate on purpose (blocks/cg/work-header.php),
	   so the change has to be made in BOTH files or the four Work pages silently
	   stay at 14px — which is where 4 of the 10 comments came from. */
	font-size: 16px;
	line-height: 1.7; /* 16 × 1.7 = 27.2px */
	color: var( --cg-white );
}

/*
 * Placeholder copy, marked the simple way: the copy itself is wrapped in
 * `<span class="cg-tmp-copy">` in the field value, so it reads as obviously
 * unfinished and an editor deletes the marker WITH the text when the real
 * copy is pasted in — nothing to remember to clean up afterwards, and no
 * detector to keep in step with the content.
 *
 * (This replaces the borrowed `.cg-placeholder` auto-marker, whose full
 * yellow-block-and-badge treatment was heavier than this surface wants.)
 */
.cg-work-hero__desc .cg-tmp-copy,
.cg-work-hero__eyebrow .cg-tmp-copy {
	color: var( --cg-yellow );
}

/* Stack: headline, rule, paragraph — one column inside the standard gutter. */
@media ( max-width: 820px ) {

	.cg-work-hero--text .cg-work-hero__inner {
		display: block;
		padding-inline: var( --pad-x );
	}

	.cg-work-hero--text .cg-work-hero__aside {
		/* Stacked — the hairline is a divider under the headline again, not a
		   rule beside it, so the ink-top pull does not apply. */
		margin-top: 0;
		padding-top: 28px;
	}

	.cg-work-hero__desc {
		max-width: none;
	}
}

/* ------------------------------------------------------------------ *
 * Text split (blocks/work_content/text.php)
 * ------------------------------------------------------------------ */

.cg-work-split .cg-split__body :where( p ) {
	margin: 0 0 22px;
}

.cg-work-split .cg-split__body :where( p ):last-child {
	margin-bottom: 0;
}

/* ------------------------------------------------------------------ *
 * Work-tile grid (blocks/work_content/work.php + blocks/content-work.php)
 *
 * Grid columns per #62 Visual Expectations: 3-up desktop, 2-up tablet,
 * 1-up mobile. Tile look matches `.cg-latest-work__tile` (template-
 * single-work.css, #63/#64) — fixed aspect-ratio crop, object-fit:cover,
 * ink gradient scrim, uppercase term-tag label + serif title caption —
 * reimplemented as its own component (not the literal `.cg-latest-work__*`
 * classes) because this tile is the `<li class="js-item">` AJAX-contract
 * card reused across every landing page's grid, not single-work.php's
 * one-off "Our latest work" band.
 * ------------------------------------------------------------------ */

/*
 * #349: the grid runs wider than the rest of the site. The Figma frame's
 * insets are asymmetric (108 left, 130 right at 1920); a centered 1682px
 * container reproduces every measured column width (542) and every gap (28)
 * exactly, which the asymmetry does not, so that is what ships.
 *
 * `max()` against the standard gutter means this only ever widens the frame
 * — below 1682 the second term goes negative and the normal
 * `clamp(24px, 5vw, 84px)` gutter wins, so nothing changes at tablet or
 * phone. Overrides `.cg-band`'s `padding-inline: var(--pad-x)` (band.css:18),
 * which is the 1314 frame.
 *
 * 1682 − 2×28 gap = 1626 / 3 = 542 per column, and (1920 − 1682) / 2 = 119
 * to the first column's left edge.
 */
.cg-work-grid-section.cg-band {
	padding-inline: max( clamp( 24px, 5vw, 84px ), calc( ( 100vw - 1682px ) / 2 ) );
	/*
	 * The hero's bottom padding is the designed gap in full. Leaving
	 * `--section-pad` here as well stacked a second gap on top of it and put
	 * 404px between the headline and the first tile where the design asks
	 * for 204. The band keeps its bottom padding.
	 */
	padding-top: 0;
}

.js-ajax-items-holder .grid-items.cg-work-grid {
	display: grid;
	grid-template-columns: repeat( 3, 1fr );
	gap: 28px;
	/* Zeroed with the band's top padding above — the hero owns the gap. */
	margin-top: 0;
}

.js-ajax-items-holder .grid-items.cg-work-grid li.js-item {
	width: auto;
	padding-top: 0;
	position: static;
	overflow: visible;
}

.js-ajax-items-holder .cg-work-tile {
	display: block;
	position: relative;
	width: auto;
	height: auto;
	top: auto;
	left: auto;
	overflow: hidden;
	/* #349: 541 × 404 in the frame — 4:3, shallower than the old near-square. */
	aspect-ratio: 4 / 3;
	background: var( --cg-ink-85 );
	text-decoration: none;
}

.js-ajax-items-holder .cg-work-tile__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	filter: none;
	transition: transform 0.6s cubic-bezier( 0.16, 1, 0.3, 1 );
}

.js-ajax-items-holder .cg-work-tile:hover .cg-work-tile__img {
	filter: none;
	transform: scale( 1.04 );
}

.js-ajax-items-holder .cg-work-tile__ov {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	/* #349: shorter and lighter than #62's 150px @ .86. The rgba() literals
	   are `--cg-ink` (#0E0E0C) channel values — a gradient stop cannot take a
	   solid token and still fade, the same documented exception as the file
	   header notes for the original scrim. */
	height: 93px;
	background: linear-gradient( 180deg, rgba( 14, 14, 12, 0 ) 0%, rgba( 14, 14, 12, 0.8 ) 100% );
	pointer-events: none;
}

.js-ajax-items-holder .cg-work-tile__cap {
	position: absolute;
	/* #349: caption sits 25px in from the tile's left edge. */
	left: 25px;
	right: 25px;
	bottom: 28px;
	z-index: 2;
}

.js-ajax-items-holder .cg-work-tile__lbl {
	display: block;
	margin: 0;
	font-family: var( --font-sans );
	font-weight: 700;
	font-size: 10px;
	line-height: 1.6; /* 10 × 1.6 = 16px */
	letter-spacing: 2.2px;
	text-transform: uppercase;
	/* Spec says #F5F3EE; the shipped `--cg-cream` is #F5F5F5 — within 7/255 on
	   every channel, and a token beats a raw hex (CLAUDE.md 2.0 conventions).
	   The 0.82 opacity from #62 is dropped: the frame draws this label solid. */
	color: var( --cg-cream );
}

.js-ajax-items-holder .cg-work-tile__name {
	display: block;
	margin: 8px 0 0;
	font-family: var( --font-serif );
	font-weight: 400;
	font-size: 28px;
	line-height: 1.25; /* 28 × 1.25 = 35px */
	letter-spacing: -0.56px;
	color: var( --cg-cream );
}

@media ( max-width: 1024px ) {
	.js-ajax-items-holder .grid-items.cg-work-grid {
		grid-template-columns: 1fr 1fr;
	}
}

@media ( max-width: 680px ) {
	.js-ajax-items-holder .grid-items.cg-work-grid {
		grid-template-columns: 1fr;
	}
}

/* ------------------------------------------------------------------ *
 * Related / latest-articles grid (blocks/work_content/related_articles.php,
 * blocks/work_content/latest_posts.php)
 *
 * Card itself (`.article-item`, blocks/content.php) is left legacy-styled
 * — shared with the not-yet-reskinned blog templates (#67), out of scope.
 * ------------------------------------------------------------------ */

.cg-work-articles__grid {
	display: grid;
	grid-template-columns: repeat( 3, 1fr );
	gap: 48px;
	margin-top: 44px;
}

@media ( max-width: 1024px ) {
	.cg-work-articles__grid {
		grid-template-columns: 1fr 1fr;
	}
}

@media ( max-width: 680px ) {
	.cg-work-articles__grid {
		grid-template-columns: 1fr;
	}
}
