/*
Theme Name: Hof Gritzenmoos
Theme URI: https://example.ch
Author: Scott Barlocher
Description: Editorial block theme for Hof Gritzenmoos. Swiss German content, content-only client editing, tasteful CSS/JS motion.
Version: 0.3.21
Requires at least: 6.6
Tested up to: 7.1
Requires PHP: 8.0
License: GPL-2.0-or-later
Text Domain: website-roman
*/

/* ---- Hof Gritzenmoos custom front-end styles ---- */

/* Header: static, never follows the scroll. On the front page it floats transparently
   over the full-screen hero (as on triumphpforte.at), so the Apricot panel can run up to
   the very top edge. .wp-site-blocks is the positioning context, which keeps the header
   below the admin bar. */
.wp-site-blocks { position: relative; }
.home .wp-site-blocks > .wp-block-template-part:has(> .site-header) {
	position: absolute;
	inset-inline: 0;
	top: 0;
	z-index: 10;
}
.home .site-header { background: transparent !important; }

/* Teaser card hover */
.card-lift { transition: transform 0.35s ease, box-shadow 0.35s ease; }
.card-lift:hover { transform: translateY(-6px); box-shadow: 0 0.75rem 1.875rem rgba(36,36,32,0.12); }
.card-lift .wp-block-image img { transition: transform 0.5s ease; will-change: transform; }
.card-lift:hover .wp-block-image img { transform: scale(1.05); }

/* Scroll-driven reveal (progressive enhancement; JS fallback adds .is-visible) */
.is-reveal { opacity: 0; transform: translateY(1rem); }
.is-reveal.is-visible { opacity: 1; transform: none; transition: opacity 0.7s ease, transform 0.7s ease; }

/* Keep reveal sections fully visible inside the block editor (motion.js is front-end only) */
.editor-styles-wrapper .is-reveal { opacity: 1; transform: none; }

@supports (animation-timeline: view()) {
	.is-reveal {
		animation: rh-reveal linear both;
		animation-timeline: view();
		animation-range: entry 0% entry 40%;
	}
}
@keyframes rh-reveal { from { opacity: 0; transform: translateY(1rem); } to { opacity: 1; transform: none; } }

/* Hero headline */
.hero-headline { animation: rh-fade-up 0.9s ease both; }
/* The farm name scales with the screen width up to 8rem, well past the Display preset. */
.hero .hero-sub { font-weight: 200; }
.hero .hero-headline { font-size: clamp(2.5rem, 4.4vw + 1.625rem, 8rem) !important; /* "Gritzenmoos" (about 7.6 x the size) must fit its column on one line */ line-height: 1; }
/* Narrow desktop: the text column is only about half the width, so keep the word on one line. */
@media (min-width: 782px) and (max-width: 1100px) { .hero .hero-headline { font-size: 6.1vw !important; } }
@keyframes rh-fade-up { from { opacity: 0; transform: translateY(1.5rem); } to { opacity: 1; transform: none; } }

/* Global scale: the design was tuned at 80% browser zoom, so 100% is now that size. All sizes are in rem
   (or vw/svh), so this one root size scales the whole site. Media-query breakpoints stay in px to match core's. */
html { font-size: 80%; }

/* ---- Hero ---- */
/* Exactly one screen tall (minus the admin bar when logged in); the Patenschaft band
   starts below the fold. */
.hero { --hero-h: calc(100svh - var(--wp-admin--admin-bar--height, 0px)); }
/* Wider than the site's wideSize, so headline, tree and panel spread across the screen
   (as on triumphpforte.at). The front-page nav shares the same edge as the headline. */
/* Left margin: 8% of the width up to 1440px, widening to 15% at 1920px and staying there; the
   right margin is a constant 6% (measured on triumphpforte.at). --hero-wide is the symmetric
   column other sections align to; the hero and nav use the asymmetric one below. */
:root {
	--hero-left: clamp(1.5rem, 8vw + (100vw - 1152px) * 0.28, 15vw);
	--hero-right: clamp(1.5rem, 6vw, 6vw);
	--hero-wide: calc(100vw - 2 * var(--hero-left));
}
.hero__columns { margin-block-start: 0; min-height: var(--hero-h); }
.hero > .hero__columns.alignwide { max-width: var(--hero-wide); }
@media (min-width: 782px) {
	.hero > .hero__columns.alignwide { max-width: calc(100vw - var(--hero-left) - var(--hero-right)); margin-left: calc(var(--hero-left) - 1.5rem) !important; margin-right: auto !important; }
}
/* The nav sits on the hero's left edge on every page, so the tabs never move between pages. */
@media (min-width: 782px) {
	.site-header > .site-nav.alignwide { max-width: calc(100vw - var(--hero-left) - var(--hero-right)); margin-left: calc(var(--hero-left) - 1.5rem) !important; margin-right: auto !important; }
}
.hero__text { padding-block: var(--wp--preset--spacing--80) var(--wp--preset--spacing--70); }
/* Keep the subtitle clear of the tree's left-hand leaves. */
.hero__text > p { max-width: 30ch; }
.hero__aside {
	--panel-w: min(100%, 26rem);
	--panel-h: calc(var(--hero-h) * 0.85);
	position: relative;
	display: flex;
	justify-content: flex-end;
	align-items: flex-start;
}
/* The panel hangs from the top edge to 85% of the screen, leaving an Organic strip below. */
.hero__panel {
	position: relative;
	z-index: 1;
	width: var(--panel-w);
	min-height: var(--panel-h);
	margin-block-start: 0;
	display: flex;
	flex-direction: column;
	justify-content: space-between;
}
.hero__panel .wordmark {
	margin-top: 0;
	font-size: clamp(1.6rem, 2.4vw, 2.3rem);
	overflow-wrap: normal;
	word-break: normal;
}
.hero__contact p { margin-block: 0.5rem; font-weight: 300; font-size: var(--wp--preset--font-size--medium); }
.hero__contact a { color: inherit; text-decoration: underline; text-underline-offset: 0.2em; overflow-wrap: anywhere; }
@media (max-width: 781px) {
	.hero__aside { flex-direction: column; align-items: center; }
	.hero__columns { min-height: 0; }
	.hero { min-height: var(--hero-h); padding-bottom: var(--wp--preset--spacing--60) !important; }
	.hero__panel { width: 100%; min-height: 0; gap: var(--wp--preset--spacing--50); }
}

