/*
Theme Name: LLF Block Theme
Author: Haji Ismael
Version: 1.0.0
Text Domain: figma-block-theme
*/

/* Target the auto-generated wp:template-part wrapper, not .llf-header itself:
   that wrapper only ever contains this one block, so it's exactly the same
   height as .llf-header - sticky positioning is bound by its own containing
   block, and a containing block with zero extra height gives it nowhere to
   "stick" as the page scrolls (it moves off with the rest of the page,
   indistinguishable from static). The wrapper's own containing block
   (.wp-site-blocks) is the full page height, which is what sticky actually
   needs. */
header.wp-block-template-part {
	position: sticky;
	top: 0;
	z-index: 100;
}

.llf-nav-active > a {
	color: var(--wp--preset--color--primary) !important;
}

/* Match the footer's link hover treatment (pale-blue -> sky blue), while
   the active page keeps its green highlight regardless of hover. The
   nav's textColor block support renders with !important, so the hover
   color needs !important too to actually take effect. */
.llf-header-nav .wp-block-navigation-item:not(.llf-nav-active) > a:hover {
	color: var(--wp--preset--color--secondary-light) !important;
}

/* GoDaddy Managed WordPress runs a host-level "contrast fallback" mu-plugin
   that force-colors any heading/paragraph/link inside a background-colored
   group block that isn't carrying WordPress's own has-text-color class, at
   high specificity with !important. Our nav and footer links get their
   color from these plain class rules rather than a block color attribute,
   so on that host they silently render white. These variants exceed that
   rule's specificity so the intended colors hold on every host, not only
   ones without that plugin. */
body .llf-header.has-contrast-background-color .wp-block-navigation.llf-header-nav .wp-block-navigation-item > a {
	color: var(--wp--preset--color--pale-blue) !important;
}

body .llf-header.has-contrast-background-color .wp-block-navigation.llf-header-nav .llf-nav-active > a {
	color: var(--wp--preset--color--primary) !important;
}

body .llf-header.has-contrast-background-color .wp-block-navigation.llf-header-nav .wp-block-navigation-item:not(.llf-nav-active) > a:hover {
	color: var(--wp--preset--color--secondary-light) !important;
}

body .llf-footer.has-contrast-background-color .llf-footer-row .llf-footer-links.wp-block-group a {
	color: var(--wp--preset--color--pale-blue) !important;
}

body .llf-footer.has-contrast-background-color .llf-footer-row .llf-footer-links.wp-block-group a:hover {
	color: var(--wp--preset--color--secondary-light) !important;
}

/* Same contrast-fallback plugin also force-colors any is-style-outline button's text AND
   border to a dark "contrast" fallback whenever it sits inside a background-colored group
   block, regardless of the button's own color/border classes - hits "Explore Our Portfolio"
   (.llf-cta has-secondary-background-color) and "Read Full Story"
   (.llf-featured-story has-base-background-color). Confirmed on the live host: both were
   rendering as rgb(18,48,62) text+border instead of their intended colors. The plugin's
   <style> tag loads after this file in <head>, so these need to out-specify its selector
   outright (7+ classes to its 6), not just rely on !important + source order - a selector
   that only ties its specificity still loses, since the plugin's tag loads later. */
body .llf-cta.has-secondary-background-color .wp-block-button.is-style-outline .wp-block-button__link.has-base-color.has-border-color {
	color: var(--wp--preset--color--base) !important;
	border-color: var(--wp--preset--color--primary) !important;
}

body .llf-featured-story.has-base-background-color .wp-block-button.is-style-outline .wp-block-button__link.has-tertiary-color.has-text-color {
	color: var(--wp--preset--color--tertiary) !important;
	border-color: var(--wp--preset--color--tertiary) !important;
}

/* "Read Full Story"'s own hover text-color swap (below, in the site-wide button-interaction-
   states section) is a separate selector from the one above and loses the same specificity
   fight on its own - without this it hovers to slate-teal-on-teal instead of the intended
   white-on-teal swap. Also resets opacity: the plugin has a THIRD rule, scoped the same way
   but at :hover, that fades these buttons to 0.75 opacity on hover - confirmed live, this is
   the "hover looks transparent" symptom on the deployed site. */
body .llf-featured-story.has-base-background-color .wp-block-button.is-style-outline .wp-block-button__link.has-tertiary-color.has-text-color:hover {
	background-color: var(--wp--preset--color--tertiary) !important;
	color: var(--wp--preset--color--base) !important;
	opacity: 1 !important;
}

body .llf-cta.has-secondary-background-color .wp-block-button.is-style-outline .wp-block-button__link.has-base-color.has-border-color:hover {
	opacity: 1 !important;
}

.has-text-align-justify {
	text-align: left;
}

.llf-cta h2 {
	/* Widened from 460px after the heading-hierarchy pass bumped this from
	   35px to the 42px xx-large size - the narrower cap was tuned for the old
	   size and wrapped to 3 lines at the new one; 590px lands back on 2
	   (measured: crosses over from 3 to 2 lines at ~568px). */
	max-width: 590px;
	margin-left: auto;
	margin-right: auto;
}

.llf-cta-buttons {
	gap: 16px;
}

