/*
 * Split Hero — firsttracks-theme/hero-split
 *
 * Solid primary-700 from the left, fading into a right-side image or video.
 * The fade seam sits at the CONTENT COLUMN'S RIGHT EDGE — measured at x950 of
 * 1920 in both desktop frames, and (wide-column edge 260 + column width 688)
 * is 948, so the seam is derived from the column, not written as 49.3%.
 *
 * ⚠ CORRECTED 2026-09-05 — "NO BELOW-DESKTOP COMPS EXIST" WAS FALSE, AND THE
 * BEHAVIOUR BUILT ON IT IS GONE. This banner used to say "Below lg: media and
 * fade hidden, solid band remains — B1 default … No below-desktop comps exist
 * (Our Team tablet/mobile are gray wireframes)". The Our Team half is still
 * true. The claim was never checked against ENGINEERING, which has both:
 * tablet 43324:16028 draws a full-bleed 768x512 image below the content at
 * y497, and smartphone 43324:15862 (hero 43324:15925) a gutter-inset 288x192
 * at y252. Both are 3:2, which is why one aspect-ratio serves both.
 *
 * So below lg the media now STACKS UNDER THE CONTENT. The fade stays hidden —
 * neither sub-lg frame draws one, and there is nothing to fade over once the
 * media is out of the band.
 *
 * ⚠ SUPERSEDED 2026-09-28 BY GARY'S Q10, WHICH CLOSES D-A. "The gradient will
 * swap from left-right to top-bottom … get rid of the extra padding around the
 * image on tablet and mobile … background image appear full-width and
 * bottom-aligned to the pattern." Below lg the media is now edge to edge at
 * EVERY width (not only md), flush with the hero's bottom edge (no band
 * padding under it, no gap above it), and faded top-to-bottom out of the navy
 * band. The Engineering sub-lg frames are wireframe-tier on this point — grey
 * placeholder, no gradient — so the fade is the desktop one turned 90°: solid
 * primary-700 up to the media's leading edge, one linear ramp, clear at the far
 * edge. The navy band is now the ruled colour, not a deviation.
 *
 * WHAT WAS A DEFAULT, AND WAS DESIGNER ITEM D-A (closed by Q10 above). Both sub-lg frames
 * also drop the navy band — tablet is #ffffff with no band at all, smartphone
 * is neutral-100 #E9ECEF, and both draw navy ink, a primary-600 eyebrow bar, a
 * primary-600 CTA and NO green highlight. This file deliberately keeps
 * primary-700 and white ink at every width, because hero-basic was
 * frame-verified at four breakpoints on the CLIENT boards and is primary-700 at
 * 320 and 768 (hero-basic.css:13-15), and because the two Engineering frames
 * disagree with each other about the ground. Layout from the frames, colour
 * from the family. DECISIONS 2026-09-05.
 *
 * WHAT THIS FILE DOES NOT USE, and why. The handoff was written against the
 * `--ftps-hero-fade-*` starter, class `.ftps-hero-split-fade`. Those custom
 * properties are real — `--ftps-hero-fade-color`, `-angle`, `-solid-stop`,
 * `-end-stop`, recorded in docs/environment-facts.md §6.
 *
 * ⚠ CORRECTED 2026-08-06 — THE REASON THEY ARE UNUSED HAS CHANGED, AND THE
 * FILE PATH WAS WRONG. This banner used to say "the page-section block ships
 * unbuilt, so the stylesheet is never enqueued and none of them have a
 * consumer", citing pattern-covers.css. At ftm-blocks 3.0.0-beta.4 the block
 * IS built and the stylesheet IS enqueued
 * (blocks/page-section/build/style-style.css; pattern-covers.css and the whole
 * src/ directory no longer exist). The four properties are shipped and would
 * resolve — but they are scoped to `.ftps-hero-split-fade`, and NOTHING on
 * this site carries that class. Measured 2026-08-06 at 1920/768/320, this
 * hero's cover carries `ftps-hero-fullbleed`, and all four `--ftps-hero-fade-*`
 * compute (undefined) on it.
 *
 * So the gradient below is still painted by this pattern, contract-free, for
 * the same practical outcome and a different reason — and adopting the starter
 * is now a real option rather than an impossible one. build-knowledge §17.
 *
 * Everything dimensional here was set by measuring the two frames at a
 * normalised 2x scale (build-knowledge §16), not by eye.
 *
 * Breakpoints written at token values (CSS vars are invalid in @media):
 *   48rem = breakpoint/md · 64rem = breakpoint/lg
 *
 * @package tonercable-2026
 */

