/**
 * Scheu + Weber — Zentrales Animationssystem
 *
 * Scroll-Reveals, Text-Effekte, Timeline-Choreografie. Timing/Easing/Distanz
 * kommen ausschließlich aus sw-tokens.css (--sw-anim-*). Drei zentrale
 * Abschalt-Wege: prefers-reduced-motion (System), body.sw-anim-off
 * (Entwickler-Schalter in functions.php) und der Elementor-Editor
 * (body.elementor-editor-active in der Vorschau-iframe) — dort läuft
 * sw-animations.js nicht zuverlässig (kein Scroll im üblichen Sinn), Inhalte
 * müssen beim Bearbeiten aber immer sichtbar sein.
 *
 * Effekte werden per data-sw-anim="..." in Elementor gesetzt (Erweitert →
 * Eigene Attribute) oder fest im Widget-Markup. sw-animations.js hängt beim
 * Scroll-Eintritt die Klasse .sw-is-visible an.
 */

/* ==========================================================================
   Abschalt-Schicht — IMMER zuerst, gilt für alle Effekte dieser Datei.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
	[data-sw-anim],
	[data-sw-anim] [data-sw-anim-child],
	.sw-anim-fade,
	.sw-anim-fade img,
	.sw-anim-fade .elementor-widget-image,
	.sw-anim-text-reveal,
	.sw-anim-text-reveal > *,
	[data-sw-anim="text-reveal"] > *,
	.sw-anim-headline,
	.sw-anim-headline .sw-letter,
	.sw-anim-sequence .sw-anim-seq-item,
	.sw-anim-hero,
	.sw-timeline__list::after,
	.sw-timeline__marker {
		transition: none !important;
		animation: none !important;
		opacity: 1 !important;
		transform: none !important;
		clip-path: none !important;
		filter: none !important;
		letter-spacing: normal !important;
	}
}

/*
 * Animationen neutralisiert — drei Fälle mit demselben Endzustand:
 *   body.sw-anim-off            → zentral abgeschaltet (S+W Animationen)
 *   body.elementor-editor-active → im Editor immer sichtbar
 *   .sw-export-clone            → die Off-Screen-Kopie des Bild-Exports
 *
 * Der Export friert Computed-Styles ein (sw-export.js). Ohne diesen Reset
 * würde er den Start-Zustand der Scroll-Reveals mit einbacken — die Kopie
 * hängt off-screen, der IntersectionObserver setzt dort nie `sw-is-visible`,
 * also landete z. B. der komplette Tagesessen-Speiseplan mit `opacity: 0`
 * (= unsichtbar) im fertigen PNG.
 */
:is(body.sw-anim-off, body.elementor-editor-active, .sw-export-clone) [data-sw-anim],
:is(body.sw-anim-off, body.elementor-editor-active, .sw-export-clone) [data-sw-anim] [data-sw-anim-child],
:is(body.sw-anim-off, body.elementor-editor-active, .sw-export-clone) .sw-anim-fade,
:is(body.sw-anim-off, body.elementor-editor-active, .sw-export-clone) .sw-anim-fade img,
:is(body.sw-anim-off, body.elementor-editor-active, .sw-export-clone) .sw-anim-fade .elementor-widget-image,
:is(body.sw-anim-off, body.elementor-editor-active, .sw-export-clone) .sw-anim-text-reveal,
:is(body.sw-anim-off, body.elementor-editor-active, .sw-export-clone) .sw-anim-text-reveal > *,
:is(body.sw-anim-off, body.elementor-editor-active, .sw-export-clone) [data-sw-anim="text-reveal"] > *,
:is(body.sw-anim-off, body.elementor-editor-active, .sw-export-clone) .sw-anim-headline,
:is(body.sw-anim-off, body.elementor-editor-active, .sw-export-clone) .sw-anim-headline .sw-letter,
:is(body.sw-anim-off, body.elementor-editor-active, .sw-export-clone) .sw-anim-sequence .sw-anim-seq-item,
:is(body.sw-anim-off, body.elementor-editor-active, .sw-export-clone) .sw-anim-hero,
:is(body.sw-anim-off, body.elementor-editor-active, .sw-export-clone) .sw-timeline__list::after,
:is(body.sw-anim-off, body.elementor-editor-active, .sw-export-clone) .sw-timeline__marker {
	transition: none !important;
	animation: none !important;
	opacity: 1 !important;
	transform: none !important;
	clip-path: none !important;
	filter: none !important;
	letter-spacing: normal !important;
}

/* ==========================================================================
   Scroll-Reveal — Sektionen, Widget-Wrapper, Karten
   ========================================================================== */

