/**
 * His Feet Fundraisers — the home page hero.
 *
 * Same hostile host as the grid: this renders inside a Thrive landing page,
 * which skins bare tags from an ID selector (`#tcb_landing_page p`, `… h1`)
 * and therefore outranks any plain class. Every rule here that paints or sizes
 * text carries the `:not(#tve)` counterweight for that reason — see the long
 * note in grid.css, which explains the device and why removing it silently
 * turns the hero's text white on white. Geometry-only rules do not need it and
 * deliberately do not carry it.
 */

/* The white frame around the hero is not the hero's.
 *
 * Thrive's blank landing page template ships no CSS reset, and nothing else on
 * the site resets it either — checked, there is no rule setting a margin on
 * body anywhere in the page's stylesheets. So the browser's own default of 8px
 * survives, and every edge of the document carries it.
 *
 * It had gone unnoticed because nothing on that page was ever edge-to-edge:
 * with all content centred inside a narrower column, 8px of body margin is
 * invisible. A full-bleed hero is the first element wide enough to show it, as
 * a white border down both sides and across the top.
 *
 * Reset here rather than in Thrive's Custom CSS box because this stylesheet
 * loads only on pages that actually render a hero — so the reset lands exactly
 * where it is needed and nowhere else. It will also let any other full-width
 * section on that page reach the edge, which is what those sections were
 * asking for anyway.
 */
body {
	margin: 0;
}

/* Thrive wraps the shortcode in boxes of its own — a page section, its inner
 * container, and a wrapper around the shortcode itself — each carrying its own
 * spacing and, on this template, a max-width inherited from the landing page.
 * Around ordinary content that spacing is the point. Around a band meant to
 * run edge to edge it shows as a white gap, and the max-width stops the band
 * reaching the sides at all.
 *
 * Nothing inside the hero can reach an ancestor, so :has() walks up to exactly
 * those wrappers that contain a hero. Every other section on the page keeps
 * its spacing untouched. A browser without :has() drops the rule and simply
 * keeps the gap, which is why this is separate from everything above it.
 *
 * The `:not(#tve)` counterweight is here for the same reason it is on the text
 * rules, and it is not optional. Setting a content width on the landing page
 * puts `--page-section-max-width` on every section, and Thrive caps the inner
 * container with it from a selector carrying three classes and an !important:
 *
 *     .thrv-page-section[data-inherit-lp-settings="1"] .tve-page-section-in
 *
 * `:has(.hff-hero)` only counts the class inside the brackets, so the plain
 * form of the rule below scores two and loses — the band gets capped at the
 * page's content width and stops short of the right-hand edge. The `:not(#tve)`
 * buys an id's worth of weight, which outranks any number of classes.
 *
 * `auto` on the side margins rather than a flat 0 for the failure case: the
 * two are identical once the cap is gone, but if a cap ever does survive, a
 * centred band reads as a design decision where a left-hugging one, with all
 * the empty space piled up on one side, reads as the breakage it is.
 */