/* ---- Hof (hero → Hof transition) ---- */
/* The photo's top edge sits exactly at the fold (the hero is one screen tall), so it scrolls
   in with the first movement. The Organic ground carries on past the fold for --hof-overlap,
   so the photo straddles the seam between the two bands (as on triumphpforte.at). */
.hof {
	--hof-overlap: clamp(3rem, 9vw, 8rem);
	background: linear-gradient(var(--wp--preset--color--primary) 0 var(--hof-overlap), var(--wp--preset--color--base) 0) !important;
	margin-block-start: -1px !important;
	padding-block-start: 1px !important;
}
.hof > .hof__columns.alignwide { max-width: var(--hero-wide); margin-block-start: 0; gap: var(--wp--preset--spacing--70); }
.hof__photo .wp-block-image { margin: 0; }
/* The photo starts half the overlap below the fold, so it reaches only half-way into the
   Organic ground above the seam. */
.hof__columns > .hof__photo { padding-block-start: calc(var(--hof-overlap) / 2); }
/* Cropped from the bottom (the empty meadow), keeping sky, Alps and farmstead. */
.hof__photo img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; object-position: 50% 0; }
.hof__text { padding-block-start: calc(var(--hof-overlap) + var(--wp--preset--spacing--50)); max-width: 34rem; }
/* Body face in bold, sentence case: quieter than the section headings elsewhere. */
.hof__text h2 {
	font-family: var(--wp--preset--font-family--body);
	font-weight: 700;
	text-transform: none;
	letter-spacing: 0;
	font-size: inherit;
	line-height: inherit;
	hyphens: manual;
}
.hof__text h2 + p { margin-block-start: 0.4em; }
/* Desktop: the photo spans 10% to 55% of the browser width. Its column ends at 55% (the
   columns are centred on --hero-wide, so their left edge is half the leftover width);
   the photo is right-aligned in it at 45vw wide, so its left edge lands at 10%. Change
   the 55vw and 45vw together to move either edge. The text starts a gap to the right. */
@media (min-width: 782px) {
	.hof > .hof__columns.alignwide { gap: 0; }
	.hof__columns > .hof__photo { flex: 0 0 calc(55vw - (100vw - var(--hero-wide)) / 2) !important; }
	.hof__columns > .hof__text { flex: 1 1 0 !important; box-sizing: border-box; }
	.hof__photo { display: flex; justify-content: flex-end; }
	.hof__photo .wp-block-image { width: min(100%, 45vw); }
	.hof__columns > .hof__text { padding-inline-start: var(--wp--preset--spacing--80); }
	/* Snapped (set by motion.js when the text column would be taller than the photo): the
	   photo reaches out to the browser's left edge (0 to 55%), and if the text is still
	   taller it grows in height to match, cropping the sides rather than leaving the text
	   hanging below it. */
	.hof.is-snapped .hof__photo .wp-block-image {
		flex: none;
		width: calc(100% + (100vw - var(--hero-wide)) / 2);
		margin-inline-start: calc((100vw - var(--hero-wide)) / -2);
	}
	.hof.is-snapped .hof__photo .wp-block-image { height: 100%; }
	/* 16:9 at the wider width, or the text's height if that is taller. */
	.hof.is-snapped .hof__photo img { height: auto; min-height: 100%; }
}
@media (max-width: 781px) {
	.hof { --hof-overlap: 2.5rem; }
	.hof__text { padding-block-start: 0; }
}

/* ---- Stacked illustration layers (swaying tree parts) ---- */
/* The tree's four parts share one square canvas and stack pixel-aligned inside a square box. */
.tree-part { margin: 0; }
.tree-part img { display: block; width: 100%; height: 100%; object-fit: contain; }
@keyframes rh-sway { 0%, 100% { transform: rotate(-1.4deg); } 50% { transform: rotate(1.6deg); } }

/* ---- Hof Gritzenmoos shared components ---- */

/* Long uppercase German headings wrap or hyphenate instead of pushing the page sideways.
   clip (not hidden) keeps position: sticky usable. */
.wp-site-blocks { overflow-x: clip; }

/* Core's root blockGap puts a Light Ivory gap between every top-level site block
   (header/main/footer) and between the full-width bands stacked inside post-content
   on the front page. Those bands already carry their own padding, so close the gap
   between them. Page templates (Impressum/Datenschutz) are not full-width bands and
   keep the normal blockGap between post-title and post-content. */
.wp-site-blocks > * + * { margin-block-start: 0; }
.wp-block-post-content > .alignfull { margin-block-start: 0; }
h1, h2, h3 { hyphens: auto; overflow-wrap: break-word; }


/* Links on light ground: Organic text, Apricot underline (Apricot text fails contrast there). */
a { text-decoration-color: var(--wp--preset--color--accent); text-underline-offset: 0.2em; }
/* On dark and Apricot bands, links take the band's text colour. */
.has-primary-background-color a:not(.wp-element-button),
.has-contrast-background-color a:not(.wp-element-button),
.has-accent-background-color a:not(.wp-element-button) { color: inherit; }