[data-sw-anim],
.sw-anim-fade {
	transition-duration: var(--sw-anim-duration-normal);
	transition-timing-function: var(--sw-anim-easing);
	transition-property: opacity, transform, clip-path;
}

[data-sw-anim="fade"],
[data-sw-anim="slide-up"],
[data-sw-anim="slide-left"],
[data-sw-anim="slide-right"],
[data-sw-anim="scale"],
.sw-anim-fade {
	opacity: 0;
}

[data-sw-anim="slide-up"]    { transform: translateY(var(--sw-anim-distance)); }
[data-sw-anim="slide-left"]  { transform: translateX(var(--sw-anim-distance)); }
[data-sw-anim="slide-right"] { transform: translateX(calc(var(--sw-anim-distance) * -1)); }
[data-sw-anim="scale"]       { transform: scale(0.96); }

[data-sw-anim].sw-is-visible,
.sw-anim-fade.sw-is-visible {
	opacity: 1;
	transform: none;
}

/*
 * Bild-Sektionen (.sw-band): Drift-Parallax.
 * Das Bild liegt absolut im Band, ist um den Overscan höher als das
 * Fenster und driftet beim Scrollen per translateY (--sw-band-vt, setzt
 * sw-animations.js pro Frame) durch die Overscan-Reserve — der sichtbare
 * Ausschnitt wandert, während das Band mit der Seite mitläuft. Dazu
 * "erwacht" die Farbe beim Eintritt (.sw-is-visible).
 *
 * Die explizite Fensterhöhe (--sw-anim-band-height) bleibt nötig, weil
 * das absolute Bild den Layoutfluss verlässt und das Band sonst
 * kollabiert. JS deckelt den Drift auf ±Overscan, das Fenster wird also
 * nie freigegeben. Nur auf Desktop (min-width: 1025px) aktiv — der
 * Breakpoint muss mit dem matchMedia-Gate in sw-animations.js
 * übereinstimmen; mobil s. u.
 */
.sw-band.sw-anim-fade {
	opacity: 1; /* hebt das Basis-opacity:0 von .sw-anim-fade auf */
	position: relative;
	overflow: hidden;
	height: var(--sw-anim-band-height);
}

/* Elementor-Widget-Wrapper sind position:relative und würden sonst zum
   (kollabierten) Bezugsrahmen des absoluten Bildes — Band muss der
   Containing Block sein, damit height:100% die Fensterhöhe liefert. */
.sw-band.sw-anim-fade .elementor-widget,
.sw-band.sw-anim-fade .elementor-widget-container {
	position: static;
}

.sw-band.sw-anim-fade img {
	position: absolute;
	top: calc(-1 * var(--sw-anim-band-overscan));
	left: 0;
	width: 100%;
	height: calc(100% + var(--sw-anim-band-overscan) * 2);
	object-fit: cover;
	transform: translateY(var(--sw-band-vt, 0px));
	will-change: transform;
	filter: var(--sw-anim-band-filter);
	transition: filter var(--sw-anim-band-duration) var(--sw-anim-easing); /* bewusst nur filter — transform kommt pro Frame */
}

.sw-band.sw-anim-fade.sw-is-visible img {
	filter: none;
}

/* Mobil/Tablet: Parallax aus, Bild in natürlicher Höhe ohne Zuschnitt.
   Breakpoint = Gegenstück zum Desktop-Gate (min-width: 1025px). */
@media (max-width: 1024px) {
	.sw-band.sw-anim-fade { height: auto; overflow: visible; }
	.sw-band.sw-anim-fade img { position: static; width: 100%; height: auto; transform: none; }
}

/* Einzelnes Band ohne Parallax (Opt-out über „Erweitert → CSS-Klassen"):
   verhält sich wie sw-parallax-off, aber nur für dieses Band — feste Höhe
   aus dem Menü (--sw-anim-band-height-static, 0/auto = volle Bildhöhe).
   sw-animations.js überspringt diese Bänder. */
.sw-band.sw-anim-fade.sw-band--static {
	height: var(--sw-anim-band-height-static, auto);
	overflow: visible;
}
.sw-band.sw-anim-fade.sw-band--static img {
	position: static;
	width: 100%;
	height: var(--sw-anim-band-height-static, auto);
	object-fit: cover;
	transform: none;
}

/* Ohne Animationen: Bild zurück in den Fluss, Band-Höhe wieder natürlich. */
@media (prefers-reduced-motion: reduce) {
	.sw-band.sw-anim-fade { height: auto; overflow: visible; }
	.sw-band.sw-anim-fade img { position: static; width: 100%; height: auto; transform: none; }
}

