/*
Theme Name: Levinky
Theme URI: https://levinky.sk
Author: Robert Ruzek
Description: Custom FSE block theme for Levinky — new housing development in Levice, Slovakia.
Version: 0.1.0
Requires at least: 6.4
Tested up to: 6.7
Requires PHP: 8.1
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: levinky
Tags: full-site-editing, block-theme
*/

/* =========================================================
 * DESIGN TOKENS — source of truth is theme.json
 * Always prefer these CSS vars over hard-coded values.
 *
 * COLORS (--wp--preset--color--*)
 *   background       #F5F0E8  cream page bg
 *   surface          #FFFFFF  cards / sections on light
 *   ink              #000000  primary text / dark UI
 *   primary          #956F60  brown — primary buttons, accents
 *   primary-light    #E9D2C9  light brown — gradients
 *   secondary        #F0E5DE  tan — pills, soft accents
 *   muted            rgba(0,0,0,0.5)   secondary text
 *   muted-soft       rgba(0,0,0,0.25)  hint text
 *   divider          rgba(0,0,0,0.1)   1px borders / dividers
 *
 * FONTS (--wp--preset--font-family--*)
 *   display          Anxler        — all headings, body, descriptions
 *   sans             Capriola      — button + small UI labels
 *
 * FONT SIZES (--wp--preset--font-size--*)
 *   xs               12px (static)
 *   small            14px (static)
 *   medium           16px (static)
 *   lead             clamp(14px → 20px)  — section descriptions, hero copy
 *   large            clamp(20px → 24px)  — body emphasis
 *   x-large          clamp(28px → 40px)  — section H2s ("Benefity projektu" etc)
 *   xx-large         clamp(40px → 64px)  — page titles where applicable
 *   huge             clamp(42px → 96px)  — H1s (hero, blog archive, etc)
 *
 * SPACING (--wp--preset--spacing--*) — literal px slugs
 *   10, 16, 24, 30, 32, 40, 48, 50, 60, 72, 80, 100
 *
 * LAYOUT
 *   --wp--custom--layout--max-width    1840px (max site container)
 *   --wp--custom--radius--button       8px    (default button radius)
 * ========================================================= */

/* =========================================================
 * Base
 * ========================================================= */
/* Reserve scrollbar gutter always — prevents layout shift when the
 * menu opens (which sets body { overflow: hidden } and would otherwise
 * remove the scrollbar). */
html {
	scrollbar-gutter: stable;
}

body {
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

body.is-menu-open {
	overflow: hidden;
}

/* Override WP block library default block top-margin everywhere.
 * WP defines `:root :where(.is-layout-flow) > * { margin-block-start: 24px }`
 * which silently injects 24px gaps between block siblings. Toxic for
 * pixel-precise layouts. Killing it site-wide. */
.is-layout-flow > *,
.wp-site-blocks > * {
	margin-block-start: 0 !important;
}

/* =========================================================
 * Header — top bar (closed state)
 *
 * Fixed at viewport top on every page. On the homepage it's
 * transparent and overlays the hero photo; elsewhere it has
 * the cream bg. WP admin bar offset handled below.
 * ========================================================= */
.site-header {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 200;
	transition: background-color 0.4s ease;
	/* Slide-in entry: header drops down from above the viewport on page load.
	 * Works for both desktop full-bar and mobile pill (which uses top:16 via
	 * !important in @media — translateY moves whichever resting position). */
	animation: site-header-slide-in 0.7s cubic-bezier(0.22, 1, 0.36, 1) 100ms backwards;
}

@keyframes site-header-slide-in {
	from { transform: translateY(-100%); opacity: 0; }
	to   { transform: translateY(0); opacity: 1; }
}

/* WP admin bar offset: shift header below admin bar when logged in. */
.admin-bar .site-header {
	top: 32px;
}

@media screen and (max-width: 782px) {
	.admin-bar .site-header {
		top: 46px;
	}
}

/* When menu is open, header bg becomes transparent so the vertical
 * divider line (inside .site-menu, behind the header) shows through.
 * !important and broad selectors to defeat WP's block-supports background rules
 * which can be emitted with varying specificity depending on layout type. */
body.is-menu-open .site-header,
body.is-menu-open header.site-header,
body.is-menu-open .site-header.has-background-background-color,
body.is-menu-open header.site-header.has-background {
	background-color: transparent !important;
}

.site-header__inner {
	position: relative;
	max-width: var(--wp--custom--layout--max-width);
	margin: 0 auto;
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: nowrap;
}

.site-header__left,
.site-header__right {
	flex: 1 1 0;
	min-width: 0;
}

.site-header__right {
	justify-content: flex-end;
}

/* Logo — true center via absolute positioning */
.site-header__logo {
	position: absolute;
	left: 50%;
	top: 50%;
	transform: translate(-50%, -50%);
	display: inline-flex;
	align-items: center;
	color: var(--wp--preset--color--ink);
	line-height: 0;
}

.site-header__logo svg {
	display: block;
	width: 164px;
	height: 54px;
}

/* Nav links */
.site-header__nav-link {
	margin: 0;
	line-height: 1;
	text-transform: uppercase;
	letter-spacing: 0.04em;
}

.site-header__nav-link a {
	position: relative;
	display: inline-block;
	color: var(--wp--preset--color--ink);
	text-decoration: none;
	transition: color 0.2s ease;
}

/* Underline wipes in left→right on hover, and also exits left→right on
 * leave (continues in the same direction instead of retracting backwards).
 *
 * How: transform-origin is non-animatable (switches instantly between
 * pseudo-class states), so we set it to LEFT for the hovered state and
 * RIGHT for the default state. Enter: origin=left, scaleX 0→1 → grows
 * rightward. Leave: origin=right, scaleX 1→0 → left edge collapses
 * toward the right. */
.site-header__nav-link a::after {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	bottom: -4px;
	height: 1px;
	background: currentColor;
	transform: scaleX(0);
	transform-origin: right center;
	transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}

.site-header__nav-link a:hover,
.site-header__nav-link a:focus-visible {
	color: var(--wp--preset--color--primary);
}

.site-header__nav-link a:hover::after,
.site-header__nav-link a:focus-visible::after {
	transform: scaleX(1);
	transform-origin: left center;
}

/* CTA — DEFAULT: white bg, ink text, no border */
.site-header__cta .wp-block-button__link {
	background-color: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--ink);
	border: 0;
	transition: background-color 0.2s ease, color 0.2s ease;
}

.site-header__cta .wp-block-button__link:hover,
.site-header__cta .wp-block-button__link:focus-visible {
	background-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--surface);
}

/* CTA when menu is open — solid black */
body.is-menu-open .site-header__cta .wp-block-button__link {
	background-color: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--surface);
}

/* =========================================================
 * Menu toggle — CSS-morphing hamburger ↔ X
 * ========================================================= */
.site-header__menu-toggle {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	padding: 0;
	background: transparent;
	border: 0;
	color: var(--wp--preset--color--ink);
	cursor: pointer;
	transition: opacity 0.2s ease;
}

.site-header__menu-toggle:hover,
.site-header__menu-toggle:focus-visible {
	opacity: 0.6;
}

.site-header__menu-icon {
	position: relative;
	display: block;
	width: 22px;
	height: 14px;
}

.site-header__menu-icon__line {
	position: absolute;
	left: 0;
	right: 0;
	height: 2px;
	background: currentColor;
	transform-origin: center;
	transition:
		transform 0.4s cubic-bezier(0.65, 0, 0.35, 1),
		opacity 0.2s ease;
}

.site-header__menu-icon__line:nth-child(1) { top: 0; }
.site-header__menu-icon__line:nth-child(2) { top: 50%; margin-top: -1px; }
.site-header__menu-icon__line:nth-child(3) { bottom: 0; }

/* Morph to X when menu is open */
body.is-menu-open .site-header__menu-icon__line:nth-child(1) {
	transform: translateY(6px) rotate(45deg);
}

body.is-menu-open .site-header__menu-icon__line:nth-child(2) {
	opacity: 0;
	transform: scaleX(0);
}

body.is-menu-open .site-header__menu-icon__line:nth-child(3) {
	transform: translateY(-6px) rotate(-45deg);
}

/* =========================================================
 * Menu overlay
 * ========================================================= */
.site-menu {
	position: fixed;
	inset: 0;
	z-index: 150;
	background: var(--wp--preset--color--surface);
	/* NO scroll here — scrolling happens in .site-menu__scroll so the
	 * absolute-positioned wordmark/dividers stay locked to viewport bottom. */
	overflow: hidden;

	/* Fade-in transition. Visibility delay ensures the overlay only
	 * becomes inert (visibility:hidden) AFTER the opacity transition,
	 * so it actually animates out. */
	opacity: 0;
	visibility: hidden;
	transition:
		opacity 0.4s ease,
		visibility 0s linear 0.4s;
}

/* Scroll wrapper — handles overflow so the menu's absolutely-positioned
 * children (wordmark, dividers) stay locked to viewport edges. */
.site-menu__scroll {
	position: absolute;
	inset: 0;
	overflow-y: auto;
	overflow-x: hidden;
	padding-top: calc(54px + var(--wp--preset--spacing--24) * 2 + var(--wp--preset--spacing--80));
	/* 80px on desktop → 40px on small viewports. Linear scale 5vw+20px sits
	 * between: yields 40px at ~400vw, 80px at ~1200vw. */
	padding-bottom: clamp(40px, calc(5vw + 20px), 80px);
	padding-left: var(--wp--preset--spacing--40);
	padding-right: var(--wp--preset--spacing--40);
}

body.is-menu-open .site-menu {
	opacity: 1;
	visibility: visible;
	transition:
		opacity 0.4s ease,
		visibility 0s linear 0s;
}

/* Dividers — break out of container, full viewport extent */
.site-menu__divider {
	position: absolute;
	background: var(--wp--preset--color--divider);
	pointer-events: none;
	opacity: 0;
	transition: opacity 0.5s ease 0.2s;
}

body.is-menu-open .site-menu__divider {
	opacity: 1;
}

.site-menu__divider--vertical {
	top: 0;
	bottom: 0;
	left: 50%;
	width: 1px;
	height: 100vh;
	z-index: 1;
}

/* Decorative Levinky wordmark glued to the very bottom of the viewport.
 * Sits BEHIND the vertical divider line (lower z-index) and behind menu content. */
.site-menu__wordmark {
	position: absolute;
	bottom: 0;
	left: 50%;
	transform: translateX(-50%);
	width: 100%;
	max-width: 1840px;
	height: auto;
	pointer-events: none;
	opacity: 0;
	transition: opacity 0.6s ease 0.3s;
	z-index: 0; /* below the divider */
}

body.is-menu-open .site-menu__wordmark {
	opacity: 1;
}

.site-menu__inner {
	position: relative;
	z-index: 2; /* above divider + wordmark */
	max-width: var(--wp--custom--layout--max-width);
	margin: 0 auto;
	display: grid;
	grid-template-columns: 1fr 1fr;
	grid-template-rows: 1fr auto; /* row 1 fills available, footer (row 2) pinned to bottom */
	grid-template-areas:
		"hero nav"
		"footer footer";
	gap: var(--wp--preset--spacing--60);
	min-height: calc(100vh - 54px - var(--wp--preset--spacing--24) * 2 - 150px - var(--wp--preset--spacing--80));
}

/* Stagger children fading in */
.site-menu__hero,
.site-menu__nav,
.site-menu__footer {
	opacity: 0;
	transform: translateY(20px);
	transition:
		opacity 0.5s ease,
		transform 0.5s ease;
}

body.is-menu-open .site-menu__hero {
	opacity: 1;
	transform: translateY(0);
	transition-delay: 0.15s;
}

body.is-menu-open .site-menu__nav {
	opacity: 1;
	transform: translateY(0);
	transition-delay: 0.25s;
}

body.is-menu-open .site-menu__footer {
	opacity: 1;
	transform: translateY(0);
	transition-delay: 0.35s;
}

/* HERO — left column */
.site-menu__hero {
	grid-area: hero;
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
	padding-right: var(--wp--preset--spacing--80);
	max-width: 600px;
	margin: 0 auto;
}

.site-menu__title {
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--xx-large);
	line-height: 1;
	letter-spacing: normal; /* Figma context shows no global tracking on title — only `ď` has -1.76px */
	color: var(--wp--preset--color--ink);
	margin: 0 0 var(--wp--preset--spacing--40);
	font-weight: 400;
	/* No align-self: stretch — let title size to content so it can center via __hero's align-items: center */
	width: max-content;
	max-width: 100%;
}

.site-menu__title-line {
	display: block;
}

/* Indent of second line so "b" sits below the "Z" of "Blízko" above.
 * "Blízko" = B + l + í + Z + k + o. The Z is the 4th glyph.
 * In Anxler at 64px, B+l+í width ≈ 1.3em. */
.site-menu__title-line--indent {
	padding-left: 1.3em;
}