/* Small uppercase label above headings and facts. */
.kicker {
	margin-bottom: 0;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 300;
	text-transform: uppercase;
	letter-spacing: 0.12em;
}

/* Text wordmark until a real logo exists. */
.wordmark {
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 300;
	font-size: var(--wp--preset--font-size--large);
	line-height: 1.1;
	text-transform: uppercase;
	letter-spacing: 0.08em;
}

/* Labelled stand-in for an illustration or photo that does not exist yet. */
.illu-placeholder {
	display: flex;
	align-items: center;
	justify-content: center;
	aspect-ratio: 4 / 3;
	padding: 1rem;
	background: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--secondary);
	text-align: center;
}
.has-surface-background-color .illu-placeholder { background: var(--wp--preset--color--base); }
.illu-placeholder p {
	margin: 0;
	color: var(--wp--preset--color--primary);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 300;
	text-transform: uppercase;
	letter-spacing: 0.12em;
}

/* ---- Header nav and footer ---- */
/* Tabs hang from the top edge; the current one carries a bar flush with the top of the
   page in the tab's own text colour (Light Ivory on Home, Organic on the Patenschaften
   page; not Apricot, which fails as a thin mark on Organic). */
.site-header { padding-block: 0 !important; }
.site-nav { font-size: var(--wp--preset--font-size--medium); letter-spacing: 0.02em; }
.site-nav a { text-decoration: none; }
@media (min-width: 600px) {
	.site-nav .wp-block-navigation-item__content { position: relative; display: block; padding-block: 1.9rem 1rem; }
	/* The header part is shared, so the page itself (its body class) says which tab is current. */
	.home .site-nav .nav-home > a::before,
	.page-template-page-patenschaften .site-nav .nav-paten > a::before {
		content: "";
		position: absolute;
		inset-inline: 0;
		top: 0;
		height: 0.3125rem;
		background: currentColor;
	}
}

/* Page wipe (motion.js), between Home and the Patenschaften page, as on triumphpforte.at:
   the page fades under its own ground colour, leaving only the header; then that ground
   slides off to the right (its left edge sweeping across), uncovering the next page's
   ground. The tabs are drawn twice, in the old and the new colours, and the old copy is
   clipped with the ground, so each letter changes colour as the edge passes it. The
   current-tab bar slides to the new tab on both copies. On arrival the new page fades in
   from under its ground (html.is-arriving, set by an inline head script in functions.php). */
.page-wipe { position: fixed; inset: 0; z-index: 1000; pointer-events: none; }
.page-wipe__layer { position: absolute; inset: 0; }
.page-wipe__nav { position: absolute; margin: 0; }
.page-wipe .site-nav { margin: 0 !important; max-width: none !important; }
.page-wipe .site-nav, .page-wipe .site-nav a { color: inherit !important; }
.page-wipe .site-nav a::before { content: none !important; }
.page-wipe__bar { position: absolute; top: 0; height: 0.3125rem; background: currentColor; }
html.is-arriving body::after {
	content: "";
	position: fixed;
	inset: 0;
	z-index: 1000;
	background: var(--wp--preset--color--base);
	transition: opacity 0.6s ease;
}
html.is-arriving body.home::after { background: var(--wp--preset--color--primary); }
html.is-arriving.is-arrived body::after { opacity: 0; }
/* The header stays above the arrival veil (on Home it is already positioned, z 10). */
html.is-arriving .wp-site-blocks > .wp-block-template-part:has(> .site-header) { position: relative; z-index: 1001; }
html.is-arriving .home .wp-site-blocks > .wp-block-template-part:has(> .site-header) { position: absolute; }
/* Below 600px core swaps the tabs for the overlay toggle. */
@media (max-width: 599px) {
	.site-nav { padding-block: 1.25rem; }
}
.site-footer p { margin-block: 0.3rem; }
.site-footer .kicker { margin-bottom: 0.6rem; }
.site-footer__wordmark { margin-top: var(--wp--preset--spacing--60); }

/* ---- Patenschaft ---- */
/* Continues the Hof band on the same Light Ivory ground; the Philosophie band below is
   Ivory, and the tree straddles that seam. Content is centred on a narrower measure
   than the hero. The short text column leaves room below it for the tree, which grows
   up beside the longer perk list. */
/* --tree-sink: how far the tree box reaches below the seam, as a share of its width. The
   trunk base sits at 81% of the canvas, so 0.40 plants it about a fifth of the tree's
   height deep in the Philosophie band. */
:root { --tree-sink: 0.40; }
.patenschaft { display: flow-root; --tree-w: min(36rem, 75vw); }
/* Both columns size to their content and the pair is centred as one block. */
.patenschaft > .patenschaft__columns.alignwide { max-width: min(100%, 75rem); margin-block-start: 0; }
.patenschaft__columns { gap: var(--wp--preset--spacing--80); justify-content: center; }
@media (min-width: 782px) {
	.patenschaft__columns > .wp-block-column { flex: 0 1 auto !important; }
	.patenschaft__intro { width: 30rem; }
	.patenschaft__perks { width: 32.25rem; }
}
.patenschaft__text { max-width: 30rem; }
.patenschaft__text h2 { hyphens: manual; }
.patenschaft__intro { display: flex; flex-direction: column; }
/* Spaced like triumphpforte.at. The Patenschaft card straddles the upper seam (half in
   the Hof band, half in this one), with empty ground between the Hof photo and the card
   and between the card and the text. The content block (text top to tree base) fits on
   about one screen by scaling the tree with screen height, and the ground below the tree
   matches, so with the block centred on screen nothing of the Hof photo or the
   Philosophie content shows, only the card's lower half and the tree on the lower seam.
   The tree's overhang is taken off the columns (see below) and added back to the
   Philosophie padding, so the gap below is measured from the tree base. */