.tc-hero-split {
	/* Comp content column: 688px = 43rem, identical to hero-overlay's. */
	--tc-hero-split-column: 43rem;

	/*
	 * Fade geometry. Solid to the CONTENT COLUMN'S right edge, then a linear
	 * ramp to clear.
	 *
	 * The seam is derived, not written as 49.3%: it is the column's left edge
	 * (the wide-size edge once the viewport allows it, the gutter below) plus
	 * the column width. At 1920 that is 260 + 688 = 948, and both frames put
	 * the seam at 950.
	 *
	 * The `100%` here is deliberate and only correct in this position. Both
	 * consumers — the background span and the cover's media, each absolutely
	 * positioned with inset 0 — resolve percentages against the cover's PADDING
	 * box, which is the full 1920. A percentage in the cover's own
	 * `padding-inline` would NOT: it resolves against the containing block,
	 * which is the 1840px constrained wrapper this full-aligned section breaks
	 * out of, and it measured 220 instead of 260 when this file first tried it.
	 *
	 * The end stop is the RIGHT EDGE, 100%, read off the node's own fill.
	 * Both desktop heroes (43657:7159, 43883:25744) carry
	 * `linear-gradient(-90deg, rgba(10,32,91,0) 0%, primary-700 50.677%)`:
	 * solid at x947, one linear ramp, clear only at x1920.
	 *
	 * ⚠ CORRECTED 2026-09-26 — this was 88%, read by eye off the export ("the
	 * photo is still visibly tinted at x3392 of 3840 and reads natural past
	 * it"). The tail of a linear ramp is low-alpha, so the eye calls it clear
	 * early: at x1690, where 88% put clear, the frame is still ~24% navy, and
	 * the build painted the whole media zone lighter than the comp.
	 * docs/reports/hero-gradient-plan.md, G-1.
	 */
	--tc-hero-split-inset: max( 2.5rem, ( 100% - var( --wp--style--global--wide-size, 1400px ) ) / 2 );
	--tc-hero-split-seam: calc( var( --tc-hero-split-inset ) + var( --tc-hero-split-column ) );
	--tc-hero-split-fade-end: 100%;

	/* Carried so the geometry converges if the plugin ever ships its build. */
	--ftps-hero-min-height: 0px;

	/*
	 * Frame band is exactly 600 tall at lg with the content optically centred
	 * (ink 154 above, 151.5 below in Our Team). Below lg there is no comp; the
	 * band is padded on the family's 5rem hero rhythm and shrink-wraps.
	 *
	 * 5rem is a documented one-off: the spacing scale has no 80px step
	 * (xlarge 40, xxlarge 64, xxxlarge clamp 48→96 — environment-facts fact 1).
	 *
	 * ⚠ CORRECTED 2026-09-05: 5rem is the md-and-up value, not the base one.
	 * The smartphone frame pads the band 40 top and 40 bottom — Content Section
	 * at y40 inside a 484-tall Frame 143 whose media ends at y444 — and 40 IS a
	 * preset. The band arithmetic closes exactly at 40+188+24+192+40 = 484.
	 */
	padding-block: var( --wp--preset--spacing--xlarge );
	padding-inline: var( --wp--style--root--padding-left, 1rem ); /* the page grid below the wide column (16 at 320; QA batch D, V-G1); md raises it to 40 */
	background-color: var( --wp--custom--color--primary--700 );
}

