/* ==========================================================================
   Module Hero — reusable component
   Markup: .module-hero (header, role="banner") > .module-hero__photo-wrap
     (featured image + .module-hero__badge) + .wrapper > .module-hero__content
     (h1 + .module-hero__tagline + .module-hero__actions with two
     .module-hero__btn-primary / .module-hero__btn-secondary buttons).
   Text content (heading, tagline, both button labels/URLs) comes from the
   universal SCF field group registered in inc/scf-fields/module-hero.php
   (post_type-only guard — available on every 'module' post, like the FAQ
   accordion). The featured image is used as-is (has_post_thumbnail()), no
   SCF field for it. First usage: single-module-fahrradbox.php.
   ========================================================================== */

/* Deliberately NOT using the sitewide .image-header/.red utility classes —
   .red * forces color:#f5f5f5 !important sitewide (AAA contrast fix), which
   would fight the primary button's black-on-white requirement below.
   Padding: 0 on mobile (image sits flush top/edges, full-bleed) — .wrapper
   below carries the vertical spacing instead. Desktop restores padding on
   the header itself, see media query. */
.module-hero {
	position: relative;
	/* overflow-x clip (not full hidden): the circle bleeds ~5% past
	   the right edge on desktop (would cause a horizontal scrollbar)
	   AND is meant to hang past the section's bottom edge (see
	   .module-hero__photo-wrap below) — plain overflow:hidden
	   clips both axes and killed the bottom bleed too. `clip`,
	   unlike `hidden`, doesn't force the other axis to compute as
	   `auto` when mixed with `visible`. */
	overflow-x: clip;
	overflow-y: visible;
	background-color: var(--red);
	padding: 0;
	/* Mobile-only viewport-fit: flex column so the photo (grow:1, see
	   .module-hero__photo-wrap) absorbs whatever height is left after the
	   text block (.wrapper, auto-sized to its own content) — instead of a
	   guessed fixed photo height, the photo becomes exactly as tall as the
	   screen safely allows. min-height (a floor, not min-height:auto)
	   lets flex-grow do the work; if text content is ever tall enough on
	   its own to exceed this, the section simply grows past it rather than
	   clipping. calc() subtracts var(--header-height) because <main>
	   already gets padding-top: var(--header-height) sitewide (style.css)
	   — .module-hero's own box starts BELOW the fixed header, so sizing it
	   to the full 100dvh would push its bottom (h1/CTA) past the fold by
	   exactly the header's height. vh fallback first for browsers without
	   dvh support; reset to min-height:0 at >=768px below, where the
	   circle/split layouts use an explicit height instead. */
	display: flex;
	flex-direction: column;
	min-height: calc(100vh - var(--header-height));
	min-height: calc(100dvh - var(--header-height));
}

/* Sitewide `* { color: var(--black) }` (style.css:114-124) sets color
   DIRECTLY on every element (not just as an inheritable default), so an
   ancestor's color:white is never consulted — each descendant already
   has its own, lower-specificity-but-direct black. Must target
   descendants explicitly; same reason the sitewide `.red *` AAA-fix
   rule exists as `ancestor *`, not a plain ancestor color. */
.module-hero * {
	color: var(--white);
}

.module-hero .wrapper {
	padding-top: 1.5rem;
	padding-bottom: 1.5rem;
	/* Growable (grow:1, not the default 0): once .module-hero__photo-wrap
	   hits its max-height:100vw cap above, flexbox reassigns whatever
	   free space it can no longer absorb to the next growable sibling —
	   this element. Without this, that space would just sit unused below
	   the CTAs (module-hero's used height is still floored by min-height
	   even though neither child grew to fill it). display:flex here (not
	   on .module-hero__content) centers .row — the only child — within
	   that reclaimed height, instead of pinning it to the top with a gap
	   below the buttons. */
	flex: 1 1 auto;
	display: flex;
	flex-direction: column;
	justify-content: center;
}

.module-hero__content {
	position: relative;
	z-index: 2;
}

/* Fluid display size: the heading is meant to be a single short word/term
   (not sitewide's usual multi-line heading), so it can run much bigger than
   the 2.2rem sitewide default without wrapping risk. clamp() over the
   sitewide fixed rem keeps it readable on small phones (min) while letting
   it grow into the generous hero height on desktop (max), scaling smoothly
   in between via the vw term — no extra breakpoint needed on top of the
   existing photo/layout media query. */