/* --section-gap: one extra gap added to every seam between the homepage sections below the
   Hof (Hof | Patenschaft | Philosophie | Shop | Über uns). It is in screen height, like most of
   the spacing above, so on tall screens the Patenschaft band, centred, still fills the screen
   on its own; the rem-sized content does not grow with the screen, the gap does. The hero |
   Hof seam is left alone: the photo is built to straddle it. */
:root {
	--pate-card-w: clamp(19rem, 30vw, 27rem);
	--pate-card-h: calc(var(--pate-card-w) * 0.63);
	--section-gap: 8svh;
}
.hof { padding-bottom: calc(var(--pate-card-h) / 2 + var(--wp--preset--spacing--70) + var(--section-gap)) !important; }
@media (min-width: 782px) {
	:root { --pat-tree-w: min(36rem, 75vw, 40svh); }
	.hof { padding-bottom: calc(var(--pate-card-h) / 2 + 14svh + var(--section-gap)) !important; }
	.patenschaft { --tree-w: var(--pat-tree-w); }
	.patenschaft .patenschaft__cardrow { margin-block-end: 10svh !important; }
	.patenschaft .patenschaft__columns { margin-block-end: calc(var(--pat-tree-w) * var(--tree-sink) * -1) !important; }
	.patenschaft__branch { width: var(--pat-tree-w); margin-block-start: auto !important; margin-inline-start: calc(var(--pat-tree-w) * -0.12); }
	.patenschaft + .philosophie { padding-top: calc(var(--pat-tree-w) * var(--tree-sink) + 12svh + var(--section-gap)) !important; }
	.patenschaft__text { padding-block-end: var(--wp--preset--spacing--50); }
}

/* A slightly deeper ground than the Hof band, so the seam the card sits on reads (as on
   triumphpforte.at); it sits between Light Ivory and the Ivory of Philosophie below. */
.patenschaft.has-base-background-color,
.ueber-uns.has-base-background-color {
	background-color: color-mix(in srgb, var(--wp--preset--color--base), var(--wp--preset--color--surface) 45%) !important;
}

/* Patenschaft card, like the triumphpforte.at service card: Organic, credit-card ratio,
   pulled up by half its height so it straddles the seam with the Hof band. Aligned with
   the right edge of the perks column below. The sapling mark is decoration in the shell. */
.patenschaft .patenschaft__cardrow {
	position: relative;
	z-index: 1;
	width: calc(30rem + 32.25rem + var(--wp--preset--spacing--80));
	max-width: 100%;
	margin-inline: auto !important;
	margin-block: calc(var(--pate-card-h) / -2) var(--wp--preset--spacing--70) !important;
}
.pate-card {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	width: var(--pate-card-w);
	margin-inline-start: auto;
	aspect-ratio: 85.6 / 54;
	box-sizing: border-box;
	padding: 1.7rem 2rem;
	border-radius: 1rem;
	display: flex;
	flex-direction: column;
	justify-content: flex-end;
	box-shadow: 0 1.125rem 2.5rem rgba(37, 38, 28, 0.22), 0 2px 0.375rem rgba(37, 38, 28, 0.12);
	/* Pointer tilt (motion.js sets --tilt-x/-y while hovered): a few degrees at most,
	   following the pointer quickly and settling back slowly on leave. */
	transform: perspective(56.25rem) rotateX(var(--tilt-x, 0deg)) rotateY(var(--tilt-y, 0deg));
	transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
.pate-card.is-tilting { transition-duration: 0.15s; }
@media (prefers-reduced-motion: reduce) {
	.pate-card { transform: none !important; transition: none !important; }
}
/* Slight paper/linen texture: SVG fractal noise, blended softly over the Organic ground,
   plus a faint top-left sheen. All in the shell, so the client cannot remove it. */
.pate-card::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	pointer-events: none;
	background:
		radial-gradient(120% 90% at 0% 0%, rgba(251, 245, 233, 0.12), transparent 60%),
		url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.75' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.98 0 0 0 0 0.96 0 0 0 0 0.91 0 0 0 0.9 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
	opacity: 0.16;
}
.pate-card::before {
	content: "";
	position: absolute;
	top: 1.5rem;
	right: 1.7rem;
	width: 3rem;
	height: 3rem;
	background-color: var(--wp--preset--color--accent);
	-webkit-mask: url("assets/images/icons/perk-placeholder.svg") center / contain no-repeat;
	mask: url("assets/images/icons/perk-placeholder.svg") center / contain no-repeat;
}
.pate-card > * { margin: 0 !important; }
.pate-card__title {
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	/* Scales with the card so the single word always fits on one line. */
	font-size: calc(var(--pate-card-w) * 0.079);
	line-height: 1.05;
	white-space: nowrap;
}
.pate-card__brand {
	margin-block-start: 0.5rem !important;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.16em;
	opacity: 0.9;
}
@media (max-width: 781px) {
	.pate-card { margin-inline: auto; padding: 1.25rem 1.4rem; }
	.pate-card::before { top: 1.1rem; right: 1.2rem; width: 2.3rem; height: 2.3rem; }
}

/* Perks: one icon per line, as on triumphpforte.at. All lines share one placeholder icon
   (a CSS background, so the client edits only the text); swap the SVG for real icons. */
