/**
 * Homepage-only sections: hero, trust bar. Section markup lives in
 * template-parts/sections/. Pricing card styles, the template-showcase
 * grid (.templates-layout/.template-grid/etc.), .final-cta and
 * .hero__actions (found 2026-09-06 to have the exact same bug —
 * reused on the Website Design detail page and homepage hero
 * respectively, but styled here, front-page-only) all moved to
 * components.css since they're shared across pages — this file is
 * only enqueued on the front page (see inc/enqueue.php). Before
 * putting a new rule here, confirm its markup is truly never rendered
 * anywhere but the homepage — this mistake has now happened 4 times.
 */

/* ---------- Hero ---------- */

.hero {
	padding-block: var(--space-10) var(--space-16);
}

.hero__inner {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-10);
	align-items: center;
}

/* Customizer → Hero Slider Behaviour → "Mobile: Show Image Above Text"
   (added 2026-09-13) — mobile-only by design: .hero__inner switches to
   a real two-column grid at ≥1024px (see the desktop override further
   down), where image-vs-text order is a left/right decision, not a
   stacking one, so this modifier is scoped to below that breakpoint. */
@media (max-width: 1023.98px) {
	.hero--mobile-image-first .hero__visual {
		order: -1;
	}
}

/* The whole left-column content block (eyebrow, title, lede, feature
   chips, CTA buttons) is centred as a unit, per explicit request —
   the visual/slides column on the right is unaffected. */
.hero__content {
	text-align: center;
}

.hero__eyebrow {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	color: var(--color-primary);
	font-weight: var(--fw-semibold);
	font-size: var(--fs-sm);
	margin-bottom: var(--space-4);
}

.hero__title {
	margin-bottom: var(--space-5);
}

.hero__lede {
	font-size: var(--fs-lg);
	max-width: 46ch;
	margin-inline: auto;
}

/* ---------- Hero slider ---------- */

/* Fixed 2026-09-13: display:none/block on .hero-slide meant only the
   active slide ever took up space, so .hero__slides' own height was
   whatever that one slide's text happened to need — every time the
   slider advanced to a shorter or longer headline, the whole page's
   content below the hero shifted and the scrollbar visibly grew/shrank.
   Standard fix for a text carousel with variable-length slides: stack
   every slide in the exact same grid cell (grid-area: 1 / 1 below) so
   ALL of them, active or not, count toward sizing this container —
   its height becomes the tallest slide's height and stays fixed
   regardless of which one is currently shown. Inactive slides are
   hidden with visibility (not display), which still removes them from
   the tab order and the accessibility tree — same as before, just
   without collapsing their box out of the layout. */
.hero__slides {
	display: grid;
}

.hero-slide {
	grid-area: 1 / 1;
	visibility: hidden;
	opacity: 0;
	pointer-events: none;
}

.hero-slide.is-active {
	visibility: visible;
	opacity: 1;
	pointer-events: auto;
	animation: appiappi-hero-fade-in 350ms ease;
}

