/*
Theme Name: Sehpunkt-Theme
Theme URI: https://sehpunkt.de/
Author: Sehpunkt
Author URI: https://sehpunkt.de/
Description: Individuelles Theme mit eigener Einstellungen-Seite (Grid, Typografie, Header-/Footer-Baukasten, Button-Stile) und WPBakery-Kompatibilität.
Version: 3.46.0
Requires at least: 6.0
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: sehpunkt-theme
Tags: custom-menu, featured-images, translation-ready
*/

/* =========================================================
   Reset / Basis
   ========================================================= */
*, *::before, *::after { box-sizing: border-box; }

/* clip statt hidden: hidden macht das Element zum Scrollcontainer, wodurch
   position:sticky im Inneren aufhört zu wirken — und es verhindert das
   seitliche Ziehen nicht, solange das html-Element weiterhin scrollen kann.
   clip unterbindet beides, ohne einen Scrollcontainer zu erzeugen. */
html { overflow-x: clip; }

body {
	margin: 0;
	-webkit-font-smoothing: antialiased;
	overflow-x: clip;
}

img, svg, video { max-width: 100%; height: auto; }

:where(a):focus-visible,
:where(button):focus-visible,
:where(input, select, textarea):focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 2px;
}

.screen-reader-text {
	position: absolute !important;
	width: 1px; height: 1px;
	clip-path: inset(50%);
	overflow: hidden;
	white-space: nowrap;
}

.skip-link {
	position: absolute;
	left: -9999px;
	z-index: 100000;
	padding: 12px 20px;
	background: #fff;
	color: #000;
}
.skip-link:focus { left: 10px; top: 10px; }

/* =========================================================
   Ladeanimation

   Ablauf, rein über CSS-Animationen gesteuert:
   1. Der Punkt blinkt (Anzahl und Gesamtdauer einstellbar).
   2. Danach wächst der Kreisbogen gegen den Uhrzeigersinn aus der Lücke
      neben dem Punkt heraus und schließt sich wieder dort.
      stroke-linecap: round hält die wandernde Spitze abgerundet.
   3. Am Ende skaliert die Grafik hoch und verblasst, der Inhalt fadet ein.

   Ohne JavaScript läuft der Ablauf genauso durch; das Skript überspringt
   die Animation lediglich bei wiederholten Aufrufen.
   ========================================================= */