.perks { list-style: none; margin: 0; padding: 0; }
.perks li {
	position: relative;
	min-height: 3rem;
	padding-inline-start: 4.25rem;
	margin-block-end: var(--wp--preset--spacing--50);
	display: flex;
	align-items: center;
	max-width: 28rem;
}
.perks li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 50%;
	width: 3rem;
	height: 3rem;
	translate: 0 -50%;
	background: url("assets/images/icons/perk-placeholder.svg") center / contain no-repeat;
}

/* The tree stands on the lower edge of the band (as the mortar does on triumphpforte.at):
   canopy beside the perks, trunk base reaching just into the Philosophie band. The
   section is a flow-root, so the overhang (a negative bottom margin on the last item)
   shortens the band rather than collapsing through it. The trunk layer's base sits at
   81% of the canvas (see --tree-sink for the depth). Nothing on the
   way up to the section carries a transform (the reveals sit on the text and the perks),
   so the positioned tree paints above the following band. */
.patenschaft__branch {
	position: relative;
	z-index: 2;
	width: var(--tree-w);
	aspect-ratio: 1;
	margin-block-start: var(--wp--preset--spacing--40);
	margin-inline-start: calc(var(--tree-w) * -0.12);
	pointer-events: none;
}
.patenschaft__branch .tree-part { position: absolute; inset: 0; }
/* Four parts on one shared canvas, simply laid over each other (trunk last in the DOM, so
   it paints over the three crowns and their branch tips stay tucked behind its silhouette).
   The trunk stands still while every crown swivels about the point where its branch meets
   the trunk — the tip of its own stem in the 1024² canvas, so the joints hold — each with
   its own period and phase lag, so the crowns rock like a light breeze rather than in step. */
.tree-part--left { transform-origin: 46.8% 70.3%; animation: rh-tree-left 9s ease-in-out infinite -2.4s; }
.tree-part--mid { transform-origin: 47.6% 73.9%; animation: rh-tree-mid 13s ease-in-out infinite -3.8s; }
.tree-part--right { transform-origin: 50.2% 74.3%; animation: rh-tree-right 11s ease-in-out infinite -3.1s; }
@keyframes rh-tree-left { 0%, 100% { transform: rotate(-2.2deg); } 50% { transform: rotate(2.5deg); } }
@keyframes rh-tree-mid { 0%, 100% { transform: rotate(-1.3deg); } 50% { transform: rotate(1.4deg); } }
@keyframes rh-tree-right { 0%, 100% { transform: rotate(-1.9deg); } 50% { transform: rotate(2.1deg); } }
/* Core's flow layout zeroes the last child's block-end margin; restate the overhang on
   the columns (the tree's column is the tallest, so it decides where the band ends). */
.patenschaft .patenschaft__columns { margin-block-end: calc(var(--tree-w) * var(--tree-sink) * -1) !important; }
.patenschaft .patenschaft__columns { align-items: stretch; }
@media (max-width: 781px) {
	.patenschaft { --tree-w: 90vw; }
	.patenschaft__branch { margin-inline: auto; }
	/* Stacked: text, then perks, then the tree on the seam. */
	.patenschaft__intro { display: contents; }
	.patenschaft__text { order: 0; }
	.patenschaft__perks { order: 1; }
	.patenschaft__branch { order: 2; margin-block-start: 0; }
	.patenschaft + .philosophie { padding-top: calc(90vw * var(--tree-sink) + var(--wp--preset--spacing--60) + var(--section-gap)) !important; }
}

/* ---- Philosophie: fold-out tier rows (core Details) ---- */
/* Lines only between the rows; equal padding above and below puts each one midway. */
.tier-list > .tier-row { margin-block: 0; padding-block: 1.2rem; }
.tier-list > .tier-row + .tier-row {
	border-top: 1px solid var(--wp--preset--color--secondary);
}
/* One size drives the title, the + icon and the indent of the text beneath, so they line up. */
.tier-row { --tier-size: var(--wp--preset--font-size--large); --tier-icon: calc(var(--tier-size) * 0.5); box-sizing: border-box; overflow: hidden; }
.tier-row summary {
	display: flex;
	gap: 0.75rem;
	align-items: center;
	list-style: none;
	cursor: pointer;
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 400;
	font-size: var(--tier-size);
}
.tier-row summary::-webkit-details-marker { display: none; }
/* The + is drawn as two bars so it sits exactly in the middle of the line; turned 45
   degrees it becomes an x. */
.tier-row summary::before {
	content: "";
	flex: none;
	width: var(--tier-icon);
	height: var(--tier-icon);
	background:
		linear-gradient(currentColor, currentColor) center / 100% 2px no-repeat,
		linear-gradient(currentColor, currentColor) center / 2px 100% no-repeat;
	color: var(--wp--preset--color--primary);
	transition: transform 0.5s cubic-bezier(0.65, 0, 0.35, 1);
}
.tier-row[open]:not(.is-closing) summary::before { transform: rotate(45deg); }
.tier-row > p { margin: 0.5rem 0 0 calc(var(--tier-icon) + 0.75rem); }
.philosophie__illu { margin: 0; }
/* The landscape is four views of one and the same drawing on one shared canvas: the full
   colour view underneath, and one view per tier laid over it with only that tier in colour
   and the rest in grey. While a fold-out row is open (the .tier-row--* hooks, rows above),
   its view fades in over the full colour one, so the tier the text talks about lights up and
   the landscape around it falls to grey; collapsing the row brings the full colour view back.
   The rows say the same in words, so the three overlays are decorative (empty alt). No
   JavaScript: the rows are core Details blocks and :has() simply follows their state — during
   the JS collapse the row carries .is-closing, so the fade-out runs alongside the collapse. */