.llf-quote-avatar-row {
	gap: 12px;
}

/* align-items:flex-start (WP's flex layout defaults to center) - the 4
   columns' labels wrap to different numbers of lines as the card narrows,
   and centering each column against its own row height made the shorter
   ones drift down and the taller ones drift up instead of keeping all 4
   values on one shared top line. */
.llf-hero-stats {
	width: 100%;
	box-sizing: border-box;
	background-color: rgba(223, 237, 244, 0.73);
	backdrop-filter: blur(12.5px);
	-webkit-backdrop-filter: blur(12.5px);
	box-shadow: 0 4px 36px 37px rgba(0, 0, 0, 0.25);
	align-items: flex-start;
}

/* flex-shrink:0 - as a flex item with the default shrink:1 and only a 1px
   flex-basis, this is the first thing the row reaches for whenever it needs
   to squeeze even a fraction of a px (the stat text can't shrink below its
   own content width, so the divider absorbs 100% of it and disappears).
   align-self:stretch (rather than a fixed height) so it keeps spanning the
   full row now that the row's height is however tall the tallest wrapped
   column gets, instead of a value tuned for the old centered layout. */
.llf-stat-divider {
	display: inline-block;
	flex-shrink: 0;
	width: 1px;
	align-self: stretch;
	background-color: rgba(42, 75, 89, 0.25);
}

/* min-height, not height: the aspect-ratio-driven value is too short to fit
   the heading/buttons/stats rail from roughly 900px up to ~1400px wide
   (verified: the rail overflows by as much as 300px around 1024px, and only
   fully clears the calc'd height again past ~1440px) - a hard height clips
   the overflow via .llf-hero's overflow:hidden below, cutting text off
   behind the header. min-height keeps the intended cinematic height on wide
   screens where content already fits, while letting the box grow on
   anything narrower instead of clipping it. */
.llf-hero {
	position: relative;
	min-height: calc(56.25vw - 93px);
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	justify-content: center;
}

.llf-hero-bg-layers {
	position: absolute;
	inset: 0;
	z-index: 0;
	-webkit-touch-callout: none;
}

.llf-hero-bg-slide {
	position: absolute;
	inset: 0;
	background-size: cover;
	background-position: center top;
	opacity: 0;
	transition: opacity 1000ms ease;
	transform-origin: center center;
	will-change: opacity, transform;
}

.llf-hero-bg-slide.is-active {
	opacity: 1;
	animation: llf-hero-zoom 3000ms ease-out forwards;
}

@keyframes llf-hero-zoom {
	from {
		transform: scale(1);
	}
	to {
		transform: scale(1.08);
	}
}

.llf-hero-gradient-overlay {
	position: absolute;
	inset: 0;
	z-index: 1;
	background: linear-gradient(97deg, rgba(6, 22, 28, 0.32) 45.26%, rgba(67, 145, 178, 0.32) 78.672%);
	pointer-events: none;
}

.llf-hero-rail {
	position: relative;
	z-index: 2;
	width: 80%;
	margin-left: auto;
	margin-right: auto;
	display: flex;
	flex-direction: column;
	gap: 115px;
}

.llf-hero-text-slides {
	display: grid;
	max-width: 812px;
}

.llf-hero-text-slide {
	grid-area: 1 / 1;
	min-width: 0; /* grid items default to min-width:auto, which would blow out to the heading's unwrapped width */
	opacity: 0;
	pointer-events: none;
	transition: opacity 1000ms ease;
}

.llf-hero-text-slide.is-active {
	opacity: 1;
	pointer-events: auto;
}

/* One-time entrance on first paint - scoped to :first-child (the only slide
   marked is-active in the static markup, so it's always what's visible on
   load) rather than .is-active itself, since .is-active keeps getting
   removed/re-added to different sibling slides every few seconds by the
   ongoing slideshow crossfade in hero.js - animating off that class would
   replay this on every slide change instead of just once. */