:is(body.sw-anim-off, body.elementor-editor-active, .sw-export-clone) .sw-band.sw-anim-fade { height: auto; overflow: visible; }
:is(body.sw-anim-off, body.elementor-editor-active, .sw-export-clone) .sw-band.sw-anim-fade img { position: static; width: 100%; height: auto; transform: none; }

/*
 * Gestaffelte Kinder (Widget-Repeater): steuert nur den Index-Versatz.
 * Start-Zustand/Transform kommt aus der [data-sw-anim="..."]-Variante auf
 * demselben Element (Timeline-Items tragen z. B. beides) — so überschreibt
 * die Stagger-Regel nicht die Slide-Richtung. Nur bei [data-sw-anim-child]
 * OHNE eigenes data-sw-anim (z. B. dynamisch erzeugte .sw-word-Spans, die
 * ihre Start-/Zielwerte selbst mitbringen) greift kein Zusatz-Fallback nötig.
 */
[data-sw-anim-child] {
	--index: 0;
	transition-delay: min(calc(var(--index) * var(--sw-anim-stagger-step)), 0.4s);
}

/* ==========================================================================
   Text-Effekte
   ========================================================================== */

/* Clip-Path-Wisch-Reveal für Überschriften.
   .sw-anim-text-reveal ist die Klassen-Variante für Elementor-Elemente
   (freies Elementor hat kein "Eigene Attribute"-Feld) — analog .sw-anim-fade.
   Die Maske liegt auf den KIND-Elementen, nicht auf dem beobachteten Element:
   Chrome verrechnet die eigene clip-path in die IntersectionObserver-Geometrie —
   ein auf Breite 0 geclipptes Element würde nie "intersecting" und bliebe
   dauerhaft unsichtbar. Der Effekt setzt daher mindestens ein Element-Kind
   voraus (bei Elementor-Elementen immer gegeben). */
[data-sw-anim="text-reveal"],
.sw-anim-text-reveal {
	opacity: 1; /* kein Fade, nur Maske */
}

[data-sw-anim="text-reveal"] > *,
.sw-anim-text-reveal > * {
	clip-path: inset(0 100% 0 0);
	transition-property: clip-path;
	transition-duration: var(--sw-anim-duration-slow);
	transition-timing-function: var(--sw-anim-easing);
}

[data-sw-anim="text-reveal"].sw-is-visible > *,
.sw-anim-text-reveal.sw-is-visible > * {
	clip-path: inset(0 0 0 0);
}

/* Wortweise gestaffelte Einblendung (Wörter werden von sw-animations.js in Spans gewrappt) */
[data-sw-anim="text-words"] {
	opacity: 1; /* Wrapper selbst bleibt sichtbar, nur Wörter animieren */
}

.sw-word {
	display: inline-block;
	--index: 0;
	opacity: 0;
	transform: translateY(calc(var(--sw-anim-distance) * 0.6));
	transition-property: opacity, transform;
	transition-duration: var(--sw-anim-duration-fast);
	transition-timing-function: var(--sw-anim-easing);
	transition-delay: min(calc(var(--index) * var(--sw-anim-stagger-step)), 0.4s);
}

.sw-word.sw-is-visible {
	opacity: 1;
	transform: none;
}

/* Wachsende Unterstreichung — gemeinsamer Baustein für Scroll- und Hover-Trigger */
.sw-anim-underline {
	position: relative;
	text-decoration: none;
}

.sw-anim-underline::after {
	content: '';
	position: absolute;
	left: 0;
	bottom: -0.15em;
	width: 100%;
	height: 1px;
	background-color: currentColor;
	transform: scaleX(0);
	transform-origin: left;
	transition: transform var(--sw-anim-duration-fast) var(--sw-anim-easing);
}

[data-sw-anim="underline"].sw-is-visible.sw-anim-underline::after,
.sw-anim-underline:hover::after,
.sw-anim-underline:focus-visible::after {
	transform: scaleX(1);
}

/* ==========================================================================
   Headline-Eingang — neutrale Rolle, zentral wechselbarer Effekt
   .sw-anim-headline markiert nur "animierte Hauptüberschrift". WELCHER Effekt
   läuft, wird an EINER Stelle bestimmt: der Konstante HEADLINE_ANIM in
   sw-animations.js. Das JS setzt daraufhin data-sw-headline="<modus>" auf das
   Element (und zerlegt den Text bei "letters" in .sw-letter-Spans); die
   passenden Regeln unten greifen über das Attribut. Zum Umstellen also nur
   HEADLINE_ANIM ändern — die Seiten behalten unverändert .sw-anim-headline.
   Die versteckten Startzustände hängen bewusst am data-sw-headline-Attribut
   (nicht an der Klasse): Solange das JS nichts gesetzt hat — abgeschaltet,
   reduced-motion, Editor —, bleibt die Überschrift regulär sichtbar (kein FOUC).
   ========================================================================== */