@keyframes appiappi-hero-fade-in {
	from {
		opacity: 0;
		transform: translateY(6px);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

.hero-dots {
	display: flex;
	justify-content: center;
	gap: var(--space-2);
	margin-top: var(--space-6);
}

.hero-dots button {
	width: 8px;
	height: 8px;
	padding: 0;
	border: none;
	border-radius: var(--radius-full);
	background: var(--color-neutral-300);
	transition: width var(--transition-base), background var(--transition-base);
}

.hero-dots button.is-active {
	width: 24px;
	background: var(--color-primary);
}

.hero__visual {
	position: relative;
	/* Lets .rating-card below size itself off THIS element's own width
	   (via cqw units) rather than the viewport's — the two normally
	   track closely at mobile widths, but only the container's actual
	   width is what the "stay 10px clear of the image edges" rule
	   (2026-09-13) is really about. */
	container-type: inline-size;
}

.hero__visual-frame {
	position: relative;
	border-radius: var(--radius-xl);
	overflow: hidden;
	aspect-ratio: 4 / 3;
	background: var(--color-navy-800);
}

.hero__visual-frame img,
.hero__visual-frame .hero-slide-visual {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	opacity: 0;
	transition: opacity 400ms ease;
}

.hero__visual-frame img.is-active,
.hero__visual-frame .hero-slide-visual.is-active {
	opacity: 1;
}

.hero__visual-frame .hero-slide-visual svg {
	display: block;
	width: 100%;
	height: 100%;
}

/* ---------- Hero illustration effects (Customizer → Hero Illustration
   Effects) ---------- */
/* Base fill always follows the admin's chosen colour, whether or not
   the blink animation itself is on — see
   appiappi_render_hero_placeholder_svg() for the "is-animated"
   modifier, and the inline custom properties set on .hero__visual-frame
   in appiappi_render_hero_slides() for where these var()s come from. */
.hero-antenna-light {
	fill: var(--hero-light-color, #1e5eff);
}

.hero-antenna-light.is-animated {
	animation: hero-light-blink calc(1.6s / var(--hero-light-speed-multiplier, 1)) ease-in-out infinite;
	transform-origin: center;
}

@keyframes hero-light-blink {
	0%, 100% {
		opacity: 0.35;
		filter: drop-shadow(0 0 1px var(--hero-light-color, #1e5eff));
	}
	50% {
		opacity: 1;
		filter: drop-shadow(0 0 6px var(--hero-light-color, #1e5eff));
	}
}

.hero-window {
	fill: var(--hero-windows-color, #f7b955);
}

.hero-window.is-animated {
	animation-name: hero-window-blink;
	animation-timing-function: ease-in-out;
	animation-iteration-count: infinite;
	/* animation-delay/-duration come from each <rect>'s own inline style
	   in hero-placeholder.svg — different per window so the flicker
	   never looks synchronized, but all scaled by the same
	   --hero-windows-speed-multiplier so the Window Flicker Speed
	   setting still moves every window together. */
}

@keyframes hero-window-blink {
	0%, 60%, 100% {
		opacity: 0.3;
	}
	30% {
		opacity: 0.95;
	}
}

.hero-star {
	fill: var(--hero-stars-color, #ffffff);
}

.hero-star.is-animated {
	animation-name: hero-star-twinkle;
	animation-timing-function: ease-in-out;
	animation-iteration-count: infinite;
	/* animation-delay/-duration come from each <circle>'s own inline
	   style in hero-placeholder.svg — same per-element-offset,
	   shared-multiplier pattern as .hero-window above. */
}

@keyframes hero-star-twinkle {
	0%, 100% {
		opacity: 0.25;
	}
	50% {
		opacity: 1;
	}
}

@media (prefers-reduced-motion: reduce) {
	.hero-antenna-light.is-animated,
	.hero-window.is-animated,
	.hero-star.is-animated {
		animation: none;
		opacity: 0.75;
	}
}

/* Bottom-center, overlapping the image itself, on every viewport width
   (was top-right on desktop and a normal-flow block below the image on
   mobile — unified 2026-09-13 per explicit request that mobile match
   desktop's position exactly). A fixed gap from the image's own bottom
   edge (not flush against it) via `bottom`, centered via
   left:50%/translateX(-50%) rather than inset:auto + margin-inline:auto,
   since this element's width is intrinsic (max-width, not 100%) and
   needs to stay centered regardless of exactly how wide its content
   makes it. Lives inside .hero__visual (position:relative), so this
   positions against the image frame, not the whole page. */
/* Fixed 2026-09-13: as the image narrows (mobile, or just a narrower
   window), this card must never wrap its text onto a second line. The
   fix has two parts working together — a hard boundary and a fluid
   scale inside it:
   1. max-width: calc(100% - 20px) — against .hero__visual's own width
      (the %-basis for an absolute-positioned element with a
      position:relative ancestor), so the card can never render closer
      than 10px to the image's left/right edges no matter what.
   2. font-size: clamp(floor, Xcqw, 1rem) — driven by cqw (relative to
      that same .hero__visual container, see container-type: inline-size
      above). The card's natural, unscaled width is ~260px, so it should
      only start shrinking once the container narrows past 260px + the
      20px clearance = 280px — tuning X so the "Xcqw" term equals
      exactly 1rem (16px) right at a 280px container makes that the
      precise hand-off point: at ≥280px the clamp holds at its 1rem
      ceiling (full, unscaled size); below it, font-size (and, since
      every child below is sized in em against it, the whole card)
      shrinks in direct proportion to the container — smoothly, and
      only as far as it needs to — down to a 0.6rem floor for
      legibility at the pathologically narrow end.
      X = 1rem ÷ (280px × 1%) = 16px ÷ 2.8px ≈ 5.71.
   white-space: nowrap (here and on every child span) forbids wrapping
   outright; overflow: hidden is just a last-resort safety net for
   anything narrower than the floor can rescue. */
.rating-card {
	display: flex;
	align-items: center;
	gap: 0.75em;
	background: var(--color-white);
	border-radius: var(--radius-lg);
	box-shadow: var(--shadow-lg);
	padding: 1em 1.25em;
	position: absolute;
	left: 50%;
	bottom: var(--space-6);
	transform: translateX(-50%);
	width: fit-content;
	max-width: calc(100% - 20px);
	white-space: nowrap;
	overflow: hidden;
	font-size: clamp(0.6rem, 5.71cqw, 1rem);
	z-index: 2;
}

.rating-card__icon {
	flex-shrink: 0;
}

.rating-card__icon .icon {
	width: 1.5em;
	height: 1.5em;
}

/* Column of 1 or 2 lines: align-items: center is what actually centers
   the placeholder's second line ("coming soon") under the width of the
   first ("★★★★★ Google Reviews") — simpler and more robust than trying
   to text-align/width:100% a shrink-to-fit flex item by hand. With a
   real rating there's only ever the one line (.rating-card__line1), so
   this has nothing to center against and is a no-op. */
.rating-card__body {
	display: flex;
	flex-direction: column;
	align-items: center;
	min-width: 0;
}

.rating-card__line1 {
	display: flex;
	align-items: baseline;
	gap: 0.35em;
}

.rating-card__score {
	font-size: 1.375em;
	font-weight: var(--fw-bold);
	color: var(--color-neutral-900);
	line-height: 1;
}

.rating-card__stars {
	color: var(--color-warning);
	font-size: 0.9375em;
	letter-spacing: 2px;
}

.rating-card__caption {
	font-size: 0.8125em;
	color: var(--color-text-muted);
}

.rating-card__caption-secondary {
	font-size: 0.8125em;
	color: var(--color-text-muted);
}

.rating-card--placeholder .rating-card__score,
.rating-card--placeholder .rating-card__stars {
	color: var(--color-neutral-400);
}

/* Placeholder-only position (added 2026-09-13): straddles the image's
   own bottom edge — half the card inside the image, half below it —
   instead of sitting fully inside like the real-rating state above.
   bottom: 0 anchors the card's own bottom edge to the image's bottom
   edge, and translateY(50%) then shifts it down by exactly half its
   own (now taller, 2-line) height, centering that edge on the seam
   instead. Reverts to the plain .rating-card position automatically
   the moment a real rating exists (this class stops being added). */
.rating-card--placeholder {
	bottom: 0;
	transform: translate(-50%, 50%);
}

@media (min-width: 1024px) {
	.hero {
		padding-block: var(--space-16) var(--space-24);
	}

	.hero__inner {
		grid-template-columns: 1fr 1fr;
		gap: var(--space-16);
		padding-inline: var(--hero-pad-desktop);
	}

	/* Matches the sitewide sidebar's own height cap (components.css,
	   .page-sidebar__card .templates-sidebar__categories) so the
	   homepage's Categories card reads the same way as the one on
	   Contact/FAQ/etc — added 2026-09-13. Scoped here rather than
	   components.css since it's specific to this page's own instance of
	   the richer .templates-sidebar__card (the /templates/ archive's
	   own copy keeps growing naturally — its main column, the design
	   grid, is always the taller one there anyway). */
	.templates-sidebar__card .templates-sidebar__categories {
		max-height: 60vh;
		overflow-y: auto;
		overflow-x: hidden;
	}
}

/* Pricing preview + Website Designs preview: their own desktop side
   padding (configurable, see tokens.css), separate from the sitewide
   --container-pad — targeted via each section's existing #id rather
   than a new class, since both already have one. */
@media (min-width: 768px) {
	#pricing > .container {
		padding-inline: var(--pricing-preview-pad-desktop);
	}

	#templates > .container {
		padding-inline: var(--templates-preview-pad-desktop);
	}
}

/* Trust bar: moved to components.css 2026-09-07 (shared with the About
   page, which this front-page-only file never reached). */

