/*
 * Home hero card — hero over a customizable background image, rendered as an
 * inset card surface (16px from the page edge, rounded, overflow hidden) and
 * sized by content plus vertical padding rather than by any viewport unit.
 * Only enqueued on pages carrying .idia-hero-card — see
 * maybe_enqueue_hero_card() in functions.php.
 */

/* ---- Wrapper: inset only, no rail ----
   The wrapper reproduces the reference's .header-block: a 16px inset from the
   page edge (via .is-surface-card in style.css) and NOTHING else — no padding
   of its own.

   WordPress adds .has-global-padding to it because it is a constrained-layout
   group, which puts the 32px rail OUTSIDE the cover. Measured before this
   rule at 1440/991/767/479: wrapper 16/1408 with padding-inline 32/32/20/20,
   so the cover started at 48/48/36/36 and ran 1344/895/695/407 — 64px (40px
   below 767) narrower than the reference's .hero-section, which is the full
   1408/959/735/447 at x=16. The background and image surface were therefore
   short by that much at every width.

   The reference puts the rail INSIDE the box, on .container. Zero it here and
   supply it on the inner container instead (see below), which moves the box
   out to full width without moving any text.

   Scoped to .idia-hero-card__wrapper deliberately. .has-global-padding is on
   8-10 elements per page and every other section depends on it — a general
   rule here would move /about, /contact and every inner page. */
.idia-hero-card__wrapper.has-global-padding {
	padding-left: 0;
	padding-right: 0;
}

/* ---- Card inner layout ----
   The Cover block doesn't expose a way to add a custom class to its own
   inner-container div, so this targets it structurally instead of by class.

   .idia-hero-card itself is also a flex container (core's own
   .wp-block-cover base style), and contentPosition: "top left" gives it
   core's is-position-top-left class, which sets align-items: flex-start on
   THIS element. That means its flex child — .wp-block-cover__inner-container
   — is sized by its own content on the cross axis, not stretched to the
   card's full height, no matter what height value is set on the child
   itself: setting an explicit height on the child doesn't fix this either
   — confirmed in the browser that height:100% on the inner container
   computes short of the card's actual height (a known percentage-height
   quirk in flex cross-axis sizing), where plain height:auto plus the
   parent's align-items:stretch resolves correctly. So the fix is two
   parts: override align-items on the parent, and leave the child's height
   at auto rather than fighting it with a percentage.

   Selector matches core's own .wp-block-cover.is-position-top-left (two
   classes) plus .idia-hero-card, so three classes beats it on specificity
   without needing !important — core's rule only sets align-items, nothing
   else on this block needs to survive from it. */
.wp-block-cover.is-position-top-left.idia-hero-card {
	align-items: stretch;
	/* Radius set here, not as a block border-radius attribute, because no
	   border-radius PRESET can step at a breakpoint. WordPress emits every
	   preset at :root, and a var() inside a custom-property declaration is
	   substituted where that property is DECLARED — so
	   --wp--preset--border-radius--xl bakes in --wp--custom--radius--24's
	   :root value (24px) and never sees the `html body` override that steps
	   it to 16px at <=767px (style.css). Measured: with the xl preset on the
	   block, the cover computed 24px at 767 and 479 while the wrapper
	   correctly computed 16px. Referencing the custom property directly on
	   an element (rather than inside another custom property) resolves at
	   use time and therefore steps correctly: 24/24/16/16 across
	   1440/991/767/479, matching the reference's .hero-section.

	   This is the same token .is-surface-card applies to the wrapper, so the
	   two corners agree; the wrapper's overflow:hidden clips this one
	   anyway, but they are kept in sync rather than left to differ. */
	border-radius: var(--wp--custom--radius--24);
	/* Kept for the hero's own absolutely-positioned children. It is no
	   longer the containing block for the nav: the nav is now the global
	   header template part, a sibling of <main>, so it anchors to the
	   initial containing block instead — see .idia-header--over-hero-dark
	   in assets/css/header.css. */
	position: relative;
	/* No min-height here on purpose. The hero is sized by content plus the
	   inner container's vertical padding (see below), never by a viewport
	   unit — the reference has no viewport-height rule on the hero at any
	   width, and an earlier min-height:92vh was removed because it left
	   ~131px of dead space below the CTA row at 1440px.

	   Worth knowing about core, though it is not acted on here: WordPress
	   injects an inline `@media (max-width: 781px) { .wp-block-cover:not
	   (.has-aspect-ratio) { min-height: 430px !important; } }` — found by
	   walking document.styleSheets in-browser, not documented anywhere. It
	   is !important, so no plain selector can beat it regardless of
	   specificity. Below 782px it therefore sets a 430px floor on this
	   cover. In practice the hero's own content + padding exceeds 430px at
	   those widths, so the floor never binds and nothing counteracts it.
	   If that ever changes, measure it before adding a rule. */
}

