/*
 * Heading Banner — firsttracks-theme/heading-banner (TC2-T40)
 *
 * Page-top banner: page name, heading, sub heading and one CTA centred on the
 * light-blue scheme over a decorative globe, with a six-logo social-proof strip
 * below. Frames: band 43404:44427, strip 43324:16778 (docs/design/heading-banner).
 *
 * Breakpoints are written at the token values with the token named (conventions
 * §4). 63.9375rem is "below lg", used so the marquee stops exactly where the
 * static six-up grid starts.
 *
 * REUSED, NOT REDEFINED: `.tc-logo-tile` (style.css) supplies the tile box and
 * the logo's fit; `.tc-eyebrow` (style.css) supplies the bar-and-label micro-kit.
 * This file owns the band, the grid tracks and the marquee — which is the split
 * the tile kit's own comment sets out.
 *
 * @package tonercable-2026
 */

/* ─────────────────────────────────────────────────────────────────────────
 * Scheme surface
 *
 * `.ftm-scheme-secondary-subtle` only sets the role custom properties; nothing
 * global paints them, so the band paints itself — the same thing every media
 * family member does. In THIS theme that scheme is re-pointed to secondary-100
 * with primary-800 text (F5, page-sections-schemes.css), which is exactly what
 * the frame binds: bg #e0f2fe, all content #0a205b. Nothing to override.
 * ───────────────────────────────────────────────────────────────────────── */

.tc-heading-banner[class*='ftm-scheme-'] {
	background-color: var(--ftm-scheme-bg);
	color: var(--ftm-scheme-text);
}

.tc-heading-banner[class*='ftm-scheme-'] :where(h1, h2, h3, h4, h5, h6):not(.has-text-color) {
	color: var(--ftm-scheme-heading);
}

/* ─────────────────────────────────────────────────────────────────────────
 * Band
 *
 * Frame rhythm resolves exactly: 80 + 284 + 60 + 144 + 40 = 608.
 * 80, 60 and 32 are documented literals, NOT presets — the scale runs
 * large 24 / xlarge 40 / xxlarge 64 and has no 80, 60 or 32 step. Same
 * treatment as the media band padding and the hero 5rem.
 * ───────────────────────────────────────────────────────────────────────── */

