/* Homepage Hero (§1, Figma node 10355:3506) — tokens only, see hero-SPEC.md for
   geometry source + Ben's 2026-07-09 checkpoint edits (bottom-pinned row, 120px
   minimum gap, 0.589em glyph, rotating words). */

.tb-hero {
	/* No outer padding/min-height — BB row settings own section spacing (Ben, 2026-07-09). */
	position: relative;
	display: flex;
	flex-flow: column nowrap;
	/* NOTE: no CSS full-bleed breakout here — BB's column in this layout is
	   content-sized, so 100vw + negative viewport margins enter a sizing
	   feedback loop (parents collapse to 0 or inflate with x-overflow).
	   Full-width is editor-owned: the BB row must be set to Full Width. */
	margin: 0;
	color: var(--Black);
	overflow: hidden;

	/* Heading centered in the space remaining above the pinned bottom row. */
	& .tb-hero__inner {
		position: relative;
		display: flex;
		flex: 1 1 auto;
		flex-flow: column nowrap;
		justify-content: center;
	}

	/* Typography comes from the theme's `.h0` class on the h1 (font-family,
	   weight, size, line-height, color — theme.css header ruleset + .h0). */
	& .tb-hero__heading {
		position: relative;
		z-index: 1;
		margin: 0; /* overrides var(--header-margin) */
		/* Module setting "Heading Max Width" — frontend.php emits the var on
		   the section's style attr; fallback covers instances not yet resaved. */
		max-width: var(--tb-hero-heading-max-w, 1100px);
		/* Figma H0-exact tracking (-1.5px @ 90px); the theme's global
		   --header-letter-spacing is -0.01em and must not change globally. */
		letter-spacing: -0.0167em;
	}

	/* Glyph + rotator unit — atomic: inline-block + nowrap means the browser
	   can never break between the glyph and the rotating phrase (QA:
	   display:inline still allowed a break between the adjacent inline-level
	   boxes at 390px). The rotating phrase renders on ONE line always (SPEC
	   item 6, round 3) — the whole unit wraps to a new line together. */
	& .tb-hero__anim {
		position: relative;
		display: inline-block;
		max-width: 100%;
		white-space: nowrap;
		vertical-align: baseline;
	}

	/* 53px at the 90px heading = 0.589em — em-based so it scales at exactly the
	   heading's rate. Symmetric 0.25em side gaps (SPEC item 6b — supersedes the
	   earlier "no side margins" edit): the markup has NO space characters around
	   the unit, so this margin is the single source of the glyph's spacing and
	   the left/right gaps are identical. */
	& .tb-hero__glyph {
		position: relative;
		display: inline-flex;
		justify-content: center;
		align-items: center;
		width: 0.589em;
		height: 0.589em;
		margin: 0 0.1em;
		vertical-align: -0.02em;

		& svg {
			position: absolute;
			display: block;
		}

		& .tb-hero__glyph-circle {
			top: 0;
			left: 0;
			width: 100%;
			height: 100%;
			color: var(--Primary-Alt-50-Base);
		}

		/* Arrow scaled LARGER within the circle vs. the raw Figma inset, and
		   optically centered per the design (SPEC item 6b): the plane points NE
		   so its body sits low-left — Figma top 29.5% / left 19.8% at 50.7%,
		   scaled to our 55%. */
		& .tb-hero__glyph-arrow {
			top: 27%;
			left: 18%;
			width: 55%;
			height: 55%;
			color: var(--White);
		}
	}

	/* Rotator — width is JS-managed during swaps (transitions to the incoming
	   word's measured width); auto when JS/motion is off. is-ghost is the
	   incoming word, is-measure an invisible nowrap measurer (lab pattern).
	   nowrap: the rotating phrase never wraps internally (SPEC item 6). */
	& .tb-hero__rotator {
		position: relative;
		display: inline-block;
		max-width: 100%;
		white-space: nowrap;
		vertical-align: baseline;
		/* Masked reveal: clip the word at the TOP so the outgoing/incoming word vanishes
		   behind a clean edge during the swap. Negative bottom/side insets EXPAND the clip
		   region outward past the tight .h0 line box so descenders (y, g, p) render fully at
		   rest, while the incoming word's deep start (translateY(0.62em + 12px)) is still masked.
		   clip-path (not overflow) — overflow on an inline-block moves its baseline. */
		clip-path: inset(0.06em -0.5em -0.22em -0.5em);
	}

	& .tb-hero__word {
		display: inline-block;
	}

	& .tb-hero__word.is-ghost {
		position: absolute;
		top: 0;
		left: 0;
		opacity: 0;
		pointer-events: none;
	}

	& .tb-hero__word.is-measure {
		position: absolute;
		visibility: hidden;
		white-space: nowrap;
		pointer-events: none;
	}

	/* Bottom row — pinned to the section bottom as its own block; the 120px
	   margin-top guarantees the minimum gap from the heading block even when
	   the viewport squeezes (Ben's checkpoint edits #2 + #3). */
	& .tb-hero__bottom-row {
		position: relative;
		z-index: 1;
		display: flex;
		flex-flow: row nowrap;
		justify-content: space-between;
		align-items: flex-end;
		gap: var(--Spacing-XS);
		margin-top: 120px;
	}

	& .tb-hero__subline,
	& .tb-hero__scroll {
		font-family: var(--body-font);
		font-weight: 400;
		font-size: var(--body-font-size);
		/* Pastel #1 (Chris) — "part of the bottom of the g is getting cut off".
		   1.094 is shallower than Sequel Sans's descender, so the ink ran 1px
		   past the line box; .tb-hero's own `overflow: hidden` sits exactly on
		   that edge (measured at 1331: box bottom 556, ink bottom 557) and
		   shaved it. 1.3 contains the descender at any size, and the hero's
		   clip edge follows the content, so it moves down with it. Fixing the
		   line box rather than the clip keeps this correct if the face or the
		   body size ever changes. */
		line-height: 1.3;
		letter-spacing: var(--header-letter-spacing);
		color: var(--Black);
	}

	& span.tb-hero__subline {
		text-wrap: auto;
	}

	& .tb-hero__scroll {
		display: inline-flex;
		align-items: center;
		gap: 8px;
		text-wrap: nowrap;
	}

	& .tb-hero__scroll-arrow {
		flex: 0 0 12px;
		width: 12px;
		height: 12px;
		color: var(--Black);
	}

	/* Pastel #127 — the label is now an anchor into the services section. The
	   underline is drawn at rest and faded in on hover: text-decoration-line
	   is discrete and cannot tween, so only the colour is animatable. */
	& .tb-hero__scroll--link {
		color: inherit;
		text-decoration: underline;
		text-decoration-thickness: from-font;
		text-decoration-color: transparent;
		transition: var(--button-easing);
	}

	& .tb-hero__scroll--link:hover,
	& .tb-hero__scroll--link:focus-visible {
		text-decoration-color: currentColor;
	}
}