@keyframes llf-hero-enter {
	from {
		opacity: 0;
		transform: translateY(48px);
	}
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

/* Explicit resting state, not just the keyframe's own "from" via
   fill-mode:backwards - Safari doesn't reliably apply a delayed animation's
   backwards fill on first paint, so elements can flash their final
   (unanimated) state for a frame before snapping into the delayed
   animation. Setting the same opacity/transform here directly means
   they're already correct from first paint regardless of that timing. */
.llf-hero-text-slide:first-child h1,
.llf-hero-text-slide:first-child p,
.llf-hero-rail .wp-block-buttons .wp-block-button:first-child,
.llf-hero-stats,
.llf-hero-rail .wp-block-buttons .wp-block-button:last-child {
	opacity: 0;
	transform: translateY(48px);
}

.llf-hero-text-slide:first-child h1 {
	animation: llf-hero-enter 900ms ease-out both;
}

.llf-hero-text-slide:first-child p {
	animation: llf-hero-enter 900ms ease-out 150ms both;
}

/* Buttons animate independently rather than as one row, with the stats card
   interleaved between them (button 1, then stats, then button 2) instead of
   a strict top-to-bottom order - an async, staggered reveal rather than
   everything sliding up in lockstep. */
.llf-hero-rail .wp-block-buttons .wp-block-button:first-child {
	animation: llf-hero-enter 900ms ease-out 300ms both;
}

.llf-hero-stats {
	animation: llf-hero-enter 900ms ease-out 450ms both;
}

.llf-hero-rail .wp-block-buttons .wp-block-button:last-child {
	animation: llf-hero-enter 900ms ease-out 600ms both;
}

@media (prefers-reduced-motion: reduce) {
	.llf-hero-text-slide:first-child h1,
	.llf-hero-text-slide:first-child p,
	.llf-hero-rail .wp-block-buttons .wp-block-button:first-child,
	.llf-hero-stats,
	.llf-hero-rail .wp-block-buttons .wp-block-button:last-child {
		animation: none;
		/* Without the animation to carry them there, the explicit resting
		   state above (opacity:0, translateY(48px)) would otherwise leave
		   these permanently invisible instead of just skipping the motion. */
		opacity: 1;
		transform: none;
	}
}

/* WordPress's layout-class-injection heuristic (wp_render_layout_support_flag)
   misattributes the llf-hero-text-slides group's blockGap classes onto slide
   0's raw div instead of the group's own wrapper, since slide 0's div is the
   last tag in the raw HTML preceding the group's first real inner block -
   zeroing its h1/p margins while slides 1-3 keep the browser defaults. Pin
   the same defaults explicitly so all four slides render identically
   regardless of which one the heuristic mistargets. */
.llf-hero-text-slide h1 {
	margin-top: 0.67em !important;
	margin-bottom: 0.67em !important;
}

.llf-hero-text-slide p {
	margin-top: 1em !important;
	margin-bottom: 1em !important;
	/* Matches the two-button row's own rendered width (measured: a constant
	   ~408px across all desktop widths, since it's driven by fixed label
	   text/padding, not viewport) - only the paragraph is capped to it, not
	   the heading above, which keeps its original wider column. */
	max-width: 408px;
}

/* "Meet Our Leaders" rests at secondary-light, which is also the color the
   theme's global button-hover rule switches TO - so its resting
   has-secondary-light-background-color !important rule always wins over
   that non-important hover rule and the button never visibly changes.
   Beat it here with matching specificity + !important, in the opposite
   direction of the usual secondary -> secondary-light hover pattern. */
.llf-hero-rail .wp-block-button__link.has-secondary-light-background-color:hover {
	background-color: var(--wp--preset--color--secondary) !important;
}

/* Clicking/tapping drops the fill entirely and leaves just the outline in
   the button's own resting color - outline (not border) so it doesn't add
   to the box size and shift surrounding layout the way a border would. */
.llf-hero-rail .wp-block-button__link.has-secondary-light-background-color:active {
	background-color: transparent !important;
	outline: 2px solid var(--wp--preset--color--secondary-light);
	outline-offset: -2px;
}

/* "Partner With Us" follows the same accent pairing as CTA's "Explore Our
   Portfolio" (primary-green border, base text) rather than the hero's blue
   accents, so hover-filling it to primary green keeps the already-white
   text legible with no color swap needed - same reasoning CTA's outline
   button relies on. */
.llf-hero-rail .wp-block-button.is-style-outline .wp-block-button__link:hover {
	background-color: var(--wp--preset--color--primary) !important;
}

.llf-hero-rail .wp-block-button.is-style-outline .wp-block-button__link:active {
	background-color: transparent !important;
}

/* ==========================================================================
   Button interaction states (site-wide, outside the hero)

   Solid buttons: darken to a color-mixed shade on hover, drop to a
   transparent fill + outline in the resting color on click - `outline`
   rather than `border` so clicking never changes the button's box size.
   Outline buttons: invert on hover (fill with the border's own color),
   revert to transparent on click. Where a button's text color already
   matches its border (Read Mercy's Full Story), the text also swaps to
   base/white on hover so it stays legible against its own fill - buttons
   where text and border are already different colors (Explore Our
   Portfolio) don't need that swap.
   ========================================================================== */

.llf-cta .wp-block-button__link.has-primary-background-color:hover {
	background-color: color-mix(in srgb, var(--wp--preset--color--primary) 80%, black) !important;
}

.llf-cta .wp-block-button__link.has-primary-background-color:active {
	background-color: transparent !important;
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: -2px;
}

.llf-cta .wp-block-button.is-style-outline .wp-block-button__link:hover {
	background-color: var(--wp--preset--color--primary) !important;
}

.llf-cta .wp-block-button.is-style-outline .wp-block-button__link:active {
	background-color: transparent !important;
}

.llf-what-we-do .wp-block-button__link.has-tertiary-background-color:hover,
.llf-featured-story .wp-block-button__link.has-tertiary-background-color:hover {
	background-color: color-mix(in srgb, var(--wp--preset--color--tertiary) 80%, black) !important;
}

.llf-what-we-do .wp-block-button__link.has-tertiary-background-color:active,
.llf-featured-story .wp-block-button__link.has-tertiary-background-color:active {
	background-color: transparent !important;
	outline: 2px solid var(--wp--preset--color--tertiary);
	outline-offset: -2px;
}

.llf-featured-story .wp-block-button.is-style-outline .wp-block-button__link:hover {
	background-color: var(--wp--preset--color--tertiary) !important;
	color: var(--wp--preset--color--base) !important;
}

.llf-featured-story .wp-block-button.is-style-outline .wp-block-button__link:active {
	background-color: transparent !important;
	color: var(--wp--preset--color--tertiary) !important;
}

/* Header "Donate" has no explicit backgroundColor block attribute, so it
   rests on the global secondary default rather than a has-background
   class - scope by section instead of by color class. */
.llf-header .wp-block-button__link:hover {
	background-color: color-mix(in srgb, var(--wp--preset--color--secondary) 80%, black) !important;
}

.llf-header .wp-block-button__link:active {
	background-color: transparent !important;
	outline: 2px solid var(--wp--preset--color--secondary);
	outline-offset: -2px;
}

.llf-hero-pause-toggle {
	position: absolute;
	z-index: 3;
	bottom: 32px;
	right: 32px;
	width: 40px;
	height: 40px;
	border: none;
	border-radius: 50%;
	background-color: rgba(223, 237, 244, 0.73);
	backdrop-filter: blur(12.5px);
	-webkit-backdrop-filter: blur(12.5px);
	box-shadow: 0 4px 16px rgba(0, 0, 0, 0.18);
	display: flex;
	align-items: center;
	justify-content: center;
	cursor: pointer;
	color: var(--wp--preset--color--tertiary);
}

.llf-hero-pause-toggle:focus-visible {
	outline: 2px solid var(--wp--preset--color--secondary-light);
	outline-offset: 2px;
}

.llf-hero-pause-toggle[aria-pressed="true"] .llf-hero-pause-icon {
	display: none;
}

.llf-hero-pause-toggle[aria-pressed="false"] .llf-hero-play-icon {
	display: none;
}

@media (prefers-reduced-motion: reduce) {
	.llf-hero-bg-slide.is-active {
		animation: none;
		transform: none;
	}
}

.llf-visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.llf-coming-soon {
	position: relative;
	min-height: calc(100vh - 93px);
	display: flex;
	align-items: center;
	box-sizing: border-box;
	padding: 64px 80px;
	background-size: cover;
	background-position: center;
	overflow: hidden;
}

.llf-coming-soon-overlay {
	position: absolute;
	inset: 0;
	z-index: 0;
	pointer-events: none;
}

.llf-coming-soon-content {
	position: relative;
	z-index: 1;
	width: 100%;
	max-width: 900px;
	margin: 0 auto;
	text-align: center;
}

.llf-coming-soon-heading {
	color: var(--wp--preset--color--base);
	font-size: var(--wp--preset--font-size--huge);
	font-weight: 800;
	line-height: 1.1;
	margin: 0 0 24px;
	display: flex;
	align-items: center;
	justify-content: center;
}

.llf-coming-soon-o {
	display: inline-block;
	width: 0.65em;
	height: 0.65em;
	margin: 0 0.02em;
	background-image: url(assets/images/emblem-pattern-solid.svg);
	background-size: contain;
	background-repeat: no-repeat;
	background-position: center;
  margin-top: 0.15em;
}

.llf-coming-soon-desc {
	color: var(--wp--preset--color--base);
	font-size: var(--wp--preset--font-size--large);
	font-weight: 500;
	max-width: 620px;
	margin: 0 auto 32px;
}

.llf-coming-soon-form {
	display: flex;
	align-items: center;
	max-width: 560px;
	margin: 0 auto;
	padding: 4px;
	border: 1px solid rgba(255, 255, 255, 0.6);
	border-radius: 999px;
}

/* GoDaddy Managed WordPress's host-level "contrast fallback" mu-plugin also
   applies its own (non-!important, but high-specificity) default styling to
   any bare <input>/submit <button> that isn't a wp-element-button, forcing a
   white input background/navy text and killing the submit button's background
   via an undefined --wp--preset--color--accent-2 var. !important here beats
   it outright regardless of specificity, on every host. */
.llf-coming-soon-form .llf-input {
	flex: 1 1 auto;
	min-width: 0;
	border: none !important;
	border-radius: 0;
	background: transparent !important;
	color: var(--wp--preset--color--base) !important;
}

.llf-coming-soon-form .llf-input::placeholder {
	color: rgba(255, 255, 255, 0.75);
}

.llf-coming-soon-submit {
	background-color: var(--wp--preset--color--secondary) !important;
	color: var(--wp--preset--color--base) !important;
	border: none;
	border-radius: 999px;
	padding: 14px 32px;
	font-family: var(--wp--preset--font-family--questrial);
	font-size: var(--wp--preset--font-size--large);
	font-weight: 600;
	cursor: pointer;
	flex: 0 0 auto;
}

.llf-coming-soon-submit:hover {
	background-color: color-mix(in srgb, var(--wp--preset--color--secondary) 80%, black) !important;
}

.llf-coming-soon-submit:active {
	background-color: transparent !important;
	outline: 2px solid var(--wp--preset--color--secondary);
	outline-offset: -2px;
}

.llf-coming-soon-submit:disabled {
	opacity: 0.6;
	cursor: default;
}

.llf-coming-soon-form-message {
	margin: 16px 0 0;
	color: var(--wp--preset--color--base);
	font-weight: 600;
}

@media (max-width: 900px) {
	.llf-coming-soon {
		padding: 48px 32px;
	}

	/* The heading is a flex row (to align the decorative "o" emblem with the
	   text baseline) at a fixed 60px font-size with no wrap - on a narrow
	   viewport that overflows and forces "C"/the emblem/"ming Soon" to break
	   independently instead of together. Shrink the text and let the row
	   wrap as a whole so it degrades to two clean lines instead. */
	.llf-coming-soon-heading {
		font-size: 44px;
		flex-wrap: wrap;
	}
}

@media (max-width: 600px) {
	.llf-coming-soon {
		padding: 40px 20px;
	}

	.llf-coming-soon-heading {
		font-size: 34px;
	}
}

.llf-photo-wrap {
	position: relative;
}

.llf-photo-accent {
	position: absolute;
	top: -32px;
	right: -30px;
	width: 228px;
	height: 209px;
	background-color: var(--wp--preset--color--primary-light);
	border-radius: 45px;
	z-index: 0;
}

.llf-photo-img {
	position: relative;
	z-index: 1;
	margin: 0;
}

.llf-photo-img img {
	border-radius: 45px;
	display: block;
	width: 100%;
	aspect-ratio: 475.8 / 549.5;
	object-fit: cover;
}

/* Default center crop cuts off the boy on the right - pan just enough left
   to clear the first boy's face without cropping the second boy's out of
   frame on the right edge. */
.llf-what-we-do .llf-photo-img img {
	object-position: 60% center;
}

.llf-text-col > * + * {
	margin-top: 20px;
}

.llf-promise {
	position: relative;
	z-index: 1;
	/* Only the vertical bleed (into the sections above/below) is meant to be
	   visible - horizontally the section already spans the full viewport, so
	   a horizontal bleed only ever goes off-screen and just adds scrollable
	   dead space if left unclipped. `clip` (not `hidden`) is required on the
	   x-axis: pairing `hidden` with `visible` gets CSS-coerced to
	   `overflow-y: auto`, which still silently clips the vertical bleed from
	   view (just makes it technically scrollable) - `clip` is exempt from
	   that coercion, so overflow-y stays genuinely visible. */
	overflow-x: clip;
	overflow-y: visible;
}

.llf-promise-icon {
	margin-bottom: 0;
}

.llf-promise-emblem {
	position: absolute;
	width: 300px;
	height: 255px;
	background-image: url(assets/images/emblem-pattern.svg);
	background-repeat: no-repeat;
	background-size: contain;
	background-position: center;
	pointer-events: none;
}

.llf-promise-emblem--left {
	left: -50px;
	bottom: -20px;
}

.llf-promise-emblem--right {
	right: -50px;
	top: -15px;
	transform: scale(-1);
}

.llf-photo-accent--left {
	top: -28px;
	left: -26px;
	right: auto;
	width: 150px;
	height: 140px;
	border-radius: 30px;
}

.llf-photo-accent--right {
	/* top:auto is required, not just "bottom" alone: the base .llf-photo-accent
	   rule already sets top:-32px, and with an explicit height, top wins over
	   bottom whenever both are set - bottom is silently ignored otherwise. */
	top: auto;
	bottom: -28px;
	right: -26px;
	width: 150px;
	height: 140px;
	border-radius: 30px;
}

.llf-story-img {
	position: relative;
	z-index: 1;
	margin: 0;
}

.llf-story-img img {
	border-radius: 30px;
	display: block;
	width: 100%;
	/* Matches the first (nurse) image's native aspect ratio (481x397) so the
	   second (ambulance, native 537x343) crops to the same size instead of
	   rendering at its own, taller-relative-to-width proportions. */
	aspect-ratio: 481 / 397;
	object-fit: cover;
}

.llf-quote-card {
	position: relative;
}

/* WP's generated per-block container CSS forces margin-block-end:0 on every
   direct child of a flow-layout group at equal specificity, appearing later
   in the cascade than this stylesheet - it silently wins over a plain
   margin-bottom here, so this needs !important to actually pull the
   following content up. */
.llf-quote-mark {
	display: block;
	font-family: Georgia, serif;
	font-size: 96px;
	font-weight: 700;
	line-height: 1;
	color: var(--wp--preset--color--tertiary);
	margin-bottom: -0.6em !important;
}

.llf-avatar {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	width: 48px;
	height: 48px;
	border-radius: 50%;
	background-color: var(--wp--preset--color--tertiary);
	color: var(--wp--preset--color--base);
	font-size: 14px;
	font-weight: 700;
}

.llf-footer-logo {
	margin: 0;
}

.llf-footer-row {
	align-items: flex-start;
}

.llf-footer-links h4 {
	margin: 0 0 10px;
}

/* .llf-footer-links is display:block (its group block uses layout:"default",
   not flex/grid), so a "gap" property here would silently do nothing - the
   previous rule set gap:12px expecting it to space these lines out, but
   block-layout containers only respect margin, which is why the links were
   rendering with zero space between them despite that rule's presence. */
.llf-footer-links p {
	margin: 0 0 14px;
}

.llf-footer-links p:last-child {
	margin-bottom: 0;
}

.llf-footer-links a {
	color: var(--wp--preset--color--pale-blue);
	text-decoration: none;
}

.llf-footer-links a:hover {
	color: var(--wp--preset--color--secondary-light);
}

.llf-footer-form {
	display: flex;
	flex-direction: column;
	gap: 16px;
	width: 100%;
	max-width: 380px;
}

/* See the coming-soon-form comment above: GoDaddy's host-level contrast
   fallback also targets bare inputs/submit buttons here, so these need the
   same !important treatment. */
.llf-input {
	background-color: transparent !important;
	border: 1px solid rgba(223, 237, 244, 0.4) !important;
	border-radius: 8px;
	padding: 14px 16px;
	color: var(--wp--preset--color--pale-blue) !important;
	font-family: var(--wp--preset--font-family--questrial);
	font-size: 16px;
	width: 100%;
	box-sizing: border-box;
}

.llf-input::placeholder {
	color: rgba(223, 237, 244, 0.6);
}

.llf-textarea {
	min-height: 96px;
	resize: vertical;
}

.llf-input:focus {
	outline: none;
	border-color: var(--wp--preset--color--secondary-light) !important;
}

.llf-form-submit {
	background-color: var(--wp--preset--color--secondary) !important;
	color: var(--wp--preset--color--base) !important;
	border: none;
	border-radius: 8px;
	padding: 14px 16px;
	font-family: var(--wp--preset--font-family--questrial);
	font-size: 16px;
	font-weight: 500;
	cursor: pointer;
	width: 100%;
}

.llf-form-submit:hover {
	background-color: color-mix(in srgb, var(--wp--preset--color--secondary) 80%, black) !important;
}

.llf-form-submit:active {
	background-color: transparent !important;
	outline: 2px solid var(--wp--preset--color--secondary);
	outline-offset: -2px;
}

.llf-form-submit:disabled {
	opacity: 0.6;
	cursor: default;
}

.llf-footer-form-message {
	margin: 16px 0 0;
	color: var(--wp--preset--color--pale-blue);
	font-weight: 600;
}

.llf-footer-bottom {
	width: 100%;
	border-top: 1px solid rgba(223, 237, 244, 0.15);
	padding-top: 24px;
}

.llf-footer-copyright {
	margin: 0;
}

/* ==========================================================================
   Responsive
   ========================================================================== */

/* Header: keep logo and donor button their intrinsic size; let the nav
   row wrap beneath them instead of squeezing every item down to fit. */
.llf-header-logo,
.llf-header-actions {
	flex-shrink: 0;
}

.llf-header-actions .wp-block-buttons,
.llf-header-actions .wp-block-button,
.llf-header-actions .wp-block-button__link {
	flex-shrink: 0;
	white-space: nowrap;
}

@media (max-width: 900px) {
	.llf-header {
		padding-left: 24px;
		padding-right: 24px;
	}
}

/* The nav-overlay donor button only makes sense once the hamburger
   overlay takes over; on desktop it would sit inline in the nav row
   next to "For Funders", which duplicates the header one. */
.llf-nav-donor-btn {
	display: none !important;
}

/* Below 900px there's no longer room for logo + nav links + donor
   button on one line - collapse straight into the hamburger overlay
   instead of letting the nav links wrap to their own row. Core's
   Navigation block only exposes this toggle via a hardcoded 600px
   media query (wp-includes/blocks/navigation/style.css), so it has
   to be overridden directly rather than configured. */
@media (max-width: 900px) {
	.llf-header-actions {
		display: none !important;
	}

	.llf-nav-donor-btn {
		display: flex !important;
		justify-content: center;
		margin-top: 32px;
	}

	.llf-header-nav .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex !important;
	}

	.llf-header-nav .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
		display: none !important;
	}
}