/* ── The section wrapper's own paint — review-batch-6 ────────────────────────
 *
 * THE WRAPPER AND THE PATTERN DISAGREED ON THE BAND COLOUR, AND THE DISAGREE-
 * MENT WAS INVISIBLE. `ftm/page-section` carries `ftm-scheme-primary`, and
 * `.page-section[class*=ftm-scheme-]` paints `var(--ftm-scheme-bg)`, which this
 * theme re-points to primary-800 #0A205B (page-sections-schemes.css:39-43). The
 * cover inside it paints primary-700 #0E2E7D, which is what both frames draw.
 * Measured at 1920 on /engineering/ and /pattern-library/: wrapper
 * rgb(10,32,91), cover rgb(14,46,125), and the two boxes are the same 1920x600
 * — so the wrong one is completely covered by the right one.
 *
 * ⚠ "Invisible" is not "harmless", and this pattern has the receipts. The
 * testimonial photo's 4.34px shortfall at 1920 was invisible too, and the same
 * defect was 86.44px at 1280 (testimonial-callout.css). A colour that is only
 * hidden because two boxes happen to be coincident becomes a visible seam the
 * first time the cover gains a radius, an inset or a margin — none of which is
 * a colour change, so nobody would look here.
 *
 * WRITTEN AS `:has()` RATHER THAN A CLASS ON THE PAGE-SECTION BLOCK, and that
 * is the whole reason for the shape. This pattern is INLINED into /engineering/
 * (tools/create-engineering-page.php) and into /pattern-library/, so a new
 * class in hero-split.php would not exist on either copy until both were
 * re-seeded — a fix that ships green and reaches no rendered page. A selector
 * reaches what is already in the database.
 *
 * `.ftm-scheme-primary` IS IN THE SELECTOR ON PURPOSE, TWICE OVER. It takes
 * this to (0,3,0), which beats `.page-section[class*=ftm-scheme-]` at (0,2,0)
 * on specificity rather than on the glob order that would otherwise settle a
 * tie (§5a). And it gates the rule on the condition that creates the problem:
 * with no scheme class the wrapper paints nothing, there is no second colour,
 * and this rule correctly stops matching.
 *
 * ⚠ VERIFY THIS BY MEASURING, NOT BY READING. A `:has()` selector that misses
 * fails silently — valid, compiled, and never applied — and the tell is a
 * measurement that comes back byte-identical (build-knowledge, T-AP-1
 * 2026-09-01). The cover is a DIRECT child of the section on both pages that
 * ship it; measured after this rule, the wrapper reads rgb(14,46,125).
 * ───────────────────────────────────────────────────────────────────────── */

.page-section-hero.ftm-scheme-primary:has( > .tc-hero-split ) {
	background-color: var( --wp--custom--color--primary--700 );
}

/*
 * Core sets `margin:0; width:auto` on the inner container of a cover with a
 * custom content position, from a doubled .has-custom-content-position selector
 * at (0,5,0) — hence the doubled classes in the second selector. Restated here
 * because the starter rule that used to do it never loads; same shape, same
 * values and same reason as hero-overlay's copy.
 *
 * `--ftps-max-width-wide` is undefined rather than empty, so the var() fallback
 * chain does reach the theme's 1400px wide size (measured: 1400 at x260 on a
 * 1920 viewport, matching both frames).
 */

.wp-block-cover.tc-hero-split .wp-block-cover__inner-container,
.wp-block-cover.tc-hero-split.tc-hero-split.has-custom-content-position.has-custom-content-position .wp-block-cover__inner-container {
	margin-inline: auto;
	width: 100%;
	max-width: var( --ftps-max-width-wide, var( --wp--style--global--wide-size, 1400px ) );
}

.tc-hero-split .tc-hero-split__content {
	max-width: var( --tc-hero-split-column );
}

/*
 * The fade SPAN is hidden below lg. The span is absolutely positioned over the
 * whole cover, so a vertical gradient on it would need the seam — the media's
 * top edge — as a stop, and that edge moves with the copy above it. Below lg
 * the same fade is a mask on the media instead (Q10, stacked block below),
 * whose own box IS the ramp's extent.
 */

.tc-hero-split .wp-block-cover__background {
	display: none;
}