.site-menu__lead {
	font-family: var(--wp--preset--font-family--display);
	font-size: 1rem; /* literal per repeated request — design system token wasn't satisfying user */
	line-height: 1.6;
	color: var(--wp--preset--color--muted);
	margin: 0 0 var(--wp--preset--spacing--60);
	text-align: center;
}

.site-menu__hero-actions {
	display: flex;
	gap: var(--wp--preset--spacing--16);
	justify-content: center;
	flex-wrap: wrap;
}

/* NAV — right column */
.site-menu__nav {
	grid-area: nav;
	display: flex;
	flex-direction: column;
	justify-content: center;
	padding-left: var(--wp--preset--spacing--80);
}

.site-menu__nav-label {
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--xs);
	color: var(--wp--preset--color--muted);
	/* 48px small viewports → 72px wide. Linear scale 3vw+36px sits between. */
	margin: 0 0 clamp(48px, calc(3vw + 36px), 72px);
	/* Align with menu items TEXT (which is offset by marker col 22 + gap 16 = 38) */
	padding-left: calc(22px + var(--wp--preset--spacing--16));
}

.site-menu__nav ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--50);
}

/* Each nav row: marker on left in its own 22px column, link to the right.
 * Marker is invisible by default; on hover/active it just fades in.
 * No movement — only opacity 0 → 1 per spec. */
.site-menu__nav li {
	display: grid;
	grid-template-columns: 22px auto;
	column-gap: var(--wp--preset--spacing--16);
	align-items: center;
}

.site-menu__nav-marker {
	color: var(--wp--preset--color--primary);
	opacity: 0;
	transition: opacity 0.25s ease;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	line-height: 0;
}

.site-menu__nav-marker svg {
	display: block;
	width: 22px;
	height: 22px;
	min-width: 22px;
	flex-shrink: 0;
}

.site-menu__nav a {
	font-family: var(--wp--preset--font-family--sans);
	font-size: var(--wp--preset--font-size--x-large);
	text-transform: uppercase;
	letter-spacing: 0.01em;
	line-height: 1;
	color: var(--wp--preset--color--muted-soft);
	text-decoration: none;
	transition: color 0.25s ease, transform 0.25s ease;
}

.site-menu__nav li:hover .site-menu__nav-marker,
.site-menu__nav li:focus-within .site-menu__nav-marker,
.site-menu__nav li.is-active .site-menu__nav-marker {
	opacity: 1;
}

.site-menu__nav li:hover a,
.site-menu__nav li:focus-within a,
.site-menu__nav li.is-active a {
	color: var(--wp--preset--color--ink);
	transform: translateX(8px);
}

/* FOOTER — full-width row, left half + right half */
.site-menu__footer {
	grid-area: footer;
	position: relative;
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--wp--preset--spacing--40);
	padding-top: var(--wp--preset--spacing--40);
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--xs);
}

/* Horizontal divider — from viewport LEFT edge to vertical divider.
 * The +var(--scrollbar-width)/2 buffer compensates for scrollbar-gutter:
 * 50vw includes the scrollbar gutter but footer's centered position doesn't,
 * so without compensation the line would end short by half a scrollbar width. */
.site-menu__footer::before {
	content: "";
	position: absolute;
	top: -100px;
	left: calc((100% - 100vw) / 2);
	width: calc(50vw + (var(--scrollbar-width, 0px) / 2) + 1px);
	height: 1px;
	background: var(--wp--preset--color--divider);
	pointer-events: none;
	opacity: 0;
	transition: opacity 0.5s ease 0.2s;
	z-index: 0; /* below vertical divider (z-index: 1) so vertical paints over any overlap */
}

body.is-menu-open .site-menu__footer::before {
	opacity: 1;
}

.site-menu__footer-left {
	display: grid;
	grid-template-columns: auto auto auto;
	gap: var(--wp--preset--spacing--60);
	align-items: end;
}

.site-menu__footer-right {
	display: flex;
	justify-content: flex-start;
	align-items: end;
	/* Visual alignment with the menu nav text (intentional tweak — 132px
	 * gives the legal block a slight inset past the nav-text edge per the
	 * latest design pass). Overridden to 0 + center-justify at ≤1050px. */
	padding-left: 132px;
}

.site-menu__contact {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--16);
	line-height: 1;
}

.site-menu__contact p {
	margin: 0;
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--16);
	color: var(--wp--preset--color--ink);
	line-height: 1;
}

.site-menu__contact-icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	color: var(--wp--preset--color--ink);
}

.site-menu__contact-icon svg {
	display: block;
}

.site-menu__contact a {
	color: inherit;
	text-decoration: none;
	line-height: 1;
}

.site-menu__contact a:hover {
	color: var(--wp--preset--color--primary);
}

.site-menu__social {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--16);
	line-height: 1;
}

.site-menu__social a {
	color: var(--wp--preset--color--ink);
	text-decoration: none;
	line-height: 1;
}

.site-menu__social a:hover {
	color: var(--wp--preset--color--primary);
}

.site-menu__address {
	margin: 0;
	color: var(--wp--preset--color--ink);
	line-height: 1.4;
}

.site-menu__legal {
	display: flex;
	gap: var(--wp--preset--spacing--24);
	color: var(--wp--preset--color--muted);
	line-height: 1.4;
}

.site-menu__legal a {
	color: inherit;
	text-decoration: none;
}

.site-menu__legal a:hover {
	color: var(--wp--preset--color--primary);
}

/* =========================================================
 * Future / "Budúcnosť sú Levinky" — section 4
 * Header + user-driven horizontal scroll slider (no autoscroll).
 * Scroll-snap so slides snap to position when user releases.
 * ========================================================= */
.future {
	position: relative;
	padding: 150px 0;
	background: var(--wp--preset--color--surface);
	overflow: hidden;
}

/* Decorative star — top-left of section, partially clipped by overflow */
.future__star {
	position: absolute;
	top: 0;
	left: 0;
	width: 383px;
	height: auto;
	transform: translate(-30%, -10%);
	pointer-events: none;
	z-index: 1;
}

.future__inner {
	position: relative;
	z-index: 2;
	max-width: 1840px;
	margin: 0 auto;
	padding: 0 var(--wp--preset--spacing--40);
}

.future__header {
	display: flex;
	justify-content: space-between;
	align-items: flex-start; /* per #7 of latest batch */
	gap: var(--wp--preset--spacing--60);
	max-width: 966px;
	margin: 0 auto 100px;
}

.future__title {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(32px, calc(0.962vw + 24.62px), 40px);
	line-height: 1.1;
	color: #494A39;
	margin: 0;
	font-weight: 400;
	max-width: 252px;
}

.future__title span {
	display: block;
}

.future__description {
	font-family: var(--wp--preset--font-family--display);
	font-size: 0.9375rem;
	line-height: 1.6;
	color: rgba(0, 0, 0, 0.50);
	margin: 0;
	max-width: 452px;
}

/* User-driven horizontal scroller with scroll-snap + drag support (via JS).
 * Trackpad swipe + touch swipe work natively; drag and wheel handled by JS.
 * Custom cursor: the white-on-transparent SVG circle-with-arrows. Hotspot
 * at 26,10 (center of the 52x21 cursor) so the cursor centers on click. */
.future__slider {
	position: relative;
	z-index: 2;
	overflow-x: auto;
	overflow-y: hidden;
	/* `proximity` instead of `mandatory` so a drag is never yanked back to
	 * the nearest slide mid-flight. Plus touch-action: pan-x so browsers
	 * don't fight the horizontal scroll with vertical-pan heuristics. */
	scroll-snap-type: x proximity;
	touch-action: pan-x;
	scrollbar-width: none; /* hide scrollbar (Firefox) */
	cursor: url('assets/images/slider-cursor.svg') 26 10, grab;
}

.future__slider:active {
	cursor: url('assets/images/slider-cursor.svg') 26 10, grabbing;
}

.future__slider::-webkit-scrollbar {
	display: none; /* hide scrollbar (Chrome/Safari) */
}

/* Track left-padding mirrors the SECTION TITLE's left edge exactly. The title
 * is inside `.future__inner` (max-width: 1840, padding: 0 40) inside
 * `.future__header` (max-width: 966, centered within inner). Title left = X
 * where X = inner_left_margin + inner_padding + header_offset.
 *
 *   inner_left_margin = max(0, (100vw - 1840) / 2)
 *   inner_padding     = --wp--preset--spacing--40 (40px)
 *   header_offset     = max(0, (min(100vw, 1840) - 80 - 966) / 2)
 *
 * Sum these for padding-left. Right padding stays at the section's standard
 * inset so slides can peek past the right edge. */
.future__track {
	display: flex;
	gap: var(--wp--preset--spacing--40);
	padding-left: calc(
		max(0px, (100vw - 1840px) / 2)
		+ var(--wp--preset--spacing--40)
		+ max(0px, (min(100vw, 1840px) - 80px - 966px) / 2)
	);
	padding-right: var(--wp--preset--spacing--40);
}

/* Slide dimensions: ~50% viewport so one full slide + peek of next is visible.
 * Min 315px (mobile readability), max 1240px (design cap). */
.future__slide {
	flex: 0 0 clamp(315px, 50vw, 1240px);
	min-width: 0; /* prevent flex-item min-content blow-up from intrinsic img width */
	scroll-snap-align: start;
}

.future__slide-image {
	width: 100%;
	height: clamp(383px, 28vw, 600px);
	border-radius: 8px;
	overflow: hidden;
}

.future__slide-image img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Nested slider inside each outer slide — its own horizontal scroller.
 * container-type: inline-size lets nested-image use cqi units so each image
 * is exactly 100% of the nested width regardless of intrinsic <img> size. */
.future__nested {
	position: relative;
	width: 100%;
	height: clamp(383px, 28vw, 600px);
	border-radius: 8px;
	overflow-x: auto;
	overflow-y: hidden;
	scroll-snap-type: x proximity;
	touch-action: pan-x;
	scrollbar-width: none;
	cursor: url('assets/images/slider-cursor.svg') 26 10, grab;
	container-type: inline-size;
}

.future__nested:active {
	cursor: url('assets/images/slider-cursor.svg') 26 10, grabbing;
}

.future__nested::-webkit-scrollbar {
	display: none;
}

.future__nested-track {
	display: flex;
	height: 100%;
}

.future__nested-image {
	flex: 0 0 100cqi; /* 100% of .future__nested inline size — definite, ignores intrinsic img width */
	min-width: 0;
	height: 100%;
	object-fit: cover;
	scroll-snap-align: start;
	-webkit-user-drag: none;
	user-select: none;
}

/* Navigation indicator bars — overlaid at the bottom of each nested slider.
 * Click jumps to the corresponding image; active bar highlighted. */
.future__nested-nav {
	position: absolute;
	bottom: 30px;
	left: 50%;
	transform: translateX(-50%);
	display: flex;
	gap: 10px;
	z-index: 3;
	pointer-events: auto;
}

.future__nested-nav-item {
	width: 40px;
	height: 2px;
	padding: 8px 0; /* hit area larger than visible bar */
	background: transparent;
	border: 0;
	cursor: pointer;
	position: relative;
}

.future__nested-nav-item::before {
	content: "";
	position: absolute;
	top: 50%;
	left: 0;
	right: 0;
	height: 2px;
	background: rgba(255, 255, 255, 0.4);
	transform: translateY(-50%);
	transition: background-color 0.2s ease;
}

.future__nested-nav-item:hover::before,
.future__nested-nav-item.is-active::before {
	background: var(--wp--preset--color--surface);
}

.future__slide-title {
	font-family: var(--wp--preset--font-family--display);
	font-size: 1.25rem;
	line-height: 1.3;
	color: #000000;
	margin: 16px 0 0;
	font-weight: 400;
}

@media (max-width: 900px) {
	.future {
		padding: 75px 0;
	}

	.future__star {
		width: 200px;
		transform: translate(-40%, -10%);
	}

	/* Mobile: drop the inner's 40px L/R padding (the .future section already
	 * supplies 30px L/R via the mobile padding ladder — double-padding made
	 * the header inset too far). */
	.future__inner {
		padding-left: 0;
		padding-right: 0;
	}

	.future__header {
		flex-direction: column;
		gap: 20px;
		margin-bottom: 35px;
	}

	.future__title {
		font-size: 2rem;
	}

	.future__slide {
		flex: 0 0 85vw;
	}

	.future__track {
		gap: var(--wp--preset--spacing--16);
		/* Mobile: track left-padding 0 — .future already supplies 30px L/R
		 * via the mobile padding ladder, which places the slider edge AT
		 * the title's left edge. Adding more would push the first slide in. */
		padding-left: 0;
		padding-right: 0;
	}

	.future__slide-image {
		height: 50vw;
	}

	.future__slide-title {
		margin-top: 16px;
		font-size: 1rem;
	}
}

/* =========================================================
 * Locality / "Nová štvrť v Leviciach" — section 5
 * Heading + full-width 3D isometric map (with pins baked into the PNG)
 * + gradient fade at the bottom to blend into the next section.
 * ========================================================= */