/* Modus "letters" — Buchstaben-Stagger (Default).
   Der Wort-Wrapper hält jedes Wort zusammen, damit nur die Zeichen animieren
   und keine Zeile mitten im Wort umbricht. */
.sw-anim-headline[data-sw-headline="letters"] .sw-hl-word {
	display: inline-block;
	white-space: nowrap;
}

.sw-anim-headline[data-sw-headline="letters"] .sw-letter {
	display: inline-block;
	opacity: 0;
	transform: translateY(0.5em);
	transition-property: opacity, transform;
	transition-duration: var(--sw-anim-duration-fast);
	transition-timing-function: var(--sw-anim-easing);
	transition-delay: min(calc(var(--index) * var(--sw-anim-stagger-step)), 0.5s);
}

.sw-anim-headline[data-sw-headline="letters"].sw-is-visible .sw-letter {
	opacity: 1;
	transform: none;
}

/* Alternativ-Modi (reines CSS, kein Text-Split) — aktiv per HEADLINE_ANIM. */
.sw-anim-headline[data-sw-headline="blur"] {
	opacity: 0;
	filter: blur(12px);
	transition: opacity var(--sw-anim-duration-slow) var(--sw-anim-easing),
	            filter var(--sw-anim-duration-slow) var(--sw-anim-easing);
}
.sw-anim-headline[data-sw-headline="blur"].sw-is-visible {
	opacity: 1;
	filter: none;
}

.sw-anim-headline[data-sw-headline="tracking"] {
	opacity: 0;
	letter-spacing: 0.3em;
	transition: opacity var(--sw-anim-duration-normal) var(--sw-anim-easing),
	            letter-spacing var(--sw-anim-duration-slow) var(--sw-anim-easing);
}
.sw-anim-headline[data-sw-headline="tracking"].sw-is-visible {
	opacity: 1;
	letter-spacing: normal;
}

.sw-anim-headline[data-sw-headline="fade"] {
	opacity: 0;
	transform: translateY(var(--sw-anim-distance));
	transition: opacity var(--sw-anim-duration-normal) var(--sw-anim-easing),
	            transform var(--sw-anim-duration-normal) var(--sw-anim-easing);
}
.sw-anim-headline[data-sw-headline="fade"].sw-is-visible {
	opacity: 1;
	transform: none;
}

/* ==========================================================================
   Sequenz-Reveal — eine Sektion blendet ihre Inhalte nacheinander ein
   .sw-anim-sequence auf einen Container/eine Sektion legen: deren direkte
   Inhalts-Elemente (Titel → Text → Button …) blenden gestaffelt von unten
   ein, sobald der Container in den Viewport kommt. Reihenfolge = DOM-Reihen-
   folge; danach startet die nächste Sektion ihre eigene Sequenz. Nur die
   EINE Container-Klasse nötig — sw-animations.js markiert die Kinder als
   .sw-anim-seq-item und setzt --sw-seq-index (berücksichtigt Elementors
   boxed .e-con-inner). Der Versatz kommt aus --sw-anim-sequence-step, die
   sichtbare Verzögerung ist gedeckelt, damit auch inhaltsreiche Sektionen
   nicht zäh wirken.
   ========================================================================== */
.sw-anim-sequence .sw-anim-seq-item {
	opacity: 0;
	transform: translateY(var(--sw-anim-distance));
	transition-property: opacity, transform;
	transition-duration: var(--sw-anim-duration-normal);
	transition-timing-function: var(--sw-anim-easing);
	transition-delay: min(calc(var(--sw-seq-index, 0) * var(--sw-anim-sequence-step)), 0.7s);
}

.sw-anim-sequence.sw-is-visible .sw-anim-seq-item {
	opacity: 1;
	transform: none;
}

/* ==========================================================================
   Hero (einmalige Einblendung beim Laden, kein Scroll-Trigger)
   ========================================================================== */

@keyframes sw-hero-fade-up {
	from {
		opacity: 0;
		transform: translateY(var(--sw-anim-distance));
	}
	to {
		opacity: 1;
		transform: none;
	}
}

.sw-anim-hero {
	animation: sw-hero-fade-up var(--sw-anim-duration-slow) var(--sw-anim-easing) both;
}

/* ==========================================================================
   Timeline — Sonderfall: Linie füllt sich mit Scroll-Fortschritt
   ========================================================================== */

.sw-timeline .sw-timeline__list {
	--sw-timeline-progress: 0;
}