.landschaft { position: relative; }
.landschaft__layer { margin: 0; }
.landschaft__layer--oben, .landschaft__layer--mitte, .landschaft__layer--unten {
	position: absolute;
	inset: 0;
	opacity: 0;
	transition: opacity 0.45s ease;
}
.philosophie:has(.tier-row--oben[open]:not(.is-closing)) .landschaft__layer--oben,
.philosophie:has(.tier-row--mitte[open]:not(.is-closing)) .landschaft__layer--mitte,
.philosophie:has(.tier-row--unten[open]:not(.is-closing)) .landschaft__layer--unten {
	opacity: 1;
}
/* Illustration out to the left (same left edge as the Hof/Patenschaft content), a short
   introduction beside it, the fold-out rows below. */
.philosophie > .philosophie__top.alignwide { gap: var(--wp--preset--spacing--70); } /* standard wide width, same edges as Shop and Über uns */
.philosophie__text { max-width: 30rem; }
.philosophie__text p { margin-block-start: 0.6em; }
@media (min-width: 782px) {
	/* The illustration reaches out to the left edge of the Hof photo: --hero-left, or, once
	   motion.js has snapped the photo to the browser edge (see .hof.is-snapped), a small gap
	   short of that edge (--illu-edge-gap), so the drawing does not touch the window. The wide
	   container is 75rem and centred, so its left edge is (100vw - 75rem) / 2, or the page padding when narrower. The column
	   grows by exactly the distance it moves left, so its right edge stays put. The three
	   other views are laid over the first (absolute, inset 0), so they move with it. */
	.philosophie__top > .philosophie__illu-col {
		--photo-left: var(--hero-left);
		--bleed: max(0px, calc(max((100vw - 75rem) / 2, var(--wp--preset--spacing--50)) - var(--photo-left)));
		flex: 0 0 calc(62% + var(--bleed)) !important;
		margin-inline-start: calc(var(--bleed) * -1);
	}
	body:has(.hof.is-snapped) .philosophie__top > .philosophie__illu-col { --photo-left: var(--illu-edge-gap, 8rem); }
	.philosophie__top > .philosophie__text { flex: 1 1 0 !important; }
}
.philosophie__illu img { display: block; width: 100%; height: auto; }
@media (prefers-reduced-motion: reduce) {
	.tier-row summary::before { transition: none; }
	/* The highlight switches instantly — but stays switched off by default, so only the
	   transition goes, not the opacity (unlike the blanket rule at the end of this file). */
	.landschaft__layer { transition: none; }
}

/* ---- Shop teaser ---- */
/* Extra room above, away from the tier rows. */
.philosophie + .shop { padding-top: calc(var(--wp--preset--spacing--80) * 2.5 + var(--section-gap)) !important; padding-bottom: calc(var(--wp--preset--spacing--80) + var(--section-gap)) !important; }
.shop__lead { max-width: 36rem; margin-inline: 0; }
.shop__note { margin-top: var(--wp--preset--spacing--60); color: var(--wp--preset--color--primary); }
.shop__illu { margin: 0; }
.shop__illu img { display: block; width: 80%; height: auto; margin-inline: auto; }
@media (min-width: 782px) {
	.shop__top > .shop__text-col { flex: 1 1 0 !important; }
	.shop__top > .shop__illu-col { flex: 0 0 40% !important; }
}

/* ---- Über uns ---- */
/* A roomy band around the content (same off-white as Patenschaft, see above). */
.ueber-uns { padding-top: calc(var(--wp--preset--spacing--80) * 1.27 + var(--section-gap)) !important; padding-bottom: calc(var(--wp--preset--spacing--80) * 1.27) !important; }
.philosophie { padding-bottom: calc(var(--wp--preset--spacing--80) + var(--section-gap)) !important; }
.ueber-uns__columns { gap: var(--wp--preset--spacing--80); }
.ueber-uns p { max-width: 34rem; }
.ueber-uns h2 { hyphens: manual; }
.ueber-uns__photo { position: relative; max-width: 27.5rem; margin-inline: auto; }
.ueber-uns__photo .illu-placeholder { aspect-ratio: 1 / 0.85; }
.ueber-uns__photo-img img { display: block; width: 100%; height: auto; }

/* ---- Patenschaften page ---- */
/* Header inverted against Home: Organic text on Light Ivory, so it runs straight into the
   light ground of the seasons band below. The mobile overlay menu keeps its Organic ground. */
/* The header always takes the ground of the section right under it: both read --paten-ground,
   which motion.js moves through the season tints while the band scrolls. */