@media (max-width: 600px) {
	.llf-header-logo img {
		width: 84px;
		height: auto;
	}
}

/* Redraw the nav toggle as a 3-line hamburger (core ships a 2-line icon). */
.llf-header-nav .wp-block-navigation__responsive-container-open {
	position: relative;
	width: 24px;
	height: 24px;
	padding: 0;
}

.llf-header-nav .wp-block-navigation__responsive-container-open svg {
	display: none;
}

.llf-header-nav .wp-block-navigation__responsive-container-open::before {
	content: "";
	position: absolute;
	top: 50%;
	left: 2px;
	right: 2px;
	height: 1.5px;
	background-color: currentColor;
	box-shadow: 0 -6px 0 currentColor, 0 6px 0 currentColor;
}

/* Hero: the desktop height is aspect-ratio driven off viewport width, which
   is too short to hold the heading, buttons, and stats row on narrow
   viewports. Let it size to its content instead. */
@media (max-width: 900px) {
	.llf-hero {
		height: auto !important;
		padding-left: 32px !important;
		padding-right: 32px !important;
	}

	.llf-hero-rail {
		width: 100% !important;
		gap: 48px !important;
		align-items: center !important;
	}

	.llf-hero-text-slide h1,
	.llf-hero-text-slide p {
		text-align: center;
	}

	/* The 408px desktop cap on the paragraph (matched to the buttons row's
	   width) is a "normal view" constraint only - at this width the rail is
	   already full-width, so let the paragraph use that same full width
	   instead of being squeezed into a narrow column. */
	.llf-hero-text-slide p {
		max-width: none !important;
	}

	.llf-hero-text-slide h1 {
		font-size: 38px !important;
	}

	.llf-hero-text-slide p {
		font-size: 18px !important;
	}

	/* Both buttons default to wrapping onto their own line on narrow
	   viewports (core's default flex-wrap for the buttons block) - force
	   them side by side and stretch them to fill the row instead of
	   shrinking them down to fit. */
	.llf-hero-rail .wp-block-buttons {
		flex-wrap: nowrap !important;
		gap: 12px !important;
		width: 100%;
	}

	.llf-hero-rail .wp-block-buttons .wp-block-button {
		flex: 1 1 0;
	}

	.llf-hero-rail .wp-block-buttons .wp-block-button__link {
		display: block;
		width: 100%;
		box-sizing: border-box;
		text-align: center;
		font-size: 16px;
		padding: 12px 16px;
	}
}