.locality {
	padding: 150px 0 0;
	background: linear-gradient(180deg, #F5F5F5 0%, #F5F5F5 35.08%, #FFF 77.63%);
}

/* Same header-band pattern as .benefits__header / .future__header:
 * narrow 966px max-width centered, title left + description right.
 * Outer .locality has no inner-wide wrapper — the title band sits
 * directly inside .locality, then .locality__map below extends full-bleed. */
.locality__inner {
	max-width: 966px;
	margin: 0 auto;
	padding: 0 var(--wp--preset--spacing--40) 80px;
	display: flex;
	justify-content: space-between;
	align-items: flex-start;
	gap: var(--wp--preset--spacing--60);
}

.locality__title {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(32px, calc(0.962vw + 24.62px), 40px);
	line-height: 1.1;
	color: #000000;
	margin: 0;
	font-weight: 400;
	max-width: 252px;
}

.locality__title span {
	display: block;
}

.locality__description {
	font-family: var(--wp--preset--font-family--display);
	font-size: 0.9375rem;
	line-height: 1.6;
	color: rgba(0, 0, 0, 0.50);
	margin: 0;
	max-width: 452px;
}

.locality__map {
	position: relative;
	width: 100%;
	overflow: hidden;
}

/* CTA below the map: brown pill button centered. */
.locality__cta-wrap {
	display: flex;
	justify-content: center;
	padding: 40px var(--wp--preset--spacing--40) 80px;
}

/* min-width keeps the map drawing big enough to remain legible on narrow
 * viewports — left side of the image stays visible while overflow on the
 * right is clipped by .locality__map { overflow: hidden }. */
.locality__map-base {
	display: block;
	min-width: 1095px;
	width: 100%;
	height: auto;
}

.locality__gradient {
	position: absolute;
	bottom: 0;
	left: 0;
	right: 0;
	height: 240px;
	background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 0%, var(--wp--preset--color--surface) 100%);
	pointer-events: none;
}

@media (max-width: 900px) {
	.locality {
		padding-top: 75px;
	}

	/* Match other section headers: column stack, title above description. */
	.locality__inner {
		flex-direction: column;
		align-items: flex-start;
		gap: 20px;
		padding-bottom: 40px;
	}

	.locality__title {
		font-size: 2rem;
	}

	.locality__gradient {
		height: 120px;
	}

	.locality__cta-wrap {
		padding: 30px var(--wp--preset--spacing--40) 50px;
	}
}

/* =========================================================
 * CTA banner / "Zvažujete nové bývanie v Leviciach?" — section 6
 * Light tan banner with heading + lead + dark olive CTA on right,
 * decorated with a diagonal small-stars pattern and a partially
 * clipped big brown star in the corner.
 * ========================================================= */
.cta-banner {
	padding: 80px var(--wp--preset--spacing--40);
	background: var(--wp--preset--color--surface);
}

.cta-banner__inner {
	position: relative;
	max-width: 1240px;
	max-height: 350px;
	margin: 0 auto;
	background: #DBCCC3;
	border-radius: 8px;
	overflow: hidden;
	padding: 100px 160px 100px 100px; /* right padding 160 per spec */
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--40);
}

/* Diagonal small-stars pattern on the top-left of the banner */
.cta-banner__small-stars {
	position: absolute;
	top: 0;
	left: 100px;
	width: 447px;
	height: 350px;
	pointer-events: none;
	z-index: 1;
}

/* Big brown star — dominant decorative shape, partially clipped on the right.
 * Per latest Figma: width 1145, top -300 (star sits above the banner with
 * just the bottom curve visible), right -551 (extends past right edge).
 * Mobile scales all three properties via the discrete-breakpoint @media
 * blocks below.
 *
 * Scroll behavior: `rotate: var(--cta-rotate, 0deg)` is driven by JS as
 * the user scrolls THROUGH the .cta-banner section (0deg when section
 * enters viewport, 360deg when it leaves). Uses the individual `rotate`
 * property so reveal-fade animations using `transform` compose cleanly. */
.cta-banner__big-star {
	position: absolute;
	right: -551px;
	top: -300px;
	width: 1145px;
	height: auto;
	pointer-events: none;
	z-index: 1;
	rotate: var(--cta-rotate, 0deg);
	transform-origin: center center;
}

.cta-banner__content {
	position: relative;
	z-index: 2;
	max-width: 690px;
}

.cta-banner__title {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(32px, calc(0.962vw + 24.62px), 40px);
	line-height: 1.1;
	color: #494A39; /* dark olive on light tan */
	margin: 0 0 32px;
	font-weight: 400;
}

.cta-banner__title span {
	display: block;
}

.cta-banner__lead {
	font-family: var(--wp--preset--font-family--display);
	font-size: 0.9375rem;
	line-height: 1.6;
	color: #494A39;
	margin: 0;
	max-width: 320px;
}

.cta-banner__cta {
	position: relative;
	z-index: 2;
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: 32px 48px;
	background: #494A39; /* dark olive on light tan banner */
	color: var(--wp--preset--color--surface);
	font-family: var(--wp--preset--font-family--display);
	font-size: 1.5rem;
	line-height: 1;
	text-transform: uppercase;
	text-decoration: none;
	border-radius: 10px;
	transition: background-color 0.2s ease;
}

.cta-banner__cta:hover,
.cta-banner__cta:focus-visible {
	background: var(--wp--preset--color--ink);
}

@media (max-width: 900px) {
	.cta-banner {
		padding: 40px var(--wp--preset--spacing--40);
	}

	/* Inner: padding 60 30 44 30 + row-gap 32 + stack column. */
	.cta-banner__inner {
		flex-direction: column;
		align-items: flex-start;
		padding: 60px 30px 44px 30px;
		row-gap: 32px;
		max-height: none; /* allow column layout to grow */
		min-height: 0;
	}

	/* Big star mobile rules now use the discrete-breakpoint approach
	 * below (this @media 900 block no longer touches the star). */

	.cta-banner__title {
		font-size: 1.75rem;
		margin-bottom: 22px; /* title-to-desc gap 22 per spec */
	}

	/* Mobile CTA button: smaller pill, Capriola 12px uppercase. */
	.cta-banner__cta {
		display: inline-flex;
		justify-content: center;
		align-items: center;
		gap: 10px;
		padding: 16px 32px;
		border-radius: 8px;
		background: #494A39;
		color: #FFF;
		font-family: var(--wp--preset--font-family--sans); /* Capriola */
		font-size: 0.75rem; /* 12px */
		font-style: normal;
		font-weight: 400;
		line-height: normal;
		text-transform: uppercase;
		align-self: flex-start;
	}
}

/* =========================================================
 * CTA banner big-star DISCRETE breakpoints (overrides the desktop
 * defaults — width 1145, right -551, top -300 — at each step).
 * Cascade: ≥1001 desktop / ≤1000 step1 / ≤780 step2 / ≤680 step3.
 * ≤450 also constrains content max-width to 270px.
 * ========================================================= */
@media (max-width: 1000px) {
	.cta-banner__big-star {
		width: 800px;
		right: -350px;
		top: -150px;
	}
}

@media (max-width: 780px) {
	.cta-banner__big-star {
		width: 640px;
		/* right + top inherited from the ≤1000px block */
	}
}

@media (max-width: 680px) {
	.cta-banner__big-star {
		width: 145px;
		right: -72.5px;
		top: 24px;
	}
}

@media (max-width: 450px) {
	.cta-banner__content {
		max-width: 270px;
	}
}

/* =========================================================
 * Generic button utility (.btn) — used inside the menu overlay
 * ========================================================= */
.btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: var(--wp--preset--spacing--16) var(--wp--preset--spacing--32);
	border-radius: var(--wp--custom--radius--button);
	font-family: var(--wp--preset--font-family--sans);
	font-size: var(--wp--preset--font-size--xs);
	text-transform: uppercase;
	letter-spacing: 0.04em;
	line-height: 1;
	text-decoration: none;
	border: 1px solid transparent;
	cursor: pointer;
	transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.btn--primary {
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--surface);
}

.btn--primary:hover,
.btn--primary:focus-visible {
	background: var(--wp--preset--color--ink);
}

/* Surface — white pill, same look as the header CTA. Used on dark
 * backgrounds (hero photo) where a brown pill would be lower contrast. */
.btn--surface {
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--ink);
}

.btn--surface:hover,
.btn--surface:focus-visible {
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--surface);
}

/* Outline button — layered gradient bg, brown text. Used in the menu overlay
 * (on white bg) so hover must NOT become white-on-white. */
.btn--outline {
	border-radius: 8px;
	border: 1px solid #F0E5DE;
	background:
		linear-gradient(0deg, rgba(255, 255, 255, 0.10) 0%, rgba(255, 255, 255, 0.10) 100%),
		linear-gradient(264deg, rgba(233, 210, 201, 0.20) -119.83%, rgba(149, 111, 96, 0.20) 116.8%);
	color: #956F60;
}

.btn--outline:hover,
.btn--outline:focus-visible {
	background: #956F60;
	color: var(--wp--preset--color--surface);
	border-color: #956F60;
}

/* Ghost button — for use on dark/photo backgrounds (hero).
 * Layered gradients per design spec — used on "Mám záujem o bývanie". */
.btn--ghost {
	border-radius: 8px;
	border: 1px solid #F0E5DE;
	background:
		linear-gradient(0deg, rgba(255, 255, 255, 0.10) 0%, rgba(255, 255, 255, 0.10) 100%),
		linear-gradient(264deg, rgba(233, 210, 201, 0.20) -119.83%, rgba(149, 111, 96, 0.20) 116.8%);
	color: var(--wp--preset--color--surface);
}

.btn--ghost:hover,
.btn--ghost:focus-visible {
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--ink);
	border-color: var(--wp--preset--color--surface);
}

/* Ghost-flat — simpler flat translucent white bg, used on "O projekte" second ghost. */
.btn--ghost-flat {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	padding: var(--wp--preset--spacing--16) var(--wp--preset--spacing--32);
	border-radius: 8px;
	border: 1px solid #F0E5DE;
	background: rgba(255, 255, 255, 0.10);
	color: var(--wp--preset--color--surface);
	font-family: var(--wp--preset--font-family--sans);
	font-size: var(--wp--preset--font-size--xs);
	text-transform: uppercase;
	letter-spacing: 0.04em;
	line-height: 1;
	text-decoration: none;
	cursor: pointer;
	transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.btn--ghost-flat:hover,
.btn--ghost-flat:focus-visible {
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--ink);
	border-color: var(--wp--preset--color--surface);
}

/* =========================================================
 * Homepage hero (transparent header overlay over photo)
 * ========================================================= */

/* Homepage: header sits ON the hero photo, transparent bg, white content */
body.home .site-header,
body.home .site-header.has-background-background-color,
body.home div.site-header.has-background {
	background-color: transparent !important;
}

body.home .site-header__nav-link a,
body.home .site-header__logo,
body.home .site-header__menu-toggle {
	color: var(--wp--preset--color--surface);
}

/* Blog archive + single post: header sits OVER the light page-top gradient,
 * so default state is transparent with dark content; the .is-scrolled rules
 * below take over once user scrolls past the gradient banner. */
body.blog:not(.is-scrolled) .site-header,
body.blog:not(.is-scrolled) .site-header.has-background-background-color,
body.blog:not(.is-scrolled) div.site-header.has-background,
body.single:not(.is-scrolled) .site-header,
body.single:not(.is-scrolled) .site-header.has-background-background-color,
body.single:not(.is-scrolled) div.site-header.has-background {
	background-color: transparent !important;
}

/* Nav + menu-toggle = ink. Logo = primary brown (matches the page-top accent
 * + the brown CTA on these pages — the design has the wordmark in brown
 * sitting over the light gradient, not black). */
body.blog:not(.is-scrolled) .site-header__nav-link a,
body.blog:not(.is-scrolled) .site-header__menu-toggle,
body.single:not(.is-scrolled) .site-header__nav-link a,
body.single:not(.is-scrolled) .site-header__menu-toggle {
	color: var(--wp--preset--color--ink);
}

body.blog:not(.is-scrolled) .site-header__logo,
body.single:not(.is-scrolled) .site-header__logo {
	color: var(--wp--preset--color--primary);
}

/* CTA — brown pill, matches the same .btn--primary used for the archive
 * "Načítať ďalšie články" / "Zobraziť všetky blogy" buttons. */
body.blog:not(.is-scrolled) .site-header__cta .wp-block-button__link,
body.single:not(.is-scrolled) .site-header__cta .wp-block-button__link {
	background-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--surface);
}

body.blog:not(.is-scrolled) .site-header__cta .wp-block-button__link:hover,
body.blog:not(.is-scrolled) .site-header__cta .wp-block-button__link:focus-visible,
body.single:not(.is-scrolled) .site-header__cta .wp-block-button__link:hover,
body.single:not(.is-scrolled) .site-header__cta .wp-block-button__link:focus-visible {
	background-color: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--surface);
}