/* Basis-Linie (sw-timeline.css ::before) wird zur gedeckten "Spur"; ::after zeigt den Fortschritt. */
.sw-timeline .sw-timeline__list::before {
	opacity: 0.35;
}

/* Fortschritts-Overlay: liegt über der bestehenden Basis-Linie (::before), gleiche Geometrie.
   Doppelte Klassen-Spezifität nötig, damit die Regel unabhängig von der Enqueue-Reihenfolge
   gegenüber sw-timeline.css gewinnt (Konvention s. scheuUndWeber.md, Abschnitt 4). */
.sw-timeline .sw-timeline__list::after {
	content: '';
	position: absolute;
	top: 0.4em;
	bottom: -1.5rem;
	left: 50%;
	width: 3px;
	transform: translateX(-50%) scaleY(var(--sw-timeline-progress));
	transform-origin: top;
	background-color: var(--sw-timeline-marker, var(--sw-color-wine));
	z-index: 0;
}

@media (max-width: 767px) {
	.sw-timeline .sw-timeline__list::after {
		left: 13px;
		transform: scaleY(var(--sw-timeline-progress));
	}
}

.sw-timeline .sw-timeline__marker {
	background-color: var(--sw-color-white);
	opacity: 0.55;
	transition: opacity var(--sw-anim-duration-fast) var(--sw-anim-easing),
	            background-color var(--sw-anim-duration-fast) var(--sw-anim-easing);
}

.sw-timeline .sw-timeline__marker--active {
	opacity: 1;
	background-color: var(--sw-timeline-marker, var(--sw-color-wine));
}

/* ==========================================================================
   Mikroanimationen — wiederkehrende Interaktionen (rein :hover/:focus, kein Scroll-Trigger)
   ========================================================================== */

/* Basis für alle Button-Effekte: Übergänge + eigener Stacking-Context.
   WELCHER Hover-Effekt läuft, bestimmt die Body-Klasse sw-btn-<modus> aus dem
   Einstellungsmenü (shimmer | lift | expand | glow | none). Ohne Modus-Klasse
   (Hover global aus) bleibt nur die Farb-Invertierung des Kits. */
.sw-btn .elementor-button,
a.sw-btn,
button.sw-btn {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	transition: background-color var(--sw-anim-duration-fast) var(--sw-anim-easing),
	            color var(--sw-anim-duration-fast) var(--sw-anim-easing),
	            transform var(--sw-anim-duration-fast) var(--sw-anim-easing),
	            box-shadow var(--sw-anim-duration-fast) var(--sw-anim-easing),
	            border-color var(--sw-anim-duration-fast) var(--sw-anim-easing),
	            letter-spacing var(--sw-anim-duration-fast) var(--sw-anim-easing);
}

/* Gemeinsamer Lift + taktiler Press — alle animierten Modi (nicht "none"). */
body:is(.sw-btn-shimmer, .sw-btn-lift, .sw-btn-expand, .sw-btn-glow) :is(.sw-btn .elementor-button, a.sw-btn, button.sw-btn):hover:not(:disabled) {
	transform: translateY(-1px);
	box-shadow: 0 6px 14px rgba(0, 0, 0, 0.26);
}
body:is(.sw-btn-shimmer, .sw-btn-lift, .sw-btn-expand, .sw-btn-glow) :is(.sw-btn .elementor-button, a.sw-btn, button.sw-btn):active:not(:disabled) {
	transform: translateY(0);
	box-shadow: var(--sw-btn-shadow);
}

a.sw-pill,
.sw-pill[role="link"] {
	transition: opacity var(--sw-anim-duration-fast) var(--sw-anim-easing);
}

a.sw-pill:hover,
.sw-pill[role="link"]:hover {
	opacity: 0.85;
}

.sw-form .elementor-field-textual {
	transition: outline-color var(--sw-anim-duration-fast) var(--sw-anim-easing),
	            outline-offset 0.15s var(--sw-anim-easing);
}

.sw-form .elementor-field-type-acceptance input[type="checkbox"] {
	transition: transform 0.15s var(--sw-anim-easing);
}

.sw-form .elementor-field-type-acceptance input[type="checkbox"]:checked {
	transform: scale(1.08);
}

/* --- Modus "shimmer": Gold-Glanz wischt HINTER dem Text durch (z-index:-1 im
   eigenen Stacking-Context; overflow:hidden klippt auf die Pill-Form). --- */