/* Mirrors the hero's own two-tier paragraph scale-down above so every
   section's body text shrinks in step with it instead of staying flat at
   the desktop 22px size down to phone widths. Excludes the quote text
   itself (.llf-quote-card > p, a direct child, not covered by either
   selector below) - its size was explicitly called out as "do not touch". */
@media (max-width: 900px) {
	.llf-what-we-do p,
	.llf-promise p,
	.llf-promise h4,
	.llf-cta p,
	.llf-featured-story .llf-text-col p,
	.llf-featured-story .llf-quote-avatar-row p,
	.llf-coming-soon-submit {
		font-size: var(--wp--preset--font-size--medium) !important;
	}
}

/* Pre-existing bug found while reworking this card for tablet padding (below):
   the "521-1200px keeps one line" rule this comment used to describe actually
   still overflowed by up to 34px from 521-599px (measured on the untouched,
   already-merged baseline, so unrelated to today's changes) - even with
   column-gap already down to 32px, the 4 columns' own natural content-width
   floor at these narrow widths exceeds available space regardless of padding
   (confirmed empirically: reducing padding all the way to 0 made zero
   difference in that range). Below 600px isn't actually a "tiny edge case"
   the way it looked before - it needs the same wrap fallback as sub-520px,
   just extended up to meet the 600px boundary the padding fix below already
   uses, rather than a separate narrow bucket in between. */