/* When user scrolls past the hero, the header switches to a solid brown
 * background (matches the "O developerovi" type pages style).
 * body.is-scrolled is toggled by scroll-reveal.js.
 * Specificity matches body.home rules (which include `div.site-header.has-background`). */
body.is-scrolled .site-header,
body.is-scrolled .site-header.has-background-background-color,
body.is-scrolled div.site-header.has-background {
	background-color: var(--wp--preset--color--primary) !important;
}

body.is-scrolled .site-header__nav-link a,
body.is-scrolled .site-header__logo,
body.is-scrolled .site-header__menu-toggle {
	color: var(--wp--preset--color--surface);
}

body.is-scrolled .site-header__cta .wp-block-button__link {
	background-color: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--ink);
}

body.is-scrolled .site-header__cta .wp-block-button__link:hover,
body.is-scrolled .site-header__cta .wp-block-button__link:focus-visible {
	background-color: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--surface);
}

/* Menu-open ALWAYS wins over is-scrolled, regardless of which page or
 * scroll position. Source order matters here because both selectors carry
 * !important and the same specificity — this block sits after is-scrolled
 * so it wins by being later in the cascade. Same for content colors and
 * the CTA button — when the menu opens, the header reverts to its "menu
 * overlay" look (dark text/logo on white menu bg) regardless of scroll state. */
body.is-menu-open .site-header,
body.is-menu-open .site-header.has-background-background-color,
body.is-menu-open div.site-header.has-background,
body.is-menu-open.is-scrolled .site-header,
body.is-menu-open.is-scrolled .site-header.has-background-background-color,
body.is-menu-open.is-scrolled div.site-header.has-background {
	background-color: transparent !important;
}

body.is-menu-open .site-header__nav-link a,
body.is-menu-open .site-header__logo,
body.is-menu-open .site-header__menu-toggle,
body.is-menu-open.is-scrolled .site-header__nav-link a,
body.is-menu-open.is-scrolled .site-header__logo,
body.is-menu-open.is-scrolled .site-header__menu-toggle {
	color: var(--wp--preset--color--ink) !important;
}

/* Menu-open CTA button: solid black initially. On hover deepens to brown.
 * Wins over .is-scrolled (white pill) via source order + !important. */
body.is-menu-open .site-header__cta .wp-block-button__link,
body.is-menu-open.is-scrolled .site-header__cta .wp-block-button__link {
	background-color: var(--wp--preset--color--ink) !important;
	color: var(--wp--preset--color--surface) !important;
}

body.is-menu-open .site-header__cta .wp-block-button__link:hover,
body.is-menu-open .site-header__cta .wp-block-button__link:focus-visible,
body.is-menu-open.is-scrolled .site-header__cta .wp-block-button__link:hover,
body.is-menu-open.is-scrolled .site-header__cta .wp-block-button__link:focus-visible {
	background-color: var(--wp--preset--color--primary) !important;
	color: var(--wp--preset--color--surface) !important;
}

/* Hero section — taller fluid clamp (748px → 1290px) per previous working values.
 * Forced full viewport width so photo bg spans edge-to-edge. */
.hero {
	position: sticky;
	top: 0;
	margin: 0 !important;
	width: 100vw !important;
	max-width: none !important;
	margin-left: calc(50% - 50vw) !important;
	/* Hero height: 748px at ~400vw, scales linearly to 1290px at ~1920vw.
	 * Slope 0.357 (= 542 / 1520) so the full range is covered across all
	 * viewports — small phones get 748, ultrawide desktops get 1290. */
	height: clamp(748px, calc(35.7vw + 605.2px), 1290px);
	overflow: hidden;
	z-index: 1;
	color: var(--wp--preset--color--surface);
	background: url('assets/images/hero-bg.jpg') center/cover no-repeat;
}

/* Entry: hero photo fades in from solid black on page load. We use a
 * pseudo so the underlying background-image stays unmodified. The animation
 * goes from opacity 1 (black covers photo) to 0 (photo fully visible). */
.hero::before {
	content: '';
	position: absolute;
	inset: 0;
	background: var(--wp--preset--color--ink);
	pointer-events: none;
	z-index: 1;
	opacity: 0;
	animation: hero-bg-reveal 1.2s cubic-bezier(0.22, 1, 0.36, 1) 100ms backwards;
}

@keyframes hero-bg-reveal {
	from { opacity: 1; }
	to   { opacity: 0; }
}

/* Dark overlay — gradient (transparent top → 50% black bottom), opacity
 * scroll-driven via --hero-darken (set by scroll-reveal.js from 0 at top
 * of page to 1 once the hero has fully scrolled past). At rest the hero
 * photo is clear; as the user scrolls the gradient fades in and the
 * lower half of the photo darkens — by the time .hero-cover wordmark
 * parallaxes over, it lands on a moody darkened photo. */
.hero::after {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 0.65) 100%);
	pointer-events: none;
	/* z-index 3 so the overlay sits ABOVE .hero__inner (z:2), darkening
	 * the content too as the user scrolls — not just the photo. */
	z-index: 3;
	opacity: var(--hero-darken, 0);
}

/* Same full-bleed treatment for the hero cover. Negative margin-top pulls
 * it up 100px so the wordmark sits at the bottom of the hero photo (per
 * Figma mobile design) instead of below it with a cream-bg gap.
 *
 * !important is required because earlier rule:
 *   .is-layout-flow > *, .wp-site-blocks > * { margin-block-start: 0 !important }
 * (used to kill WP's default block-stack 24px gap) wins over plain margin-top.
 * margin-block-start === margin-top in LTR, so we need !important to overcome
 * the global block-stack reset. */
.hero-cover {
	width: 100vw !important;
	max-width: none !important;
	margin-left: calc(50% - 50vw) !important;
	margin-top: -100px !important;
}

.hero__inner {
	position: relative;
	z-index: 2;
	max-width: 1420px;
	margin: 0 auto;
	height: 100%;
	/* box-sizing: border-box so the inner's height (100%) INCLUDES the
	 * padding instead of stacking on top — without this the padding-top
	 * pushed the inner taller than .hero, exposing the cream/white below
	 * the hero photo (visible as a band under the Levinky wordmark). */
	box-sizing: border-box;
	/* 150px on small viewports → 224px on wide. Linear scale ~7vw+122px sits
	 * inside the clamp band: yields 150px at ~400vw, 224px at ~1456vw. */
	padding: clamp(150px, calc(7vw + 122px), 224px) var(--wp--preset--spacing--40) 0;
	display: flex;
	justify-content: space-between;
	align-items: flex-start;
	column-gap: var(--wp--preset--spacing--60);
}

.hero__left {
	flex: 0 0 auto; /* sized by content */
}

/* Hero content micro-parallax: each layer translates independently as the
 * user scrolls (scroll-reveal.js sets --parallax-y per element). Different
 * coefficients per element create the depth illusion. We use the individual
 * `translate` property so reveal animations using `transform` compose
 * without overwriting this parallax offset. */
.hero__title,
.hero__description,
.hero__actions {
	translate: 0 var(--parallax-y, 0);
	will-change: translate;
}

.hero__title {
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--huge); /* clamp(42px → 96px) from theme.json */
	line-height: 1;
	letter-spacing: normal; /* Figma design context has no global tracking on title */
	color: var(--wp--preset--color--surface);
	margin: 60px 0 0; /* offset title down 60px from inner padding-top */
	font-weight: 400;
	white-space: nowrap; /* prevent wrapping within each line */
}

.hero__title-line {
	display: block;
}

.hero__title-line--indent {
	padding-left: 1.3em;
}

.hero__right {
	flex: 0 0 auto;
	display: flex;
	flex-direction: column;
	align-items: flex-start; /* description + buttons left-aligned in this column */
}

/* Sparkle — only item in __right that's right-aligned. 32px above description, 16px right offset.
 * Spins scroll-scrubbed via --hero-rotate (set by scroll-reveal.js): one full
 * rotation as user scrolls from page-top through the hero height. Mirrors
 * the home-intro star behavior. */
.hero__sparkle {
	align-self: flex-end;
	margin-bottom: 32px;
	margin-right: 16px;
	color: var(--wp--preset--color--primary-light);
	pointer-events: none;
	line-height: 0;
	/* Individual transform properties so the JS-driven scroll rotation,
	 * the CSS-driven entry scale, and the scroll parallax translate
	 * each live in their own property and compose without overwriting.
	 * Modern browsers support rotate/scale/translate as separate properties. */
	rotate: var(--hero-rotate, 0deg);
	translate: 0 var(--parallax-y, 0);
	transform-origin: center center;
	/* Entry: fade in + scale up (small "pop") on page load. Anchored late
	 * in the hero cascade so it lands after the title's first half. */
	opacity: 0;
	scale: 0.6;
	animation: hero-sparkle-entry 1s cubic-bezier(0.22, 1, 0.36, 1) 700ms forwards;
	will-change: rotate, translate, scale, opacity;
	/* Smoothing is now driven entirely by JS lerp (scroll-reveal.js). */
}

@keyframes hero-sparkle-entry {
	from { opacity: 0; scale: 0.6; }
	to   { opacity: 1; scale: 1; }
}

.hero__sparkle svg {
	display: block;
	width: 75px;
	height: 78px;
}

.hero__description {
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--lead); /* clamp(14px → 20px) from theme.json */
	line-height: 1.6;
	color: var(--wp--preset--color--surface);
	margin: 0 0 var(--wp--preset--spacing--50);
	max-width: 496px;
}

.hero__actions {
	display: flex;
	gap: var(--wp--preset--spacing--16);
	flex-wrap: wrap;
}

/* Site-main below hero — white bg. With sticky hero above, site-main scrolls
 * normally and (z-index 2) rises over the hero photo on scroll. */
.site-main {
	position: relative;
	z-index: 2;
	background: var(--wp--preset--color--surface);
}

/* Hero-cover: sits between .hero and .site-main in flow (SIBLING of both,
 * NOT inside site-main — otherwise site-main's white bg would paint behind
 * the wordmark). Transparent bg lets the sticky hero photo show through,
 * so the white wordmark renders on the photo. Same z-index 2 as site-main
 * so it overlays the sticky hero on scroll. As user scrolls, hero-cover
 * rises in flow — wordmark "travels up" WITH it. Site-main follows
 * immediately below so the white bg appears right under the wordmark. */
.hero-cover {
	position: relative;
	z-index: 2;
	overflow: hidden;
}

.hero-cover__wordmark {
	display: block;
	width: 100%;
	height: auto;
}

/* =========================================================
 * Homepage intro section — large statement text with
 * scroll-scrubbed character color reveal.
 * ========================================================= */
.home-intro {
	position: relative;
	padding: 300px var(--wp--preset--spacing--40) 150px;
	background: var(--wp--preset--color--surface);
}

.home-intro__inner {
	position: relative;
	max-width: 966px; /* matches the text max-width so the whole block (text + star) centers as one */
	margin: 0 auto;
}

.home-intro__star {
	position: absolute;
	top: -77px;   /* star is 155 tall — pull it up by half */
	left: -74px;  /* star is 149 wide — pull it left by half so it pokes outside */
	pointer-events: none;
	transform: rotate(var(--reveal-rotate, 0deg));
	/* Smoothing driven by JS lerp (scroll-reveal.js inertia loop). */
}

.home-intro__star svg {
	display: block;
	width: 149px;
	height: 155px;
}

.home-intro__text {
	position: relative;
	font-family: var(--wp--preset--font-family--display);
	font-size: 2rem;
	line-height: 1.6;
	margin: 0;
	max-width: 966px;
}

/* Scroll-reveal text — each CHARACTER lerps from muted to full color
 * via --reveal CSS variable (0 → 1) set by scroll-reveal.js
 * Character-level resolution matches the Figma design where parts of
 * one word can be dark while the rest is still muted. */
.reveal-text {
	color: #494A39; /* Default (no-JS) color — full color so text is readable */
	max-width: 966px;
}

/* Each character lerps from a light gray (#CFCFCB ≈ visible muted) to
 * the full olive (#494A39) via color-mix. Color difference is bigger
 * than alpha-only, so the reveal reads more clearly.
 * Targets .reveal-char (produced by reveal.js's text split) so the
 * scroll-scrubbed color reveal coexists with the slice entry animation. */