:not(#tve) .thrv-page-section:has(.hff-hero),
:not(#tve) .tve-page-section-in:has(.hff-hero),
:not(#tve) .thrv_wrapper:has(> .hff-hero) {
	margin: 0 auto !important;
	padding: 0 !important;
	max-width: none !important;
}

/* Box sizing, stated rather than assumed.
 *
 * The page already sets `html { box-sizing: border-box }` with
 * `*, *:before, *:after { box-sizing: inherit }`, which would be the end of it
 * anywhere else. Thrive then sets
 *
 *     .thrv_wrapper div { box-sizing: content-box }
 *
 * and every box Thrive wraps this shortcode in is a div inside a
 * `.thrv_wrapper` — so content-box is what actually arrives at the hero, and
 * the inherit chain hands it on to everything inside.
 *
 * What that breaks is `.hff-hero__inner`: width 100% *plus* its own side
 * padding, which in content-box is a box wider than the band it sits in by
 * exactly the padding. `overflow: hidden` on the section then hides the
 * evidence by cutting it off. On a phone that is the thermometer and the last
 * word of every line of the summary running off the right-hand edge; on a
 * desktop it is the same overflow, unnoticed only because the text is capped
 * at 34rem and never reaches the cut.
 *
 * The `:not(#tve)` counterweight is not optional here. `.thrv_wrapper div`
 * scores a class and a type, so a plain `.hff-hero *` scores one class and
 * loses. This is a geometry rule carrying the counterweight that the note at
 * the top of this file says geometry rules do not need — it needs one because
 * it is arguing with a Thrive *rule*, not with a browser default.
 */
.hff-hero:not(#tve),
.hff-hero:not(#tve) *,
.hff-hero:not(#tve) *::before,
.hff-hero:not(#tve) *::after {
	box-sizing: border-box;
}

.hff-hero {
	--hff-navy: #0b477e;
	--hff-navy-deep: #07305a;
	--hff-green: #7ac819;
	--hff-green-dark: #6cb50c;

	position: relative;
	display: flex;
	align-items: center;
	overflow: hidden;

	/* The band's own colour, and the thing the photograph dissolves into.
	   Given a slight angle rather than left flat: a single solid colour behind
	   a fading photo reads as a mistake in the image, where a gradient reads as
	   the design it is.

	   The channels arrive as a custom property from the Home Hero screen so one
	   chosen colour can drive the band, the gradient and the scrim together.
	   The fallbacks are the brand navy, so the hero still looks right if the
	   attribute is ever missing. */
	--hff-band-rgb: 7, 48, 90;
	--hff-band-lift: 38, 74, 111;

	background: linear-gradient(
		115deg,
		rgb(var(--hff-band-rgb)) 0%,
		rgb(var(--hff-band-lift)) 62%,
		rgb(var(--hff-band-rgb)) 100%
	);

	/* Tall enough to feel like a hero, short enough that the call to action is
	   still on screen on a laptop. Height is capped in vh as well as px so a
	   short window never has to scroll past the hero to reach the page. */
	min-height: clamp(420px, 46vw, 620px);
}

/* ---------- photo ---------- */

/* The photo is shown whole, not cropped to fill the band.

   This is the opposite of the usual hero treatment, and deliberately so. These
   photographs arrive at whatever shape and size the field sent them — 500×400
   next to 1179×654 — and a band cropped to full bleed has to throw away most of
   a squarish photo to get there, which is how heroes end up with somebody's
   forehead missing. Sizing to the band's height and letting the width fall out
   of the photo's own proportions means nothing is ever cut off, and an odd
   shape stops being a liability: it simply occupies less of the band and more
   of the gradient shows.

   The container is sized to the picture rather than the band so the fade below
   can be measured from the photo's own left edge. */
/* Flex, and sized to the picture rather than the band, for one reason: the
   fade below is measured from the image element's edges, so that element has
   to *be* the photograph. Stretch it to the band and the mask starts fading
   empty space instead of the picture, which is exactly how the first attempt
   at this ended up still cropping. */
.hff-hero__media {
	position: absolute;
	top: 0;
	right: 0;
	bottom: 0;
	left: auto;
	width: auto;
	max-width: 100%;
	display: flex;
	align-items: center;
	justify-content: flex-end;
	z-index: 0;
}

.hff-hero__media--empty {
	inset: 0;
	max-width: none;
}

/* Full band height, and whatever width that implies at the photo's own
   proportions. Those two together are what make the picture both complete and
   full-bleed: a 1.86 photo in a 920px band simply becomes 1711px wide and runs
   most of the way across, with its left half dissolved into the gradient that
   the text sits on. Nothing is cropped — the part under the words is faded,
   not cut off.

   No width cap, because a cap is what forced the earlier crop. object-fit is
   the safety net for a true panorama whose natural width would exceed the
   band: there it letterboxes rather than distorting, which is the right
   failure for a shape this layout was never going to flatter. */
.hff-hero__img {
	display: block;
	width: auto;
	height: 100%;
	max-width: 100%;
	max-height: 100%;
	object-fit: contain;

	/* The dissolve, measured from the photo's own left edge, so it lands in the
	   same place whether the picture occupies 40% of the band or 78% — which a
	   gradient laid over the band could not do without knowing each photo's
	   proportions in advance. */
	/* Reaches full opacity later than it used to. Now the photo runs most of the
	   width, the summary's last lines sit further into it, and a fade that was
	   already done by half-way left them competing with a lit background. */
	-webkit-mask-image: linear-gradient(to right, transparent 0%, rgba(0, 0, 0, .22) calc(var(--hff-fade, 58%) * .32), #000 var(--hff-fade, 58%));
	mask-image: linear-gradient(to right, transparent 0%, rgba(0, 0, 0, .22) calc(var(--hff-fade, 58%) * .32), #000 var(--hff-fade, 58%));
}

/* ---------- a photo deliberately narrower than the band ---------- */

/* Left to itself a faded photo is flush right at whatever width its own
   proportions give it, which is why neither the focal point nor the fade
   toggle could move it further right — there was no width to give back.
   Constraining the container hands that back: the photo covers the share of
   the band chosen on the Home Hero screen, and the rest is band colour for the
   words to sit on.

   The image switches to cover here because a narrower box and a whole photo
   cannot both be had — something must be cropped. The focal point decides
   what, which is exactly the job it already does in fill mode. */
.hff-hero--sized .hff-hero__media {
	max-width: var(--hff-photo-w, 100%);
}

/* The shading now stops where the photo starts.
 *
 * Before this it ran a fixed distance across the band — solid to about a
 * third, gone by two thirds — on the assumption the photo was always behind
 * the words. Once the photo can be moved right that assumption breaks: the
 * shading carried on across open background and then washed over the front of
 * a picture that no longer needed protecting, which is exactly the haze in the
 * photograph you sent.
 *
 * Deriving the stops from the photo's own left edge fixes it without adding a
 * control: the shading is full strength over the background where the words
 * are, releases as the photo begins, and is clear a short way into it. Move
 * the photo further right and the shading follows on its own. */
/* Anchored to the words, not to the photo.
 *
 * Shading exists for one reason: to keep the text readable. The words occupy
 * roughly the left half of the banner, so beyond that the shading has no job —
 * and every percent it travels past them is veiling a photograph for nothing.
 * An earlier version stretched it from the photo's left edge, which meant
 * moving the photo right dragged the haze right along with it, out over the
 * subject's face.
 *
 * These stops hold full strength across the text, release through the gap, and
 * are clear before the middle of the banner. Four stops rather than two so the
 * release is gradual — a straight ramp is visible as a band of its own. */
.hff-hero--sized .hff-hero__scrim {
	background:
		linear-gradient(
			to right,
			rgba(var(--hff-band-rgb), var(--hff-scrim, .88)) 0%,
			rgba(var(--hff-band-rgb), var(--hff-scrim, .88)) 30%,
			rgba(var(--hff-band-rgb), calc(var(--hff-scrim, .88) * .55)) 42%,
			rgba(var(--hff-band-rgb), calc(var(--hff-scrim, .88) * .18)) 50%,
			rgba(var(--hff-band-rgb), 0) 58%
		);
}

.hff-hero--sized .hff-hero__img {
	width: 100%;
	height: 100%;
	max-width: none;
	max-height: none;
	object-fit: cover;
}

/* ---------- the scrim ---------- */

/* Belt to the mask's braces. The mask fades the photo's own edge, which is
   enough on most shapes — but a wide photo clamped to 72% still reaches under
   the last lines of a long summary, and "most shapes" is not a standard to
   hold white text to. This stays light because it is insurance rather than the
   main event: the text is sitting on the band's own gradient, not on the
   photograph. */
.hff-hero__scrim {
	position: absolute;
	inset: 0;
	z-index: 1;
	/* Every stop is a fraction of the chosen strength rather than a fixed
	   alpha, so the slider moves the whole gradient together and its shape —
	   dense behind the words, gone by the time it reaches the face — survives
	   at any setting. At 0 the shading disappears entirely without the rule
	   needing to be switched off. */
	background:
		linear-gradient(
			to right,
			rgba(var(--hff-band-rgb), var(--hff-scrim, .88)) 0%,
			rgba(var(--hff-band-rgb), calc(var(--hff-scrim, .88) * .82)) 30%,
			rgba(var(--hff-band-rgb), calc(var(--hff-scrim, .88) * .32)) 48%,
			rgba(var(--hff-band-rgb), 0) 66%
		);
}

/* ---------- text colour ---------- */

/* Chosen alongside the band, not derived from it. Automatic contrast picking
   sounds appealing but gets it wrong exactly where it matters: the words sit
   over a gradient and a photograph, not over the flat colour a calculation
   would measure. */
.hff-hero--text-light:not(#tve) .hff-hero__eyebrow {
	color: #9fd45f;
}

.hff-hero--text-light:not(#tve) .hff-hero__title {
	color: #fff;
}

.hff-hero--text-light:not(#tve) .hff-hero__summary {
	color: rgba(255, 255, 255, .92);
}

.hff-hero--text-light:not(#tve) .hff-hero__amounts {
	color: rgba(255, 255, 255, .86);
}

.hff-hero--text-light:not(#tve) .hff-hero__amounts .hff-card__raised {
	color: #fff !important;
}

.hff-hero--text-light:not(#tve) .hff-hero__bar {
	background: rgba(255, 255, 255, .22);
}

.hff-hero--text-light:not(#tve) .hff-hero__cta:focus-visible {
	outline-color: #fff;
}

.hff-hero--text-dark:not(#tve) .hff-hero__eyebrow {
	color: #3f7a10;
}

.hff-hero--text-dark:not(#tve) .hff-hero__title {
	color: #0d1b26;
}

.hff-hero--text-dark:not(#tve) .hff-hero__summary {
	color: rgba(13, 27, 38, .84);
}

.hff-hero--text-dark:not(#tve) .hff-hero__amounts {
	color: rgba(13, 27, 38, .74);
}

.hff-hero--text-dark:not(#tve) .hff-hero__amounts .hff-card__raised {
	color: #0d1b26 !important;
}

.hff-hero--text-dark:not(#tve) .hff-hero__bar {
	background: rgba(13, 27, 38, .16);
}

.hff-hero--text-dark:not(#tve) .hff-hero__cta:focus-visible {
	outline-color: #0d1b26;
}

/* ---------- fill: a photo that needs no rescuing ---------- */

/* For a picture composed for this slot, dissolving it is meddling. Fill mode
   gives it the whole band edge to edge and drops the mask. The focal point
   still governs what survives the crop, because filling a band this wide is
   the one case where cropping is unavoidable.

   The scrim is deliberately NOT dropped here. Filling the band and shading the
   words are separate questions, and tying them together meant a photograph
   that wanted to fill the band could not have any gradient behind its text —
   which is exactly the standing hero's case. Shading strength answers that on
   its own, in either mode; set it to 0 for no shading at all. */
.hff-hero--fill .hff-hero__media {
	inset: 0;
	width: auto;
	max-width: none;
	display: block;
}

.hff-hero--fill .hff-hero__img {
	width: 100%;
	height: 100%;
	max-width: none;
	max-height: none;
	object-fit: cover;
	-webkit-mask-image: none;
	mask-image: none;
}

/* Under about 900px the photo has no room to sit beside the text, so the scrim
   stops pretending there is a left half and covers the whole band instead. */
@media (max-width: 900px) {
	/* Reached only if the stacked layout below ever stops hiding the scrim.
	   Written in the band's own colour rather than a fixed navy so that, if it
	   is, it is not a colour nobody chose. */
	.hff-hero__scrim {
		background: linear-gradient(
			to bottom,
			rgba(var(--hff-band-rgb), calc(var(--hff-scrim, .88) * .93)) 0%,
			rgba(var(--hff-band-rgb), var(--hff-scrim, .88)) 55%,
			rgba(var(--hff-band-rgb), var(--hff-scrim, .88)) 100%
		);
	}
}

/* ---------- content ---------- */

.hff-hero__inner {
	position: relative;
	z-index: 2;
	width: 100%;
	max-width: 1180px;
	margin: 0 auto;
	padding: clamp(48px, 6vw, 88px) clamp(20px, 4vw, 40px);
}

.hff-hero__text {
	max-width: 34rem;
}

.hff-hero:not(#tve) .hff-hero__eyebrow {
	margin: 0 0 10px;
	font-size: .82rem;
	line-height: 1.2;
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
}

.hff-hero:not(#tve) .hff-hero__title {
	margin: 0 0 16px;
	font-size: clamp(1.9rem, 4vw, 3.1rem);
	line-height: 1.12;
	font-weight: 700;
	letter-spacing: normal;
	text-transform: none;
	text-wrap: balance;
}

.hff-hero:not(#tve) .hff-hero__summary {
	margin: 0 0 26px;
	font-size: clamp(1rem, 1.3vw, 1.12rem);
	line-height: 1.6;
	font-weight: 400;
}

/* ---------- thermometer ---------- */

.hff-hero__progress {
	margin: 0 0 28px;
	max-width: 26rem;
}

.hff-hero__bar {
	height: 12px;
	border-radius: 6px;
	overflow: hidden;
}

.hff-hero__bar-fill {
	display: block;
	height: 100%;
	background: var(--hff-green);
	border-radius: 6px;
	transition: width .8s ease;
}

.hff-hero:not(#tve) .hff-hero__amounts {
	margin: 10px 0 0;
	font-size: 1rem;
	line-height: 1.5;
	font-weight: 400;
}

/* !important for the same reason grid.css needs it on this element: the site's
   own Custom CSS box carries `strong, b { color: white !important }`, which
   only !important can outrank. White is already the colour here, so the
   visible failure was the weight rather than the hue — the raised figure
   arriving indistinguishable from the words around it. */
.hff-hero:not(#tve) .hff-hero__amounts .hff-card__raised {
	font-size: 1.3rem;
	font-weight: 700 !important;
}

/* ---------- call to action ---------- */

/* Written to fit both shapes this button takes: an <a> to a fundraiser page
   when a need is promoted, and a GiveCloud <button data-fundraising-form> on
   the standing hero, which opens the donation form in place. font-family and
   appearance are stated because a <button> inherits neither, and the site's
   own Custom CSS box restyles bare `button` with a 10px radius that would
   otherwise leak in and make the two shapes look like different buttons. */
.hff-hero:not(#tve) .hff-hero__cta {
	display: inline-block;
	appearance: none;
	-webkit-appearance: none;
	background: var(--hff-green);
	color: #fff;
	border: 0;
	border-radius: 4px;
	padding: 15px 32px;
	font-family: inherit;
	font-size: 1.05rem;
	font-weight: 600;
	line-height: 1.2;
	letter-spacing: normal;
	text-transform: none;
	text-align: center;
	text-decoration: none;
	cursor: pointer;
	transition: background .15s ease;
}

.hff-hero:not(#tve) .hff-hero__cta:hover,
.hff-hero:not(#tve) .hff-hero__cta:focus {
	background: var(--hff-green-dark);
	color: #fff;
	text-decoration: none;
}

.hff-hero:not(#tve) .hff-hero__cta:focus-visible {
	outline: 3px solid;
	outline-offset: 3px;
}

/* ---------- narrow screens ---------- */

/* Below 900px the hero stops competing for a right-hand crop it cannot win.
   The photo becomes a band across the top in the same 16:9 shape the grid
   cards already use — a composition these photographs were actually chosen
   for — and the words move onto flat navy underneath, where contrast is a
   certainty rather than a gradient's best effort. */
@media (max-width: 900px) {
	.hff-hero {
		display: block;
		min-height: 0;
	}

	/* Stacked, the photo has the full width to itself and no text to stay clear
	   of, so it is shown whole at its own proportions — no crop, and no fade,
	   because there is nothing beside it to dissolve into.

	   Every mode is named explicitly. A media query does not raise specificity,
	   so a bare `.hff-hero__media` here loses to `.hff-hero--sized
	   .hff-hero__media` no matter which comes last in the file — which is why a
	   photo set to 55% stayed at 55% on a phone, stranded beside a column of
	   empty background. Narrowing a photo is a decision about a wide screen;
	   there is no room for it beside anything on a narrow one. */
	.hff-hero__media,
	.hff-hero--sized .hff-hero__media,
	.hff-hero--fill .hff-hero__media {
		position: relative;
		display: block;
		top: auto;
		right: auto;
		bottom: auto;
		left: auto;
		width: 100%;
		max-width: none;
	}

	.hff-hero__img,
	.hff-hero--sized .hff-hero__img,
	.hff-hero--fill .hff-hero__img {
		width: 100%;
		height: auto;
		max-width: none;
		max-height: none;
		object-fit: contain;
		-webkit-mask-image: none;
		mask-image: none;
	}

	.hff-hero__scrim {
		display: none;
	}

	/* The chosen colour, not a hardcoded navy. This panel is the whole
	   background behind the words once the layout stacks, so leaving it fixed
	   put near-black text on navy for anyone who had picked a pale colour —
	   unreadable, and only on phones, where it is least likely to be noticed. */
	.hff-hero__inner {
		padding: clamp(28px, 7vw, 44px) clamp(20px, 5vw, 32px);
		background: rgb(var(--hff-band-rgb));

		/* `width: auto`, and only here.
		 *
		 * The base rule needs `width: 100%` because up there the hero is a flex
		 * container and the inner is a flex item, where an auto width sizes to
		 * content rather than filling — removing it collapses the 1180px measure
		 * to about 620px and drags the text column into the middle of the band.
		 * Measured, not assumed.
		 *
		 * Stacked, the hero is `display: block` and the inner is an ordinary
		 * block box, where auto fills the band *minus* its own padding under
		 * either box model. That matters because `width: 100%` plus padding only
		 * agrees with the band while the box-sizing rule near the top of this
		 * file is winning its argument with Thrive, and that rule is the single
		 * point of failure behind v1.23.1: the one time it lost, the inner ran
		 * 40px past the band and `overflow: hidden` cut eight elements off the
		 * right-hand edge — the thermometer, the summary and the amounts among
		 * them.
		 *
		 * Phones are where that failure shows, because they are the only place
		 * the words reach the cut; on a desktop the text stops at 34rem and the
		 * overflow is invisible. So the guard belongs here, where it costs
		 * nothing, rather than in the base rule, where it costs the layout.
		 */
		width: auto;
	}

	.hff-hero__text {
		max-width: none;
	}
}

@media (prefers-reduced-motion: reduce) {
	.hff-hero__bar-fill {
		transition: none;
	}
}