@media (max-width: 599px) {
	.llf-hero-stats {
		flex-wrap: wrap !important;
		row-gap: 24px;
		column-gap: 32px;
		padding-left: 24px;
		padding-right: 24px;
	}

	.llf-stat-divider {
		display: none;
	}
}

/* 600-1200px: covers the whole phone-landscape/tablet range (including iPad
   and Galaxy Tab portrait widths, ~768-834px) - keep the stats card on one
   line like desktop instead of growing vertically. The full 73px desktop gap
   doesn't fit until ~1140px, but shrinking it to 32px does across this entire
   range (measured: zero overflow at every width tested from 600px up to
   1200px; past 1200px the unmodified 73px gap already fits on its own). */
@media (min-width: 600px) and (max-width: 1200px) {
	.llf-hero-stats {
		column-gap: 32px;
	}
}

/* Less horizontal padding gives each stat column more room to wrap its label
   onto fewer lines, converging the 4 columns' heights (measured: 56px padding
   leaves the longer 3-word labels wrapping to 3 lines while shorter ones sit
   at 1-2; reducing to 16px lands most of them on the same line count). Shares
   the 600px boundary above rather than starting at 521px: freeing up that
   padding below 600px lets a label un-wrap onto a wider single line, which
   is exactly the overflow the wrap-fallback above exists to avoid. */