.reveal-text .reveal-char {
	color: color-mix(in srgb, #494A39 calc(var(--reveal, 1) * 100%), #CFCFCB);
	transition: color 0.05s linear;
}

/* Reduce motion: chars always shown at full color */
@media (prefers-reduced-motion: reduce) {
	.reveal-text .reveal-char {
		color: #494A39 !important;
		transition: none;
	}
}

@media (max-width: 900px) {
	.home-intro {
		padding: 150px var(--wp--preset--spacing--40) 75px;
	}

	.home-intro__star {
		top: -50px;
		left: -30px;
	}

	.home-intro__star svg {
		width: 80px;
		height: 83px;
	}

	.home-intro__text {
		font-size: 1.438rem;
	}
}

/* =========================================================
 * Benefits section — header (title + description) + 5-card grid
 * with hover-to-expand cards (accordion-style).
 * ========================================================= */
.benefits {
	padding: 150px var(--wp--preset--spacing--40);
	background: var(--wp--preset--color--surface);
}

.benefits__inner {
	max-width: 1242px;
	margin: 0 auto;
}

.benefits__header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	gap: var(--wp--preset--spacing--60);
	max-width: 966px;
	margin: 0 auto 100px; /* center horizontally within section */
}

.benefits__title {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(32px, calc(0.962vw + 24.62px), 40px);
	line-height: 1.1;
	color: #494A39;
	margin: 0;
	font-weight: 400;
	max-width: 252px;
}

.benefits__title span {
	display: block;
}

.benefits__description {
	font-family: var(--wp--preset--font-family--display);
	font-size: 0.9375rem;
	line-height: 1.4;
	color: rgba(0, 0, 0, 0.50);
	margin: 0;
	max-width: 452px;
}

/* Card grid — flex container so cards can expand/contract on hover.
 * Default: each card capped at 154px (compact). On hover, max-width is
 * lifted and the hovered card grows. Group is centered in the section. */
.benefits__grid {
	display: flex;
	justify-content: center;
	gap: 2px;
}

.benefit {
	position: relative;
	flex: 0 1 156px; /* compact default — 156px wide, no growth */
	min-width: 0;
	max-width: 156px;
	height: 800px;
	border-radius: 8px;
	overflow: hidden;
	cursor: pointer;
	transition:
		flex-grow 0.5s cubic-bezier(0.4, 0, 0.2, 1),
		max-width 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Open card state. Three drivers, all gated by `:not(:hover)` on the grid
 * so that any of them YIELDS to a live hover (otherwise two cards would
 * both try to grow and neither would reach full open width):
 *   1. `.is-active` (JS-controlled) — only opens when grid not hovered.
 *      Click handler moves the class. Initial state: 2nd card.
 *   2. `:nth-child(2)` — no-JS fallback (only when `.is-js-controlled`
 *      is NOT set on the grid, also gated by not-hover).
 *   3. `:hover` / `:focus-within` — wins while grid is hovered. Mobile
 *      kills hover/focus expansion via the @media (max-width: 900px)
 *      override below. */
.benefits__grid:not(:hover) .benefit.is-active,
.benefits__grid:not(.is-js-controlled):not(:hover) .benefit:nth-child(2),
.benefit:hover,
.benefit:focus-within {
	flex-grow: 4;
	max-width: 618px;
	border: 0;
}

.benefit--light {
	background: linear-gradient(180deg, #FFFFFF 0%, #FAF6F1 100%);
	border: 1px solid rgba(0, 0, 0, 0.10);
}

.benefit--brown {
	background: linear-gradient(180deg, #E9D2C9 0%, #956F60 100%);
}

/* Star top-center on every card (inactive state) */
.benefit__star {
	position: absolute;
	top: 80px;
	left: 50%;
	transform: translateX(-50%);
	z-index: 3;
	line-height: 0;
	pointer-events: none;
	transition: opacity 0.4s ease;
}

.benefit__star svg {
	display: block;
	width: 27px;
	height: 29px;
}

/* Brown card decoration — Group 4502 SVG anchored bottom-left. opacity 0.05
 * to keep it as a subtle texture rather than a busy cluster. Fades out when
 * the card opens (hover / focus) so the expanded state stays clean — same
 * treatment as .benefit__star. */
.benefit__deco {
	position: absolute;
	bottom: 0;
	left: 0;
	width: 153px;
	height: 522px;
	opacity: 0.05;
	pointer-events: none;
	z-index: 1;
	transition: opacity 0.4s ease;
}

.benefit--brown:hover .benefit__deco,
.benefit--brown:focus-within .benefit__deco {
	opacity: 0;
}

/* Brown card's star is white (overrides the inline SVG fill="#DBCCC3"). */
.benefit--brown .benefit__star svg path {
	fill: var(--wp--preset--color--surface);
}

/* Image inside hover-image cards — hidden by default, reveals on hover */
.benefit__image {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	opacity: 0;
	transition: opacity 0.4s ease;
	z-index: 1;
}

.benefit__overlay {
	position: absolute;
	inset: 0;
	background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 60%, rgba(0, 0, 0, 0.4) 100%);
	pointer-events: none;
	opacity: 0;
	transition: opacity 0.4s ease;
	z-index: 2;
}

/* On hover (or first-card-default): reveal image, hide star, dim overlay shows */
.benefits__grid:not(.is-js-controlled):not(:hover) .benefit--has-image:nth-child(2),
.benefits__grid:not(:hover) .benefit--has-image.is-active .benefit__image,
.benefit--has-image:hover .benefit__image,
.benefit--has-image:focus-within .benefit__image {
	opacity: 1;
}

.benefits__grid:not(.is-js-controlled):not(:hover) .benefit--has-image:nth-child(2),
.benefits__grid:not(:hover) .benefit--has-image.is-active .benefit__overlay,
.benefit--has-image:hover .benefit__overlay,
.benefit--has-image:focus-within .benefit__overlay {
	opacity: 1;
}

.benefits__grid:not(.is-js-controlled):not(:hover) .benefit:nth-child(2) .benefit__star,
.benefits__grid:not(:hover) .benefit.is-active .benefit__star,
.benefit:hover .benefit__star,
.benefit:focus-within .benefit__star {
	opacity: 0;
}

.benefit__title {
	position: absolute;
	bottom: var(--wp--preset--spacing--30);
	left: var(--wp--preset--spacing--24);
	right: var(--wp--preset--spacing--24);
	font-family: var(--wp--preset--font-family--display);
	font-size: 1rem; /* compact size when card is narrow */
	line-height: 1.3;
	font-weight: 400;
	margin: 0;
	z-index: 3;
	text-align: center;
	transition: font-size 0.4s ease, color 0.4s ease;
}

.benefits__grid:not(.is-js-controlled):not(:hover) .benefit:nth-child(2) .benefit__title,
.benefits__grid:not(:hover) .benefit.is-active .benefit__title,
.benefit:hover .benefit__title,
.benefit:focus-within .benefit__title {
	font-size: 1.25rem;
	text-align: left;
}

.benefit__title span {
	display: block;
}

.benefit--light .benefit__title {
	color: #494A39;
}

.benefit--brown .benefit__title {
	color: var(--wp--preset--color--surface); /* white on brown card */
}

/* Cards with image: on hover (or first-card-default), title flips to white (image is dark behind) */
.benefits__grid:not(.is-js-controlled):not(:hover) .benefit--has-image:nth-child(2),
.benefits__grid:not(:hover) .benefit--has-image.is-active .benefit__title,
.benefit--has-image:hover .benefit__title,
.benefit--has-image:focus-within .benefit__title {
	color: var(--wp--preset--color--surface);
}

/* =========================================================
 * Mobile (≤900px) — cards stack vertically with a totally different
 * resting layout: row-oriented pills (94px min-height, star left + title
 * right, 24px padding, light gradient). The open card (default-open
 * nth-child(2)) keeps the desktop "image with title at bottom" layout
 * but shrunk to 401px. No brown variant on mobile — every card uses
 * the same light gradient + dark text.
 * ========================================================= */
@media (max-width: 900px) {
	.benefits {
		padding: 75px var(--wp--preset--spacing--40);
	}

	.benefits__header {
		flex-direction: column;
		align-items: flex-start;
		gap: 20px;
		margin-bottom: 35px;
	}

	.benefits__title {
		font-size: 2rem;
	}

	.benefits__grid {
		flex-direction: column;
		gap: 2px;
	}

	/* CLOSED card: row-reverse pill — TITLE on left, STAR on right per design. */
	.benefit {
		flex: 0 0 auto;
		width: 100%;
		max-width: 100%;
		min-height: 94px;
		height: auto;
		display: flex;
		flex-direction: row-reverse;
		align-items: center;
		justify-content: space-between;
		padding: 24px;
		box-sizing: border-box;
		background: linear-gradient(180deg, #FFF 0%, #FAF6F1 100%);
		border: 1px solid rgba(0, 0, 0, 0.10);
		border-radius: 8px;
		overflow: hidden;
		transition: min-height 0.4s cubic-bezier(0.4, 0, 0.2, 1);
	}

	/* Hover/focus must NOT expand on mobile — :hover on touch is buggy.
	 * Only `.is-active` (JS-controlled) and the no-JS nth-child(2) fallback
	 * trigger the expanded state. */
	.benefit:hover,
	.benefit:focus-within {
		flex-grow: 0;
		max-width: 100%;
		border: 1px solid rgba(0, 0, 0, 0.10);
	}

	/* Star + title revert to flow (no absolute positioning on mobile). */
	.benefit__star {
		position: static;
		top: auto;
		left: auto;
		transform: none;
	}

	.benefit__title {
		position: static;
		bottom: auto;
		left: auto;
		right: auto;
		margin: 0;
		font-size: 1rem;
		line-height: 1.3;
		text-align: left;
	}

	.benefit__title span {
		display: block;
	}

	/* Mobile: every card uses the same light look — no brown variant.
	 * Star color reverts to standard tan, deco hidden entirely. */
	.benefit--brown {
		background: linear-gradient(180deg, #FFF 0%, #FAF6F1 100%);
		border: 1px solid rgba(0, 0, 0, 0.10);
	}

	.benefit--brown .benefit__title {
		color: #494A39;
	}

	.benefit--brown .benefit__star svg path {
		fill: #DBCCC3;
	}

	.benefit__deco {
		display: none;
	}

	/* OPEN card on mobile: taller (401px), image visible, title at bottom-left.
	 * Matches the structure of the desktop open card, just compact. Mobile
	 * has no live hover, so `:not(:hover)` doesn't restrict here — but we
	 * keep the same selector shape as desktop for consistency. */
	.benefits__grid:not(.is-js-controlled):not(:hover) .benefit:nth-child(2),
	.benefits__grid:not(:hover) .benefit.is-active {
		min-height: 401px;
		height: 401px;
		flex-direction: column;
		align-items: stretch;
		justify-content: flex-end;
		border: 0;
	}

	.benefits__grid:not(.is-js-controlled):not(:hover) .benefit:nth-child(2) .benefit__title,
.benefits__grid:not(:hover) .benefit.is-active .benefit__title {
		text-align: left;
		font-size: 1.25rem;
		position: relative;
		z-index: 3;
	}
}

/* =========================================================
 * Site menu responsive ladder
 *   ≤1200px  reduce nav-side padding from 80px → 20px (room for menu)
 *   ≤1050px  collapse to single column: hide hero half, align menu items
 *            with the closed-state logo's screen edge (40px), hide marker
 *            column, move footer divider above the contact block, center
 *            legal links.
 *   ≤900px   typography size tweaks (smaller nav text)
 * ========================================================= */
@media (max-width: 1200px) {
	.site-menu__nav {
		padding-left: 20px;
	}
}

@media (max-width: 1050px) {
	/* Hide the hero half — menu becomes single-column */
	.site-menu__hero {
		display: none;
	}

	.site-menu__inner {
		grid-template-columns: 1fr;
		grid-template-areas:
			"nav"
			"footer";
		gap: var(--wp--preset--spacing--50);
	}

	.site-menu__divider--vertical {
		display: none;
	}

	/* Align menu items with the closed-pill logo position:
	 * pill left:16 + pill padding-left:24 = 40px from screen. The
	 * .site-menu__scroll already supplies 40px padding-left, so we just
	 * need to flatten the nav's marker grid so text starts at the
	 * scroll-content edge instead of being offset by the marker column. */
	.site-menu__nav {
		padding-left: 0;
		padding-bottom: var(--wp--preset--spacing--24); /* breathing room before the divider */
	}

	.site-menu__nav-label {
		padding-left: 0;
	}

	.site-menu__nav li {
		grid-template-columns: auto;
		column-gap: 0;
	}

	/* Hide the asterisk marker on mobile — active state still indicated by
	 * the link's color/translate. Keeps text at the 40px screen-edge target. */
	.site-menu__nav-marker {
		display: none;
	}

	/* FOOTER — single column. Divider above the contact block (between nav
	 * items and footer). Legal links centered. */
	.site-menu__footer {
		grid-template-columns: 1fr;
	}

	/* Full-bleed divider: 100vw, anchored to the viewport center so it spans
	 * edge-to-edge regardless of the scroll padding on the parent. */
	.site-menu__footer::before {
		top: -20px;
		left: 50%;
		transform: translateX(-50%);
		width: 100vw;
	}

	.site-menu__footer-left {
		grid-template-columns: 1fr;
		gap: var(--wp--preset--spacing--24);
	}

	.site-menu__footer-right {
		padding-left: 0;
		justify-content: center;
	}

	.site-menu__legal {
		justify-content: center;
		margin-left: 24px; /* visual nudge right per design */
	}
}

@media (max-width: 900px) {
	.site-menu__nav a {
		font-size: var(--wp--preset--font-size--large);
	}
}

/* ----- MOBILE HEADER PILL: activates at ≤1050px (earlier than other mobile rules) ----- */
@media (max-width: 1050px) {
	/* Override fixed positioning to make it a floating pill */
	.site-header {
		top: 16px !important;
		left: 16px !important;
		right: 16px !important;
		background: var(--wp--preset--color--surface) !important;
		border-radius: 8px !important;
		padding: 12px 24px !important;
	}

	/* Override homepage transparent + is-scrolled brown */
	body.home .site-header,
	body.home .site-header.has-background-background-color,
	body.home div.site-header.has-background,
	body.is-scrolled .site-header,
	body.is-scrolled .site-header.has-background-background-color,
	body.is-scrolled div.site-header.has-background {
		background: var(--wp--preset--color--surface) !important;
	}

	/* Admin bar offset: shift pill below admin bar */
	.admin-bar .site-header {
		top: calc(46px + 16px) !important;
	}

	/* Hide 3 inline nav links + CTA — only logo + hamburger on mobile */
	.site-header__left,
	.site-header__cta,
	.site-header__right .wp-block-buttons,
	.site-header__right .wp-block-button {
		display: none !important;
	}

	/* Logo: static, on the left (NOT absolute-centered) */
	.site-header__logo,
	body.home .site-header__logo {
		position: static !important;
		transform: none !important;
	}

	.site-header__logo svg {
		width: 80px;
		height: auto;
	}

	/* Always dark on the white pill (override homepage white-on-photo rules) */
	body .site-header__logo,
	body .site-header__menu-toggle,
	body.home .site-header__logo,
	body.home .site-header__menu-toggle,
	body.is-scrolled .site-header__logo,
	body.is-scrolled .site-header__menu-toggle {
		color: var(--wp--preset--color--ink);
	}
}

/* On mobile phones (≤640px), tighten the pill padding to 16px */
@media (max-width: 640px) {
	.site-header {
		padding: 12px 16px !important;
	}
}

/* ----- Hero column-stack: row layout breaks at ≤1100px (title left +
 *       content right gets too tight with the wide title). At this width
 *       we stack vertically (title above, content below), centered. ----- */
@media (max-width: 1100px) {
	.hero__inner {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: flex-start;
		text-align: center;
		gap: var(--wp--preset--spacing--30);
	}

	.hero__left,
	.hero__right {
		max-width: 100%;
		align-items: center;
	}

	.hero__title {
		text-align: center;
		white-space: normal; /* allow wrapping when stacked */
		margin: 0;
	}

	.hero__title-line--indent {
		padding-left: 0; /* drop the desktop second-line indent */
	}

	.hero__right {
		align-items: center;
	}

	.hero__description {
		text-align: center;
		max-width: 100%;
	}

	.hero__actions {
		justify-content: center;
		flex-wrap: wrap;
	}
}

/* ----- True mobile (≤900px): tighten things further + hide sparkle ----- */
@media (max-width: 900px) {
	.hero__sparkle {
		display: none; /* sparkle hidden on mobile per design */
	}

	/* Mobile shows only the primary "Výber bývania" CTA — hide the two ghost ones.
	 * Note: in the template the primary uses .btn--primary "O projekte" text.
	 * If you want a different label on mobile, send me the target text. */
	.hero__actions .btn--ghost,
	.hero__actions .btn--ghost-flat {
		display: none;
	}
}

/* =========================================================
 * Site footer — dark olive bg, logo + nav + contact on left,
 * form on right, vertical divider between. Bottom row with legal links.
 * ========================================================= */
/* Site-footer: dark olive container with the white "Levinky" wordmark
 * positioned absolutely INSIDE — top-clipped by overflow:hidden creating
 * a knockout effect (only bottom half of wordmark visible as white-on-olive).
 * Star pattern at top-left for additional decoration (5% opacity).
 * The wordmark translates Y based on scroll position (parallax) — handled
 * by scroll-reveal.js so it "rises" from below into final position as the
 * user approaches the bottom of the page. */
.site-footer {
	position: relative;
	z-index: 2; /* above sticky hero (z-index: 1) so footer covers the photo */
	background: #494A39;
	color: var(--wp--preset--color--surface);
	/* Padding-top scales 230px (mobile ~400vw) → 435px (desktop ~1440vw).
	 * Slope 19.7vw + 151.2px sits between, clamped at the endpoints. */
	padding: clamp(230px, calc(19.7vw + 151.2px), 435px) var(--wp--preset--spacing--40) 30px;
	overflow: hidden;
}

/* Star pattern — fixed dimensions across all viewports per spec. */
.site-footer__stars {
	position: absolute;
	left: -532px;
	top: -219px;
	width: 1034px;
	height: 1332px;
	pointer-events: none;
	user-select: none;
	z-index: 0;
}

/* Big white wordmark — anchored above the footer's top edge so most of it
 * clips against `overflow:hidden` (knockout effect — only bottom curves
 * visible inside the olive footer at the final position). JS translates
 * it DOWNWARD via --footer-wordmark-y as the user scrolls toward the
 * footer; at the bottom of the page it reaches its Figma resting position. */
.site-footer__wordmark {
	position: absolute;
	top: -200px; /* base position — mostly above footer's top edge */
	left: 50%;
	transform: translateX(-50%) translateY(var(--footer-wordmark-y, 0px));
	width: clamp(800px, 110vw, 1840px);
	height: auto;
	color: var(--wp--preset--color--surface);
	pointer-events: none;
	user-select: none;
	z-index: 0;
	/* footer-levinky.svg has fill="white" already so it renders white on olive. */
}

.site-footer__inner {
	position: relative;
	z-index: 1; /* above the wordmark/stars background */
	max-width: 1840px;
	margin: 0 auto;
	display: grid;
	grid-template-columns: 1fr 1px 1.4fr;
	gap: var(--wp--preset--spacing--80);
}

.site-footer__divider {
	width: 1px;
	background: rgba(255, 255, 255, 0.15);
}

/* LEFT column: logo + nav + contact */
.site-footer__logo {
	display: inline-flex;
	color: var(--wp--preset--color--surface);
	margin-bottom: 55px; /* per spec — both desktop and mobile */
}

.site-footer__logo svg {
	display: block;
	width: 134px;
	height: 44px;
}

.site-footer__nav {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--wp--preset--spacing--24);
}

/* Nav links: F0E5DE / Anxler / 12px / uppercase / underline-wipe on hover
 * (same animation as the top-bar nav: grows L→R on enter, exits L→R on leave). */
.site-footer__nav a {
	position: relative;
	display: inline-block;
	color: #F0E5DE;
	font-family: var(--wp--preset--font-family--display);
	font-size: 12px;
	font-style: normal;
	font-weight: 400;
	line-height: normal;
	text-transform: uppercase;
	text-decoration: none;
	transition: color 0.2s ease;
}

.site-footer__nav a::after {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	bottom: -4px;
	height: 1px;
	background: currentColor;
	transform: scaleX(0);
	transform-origin: right center;
	transition: transform 0.35s cubic-bezier(0.22, 1, 0.36, 1);
}

.site-footer__nav a:hover,
.site-footer__nav a:focus-visible {
	color: var(--wp--preset--color--surface);
}

.site-footer__nav a:hover::after,
.site-footer__nav a:focus-visible::after {
	transform: scaleX(1);
	transform-origin: left center;
}

.site-footer__contact {
	margin-top: 75px;
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--16);
	font-family: var(--wp--preset--font-family--display);
}

.site-footer__contact p {
	display: flex;
	align-items: center;
	column-gap: 16px;
	margin: 0;
	color: var(--wp--preset--color--surface);
}

.site-footer__contact a {
	color: #F0E5DE;
	font-family: var(--wp--preset--font-family--display);
	font-size: 12px;
	font-style: normal;
	font-weight: 400;
	line-height: normal;
	text-decoration: none;
	transition: color 0.2s ease;
}

.site-footer__contact a:hover {
	color: var(--wp--preset--color--surface);
}

.site-footer__contact-icon {
	display: inline-flex;
	color: var(--wp--preset--color--surface);
}

.site-footer__address {
	margin: var(--wp--preset--spacing--16) 0 0;
	font-style: normal;
	line-height: 1.4;
	color: var(--wp--preset--color--surface);
}

/* RIGHT column: form */
.site-footer__form-heading {
	font-family: var(--wp--preset--font-family--display);
	font-size: 1.25rem;
	line-height: 1.3;
	color: var(--wp--preset--color--surface);
	margin: 0 0 var(--wp--preset--spacing--40);
	font-weight: 400;
}

.site-footer__form {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--16);
}

.form-row {
	display: flex;
	gap: var(--wp--preset--spacing--16);
}

.form-row--inline {
	flex-wrap: wrap;
	align-items: center;
}

.form-field {
	flex: 1;
	min-width: 0;
	display: flex;
	align-items: center;
	background: rgba(255, 255, 255, 0.95);
	border: 1px solid rgba(255, 255, 255, 0.2);
	border-radius: 8px;
	padding: 0 var(--wp--preset--spacing--16);
	min-height: 47px;
}

.form-field input,
.form-field select {
	flex: 1;
	width: 100%;
	background: transparent;
	border: 0;
	padding: 12px 0;
	font-family: var(--wp--preset--font-family--display);
	font-size: 0.875rem;
	color: var(--wp--preset--color--ink);
	outline: none;
}

.form-field input::placeholder {
	color: rgba(0, 0, 0, 0.4);
}

.form-field--area input {
	max-width: 60px;
}

.form-field--select {
	max-width: 110px;
	flex: 0 0 110px;
}

.form-suffix {
	color: rgba(0, 0, 0, 0.4);
	font-size: 0.875rem;
	margin-left: 4px;
}

.form-label {
	font-family: var(--wp--preset--font-family--display);
	font-size: 0.875rem;
	color: rgba(255, 255, 255, 0.7);
}

.form-checkbox {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--10);
	color: var(--wp--preset--color--surface);
	font-family: var(--wp--preset--font-family--display);
	font-size: 0.875rem;
	cursor: pointer;
}