.tc-heading-banner {
	/*
	 * No global `--tc-icon-*` layer exists — the property is defined per pattern
	 * that needs it (build-knowledge §6/§17, the contract layer is dead). The
	 * path is the Figma export of `fi-rs-arrow-right` (42222:4552), the same in
	 * all nine declarations (2026-09-28, docs/reports/icon-audit.md §7).
	 * Declared on the band rather than in
	 * the CTA section below so this selector appears once (no-duplicate-selectors).
	 */
	--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");

	position: relative; /* containing block for the globe */
	overflow: hidden;   /* clips the globe's right overhang */
	padding-block: 5rem var(--wp--preset--spacing--xlarge, 2.5rem); /* 80 / 40 */

	/* Decorative globe, every width (G37), placed exactly as the homepage hero's
	   since I25 (2026-09-30) — the shared tokens in style.css. Full account in
	   the globe section at the end of this file. */
	--tc-globe-on: "";
	--tc-globe-size: var( --tc-hero-globe-size );
	--tc-globe-bleed: calc( var( --tc-hero-globe-right ) * -1 );
	--tc-globe-offset-y: var( --tc-hero-globe-top );
	--tc-globe-offset-block-end: var( --tc-hero-globe-bottom );
	--tc-globe-shift-y: 0;

	/*
	 * COLOUR — read from the frame's DECLARED values, not sampled from a
	 * composited pixel. Figma node 43404:44429 (svg1827) exports
	 * `stroke="#7DD3FC"` on all six paths, which is the bound variable
	 * `color/secondary/300`, and carries `opacity="0.3"` on the layer
	 * itself. The token is opaque, so the alpha lives in the opacity
	 * property — exactly one of the two carries it.
	 *
	 * PER-PATTERN, NOT SITE-WIDE. Each globe is coloured against its own
	 * band: hero-overlay declares secondary-500 and product-grid declares
	 * white-alpha-300 over the navy. Do not normalise these to one value.
	 */

	/*
	 * ⚠ secondary-500 SINCE 2026-09-30 (I25), REVERSING THE FRAME READING
	 * ABOVE. secondary-300 at 0.3 over this band's own pale blue was the reason
	 * the globe could not be seen — it was drawn at every width and nobody
	 * could find it at 390. Gary asked for this globe to match the homepage
	 * hero's and stay visible on phones, so it takes the homepage's paint as
	 * well as its placement. The per-pattern rule still holds: this is a
	 * decision about THIS band, not a normalisation.
	 */
	--tc-globe-paint: var( --wp--custom--color--secondary--500, #0ea5e9 );

	/*
	 * ⚠ 0.12, NOT THE HOMEPAGE'S 0.3 — I25 follow-up, 2026-10-01. Gary: "too
	 * dark, distracting when trying to read the text". The same paint and alpha
	 * read heavier here than on the hero's navy: composited over this band's
	 * secondary-100 the line was rgb(161,219,248), 1.31:1 against the band,
	 * crossing the heading and subtitle. Weight only; size and position stay the
	 * shared hero tokens. hero-overlay hard-codes its own 0.3 and is untouched.
	 */
	--tc-globe-opacity: 0.12;
}

.tc-heading-banner .tc-heading-banner__logos {
	margin-block-start: 3.75rem; /* 60 — content stack -> logo strip */
}

/* Content and strip sit above the globe. */

.tc-heading-banner__content,
.tc-heading-banner__logos {
	position: relative;
	z-index: 1;
}

/* ─────────────────────────────────────────────────────────────────────────
 * Content stack — 800px, the theme contentSize, so no align is needed.
 *
 * Rhythm is explicit per gap rather than one flat blockGap: the frame steps
 * 16 / 24 / 32 between the four children, which no single value gives.
 * ───────────────────────────────────────────────────────────────────────── */

.tc-heading-banner__content {
	text-align: center;
}

/*
 * Page name — the h1 (J9). `.tc-eyebrow` has only ever been carried by a <p>
 * in this theme, so this is the scoped reset that keeps the shared kit free of
 * heading-specific rules. It restates only what a heading element would
 * otherwise impose: the display font, heading weight and heading margins. The
 * bar, gap and label size all still come from the kit.
 */

.tc-heading-banner__pagename {
	justify-content: center; /* .tc-eyebrow is display:flex */
	margin: 0;
	font-family: var(--wp--preset--font-family--body);
	letter-spacing: normal;
	text-transform: none;
}

/*
 * Eyebrow bar — the kit draws `::before` from `currentcolor`, which this scheme
 * re-points to primary-800. The frames bind the bar to primary-600, so pin it
 * (J15 — the same pin brand-grid.css and media-basic.css already ship).
 */

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

/*
 * The three stack margins are scoped through `__content` deliberately. The
 * group's default layout emits its own `> * + *` blockGap at (0,1,0); a bare
 * `.tc-heading-banner__title` ties that and loses on load order, which silently
 * left the eyebrow -> title gap at the 24 blockGap instead of the frame's 16.
 * (0,2,0) beats it on specificity, which is the house rule — never on order.
 */

.tc-heading-banner__content .tc-heading-banner__title {
	margin-block: var(--wp--preset--spacing--normal, 1rem) 0; /* 16 — eyebrow -> title */
	font-weight: 700; /* F23 — headings render at 400 without this */
	line-height: 1.1765; /* 60/51 */
	letter-spacing: -0.02em; /* bound at -2% on every heading in the file */
}

/*
 * 26px @320 -> 51px, max reached at breakpoint/md:
 *   26 + 25 * (100vw - 320px) / 448.
 * The shipped fluid preset does not reach 51 until far past 768, and the
 * tablet frame draws the full 51 at 768. Third family to restate a preset
 * clamp for this reason (F23); `!important` beats the fluid preset.
 */

.tc-heading-banner .has-heading-large-font-size {
	font-size: clamp(1.625rem, 0.5089rem + 5.5804vw, 3.1875rem) !important;
}

.tc-heading-banner__content .tc-heading-banner__subtitle {
	margin-block: var(--wp--preset--spacing--large, 1.5rem) 0; /* 24 — title -> subtitle */
	line-height: 1.3333; /* 24/18 */
}

.tc-heading-banner__content .wp-block-buttons {
	margin-block-start: 2rem; /* 32 — subtitle -> CTA; no preset resolves to 32 */
}

/* ─────────────────────────────────────────────────────────────────────────
 * CTA
 *
 * Same shape as the media family's button, restated here rather than shared:
 * `.tc-media` is a different family and pulling this pattern under it would
 * drag the whole media band ruleset with it.
 * ───────────────────────────────────────────────────────────────────────── */

.tc-heading-banner .wp-block-button__link {
	display: inline-flex;
	align-items: center;
	gap: var(--wp--preset--spacing--xsmall, 0.5rem); /* 8 */
	padding: var(--wp--preset--spacing--small, 0.75rem) var(--wp--preset--spacing--normal, 1rem); /* 12 16 -> 48 tall */

	/* The 48 above only holds if the border is 0, and it was only 0 by cascade
	   order until 2026-09-03: theme.json's `border-width: 0` at (0,1,0) ties with
	   the design system's `border: hairline solid transparent` at (0,1,0), and on
	   a page carrying a core block style variation `global-styles` prints first,
	   so the hairline won and this button stood 50. Measured on `/services/`,
	   where "Talk to an Expert" was 50 against 48 everywhere else. Stated here so
	   the padding comment stays true on every page. Full account in
	   docs/reports/footer-cta-parity.md. */
	border: 0;
	border-radius: 2px; /* bound in every frame */
	font-size: var(--wp--preset--font-size--label-large, 0.9375rem);
	font-weight: 500; /* G01, corrected to 500 on 2026-09-15 */
	line-height: 1.6; /* 24/15 per the button instances */
	letter-spacing: 0.2px;
}

.tc-heading-banner .wp-block-button:not(.is-style-outline) .wp-block-button__link {
	/*
	 * J2/F1 CLOSED 2026-08-06: the comp binds secondary-600 and that is now what
	 * ships. The remap to 700 existed because white on the OLD 600 (#0284C7) was
	 * 4.10:1 against the 4.5:1 this 15px Medium label needs. secondary-600 is
	 * #057DB9 as of 2026-08-06 and white on it is 4.53:1 — AA clear. On this
	 * secondary-100 band the fill itself is 3.94:1, past the 3:1 non-text floor.
	 */
	background-color: var(--wp--custom--color--secondary--600, #057db9);
	color: var(--wp--custom--color--base--white, #fff);
}

.tc-heading-banner .wp-block-button__link::after {
	content: "";
	inline-size: 1rem; /* 16px icon per the button instance */
	block-size: 1rem;
	background-color: currentcolor;

	/* stylelint-disable-next-line property-no-vendor-prefix -- mask needs the prefix pair; scoped exception per the header/media precedent */
	-webkit-mask: var(--ftps-icon-arrow-right, var(--tc-icon-arrow-right)) center / contain no-repeat;
	mask: var(--ftps-icon-arrow-right, var(--tc-icon-arrow-right)) center / contain no-repeat;
}

/* ─────────────────────────────────────────────────────────────────────────
 * Social proof — label
 *
 * NOT a `.tc-eyebrow`. The frame binds Inter Bold 14/20 with the bar layer
 * explicitly hidden, where the eyebrow kit is Medium with a visible bar.
 * Reusing the kit here would mean adding a rule to delete its bar.
 * ───────────────────────────────────────────────────────────────────────── */

.tc-heading-banner__logos-label {
	margin: 0;
	font-size: var(--wp--preset--font-size--label-medium, 0.875rem);
	font-weight: 700;
	line-height: 1.4286; /* 20/14 */
	text-align: center;
}

/* ─────────────────────────────────────────────────────────────────────────
 * Social proof — tiles
 *
 * The tile box, radius, panel and logo fit all come from `.tc-logo-tile`
 * (style.css). Only the two things the kit assigns to the consumer are set
 * here: the grid tracks, and the block-level margin reset that a
 * `figure.wp-block-image` brings with it.
 *
 * J4 — vertical padding. The kit ships 8/32 and this frame draws 16/32 (and
 * 16/24 on three of its six tiles, which is internally inconsistent and is not
 * followed). The horizontal 32 stands; the vertical 8 -> 16 is a single
 * consistent value and is the one difference that shows, because it is what
 * caps a tall logo: at 8 the NASA mark renders 102x82 against the frame's
 * 82x66, a quarter too large. Set on the consumer so `style.css` and
 * brand-grid are untouched.
 * ───────────────────────────────────────────────────────────────────────── */

.tc-heading-banner .tc-logo-tile {
	margin: 0;
	padding-block: var(--wp--preset--spacing--normal, 1rem); /* 16 — J4 */
}

/* ─────────────────────────────────────────────────────────────────────────
 * Social proof — marquee (below lg) / static grid (lg and up)
 *
 * Below lg the track scrolls slowly and is cloned at runtime by the co-located
 * heading-banner.js, so a seamless loop costs the editor six
 * image blocks rather than twelve. The clone carries aria-hidden. One cycle
 * translates a full track plus one gap, which lands the clone exactly where
 * the original started.
 *
 * The Zoho description specifies the marquee at tablet and mobile; the tablet
 * and mobile frames draw a static placeholder grid instead. Those frames are
 * wireframe-tier for this band (no surface, no globe, unbound colours, grey
 * rectangles), so the written spec is followed — recorded in DECISIONS.
 * ───────────────────────────────────────────────────────────────────────── */

.tc-heading-banner__logos-label + .tc-heading-banner__marquee {
	margin-block-start: var(--wp--preset--spacing--large, 1.5rem); /* 24 — label -> grid */
}

.tc-heading-banner__marquee {
	display: flex;

	/* Belt-and-braces against the stretch trap the track already hit: a
	   stretched track would re-derive its tiles' widths through aspect-ratio. */
	align-items: center;
	gap: var(--wp--preset--spacing--normal, 1rem); /* 16 — track -> clone */
	overflow: hidden;
}

/*
 * The marquee is a wp-block-group, so its layout adds a blockGap
 * `margin-block-start` to every child after the first. In a flex ROW that lands
 * as a top margin on the cloned track, which pushed the clone 24px out of line
 * and stretched the original to match. Zeroed here; the `gap` above owns it.
 *
 * Scoped through `.tc-heading-banner` for the specificity, not for the reach:
 * the layout rule is `:root :where(.is-layout-flow) > *` at (0,1,0), so a bare
 * `.tc-heading-banner__marquee > *` ties it and loses on load order. This is
 * the same trap as the content-stack margins above.
 */

.tc-heading-banner .tc-heading-banner__track {
	margin-block: 0;
}

.tc-heading-banner__track {
	display: flex;

	/*
	 * `center`, not the flex default `stretch`. A stretched tile takes the
	 * track's height and `.tc-logo-tile`'s aspect-ratio then derives WIDTH from
	 * it, which inflated every tile past its flex-basis — 274x122 at tablet
	 * against the frame's 220x98. Centring lets the basis set the width and the
	 * aspect-ratio set the height, which is the direction the kit expects.
	 */
	align-items: center;
	flex: none;
	gap: var(--wp--preset--spacing--normal, 1rem); /* 16 — frame-bound at every breakpoint */
	animation: tc-heading-banner-marquee var(--tc-heading-banner-marquee-duration, 50s) linear infinite;
}

/* Fixed track widths so the loop distance is stable; the kit's aspect-ratio
   derives the height. 136 at mobile and 220 at tablet are the frame values. */

.tc-heading-banner__track > .tc-logo-tile {
	flex: 0 0 136px;
}

@keyframes tc-heading-banner-marquee {
	from {
		transform: translateX(0);
	}

	to {
		/* one track plus one gap — the clone lands where the original began */
		transform: translateX(calc(-100% - var(--wp--preset--spacing--normal, 1rem)));
	}
}

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

	.tc-heading-banner__track > .tc-logo-tile {
		flex: 0 0 220px;
	}
}

@media (min-width: 64rem) { /* breakpoint/lg */
	/* Static six-up grid — "static grid on desktop (no scrolling)". `1fr`
	   tracks rather than the frame's literal 220 so the row fits any width at
	   or above lg, not only the 1400 the desktop frame happens to draw. Same
	   ladder brand-grid uses (2 / 3 / 6 at base / md / lg). */

	.tc-heading-banner__marquee {
		display: block;
		overflow: visible;
	}

	.tc-heading-banner__track {
		display: grid;
		grid-template-columns: repeat(6, 1fr);
		animation: none;
	}

	.tc-heading-banner__track > .tc-logo-tile {
		flex: none;
	}
}

/* ─────────────────────────────────────────────────────────────────────────
 * Reduced motion — the static grid is the fallback (conventions §4.4)
 *
 * The script does not clone under this preference, so the track holds its six
 * originals and simply wraps: 2-up at mobile and 3-up at tablet, which is what
 * the tablet and mobile frames draw. `animation: none` is belt-and-braces for
 * the case where the preference changes after the script has already run.
 * ───────────────────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
	.tc-heading-banner__marquee {
		display: block;
		overflow: visible;
	}

	.tc-heading-banner__track {
		flex-wrap: wrap;
		justify-content: center;
		animation: none;
	}

	.tc-heading-banner__track > .tc-logo-tile {
		flex: 0 1 calc((100% - var(--wp--preset--spacing--normal, 1rem)) / 2); /* 2-up */
	}

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

		.tc-heading-banner__track > .tc-logo-tile {
			flex: 0 1 calc((100% - 2 * var(--wp--preset--spacing--normal, 1rem)) / 3); /* 3-up */
		}
	}

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

		.tc-heading-banner__track > .tc-logo-tile {
			flex: none;
		}
	}
}