/*
 * ── STACKED MEDIA, BELOW LG ─────────────────────────────────────────────────
 *
 * Written as a max-width query, against this file's mobile-first habit,
 * DELIBERATELY. Core positions the media `absolute; inset: 0; height: 100%`
 * (.wp-block-cover .wp-block-cover__image-background, (0,2,0), cover/style.css)
 * and puts it FIRST in the DOM — img, then the background span, then the inner
 * container — so putting it in flow renders it ABOVE the content, not below.
 * Undoing that takes five reversals plus a flex-direction and align-items
 * change on the cover, and doing it mobile-first would mean undoing all seven
 * again inside the lg block. The lg block is frame-verified and spec-frozen;
 * it is left byte-identical instead. 63.9375rem as "below lg" is the house
 * idiom — heading-banner.css:9 and product-grid.css:15 both use it.
 *
 * Selectors are (0,3,0) — doubling the cover class — so they BEAT core rather
 * than tie it and depend on load order (build-knowledge §5a).
 */

@media (max-width: 63.9375rem) { /* below breakpoint/lg */
	/*
	 * `is-position-center-left` gives the cover `align-items: center`, which in
	 * a column flex box centres HORIZONTALLY and shrink-wraps both children to
	 * their content width. `stretch` is what makes the media full width and the
	 * content column reach its own max-width. `justify-content: flex-start`
	 * from the same core rule is already correct in column — content on top.
	 */

	/*
	 * Q10 — the media is bottom-aligned to the pattern, so the band pays no
	 * padding under it. `space-between` keeps it on the bottom edge even if the
	 * cover is ever given a min-height taller than content + media (core's
	 * justify-content is flex-start, which would float it mid-band).
	 */

	.wp-block-cover.tc-hero-split {
		flex-direction: column;
		align-items: stretch;
		justify-content: space-between;
		padding-block-end: 0;
	}

	/*
	 * Frame media boxes are 288x192 at 320 and 768x512 at 768. BOTH ARE 3:2, so
	 * one aspect-ratio serves both breakpoints. `object-fit: cover` is core's
	 * and is kept: the box is fixed, the upload is not.
	 *
	 * Q10 — full width at every sub-lg width: the band's inline padding (1rem
	 * here, 40 from md, below) is paid back as a negative margin, and core's
	 * `overflow: clip` on the cover keeps it off the document scroll width. No
	 * top margin: the 24/36 content→media gap was the media-content spacing Gary
	 * named, and the fade's opaque top now provides the separation.
	 *
	 * THE FADE is the desktop gradient turned 90°. Desktop: primary-700 solid to
	 * the seam, which is the media's leading edge, then one linear ramp to clear
	 * at 100%, the media's far edge. Here the seam is the media's TOP edge and
	 * 100% its bottom, so the ramp spans exactly the media box — written as an
	 * alpha mask over the band's own primary-700 rather than a navy overlay,
	 * which composites identically (a·photo + (1−a)·navy) and needs no stop that
	 * depends on the copy above. Same construction hero-overlay uses below lg.
	 */

	.wp-block-cover.tc-hero-split .wp-block-cover__image-background,
	.wp-block-cover.tc-hero-split .wp-block-cover__video-background {
		display: block;
		position: static; /* core: absolute + inset 0 */
		order: 2; /* the media is FIRST in the DOM; this is the whole fix */
		width: calc( 100% + 2 * var( --wp--style--root--padding-left, 1rem ) ); /* the band's gutter, both sides */
		height: auto; /* core: 100% */
		aspect-ratio: 3 / 2;
		margin-block-start: 0;
		margin-inline: calc( -1 * var( --wp--style--root--padding-left, 1rem ) );
		object-fit: cover;
		mask-image: linear-gradient( to bottom, transparent 0%, #000 100% );
	}
}

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

	.tc-hero-split {
		padding-block: 5rem;
		padding-inline: 2.5rem;
	}
}