body.sw-btn-shimmer :is(.sw-btn .elementor-button, a.sw-btn, button.sw-btn)::after {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	left: 0;
	width: 55%;
	z-index: -1;
	pointer-events: none;
	background: linear-gradient(100deg, transparent 0%, rgba(211, 184, 128, 0.5) 50%, transparent 100%);
	transform: translateX(-180%) skewX(-12deg);
	opacity: 0;
	transition: transform var(--sw-anim-duration-normal) var(--sw-anim-easing),
	            opacity var(--sw-anim-duration-normal) var(--sw-anim-easing);
}
body.sw-btn-shimmer :is(.sw-btn .elementor-button, a.sw-btn, button.sw-btn):hover:not(:disabled)::after {
	transform: translateX(280%) skewX(-12deg);
	opacity: 1;
}

/* --- Modus "expand": Buchstaben-Laufweite weitet sich (Text „atmet"). --- */
body.sw-btn-expand :is(.sw-btn .elementor-button, a.sw-btn, button.sw-btn):hover:not(:disabled) {
	letter-spacing: 3.5px;
}

/* --- Modus "glow": Rahmen wird Gold, dezenter Gold-Schein rundherum. --- */
body.sw-btn-glow :is(.sw-btn .elementor-button, a.sw-btn, button.sw-btn):hover:not(:disabled) {
	border-color: var(--sw-color-gold);
	box-shadow: 0 0 0 3px rgba(211, 184, 128, 0.35), 0 6px 14px rgba(0, 0, 0, 0.22);
}

/* Link mit gleitendem Pfeil — Opt-in .sw-anim-arrow (z. B. "mehr erfahren").
   Der Pfeil rückt beim Hover/Fokus nach rechts. */
.sw-anim-arrow {
	text-decoration: none;
	white-space: nowrap;
}

.sw-anim-arrow::after {
	content: "\2192";
	display: inline-block;
	margin-left: 0.35em;
	transition: transform var(--sw-anim-duration-fast) var(--sw-anim-easing);
}

.sw-anim-arrow:hover::after,
.sw-anim-arrow:focus-visible::after {
	transform: translateX(0.3em);
}

@media (prefers-reduced-motion: reduce) {
	.sw-btn .elementor-button,
	a.sw-btn,
	button.sw-btn,
	a.sw-pill,
	.sw-pill[role="link"],
	.sw-form .elementor-field-textual,
	.sw-form .elementor-field-type-acceptance input[type="checkbox"],
	.sw-anim-underline::after,
	.sw-anim-arrow::after {
		transition-duration: 0.01ms !important;
	}
	.sw-btn .elementor-button::after,
	a.sw-btn::after,
	button.sw-btn::after {
		display: none !important;
	}
}

/* ==========================================================================
   Header — verkleinert sich beim Scrollen
   Der fixierte ElementsKit-Header (.ekit-template-content-header → ein
   position:fixed-Elementor-Container .e-con.e-parent) bekommt von
   sw-animations.js (initHeaderShrink) die Klasse .sw-header-shrunk, sobald
   gescrollt wird. Elementor steuert Padding über --padding-* und die
   Logo-Breite über .elementor-element-…-img{width} — beides hier mit höherer
   Klassen-Spezifität heruntergefahren, plus dezenter Schatten. Läuft nicht bei
   sw-anim-off/reduced-motion/Editor (JS kehrt vorher zurück → Header bleibt groß).
   ========================================================================== */

/* Schatten liegt auf dem äußeren fixierten Container. */
.ekit-template-content-header .e-con.e-parent {
	transition: box-shadow var(--sw-anim-duration-normal) var(--sw-anim-easing);
}

/* Das sichtbare Padding eines boxed-Containers sitzt auf .e-con-inner (liest
   Elementors --padding-*-Variablen). Die Transition muss deshalb HIER liegen,
   sonst springt das Padding, während das Logo gleitet. */
.ekit-template-content-header .e-con.e-parent > .e-con-inner {
	transition: padding var(--sw-anim-duration-normal) var(--sw-anim-easing);
}

/* Logo weich mitfahren lassen. */
.ekit-template-content-header .elementor-widget-image img {
	transition: width var(--sw-anim-duration-normal) var(--sw-anim-easing);
}

/* Verkleinerter Zustand: Padding runter (über Elementors --padding-*-Variablen,
   die --e-con-inner erbt), Logo kleiner, Header hebt sich mit leichtem Schatten ab. */
.ekit-template-content-header .e-con.e-parent.sw-header-shrunk {
	/* Padding nur moderat reduzieren (16px → 12px), damit das Logo im
	   verkleinerten Header nicht an den Rändern klebt. */
	--padding-top: 12px;
	--padding-bottom: 12px;
	box-shadow: 0 4px 18px rgba(0, 0, 0, 0.12);
}

.ekit-template-content-header .e-con.e-parent.sw-header-shrunk .elementor-widget-image img {
	/* Logo dafür spürbar kleiner (88px → 64px) — die Verkleinerung kommt
	   jetzt hauptsächlich vom Logo, nicht vom Abstand. */
	width: 64px;
}