/* .idia-hero-card is flex-direction: row (core's own .wp-block-cover base
   style, untouched by the align-items override above — that override only
   reaches the cross axis, height). On a row, width is the main axis, and
   the inner-container's default flex-grow: 0 leaves it shrunk to its own
   content width instead of spanning the card — confirmed in the browser:
   without flex-grow: 1 the inner-container stops hundreds of px short of
   the card's right edge, which is what was pulling the bottom-right
   actions block back toward the left instead of the true right edge. */
.idia-hero-card > .wp-block-cover__inner-container {
	display: flex;
	flex-direction: column;
	flex-grow: 1;
	justify-content: space-between;
	/* Vertical padding is what sizes the hero — there is no min-height on
	   the cover (see above). These two tokens reproduce the reference's
	   .hero-section padding: spacing--196 resolves 196/120/80/140px and
	   spacing--hero-bottom resolves 44/36/24/24px across 1440/991/767/479,
	   both through their own breakpoint steps in style.css, so no media
	   query is needed here.

	   padding-bottom was spacing--44 (44/44/36/32) until the geometry pass
	   against the live reference: it matched only at 1440 and ran 8/12/8px
	   long at the other three widths. spacing--hero-bottom exists solely to
	   carry the reference's 44/36/24/24 curve, exactly as spacing--196
	   carries the top one.

	   This is the rail — 32px at >=768px, 20px below, stepping on its own
	   through --wp--custom--rail in style.css, matching .container in the
	   reference exactly. It lives HERE and not on the wrapper: the wrapper's
	   own has-global-padding is zeroed above so the cover can span the full
	   inset width, so this is the only place the rail is applied. Applying
	   it in both places doubles it to 64px and pushes every text element
	   32px right — if the h1 or badge move off 48/48/36/36, that is what
	   happened. */
	padding-top: var(--wp--preset--spacing--196);
	padding-bottom: var(--wp--preset--spacing--hero-bottom);
	padding-left: var(--wp--custom--rail);
	padding-right: var(--wp--custom--rail);
}

/* ---- Lower row ----
   Meta stats (left) and the existing actions column (right) side by side,
   both anchored to the row's bottom edge so short and tall content align
   on their baseline rather than their tops. */

.idia-hero-card .idia-hero-card__lower {
	align-items: flex-end;
	/* Separation from the intro paragraph above. The inner container's own
	   blockGap (spacing--24) is what applied here before, which put 24px
	   between the intro and this row against the reference's 80px — measured
	   80/80/80/48 across 1440/991/767/479 on stodio.webflow.io, where it
	   comes from .hero-content-wrapper's top padding. spacing--80 (80/60/40/40)
	   is the closest token in the scale: exact at 1440, short by 20/40/8 at
	   the narrower widths. No closer token exists — the next candidates are
	   spacing--120 (120/80/60/80) and spacing--64 (64/52/48/24), both worse
	   overall. Left on the existing token rather than adding a new one; if
	   the narrower breakpoints need to match the reference exactly, that is
	   a new spacing token and an explicit decision.

	   Two things here are load-bearing against core, which sets this gap via
	   ":root :where(.is-layout-flow) > * { margin-block-start: ... }":

	   1. The property is margin-block-start, matching core's. A margin-top
	      declaration does not override a margin-block-start one on the same
	      element regardless of specificity — they are different properties,
	      and the logical one resolves last.
	   2. The selector is scoped to .idia-hero-card, not the bare
	      .idia-hero-card__lower class. Core's selector scores (0,1,0) —
	      :root contributes one class-equivalent, :where() contributes zero —
	      which TIES a single class. Ties go to source order, and core emits
	      its rule in an inline <style> in <head> that comes after this
	      enqueued file, so the bare class silently lost. The descendant
	      scope takes it to (0,2,0) and wins outright. Verified in-browser:
	      the bare-class version parsed into the CSSOM correctly and still
	      computed 24px. */
	margin-block-start: var(--wp--preset--spacing--80);
}