@media (min-width: 48rem) and (max-width: 63.9375rem) { /* md only */
	/*
	 * The same full bleed against md's 40px band padding. Until Q10 this was
	 * md-only, because the smartphone frame inset the media to the gutter; Gary
	 * ruled full width at both, so only the amount paid back differs now. The
	 * frame's 36 content→media gap went with the same ruling (base block).
	 */

	.wp-block-cover.tc-hero-split .wp-block-cover__image-background,
	.wp-block-cover.tc-hero-split .wp-block-cover__video-background {
		width: calc( 100% + 2 * var( --wp--preset--spacing--xlarge ) );
		margin-inline: calc( -1 * var( --wp--preset--spacing--xlarge ) );
	}
}

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

	.tc-hero-split {
		--ftps-hero-min-height: 600px;

		min-height: var( --ftps-hero-min-height );
	}

	/*
	 * Media occupies the band from the seam rightward — 970 of 1920, the same
	 * 50.5% the frames measure. Left-anchoring it there rather than running it
	 * full-bleed keeps the photograph's composition where the comp puts it;
	 * the gradient then only has to fade over the part that is actually visible.
	 */

	.tc-hero-split .wp-block-cover__image-background,
	.tc-hero-split .wp-block-cover__video-background {
		display: block;
		left: auto;
		right: 0;
		width: calc( 100% - var( --tc-hero-split-seam ) );
	}

	/*
	 * The fade rides on the cover's own background span (dimRatio 100), the
	 * construction the starter uses and hero-overlay verified: core paints that
	 * span black at (0,3,0) via
	 * `.wp-block-cover .has-background-dim:not([class*="-background-color"])`,
	 * so the doubled cover class out-ranks it without !important.
	 *
	 * ⚠ 2026-09-26 — it DOES need !important, against a different opponent.
	 * Core writes the image's average colour inline on this span whenever an
	 * image is set in the editor with `isUserOverlayColor: false`, and an
	 * inline style beats every selector. Here that is worse than on
	 * hero-overlay: there is no multiply on this span, so an inline colour
	 * would paint OPAQUE over the photo. Not live today (Engineering has no
	 * inline colour); one image swap away. Scoped to the colour only.
	 */

	.wp-block-cover.tc-hero-split .wp-block-cover__background.has-background-dim {
		display: block;
		background-color: transparent !important;
		background-image: linear-gradient(
			90deg,
			var( --wp--custom--color--primary--700 ) 0%,
			var( --wp--custom--color--primary--700 ) var( --tc-hero-split-seam ),
			transparent var( --tc-hero-split-fade-end )
		);
	}
}

/*
 * Content colour. Restated for the same reason hero-overlay restates it.
 * ⚠ CORRECTED 2026-08-06: this used to say "with pattern-covers.css absent,
 * `--ftps-hero-content-color` has no consumer". At ftm-blocks 3.0.0-beta.4 the
 * plugin sets it on `.ftps-hero-fullbleed` and it computes #ffffff here, so
 * the restatement now agrees with the contract instead of standing in for it.
 * The path `pattern-covers.css` is dead — the rules live in
 * blocks/page-section/build/style-style.css (build-knowledge §17).
 * The original reason still holds: while `.ftm-scheme-primary` happens to
 * resolve white on the front end, the EDITOR CANVAS renders the heading
 * navy-on-blue. The `:where()` + `:not(.has-text-color)` shape is copied from
 * the plugin stylesheet on purpose — it forces the colour down the tree while
 * yielding to an editor's explicit colour choice.
 */

.tc-hero-split .wp-block-cover__inner-container,
.tc-hero-split .wp-block-cover__inner-container :where( .wp-block-group, h1, h2, h3, h4, h5, h6, p ):not( .has-text-color ) {
	color: var( --ftps-hero-content-color, var( --wp--custom--color--base--white, #fff ) );
}

/*
 * Heading — the same three-part stand-in hero-overlay carries, for the same
 * reason: the theme's `custom.typeStyles` block is inert (design-system values
 * win the merge and the theme's weights reference a token that is never
 * emitted), so `heading-strong` lands at weight 400 / tracking 0. That is a
 * site-wide defect on the maintainer report, not something to fix from a
 * pattern; scoped here as a stand-in, identical to hero-overlay's.
 *
 * The frames agree with hero-overlay's measurements exactly — heading ink is
 * 37.5px tall at 2x on a no-descender line in every desktop and tablet frame
 * across both new patterns (= 51px type), 19px on mobile (= 26px), and the
 * line pitch is 60 at 51. Same flat-then-drop curve, same clamp between
 * heading-strong's own bounds, reaching max at 768.
 */

.tc-hero-split h1 {
	font-size: clamp( 1.625rem, 0.509rem + 5.58vw, 3.1875rem );
	font-weight: 700;

	/*
	 * Frame line pitch is 60 at 51px type from md up (= 1.176, the theme's own
	 * intended value) but 32 at 26px on mobile. Two lines only accumulate 4px,
	 * which is inside tolerance on its own — it is set because everything below
	 * the heading inherits the error, not because the heading looks wrong.
	 */
	line-height: 1.23;
	letter-spacing: -0.02em;
}

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

	.tc-hero-split h1 {
		line-height: 1.176;
	}
}

/*
 * Body copy. Same story and same clamp as hero-overlay's: the `body` preset is
 * 18 / 16.8 / 16 where the frames measure 18 / 18 / 16, and the emitted
 * line-height is the design-system's 1.4 where the frames measure 24px pitch
 * at 18px type (1.333).
 */

.tc-hero-split .tc-hero-split__content p:not( .tc-eyebrow ) {
	font-size: clamp( 1rem, 0.9107rem + 0.4464vw, 1.125rem );
	line-height: 1.25;
}

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

	.tc-hero-split .tc-hero-split__content p:not( .tc-eyebrow ) {
		line-height: 1.333;
	}
}