.module-hero h1 {
	font-size: clamp(2.75rem, 1rem + 6vw, 5.5rem);
	line-height: 1.05;
	/* em, not sitewide's fixed -.1rem: that value was tuned for the
	   2.2rem default and barely registers at this size (~-2px on an
	   88px headline); em scales the tracking together with the
	   clamp() above so it stays proportionally tight at every size. */
	letter-spacing: -.02em;
	margin-bottom: .5rem;
}

.module-hero__tagline {
	margin: 0;
	font-size: clamp(1.35rem, .7rem + 2vw, 2rem);
	font-weight: 500;
}

.module-hero__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 1rem;
	/* Fluid, not a fixed 2rem: h1/tagline above scale via clamp() too, so a
	   static gap would look cramped next to the 88px desktop headline and
	   slightly loose next to the 44px mobile one. Grows in step with them
	   across the same viewport range. */
	margin-top: clamp(1.5rem, 1rem + 1.5vw, 2.75rem);
}

.module-hero .button {
	width: auto;
	margin: 0;
	gap: .5rem;
}

/* Higher specificity (.module-hero + this class = 2 classes) needed to
   reliably beat the .module-hero * white rule above — a bare
   .module-hero__btn-primary{color:black} would tie it on specificity and
   depend on source order. The " *" arm covers the arrow <span> too, which
   .module-hero * would otherwise also whiten directly (descendant color
   isn't inherited from the <a>, each element is matched independently). */
.module-hero .module-hero__btn-primary,
.module-hero .module-hero__btn-primary * {
	color: var(--black);
}

.module-hero__btn-primary {
	background: var(--white);
	border: 1px solid var(--white);
}

.module-hero__btn-primary:hover {
	background: var(--white-80);
}

.module-hero__btn-secondary {
	background: transparent;
	border: 1px solid var(--white);
}

.module-hero__btn-secondary:hover {
	background: var(--white-15);
}

/* Photo: mobile = normal-flow square/rect image above the red field.
   Desktop (>=768px) = absolutely positioned circle bleeding off the
   right/bottom edge, diameter = --module-hero-height (set on .module-hero
   in the media query below). */
.module-hero__photo-wrap {
	/* relative (not static): scopes the badge's absolute positioning to
	   this wrapper on mobile without affecting normal-flow layout */
	position: relative;
	display: block;
	width: 100%;
	/* TEST 2026-07-22: fixed 3:2 instead of the previous viewport-fit
	   flex-grow/max-height:100vw mechanism (still described in the .module-hero
	   and .wrapper comments below, not yet reworded — this rule is what
	   actually governs sizing now). aspect-ratio gives a definite height
	   directly, no circularity trick needed, so flex-basis/min-height/
	   flex-grow aren't required here either (0 0 auto, not 1 1 0).
	   Trade-off: no longer adapts to available viewport height — on tall
	   phones this leaves more room for text (bigger than the old 1:1 cap
	   would have used), but on short viewports (small phones, landscape)
	   photo+text may together exceed the fold where the old mechanism
	   guaranteed a fit by shrinking the photo. No margin-bottom: the parent
	   is flex, so a margin here would stack on .wrapper's own
	   padding-top:1.5rem below, double-spacing photo/text. */
	flex: 0 0 auto;
	aspect-ratio: 3 / 2;
}