@media (min-width: 600px) and (max-width: 1200px) {
	.llf-hero-stats {
		padding-left: 16px !important;
		padding-right: 16px !important;
	}
}

@media (max-width: 480px) {
	.llf-hero {
		padding-left: 20px !important;
		padding-right: 20px !important;
	}

	.llf-hero-rail {
		gap: 32px !important;
	}

	.llf-hero-text-slide h1 {
		font-size: 32px !important;
	}

	.llf-hero-text-slide p {
		font-size: 16px !important;
	}

	.llf-hero-rail .wp-block-buttons {
		gap: 8px !important;
	}

	.llf-hero-rail .wp-block-buttons .wp-block-button__link {
		font-size: 15px;
		padding: 10px 14px;
	}

	.llf-hero-pause-toggle {
		width: 32px;
		height: 32px;
		bottom: 16px;
		right: 16px;
	}

	.llf-hero-stats {
		display: none !important;
	}
}

/* Second tier of the paragraph scale-down mirrored above at 900px. */
@media (max-width: 480px) {
	.llf-what-we-do p,
	.llf-promise p,
	.llf-promise h4,
	.llf-cta p,
	.llf-featured-story .llf-text-col p,
	.llf-featured-story .llf-quote-avatar-row p,
	.llf-coming-soon-submit {
		font-size: var(--wp--preset--font-size--small) !important;
	}
}