:root { --paten-ground: #FAE6E2; }
.page-template-page-patenschaften .site-header {
	background-color: var(--paten-ground) !important;
	color: var(--wp--preset--color--primary) !important;
	transition: background-color 0.8s ease;
}
.page-template-page-patenschaften .site-header .wp-block-navigation__responsive-container:not(.is-menu-open) { color: var(--wp--preset--color--primary) !important; }
.page-template-page-patenschaften .site-header .wp-block-navigation__responsive-container-open { color: var(--wp--preset--color--primary); }
/* The page opens on the tree: the spring text doubles as the page title. */
.saison h1 { margin-block: 0.3rem 1.2rem; font-size: var(--wp--preset--font-size--xx-large); hyphens: manual; }
.saison .wp-block-buttons { margin-block-start: var(--wp--preset--spacing--50); }

/* Jahreslauf: one tree through the four seasons. The band is a tall track; the tree and the
   text column both stick to the screen while it scrolls past, and motion.js (.is-scrubbed)
   cross-fades the five views with the scroll position: each next season fades in fully over
   the current one, then the current one fades out; at autumn → winter the snow on the
   ground fades in while autumn fades out. The four texts share one spot and swap in place.
   --step is how far one scrolls from one season to the next. Static trees (no sway) for now.
   Without JS or with reduced motion the seasons simply stand one below the other. */
.jahreslauf { --step: 80svh; background: var(--paten-ground); transition: background-color 0.8s ease; }
.jahreslauf > .jahreslauf__inner.alignwide { max-width: 90rem; }
.jahreslauf__tree { position: relative; aspect-ratio: 1; width: min(100%, 100svh); margin-inline: auto; }
.jahreslauf__layer { margin: 0; }
.jahreslauf__layer img { display: block; width: 100%; height: 100%; }
.jahreslauf__drift { position: absolute; inset: 10% 15% 15%; pointer-events: none; opacity: 0; }
.jahreslauf__drift i { position: absolute; top: 0; width: 0.7rem; height: 0.45rem; border-radius: 60% 0 60% 0; opacity: 0; animation: rh-fall linear infinite; }
.jahreslauf__drift--fruehling i { background: #E7A9A2; width: 0.6rem; }
.jahreslauf__drift--sommer i { background: #6B7F3A; }
.jahreslauf__drift--herbst i { background: #C4622D; }
.jahreslauf__drift--winter i { background: #fff; width: 0.45rem; height: 0.45rem; border-radius: 50%; box-shadow: 0 0 2px rgba(120, 110, 90, 0.35); animation-name: rh-snow; }
@keyframes rh-fall {
	0% { transform: translate(0, 0) rotate(0); opacity: 0; }
	10% { opacity: 0.9; }
	100% { transform: translate(var(--dx), 70svh) rotate(540deg); opacity: 0; }
}
@keyframes rh-snow {
	0% { transform: translate(0, 0); opacity: 0; }
	10% { opacity: 0.95; }
	50% { transform: translate(calc(var(--dx) * 0.5 + 0.9rem), 40svh); }
	100% { transform: translate(var(--dx), 72svh); opacity: 0; }
}
.saison > * { margin-block: 0; }
.saison h2 { margin-block: 0.3rem 1.2rem; }
.saison p:not(.kicker) { max-width: 28rem; }

/* Tree beside the texts; the five views always share one square, the spring view on top.
   Fallback (no JS, reduced motion, editor): that one static tree beside the four texts, one below the other. */
.jahreslauf__inner { display: grid; grid-template-columns: 1.5fr 1fr; gap: var(--wp--preset--spacing--50); align-items: center; }
.jahreslauf__layer { position: absolute; inset: 0; }
.jahreslauf__layer:not(.jahreslauf__layer--fruehling) { opacity: 0; }
.jahreslauf:not(.is-scrubbed) { padding-block: var(--wp--preset--spacing--70) !important; }
.jahreslauf:not(.is-scrubbed) .saison + .saison { margin-block-start: var(--wp--preset--spacing--60); }
@media (max-width: 781px) { .jahreslauf__inner { grid-template-columns: 1fr; } }

.jahreslauf.is-scrubbed .jahreslauf__inner {
	align-items: stretch;
	min-height: calc(100svh + 3 * var(--step));
}
.jahreslauf.is-scrubbed .jahreslauf__stage,
.jahreslauf.is-scrubbed .jahreslauf__texts {
	position: sticky;
	top: 0;
	height: 100svh;
	display: grid;
	align-items: center;
	margin: 0;
}
.jahreslauf.is-scrubbed .jahreslauf__layer { will-change: opacity; }
/* Desktop: the drawing sits in the middle of its square canvas, so scaling the canvas about the
   tree's centre makes the tree 50% taller without moving the text column. */
@media (min-width: 782px) {
	/* The cap keeps the grass on screen on short windows (scaled, the canvas is 1.5 × 80svh). */
	.jahreslauf.is-scrubbed .jahreslauf__tree { width: min(100%, 80svh); transform: scale(1.5); transform-origin: 50% 52%; }
}
.jahreslauf.is-scrubbed .saison {
	grid-area: 1 / 1;
	margin: 0;
	opacity: 0;
	transform: translateY(1rem);
	pointer-events: none;
	transition: opacity 0.6s ease, transform 0.6s ease;
}
.jahreslauf.is-scrubbed .saison.is-active { opacity: 1; transform: none; pointer-events: auto; }
.jahreslauf.is-scrubbed .saison.is-past { transform: translateY(-1rem); }
@media (max-width: 781px) {
	.jahreslauf.is-scrubbed .jahreslauf__inner { grid-template-columns: 1fr; gap: 0; }
	/* Tree and text share one grid cell (the whole scroll track): the tree sticks to the top
	   55% of the screen, the text to the bottom 45%, so both are in view from the first screen. */
	.jahreslauf.is-scrubbed .jahreslauf__stage,
	.jahreslauf.is-scrubbed .jahreslauf__texts { grid-area: 1 / 1; align-self: start; }
	.jahreslauf.is-scrubbed .jahreslauf__stage { height: 55svh; z-index: 1; }
	.jahreslauf.is-scrubbed .jahreslauf__tree { width: min(100%, 55svh); }
	.jahreslauf.is-scrubbed .jahreslauf__texts { top: 55svh; height: 45svh; margin-block-start: 55svh; align-items: start; padding-inline: var(--wp--preset--spacing--40); }
	.saison h1 { font-size: var(--wp--preset--font-size--x-large); margin-block-end: 0.6rem; }
}

/* Offer: four prices as quiet cards, then perks and contribution side by side. */
.paten-angebot__head { max-width: 40rem; }
.tarife { gap: var(--wp--preset--spacing--40); margin-block-start: var(--wp--preset--spacing--60) !important; }
.tarif {
	padding: var(--wp--preset--spacing--50);
	background: var(--wp--preset--color--base);
	border-top: 0.3125rem solid var(--wp--preset--color--primary);
}
.tarif > * { margin-block: 0; }
.tarif__term { font-family: var(--wp--preset--font-family--heading); font-weight: 600; font-size: var(--wp--preset--font-size--x-large); text-transform: uppercase; line-height: 1.1; margin-block-start: 0.4rem !important; }
.tarif__price { margin-block-start: 0.2rem !important; color: var(--wp--preset--color--primary); font-weight: 400; }
.tarif__note { margin-block-start: 1rem !important; font-size: var(--wp--preset--font-size--small); }
/* Perks as one short row: icon above each line. */
.perks--row {
	display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--wp--preset--spacing--50);
	margin-block-start: var(--wp--preset--spacing--40) !important;
}
.perks--row li { display: block; min-height: 0; padding-inline-start: 0; padding-top: 4rem; margin: 0; max-width: none; text-align: center; font-size: var(--wp--preset--font-size--small); }
.perks--row li br { display: none; }
.perks--row li strong { display: block; margin-bottom: 0.25rem; font-size: var(--wp--preset--font-size--medium, 1rem); font-weight: 400; }
.paten-angebot__sub { margin-block-start: var(--wp--preset--spacing--70); text-align: center; }
.paten-angebot__block { margin-block-start: var(--wp--preset--spacing--70); max-width: 44rem; }
.paten-angebot__block h3 { margin-block-end: 0.5rem; }
.perks--row li::before { left: 50%; top: 0; translate: -50% 0; }
@media (max-width: 781px) { .perks--row { grid-template-columns: 1fr 1fr; } }
.paten-bedingungen { margin-block-start: var(--wp--preset--spacing--70) !important; border-block: 1px solid var(--wp--preset--color--secondary); }
.paten-bedingungen__list { margin: 0.75rem 0 0 calc(var(--tier-icon) + 0.75rem); padding-block-end: 1.25rem; }
.paten-bedingungen__list > p { margin: 0 0 0.6rem; }

/* Sign-up: text on the left, Contact Form 7 form on the right, both on the page ground (no card). */
.pate-werden__columns { gap: var(--wp--preset--spacing--70); align-items: flex-start; }
.pate-werden__head { position: sticky; top: 2rem; }
.pate-werden__form { min-width: 0; font-size: var(--wp--preset--font-size--medium); }
@media (max-width: 781px) {
	.pate-werden__head { position: static; }
}
.pate-werden__form .wpcf7-form-control-wrap { display: block; }
.pate-werden__form .cf-group { margin: 0 0 var(--wp--preset--spacing--50); padding: 0; border: 0; }
.pate-werden__form legend {
	padding: 0; margin-bottom: 0.75rem;
	font-size: var(--wp--preset--font-size--small); font-weight: 300; letter-spacing: 0.14em; text-transform: uppercase;
	color: var(--wp--preset--color--primary);
}
.pate-werden__form .cf-field { display: block; margin-bottom: 1.25rem; font-size: inherit; }
.pate-werden__form .cf-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1rem; }
.pate-werden__form .cf-row--plz { grid-template-columns: 8rem 1fr; }
.pate-werden__form input[type="text"],
.pate-werden__form input[type="email"],
.pate-werden__form input[type="tel"],
.pate-werden__form select,
.pate-werden__form textarea {
	display: block; box-sizing: border-box; width: 100%; margin-top: 0.3rem; padding: 0.75rem 0.85rem;
	font: inherit; color: var(--wp--preset--color--contrast);
	background: transparent;
	border: 0; border-bottom: 1px solid var(--wp--preset--color--secondary); border-radius: 0;
}
.pate-werden__form input:focus-visible,
.pate-werden__form select:focus-visible,
.pate-werden__form textarea:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary); outline-offset: 1px;
}
.pate-werden__form .cf-check { display: block; margin-bottom: 1.25rem; font-size: inherit; }
.pate-werden__form .cf-check input { margin-right: 0.5rem; accent-color: var(--wp--preset--color--primary); }
.pate-werden__form .cf-check a { color: var(--wp--preset--color--primary); text-decoration: underline; }
/* Gift fields only show once the box is ticked. */
.pate-werden__form .cf-gift__more { display: none; }
.pate-werden__form .cf-gift:has(input[name="geschenk[]"]:checked) .cf-gift__more { display: block; }
/* Hidden spam trap: out of sight, still in the DOM for bots. */
.pate-werden__form .cf-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.pate-werden__form .wpcf7-submit {
	padding: 0.95rem 2rem; font: inherit; font-weight: 300; cursor: pointer;
	color: var(--wp--preset--color--contrast); background: var(--wp--preset--color--accent);
	border: 0; border-radius: 0;
}
.pate-werden__form .wpcf7-not-valid-tip { margin-top: 0.25rem; font-size: var(--wp--preset--font-size--small); color: #8a2a12; }
.pate-werden__form .wpcf7-response-output { margin: 1.25rem 0 0; padding: 0.8rem 1rem; border: 1px solid var(--wp--preset--color--primary); }
.pate-werden__form .wpcf7-spinner { margin-left: 0.75rem; }
@media (max-width: 781px) {
	.pate-werden__form .cf-row, .pate-werden__form .cf-row--plz { grid-template-columns: 1fr; }
}

/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
	.is-reveal, .hero-headline, .card-lift, .card-lift .wp-block-image img,
	.tree-part, .tier-row > p {
		animation: none !important;
		transition: none !important;
		opacity: 1 !important;
		transform: none !important;
	}
}