/* ─────────────────────────────────────────────────────────────────────────
 * Decorative globe — every width (G37, 2026-09-25)
 *
 * Box mechanics, asset and mask live in the shared globe kit (style.css); this
 * block sets only the positioning contract and the colour. See that kit for
 * why it is theme-level (F22) and for the full property list.
 *
 * DECISION A (lead developer, 2026-08-31) — THE GLOBE SCALES WITH THE BAND.
 *
 * It used to be a flat 741.17px square anchored 139.86px past the right edge,
 * both read off the 1920 frame. A fixed square in a fluid band means the
 * globe's share of the band GROWS as the viewport shrinks, and it grew a long
 * way: measured before the change, the artwork covered 31.3% of the band at
 * 1920 and 58.7% at 1024 — nearly double — and its arcs ran 281px into the
 * 800px content column at 1440 against 41px at 1920.
 *
 * The 1920 frame is still the only frame that draws this globe, so it stays
 * the source. What changes is that its geometry is now read as a RATIO of the
 * band rather than as two lengths:
 *
 *   size  = 741.17 / 1920 = 38.6023% of the band, capped at 741.17px
 *   bleed = 139.86 / 741.17 = 18.87% of the size
 *
 * Both are percentages of the same thing — for an absolutely positioned box,
 * `inline-size` and `inset-inline-end` both resolve percentages against the
 * containing block's width — so `--tc-globe-bleed` can be written as a
 * fraction of `--tc-globe-size` and the two stay locked together. That is what
 * holds the coverage ratio CONSTANT at 31.32% from 1024 to 1920 instead of
 * letting it drift, and it is why the bleed scales rather than staying at
 * 139.86px: a fixed bleed under a fluid size gives 24.9% coverage at 1024
 * against 31.3% at 1920, which is the same class of error in the other
 * direction.
 *
 * The `min()` cap means 1920 renders EXACTLY as it did before this change —
 * 741.16px at −139.86px — so the frame is still met at the width it was drawn
 * at, and above 1920 the globe stops growing rather than tracking a very wide
 * viewport.
 *
 * PRESENT AT EVERY WIDTH SINCE 2026-09-25 (G37). It used to be lg and up
 * only, because the Solutions tablet and smartphone boards draw no globe; the
 * designer overruled that — "although it is not in the mockup, it should
 * still be there and behave similarly to the product grid pattern", which is
 * present at every width. The declarations therefore live on the BASE
 * `.tc-heading-banner` rule at the top of this file (one selector,
 * no-duplicate-selectors), not in a 64rem query.
 *
 * SIZE BELOW 1024 IS THE DECISION A RATIO, UNCHANGED, AND THAT IS DELIBERATE.
 * The designer has not given a size for 1024 and below — that is G36, still
 * open — so no new number was invented: the same rule applies at every width
 * (296.5 at 768, 123.5 at 320; coverage 31.32% throughout). When G36 is
 * answered it replaces this one rule. Unlike product-grid, which has its own
 * tablet and mobile boards to read flat sizes from, this pattern has none.
 *
 * media-stats, the other globe on /services/, is still lg and up only (J24).
 * The designer's G37 note named this globe, not that one.
 *
 * ASSET: globe-wireframe-full.svg, the one complete globe every consumer
 * uses. The pre-cropped globe-wireframe.svg was retired 2026-09-25 (assets are
 * complete, crops are CSS); do not reintroduce a crop baked into a file.
 *
 * A failed mask URL paints a solid square, so verify this as artwork rather
 * than by presence alone (environment-facts §4).
 *
 * ⚠ SUPERSEDED 2026-09-30 (I25) — DECISION A's ratio and the G36 question
 * above are both answered. Gary asked for the Services hero globe to "match
 * the hero icon" and stay visible on phones; recorded as the G36 decision,
 * Gary's override at review. The globe now takes the HOMEPAGE hero's
 * geometry at every width — flat px sizes per breakpoint, anchored off the
 * bottom-right below lg and the top-right from lg — read from the shared
 * `--tc-hero-globe-*` tokens in style.css rather than copied, and the
 * homepage's paint (secondary-500 at 0.3). It applies to every heading-banner
 * (Services and Solutions). The ratio account above is kept as the record of
 * why it was a ratio; it no longer describes what renders. media-stats is
 * untouched and still lg-only (J24).
 * ───────────────────────────────────────────────────────────────────────── */