.module-hero__photo {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Mobile: centered on the photo itself (not a corner) — top/left 50% +
   translate(-50%,-50%), containing block is .module-hero__photo-wrap
   (position:relative). 4.125rem = 2.75rem * 1.5 (2026-07-22 mobile resize). */
.module-hero__badge {
	position: absolute;
	z-index: 3;
	width: 4.125rem;
	height: 4.125rem;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	border-radius: 50%;
	background: var(--white);
	display: flex;
	align-items: center;
	justify-content: center;
	box-shadow: 0px 1px 5px 0px var(--shadow);
}

.module-hero__badge svg {
	width: 1.65rem;
	height: 1.65rem;
}

.module-hero__badge-icon {
	fill: var(--red);
}

@media (min-width: 768px) {
	.module-hero {
		/* Fixed height + a custom property shared with .photo-wrap below,
		   instead of min-height/auto: percentage heights on an absolutely
		   positioned child do NOT reliably resolve against an auto-height
		   parent — display:flex does not fix this (an earlier attempt at
		   that still rendered the photo as a flattened oval, not a circle,
		   and the section stayed short). Giving the parent an explicit
		   height and having the photo reference that exact same value
		   directly (not as a %) sidesteps the ambiguity entirely. Adjust
		   this one value to retune the hero's height. */
		--module-hero-height: 40rem;
		height: var(--module-hero-height);
		/* Cancels the mobile-only viewport-fit floor above — height:
		   (a fixed value, not a floor) already wins over any leftover
		   min-height on its own, but resetting explicitly follows this
		   project's convention of re-declaring every property the base
		   rule touched per breakpoint, rather than relying on that. */
		min-height: 0;
		/* Symmetric top/bottom: <main id="main-content"> already gets
		   padding-top: var(--header-height) sitewide (see style.css), so
		   the section starts below the fixed header on its own — this
		   padding is just breathing room inside the fixed-height box, not
		   header clearance, and should stay vertically centered. */
		padding: 2.6rem 0;
		display: flex;
		flex-direction: column;
		justify-content: center;
	}

	.module-hero .wrapper {
		padding-top: 0;
		padding-bottom: 0;
		/* Cancels the mobile-only growable/centering block above — the
		   circle layout already centers .wrapper via .module-hero's own
		   justify-content:center (it's the sole in-flow flex item once
		   photo-wrap goes position:absolute below), so a lingering
		   flex-grow:1 here would stretch it to the full 40rem height and
		   silence that centering instead of complementing it. */
		flex: 0 1 auto;
		display: block;
	}

	.module-hero__content {
		max-width: min(45%, 50rem);
	}

	.module-hero__photo-wrap {
		position: absolute;
		top: 0;
		right: 5rem;
		/* Explicit width AND height (not aspect-ratio) — the mobile base
		   rule above sets width:100%, which the desktop block never
		   overrode; width:100% + height:var(...) together made
		   aspect-ratio a no-op (it only fills in a MISSING dimension, and
		   both were already set), producing a flattened lozenge nearly the
		   full header width instead of a circle. Setting width to the
		   same var as height removes the ambiguity entirely instead of
		   re-introducing aspect-ratio. */
		width: var(--module-hero-height);
		height: var(--module-hero-height);
		/* Cancels the mobile-only max-height:100vw cap — harmless today
		   since 100vw is always >= this breakpoint's own 768px floor,
		   comfortably above the 720px --module-hero-height, but silently
		   wrong the moment someone retunes --module-hero-height past that
		   (the comment above it explicitly invites doing so). */
		max-height: none;
		transform: translateY(10%);
		/* No border-radius/overflow/box-shadow here anymore (2026-07-22) —
		   moved to .module-hero__photo below. overflow:hidden + border-radius
		   on the SAME element clips descendants to the rounded curve, not
		   just the square box — that used to clip .module-hero__badge too,
		   which now deliberately sits astride the circle's edge (see badge
		   rule below) and needs to stay visible past it, over the red
		   background. Rounding the <img> directly instead (a replaced
		   element paints its own content pre-clipped to its box) crops the
		   photo into the same circle without touching this wrap or its
		   other children. */
		z-index: 1;
		margin-bottom: 0;
	}

	.module-hero__photo {
		height: 100%;
		max-height: none;
		border-radius: 50%;
		box-shadow: 0px 1px 5px 0px var(--shadow);
	}

	/* 7rem = 3.5rem * 2 (2026-07-22 desktop resize). Position: clock "7:30" on
	   the circle — top:85%/left:15% is the point on the circle's edge at
	   225° clockwise from 12 o'clock (cx,cy = 50%,50%; r = 50% of this box,
	   since the box IS the circle's bounding square), i.e.
	   50% ± r*sin/cos(225°) ≈ 50% ∓ 35.35%. translate(-50%,-50%) then
	   centers the badge itself ON that edge point, so it straddles the
	   circle boundary — the top layer overlapping BOTH .module-hero__photo
	   (rounded on itself, see above) and the section's red background
	   outside the circle. Works because the wrap no longer clips its
	   children (see comment on .module-hero__photo-wrap above). */
	.module-hero__badge {
		width: 7rem;
		height: 7rem;
		top: 85%;
		left: 15%;
		right: auto;
		bottom: auto;
		transform: translate(-50%, -50%);
	}

	.module-hero__badge svg {
		width: 3rem;
		height: 3rem;
	}
}