/*
 * Inter-block spacing — measured, not assumed. The markup's `large` blockGap
 * stays as the default for anything an editor adds; the four real gaps are set
 * explicitly. See the measured table in the build report; values below are
 * box-to-box.
 *
 * ⚠ CORRECTED 2026-09-05: this used to end "at lg, which is the only breakpoint
 * with comps". Engineering has all three, and re-measuring against them found
 * the content→CTA gap wrong AT DESKTOP, where it had been believed verified.
 * Content Section 43657:7160 puts the Button at y188 under a 156-tall Text
 * Block — 32, not 24 — and the tablet Content Section 43324:16090 measures the
 * same 32. 24 is right only at 320 (Text Block 124, Button at y148). The scale
 * has no 32 step, hence the `2rem` one-off below.
 *
 * The eyebrow→heading gap moved the other way: `normal` (16) at md and up, but
 * `xsmall` (8) at base, which is what the smartphone frame draws (Title +
 * Description at y28 under a 20-tall Eyebrow). DECISIONS 2026-07-22 recorded it
 * as 16 at every breakpoint, measured when only desktop frames were known.
 */

.tc-hero-split .tc-hero-split__content > * {
	margin-block-start: 0;
}

.tc-hero-split .tc-hero-split__content > h1 {
	margin-block-start: var( --wp--preset--spacing--xsmall );
}

.tc-hero-split .tc-hero-split__content > p:not( .tc-eyebrow ) {
	margin-block-start: var( --wp--preset--spacing--xsmall );
}

.tc-hero-split .tc-hero-split__content > .wp-block-buttons {
	margin-block-start: var( --wp--preset--spacing--large );
}

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

	.tc-hero-split .tc-hero-split__content > p:not( .tc-eyebrow ) {
		margin-block-start: var( --wp--preset--spacing--large );
	}

	.tc-hero-split .tc-hero-split__content > h1 {
		margin-block-start: var( --wp--preset--spacing--normal );
	}

	.tc-hero-split .tc-hero-split__content > .wp-block-buttons {
		margin-block-start: 2rem; /* 32 — no preset; large 24 → xlarge 40 */
	}
}

/*
 * CTA button. theme.json pins core/button to `var(--color-primary)` /
 * `var(--color-white)`, and `--color-primary` is the ONE role token
 * theme-tokens.css does not remap under [class*='ftm-scheme-'] — left alone the
 * button paints primary-600 blue on blue. The scheme roles are wired to it here,
 * exactly as hero-overlay does; see the G12 note in that file.
 *
 * ⚠ CORRECTED 2026-09-05 — THE PADDING TOKENS DID NOT REPRODUCE THE FRAME BOX.
 * This comment used to end "Frame box is 210x48 for a 19-character label, which
 * the same padding tokens hero-overlay measured reproduce." Measured on the
 * live page, they do not: `small` block padding over a 19.995px line box is
 * 12 + 19.995 + 12 = 43.98, and at base `xsmall` gives 35.98. The frames draw
 * 48 (desktop 43657:7168 and tablet 43324:16098, both 210x48) and 40
 * (smartphone 43324:15934, 199x40).
 *
 * Pinned as a min-height rather than a 14px padding, for two reasons: 14 is not
 * a preset, and a label that wraps to two lines must still be allowed to grow.
 * `border: 0` is an explicit restatement — the live border-width already
 * measured 0, so nothing here is repairing a border, it is stopping one from
 * ever entering the arithmetic.
 *
 * hero-basic.css:196/:219 carries the identical defect and is NOT fixed here.
 * DECISIONS standing list 4.
 */