/* Aktiver Menüeintrag: Unterstrich (::after, sitzt in sw-components.css,
   normal scaleX(1)) blendet beim Verkleinern per Opacity aus — in-place,
   nicht seitlich einziehend. Basis-::after transitioniert nur transform;
   Opacity hier zusätzlich mitschalten, damit das Aus-/Einblenden gleitet.
   Diese Datei lädt nach sw-components.css → gewinnt bei gleicher Spezifität. */
.ekit-template-content-header .elementor-heading-title a[aria-current="page"]::after,
.ekit-template-content-header .current-menu-item .elementor-heading-title a::after,
.ekit-template-content-header .current_page_item .elementor-heading-title a::after {
	transition: transform var(--sw-anim-duration-fast) var(--sw-anim-easing),
	            opacity var(--sw-anim-duration-normal) var(--sw-anim-easing);
}

.ekit-template-content-header .e-con.e-parent.sw-header-shrunk .elementor-heading-title a[aria-current="page"]::after,
.ekit-template-content-header .e-con.e-parent.sw-header-shrunk .current-menu-item .elementor-heading-title a::after,
.ekit-template-content-header .e-con.e-parent.sw-header-shrunk .current_page_item .elementor-heading-title a::after {
	opacity: 0;
}

/* ==========================================================================
   Scroll-Snap — nur Startseite (page-id-26), nur Desktop
   Man scrollt von Kombi zu Kombi: Jede Text-Sektion rastet mit der
   Unterkante am Viewport-Ende ein — Bild+Text stehen dann komplett im
   Bild. Dieser Rastpunkt ist zugleich der Release-Punkt der Band-Mechanik,
   das Band-Bild ist im eingerasteten Zustand also immer gerade angedockt.
   Snap-Kette: Seitenanfang (Header, align start) → jede .sw-section
   (align end) → Footer (align end, sonst wäre er bei mandatory
   unerreichbar). Nur Desktop: Auf schmalen Viewports sind die Kombis
   höher als der Viewport — mandatory würde Inhalt unscrollbar machen.
   ========================================================================== */

@media (min-width: 1025px) {
	html:has(body.page-id-26) {
		scroll-snap-type: y mandatory;
		/* Bremst die native Snap-Animation etwas ab (einziger CSS-Hebel dafür —
		   die Dauer selbst bleibt browserintern, ist nicht frei einstellbar). */
		scroll-behavior: smooth;
	}

	/* Master-Schalter, Elementor-Editor, Reduced-Motion: Snapping + Smooth-Scroll aus */
	html:has(body.page-id-26.sw-anim-off),
	html:has(body.page-id-26.elementor-editor-active) {
		scroll-snap-type: none;
		scroll-behavior: auto;
	}
}

@media (min-width: 1025px) and (prefers-reduced-motion: reduce) {
	html:has(body.page-id-26) {
		scroll-snap-type: none;
		scroll-behavior: auto;
	}
}

@media (min-width: 1025px) {

	body.page-id-26 .ekit-template-content-header {
		scroll-snap-align: start;
	}

	body.page-id-26 .sw-section {
		scroll-snap-align: end;
		scroll-snap-stop: always;
	}

	body.page-id-26 .ekit-template-content-footer {
		scroll-snap-align: end;
	}
}

/*
 * Zu flacher Viewport: Snap aus, sonst "gehen die Bilder unter" — die
 * Bild+Text-Kombi passt nicht mehr in die Viewporthöhe, und mandatory-Snap
 * würde den überstehenden Bildanteil unerreichbar machen. Abschalten, wenn:
 *   (a) Viewporthöhe < 1000px, ODER
 *   (b) das sichtbare Bildband unter 600px fällt. Die Bandhöhe ist
 *       --sw-anim-band-height = clamp(300px, 55vh, 680px); im relevanten
 *       Bereich also 55vh. 55vh < 600px  ⟺  Viewporthöhe < 1090,9px.
 * Die 1091px-Grenze (hier: max-height 1090px) deckt beide Fälle ab, da
 * 1000px darin enthalten ist. Kommt nach dem Setz-Block, gewinnt also bei
 * gleicher Spezifität über scroll-snap-type: y mandatory.
 * (Bei Änderung von --sw-anim-band-height diese Grenze mitziehen.)
 */
@media (min-width: 1025px) and (max-height: 1090px) {
	html:has(body.page-id-26) {
		scroll-snap-type: none;
	}
}