.form-checkbox input {
	width: 18px;
	height: 18px;
	flex-shrink: 0;
	accent-color: var(--wp--preset--color--primary);
	cursor: pointer;
}

.form-submit {
	margin-top: var(--wp--preset--spacing--16);
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--surface);
	padding: 16px 32px;
	border: 0;
	border-radius: 8px;
	font-family: var(--wp--preset--font-family--display);
	font-size: 0.9375rem;
	cursor: pointer;
	transition: background-color 0.2s ease;
}

.form-submit:hover,
.form-submit:focus-visible {
	background: var(--wp--preset--color--ink);
}

/* BOTTOM row: legal + center logo + credit (3-column on desktop). */
.site-footer__bottom {
	position: relative;
	z-index: 1;
	max-width: 1840px;
	margin: 120px auto 0;
	padding-top: 24px;
	border-top: 1px solid rgba(255, 255, 255, 0.1);
	display: grid;
	grid-template-columns: 1fr auto 1fr;
	align-items: center;
	font-family: var(--wp--preset--font-family--display);
	font-size: 0.875rem;
	color: rgba(255, 255, 255, 0.5);
}

.site-footer__legal {
	display: flex;
	gap: var(--wp--preset--spacing--24);
	justify-self: start;
}

.site-footer__legal a {
	color: inherit;
	text-decoration: none;
}

.site-footer__legal a:hover {
	color: var(--wp--preset--color--surface);
}

/* Centered small logo between legal and credit. */
.site-footer__bottom-logo {
	display: inline-flex;
	color: var(--wp--preset--color--surface);
	justify-self: center;
}

.site-footer__bottom-logo svg {
	display: block;
	width: 80px;
	height: auto;
}

.site-footer__credit {
	margin: 0;
	color: rgba(255, 255, 255, 0.50);
	line-height: 140%;
	justify-self: end;
}

.site-footer__credit a {
	color: #FFF;
	text-decoration-line: underline;
	text-underline-position: from-font;
}

@media (max-width: 900px) {
	.site-footer {
		padding: 60px var(--wp--preset--spacing--40) 30px;
	}

	.site-footer__inner {
		grid-template-columns: 1fr;
		gap: var(--wp--preset--spacing--50);
	}

	.site-footer__divider {
		display: none;
	}

	.site-footer__form-heading {
		margin-bottom: 30px;
	}

	.form-row {
		flex-direction: column;
	}

	.form-row--inline {
		flex-direction: row;
	}

	/* Mobile bottom row: 2 rows × 2 columns.
	 *   Row 1: legal-left | credit-right
	 *   Row 2: (centered logo spans both columns)
	 * (per Figma — the order is different from desktop's 3-column inline.) */
	.site-footer__bottom {
		display: grid;
		grid-template-columns: 1fr 1fr;
		grid-template-areas:
			"legal credit"
			"logo logo";
		row-gap: 24px;
		column-gap: 16px;
		align-items: center;
		margin-top: 60px;
	}

	.site-footer__legal {
		grid-area: legal;
		flex-wrap: wrap;
		justify-self: start;
	}

	.site-footer__credit {
		grid-area: credit;
		justify-self: end;
	}

	.site-footer__bottom-logo {
		grid-area: logo;
		justify-self: center;
	}
}