/* WP core stacks .wp-block-column into a single column at exactly this
   breakpoint (flex-basis:100% !important, from block-library/style.css) -
   these columns only ever declare a horizontal blockGap ("left"), so once
   stacked there's zero space between the now-full-width photo and text
   blocks. Add the missing vertical gap right where stacking actually
   happens. */
@media (max-width: 781px) {
	.llf-what-we-do .wp-block-columns,
	.llf-featured-story .wp-block-columns {
		row-gap: 32px;
	}
}

/* Featured story's second columns row (paragraph left, photo right) swaps
   which side is taller depending on viewport width - the paragraph is
   taller from 782px up to ~1090px (before it drops to fewer wrapped lines),
   the photo is taller again above that. Centered alignment (the block's own
   verticalAlignment:center) splits whichever height difference exists
   between the top and bottom of the row, so through this tablet band the
   paragraph ends up hard against the button below with the photo left
   dangling with slack space instead. Bottom-align just this row so both
   finish flush with the section's normal 48px gap either way (measured:
   0px imbalance at 900/1024/1200px). Left at the block's default `center`
   above 1200px, where the photo keeps growing taller than the text the
   wider it gets and this same fix would reopen a gap above the paragraph
   instead. The parent's own align-items is inert here (WP core forces
   align-items:initial !important on .wp-block-columns; the real alignment
   comes from each column's own align-self), so this overrides align-self
   directly. The `+` targets specifically the row that follows another
   columns row, leaving the first row's alignment untouched. */
@media (min-width: 782px) and (max-width: 1200px) {
	.llf-featured-story .wp-block-columns + .wp-block-columns > .wp-block-column {
		align-self: flex-end !important;
	}
}

/* Below 1130px the footer row wraps and the signup form ends up alone on
   its own line (measured: alone at 1139px, still beside "Connect" at
   1140px - this stays a little under that crossover rather than over it,
   since going the other way would let the uncapped form blow out while
   still sharing a row with the logo/links). The 380px desktop cap makes
   sense next to the other columns, but alone on a row it just leaves the
   form stranded on the left with empty space to its right instead of
   filling the row it now has to itself. */
@media (max-width: 1130px) {
	.llf-footer-form {
		max-width: none;
	}
}

/* Section padding: the 80px/72px desktop gutters overwhelm small screens. */
@media (max-width: 600px) {
	.llf-featured-story,
	.llf-promise,
	.llf-cta,
	.llf-what-we-do {
		padding-left: 24px !important;
		padding-right: 24px !important;
		padding-top: 40px !important;
		padding-bottom: 40px !important;
	}

	.llf-quote-card {
		padding: 32px 24px !important;
	}

	.llf-footer {
		padding-left: 24px !important;
		padding-right: 24px !important;
	}

	/* The logo, the two link lists, and the signup form wrap into an
	   uneven 2-up grid at this width (whichever pairs happen to fit
	   side by side) - stack them into a single column instead. */
	.llf-footer-row {
		flex-direction: column;
		align-items: stretch;
	}

	/* Section headings/copy are hardcoded desktop px sizes (no theme.json
	   preset backs them) - scale them down in step with the padding above
	   so mobile sections don't look mismatched next to the already-responsive
	   hero/header text around them. Bumped from 26 to 30: at 26 the gap to
	   h3 below (24px, in Featured Story) was only 2px - technically bigger
	   but not perceptibly so, especially since they're not adjacent (a
	   photo sits between them) and use different color treatments. */
	.llf-cta h2,
	.llf-promise h2,
	.llf-what-we-do-heading,
	.llf-featured-story-heading {
		font-size: 30px !important;
	}

	/* h1>h2>h3>h4 must hold at every breakpoint, not just desktop - and by
	   a perceptible margin, not just a technical one. h4 is floored at 20px
	   (the "From One Village..." heading in Featured Story) to clear the
	   18px mobile paragraph size below it; h3 (Wandikweza) stays at 24px,
	   4px clear of h4 and 6px clear of the 30px h2 above. */
	.llf-what-we-do h3,
	.llf-featured-story h3 {
		font-size: 24px !important;
	}

	.llf-featured-story h4 {
		font-size: 20px !important;
	}

	.llf-quote-mark {
		font-size: 56px !important;
	}

	/* "Learn More" defaults to a left-aligned flex row (wp:buttons has no
	   justifyContent set) - center it to match the rest of the stacked,
	   full-width mobile layout. */
	.llf-what-we-do .wp-block-buttons {
		justify-content: center;
	}
}

/* Decorative accent shapes are sized/positioned for desktop and can push
   narrow viewports into horizontal scroll; scale and reposition them so
   they stay within their photo. */
@media (max-width: 600px) {
	.llf-photo-accent {
		width: 120px;
		height: 110px;
		top: -18px;
		right: -16px;
	}

	.llf-photo-accent--left {
		top: -16px;
		left: -14px;
	}

	.llf-photo-accent--right {
		top: auto;
		bottom: -16px;
		right: -14px;
	}

	.llf-promise-emblem {
		width: 180px;
		height: 170px;
	}

	.llf-promise-emblem--left {
		left: -40px;
		bottom: -15px;
	}

	.llf-promise-emblem--right {
		right: -40px;
		top: -10px;
	}
}

.llf-featured-story,
.llf-hero {
	overflow: hidden;
}