/* ==========================================================================
   Effekt-Schalter aus dem Einstellungsmenü (S+W Animationen).
   sw-animation-settings.php setzt diese Body-Klassen, wenn der jeweilige
   Effekt im Admin deaktiviert wurde. Numerische Werte laufen dagegen über
   die --sw-anim-*-Token-Overrides (Inline-:root) und brauchen hier nichts.
   ========================================================================== */

/* Scroll-Snap aus (Startseite). */
@media (min-width: 1025px) {
	html:has(body.page-id-26.sw-snap-off) {
		scroll-snap-type: none;
		scroll-behavior: auto;
	}
}

/* Parallax aus: Bild-Bänder zurück in den normalen Fluss. Höhe kommt aus dem
   Einstellungsmenü (--sw-anim-band-height-static): feste Höhe = Bild wird
   zugeschnitten (object-fit: cover); "auto" = volle Bildhöhe. */
body.sw-parallax-off .sw-band.sw-anim-fade {
	height: var(--sw-anim-band-height-static, auto);
	overflow: visible;
}
body.sw-parallax-off .sw-band.sw-anim-fade img {
	position: static;
	width: 100%;
	height: var(--sw-anim-band-height-static, auto);
	object-fit: cover;
	transform: none;
}

/* Hero-Einblendung aus. */
body.sw-hero-off .sw-anim-hero {
	animation: none;
	opacity: 1;
	transform: none;
}

/* Hover-Mikroeffekte aus. */
body.sw-hover-off .sw-btn .elementor-button:hover,
body.sw-hover-off a.sw-btn:hover,
body.sw-hover-off button.sw-btn:hover:not(:disabled) {
	transform: none;
	box-shadow: var(--sw-btn-shadow);
}
body.sw-hover-off a.sw-pill:hover,
body.sw-hover-off .sw-pill[role="link"]:hover {
	opacity: 1;
}
body.sw-hover-off .sw-form .elementor-field-type-acceptance input[type="checkbox"]:checked {
	transform: none;
}
body.sw-hover-off .sw-btn .elementor-button::after,
body.sw-hover-off a.sw-btn::after,
body.sw-hover-off button.sw-btn::after {
	display: none;
}
body.sw-hover-off .sw-anim-arrow:hover::after,
body.sw-hover-off .sw-anim-arrow:focus-visible::after {
	transform: none;
}

/* ==========================================================================
   Seitenübergänge — View Transitions

   Beim Wechsel zwischen zwei Seiten blendet der Inhalt weich um, statt hart
   umzuspringen. Das ist keine zusätzliche Animation, sondern das Gegenteil:
   es nimmt dem Seitenwechsel den Ruck, den er sonst hat.

   Der Effekt kostet nichts. `@view-transition` ist eine reine CSS-Regel;
   Browser, die sie nicht kennen, überlesen sie und wechseln wie bisher.
   WordPress lädt Seiten über Speculation Rules ohnehin vorab, der Wechsel ist
   also schon schnell — er wird hier nur ruhig.

   Header und Logo bekommen einen eigenen Namen: dadurch bleiben sie beim
   Wechsel stehen, statt mitzublenden. Genau das lässt eine Website wie eine
   Anwendung wirken und nicht wie eine Folge von Dokumenten.

   Die einschaltende Regel `@view-transition { navigation: auto }` steht
   bewusst NICHT hier, sondern wird von sw-animation-settings.php inline
   ausgegeben — nur dann, wenn der Schalter im Menü gesetzt ist. Eine
   Body-Klasse könnte sie nicht abschalten: `@view-transition` ist eine
   Regel auf Dokumentebene und kennt keinen Selektor, an dem sich eine
   Klasse festmachen ließe.

   Was hier steht, sind die Namen und das Timing. Ohne die einschaltende
   Regel sind sie wirkungslos.
   ========================================================================== */

.ekit-template-content-header .e-con.e-parent {
	view-transition-name: sw-header;
}

.ekit-template-content-header .elementor-widget-image img {
	view-transition-name: sw-logo;
}

::view-transition-old(root),
::view-transition-new(root) {
	animation-duration: var(--sw-anim-duration-fast);
	animation-timing-function: var(--sw-anim-easing);
}

/* Bei abgeschalteten Animationen auch die Namen zurücknehmen — ein benanntes
   Element versucht der Browser sonst weiter eigenständig zu überblenden. */
body.sw-anim-off .ekit-template-content-header .e-con.e-parent,
body.sw-anim-off .ekit-template-content-header .elementor-widget-image img {
	view-transition-name: none;
}

@media (prefers-reduced-motion: reduce) {
	.ekit-template-content-header .e-con.e-parent,
	.ekit-template-content-header .elementor-widget-image img {
		view-transition-name: none;
	}
}