.sp-preloader {
	position: fixed;
	inset: 0;
	z-index: 9999;
	display: flex;
	align-items: center;
	justify-content: center;
	background-color: var(--sp-pl-bg, #16161d);
	color: var(--sp-pl-color, #e9e9e0);
	overscroll-behavior: contain;
	animation-name: sp-pl-out;
	animation-duration: var(--sp-pl-exit, 600ms);
	animation-timing-function: ease;
	animation-delay: var(--sp-pl-hold, 3000ms);
	animation-fill-mode: forwards;
}

/* Sicherheitsnetz: JavaScript blendet das Overlay hart aus, falls die
   Animation aus irgendeinem Grund nicht durchläuft. */
.sp-preloader.is-finished { display: none; }

.sp-preloader__figure {
	width: var(--sp-pl-size, 80px);
	height: var(--sp-pl-size, 80px);
	animation-name: sp-pl-zoom;
	animation-duration: var(--sp-pl-exit, 600ms);
	animation-timing-function: cubic-bezier(.4, 0, .2, 1);
	animation-delay: var(--sp-pl-hold, 3000ms);
	animation-fill-mode: forwards;
}

.sp-preloader__svg { display: block; width: 100%; height: 100%; }

/* Der Punkt blinkt und bleibt danach als runde Kappe stehen. */
.sp-preloader__dot {
	animation-name: sp-pl-blink;
	animation-duration: var(--sp-pl-blink-step, 667ms);
	animation-iteration-count: var(--sp-pl-blinks, 3);
	animation-timing-function: ease-in-out;
	animation-fill-mode: both;
}

/* pathLength="100" normiert die Zeichenlänge auf 100. --sp-pl-offset ist der
   fertige, vorzeichenbehaftete Startwert: +100 zeichnet in Pfadrichtung, -100
   kehrt sie um. Der Pfad des eingebauten Logos verläuft bereits gegen den
   Uhrzeigersinn.

   Wichtig: hier darf kein calc() stehen. Ein calc() ohne Einheit ist für
   stroke-dashoffset ungültig, die Deklaration würde verworfen und der Ring
   von Beginn an vollständig sichtbar sein. */
.sp-preloader__ring {
	stroke-dasharray: var(--sp-pl-dash, 101);
	stroke-dashoffset: var(--sp-pl-offset, 101);
	stroke-linecap: round;
	/* Zweite Absicherung: Solange die Animation noch nicht läuft, ist die
	   Linie durchsichtig. Selbst wenn ein Browser einen Strich der Länge
	   null zeichnen wollte, wäre er unsichtbar. */
	stroke-opacity: 0;
	animation-name: sp-pl-draw;
	animation-duration: var(--sp-pl-draw, 1000ms);
	animation-timing-function: ease-in-out;
	animation-delay: var(--sp-pl-blink, 2000ms);
	animation-fill-mode: forwards;
}

/* Der Inhalt blendet ein, während das Overlay noch undurchsichtig ist.

   Vorher liefen beide gleichzeitig: Das Overlay wurde durchsichtig, der Inhalt
   gleichzeitig sichtbar. In der Mitte war jedes von beiden zur Hälfte
   durchsichtig — übrig blieb ein Viertel der Helligkeit, und genau das sah man
   als dunklen Moment.

   Jetzt endet das Einblenden des Inhalts genau dann, wenn das Overlay zu
   verschwinden beginnt. Er liegt also bereits vollständig da, während der
   Kreis größer wird und sich auflöst — das Logo geht in die Seite über, statt
   von ihr abgelöst zu werden. */
.sp-has-preloader .sp-site {
	animation: sp-pl-in var(--sp-pl-fade, 600ms) ease var(--sp-pl-site-delay, 2400ms) both;
}

body.sp-preloading { overflow: hidden; }

@keyframes sp-pl-blink {
	0%, 100% { opacity: 1; }
	50% { opacity: 0; }
}
@keyframes sp-pl-draw {
	from { stroke-opacity: 1; }
	to { stroke-opacity: 1; stroke-dashoffset: 0; }
}
@keyframes sp-pl-zoom {
	to { transform: scale(var(--sp-pl-scale, 1.6)); opacity: 0; }
}
@keyframes sp-pl-out {
	0%   { opacity: 1; visibility: visible; }
	99%  { visibility: visible; }
	100% { opacity: 0; visibility: hidden; }
}
@keyframes sp-pl-in {
	from { opacity: 0; }
	to { opacity: 1; }
}

/* Angehalten, bis die Seite fertig geladen ist. Blinken und Kreis laufen
   weiter — nur das Ausblenden wartet. Die Verzögerung wird dabei auf null
   gesetzt, weil das Skript den Zeitpunkt selbst bestimmt. */
.sp-preloader-hold .sp-preloader,
.sp-preloader-hold .sp-preloader__figure {
	animation-play-state: paused;
	animation-delay: 0s;
}

/* Der Inhalt wird dabei ausdrücklich nicht angehalten: Er blendet hinter dem
   undurchsichtigen Overlay ein und ist fertig, wann immer dieses weicht.
   Angehalten müsste er beim Weitergehen erst noch einblenden — und damit wäre
   die Überblendung samt dunklem Moment zurück. */
.sp-preloader-hold .sp-has-preloader .sp-site { animation-delay: 0s; }

/* Wiederholter Aufruf: gar nicht erst anzeigen. */
.sp-skip-preload .sp-preloader { display: none; }
.sp-skip-preload .sp-has-preloader .sp-site,
.sp-skip-preload.sp-has-preloader .sp-site { animation: none; }

/* =========================================================
   Grid
   Die max-width und der Gutter kommen aus den Einstellungen
   (--sp-grid-max, --sp-grid-max-header, --sp-grid-max-footer).
   ========================================================= */
.sp-container { width: 100%; margin-inline: auto; }

/* Abschnitte, Projekte und das Blograster bringen ihren eigenen .sp-container
   mit. Steht er bereits in einem anderen — etwa im Inhaltsbereich einer
   normalen Seite —, zählt der äußere; sonst käme der Seitenabstand doppelt.

   Steht er allein, gelten für ihn Breite und Seitenabstand wie für jeden
   anderen Container. Genau dadurch fluchten Inhalt, Header und Footer, und
   zwar auf jeder Bildschirmbreite. Sonderregeln je Inhaltstyp gibt es hier
   bewusst nicht: Sie hatten dieselbe Spezifität wie dieser Reset, standen
   später in der Datei und haben ihn damit ausgehebelt. */
.sp-container .sp-container { max-width: none; padding-inline: 0; }

.sp-col { display: flex; align-items: center; gap: 16px; }

/* =========================================================
   Header
   ========================================================= */
.sp-header { position: relative; z-index: 500; }

.sp-header--sticky { position: sticky; top: 0; }
.admin-bar .sp-header--sticky { top: var(--wp-admin--admin-bar--height, 32px); }

/* Während die Hero-Section festgehalten wird, bleibt der Header oben stehen.

   Bewusst sticky und nicht fixed: fixed nimmt den Header aus dem Textfluss,
   wodurch der Inhalt darunter um seine Höhe hochspringt. Sticky lässt ihn im
   Fluss, wird aber ebenso vom Browser selbst erledigt — also ohne das
   Nachhinken, das eine per Skript gesetzte Verschiebung in Safari erzeugt. */
.sp-header--held {
	position: sticky;
	top: 0;
}
.admin-bar .sp-header--held { top: var(--wp-admin--admin-bar--height, 32px); }

/* Der Farbwechsel selbst steht im dynamischen CSS: Dort werden auch die
   Grundfarben von Menü und Logo gesetzt, und nur dort lässt sich sicher
   danach schreiben. Hier bleibt allein der Übergang. */
.sp-header,
.sp-header .sp-logo,
.sp-header .sp-menu a,
.sp-header .sp-logo__svg,
.sp-header .sp-burger__bar {
	transition: color var(--sp-header-contrast-speed, 250ms) ease,
		background-color var(--sp-header-contrast-speed, 250ms) ease;
}

.sp-header__inner { position: relative; }

.sp-logo { display: inline-flex; align-items: center; text-decoration: none; }
.sp-logo img,
.sp-logo svg {
	display: block;
	width: var(--sp-logo-w);
	max-height: var(--sp-logo-max-h);
	height: auto;
	transition: width .25s ease;
}
.sp-logo__text { font-family: var(--sp-font-heading); font-size: 22px; font-weight: 700; }

/* Navigation */
.sp-menu { position: relative; }
.sp-menu li { position: relative; }
.sp-menu a { display: block; padding: 6px 0; }

.sp-menu .sub-menu {
	position: absolute;
	top: 100%;
	left: 0;
	list-style: none;
	margin: 0;
	padding: 8px 0;
	opacity: 0;
	visibility: hidden;
	transform: translateY(6px);
	transition: opacity .2s ease, transform .2s ease, visibility .2s;
	z-index: 10;
}
.sp-menu .sub-menu .sub-menu { top: 0; left: 100%; }
.sp-menu li:hover > .sub-menu,
.sp-menu li:focus-within > .sub-menu {
	opacity: 1;
	visibility: visible;
	transform: translateY(0);
}
.sp-menu .sub-menu a { padding: 8px 18px; white-space: nowrap; }

/* Pillen-Menü — Maße und Farben kommen aus den Einstellungen. */
.sp-menu--pill > li > a { text-decoration: none; }
.sp-pill-layer { display: block; }

/* Burger */
.sp-burger {
	display: none;
	flex-direction: column;
	justify-content: center;
	gap: var(--sp-burger-gap, 5px);
	width: 44px;
	height: 44px;
	margin-left: auto;
	padding: 0;
	background: none;
	border: 0;
	cursor: pointer;
}
.sp-burger__bar {
	display: block;
	width: var(--sp-burger-w, 24px);
	height: var(--sp-burger-h, 2px);
	margin-inline: auto;
	background: currentColor;
	border-radius: var(--sp-burger-r, 2px);
	transition: transform .25s ease, opacity .2s ease, width .25s ease;
}
/* Erster und dritter Strich kürzer, durch margin-inline:auto mittig. */
.sp-burger__bar:nth-child(1),
.sp-burger__bar:nth-child(3) { width: var(--sp-burger-w-short, 16px); }

/* Im geöffneten Zustand bilden alle drei ein X — dafür müssen der erste und
   dritte auf die volle Länge zurück, sonst wären die Schenkel ungleich. */
.sp-burger[aria-expanded="true"] .sp-burger__bar:nth-child(1),
.sp-burger[aria-expanded="true"] .sp-burger__bar:nth-child(3) { width: var(--sp-burger-w, 24px); }
/* Der Weg zur Mitte ist Strichstärke plus Abstand — sonst passt das X nicht
   mehr, sobald einer der beiden Werte geändert wird. */
.sp-burger[aria-expanded="true"] .sp-burger__bar:nth-child(1) {
	transform: translateY(calc(var(--sp-burger-h, 2px) + var(--sp-burger-gap, 5px))) rotate(45deg);
}
.sp-burger[aria-expanded="true"] .sp-burger__bar:nth-child(2) { opacity: 0; }
.sp-burger[aria-expanded="true"] .sp-burger__bar:nth-child(3) {
	transform: translateY(calc((var(--sp-burger-h, 2px) + var(--sp-burger-gap, 5px)) * -1)) rotate(-45deg);
}

/* Mobiles Panel
   Startposition, Höhe, Dauer und Deckkraft setzt das dynamische CSS
   je nach gewähltem Einblend-Effekt. */
/* z-index über dem Header: Der liegt bei 500, und ein feststehender Header mit
   eigenem Hintergrund würde das Panel sonst verdecken. */
.sp-mobile-panel {
	position: fixed;
	left: 0;
	right: 0;
	top: var(--sp-panel-top, 0);
	z-index: 950;
	height: var(--sp-panel-height-fallback, 100vh);
	height: var(--sp-panel-height, 100vh);
	overflow-y: auto;
	overscroll-behavior: contain;
	opacity: var(--sp-panel-opacity, 1);
	visibility: hidden;
	transform: var(--sp-panel-closed, translateY(-100%));
	transition:
		transform var(--sp-panel-duration, 320ms) cubic-bezier(.4, 0, .2, 1),
		opacity var(--sp-panel-duration, 320ms) ease,
		visibility 0s linear var(--sp-panel-duration, 320ms);
}
.sp-mobile-panel.is-open {
	transform: none;
	opacity: 1;
	visibility: visible;
	transition-delay: 0s;
}

.sp-mobile-menu { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.sp-mobile-menu a { display: block; padding: 8px 0; text-decoration: none; }
.sp-mobile-menu .sub-menu {
	list-style: none;
	margin: 4px 0 4px;
	padding-left: var(--sp-mob-sub-indent, 18px);
}
.sp-mobile-menu .sub-menu a { font-size: var(--sp-mob-sub-size, .85em); }
.sp-mobile-menu--secondary { margin-top: var(--sp-mob-gap, 6px); }
/* Die Seite wird beim geöffneten Menü nicht mehr festgestellt.

   Die frühere Sperre setzte den Body auf position:fixed. Damit fand kein
   Scrollen mehr statt — und ein Header mit position:sticky hatte nichts mehr,
   woran er kleben konnte, und fiel an seine Stelle im Dokument zurück. Auf
   einer gescrollten Seite liegt die weit oberhalb des Bildes, Logo und
   Menüknopf verschwanden also nach oben.

   Ohne Sperre bleibt der Header, wo er ist. Dass der Inhalt dahinter
   mitscrollen kann, ist hier ausdrücklich gewollt. Die Klasse bleibt, weil der
   Angebot-Button sich daran ausblendet. */

/* =========================================================
   Bausteine (Header + Footer)
   ========================================================= */
.sp-block__title { font-family: var(--sp-font-heading); font-weight: 600; margin-bottom: 14px; }
.sp-block--menu .sp-menu--vertical { flex-direction: column; align-items: flex-start; gap: 8px; }

.sp-svg-group { display: flex; align-items: center; gap: var(--sp-svg-gap, 14px); flex-wrap: wrap; }
.sp-svg-item { display: inline-flex; transition: color .2s ease, opacity .2s ease; }
.sp-svg-item svg { width: var(--sp-svg-size, 28px); height: auto; }
.sp-svg-item:hover { opacity: .85; }

/* =========================================================
   Footer
   ========================================================= */
.sp-footer__cols { align-items: flex-start; }
.sp-footer__col { flex-direction: column; align-items: stretch; gap: 20px; }
.sp-footer .sp-menu--vertical a { padding: 4px 0; }
.sp-footer-bottom__col { align-items: center; }
.sp-footer-bottom__col .sp-menu { flex-wrap: wrap; gap: 20px; }
.sp-footer-bottom__col .sp-block { margin: 0; }

/* =========================================================
   Buttons – Farben und Maße kommen aus den Einstellungen
   ========================================================= */
.sp-btn { line-height: 1.3; }
.sp-btn-wrap { margin: 8px 0; }

/* =========================================================
   Projekte
   Radien, Abstände und Farben kommen aus den Einstellungen.
   ========================================================= */
.sp-pj-list,
.sp-pj-related__grid {
	display: grid;
	gap: var(--sp-pj-list-gap, 60px);
	grid-template-columns: repeat(var(--sp-pj-list-cols, 1), minmax(0, 1fr));
	margin: 0;
}
.sp-pj-related__grid {
	grid-template-columns: repeat(var(--sp-pj-related-cols, 4), minmax(0, 1fr));
	gap: var(--sp-pj-gap, 40px);
}

.sp-pj-card { display: block; text-decoration: none; max-width: var(--sp-pj-thumb, 900px); }
.sp-pj-card img { display: block; width: 100%; height: auto; }
.sp-pj-card__blank {
	display: block;
	aspect-ratio: 3 / 2;
	background: rgba(233, 233, 224, .12);
	border-radius: var(--sp-pj-radius, 0);
}
.sp-pj-card__title { display: block; margin-top: 14px; }
.sp-pj-card__sub { display: block; opacity: .7; font-size: .9em; }
.sp-pj-related__grid .sp-pj-card { max-width: none; }

/* Zeilenraster der Detailansicht */
/* Waagerechter und senkrechter Abstand getrennt.

   gap gilt in einer umbrechenden Flexzeile in beide Richtungen. Sobald die
   Spalten stapeln, wurde daraus ein senkrechter Zwischenraum, den es auf dem
   Desktop gar nicht gibt — und der sich mit den Abständen überlagerte, die im
   Baukasten je Zeile und Baustein eingestellt sind. Der senkrechte Anteil ist
   deshalb eigenständig und steht voreingestellt auf null. */
.sp-pj-row {
	display: flex;
	flex-wrap: wrap;
	column-gap: var(--sp-pj-gap, 40px);
	row-gap: var(--sp-pj-stack-gap, 0px);
	margin-bottom: var(--sp-pj-row-gap, 70px);
	justify-content: var(--sp-pj-justify, flex-start);
}
.sp-pj-row--top { align-items: flex-start; }
.sp-pj-row--center { align-items: center; }
.sp-pj-row--bottom { align-items: flex-end; }
.sp-pj-row--stretch { align-items: stretch; }
/* Welche Breite gilt, entscheiden die Medienabfragen im dynamischen CSS:
   --sp-col-d fürs Grosse, --sp-col-t fürs Tablet, --sp-col-m für Mobil.
   Nicht gesetzte Werte fallen auf die Ebene darueber zurueck. */
.sp-pj-col {
	min-width: 0;
	flex: 0 0 var(--sp-col-w, var(--sp-col-d, 100%));
	max-width: var(--sp-col-w, var(--sp-col-d, 100%));
}
.sp-pj-col > .sp-pj-block + .sp-pj-block { margin-top: var(--sp-pj-block-gap, 26px); }

.sp-pj-hero { margin-bottom: var(--sp-pj-row-gap, 70px); }
.sp-pj-hero img,
.sp-pj-block img { display: block; width: 100%; height: auto; }
/* Ausrichtung je Baustein. Bilder und Videos sind Blockelemente und werden
   deshalb über die Außenabstände ausgerichtet, nicht über text-align. */
.sp-pj-block--left { text-align: left; }
.sp-pj-block--center { text-align: center; }
.sp-pj-block--right { text-align: right; }

.sp-pj-block--left > .sp-pj-image,
.sp-pj-block--left > .sp-pj-video { margin-right: auto; margin-left: 0; }
.sp-pj-block--center > .sp-pj-image,
.sp-pj-block--center > .sp-pj-video { margin-left: auto; margin-right: auto; }
.sp-pj-block--right > .sp-pj-image,
.sp-pj-block--right > .sp-pj-video { margin-left: auto; margin-right: 0; }

.sp-pj-block--center .sp-pj-tags { justify-content: center; }
.sp-pj-block--right .sp-pj-tags { justify-content: flex-end; }

.sp-pj-label { display: block; margin-bottom: 8px; }
/* Laufweite nur beim neutralen Label; als Überschrift gilt die Typografie
   der jeweiligen H-Ebene. */
.sp-pj-label:not(.sp-pj-label--tag) { letter-spacing: .01em; }
.sp-pj-label--tag { margin-bottom: 0; }
.sp-pj-text > *:last-child { margin-bottom: 0; }

/* Projekte als Titelliste. Die Bilder liegen über der Fläche, aber unter den
   Titeln; bewegt werden sie im Skript. */
/* Kein overflow:hidden — die Bilder dürfen über die Titel hinausragen. Der
   Abstand oben und unten hält dafür Platz frei. */
.sp-titles {
	position: relative;
	padding-block: var(--sp-titles-space, 56px);
	margin-block: var(--sp-titles-edge, 100px);
}
.sp-titles .sp-container { position: relative; }

.sp-titles__wall {
	position: relative;
	z-index: 2;
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	justify-content: var(--sp-titles-align, center);
	column-gap: var(--sp-titles-gap, 16px);
	row-gap: var(--sp-titles-row-gap, 4px);
}
.sp-titles__item {
	position: relative;
	display: inline-block;
	padding: var(--sp-titles-hit, 0px);
	margin: calc(var(--sp-titles-hit, 0px) * -1);
	font-size: var(--sp-titles-size, 34px);
	line-height: 1.25;
	color: var(--sp-titles-color, inherit);
	text-decoration: none;
	white-space: nowrap;
	transition: opacity .35s ease, color .35s ease;
}
.sp-titles.is-hot .sp-titles__item { opacity: var(--sp-titles-dim, .2); }
.sp-titles.is-hot .sp-titles__item.is-active {
	opacity: 1;
	color: var(--sp-titles-color-active, var(--sp-titles-color, inherit));
}

.sp-titles__shots { position: absolute; inset: 0; z-index: 1; pointer-events: none; }
/* Die Höhe kommt vom Bild selbst: auf die eingestellte Breite gebracht,
   nichts beschnitten. */
.sp-titles__shot {
	position: absolute;
	top: 0;
	left: 0;
	width: var(--sp-titles-img, 340px);
	line-height: 0;
	border-radius: var(--sp-titles-img-radius, 10px);
	overflow: hidden;
	opacity: 0;
	transition: opacity .3s ease;
	will-change: transform;
}
.sp-titles__shot.is-active { opacity: 1; }
.sp-titles__shot img { width: 100%; height: auto; display: block; }

/* Ohne Zeiger gibt es nichts mitzubewegen. */
@media (hover: none) {
	.sp-titles__shots { display: none; }
	.sp-titles.is-hot .sp-titles__item { opacity: 1; }
}

/* Weiche Kante oben.

   Drei Lagen übereinander, jede mit mehr Unschärfe und einer kürzeren Maske.
   Dadurch nimmt die Unschärfe nach unten hin ab, statt an einer Kante
   aufzuhören. Eine einzelne Lage würde genau dort einen sichtbaren Absatz
   erzeugen, wo die Maske endet.

   Der Streifen nimmt keine Klicks an — sonst läge eine unsichtbare Fläche über
   dem Inhalt und finge Verweise darunter ab. */
.sp-blur,
.sp-blur::before,
.sp-blur::after {
	position: fixed;
	top: var(--sp-blur-top, 0px);
	left: 0;
	right: 0;
	height: var(--sp-blur-h, 100px);
	pointer-events: none;
}
.sp-blur {
	z-index: 490;
	backdrop-filter: blur(calc(var(--sp-blur-s, 14px) * .25));
	-webkit-backdrop-filter: blur(calc(var(--sp-blur-s, 14px) * .25));
	-webkit-mask-image: linear-gradient(to bottom, #000 0%, transparent 100%);
	mask-image: linear-gradient(to bottom, #000 0%, transparent 100%);
}
.sp-blur::before,
.sp-blur::after { content: ""; display: block; }
.sp-blur::before {
	backdrop-filter: blur(calc(var(--sp-blur-s, 14px) * .5));
	-webkit-backdrop-filter: blur(calc(var(--sp-blur-s, 14px) * .5));
	-webkit-mask-image: linear-gradient(to bottom, #000 0%, transparent 66%);
	mask-image: linear-gradient(to bottom, #000 0%, transparent 66%);
}
.sp-blur::after {
	backdrop-filter: blur(var(--sp-blur-s, 14px));
	-webkit-backdrop-filter: blur(var(--sp-blur-s, 14px));
	-webkit-mask-image: linear-gradient(to bottom, #000 0%, transparent 33%);
	mask-image: linear-gradient(to bottom, #000 0%, transparent 33%);
}

/* Der Streifen ist über dem Menü und in der Lightbox fehl am Platz. */
body.sp-menu-open .sp-blur,
body.sp-lightbox-open .sp-blur,
body.sp-form-open .sp-blur { display: none; }

/* Fester Aktionsbutton, unten mittig. Der äußere Kasten trägt die Farbe, die
   beiden inneren Flächen setzen sich davon ab — wie ein Rahmen, der zwischen
   Text und Zeichen hindurchläuft. */
/* Er blendet sich verzögert ein: Die Deckkraft steigt nach einer Wartezeit,
   die als Verzögerung des Übergangs gesetzt ist. Das kommt ohne Skript aus.
   Bis dahin nimmt er keine Klicks an — sonst ließe sich etwas Unsichtbares
   treffen. */
.sp-cta {
	opacity: 0;
	pointer-events: none;
	animation: sp-cta-in var(--sp-cta-fade, 600ms) ease var(--sp-cta-delay, 2000ms) forwards;
	position: fixed;
	left: 50%;
	bottom: var(--sp-cta-bottom, 28px);
	transform: translateX(-50%);
	z-index: 800;
	display: inline-flex;
	align-items: stretch;
	gap: var(--sp-cta-gap, 6px);
	padding: var(--sp-cta-padding, 8px);
	background: var(--sp-cta-bg, #0e0e13);
	border-radius: var(--sp-cta-radius, 40px);
	color: var(--sp-cta-color, #e9e9e0);
	text-decoration: none;
	max-width: calc(100vw - 32px);
	transition: background-color .25s ease, color .25s ease;
}
.sp-cta__text,
.sp-cta__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--sp-cta-inner, #1f1f28);
	border-radius: var(--sp-cta-radius, 40px);
	transition: background-color .25s ease, color .25s ease;
}
/* Feste Höhe statt Innenabstand oben und unten: Die Gesamthöhe soll
   unabhängig von der Schriftgröße sein — sie ergibt sich aus dieser Höhe plus
   zweimal der Rahmenbreite. */
.sp-cta__text {
	height: var(--sp-cta-inner-h, 40px);
	padding-inline: var(--sp-cta-text-pad, 28px);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}
.sp-cta__icon {
	/* Quadratisch, damit daraus ein Kreis wird. */
	flex: 0 0 auto;
	width: var(--sp-cta-inner-h, 40px);
	height: var(--sp-cta-inner-h, 40px);
	border-radius: 50%;
}
.sp-cta__svg { display: block; width: var(--sp-cta-icon, 26px); height: auto; }

.sp-cta:hover .sp-cta__text,
.sp-cta:hover .sp-cta__icon,
.sp-cta:focus-visible .sp-cta__text,
.sp-cta:focus-visible .sp-cta__icon {
	background: var(--sp-cta-hover-bg, #e9e9e0);
	color: var(--sp-cta-hover-color, #16161d);
}

@keyframes sp-cta-in {
	to { opacity: 1; pointer-events: auto; }
}

/* Wer Bewegung ablehnt, bekommt ihn ohne Übergang — aber ebenfalls erst
   nach der Wartezeit, damit er nicht sofort im Weg steht. */
@media (prefers-reduced-motion: reduce) {
	.sp-cta { animation-duration: 1ms; }
}

/* Beim geöffneten Menü oder in der Lightbox wäre er im Weg. */
body.sp-menu-open .sp-cta,
body.sp-lightbox-open .sp-cta { display: none; }

/* Anfrageformular in einem Fenster. Mittig in beide Richtungen; wird der
   Inhalt höher als das Fenster, scrollt er innerhalb der Fläche. */
.sp-form-modal {
	position: fixed;
	inset: 0;
	z-index: 9100;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 24px;
	background: var(--sp-form-modal-veil, rgba(0, 0, 0, .6));
	opacity: 0;
	transition: opacity .25s ease;
}
.sp-form-modal[hidden] { display: none; }
.sp-form-modal.is-open { opacity: 1; }

.sp-form-modal__box {
	position: relative;
	width: 100%;
	max-width: var(--sp-form-modal-w, 860px);
	max-height: calc(100dvh - 48px);
	overflow-y: auto;
	overscroll-behavior: contain;
	padding: var(--sp-form-modal-pad, 48px);
	background: var(--sp-form-modal-bg, #16161d);
	border-radius: var(--sp-form-modal-radius, 16px);
	box-shadow: 0 30px 70px rgba(0, 0, 0, .5);
	transform: translateY(12px);
	transition: transform .25s ease;
}
.sp-form-modal.is-open .sp-form-modal__box { transform: none; }

/* Im Fenster darf das Formular die ganze Breite nutzen. */
.sp-form-modal .sp-form { max-width: none; }

.sp-form-modal__title { margin: 0 0 24px; }
.sp-form-modal__close {
	position: absolute;
	top: 14px;
	right: 18px;
	background: none;
	border: 0;
	color: inherit;
	font-size: 30px;
	line-height: 1;
	cursor: pointer;
	opacity: .6;
	transition: opacity .2s ease;
}
.sp-form-modal__close:hover { opacity: 1; }
/* Safari zeichnet nach einem Mausklick einen Rahmen um den Knopf. Für die
   Tastatur bleibt er erhalten, für die Maus nicht. */
.sp-form-modal__close:focus:not(:focus-visible) { outline: none; }

body.sp-form-open { overflow: hidden; }

@media (max-width: 767px) {
	.sp-form-modal { padding: 12px; }
	.sp-form-modal__box { padding: 28px 20px; max-height: calc(100dvh - 24px); }
}

/* Anfrageformular. Verborgene Schritte sind wirklich verborgen — hidden statt
   nur unsichtbar, damit sie weder anfassbar noch vorlesbar sind. */
.sp-form { max-width: var(--sp-form-width, 640px); }
/* Steht bewusst weit oben und trotzdem mit Vorrang: Die Regeln für die
   einzelnen Bestandteile weiter unten setzen display und würden das
   Ausblenden sonst überschreiben, weil sie gleich stark sind und später
   stehen. */
.sp-form [hidden],
.sp-form .sp-form__tag[hidden] { display: none !important; }
.sp-form__step { margin-bottom: var(--sp-form-gap, 30px); }
.sp-form__field { margin: 0 0 var(--sp-form-gap, 30px); }

/* Die Auswahlkästen sind ebenfalls Labels und hier ausgenommen — sonst erben
   sie Blocksatz, Außenabstand und Schriftgröße der Feldbeschriftungen. */
.sp-form__label,
.sp-form label:not(.sp-form__tag) {
	display: block;
	margin-bottom: 8px;
	font-size: var(--sp-form-label, .9em);
	opacity: .85;
}

/* Leistungen als Tags. Ausgewählte werden gefüllt — die Farben kommen aus
   Button-Stil 1, damit sie zum übrigen Auftritt passen. */
.sp-form__tags {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	align-content: flex-start;
	gap: 10px;
	margin-bottom: 10px;
}
.sp-form .sp-form__tag {
	display: inline-flex;
	align-items: center;
	margin: 0;
	padding: 9px 18px;
	border: 1px solid currentColor;
	border-radius: var(--sp-form-tag-radius, 20px);
	font-size: inherit;
	line-height: 1.2;
	cursor: pointer;
	opacity: .75;
	transition: opacity .2s ease, background-color .2s ease, color .2s ease;
}
.sp-form .sp-form__tag:hover { opacity: 1; }
.sp-form .sp-form__tag:has(input:checked) {
	opacity: 1;
	background: var(--sp-form-tag-bg, #e9e9e0);
	border-color: var(--sp-form-tag-bg, #e9e9e0);
	color: var(--sp-form-tag-color, #16161d);
}

/* Das Kästchen selbst wird nicht gebraucht: Der ganze Tag zeigt den Zustand.
   Es bleibt aber im Markup, damit Tastatur und Vorleseprogramme es finden. */
.sp-form__tag input {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
	pointer-events: none;
}
.sp-form__tag:focus-within { outline: 2px solid currentColor; outline-offset: 2px; }

.sp-form__grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
	gap: 0 var(--sp-form-gap, 30px);
}

.sp-form input[type="text"],
.sp-form input[type="email"],
.sp-form input[type="url"],
.sp-form input[type="tel"],
.sp-form input[type="number"],
.sp-form select,
.sp-form textarea {
	width: 100%;
	padding: 12px 14px;
	background: transparent;
	border: 1px solid currentColor;
	border-radius: var(--sp-form-radius, 8px);
	color: inherit;
	font: inherit;
	/* Gleiche Zeilenhöhe für alle Felder. „font: inherit“ überträgt sie nicht
	   auf ein Auswahlfeld — dort setzt der Browser eine eigene, und das Feld
	   fällt niedriger aus als die Textfelder daneben. */
	line-height: 1.5;
}

/* Und dieselbe Mindesthöhe: Zeilenhöhe plus Polsterung plus Rahmen. Damit
   stehen Auswahl- und Textfelder auch dann gleich hoch, wenn ein Browser
   intern noch etwas dazurechnet. */
.sp-form input[type="text"],
.sp-form input[type="email"],
.sp-form input[type="url"],
.sp-form input[type="tel"],
.sp-form input[type="number"],
.sp-form select {
	min-height: calc(1.5em + 26px);
}
.sp-form textarea { resize: vertical; }
/* Kein zweiter Rahmen um das Feld: Der vorhandene wird kräftiger, statt dass
   sich außen herum eine weitere Linie legt. */
.sp-form input:focus-visible,
.sp-form select:focus-visible,
.sp-form textarea:focus-visible {
	outline: none;
	box-shadow: inset 0 0 0 1px currentColor;
}

.sp-form__hint { display: block; margin-top: 6px; font-size: .85em; opacity: .6; }
.sp-form__privacy { font-size: .85em; opacity: .7; }

/* Die Falle liegt außerhalb des Bildes statt auf display:none — manche
   selbsttätigen Ausfüller überspringen verborgene Felder. */
.sp-form__trap {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

.sp-form__status { min-height: 1.5em; margin: 0; }
.sp-form.is-error .sp-form__status { color: var(--sp-form-error, #e2686d); }
.sp-form.is-done .sp-form__status { color: var(--sp-form-ok, #4ab866); }
.sp-form.is-done .sp-form__step { display: none; }

/* Akkordeon. Der Inhalt bleibt auch geschlossen im Markup — nur die Höhe geht
   auf null, damit er weder sichtbar noch anfassbar ist. */
.sp-acc__item { border-bottom: 1px solid var(--sp-acc-line, currentColor); }
.sp-acc--boxed .sp-acc__item {
	border: 1px solid var(--sp-acc-line, currentColor);
	border-radius: var(--sp-acc-radius, 10px);
	margin-bottom: var(--sp-acc-gap, 10px);
	padding-inline: var(--sp-acc-pad, 20px);
}

.sp-acc__head { margin: 0; }
.sp-acc__button {
	display: flex;
	align-items: center;
	gap: 16px;
	width: 100%;
	padding: var(--sp-acc-pad, 20px) 0;
	background: none;
	border: 0;
	color: inherit;
	font: inherit;
	text-align: left;
	cursor: pointer;
	transition: color .2s ease;
}
.sp-acc__title { flex: 1; }

/* Zwei Striche bilden je nach Einstellung ein Plus oder einen Pfeil. */
.sp-acc__mark {
	position: relative;
	flex: 0 0 auto;
	width: var(--sp-acc-mark, 20px);
	height: var(--sp-acc-mark, 20px);
	transition: transform .3s ease;
}
.sp-acc__mark span {
	position: absolute;
	left: 0;
	top: 50%;
	width: 100%;
	height: 1.5px;
	background: currentColor;
	border-radius: 2px;
	transition: transform .3s ease, opacity .3s ease;
}
.sp-acc__mark span:nth-child(2) { transform: rotate(90deg); }
.sp-acc__item.is-open .sp-acc__mark span:nth-child(2) { transform: rotate(0); opacity: 0; }

.sp-acc--chevron .sp-acc__mark span:nth-child(1) { width: 55%; transform: translateX(10%) rotate(45deg); }
.sp-acc--chevron .sp-acc__mark span:nth-child(2) { width: 55%; left: auto; right: 10%; transform: rotate(-45deg); }
.sp-acc--chevron .sp-acc__item.is-open .sp-acc__mark { transform: rotate(180deg); }
.sp-acc--chevron .sp-acc__item.is-open .sp-acc__mark span:nth-child(2) { opacity: 1; }

.sp-acc__panel {
	height: 0;
	overflow: hidden;
	transition: height var(--sp-acc-speed, 320ms) cubic-bezier(.4, 0, .2, 1);
}
.sp-acc__text { padding-bottom: var(--sp-acc-pad, 20px); }
.sp-acc__text > *:first-child { margin-top: 0; }
.sp-acc__text > *:last-child { margin-bottom: 0; }

/* Ohne Skript bleibt alles offen, damit der Inhalt lesbar ist. */
.no-js .sp-acc__panel { height: auto; }

/* Progress.

   Das Element ist so hoch wie der Scrollweg; der Container darin klebt am
   oberen Rand, solange es durchlaufen wird. Die Grafik passt sich dabei in die
   Fensterhöhe ein — der ganze Weg bleibt sichtbar, die dicke Linie wächst
   darüber. sticky funktioniert hier, weil html und body overflow-x: clip
   tragen statt hidden; hidden würde einen Scrollcontainer erzeugen und das
   Kleben verhindern. */
.sp-progress {
	position: relative;
	height: var(--sp-progress-scroll, 250vh);
	color: var(--sp-progress-color, #e9e9e0);
}
.sp-progress__sticky {
	position: sticky;
	top: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	height: 100vh;
	height: 100svh;
	padding-block: 2vh;
	box-sizing: border-box;
}
.sp-progress__svg {
	display: block;
	width: 100%;
	height: 100%;
	overflow: visible;
}
.sp-progress__num { font-weight: 500; }

/* Zwei Fassungen: Desktop sichtbar, Mobil verborgen. Die Umschaltung am
   mobilen Umbruchpunkt setzt das dynamische Stylesheet, weil der Wert im
   Backend einstellbar ist. */
.sp-progress__svg--m { display: none; }

/* Links im Text. SVG kennt kein color für Text — die Farbe steht in fill.
   Hervorgehoben durch die Strichstärke statt einer Unterstreichung. */
.sp-progress__link tspan {
	text-decoration: none;
	font-weight: 500;
}
.sp-progress__link:hover tspan,
.sp-progress__link:focus-visible tspan { fill: var(--sp-progress-link-hover, #ffffff); }
.sp-progress__link:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }
.sp-progress__num,
.sp-progress__text { transition: none; }

/* Bild mit Würfel in einer Ecke.

   Der Rahmen ist nur so breit wie das Bild — dadurch sitzt der Würfel an
   dessen Kante und nicht an der Spaltenkante. Das Bild behält sein eigenes
   Seitenverhältnis; angegeben wird nur die Breite. */
.sp-iz {
	position: relative;
	display: inline-block;
	max-width: 100%;
	width: var(--sp-iz-w, 100%);
	vertical-align: top;
}
.sp-iz__img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: var(--sp-pj-radius, 0);
}

.sp-iz__box {
	position: absolute;
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: 4px;
	width: var(--sp-iz-box-w, 150px);
	height: var(--sp-iz-box-h, var(--sp-iz-box-w, 150px));
	padding: 14px 18px;
	background: var(--sp-iz-bg, #e9e9e0);
	color: var(--sp-iz-color, #16161d);
	border-radius: var(--sp-iz-radius, 16px);
	box-sizing: border-box;
}

/* Der Überstand zieht den Würfel über die Bildkante hinaus. */
.sp-iz--tl .sp-iz__box { top: calc(var(--sp-iz-shift, 0px) * -1); left: calc(var(--sp-iz-shift, 0px) * -1); }
.sp-iz--tr .sp-iz__box { top: calc(var(--sp-iz-shift, 0px) * -1); right: calc(var(--sp-iz-shift, 0px) * -1); }
.sp-iz--bl .sp-iz__box { bottom: calc(var(--sp-iz-shift, 0px) * -1); left: calc(var(--sp-iz-shift, 0px) * -1); }
.sp-iz--br .sp-iz__box { bottom: calc(var(--sp-iz-shift, 0px) * -1); right: calc(var(--sp-iz-shift, 0px) * -1); }

/* Ohne Bild steht der Würfel für sich und braucht keine Verankerung. */
.sp-iz--solo { width: auto; }
.sp-iz--solo .sp-iz__box { position: static; }

.sp-iz__num {
	display: block;
	line-height: 1;
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	font-feature-settings: "tnum";
}
.sp-iz__text { display: block; line-height: 1.3; }

/* Zahl mit Text darunter. Die Größe der Zahl kommt als eigener Wert am
   Element — sie soll sich nicht nach der Typografie richten, sondern genau so
   groß sein, wie im Baustein eingetragen. */
.sp-count__value {
	display: block;
	line-height: 1.05;
	/* Ziffern gleich breit, damit die Zahl beim Hochzählen nicht zappelt. */
	font-variant-numeric: tabular-nums;
	font-feature-settings: "tnum";
}
.sp-count__text { margin: 12px 0 0; }

/* Aufzählung im Textbaustein.

   Das Zeichen steht im Textfluss (list-style-position: inside), damit es genau
   auf der Höhe der ersten Zeile sitzt. Ohne weiteres Zutun würde eine
   umbrechende Zeile aber wieder ganz links beginnen. Deshalb wird der Punkt um
   den Einzug nach rechts geschoben und die erste Zeile um denselben Betrag
   zurückgezogen — die Folgezeilen stehen dadurch bündig unter dem Text. */
.sp-list {
	list-style-position: inside;
	margin: var(--sp-list-gap, 12px) 0;
	padding: 0;
}
.sp-list li {
	padding-left: var(--sp-list-indent, 1.4em);
	text-indent: calc(var(--sp-list-indent, 1.4em) * -1);
	margin-bottom: var(--sp-list-gap, 12px);
}
.sp-list li:last-child { margin-bottom: 0; }
.sp-list li::marker { content: var(--sp-list-marker, "–  "); }

/* Liste mit Haken. Das Zeichen ist eine Maske, keine eigene Farbe: Es nimmt
   dadurch die Textfarbe an und passt sich jedem Farbschema an. */
.sp-check {
	list-style: none;
	margin: var(--sp-check-gap, 14px) 0 0;
	padding: 0;
}
.sp-check li {
	position: relative;
	display: flex;
	align-items: flex-start;
	gap: var(--sp-check-space, 14px);
	margin-bottom: var(--sp-check-gap, 14px);
}
.sp-check li:last-child { margin-bottom: 0; }
.sp-check li::before {
	content: "";
	flex: 0 0 auto;
	width: var(--sp-check-size, 22px);
	height: var(--sp-check-size, 22px);
	/* Senkrecht auf die erste Zeile ausgerichtet, nicht auf den ganzen Block:
	   bei umbrechenden Punkten bliebe das Zeichen sonst in der Mitte hängen. */
	margin-top: calc((1em * var(--sp-check-line, 1.65) - var(--sp-check-size, 22px)) / 2);
	background-color: currentColor;
	-webkit-mask: var(--sp-check-mark) center / contain no-repeat;
	mask: var(--sp-check-mark) center / contain no-repeat;
}

:root {
	--sp-check-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M8.5 12.3l2.4 2.4 4.6-5'/%3E%3C/svg%3E");
}

/* Button und Icon im Baukasten.

   Die Auswahl ist bewusst zwei Klassen tief: Die Button-Stile setzen
   display:inline-block und stehen im dynamischen CSS, also später. Mit nur
   einer Klasse würde inline-flex überschrieben und der Abstand zwischen Icon
   und Text fiele weg. */
.sp-pj-block .sp-pj-button {
	display: inline-flex;
	align-items: center;
	gap: var(--sp-pj-icon-gap, 12px);
	line-height: 1.2;
}
.sp-pj-block .sp-pj-button--right { flex-direction: row-reverse; }

.sp-pj-icon { display: inline-flex; align-items: center; }
.sp-pj-icon__mark {
	flex: 0 0 auto;
	width: var(--sp-pj-icon, 20px);
	height: auto;
	/* Feinausgleich, falls das Icon im eigenen Rahmen nicht mittig sitzt. */
	transform: translateY(var(--sp-pj-icon-shift, 0px));
}
.sp-pj-icon__mark svg { display: block; width: 100%; height: auto; }

/* Bausteine nebeneinander, etwa für eine Buttonreihe. */
/* Die Ausrichtung der Zeile vererbt sich hierher: Eine zentrierte Zeile
   zentriert damit auch eine Buttonreihe in einer vollbreiten Spalte, wo
   justify-content an der Zeile selbst nichts bewirken würde. */
.sp-pj-col--inline {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--sp-pj-inline-gap, 16px);
	justify-content: var(--sp-pj-justify, flex-start);
}
/* Der senkrechte Abstand entfällt, den Zwischenraum macht hier gap. */
.sp-pj-col--inline > .sp-pj-block,
.sp-pj-col--inline > .sp-pj-block + .sp-pj-block { margin-top: 0; }

.sp-pj-quote { margin: 0; }
.sp-pj-quote > *:last-child { margin-bottom: 0; }
.sp-pj-author { margin-top: 14px; opacity: .7; font-size: .85em; }

/* Abstand: Grundhöhe am Element, die Ebenen darunter im dynamischen CSS. */
.sp-pj-spacer { height: var(--sp-h, 0px); }

.sp-pj-tags {
	display: flex;
	flex-wrap: wrap;
	/* Ohne diese Angabe streckt Flexbox die Einträge einer Zeile auf die Höhe
	   des höchsten — ein einzelner Eintrag mit abweichendem Inhalt zieht dann
	   alle mit. Jeder Eintrag soll genau so hoch sein wie sein Inhalt. */
	align-items: flex-start;
	align-content: flex-start;
	gap: 10px;
	list-style: none;
	margin: 0;
	padding: 0;
}
.sp-pj-tags .sp-pj-tag {
	position: relative;
	display: inline-flex;
	align-items: center;
	padding: 7px 16px;
	border: 1px solid currentColor;
	line-height: 1.2;
}

/* Hinweis beim Überfahren. Er liegt im Eintrag selbst, damit er beim Wechsel
   zwischen Eintrag und Hinweis nicht verschwindet. */

.sp-pj-tag__tip {
	position: absolute;
	top: calc(100% + 10px);
	bottom: auto;
	left: 50%;
	transform: translate(-50%, 6px);
	z-index: 30;
	width: max-content;
	max-width: var(--sp-tip-width, 340px);
	padding: var(--sp-tip-padding, 24px);
	background: var(--sp-tip-bg, #1f1f28);
	color: var(--sp-tip-color, inherit);
	border-radius: var(--sp-tip-radius, 16px);
	box-shadow: 0 18px 40px rgba(0, 0, 0, .45);
	text-align: left;
	white-space: normal;
	opacity: 0;
	visibility: hidden;
	pointer-events: none;
	transition: opacity .22s ease, transform .22s ease, visibility 0s linear .22s;
}
.sp-pj-tag--tip:hover .sp-pj-tag__tip,
.sp-pj-tag--tip:focus .sp-pj-tag__tip,
.sp-pj-tag--tip:focus-within .sp-pj-tag__tip {
	opacity: 1;
	visibility: visible;
	transform: translate(-50%, 0);
	transition-delay: 0s;
}

/* Nach oben, wenn darunter zu wenig Platz ist. Die Bewegung beim Einblenden
   dreht sich mit, damit der Hinweis aus der Richtung kommt, in der er liegt. */
.sp-pj-tag--above .sp-pj-tag__tip {
	top: auto;
	bottom: calc(100% + 10px);
	transform: translate(-50%, -6px);
}
.sp-pj-tag--above.sp-pj-tag--tip:hover .sp-pj-tag__tip,
.sp-pj-tag--above.sp-pj-tag--tip:focus .sp-pj-tag__tip,
.sp-pj-tag--above.sp-pj-tag--tip:focus-within .sp-pj-tag__tip {
	transform: translate(-50%, 0);
}

/* Ohne Zeiger gibt es kein Überfahren: Dort öffnet ein Tippen den Hinweis in
   der Lightbox, der Kasten bleibt verborgen. */
@media (hover: none), (pointer: coarse) {
	.sp-pj-tag__tip { display: none; }
}

/* Beitrag in der Lightbox */
.sp-post-lightbox { padding-block: 10px 40px; }
.sp-post-lightbox__thumb { margin-bottom: 30px; }
.sp-post-lightbox__thumb img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: var(--sp-pj-radius, 0);
}
.sp-post-lightbox__meta {
	display: flex;
	flex-wrap: wrap;
	gap: 14px;
	margin-bottom: 10px;
	font-size: .85em;
	opacity: .7;
}
.sp-post-lightbox__title { margin: 0 0 24px; }
.sp-post-lightbox__text > *:first-child { margin-top: 0; }
.sp-post-lightbox__text > *:last-child { margin-bottom: 0; }

/* Hinweis in der Lightbox */
.sp-lightbox__note { padding-block: 20px 40px; }
.sp-lightbox__note-title { margin: 0 0 14px; }
.sp-lightbox__note-text { line-height: 1.7; }

.sp-pj-video { overflow: hidden; }
/* Eingebettete Videos brauchen ein festes Verhältnis, weil ein iframe seine
   Höhe nicht vom Inhalt nimmt. Eine eigene Datei bringt ihre Maße mit — dort
   wäre 16:9 eine Verzerrung. */
.sp-pj-video iframe { display: block; width: 100%; aspect-ratio: 16 / 9; border: 0; }
.sp-pj-video video { display: block; width: 100%; height: auto; }

.sp-pj-divider {
	display: flex;
	align-items: center;
	gap: 20px;
	margin: var(--sp-pj-divider-top, 40px) 0 var(--sp-pj-row-gap, 70px);
}
.sp-pj-divider::before,
.sp-pj-divider::after { content: ""; flex: 1 1 0; height: 1px; background: currentColor; opacity: .25; }
.sp-pj-divider__mark { display: block; width: var(--sp-pj-divider-mark, 26px); }
.sp-pj-divider__mark svg { display: block; width: 100%; height: auto; }

.sp-pj-related { margin-bottom: 40px; }
.sp-pj-related .sp-pj-label { margin-bottom: 24px; }

/* Hero-Section mit horizontalem Verlauf.
   Der Wrapper ist so hoch wie Section plus waagerechte Strecke; die Höhe
   setzt das Skript nach dem Messen. Bis dahin bleibt die Spur einfach
   waagerecht scrollbar — so ist der Inhalt auch ohne JavaScript erreichbar. */
/* Die Hero-Section geht immer über die volle Fensterbreite.

   Sie liegt oft in einer gewöhnlichen WPBakery-Zeile, und die ist auf die
   Rasterbreite begrenzt. Statt das je Seite von Hand einzustellen, bricht die
   Section hier aus ihrem Container aus: Sie wird so breit wie das Fenster und
   um die halbe Differenz nach links gezogen. Der seitliche Überstand wird vom
   overflow-x: clip an html und body aufgefangen. */
.sp-hero-wrap {
	position: relative;
	width: var(--sp-hero-width, 100vw);
	margin-left: calc(50% - var(--sp-hero-width, 100vw) / 2);
}

/* In einem Container, der ohnehin die volle Breite hat, bleibt sie, wie sie
   ist — sonst käme der Überstand doppelt. */
.sp-hero-wrap--full { width: 100%; margin-left: 0; }

.sp-hero-sticky {
	position: relative;
	height: var(--sp-hero-height, 90vh);
	overflow-x: auto;
	overflow-y: hidden;
	background: var(--sp-hero-bg, transparent);
}
@supports (height: 100svh) {
	.sp-hero-sticky { height: var(--sp-hero-height-sv, 90svh); }
}
.sp-hero-wrap.is-pinned .sp-hero-sticky {
	position: sticky;
	top: 0;
	overflow: hidden;
}

.sp-hero-sticky { display: flex; align-items: center; }

/* Feste Entwurfshöhe; das Skript verkleinert die ganze Fläche, wenn die
   Section niedriger ist. Der Ursprung liegt links, damit der Anfang der Spur
   an Ort und Stelle bleibt. */
.sp-hero-stage {
	position: relative;
	flex: 0 0 auto;
	height: var(--sp-hero-design-h, 800px);
	transform-origin: 0 50%;
}

.sp-hero-el {
	position: absolute;
	transform: translate3d(0, -50%, 0);
	text-decoration: none;
	color: inherit;
	will-change: transform;
}
/* Gilt für <img> wie für eingebettete SVGs: beide füllen die eingestellte
   Breite des Elements und behalten ihr Seitenverhältnis. */
.sp-hero-img { display: block; width: 100%; height: auto; }
.sp-hero-el--image > svg.sp-hero-img { width: 100%; height: auto; }
.sp-hero-video { display: block; width: 100%; height: auto; background: rgba(233, 233, 224, .06); }

.sp-hero-kicker { margin-bottom: 18px; opacity: .85; }
.sp-hero-words__now { display: inline-block; }
.sp-hero-headline { font-family: var(--sp-font-heading); line-height: 1.15; margin-bottom: 28px; }
.sp-hero-button { display: inline-block; }

.sp-hero-quote { margin: 0; }
.sp-hero-author { margin-top: 14px; opacity: .7; font-size: .85em; }

.sp-hero-icon { display: flex; align-items: flex-start; gap: 16px; }
.sp-hero-icon__mark { flex: 0 0 auto; width: var(--sp-hero-icon-size, 28px); height: auto; }
.sp-hero-icon__text strong { display: block; font-weight: 600; }
.sp-hero-icon__text span { display: block; opacity: .8; }

/* Der Kasten lässt sich jedem Elementtyp zuweisen. */
.sp-hero-el.is-boxed {
	display: flex;
	align-items: center;
	justify-content: center;
	padding: var(--sp-hero-box-padding, 20px);
	background: var(--sp-hero-box-bg, #e9e9e0);
	color: var(--sp-hero-box-color, #16161d);
	border-radius: var(--sp-hero-radius, 20px);
	box-sizing: border-box;
}
.sp-hero-el.is-boxed .sp-hero-img { border-radius: 0; }
.sp-hero-el--text.is-boxed,
.sp-hero-el--quote.is-boxed { display: block; }
.sp-hero-el.is-boxed .sp-hero-icon__text span { opacity: .7; }

@media (max-width: 767px) {
	.sp-hero-el { position: static; width: auto !important; transform: none !important; }
	.sp-hero-el--nomobile { display: none !important; }
	.sp-hero-stage {
		width: auto !important;
		height: auto !important;
		transform: none !important;
		display: flex;
		flex-direction: column;
		gap: 40px;
		padding: 40px var(--sp-gutter, 20px);
	}
	.sp-hero-sticky { height: auto; overflow: visible; display: block; }
	.sp-hero-wrap.is-pinned .sp-hero-sticky { position: static; overflow: visible; }
	.sp-hero-wrap { height: auto !important; }
}

/* Bewegung beim Hereinscrollen.
   Bis das Skript den ersten Wert gesetzt hat, steht --sp-anim auf 1 — ohne
   JavaScript bleibt der Inhalt dadurch sichtbar. */
.sp-anim { --sp-anim: 1; --sp-anim-scale: 1; }

.sp-anim--scale {
	transform: scale(var(--sp-anim-scale));
	transform-origin: center top;
	will-change: transform;
}
/* Der Radius wird durch den Faktor geteilt und bleibt so optisch konstant. */
.sp-anim--scale .sp-pj-image,
.sp-anim--scale .sp-pj-video {
	border-radius: calc(var(--sp-pj-radius, 0px) / var(--sp-anim-scale));
}

.sp-anim--fade { opacity: var(--sp-anim); }
.sp-anim--fade_up {
	opacity: var(--sp-anim);
	transform: translateY(calc((1 - var(--sp-anim)) * 40px));
	will-change: transform, opacity;
}

/* Beitragsbild auf der Einzelseite */
.sp-entry-thumb { margin: 0 0 32px; }
.sp-entry-thumb__img { display: block; width: 100%; height: auto; border-radius: var(--sp-pj-radius, 0); }

/* Blog im Zeitungslayout.
   Ohne JavaScript stehen die Karten untereinander; erst .is-tiled schaltet
   auf absolute Positionierung um. Der Inhalt ist also nie unerreichbar. */
/* Über die volle Breite bleibt nur der Seitenabstand; im Grid übernimmt
   der Container in der Ausgabe Breite und Abstand wie überall sonst. */
/* Das Raster über die volle Fensterbreite.

   Es liegt meist in einer gewöhnlichen WPBakery-Zeile, und die ist auf die
   Rasterbreite begrenzt. Deshalb bricht es aus seinem Container aus — so wie
   die Hero-Section: so breit wie das Fenster, um die halbe Differenz nach
   links gezogen. Der Überstand wird vom overflow-x: clip an html und body
   aufgefangen. */
.sp-blog--full {
	width: var(--sp-blog-full-width, 100vw);
	margin-left: calc(50% - var(--sp-blog-full-width, 100vw) / 2);
	padding-inline: var(--sp-gutter);
}

/* In einem Container, der ohnehin die volle Breite hat, bleibt es, wie es
   ist — sonst käme der Überstand doppelt. */
.sp-container .sp-blog--full {
	width: 100%;
	margin-left: 0;
	padding-inline: 0;
}

.sp-blog__filter {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 10px;
	margin: 0 auto 36px;
}
.sp-blog__chip {
	padding: 7px 16px;
	font: inherit;
	font-size: var(--sp-blog-meta-size, 12px);
	letter-spacing: .04em;
	text-transform: uppercase;
	color: inherit;
	background: none;
	border: 1px solid currentColor;
	border-radius: 20px;
	cursor: pointer;
	opacity: .6;
	transition: opacity .2s ease, background-color .2s ease, color .2s ease;
}
.sp-blog__chip span { opacity: .6; margin-left: 4px; }
.sp-blog__chip:hover { opacity: 1; }
.sp-blog__chip.is-active {
	opacity: 1;
	background: var(--sp-blog-cat-color, currentColor);
	border-color: var(--sp-blog-cat-color, currentColor);
	color: var(--sp-color-bg, #16161d);
}
.sp-blog-card[hidden] { display: none; }

.sp-blog__grid { position: relative; }
.sp-blog__grid > .sp-blog-card { margin-bottom: var(--sp-blog-gap, 28px); }

.sp-blog__grid.is-tiled > .sp-blog-card {
	position: absolute;
	top: 0;
	left: 0;
	margin-bottom: 0;
	box-sizing: border-box;
	transition: top .25s ease, left .25s ease;
}

.sp-blog__grid.is-columns {
	column-gap: var(--sp-blog-gap, 28px);
}
.sp-blog__grid.is-columns > .sp-blog-card {
	break-inside: avoid;
	-webkit-column-break-inside: avoid;
	display: inline-block;
	width: 100%;
}

.sp-blog-card__inner {
	display: block;
	color: inherit;
	text-decoration: none;
	padding-bottom: 18px;
	border-bottom: 1px solid var(--sp-blog-rule, currentColor);
}
.sp-blog-card__media { margin-bottom: 12px; overflow: hidden; border-radius: var(--sp-blog-radius, 12px); }
.sp-blog-card__media img { display: block; width: 100%; height: auto; }

.sp-blog-card__meta { display: flex; align-items: baseline; gap: 10px; }
.sp-blog-card__cat {
	font-size: var(--sp-blog-meta-size, 11px);
	letter-spacing: .06em;
	text-transform: uppercase;
	color: var(--sp-blog-cat-color, currentColor);
}
.sp-blog-card__date { font-size: var(--sp-blog-meta-size, 11px); color: var(--sp-blog-meta-color, currentColor); }

.sp-blog-card__title {
	font-size: var(--sp-blog-title-size, 17px);
	line-height: 1.25;
	margin: 8px 0 6px;
}
.sp-blog-card--lead .sp-blog-card__title { font-size: var(--sp-blog-lead-size, 24px); }

/* Der Anriss wächst weiter, statt dass der Text ein zweites Mal erscheint.
   Ohne JavaScript bleibt die Fortsetzung verborgen und der Klick führt auf
   die Einzelseite. */
.sp-blog-card__rest { display: none; }
.sp-blog-card.is-open .sp-blog-card__rest { display: inline; }
.sp-blog-card.is-open .sp-blog-card__ellipsis { display: none; }

.sp-blog-card__permalink {
	display: none;
	margin-top: 14px;
	font-size: var(--sp-blog-meta-size, 11px);
}
.sp-blog-card.is-open .sp-blog-card__permalink { display: inline-block; }

.sp-blog-card__text {
	font-size: var(--sp-blog-text-size, 13px);
	line-height: 1.5;
	color: var(--sp-blog-text-color, currentColor);
	margin: 0;
}

/* Lightbox */
/* Ein Klick in die Lücke über der Fläche schließt die Lightbox — der Zeiger
   zeigt das auf der ganzen Breite an. Innerhalb der Fläche gilt wieder der
   normale Zeiger. */
.sp-lightbox {
	cursor: pointer;
	position: fixed;
	inset: 0;
	z-index: 9000;
	display: flex;
	justify-content: center;
	align-items: flex-end;
	opacity: 0;
	transition: opacity .3s ease;
}
.sp-lightbox.is-open { opacity: 1; }
.sp-lightbox[hidden] { display: none; }

.sp-lightbox__panel {
	cursor: default;
	position: relative;
	width: 100%;
	overflow: hidden;
	transform: translateY(3%);
	transition: transform .35s cubic-bezier(.4, 0, .2, 1);
}
.sp-lightbox.is-open .sp-lightbox__panel { transform: none; }

.sp-lightbox__scroll {
	height: 100%;
	overflow-y: auto;
	/* Ohne diese Angabe rechnet der Browser overflow-x auf auto hoch, sobald
	   overflow-y gesetzt ist — der Inhalt ließe sich dann seitlich schieben. */
	overflow-x: hidden;
	overscroll-behavior: contain;
	padding: 50px 0 40px;
}
.sp-lightbox__scroll > * { max-width: 100%; }

/* Sitzt im freien Rand über der Fläche. Die Höhe entspricht dem Rand,
   damit das Kreuz darin mittig steht. */
.sp-lightbox__close {
	position: absolute;
	top: 0;
	right: var(--sp-gutter, 24px);
	z-index: 2;
	display: inline-flex;
	align-items: center;
	padding: 0 8px;
	color: #fff;
	background: none;
	border: 0;
	cursor: pointer;
	opacity: .8;
	transition: opacity .2s ease;
}
.sp-lightbox__close:hover { opacity: 1; }
.sp-lightbox__status { text-align: center; padding: 60px 20px; opacity: .7; }
body.sp-lightbox-open { overflow: hidden; }

/* =========================================================
   Inhalt
   ========================================================= */
.sp-main { padding-block: 60px; }
.sp-content > *:last-child { margin-bottom: 0; }

/* WPBakery: Full-Width-Rows brauchen einen unbeschnittenen Container. */
.sp-vc-page .sp-main { padding-block: 0; overflow: visible; }
.sp-vc-page .sp-main > .sp-container { max-width: none; padding-inline: 0; }
.vc_row.sp-row--custom-width > .vc_column_container,
.vc_row.sp-row--custom-width { --sp-grid-max: inherit; }

/* Sichtbarkeit */
.sp-col--hide-tablet,
.sp-col--hide-mobile { display: flex; }

@media (prefers-reduced-motion: reduce) {
	/* Die Ladeanimation entfällt vollständig statt im Zeitraffer abzulaufen. */
	.sp-preloader { display: none; }
	.sp-has-preloader .sp-site { animation: none; }

	*, *::before, *::after {
		animation-duration: .001ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .001ms !important;
		transition-delay: 0s !important;
	}
}