/* =========================================================
 * Blog: homepage section, archive, single. Card component is shared.
 * ========================================================= */

/* Shared blog card. 600px max-width, 1px border + 8px radius, 10px outer padding
 * (image-link sits in that padded area = 580px image). The whole card is a
 * click target via a stretched pseudo-element on the title's <a>; individual
 * inner links (image, arrow) stay clickable on their own at higher z-index. */
.blog-card {
	position: relative;
	display: flex;
	flex-direction: column;
	max-width: 600px;
	background: var(--wp--preset--color--surface);
	border: 1px solid rgba(0, 0, 0, 0.10);
	border-radius: 8px;
	padding: 10px;
	box-sizing: border-box;
}

.blog-card__image-link {
	position: relative;
	z-index: 2; /* above the stretched-title pseudo-link */
	display: block;
	line-height: 0;
	overflow: hidden;
	border-radius: 8px;
	aspect-ratio: 580 / 342;
}

.blog-card__image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 0.5s ease;
}

/* Image zoom triggered by hover anywhere on the card — not just the image link. */
.blog-card:hover .blog-card__image {
	transform: scale(1.04);
}

.blog-card__image--placeholder {
	background: linear-gradient(135deg, #EFEAE5 0%, #DBCCC3 100%);
}

.blog-card__body {
	display: flex;
	flex-direction: column;
	/* Top padding = image-to-pill gap (40px desktop, 30px mobile).
	 * Side/bottom padding (30px desktop, 15px mobile). */
	padding: clamp(30px, calc(1.5vw + 24px), 40px)
		clamp(15px, calc(1.9vw + 9px), 30px)
		clamp(15px, calc(1.9vw + 9px), 30px);
	flex: 1 1 auto;
}

.blog-card__pills {
	display: flex;
	flex-wrap: wrap;
	gap: 6px;
	/* Pill-to-title gap: 40px desktop → 16px mobile. */
	margin: 0 0 clamp(16px, calc(2.4vw + 8px), 40px);
}

.blog-card__pill {
	display: inline-flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
	gap: 10px;
	padding: 8px 10px;
	background: rgba(240, 229, 222, 0.50);
	color: #956F60;
	border-radius: 8px;
	font-family: var(--wp--preset--font-family--display);
	font-size: 0.75rem;
	font-weight: 400;
	line-height: 1;
	letter-spacing: -0.06px;
	text-align: center;
	text-decoration: none;
	transition: background-color 0.2s ease;
}

.blog-card__pill:hover {
	background: rgba(240, 229, 222, 0.85);
}

.blog-card__title {
	font-family: var(--wp--preset--font-family--display);
	/* 20px desktop → 14px mobile */
	font-size: clamp(14px, calc(0.94vw + 11px), 20px);
	line-height: 1.4;
	color: #000000;
	margin: 0 0 10px;
	font-weight: 400;
}

.blog-card__title a {
	color: inherit;
	text-decoration: none;
}

/* No underline on title hover — the whole-card image zoom is the hover affordance.
 * The pseudo-element stretches to cover the whole card so any click on the
 * card outside the image-link/arrow lands on the title's permalink. */
.blog-card__title a:hover {
	text-decoration: none;
}

.blog-card__title a::after {
	content: '';
	position: absolute;
	inset: 0;
	z-index: 1;
}

.blog-card__excerpt {
	font-family: var(--wp--preset--font-family--display);
	/* 14px desktop → 10px mobile */
	font-size: clamp(10px, calc(0.63vw + 8px), 14px);
	line-height: 2;
	color: #000000;
	margin: 0 0 16px;
	max-width: 468px;
}

.blog-card__footer {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-top: auto;
}

.blog-card__date {
	font-family: var(--wp--preset--font-family--display);
	/* 14px desktop → 10px mobile (same scale as excerpt) */
	font-size: clamp(10px, calc(0.63vw + 8px), 14px);
	line-height: 1;
	color: #000000;
	letter-spacing: 0.04em;
}

/* Arrow wrapper: 40x40 tan square desktop → 24x24 mobile.
 * Padding tuned so the SVG stays at the full size at every breakpoint.
 * Slides right on card hover for a subtle "go" affordance. */
.blog-card__arrow {
	position: relative;
	z-index: 2; /* above the stretched-title pseudo-link */
	display: flex;
	width: clamp(24px, calc(2.5vw + 16px), 40px);
	height: clamp(24px, calc(2.5vw + 16px), 40px);
	padding: clamp(8px, calc(0.63vw + 6px), 12px);
	box-sizing: border-box;
	justify-content: center;
	align-items: center;
	border-radius: 8px;
	background: #F0E5DE;
	transition: background-color 0.2s ease, transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

.blog-card__arrow svg {
	display: block;
	width: clamp(8px, calc(1.25vw + 4px), 16px);
	height: auto;
	flex-shrink: 0;
}

.blog-card:hover .blog-card__arrow {
	transform: translateX(6px);
}

.blog-card__arrow:hover {
	background: #E5D5CB;
}

/* Hero variant (archive only): horizontal layout, image on the left.
 * Wraps to single-column at ≤1100px (image + content stack vertically) since
 * the 580px image + content side-by-side doesn't read well below that width. */
.blog-card--hero {
	flex-direction: row;
	max-width: 1220px;
}

.blog-card--hero .blog-card__image-link {
	flex: 0 0 580px;
	aspect-ratio: 580 / 342;
}

.blog-card--hero .blog-card__body {
	flex: 1 1 auto;
	padding: 30px 40px;
	justify-content: center;
}

@media (max-width: 1100px) {
	.blog-card--hero {
		flex-direction: column;
	}

	.blog-card--hero .blog-card__image-link {
		flex: 0 0 auto;
		width: 100%;
	}

	.blog-card--hero .blog-card__body {
		padding: clamp(15px, 3vw, 30px);
	}
}

/* =========================================================
 * Homepage blog section ("Čo je nové v Levínkach?")
 * Header copies .benefits__header pattern: narrow 966px band centered.
 * ========================================================= */
.blog-section {
	position: relative;
	overflow: hidden; /* clip the decorative star at the edges */
	padding: 150px var(--wp--preset--spacing--40);
	background: var(--wp--preset--color--surface);
}

.blog-section__inner {
	position: relative;
	z-index: 1;
	max-width: 1620px;
	margin: 0 auto;
}

/* Decorative star with soft cream drop-shadow — sits right of the cards
 * column, well below the section header. Positioned via viewport math:
 * center + half-of-cards-grid (1316/2=658) + 140px gap. Behind content. */
.blog-section__star {
	position: absolute;
	top: clamp(280px, 26vw, 480px); /* approx 340px below description bottom */
	left: calc(50% + 658px + 140px);
	width: 766px;
	height: 784px;
	pointer-events: none;
	user-select: none;
	z-index: 0;
}

.blog-section__header {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	align-items: flex-start;
	column-gap: var(--wp--preset--spacing--60);
	row-gap: 20px;
	max-width: 966px;
	/* 80px desktop → 32px mobile space below header */
	margin: 0 auto clamp(32px, calc(7.5vw + 8px), 80px);
}

.blog-section__title {
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(32px, calc(0.962vw + 24.62px), 40px);
	line-height: 1.1;
	color: #494A39;
	margin: 0;
	font-weight: 400;
	max-width: 264px;
}

.blog-section__title span {
	display: block;
}

.blog-section__description {
	font-family: var(--wp--preset--font-family--display);
	font-size: 0.9375rem;
	line-height: 1.4;
	color: rgba(0, 0, 0, 0.50);
	margin: 0;
	max-width: 452px;
}

.blog-section__grid {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 600px));
	gap: 20px;
	justify-content: center;
	max-width: 1316px;
	margin: 0 auto;
}

.blog-section__cta-wrap {
	/* 80px desktop → 32px mobile space above the CTA */
	margin-top: clamp(32px, calc(7.5vw + 8px), 80px);
	display: flex;
	justify-content: center;
}

@media (max-width: 900px) {
	.blog-section {
		padding: 75px var(--wp--preset--spacing--40);
	}

	.blog-section__header {
		flex-direction: column;
		gap: var(--wp--preset--spacing--30);
		margin-bottom: 35px;
	}

	.blog-section__title {
		font-size: 2rem;
	}

	.blog-section__grid {
		grid-template-columns: 1fr;
		gap: 20px;
	}

	/* Single-column on mobile: card grows to fill the column. */
	.blog-card {
		max-width: 100%;
	}
}

/* =========================================================
 * Page-top gradient: full-bleed light banner under the site-header.
 * Used on archive + single. Sits behind everything so the (initially
 * transparent) header overlays it; title is positioned ~180px below
 * the header bottom via inner padding-top.
 * ========================================================= */
.page-top-gradient {
	position: absolute;
	top: 0;
	left: 50%;
	transform: translateX(-50%);
	width: 100vw;
	height: 280px;
	background: linear-gradient(180deg, #FAF6F1 0%, #FFF 100%);
	border-radius: 8px 0 0 8px;
	z-index: 0;
	pointer-events: none;
}

/* =========================================================
 * Blog archive (templates/home.html)
 * ========================================================= */
.blog-archive {
	position: relative;
	padding: 0 var(--wp--preset--spacing--40) 150px;
	background: var(--wp--preset--color--surface);
}

.blog-archive__inner {
	position: relative;
	z-index: 1;
	max-width: 1220px;
	margin: 0 auto;
	padding-top: 280px; /* header (~100px) + 180px gap to title */
}

.blog-archive__title {
	color: #000;
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--huge); /* clamp(42px, fluid, 96px) — same as h1 on homepage hero */
	font-weight: 400;
	font-style: normal;
	line-height: normal;
	margin: 0 0 80px;
}

.blog-archive__hero {
	margin-bottom: 20px;
}

.blog-archive__grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 20px;
}

.blog-archive__load-more-wrap {
	margin-top: 60px;
	display: flex;
	justify-content: center;
}

/* Load-more inherits .btn .btn--primary; only need to add the loading state. */
.blog-archive__load-more.is-loading {
	opacity: 0.6;
	cursor: progress;
}

@media (max-width: 900px) {
	.blog-archive {
		padding: 0 var(--wp--preset--spacing--40) 75px;
	}

	.blog-archive__inner {
		padding-top: 180px;
	}

	.blog-archive__title {
		font-size: 3.5rem;
		margin-bottom: 30px;
	}

	.blog-archive__grid {
		grid-template-columns: 1fr;
		gap: 20px;
	}

	.blog-card--hero {
		max-width: 100%;
	}
}

/* =========================================================
 * Single post (templates/single.html) — centered top per Figma:
 * gradient banner, meta line, BIG title, author group, then wide
 * featured image, then narrow prose body.
 * ========================================================= */
/* Scoped to article.single-post so it doesn't collide with WordPress's
 * `body.single-post` class (which would double the horizontal padding). */
article.single-post {
	position: relative;
	padding: 0 var(--wp--preset--spacing--40) 120px;
	background: var(--wp--preset--color--surface);
}

.single-post__header {
	position: relative;
	z-index: 1;
	max-width: 1240px;
	margin: 0 auto;
	padding-top: 230px; /* header (~100px) + 130px gap to meta */
	text-align: center;
}

.single-post__meta-top {
	font-family: var(--wp--preset--font-family--display);
	font-size: 1rem;
	font-style: normal;
	font-weight: 400;
	line-height: 170%;
	color: rgba(0, 0, 0, 0.50);
	margin-bottom: 48px;
}

.single-post__title {
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--huge);
	line-height: 1.1;
	color: #000;
	margin: 0 auto 50px;
	font-weight: 400;
	max-width: 980px;
}

.single-post__authors {
	display: inline-flex;
	align-items: center;
	gap: 16px;
	margin-bottom: 80px;
}

/* Defensive: wpautop sometimes wraps the inline names element when it sits
 * next to the avatars div. Zero-margin any <p> that ends up inside. */
.single-post__authors > p {
	margin: 0;
}

.single-post__authors-avatars {
	display: inline-flex;
	align-items: center;
}

.single-post__author-avatar {
	width: 32px;
	height: 32px;
	border-radius: 999px;
	border: 2px solid var(--wp--preset--color--surface);
	margin-left: -8px;
	background: #EFEAE5;
	box-sizing: border-box;
}

.single-post__author-avatar:first-child {
	margin-left: 0;
}