/* ---- Meta row ----
   Three short "+ stat" items. The "+" is real markup (not a ::before) so
   the site owner can edit or remove it from the editor, but it is wrapped
   in an aria-hidden span so screen readers announce only the stat text,
   not a stray "plus" before every item. */

.idia-hero-card__meta {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--main-accent);
	text-transform: uppercase;
	letter-spacing: var(--wp--custom--letter-spacing--body);
}

.idia-hero-card__meta-item {
	margin: 0;
}

/* ---- Badge pill ----
   Both the chassis (background, mono family, size, uppercase, letter-spacing
   reset, line-height) and the icon mask rules live in footer-cta.css, shared
   with .idia-cta-badge — see the note at the top of that file. Step 6 moved
   the chassis there so one definition governs both badges; only the
   plus-square icon-fill override below is hero-specific. */

/* The one place the shared icon mechanism cannot be reused as-is. The shared
   ::before rule in footer-cta.css sets background-color: currentColor, so every
   badge icon takes its badge's text colour — correct for the other four
   variants, which sit on badges whose icon and text are the same colour. The
   reference's plus-square tag is not: its icon is brand red while its text is
   near-black. So this variant, and only this one, overrides the fill. Applies
   to both badge classes that use this variant — .idia-hero-card__badge (hero,
   FAQ) and .idia-cta-badge (footer CTA) — since the fill mismatch is a
   property of the icon variant, not of which section it sits in.

   The shared rule is left untouched — sparkle, arrow-right, rocket and chat all
   still resolve through currentColor.

   Size is set explicitly rather than left at the shared 1em, which would
   resolve to 14px against these badges' 14px font-size; the reference's icon
   is 16px. An em value would have to be 16/14 (1.142857…), a repeating decimal
   that rounds unpredictably — a literal 16px is the honest expression of a
   fixed 16px icon. */
.idia-hero-card__badge.is-style-badge-icon-plus-square::before,
.idia-cta-badge.is-style-badge-icon-plus-square::before {
	width: 16px;
	height: 16px;
	background-color: var(--wp--preset--color--primary-dark);
}

/* ---- Bottom actions column ----
   Vertical gap between the "Two engineers" line and the buttons row is set
   by the block's own blockGap (var:preset|spacing|16) — nothing to add
   here.

   Horizontal position needs one rule though: the parent inner-container's
   align-items is left at its default (normal/stretch, see above) so both
   this block and .idia-hero-card__text stretch to the container's full
   width — .idia-hero-card__text wants that (its own contentSize:680px and
   justifyContent:left constrain it correctly from there), but this block
   has no contentSize, so without align-self it just fills the row and its
   content's own justifyContent:right (which sets align-items:flex-end
   internally — confirmed in rendered markup) only right-aligns the text
   and buttons *within* this box, not this box within the hero card. This
   is what actually pins the whole cluster to the card's right edge. */
.idia-hero-card__actions {
	align-self: flex-end;
}

/* The house hover is a radius change and nothing else (AGENTS.md §11.1),
   supplied by theme.json's elements.button[":hover"]. The transition is
   declared here so the radius animates rather than snapping; the property
   list is deliberately radius-only.

   Removed in step 6: a background-color shift on :hover for both buttons
   (transparent -> rgba white on the secondary, base -> primary-accent on the
   primary) and a transform: scale(0.98) on :active. Those stacked three
   gestures on top of the radius; one gesture consistently applied reads as
   craft, three read as a template. The secondary's `background-color:
   transparent` went with them — it existed to support the outline style,
   which is now a real variant with a solid background. */
.idia-hero-card__button-secondary .wp-block-button__link,
.idia-hero-card__button-primary .wp-block-button__link {
	display: inline-flex;
	align-items: center;
	gap: var(--wp--preset--spacing--8);
	transition: border-radius var(--wp--custom--transition) cubic-bezier(0.32, 0.72, 0, 1);
}

/* Trailing arrow — step 7 moved this from a ::after pseudo-element to a real
   .idia-btn-icon element (assets/css/button-roll.css) so button-roll.js can
   clone it for the hover text/icon roll; a pseudo-element cannot be cloned.
   Same glyph, same mechanism, shared by every button on the site — nothing
   to add here. */

/* Base outline with a dark offset shadow so the ring reads on any photo,
   including a light one where a plain white ring would disappear. */
