/**
 * Grid with Icons — TC2 About Us "Decades Of Expertise, Simplified"
 *
 * Frames: docs/design/grid-with-icons/{desktop,tablet,mobile}.png —
 * 43782:15328 / 43324:15670 / 43324:15522. All three @1x, cropped to the
 * content box (1400 / 688 / 288 logical).
 *
 * Breakpoints are written at the token values with the token named in a comment
 * (CSS vars cannot be used in @media conditions). Mobile-first, min-width only.
 *
 * Colour tokens are `--wp--custom--color--<family>--<step>`, DOUBLE dash. There
 * is no `--wp--preset--color--primary-600` — the theme palette holds only the
 * nine `scheme-*` entries, so preset spellings fall through to their literals
 * every time (build-knowledge corrections log).
 *
 * The eyebrow is the shared `.tc-eyebrow` micro-kit in style.css. Pattern CSS is
 * glob-loaded and unconditional (§1), so it is NOT redefined here — only the two
 * scoped corrections below, exactly as brand-grid, bulleted-list, contact-form,
 * blog-archive and blog-post already do.
 *
 * @package WordPress
 * @subpackage FTM_Theme
 */

/* ── The eyebrow's two scoped corrections ───────────────────────────────────
 *
 * Sixth consumer of the same pair. The kit is right in every other respect
 * (label-medium 500, 20x4 bar) so it is not redefined.
 *
 *   - The kit paints the bar from `currentcolor`. This frame draws it at
 *     primary-600 (#123B9E, and the Figma variable is literally
 *     `color/primary/600`) against #0A205B text. Pixel-verified on desktop.png:
 *     (5,10) = #123b9e, first text ink at x=31 = #0a205b.
 *   - The kit ships `gap: 9px`, measured off the five hero frames. THIS frame
 *     draws 8 — the bar occupies x 0..19 and the label box starts at x=28.
 *
 * Both land at (0,2,0) and the kit's are (0,1,0) / (0,1,1), so these win on
 * specificity rather than on load order — which matters, because style.css is
 * every pattern stylesheet's declared dependency and therefore always loads
 * FIRST. Verified with CSS.getMatchedStylesForNode rather than assumed; two
 * rules on this project have been found losing to another rule in the same
 * file. */

