@layer components {
	/* Centralized Hero component (Phase 13 — radical simplification).
	 *
	 * The global rule, non-negotiable per the client: a hero contains a
	 * Main Title (H1) and a Description (paragraph). Nothing else. No
	 * eyebrow label, no secondary subheading, no glass panel, no button.
	 * Three CONTENT classes: .tf-hero, .tf-hero__title, .tf-hero__description.
	 *
	 * ARCHITECTURE NOTE — why there is still a structural wrapper.
	 * Elementor forces `max-width: 100%` unconditionally and unlayered on
	 * every `.elementor-widget` wrapper (in addition to forcing
	 * min-height/padding-block/text-align/border-radius on every `.e-con`
	 * container, per Phase 12's findings), so a layered max-width rule on
	 * .tf-hero__title/.tf-hero__description themselves cannot win.
	 *
	 * An attempt to instead target Elementor's inner
	 * `.elementor-widget-container` div (which carries no such forced
	 * rule) was tried and discarded: this Elementor build renders the
	 * heading/paragraph directly inside the widget wrapper, with no such
	 * intermediate div to target — confirmed by inspecting the live
	 * markup, not assumed. `.tf-hero__inner` is therefore still required
	 * to hold the 1140px cap, via Elementor's own `content_width: boxed`
	 * control — the same mechanism every other boxed section on the site
	 * already uses, and Elementor's own `.e-con > .e-con-inner` rule
	 * already includes `margin: 0 auto`, so the box is centered
	 * identically to every other section without this file setting
	 * width/centering itself. It is structural plumbing, not part of
	 * the client's three-class content vocabulary — title and
	 * description are the only classes that carry meaning.
	 *
	 * NON-ELEMENTOR USAGE (Phase 23, Single Post template). `single.php`
	 * is a native WordPress template, not an Elementor document, so
	 * there is no `boxed_width` control to reach for. `.tf-hero__inner`
	 * there instead carries the existing `.tf-container` utility class
	 * (layout.css) for the same job — plain `max-inline-size` +
	 * `margin-inline: auto`. Same visual result, different mechanism;
	 * this file's three content classes and structural rules are
	 * unchanged either way.
	 *
	 * Still necessarily set per-page in Elementor, documented as "the
	 * standard" in docs/design-system.md §33: on `.tf-hero`,
	 * min_height/min_height_mobile and padding/padding_mobile; on
	 * `.tf-hero__inner`, flex_direction ('column'), flex_gap, and
	 * flex_align_items ('center' for Home's centered variant,
	 * 'flex-start' — the default — for every other hero).
	 *
	 * The overlay is a `::after` pseudo-element (Phase 12): `::before`
	 * collides with Elementor's own unconfigured overlay feature on the
	 * same node, and `::after` is untouched by any Elementor base rule.
	 */

	.tf-hero {
		background-size: cover;
		background-position: center center;
		color: var(--tf-text-on-dark);
	}

	.tf-hero::after {
		content: "";
		position: absolute;
		inset: 0;
		z-index: 0;
		background-color: var(--tf-text);
		opacity: 0.55;
	}

	.tf-hero--no-overlay::after {
		content: none;
	}

	/* A hero with no scrim has no guarantee of a dark backdrop behind
	 * it — on-dark text there would be barely legible. Reverting to the
	 * standard dark-on-light pair keeps this variant readable. */
	.tf-hero--no-overlay:not(.tf-hero--photo) {
		color: var(--tf-text);
	}

	/* Hero text is pure white wherever the hero sits on photography:
	 * every scrimmed hero, plus image heroes that opt out of the scrim
	 * via .tf-hero--photo (Home). Text-only heroes (Blog Insight,
	 * Portfolio) sit on a light surface and keep dark text.
	 *
	 * Elementor emits each heading/text-editor colour as unlayered CSS
	 * from its own title_color/text_color controls, which a layered
	 * declaration cannot beat -- but a layered !important one does, so
	 * the colour is enforced here once for both languages instead of per
	 * page in Elementor. */
	.tf-hero--photo,
	.tf-hero:not(.tf-hero--no-overlay) {
		color: var(--tf-text-hero);
	}

	.tf-hero--photo .tf-hero__title,
	.tf-hero--photo .tf-hero__title *,
	.tf-hero--photo .tf-hero__description,
	.tf-hero--photo .tf-hero__description *,
	.tf-hero:not(.tf-hero--no-overlay) .tf-hero__title,
	.tf-hero:not(.tf-hero--no-overlay) .tf-hero__title *,
	.tf-hero:not(.tf-hero--no-overlay) .tf-hero__description,
	.tf-hero:not(.tf-hero--no-overlay) .tf-hero__description * {
		color: var(--tf-text-hero) !important;
	}

	/* Structural only — see the architecture note above. Width and
	 * centering come from Elementor's boxed_width setting; this file
	 * only lifts the content above the overlay.
	 *
	 * z-index needs !important: Elementor's own unlayered CSS sets
	 * z-index on this same `.e-con`/`.e-child` node (confirmed live —
	 * `position: relative` from this rule took effect but `z-index: 1`
	 * did not, computed value stayed `auto`), and per the project's
	 * established "unlayered always wins" rule a layered declaration
	 * cannot beat it — except a layered !important one can, the same
	 * mechanism already used above for the hero text color. Without
	 * this, the ::after scrim painted on top of the text instead of
	 * behind it on every hero except Home's (Home has no scrim to begin
	 * with, via .tf-hero--no-overlay), washing white text out to a dim
	 * grey against the underlying photo — a real, live contrast bug
	 * this fixes, not a hypothetical one. */
	.tf-hero__inner {
		position: relative;
		z-index: 1 !important;
	}

	.tf-hero__title,
	.tf-hero__description {
		margin: 0;
	}
}