/* Masked-marquee word swap (Ben, 2026-07-10). The incoming word rises at FULL
   opacity from fully below the rotator's clip window while the outgoing word
   exits fully out the top — no fades; the clip edge does the reveal/hide.
   Whole recipe gated for reduced motion — reduced-motion visitors keep the
   static first word (JS never starts the cycle either).

   2026-08-26 (Ben): the glyph arrow's rotation is GONE — "simply have it be the
   switching words". The circle-and-arrow mark itself stays, static; only its
   keyframes and the transform-origin they needed were removed, along with the
   is-swapping class and the intro lead the JS used to hold for them. */
@media (prefers-reduced-motion: no-preference) {
	/* No rotator width transition — the rotator holds a FIXED width equal to
	   the longest rotating word (JS-measured; SPEC item 5, Ben round 6) so
	   the heading's wrap points never shift between words. */

	/* Marquee variant (Ben, 2026-07-10): NO opacity fades — words hold full
	   opacity and the clip-path window on .tb-hero__rotator does all the
	   revealing/hiding. Outgoing exits fully out the TOP of the window;
	   incoming rises in from fully BELOW it. */
	.tb-hero .tb-hero__word.is-ghost {
		transition: transform 300ms ease-out;
	}

	.tb-hero .tb-hero__word.is-current {
		transition: transform 300ms ease-out;
	}

	/* Start/end positions sit OUTSIDE the clip window (top inset 0.06em,
	   bottom extends -0.22em past the line box): 1.5em below hides the
	   incoming word's cap; -1.2em above clears the outgoing descenders. */
	.tb-hero .tb-hero__word.is-ghost {
		transform: translateY(1.2em);
		opacity: 1;
	}

	.tb-hero .tb-hero__anim.is-go .tb-hero__word.is-current {
		transform: translateY(-1.25em);
	}

	.tb-hero .tb-hero__anim.is-go .tb-hero__word.is-ghost {
		transform: translateY(0);
		opacity: 1;
	}
}

/* @media (max-width:767px) {
	.tb-hero {
		& .tb-hero__bottom-row {
			align-items: flex-start;
			gap: var(--Spacing-3XS);
		}
	}
} */