.tc-grid-with-icons .tc-eyebrow {
	gap: var( --wp--preset--spacing--xsmall, 0.5rem ); /* 8 — kit ships 9 */

	/* Zeroed so the HEADING's margin alone sets the eyebrow -> H2 distance.
	   The section is `is-layout-constrained`, i.e. normal flow, so adjacent
	   sibling margins COLLAPSE TO THE LARGER of the two. The eyebrow carries a
	   16px margin-block-end, which swallowed the 8 the mobile frame draws and
	   rendered 16 — measured, not predicted: the H2 sat at y=36 against the
	   frame's y=28, and that 8px then pushed the whole grid down.

	   Desktop was RIGHT BY ACCIDENT before this: the frame wants 16 there and
	   the collapse happened to produce 16. One value being correct for the
	   wrong reason is exactly what makes the other one wrong. */
	margin-block: 0;
	color: var( --wp--custom--color--base--black, #0a205b );
}

.tc-grid-with-icons .tc-eyebrow::before {
	background-color: var( --wp--custom--color--primary--600, #123b9e );
}

/* ── Heading ────────────────────────────────────────────────────────────────
 *
 * THE PRESET RAMP IS WRONG IN THE MIDDLE, AND THAT IS THE WHOLE REASON THIS
 * BLOCK EXISTS. `heading-medium` emits
 *
 *   clamp(1.4375rem, 1.438rem + ((1vw - 0.2rem) * 1.667), 2.5625rem)
 *
 * which ramps 320 -> 1400 (solve for max: 1399.8px). Its endpoints are exactly
 * right — 23px at 320 and 41px at 1400+, both matching the frames. Its MIDDLE
 * is not: at 768 it computes 30.5px where the tablet frame draws 41.
 *
 * `Heading/Medium` and `Title/Large` are FLAT from 768 to 1920 in the Figma
 * mode variables and drop only at 320 — run get_variable_defs on each
 * breakpoint's node separately to see it. Same finding as the contact-form
 * harvest. So the ramp must END AT 768, not at 1400.
 *
 * Same formula shape WordPress itself emits, with maxViewportWidth = 768:
 *   factor = (max - min) / ((768 - 320) / 1600)  =  1.125 / 0.28  =  4.018
 * Checked at all three measured points: 320 -> 23, 768 -> 41, 1920 -> 41.
 *
 * Line-height is NOT a constant ratio either — 28/23 = 1.2174 at mobile against
 * 48/41 = 1.1707 at desktop — so it is STEPPED at `md` rather than ramped.
 * Unitless, because `line-height` must be (stylelint
 * `declaration-property-unit-allowed-list`, and it is the right rule: a
 * unitless value inherits proportionally). Exact at both measured points —
 * 23 x 1.2174 = 28.0 and 41 x 1.1707 = 48.0. Between 320 and 768 the ratio is
 * the mobile one while the size ramps, which no frame contradicts.
 *
 * `!important` is required and is J7, not a workaround: the pattern KEEPS the
 * `fontSize` attribute so the block stays a normal preset-bearing heading in
 * the editor, and WordPress emits `.has-heading-medium-font-size { font-size:
 * … !important }`. (0,2,0) + !important beats (0,1,0) + !important. */

.tc-grid-with-icons .tc-grid-with-icons__heading {
	margin-block: var( --wp--preset--spacing--xsmall, 0.5rem ) 0; /* 8 at mobile */
	font-family: var( --wp--preset--font-family--display );
	font-size: clamp( 1.4375rem, 1.4375rem + ( ( 1vw - 0.2rem ) * 4.018 ), 2.5625rem ) !important; /* 23 -> 41 over 320 -> 768 */
	font-weight: 700;
	line-height: 1.2174; /* 28 on 23 — stepped at md, see above */
	color: var( --wp--custom--color--base--black, #0a205b );
	letter-spacing: -0.02em; /* Figma declares -2 on the role; renders -0.82px on 41 */
	text-transform: capitalize; /* the frame's own transform — see the report's flag list */
}

/* 16 from `md`; the frame draws eyebrow -> heading at 8 on mobile and 16 on
   both wider boards. */
@media ( min-width: 48rem ) { /* --wp--custom--breakpoint--md */

	.tc-grid-with-icons .tc-grid-with-icons__heading {
		margin-block-start: var( --wp--preset--spacing--normal, 1rem ); /* 16 */
		line-height: 1.1707; /* 48 on 41 */
	}
}

/* ── Grid ───────────────────────────────────────────────────────────────────
 *
 * Written at (0,2,0) to beat WP's flow-layout blockGap. That rule is
 * `:root :where(.is-layout-flow) > *` — `:where()` contributes nothing, so it
 * lands at (0,1,0), the same as a bare `.tc-grid-with-icons__grid`, and a tie
 * is decided by load order. Beat it on specificity, never on order
 * (build-knowledge corrections log, heading-banner 2026-07-28).
 *
 * Row gap 40 -> 80 and column gap 24 -> 64 are all frame values:
 *   mobile  1-up, cells at y 0 / 248 / 496 / 743, each 208 tall -> row gap 40
 *   tablet  2-up, 332 cells at x 0 / 356 -> column gap 24; rows 0 / 272 -> 80
 *   desktop 2-up, 668 cells at x 0 / 732 -> column gap 64; rows 0 / 247 -> 80 */

.tc-grid-with-icons .tc-grid-with-icons__grid {
	display: grid;
	grid-template-columns: 1fr;
	gap: var( --wp--preset--spacing--xlarge, 2.5rem ); /* 40 */
	margin-block-start: var( --wp--preset--spacing--large, 1.5rem ); /* 24 at mobile */
}

@media ( min-width: 48rem ) { /* --wp--custom--breakpoint--md */

	.tc-grid-with-icons .tc-grid-with-icons__grid {
		grid-template-columns: repeat( 2, 1fr );

		/* 80 row / 24 column. 80 has no preset — the `80` step is 5.06rem and
		   `xxlarge` is 4rem — so the row gap is a literal 5rem. */
		gap: 5rem var( --wp--preset--spacing--large, 1.5rem );
		margin-block-start: 3rem; /* 48 — no preset at this step */
	}
}

@media ( min-width: 64rem ) { /* --wp--custom--breakpoint--lg */

	.tc-grid-with-icons .tc-grid-with-icons__grid {
		gap: 5rem var( --wp--preset--spacing--xxlarge, 4rem ); /* 80 row / 64 column */
	}
}

/* ── blockGap reset ─────────────────────────────────────────────────────────
 *
 * MEASURED, NOT PRECAUTIONARY. WordPress's flow layout emits
 *
 *   :root :where(.is-layout-flow) > *              { margin-block-start: 24px }
 *   :root :where(.is-layout-flow) > *:first-child  { margin-block-start: 0    }
 *
 * and every group in this pattern is `is-layout-flow`. Inside a GRID that is
 * not a gap, it is a margin on three of the four items: the first cell measured
 * top=18890 and the second top=18914, so row one was 24px out of level and the
 * row pitch was inflated by the same amount. Inside the cell it stacked on top
 * of the spacing the cell sets for itself, which is why the icon -> title and
 * title -> body distances are margins here rather than a flex `gap`.
 *
 * Zeroed at (0,2,0) — `:where()` contributes nothing, so WP's rule is (0,1,0)
 * and a bare class would only tie and lose on load order. Beat it on
 * specificity, never on order (build-knowledge corrections log, heading-banner
 * 2026-07-28).
 *
 * THIS RULE MUST STAY ABOVE the per-element margins below. They are (0,2,0)
 * too, so the tie between them is decided by source order and a reset placed
 * after would silently erase them. */

.tc-grid-with-icons .tc-grid-with-icons__grid > *,
.tc-grid-with-icons .tc-grid-with-icons__cell > * {
	margin-block: 0;
}

/* ── Cell ───────────────────────────────────────────────────────────────────
 *
 * Icon -> text is 15 at every breakpoint. The frame draws 16 on cells 1-2 and
 * 15 on cells 3-4 at tablet and mobile, and 15 on all four at desktop —
 * inconsistent WITHIN a single board, so it is a slip, not a rule (frames
 * README, D3). Shipped at 15.
 *
 * The two internal gaps differ (15 icon->title, 16 title->body), so they are
 * margins on the children rather than one flex `gap`. */

.tc-grid-with-icons .tc-grid-with-icons__cell {
	display: flex;
	flex-direction: column;
	align-items: flex-start;

	/* Frame value — the cell's text container carries `word-break: break-word`
	   (43782:15351). `anywhere` rather than `break-word` because only
	   `anywhere` reduces min-content width, which is what stops an unbreakable
	   string forcing the grid track open. Same fix, same reason, as the
	   rep-directory name block. */
	overflow-wrap: anywhere;
}

/* The icon is a fixed 56 box at every breakpoint. Both dimensions are set
   explicitly rather than left to `auto`: the SVG FILE carries its own 56x56
   `width`/`height` root attributes, but core/image's
   `figure > img { max-width: 100% }` plus a narrow grid track would otherwise
   let it shrink. `flex: none` stops the column's stretch from touching it.

   These two declarations are now the ONLY thing pinning the box. The `<img>`
   elements used to repeat the dimensions as HTML attributes and no longer do —
   they broke editor block validation, and core/image has no way to emit them.
   Reasoning in grid-with-icons.php's docblock; do not put them back. */

.tc-grid-with-icons .tc-grid-with-icons__icon {
	flex: none;
	margin: 0;
}

.tc-grid-with-icons .tc-grid-with-icons__icon img {
	display: block;
	width: 56px;
	height: 56px;
}

/* Title — same 320 -> 768 ramp as the heading, same reason, same J7 !important.
   19 -> 27 is +8 over the same 0.28 of viewport, giving factor 0.5 / 0.28 =
   1.786. Line-height is stepped at `md` rather than ramped, like the heading's
   and for the same two reasons: it must be unitless, and 24/19 = 1.2632 against
   32/27 = 1.1852 is not a constant ratio. */

.tc-grid-with-icons .tc-grid-with-icons__title {
	margin-block: 15px 0; /* icon -> title */
	font-family: var( --wp--preset--font-family--display );
	font-size: clamp( 1.1875rem, 1.1875rem + ( ( 1vw - 0.2rem ) * 1.786 ), 1.6875rem ) !important; /* 19 -> 27 */
	font-weight: 700;
	line-height: 1.2632; /* 24 on 19 — stepped at md */
	color: var( --wp--custom--color--base--black, #0a205b );
	letter-spacing: -0.02em;
	text-transform: capitalize;
}

@media ( min-width: 48rem ) { /* --wp--custom--breakpoint--md */

	.tc-grid-with-icons .tc-grid-with-icons__title {
		line-height: 1.1852; /* 32 on 27 */
	}
}

/* Body — flat 16/24 at all three breakpoints, and `body-small` is a non-fluid
   preset, so no clamp and no !important is needed for the size. The family,
   weight and colour ARE asserted: the section's body copy is `black`, not a
   muted grey, on all three boards. */

.tc-grid-with-icons .tc-grid-with-icons__body {
	margin-block: var( --wp--preset--spacing--normal, 1rem ) 0; /* 16 title -> body */
	font-family: var( --wp--preset--font-family--body );
	font-weight: 400;
	line-height: 1.5; /* 24 on 16 */
	color: var( --wp--custom--color--base--black, #0a205b );
	letter-spacing: 0;
}