.single-post__author-plus {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 28px;
	height: 28px;
	padding: 0 8px;
	border-radius: 999px;
	background: #956F60;
	color: var(--wp--preset--color--surface);
	font-family: var(--wp--preset--font-family--display);
	font-size: 0.75rem;
	line-height: 1;
	margin-left: -8px;
	border: 2px solid var(--wp--preset--color--surface);
	box-sizing: border-box;
}

.single-post__authors-names {
	font-family: var(--wp--preset--font-family--display);
	font-size: 1rem;
	color: #494A39;
}

.single-post__image-wrap {
	position: relative;
	z-index: 1;
	max-width: 1240px;
	margin: 0 auto 80px;
}

.single-post__image {
	display: block;
	width: 100%;
	height: auto;
	max-height: 600px;
	object-fit: cover;
}

/* Prose body: narrower than image, left-aligned reading column. */
.single-post__content {
	position: relative;
	z-index: 1;
	max-width: 951px;
	margin: 0 auto;
	font-family: var(--wp--preset--font-family--display);
	font-size: 1rem;
	line-height: 1.8;
	color: #494A39;
}

.single-post__content > * {
	margin-block: 1.4em;
}

.single-post__content > :first-child {
	margin-top: 0;
}

.single-post__content > :last-child {
	margin-bottom: 0;
}

.single-post__content h2,
.single-post__content h3,
.single-post__content h4 {
	font-family: var(--wp--preset--font-family--display);
	color: #494A39;
	font-weight: 400;
	line-height: 1.2;
}

.single-post__content h2 { font-size: 2rem; margin-top: 2em; }
.single-post__content h3 { font-size: 1.5rem; }

.single-post__content a {
	color: #494A39;
	text-underline-offset: 3px;
}

/* Quote block: brown underlined quote text, ink author label. */
.single-post__content .wp-block-quote {
	border: 0;
	padding: 40px 0;
	margin: 2em 0;
	position: relative;
}

.single-post__content .wp-block-quote p {
	color: #956F60;
	font-family: var(--wp--preset--font-family--display);
	font-size: 2rem;
	font-style: normal;
	font-weight: 400;
	line-height: 160%;
	margin: 0 0 32px;
	text-decoration-line: underline;
	text-decoration-style: solid;
	text-decoration-skip-ink: none;
	text-decoration-thickness: auto;
	text-underline-offset: auto;
	text-underline-position: from-font;
}

.single-post__content .wp-block-quote cite {
	color: #000;
	font-family: var(--wp--preset--font-family--display);
	font-size: 1rem;
	font-style: normal;
	font-weight: 400;
	line-height: 110%;
}

/* Gallery: 2-column 60/40 split per Figma single design. Native gallery wraps
 * each image in figure.wp-block-image; widen the first one. */
.single-post__content .wp-block-gallery.columns-2 {
	display: grid;
	grid-template-columns: 60fr 40fr;
	gap: 16px;
	margin: 2em 0;
}

.single-post__content .wp-block-gallery .wp-block-image {
	margin: 0;
}

.single-post__content .wp-block-gallery .wp-block-image img {
	display: block;
	width: 100%;
	height: 100%;
	max-height: 460px;
	object-fit: cover;
	border-radius: 8px;
}

@media (max-width: 900px) {
	article.single-post {
		padding: 0 30px 75px;
	}

	.single-post__header {
		padding-top: 180px;
	}

	.single-post__title {
		font-size: clamp(32px, calc(4vw + 16px), 56px);
		margin-bottom: 30px;
	}

	.single-post__authors {
		margin-bottom: 40px;
	}

	.single-post__image-wrap {
		margin-bottom: 40px;
	}

	.single-post__content {
		font-size: 0.9375rem;
	}

	.single-post__content .wp-block-gallery.columns-2 {
		grid-template-columns: 1fr;
	}
}

/* =========================================================
 * Reveal-on-scroll system (paired with assets/js/reveal.js).
 *
 * Three reusable variants — apply via data-reveal="..." on any element:
 *   - text   : per-character slice (titles); JS splits into .reveal-char
 *   - fade   : whole-element fade + small slide-up (descriptions, copy)
 *   - card   : card-grid stagger; JS auto-indexes siblings via --i
 *
 * Initial state (hidden) only applies when JS adds .has-reveal-js to <html>.
 * Without JS the element stays visible (graceful degradation).
 * ========================================================= */

/* TEXT variant. Two sub-modes:
 *   default              — per-CHARACTER slice (best for short titles)
 *   data-reveal-by="word"— per-WORD slice (best for long paragraphs)
 *
 * Both rely on the same JS split (reveal.js): chars inside .reveal-word
 * wrappers. .reveal-word is always nowrap so lines break BETWEEN words only.
 * --i  is set on every char; --word-i is set on every word.
 *
 * FOUC PREVENTION: until JS has split the text and added .is-split, the
 * whole parent is `visibility: hidden`. Without this, the raw text is
 * visible on first paint, then JS splits it and the (now-existing) chars
 * snap to opacity:0 — producing a visible "flash and disappear" before
 * the slice animation fires. The visibility-hide preserves layout, so
 * nothing shifts when the title finally appears. */
.has-reveal-js [data-reveal="text"]:not(.is-split) {
	visibility: hidden;
}

.has-reveal-js [data-reveal="text"] .reveal-word {
	display: inline-block;
	white-space: nowrap;
}

.has-reveal-js [data-reveal="text"]:not([data-reveal-by="word"]) .reveal-char {
	display: inline-block;
	opacity: 0;
	transform: translateX(12px);
	will-change: opacity, transform;
}

.has-reveal-js [data-reveal="text"]:not([data-reveal-by="word"]).is-revealed .reveal-char {
	animation: reveal-text-char 0.6s cubic-bezier(0.22, 1, 0.36, 1) forwards;
	animation-delay: calc(var(--i, 0) * 22ms);
}

@keyframes reveal-text-char {
	from { opacity: 0; transform: translateX(12px); }
	to   { opacity: 1; transform: translateX(0); }
}

/* MAP variant — for large image reveals (e.g. .locality__map). Fade + subtle
 * zoom-down + slide-up. Uses transitions (not keyframe animations + clip-path
 * which was leaving the map stuck in the initial hidden state in some browsers). */
.has-reveal-js [data-reveal="map"] {
	opacity: 0;
	transform: translateY(20px) scale(0.97);
	transform-origin: center top;
	transition:
		opacity 1.2s cubic-bezier(0.22, 1, 0.36, 1),
		transform 1.4s cubic-bezier(0.22, 1, 0.36, 1);
	will-change: opacity, transform;
}

.has-reveal-js [data-reveal="map"].is-revealed {
	opacity: 1;
	transform: translateY(0) scale(1);
}

/* Word-mode: animate whole words, leave chars alone. */
.has-reveal-js [data-reveal="text"][data-reveal-by="word"] .reveal-word {
	opacity: 0;
	transform: translateY(12px);
	will-change: opacity, transform;
}

.has-reveal-js [data-reveal="text"][data-reveal-by="word"].is-revealed .reveal-word {
	animation: reveal-text-word 0.7s cubic-bezier(0.22, 1, 0.36, 1) forwards;
	animation-delay: calc(var(--word-i, 0) * 60ms);
}

@keyframes reveal-text-word {
	from { opacity: 0; transform: translateY(12px); }
	to   { opacity: 1; transform: translateY(0); }
}

/* FADE variant — whole element. Animation (not transition) so the
 * element's own transition can still be used for hover effects. */
.has-reveal-js [data-reveal="fade"] {
	opacity: 0;
	will-change: opacity, transform;
}

.has-reveal-js [data-reveal="fade"].is-revealed {
	animation: reveal-fade 0.8s cubic-bezier(0.22, 1, 0.36, 1) 200ms forwards;
}

@keyframes reveal-fade {
	from { opacity: 0; transform: translateY(14px); }
	to   { opacity: 1; transform: translateY(0); }
}

/* CARD variant — grid item with stagger (JS sets --i per sibling).
 * Same animation-not-transition approach so button .btn hover transitions
 * (background-color/color/border-color) survive on .hero__actions buttons. */
.has-reveal-js [data-reveal="card"] {
	opacity: 0;
	will-change: opacity, transform;
}

.has-reveal-js [data-reveal="card"].is-revealed {
	animation: reveal-card 0.7s cubic-bezier(0.22, 1, 0.36, 1) forwards;
	animation-delay: calc(var(--i, 0) * 90ms);
}

@keyframes reveal-card {
	from { opacity: 0; transform: translateY(24px); }
	to   { opacity: 1; transform: translateY(0); }
}

/* CTA banner entrance sequencing — brown background appears first, then
 * content cascades in. The big-star + small-stars are children of the
 * inner so they inherit the inner's opacity transition (no individual
 * data-reveal needed on them — which was causing the perceived 1-1.5s
 * delay because their absolute-positioned top: -300 placed them outside
 * the IntersectionObserver's hit zone). */
.has-reveal-js .cta-banner__title[data-reveal="text"].is-revealed .reveal-char {
	animation-delay: calc(400ms + var(--i, 0) * 22ms);
}
.has-reveal-js .cta-banner__lead[data-reveal="fade"].is-revealed {
	animation-delay: 700ms;
}
.has-reveal-js .cta-banner__cta[data-reveal="card"].is-revealed {
	animation-delay: 1000ms;
}

/* Hero entrance sequencing — orchestrates a deliberate cascade:
 *   title (slice, 0ms)
 *     ↓
 *   description (fade, 500ms — overlaps mid-title)
 *     ↓
 *   3 buttons (card stagger, 900ms base + 100ms/btn)
 * Without these overrides each element animates with its own default
 * timing and they finish in arbitrary order, which feels unmotivated. */
.has-reveal-js .hero__description[data-reveal="fade"].is-revealed {
	animation-delay: 500ms;
}

/* Buttons need a tighter motion + base delay for the cascade. We override
 * the animation entirely with a custom-keyframe variant (12px instead of
 * the card default 24px) and a per-button stagger anchored to 900ms. */
.has-reveal-js .hero__actions [data-reveal="card"].is-revealed {
	animation: reveal-hero-button 0.7s cubic-bezier(0.22, 1, 0.36, 1) forwards;
	animation-delay: calc(900ms + var(--i, 0) * 100ms);
}

@keyframes reveal-hero-button {
	from { opacity: 0; transform: translateY(12px); }
	to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
	.has-reveal-js [data-reveal] {
		opacity: 1 !important;
		transform: none !important;
		transition: none !important;
	}
	.has-reveal-js [data-reveal="text"] .reveal-char {
		opacity: 1 !important;
		transform: none !important;
		animation: none !important;
	}
}

/* =========================================================
 * MOBILE PADDING LADDER — single source of truth for horizontal padding on
 * small screens. Lives at the bottom so it wins over all earlier rules.
 *
 * Most sections        30px  | section bodies, titles, prose containers
 * Hero content         30px  | matches section bodies
 * Header pill          15px  | tighter so the pill doesn't feel oversized
 * Blog cards           15px  | grids hug the screen edge a bit more
 * CTA banner           10px  | banner takes near-full width on mobile
 * Benefits cards        5px  | expandable cards need maximum room
 * ========================================================= */
@media (max-width: 900px) {
	/* Most sections: 30px L/R */
	.home-intro,
	.future,
	.blog-section {
		padding-left: 30px;
		padding-right: 30px;
	}

	.locality__inner {
		padding-left: 30px;
		padding-right: 30px;
	}

	.hero__inner {
		padding-left: 30px;
		padding-right: 30px;
	}

	/* Header pill: 15px L/R (overrides the existing .site-header rule). */
	.site-header {
		padding-left: 15px !important;
		padding-right: 15px !important;
	}

	/* Blog cards container: 15px from screen edge; header keeps 30px via
	 * its own extra padding so the title sits at 30px from the edge. */
	.blog-archive {
		padding-left: 15px;
		padding-right: 15px;
	}
	.blog-section {
		padding-left: 15px;
		padding-right: 15px;
	}
	.blog-section__header {
		padding-left: 15px;
		padding-right: 15px;
	}

	/* Single post: 30px article container (already set in article.single-post). */

	/* CTA banner: 10px L/R */
	.cta-banner {
		padding-left: 10px;
		padding-right: 10px;
	}

	/* Benefits expandable cards: 5px L/R so cards take maximum width. The
	 * header (title + description) gets its own 25px padding so the text
	 * still sits at 30px from the screen edge. */
	.benefits {
		padding-left: 5px;
		padding-right: 5px;
	}
	.benefits__header {
		padding-left: 25px;
		padding-right: 25px;
	}
}

/* =========================================================
 * Reduced motion — disable all animations for users that ask
 * ========================================================= */
@media (prefers-reduced-motion: reduce) {
	.site-header,
	.site-menu,
	.site-menu__divider,
	.site-menu__hero,
	.site-menu__nav,
	.site-menu__footer,
	.site-header__menu-icon__line {
		transition: none !important;
	}
}