.idia-hero-card__button-secondary .wp-block-button__link:focus-visible,
.idia-hero-card__button-primary .wp-block-button__link:focus-visible {
	outline: 2px solid var(--wp--preset--color--base);
	outline-offset: 3px;
	box-shadow: 0 0 0 5px rgba(0, 0, 0, 0.45);
}

@media (max-width: 600px) {

	/* The block now carries its own generated layout class
	   (orientation: vertical -> flex-direction: column; align-items:
	   flex-end) with no media query of its own, so it applies at every
	   width and matches this rule's specificity. !important is the only
	   reliable way to win the cascade here regardless of which stylesheet
	   loads second. */
	.idia-hero-card__actions {
		align-items: flex-start !important;
	}

	.idia-hero-card__actions .wp-block-buttons {
		justify-content: flex-start !important;
	}

	/* Meta row wraps to two columns and lightens against the photo once it
	   can no longer sit on one line at its full measure. */
	.idia-hero-card__meta {
		display: grid;
		grid-template-columns: 1fr 1fr;
		column-gap: var(--wp--preset--spacing--24);
		row-gap: var(--wp--custom--gap--8);
		color: var(--wp--preset--color--base);
	}
}

@media (prefers-reduced-motion: reduce) {

	/* The radius still changes on hover — that is a state change, not motion,
	   and the button reads correctly at either radius. Only the animation
	   between them is suppressed. The former `transform: none` overrides that
	   sat here were removed with the transforms they guarded (step 6). */
	.idia-hero-card__button-secondary .wp-block-button__link,
	.idia-hero-card__button-primary .wp-block-button__link {
		transition: none;
	}
}

/* ---- Header, hero ----
   Rounds 2 and 3 tried to render the global header (parts/header.html)
   transparently "inside" the hero card via a negative margin, then via
   position:absolute on the header itself. Both were abandoned: the header
   renders before <main> and the hero card lives deep inside it, so they
   share no positioning context — every attempt produced clipping or
   misalignment against the header's real edges.

   The header unification step superseded that fix entirely: there is now
   one global header template part on every page, and the homepage renders
   it at its .idia-header--over-hero-dark variant — transparent, absolutely
   positioned over this hero, base link colour, logo inverted. No nav markup
   is nested in this pattern any more. See assets/css/header.css. */

/* ---- Nav ----
   The homepage nav is no longer part of this pattern. It was a nested copy
   of the header markup; the header unification step replaced it with the one
   global template part at its .idia-header--over-hero-dark variant, so every
   rule that used to live here — the 12px+rail offset, the 38px row gap, the
   invert(1) logo, the light CTA pill, and the whole reveal-on-scroll-up
   block — now lives in assets/css/header.css alongside the header it styles.
   header-scroll.js is unchanged: it still finds .idia-header generically. */

/* ---- Entrance animation ----
   Badge, headline, subtext, meta row, and the actions column blur-fade-rise
   on load, staggered per assets/js/hero-reveal.js — reverse-engineered from
   stodio.webflow.io's live Webflow IX2 interaction data (see that file's
   top-of-file comment and .agents/skills/webflow-clone/state/
   animation-map.json for the full derivation).

   This block sets ONLY the phase-1 instant "from" state — opacity 0, 5px
   blur, translateY 50px, matching the reference's own trick of authoring
   that state directly into server-rendered HTML/CSS so there is never a
   flash of the finished hero before the script attaches. hero-reveal.js
   owns every animated frame after that; nothing here uses @keyframes or a
   CSS transition, both of which would fight the script's own GSAP tweens on
   the same properties.

   Opt-in only: scoped to prefers-reduced-motion: no-preference, so a
   reduced-motion visitor's hero renders complete and settled immediately —
   hero-reveal.js also independently checks the same media query and takes
   no action at all when motion is reduced, so the two can never disagree. */

@media (prefers-reduced-motion: no-preference) {

	.idia-hero-card__badge,
	.idia-hero-card__text > .wp-block-heading,
	.idia-hero-card__text > p,
	.idia-hero-card__meta,
	.idia-hero-card__actions {
		opacity: 0;
		transform: translateY(50px);
		filter: blur(5px);
	}

	/* core/cover always renders its background image as a direct
	   <img class="wp-block-cover__image-background">, a SIBLING of the
	   dim-overlay <span class="wp-block-cover__background">, never nested
	   inside it — confirmed against page 29's rendered content. */
	.wp-block-cover__image-background {
		transform: scale(1.4);
	}
}