.tc-hero-split .wp-block-button__link {
	/*
	 * G13 — arrow-right through the contract icon layer with a --tc-icon-*
	 * fallback (build-knowledge §6): the slug is confirmed in the 90-icon set
	 * but the contract layer is dead, and an unresolved mask renders as a solid
	 * currentColor square. Artwork is the Figma export of `fi-rs-arrow-right`
	 * (42222:4552), the same path in all nine declarations (2026-09-28,
	 * docs/reports/icon-audit.md §7).
	 */
	--tc-icon-arrow-right: url( "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M23.124 9.87897L18.538 5.29297L17.124 6.70697L21.386 10.97L0 11V13L21.446 12.97L17.123 17.293L18.537 18.707L23.124 14.121C23.6847 13.5575 23.9995 12.7949 23.9995 12C23.9995 11.205 23.6847 10.4425 23.124 9.87897Z'/%3E%3C/svg%3E" );

	/* G11 — 2px radius + 0.2px tracking, component-scoped. theme.json is 4px
	 * and the footer was frame-verified at 4px; the designer owns the global
	 * call (DECISIONS, G11). */
	display: inline-flex;
	gap: var( --wp--preset--spacing--xsmall ); /* 8 — Figma Button, Icon R 8 after the label (43386:22607, 43391:28219) */
	align-items: center;
	min-height: 2.5rem; /* 40 — smartphone frame 43324:15934 is 199x40 */
	border: 0;
	border-radius: 2px;
	padding-block: 0;
	padding-inline: var( --wp--preset--spacing--small );

	/*
	 * The pattern markup repeats `ftm-scheme-primary` on this block, and that is
	 * why the roles resolve at all in the editor. `ftm/page-section` is a DYNAMIC
	 * block whose wrapper is built in render.php, so the scheme class it carries
	 * never reaches the editor canvas DOM; the roles then fell back to their
	 * `:root` defaults and the canvas painted this CTA primary-600 blue while the
	 * front end was correct. Measured, not reasoned about.
	 *
	 * The theme fallbacks below are belt-and-braces for the same failure mode.
	 */
	background-color: var( --ftm-scheme-accent, var( --wp--custom--color--base--white, #fff ) );
	color: var( --ftm-scheme-accent-text, var( --wp--custom--color--primary--800, #0a205b ) );
	font-size: var( --wp--custom--type-styles--button--font-size );
	line-height: var( --wp--custom--type-styles--button--line-height );
	letter-spacing: 0.2px;
}

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

	.tc-hero-split .wp-block-button__link {
		min-height: 3rem; /* 48 — 43657:7168 and 43324:16098 are both 210x48 */
		padding-inline: var( --wp--preset--spacing--normal );
	}
}

.tc-hero-split .wp-block-button__link::after {
	--icon: var( --ftps-icon-arrow-right, var( --tc-icon-arrow-right ) );

	content: "";
	flex: none;
	width: 1rem; /* 16 — Figma Button Icon R is 16×16 at every size; QA batch F item 9 */
	height: 1rem;
	background-color: currentcolor;
	-webkit-mask: var( --icon ) no-repeat center / contain;
	mask: var( --icon ) no-repeat center / contain;
}

/*
 * Phone tap target (QA batch F, 2026-09-28). style.css gives every core button
 * a centred 44 hit box on phones. Here the photo box, stacked flush under the
 * content below lg, starts on the button's last half-pixel row and paints over
 * anything below it, so a centred box measured 42 ("Speak with Our Team" on
 * /engineering/). This one takes its extra 4 all above the button, where the
 * paragraph is text, not a control.
 */
@media (max-width: 47.9375rem) {
	.tc-hero-split .wp-block-buttons > .wp-block-button > .wp-block-button__link::before {
		inset-block: min(-4px, calc(100% - 44px)) 0;
	}
}
