/* ==========================================================================
   DB Digital – Stylesheet
   Mobile first. Keine Frameworks, keine jQuery-Abhängigkeiten.
   Ablösung von: stylesheet.css, aos.css, slick*.css, jquery.fancybox.min.css
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Fonts
   -------------------------------------------------------------------------- */

@font-face {
	font-family: 'Lato';
	font-style: normal;
	font-weight: 300;
	font-display: swap;
	src: url('../fonts/lato-v24-latin-300.woff2') format('woff2');
}

@font-face {
	font-family: 'Lato';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('../fonts/lato-v24-latin-regular.woff2') format('woff2');
}

@font-face {
	font-family: 'Lato';
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: url('../fonts/lato-v24-latin-700.woff2') format('woff2');
}

/*
 * DM Mono trägt ausschließlich die Kicker (30.10.2026). Ein einziger Schnitt,
 * lokal wie Lato – über `fonts.googleapis.com` bräuchte es eine Lockerung der
 * CSP, und die gehört nicht in den Livebetrieb (siehe Schriftprobe vom 03.10.).
 */
@font-face {
	font-family: 'DM Mono';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url('../fonts/dm-mono-v16-latin-500.woff2') format('woff2');
}

/* --------------------------------------------------------------------------
   2. Design-Tokens
   -------------------------------------------------------------------------- */

:root {
	/* Farben */
	--ink: #232426;
	--ink-deep: #121314;
	--ink-soft: #33353a;
	--cream: #fef9f1;
	--surface: #ffffff;
	--muted: #5d6066;
	--muted-invert: #b9bbc0;
	--line: rgba(35, 36, 38, .12);
	--line-invert: rgba(254, 249, 241, .16);

	/* Schrift der Kicker – sonst traegt Lato alles */
	--font-mono: 'DM Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;

	/* Leitfarbe der gelebten CI (dbdigital.de) */
	--gold: #f9b233;
	--gold-deep: #b26d0c;
	--gold-light: #ffd27a;

	--green: #16b079;
	--blue: #1178c7;
	--red: #ff2954;


	/* Flächen, die pro Sektion umgeschaltet werden */
	--bg: var(--ink);
	--fg: var(--cream);
	--fg-muted: var(--muted-invert);
	--hairline: var(--line-invert);

	/* Radien */
	--radius-s: 12px;
	--radius-m: 18px;
	--radius-l: 24px;
	--radius-pill: 999px;

	/* Raster */
	--shell: 1340px;
	/*
	 * Höhe des Kopfbereichs. Er liegt im Fluss über dem Hero, deshalb muss
	 * der Hero ihn abziehen, damit Kopf und Hero zusammen genau einen
	 * Bildschirm füllen. Gemessen: 98 px auf dem Desktop, 96 px auf dem
	 * Telefon. Wer Logo oder Knopf im Kopf ändert, misst nach.
	 */
	--header-h: 6.125rem;
	/*
	 * Strecke, um die der Fußbereich nach oben gezogen und sein
	 * Innenabstand erhöht wird – siehe `.site-footer`. Muss größer sein als
	 * die Sticky-Leiste samt Abstand (Telefon rund 10 rem), der Überschuss
	 * hebt sich auf.
	 */
	--cta-reserve: 12rem;
	--gutter: clamp(1.25rem, 5vw, 2.5rem);
	--section-y: clamp(3.5rem, 8vw, 6.5rem);
	--gap: clamp(.75rem, 2vw, 1.25rem);

	/* Fließende Typo */
	--step--2: clamp(.6875rem, .67rem + .1vw, .75rem);
	--step--1: clamp(.8125rem, .79rem + .12vw, .875rem);
	--step-0: clamp(1rem, .97rem + .16vw, 1.0625rem);
	--step-1: clamp(1.0625rem, 1rem + .3vw, 1.25rem);
	--step-2: clamp(1.25rem, 1.12rem + .6vw, 1.625rem);
	--step-3: clamp(1.625rem, 1.3rem + 1.5vw, 2.5rem);
	--step-4: clamp(2rem, 1.35rem + 3.1vw, 4rem);

	--transition: 320ms cubic-bezier(.22, .61, .36, 1);
}

/* --------------------------------------------------------------------------
   3. Reset
   -------------------------------------------------------------------------- */

*,
*::before,
*::after {
	box-sizing: border-box;
	margin: 0;
	padding: 0;
}

/*
 * Der Browser bringt fuer [hidden] nur `display: none` mit derselben
 * Spezifitaet mit, die jede Klasse hier auch hat – `.dialog__ways` mit
 * `display: flex` gewann und das Element blieb sichtbar, obwohl das
 * Attribut gesetzt war. Einer der wenigen Faelle, in denen !important
 * das richtige Mittel ist: `hidden` soll ausnahmslos gelten.
 */
[hidden] {
	display: none !important;
}

html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
	scroll-padding-top: 6rem;
}

body {
	background: var(--ink);
	color: var(--cream);
	font-family: 'Lato', system-ui, -apple-system, 'Segoe UI', sans-serif;
	font-size: var(--step-0);
	font-weight: 400;
	line-height: 1.65;
	overflow-x: hidden;
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
}

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

button,
input,
textarea,
select {
	font: inherit;
	color: inherit;
}

:focus-visible {
	outline: 3px solid var(--green);
	outline-offset: 3px;
	border-radius: 4px;
}

::selection {
	background: var(--gold);
	color: var(--ink);
}

/* --------------------------------------------------------------------------
   4. Typografie
   -------------------------------------------------------------------------- */

h1,
h2,
h3,
h4,
h5 {
	font-weight: 700;
	line-height: 1.08;
	text-wrap: balance;
}

h1 {
	font-size: var(--step-4);
	line-height: 1.16;
	letter-spacing: -.02em;
}

/* Signatur des Originals: dünn gesetzte Versalien mit fetter Hervorhebung */
h2 {
	font-size: clamp(2rem, 1.2rem + 3.6vw, 4rem);
	font-weight: 300;
	line-height: 1.05;
	letter-spacing: -.015em;
	text-transform: uppercase;
}

h2 b,
h2 strong {
	font-weight: 700;
}

h3 {
	font-size: var(--step-2);
}

h4,
h5 {
	font-size: var(--step-1);
}

p {
	text-wrap: pretty;
}

p + p,
p + ul,
ul + p,
h2 + p,
h3 + p,
h4 + p,
h5 + p {
	margin-top: .85em;
}

/* Kein Standard-Unterstrich: Kopfzeile, Fußzeile und Buttons sind Bedienelemente.
   Unterstrichen wird nur im Fließtext – dort trägt er zur Lesbarkeit bei. */
a {
	color: inherit;
	text-decoration: none;
	text-decoration-thickness: 1px;
	text-underline-offset: .2em;
	transition: color var(--transition), opacity var(--transition);
}

.prose a {
	font-weight: 700;
	text-decoration: underline;
}

.prose a:hover {
	color: var(--gold);
}

strong,
b {
	font-weight: 700;
}

ul {
	list-style: none;
}

.lead {
	font-size: var(--step-1);
	font-weight: 300;
	line-height: 1.5;
}

/* Laufender Verlauf auf einzelnen Wörtern. Anfangs- und Endfarbe sind
   identisch, dadurch läuft die Schleife ohne sichtbaren Sprung.
   Die reduced-motion-Regel weiter unten hält die Animation an. */
/* Die Flaeche wird auf die Schrift zugeschnitten – bei knapper Zeilenhoehe
   schneidet die Box sonst die Unterlaengen von g, j und p ab. */
.gradient-text {
	display: inline-block;
	padding-bottom: .12em;
	background: linear-gradient(90deg,
		#f9b233 0%,
		#ffd27a 20%,
		#ffffff 40%,
		#ffd27a 60%,
		#e08c1a 80%,
		#f9b233 100%);
	background-size: 300% 100%;
	-webkit-background-clip: text;
	background-clip: text;
	color: transparent;
	animation: gradient-shift 9s linear infinite;
}

@keyframes gradient-shift {
	from {
		background-position: 0 0;
	}

	to {
		background-position: -300% 0;
	}
}

/*
 * `block`, nicht `inline-block`: Die Überschrift darunter trägt
 * `.gradient-text` und ist deshalb inline-block. Als inline-block rutschte
 * der Kicker neben sie, sobald beide zusammen in eine Zeile passten – bei
 * kurzem Kickertext also plötzlich.
 */
/*
 * Einheitliche Kicker-Optik: hellgrau, klein, weit gesperrt. Bewusst kein
 * Gold – ein Kicker nennt den Rahmen, die Aussage macht die Überschrift
 * darunter. Gold würde ihn über sie stellen.
 */
.eyebrow {
	display: block;
	margin-bottom: 1rem;
	font-family: var(--font-mono);
	font-size: var(--step--1);
	font-weight: 500;
	letter-spacing: .15em;
	text-transform: uppercase;
	color: var(--muted-invert);
}

.hero .eyebrow {
	margin-bottom: 1.25rem;
}

/* --------------------------------------------------------------------------
   5. Layout-Primitive
   -------------------------------------------------------------------------- */

.shell {
	width: 100%;
	max-width: var(--shell);
	margin-inline: auto;
	padding-inline: var(--gutter);
}

/* `z-index` über dem klebenden Hero, sonst scrollten die Abschnitte
   unsichtbar darunter hinweg. */
.section {
	position: relative;
	z-index: 1;
	background: var(--bg);
	color: var(--fg);
	padding-block: var(--section-y);
}

.section--light {
	--bg: var(--cream);
	--fg: var(--ink);
	--fg-muted: var(--muted);
	--hairline: var(--line);
}

.section--dark {
	--bg: var(--ink);
	--fg: var(--cream);
	--fg-muted: var(--muted-invert);
	--hairline: var(--line-invert);
}

/*
 * Für Abschnitte, in denen etwas bewusst über die Fensterkante hinausragt
 * – hier der nach hinten geworfene Schatten der Case-Studies-Geräte.
 * `clip` statt `hidden`: `hidden` macht den Abschnitt zum Scroll-Container
 * und nimmt jedem `position: sticky` darin den Halt.
 */
.section--clip {
	overflow-x: clip;
}

/* Gleicher Verlauf wie der Hero */
.section--gradient {
	background: linear-gradient(to bottom, var(--ink) 0%, var(--ink-deep) 100%);
}

.section__head {
	max-width: 46rem;
	margin-bottom: clamp(2rem, 5vw, 3.5rem);
}

.section__head p {
	color: var(--fg-muted);
	font-size: var(--step-1);
	font-weight: 300;
}

/*
 * Ein Kicker im Abschnittskopf ist ein `p` und faengt sich sonst die drei
 * Werte darueber ein – auf `termin.php` kam er dadurch eine Schriftstufe zu
 * gross, in Gewicht 300 und in der falschen Farbe heraus. Mit Lato fiel das
 * nicht auf, weil 300 lokal vorliegt; DM Mono hat nur den Schnitt 500, und
 * der Browser rechnete sich den Rest zurecht. Dieselbe Falle wie bei
 * `.case__body .case__kicker` und `.section__head .figure-callout`:
 * Ein Element-Selektor im Kontext (0,2,0) schlaegt die Einzelklasse (0,1,0).
 */
.section__head .eyebrow {
	color: var(--muted-invert);
	font-size: var(--step--1);
	font-weight: 500;
}

/*
 * Leitsatz unter einer Abschnittsüberschrift. Er trägt die Positionierung,
 * nicht nur Kontext.
 *
 * ⚠️ Seine Darstellung kommt seit dem 04.10. aus `.figure-callout` – das
 * Element trägt **beide** Klassen. Vorher hatte er eigene Werte (`--step-1`,
 * Gewicht 700) und sah neben den Störern im SaaS-Block und unter den Case
 * Studies anders aus, obwohl er dieselbe Figur ist. Hier bleibt nur, was ihn
 * davon unterscheidet: der Abstand zur Überschrift darüber.
 */
.section__head .section__principle {
	margin-top: 1.25rem;
	text-wrap: balance;
}

.skip-link {
	position: absolute;
	inset-inline-start: 1rem;
	top: -4rem;
	z-index: 200;
	padding: .75rem 1.25rem;
	background: var(--cream);
	color: var(--ink);
	border-radius: var(--radius-pill);
	font-weight: 700;
	transition: top var(--transition);
}

.skip-link:focus-visible {
	top: 1rem;
}

[data-scroll-sentinel] {
	display: block;
	height: 1px;
	margin: 0;
}

.visually-hidden {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

/* --------------------------------------------------------------------------
   6. Buttons
   -------------------------------------------------------------------------- */

.btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: .5rem;
	min-height: 44px;
	padding: .6rem 1.6rem;
	border: 2px solid transparent;
	border-radius: var(--radius-pill);
	/*
	 * Flache Farbe statt Verlauf: Nur so lässt sich der Wechsel beim
	 * Überfahren weich animieren – Verläufe sind nicht interpolierbar.
	 * Nebenbei entfällt damit der helle Streifen, den der Verlauf am
	 * durchsichtigen Rahmen erzeugt hat.
	 */
	background-color: var(--gold);
	/* Gold ist hell – heller Text darauf käme nur auf rund 2:1 */
	color: var(--ink);
	/* Eine Stufe unter dem Fließtextmaß: Versalien mit Sperrung tragen
	   optisch weiter als ihre Punktgröße, bei `--step--1` wirkten die
	   Knöpfe schwerer als der Text daneben. `min-height: 44px` bleibt,
	   die Tastfläche ändert sich also nicht. */
	font-size: var(--step--2);
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	text-align: center;
	text-decoration: none;
	cursor: pointer;
	transition: background-color var(--transition), border-color var(--transition), color var(--transition);
}

/* Heller statt dunkler: Auf #b26d0c käme die dunkle Schrift nur auf 3,8:1,
   auf der Aufhellung sind es 11:1. */
.btn:hover {
	background-color: var(--gold-light);
	border-color: var(--gold-light);
}

.btn--outline {
	background-color: transparent;
	border-color: currentColor;
	color: inherit;
}

.btn--outline:hover {
	background-color: var(--fg);
	color: var(--bg);
}

.btn--light {
	background-color: var(--cream);
	border-color: var(--cream);
	color: var(--ink);
}

.btn--light:hover {
	background-color: transparent;
	color: var(--cream);
}

/*
 * Im WeCare/OS-Kasten kehrt sich der Knopf nicht auf Umriss um, sondern
 * wird golden. Der Kasten traegt die Farben des Produkts; ein durchsichtiger
 * Knopf verschwindet darin fast, waehrend Gold die Richtung „hier geht es
 * weiter" deutlich macht.
 *
 * Bewusst nur hier: `.btn--light` steht auch in der CTA-Leiste, und die hat
 * ihre eigene Umkehrung weiter unten.
 */
.product .btn--light:hover {
	background-color: var(--gold);
	border-color: var(--gold);
	color: var(--ink);
}

.btn-row {
	display: flex;
	flex-wrap: wrap;
	gap: .75rem;
	margin-top: 1.75rem;
}

.btn-row--center {
	justify-content: center;
}

/* --------------------------------------------------------------------------
   7. Header
   -------------------------------------------------------------------------- */

/*
 * Der Kopf schwebt als Pille über dem Inhalt – dieselbe Machart wie die
 * Leiste unten: durchscheinender Grund, feiner Rand, Unschärfe dahinter.
 * Bewusst ohne Farbwechsel beim Scrollen.
 */
.site-header {
	position: sticky;
	top: 0;
	z-index: 100;
	padding-block: 1rem;
}

/*
 * Auf schmalen Schirmen faehrt der Kopfbereich beim Runterscrollen aus dem
 * Bild (`initHeaderSlide()` in js/main.js – die Bedingungen stehen dort).
 *
 * ⚠️ Nur hier, nicht auf dem Schirm: Am Telefon ist die Hoehe knapp und der
 * Kopfbereich hat dort nur noch Logo und Menue zu tragen. Auf breiten
 * Schirmen ist das zweimal gebaut und zweimal verworfen worden.
 *
 * ⚠️ `transform`, nicht `top`: Nichts bricht neu um, die Bewegung laeuft auf
 * dem Compositor. `-100%` deckt die eigene Hoehe samt `padding-block` ab.
 */
@media (max-width: 47.99rem) {
	.site-header {
		transition: transform var(--transition);
	}

	.site-header.is-hidden {
		transform: translateY(-100%);
	}
}

/* Über dem Hero steht alles frei auf dem Bild – die Pille fährt erst
   beim Scrollen hoch. */
.site-header__bar {
	position: relative;
	display: flex;
	align-items: center;
	gap: 1rem;
	padding: .55rem .55rem .55rem 1.4rem;
	border: 1px solid transparent;
	border-radius: var(--radius-pill);
	background: transparent;
	transition:
		padding var(--transition),
		background var(--transition),
		border-color var(--transition),
		backdrop-filter var(--transition);
}

.site-header.is-stuck .site-header__bar {
	padding-block: .4rem;
	border-color: rgba(254, 249, 241, .3);
	background: rgba(18, 19, 20, .55);
	backdrop-filter: blur(18px) saturate(1.3);
	-webkit-backdrop-filter: blur(18px) saturate(1.3);
}

.site-header__logo {
	flex: none;
}

.site-header__logo img {
	width: clamp(110px, 16vw, 150px);
	transition: width var(--transition);
}

.site-header.is-stuck .site-header__logo img {
	width: clamp(100px, 13vw, 128px);
}

/*
 * ⚠️ Auf schmalen Schirmen faellt der Knopf weg – dort bleiben Logo und
 * Burger. Die Aufforderung traegt stattdessen die Leiste unten
 * (`.cta-bar__call`), die ohnehin im Bild steht. Zwei Aufforderungen auf
 * einem Telefonbildschirm sind eine zu viel.
 *
 * ⚠️ `display: none`, nicht `visibility`: Der Knopf soll keinen Platz
 * belegen und nicht in der Tabulatorreihenfolge stehen.
 */
.site-header__cta {
	display: none;
}

@media (min-width: 48rem) {
	.site-header__cta {
		display: inline-flex;
		flex: none;
		margin-left: auto;
	}
}

/*
 * Rueckweg statt Angebot: Auf den Rechtstexten steht hier ein Textlink, kein
 * Knopf – ein Knopf verspricht eine Handlung, die es dort nicht gibt.
 *
 * Die Tastflaeche kommt aus `min-height` und der Polsterung, nicht aus der
 * Schrift: 44 px wie bei den Knoepfen, damit die Zeile im Kopfbereich nicht
 * springt.
 */
.site-header__back {
	display: inline-flex;
	flex: none;
	align-items: center;
	gap: .5rem;
	min-height: 44px;
	padding-inline: .25rem;
	margin-left: auto;
	font-size: var(--step--2);
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--cream);
	transition: color var(--transition);
}

/* Winkel aus zwei Raendern – bleibt bei jeder Schriftgroesse gleich duenn,
   dieselbe Figur wie die Pfeile im Kalender. */
.site-header__back::before {
	content: '';
	width: 8px;
	height: 8px;
	border-left: 1.5px solid currentColor;
	border-bottom: 1.5px solid currentColor;
	transform: rotate(45deg);
	transition: transform var(--transition);
}

.site-header__back:hover {
	color: var(--gold);
}

.site-header__back:hover::before {
	transform: rotate(45deg) translate(2px, -2px);
}

/* Sobald die Pille steht, tritt der Knopf auf Dunkelgrau zurueck: Gold auf
   der dunklen Flaeche zog mehr Aufmerksamkeit als der Inhalt daneben.
   `--ink-soft` statt `--ink`, damit er sich von der Pille darunter
   (`rgba(18, 19, 20, .55)`) noch abhebt. Creme darauf kommt auf 11,6:1. */
.site-header.is-stuck .site-header__cta {
	background-color: color-mix(in srgb, var(--ink-soft) 70%, transparent);
	/*
	 * ⚠️ Rahmen durchsichtig lassen, nicht in derselben Farbe setzen: Die
	 * Flaeche reicht bei `background-clip: border-box` unter den Rahmen, ein
	 * halbdeckender Rahmen darueber deckt am Rand also doppelt – das liest
	 * sich als Umriss um den Knopf. Die 2 px aus `.btn` bleiben als Platz
	 * erhalten, damit die Groesse dieselbe ist wie im Hero.
	 */
	border-color: transparent;
	color: var(--cream);
}

/* Beim Ueberfahren kommt das Gold zurueck – es zeigt die Richtung, die der
   Ruhezustand jetzt zurueckhaelt.

   ⚠️ Die Spezifitaet muss die Regel darueber schlagen (0,3,0), deshalb der
   volle Selektor samt `:hover`. Ein blankes `.btn:hover` (0,2,0) verliert. */
.site-header.is-stuck .site-header__cta:hover {
	background-color: var(--gold);
	border-color: var(--gold);
	color: var(--ink);
}

/* --------------------------------------------------------------------------
   7b. Sprungmarken im Kopf
   -------------------------------------------------------------------------- */

.site-nav {
	display: flex;
	gap: clamp(1rem, 3vw, 2.25rem);
	/* Mittig zwischen Logo und Knopf, unabhängig von deren Breiten */
	position: absolute;
	left: 50%;
	transform: translateX(-50%);
}

.site-nav a {
	position: relative;
	padding-block: .35rem;
	/* Dieselbe Stufe wie die Knöpfe – Menü und Knopf stehen nebeneinander
	   im Kopfbereich und sollen gleich schwer wirken. */
	font-size: var(--step--2);
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--cream);
	white-space: nowrap;
}

/* Linie wächst von links nach rechts und zieht sich nach rechts wieder zurück */
.site-nav a::after {
	content: '';
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 1px;
	background: var(--gold);
	transform: scaleX(0);
	transform-origin: right;
	transition: transform 280ms cubic-bezier(.22, .61, .36, 1);
}

.site-nav a:hover,
.site-nav a:focus-visible,
.site-nav a.is-active {
	color: var(--gold);
}

/*
 * Der laufende Abschnitt. Die Linie waechst von links – anders als beim
 * Ueberfahren, wo sie sich nach rechts zurueckzieht. So liest sich der
 * Zustand als „steht hier", nicht als „Zeiger daneben".
 */
.site-nav a.is-active::after {
	transform: scaleX(1);
	transform-origin: left;
}

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

/* --------------------------------------------------------------------------
   7c. Schaltfläche für schmale Schirme
   -------------------------------------------------------------------------- */

.burger {
	display: none;
	/* Ohne den Knopf daneben traegt der Burger das `auto` – sonst saesse er
	   direkt neben dem Logo. */
	margin-left: auto;
	flex: none;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
	color: var(--cream);
}

/* Drei Striche aus einem Element: der mittlere ist das Element selbst */
.burger__lines,
.burger__lines::before,
.burger__lines::after {
	display: block;
	width: 20px;
	height: 2px;
	margin-inline: auto;
	border-radius: 2px;
	background: currentColor;
	transition: transform var(--transition), opacity var(--transition);
}

.burger__lines::before,
.burger__lines::after {
	content: '';
	position: absolute;
	left: 50%;
	margin-left: -10px;
}

.burger__lines::before {
	transform: translateY(-6px);
}

.burger__lines::after {
	transform: translateY(6px);
}

.burger {
	position: relative;
}

/* Im geöffneten Zustand werden daraus zwei gekreuzte Striche */
.burger[aria-expanded='true'] {
	color: var(--gold);
}

.burger[aria-expanded='true'] .burger__lines {
	transform: rotate(45deg);
}

.burger[aria-expanded='true'] .burger__lines::before {
	transform: translateY(0) rotate(90deg);
}

.burger[aria-expanded='true'] .burger__lines::after {
	opacity: 0;
}

/* Unterhalb dieser Breite wird es neben Logo und Knopf zu eng –
   die Sprungmarken wandern in ein aufklappbares Feld. Mit vier Einträgen
   blieben bei 1024px nur noch 3px Luft zum Knopf. */
@media (max-width: 67.99rem) {
	.burger {
		display: block;
	}

	.site-nav {
		position: absolute;
		top: calc(100% + .6rem);
		left: 0;
		right: 0;
		transform: none;
		flex-direction: column;
		gap: 0;
		padding: .5rem;
		border: 1px solid rgba(254, 249, 241, .3);
		border-radius: var(--radius-m);
		background: rgba(18, 19, 20, .92);
		backdrop-filter: blur(18px) saturate(1.3);
		-webkit-backdrop-filter: blur(18px) saturate(1.3);
		box-shadow: 0 18px 40px rgba(0, 0, 0, .45);

		/* Ausgeblendet ist es auch für die Tastatur nicht erreichbar */
		opacity: 0;
		visibility: hidden;
		transform: translateY(-.5rem);
		transition: opacity var(--transition), visibility var(--transition), transform var(--transition);
	}

	.site-nav.is-open {
		opacity: 1;
		visibility: visible;
		transform: translateY(0);
	}

	.site-nav a {
		padding: .75rem 1rem;
		border-radius: var(--radius-s);
		text-align: center;
	}

	/* Die mitlaufende Linie ergibt gestapelt keinen Sinn */
	.site-nav a::after {
		display: none;
	}

	.site-nav a:hover,
	.site-nav a:focus-visible {
		background: rgba(254, 249, 241, .08);
	}
}

/*
 * Kurzfassung für schmale Schirme. `.only-narrow` ist nicht das Gegenteil
 * von `.only-wide`, sondern dessen Ersatz: Das erste Wort wegzulassen
 * reicht beim Knopf im Kopfbereich nicht – „Erstberatung" allein ist noch
 * 168 px breit und schiebt den Burger bei 375 px über den Rand (391 px
 * Dokumentbreite). „Beratung" passt mit 132 px.
 */
.only-narrow {
	display: none;
}

/* Umbruchpunkt gemessen: Bis 520 px bleibt die Dokumentbreite gleich der
   Fensterbreite, bei 500 px läuft sie über. 34 rem (544 px) liegt mit
   Reserve darüber und ist derselbe Punkt wie beim Formular im Dialog. */
@media (max-width: 34rem) {
	.only-wide {
		display: none;
	}

	.only-narrow {
		display: inline;
	}
}

@media (max-width: 30rem) {
	.site-header__bar {
		padding-left: 1rem;
	}
}

/* --------------------------------------------------------------------------
   8. Hero
   -------------------------------------------------------------------------- */

/* Flex statt Grid mit place-items: center – sonst bekommt die Spalte eine
   intrinsische Breite und der prozentuale Innenabstand des Sliders wird
   zirkulär, was auf schmalen Schirmen die Seite seitlich überlaufen lässt. */
/*
 * Der Hero bleibt beim Scrollen stehen und wird vom nächsten Abschnitt
 * zugedeckt – 1:1 wie auf der WeCare/OS-Website (dort `.hero.dark`).
 * `z-index: 0` ist die Grundlage dafür: Alles, was ihn zudecken soll,
 * braucht eine höhere Stufe (siehe `.section`, `.site-footer`).
 */
.hero {
	position: sticky;
	top: 0;
	z-index: 0;
	display: flex;
	flex-direction: column;
	justify-content: center;
	/*
	 * Mindestens ein voller Bildschirm, abzüglich des Kopfbereichs darüber.
	 * `svh` statt `vh`: Auf dem Telefon rechnet `vh` mit eingeklappter
	 * Adressleiste, der Hero ragte dadurch beim Laden unter den Rand.
	 * Kein Deckel mehr – der ließ auf hohen Schirmen Luft unter dem Hero.
	 */
	min-height: calc(100svh - var(--header-h));
	/*
	 * Unten der Kopfbereich zusätzlich, oben nicht. Der Hero beginnt erst
	 * unter dem Kopf; wäre der Abstand symmetrisch, läge die Mitte des
	 * Inhalts um dessen halbe Höhe unter der Bildschirmmitte. Mit dem
	 * Aufschlag unten landet sie genau in der Mitte des Fensters.
	 * Gesamthöhe bleibt dabei etwa gleich, weil der Grundwert kleiner ist.
	 */
	padding-block: clamp(2rem, 5vw, 3rem) calc(clamp(2rem, 5vw, 3rem) + var(--header-h));
	background: linear-gradient(to bottom, var(--ink) 0%, var(--ink-deep) 100%);
	text-align: center;
}

.hero__inner {
	width: 100%;
	/* Breiter als der übrige Textkörper, damit der Claim zweizeilig bleibt.
	   Überschrift und Kicker darüber sind kurz und zentriert – sie merken
	   von der Breite nichts. */
	max-width: 56rem;
	margin-inline: auto;
}

.hero h1 {
	margin-bottom: 1.25rem;
}

/*
 * Auf dem Telefon traegt die H1 den Hero (31.10.2026). `--step-4` ergibt dort
 * 33 px und bleibt einzeilig – neben dem Claim darunter wirkte die Marke
 * dadurch kleiner als der Satz, der sie erklaert.
 *
 * Der Wert ist so gewaehlt, dass „Digitale Lösungen" sicher umbricht: Bei
 * 375 px Fensterbreite misst die Zeile einzeilig 254 px, die Spalte bietet
 * 335 – ab rund 44 px Schriftgroesse bricht sie. Die 14.4vw liegen mit 54 px
 * deutlich darueber, der Deckel bei 3.75 rem haelt grosse Telefone in Zaum.
 *
 * ⚠️ Nur unter 48 rem. Auf dem Schirm steht die H1 neben einem breiteren
 * Claim und darf ihn nicht ueberragen.
 */
@media (max-width: 47.99rem) {
	.hero h1 {
		font-size: clamp(2.75rem, 14.4vw, 3.75rem);
		margin-bottom: 1rem;
	}
}

.hero__claim {
	/* Eine Spur unter --step-2: Bei voller Stufe fällt der Satz auf
	   mittleren Breiten in eine dritte Zeile. An die Stufe gekoppelt,
	   damit er die Skala weiter mitmacht. */
	font-size: calc(var(--step-2) * .92);
	/* Nicht fett: Bei dieser Größe trägt der Satz von selbst, fett würde
	   er mit der Überschrift darüber konkurrieren. */
	font-weight: 400;
	color: var(--cream);
	/* Ohne das reißt der längere Satz auf mittleren Breiten in eine
	   sehr kurze letzte Zeile auf. */
	text-wrap: balance;
}

/*
 * Inhalt des Heros verblasst und verschwimmt, während er zugedeckt wird.
 * Übernommen von der WeCare/OS-Website (`hero-weicht`). Animiert werden
 * die Kinder, nicht der Hero selbst – sonst verschwände auch sein dunkler
 * Grund und die Abschnitte darunter blitzten durch.
 *
 * Die Unschärfe beginnt fast sofort und ist bei halber Strecke voll da;
 * die Deckkraft folgt später, damit der verschwommene Hero eine Weile
 * sichtbar bleibt, statt einfach zu verschwinden.
 *
 * Ohne `animation-timeline` (derzeit Firefox) bleibt der Hero scharf
 * stehen – das ist der Rückfall, kein Fehler.
 */
@supports (animation-timeline: view()) {
	.hero > * {
		animation: hero-weicht linear both;
		animation-timeline: scroll(root block);
		animation-range: 0 78vh;
	}

	@keyframes hero-weicht {
		12% { opacity: 1; transform: none; filter: blur(0); }
		55% { opacity: .85; filter: blur(10px); }
		100% { opacity: 0; transform: translateY(-28px) scale(.975); filter: blur(16px); }
	}

	/* Die allgemeine Regel am Dateiende greift hier nicht: Bei einer
	   scrollgesteuerten Animation bestimmt die Strecke den Ablauf, nicht
	   die Dauer. Deshalb hier ausdrücklich abschalten. */
	@media (prefers-reduced-motion: reduce) {
		.hero > * {
			animation: none;
		}
	}
}

/* Showcase-Slider: reine CSS-Snap-Spur, JS steuert nur Autoplay + Dots */
.showcase {
	width: 100%;
	margin-top: clamp(2.5rem, 6vw, 4rem);
}

.showcase__viewport {
	position: relative;
}

/* Dünne Pfeile ganz außen, vertikal auf Höhe der Bilder */
.showcase__arrow {
	position: absolute;
	top: 50%;
	z-index: 3;
	width: 48px;
	height: 48px;
	display: grid;
	place-items: center;
	transform: translateY(-50%);
	border: 0;
	background: none;
	cursor: pointer;
	color: var(--cream);
	opacity: .45;
	transition: opacity var(--transition);
}

.showcase__arrow:hover {
	opacity: 1;
}

.showcase__arrow--prev {
	left: max(.25rem, calc(var(--gutter) - 1rem));
}

.showcase__arrow--next {
	right: max(.25rem, calc(var(--gutter) - 1rem));
}

/* Winkel aus zwei Rändern – bleibt bei jeder Größe gleich dünn */
.showcase__arrow span {
	width: 15px;
	height: 15px;
	border-top: 1.5px solid currentColor;
	border-right: 1.5px solid currentColor;
}

.showcase__arrow--prev span {
	transform: rotate(-135deg);
	margin-left: 5px;
}

.showcase__arrow--next span {
	transform: rotate(45deg);
	margin-right: 5px;
}

.showcase__track {
	display: flex;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	-ms-overflow-style: none;
	overscroll-behavior-x: contain;
	gap: clamp(1rem, 3vw, 2rem);
	/* Seitliches Polster zentriert die aktive Folie, die Nachbarn bleiben angeschnitten */
	padding-inline: calc(50% - min(300px, 38vw));
}

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

/*
 * Zeigegeräte: keine eigene Scroll-Spur. Das Mausrad über dem Hero gehört der
 * Seite – ein horizontal scrollbarer Container nimmt sonst den waagerechten
 * Anteil der Radbewegung an, der Snap zieht ihn zurück, und das Scrollen
 * stockt. Programmatisch bleibt die Spur scrollbar: `scrollLeft` wirkt auch
 * bei `overflow: hidden`, Pfeile und Punkte arbeiten unverändert.
 *
 * Bewusst nach Eingabeart und nicht nach Breite: Auf Touchgeräten bleibt die
 * Spur scrollbar, dort ist Wischen der einzige Weg zwischen den Folien.
 */
@media (hover: hover) and (pointer: fine) {
	.showcase__track {
		overflow-x: hidden;
	}
}

.showcase__slide {
	position: relative;
	flex: 0 0 min(600px, 76vw);
	scroll-snap-align: center;
	opacity: .16;
	transition: opacity 600ms ease;
}

.showcase__slide.is-current {
	opacity: 1;
}

/*
 * Pille für Kurzhinweise – „iOS/Android App", „Eigenentwicklung".
 * Bewusst kein Gold und keine volle Fläche: Sie beschriftet, sie fordert
 * nicht zum Klicken auf und soll nicht wie ein Knopf wirken.
 */
.badge {
	display: inline-flex;
	align-items: center;
	gap: .5rem;
	padding: .32rem .85rem;
	border: 1px solid rgba(254, 249, 241, .4);
	border-radius: var(--radius-pill);
	background: rgba(18, 19, 20, .5);
	backdrop-filter: blur(8px);
	-webkit-backdrop-filter: blur(8px);
	color: var(--cream);
	font-family: var(--font-mono);
	font-size: var(--step--2);
	font-weight: 500;
	letter-spacing: .1em;
	text-transform: uppercase;
	white-space: nowrap;
}

/*
 * Störer und Store-Abzeichen im Slider. Beide sitzen am Telefon, nicht am
 * Bild: Die Prozentwerte kommen aus der Mockup-Geometrie (siehe
 * _FILES/build-mockups.py) – Telefon 943..1252 von 1280 Breite,
 * Oberkante 135 und Unterkante 789 von 820 Höhe.
 *
 * Das Aussehen der Pille kommt aus `.badge`, hier steht nur die Lage.
 */
.showcase__badge {
	position: absolute;
	top: 16%;
	left: 91%;
	/* Ohne das begrenzt der Browser die Breite auf den Platz rechts von
	   `left` – bei 91 % sind das 9 % der Folie, und der Stoerer rutscht
	   dadurch sichtbar nach links. Dieselbe Falle wie bei den
	   Store-Abzeichen darunter. */
	width: max-content;
	transform: translate(-50%, -50%) scale(var(--flag-scale, 1));
	z-index: 2;
}

/*
 * Abzeichen nebeneinander am unteren Ende des Telefons. Mittig auf dessen
 * Achse (85,7 % der Bildbreite), nicht an der rechten Kante ausgerichtet –
 * als Paar sind sie breiter als das Gerät und stünden sonst schief.
 */
.showcase__stores {
	position: absolute;
	left: 85.7%;
	bottom: 5%;
	z-index: 2;
	/* Ohne das begrenzt der Browser die Breite auf den Platz rechts von
	   `left` – die beiden Abzeichen würden zusammengestaucht. */
	width: max-content;
	transform: translateX(-50%) scale(var(--flag-scale, 1));
	transform-origin: bottom center;
}

.showcase__stores .store-links {
	gap: .5rem;
}

/*
 * Störer und Abzeichen haben feste Maße, die Folie schrumpft mit dem
 * Fenster – ohne Skalierung decken sie auf dem Telefon das halbe Bild ab.
 */
@media (max-width: 64rem) {
	.showcase {
		--flag-scale: .8;
	}
}

@media (max-width: 48rem) {
	.showcase {
		--flag-scale: .6;
	}
}

.store-links {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 1.125rem;
}

.store-link {
	display: inline-flex;
	transition: opacity var(--transition);
}

.store-link:hover,
.store-link:focus-visible {
	opacity: .8;
}

.store-link img {
	display: block;
	height: 1.95rem;
	width: auto;
}

/* Erst ab dieser Breite ist im Ausschnitt Platz, den Störer auf das Telefon
   zu rücken – darunter bliebe er sonst halb außerhalb der Folie. */
@media (min-width: 48rem) {
	.showcase__badge {
		left: 91%;
	}
}

.showcase__slide img {
	width: 100%;
	border-radius: var(--radius-s);
}

.hero__logos {
	padding-inline: var(--gutter);
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: clamp(1.25rem, 4vw, 2.5rem);
	margin-top: clamp(2rem, 5vw, 3rem);
}

.hero__logos img {
	height: 26px;
	width: auto;
	/* Logos liegen in gemischten Farben vor – einheitlich weiß statt bunt */
	filter: brightness(0) invert(1);
	opacity: .75;
}

.showcase__dots {
	display: flex;
	justify-content: center;
	gap: 0;
	margin-top: 1.25rem;
}

/*
 * Kurze Pillen statt runder Punkte, wie unter den Case Studies. Die
 * Tastflaeche kommt aus Hoehe und Polsterung des Knopfs, nicht aus der
 * Pille: 18 + 2x3 px sind die 24 px, die WCAG 2.5.8 verlangt.
 */
.showcase__dot {
	height: 40px;
	padding-inline: 3px;
	display: grid;
	place-items: center;
	background: none;
	border: 0;
	cursor: pointer;
}

.showcase__dot::before {
	content: '';
	width: 18px;
	height: 5px;
	border-radius: 999px;
	background: var(--muted-invert);
	opacity: .45;
	/* Die Breite waechst statt `transform: scale()` – ein skalierter Strich
	   wuerde auch dicker, und die Pille soll ihre Staerke behalten. */
	transition: width var(--transition), opacity var(--transition),
		background var(--transition);
}

.showcase__dot[aria-current='true']::before {
	width: 30px;
	background: var(--gold);
	opacity: 1;
}

/* --------------------------------------------------------------------------
   9. Leistungskarten
   -------------------------------------------------------------------------- */

.cards {
	display: grid;
	gap: var(--gap);
	grid-template-columns: 1fr;
}

@media (min-width: 40rem) {
	.cards {
		grid-template-columns: repeat(2, 1fr);
	}

	.card--feature {
		grid-column: 1 / -1;
	}
}

/* Original-Anordnung: zwei Karten links, die hohe Karte mittig, zwei rechts.
   Im Markup steht die hohe Karte zuerst – Lesereihenfolge vor Optik. */
@media (min-width: 64rem) {
	.cards {
		grid-template-columns: repeat(3, 1fr);
		grid-auto-rows: 1fr;
	}

	.card--feature {
		grid-column: 2;
		grid-row: 1 / span 2;
	}

	.card:nth-of-type(2) {
		grid-column: 1;
		grid-row: 1;
	}

	.card:nth-of-type(3) {
		grid-column: 1;
		grid-row: 2;
	}

	.card:nth-of-type(4) {
		grid-column: 3;
		grid-row: 1;
	}

	.card:nth-of-type(5) {
		grid-column: 3;
		grid-row: 2;
	}
}

.card {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 1rem;
	padding: clamp(1.75rem, 3vw, 2.5rem);
	background: var(--surface);
	color: var(--ink);
	border-radius: var(--radius-m);
	height: 100%;
	text-align: center;
}

.card img {
	width: 60px;
	height: 60px;
	/* Der Bestand ist gemischt eingefärbt – hier soll alles schwarz wirken */
	filter: brightness(0);
}

.card p {
	color: var(--muted);
	font-size: var(--step-0);
}


/* --------------------------------------------------------------------------
   10. SaaS-Ablösung
   -------------------------------------------------------------------------- */

.split {
	display: grid;
	gap: clamp(2rem, 5vw, 4rem);
	align-items: start;
}

@media (min-width: 60rem) {
	.split {
		grid-template-columns: 1.25fr 1fr;
	}
}

.figure-callout {
	font-size: var(--step-2);
	font-weight: 300;
	line-height: 1.35;
	padding-left: 1.25rem;
	border-left: 3px solid var(--gold);
}

.figure-callout strong {
	font-weight: 700;
}

/*
 * Folgt dem Stoerer ein Absatz, braucht er mehr Luft als die uebliche
 * Absatzschaltung: `p + p` rechnet `.85em` der **eigenen** Groesse, also der
 * des Fliesstexts – gemessen 14 px unter einer 24-px-Zeile. Der Stoerer ist
 * eine eigene Aussage, kein Satzanfang.
 */
.figure-callout + p {
	margin-top: 1.75rem;
}

/*
 * Derselbe Stoerer im Abschnittskopf (Case Studies).
 *
 * ⚠️ Der doppelte Kontext ist noetig: `.section__head p` (0,2,0) schlaegt die
 * Einzelklasse (0,1,0) und wuerde Groesse und Farbe zurueckdrehen – dieselbe
 * Falle wie bei `.section__principle`.
 */
.section__head .figure-callout {
	font-size: var(--step-2);
	color: inherit;
}

.check-list {
	display: grid;
	gap: .6rem;
	margin-top: 1rem;
}

.check-list li {
	position: relative;
	padding-left: 1.9rem;
	color: var(--fg-muted);
}

/* Haken aus zwei Rändern statt einer Symboldatei – skaliert mit der Schrift */
.check-list li::before {
	content: '';
	position: absolute;
	left: .2rem;
	top: .35em;
	width: .42rem;
	height: .78rem;
	border-right: 2px solid var(--cream);
	border-bottom: 2px solid var(--cream);
	transform: rotate(45deg);
}

.stack-gap {
	display: grid;
	gap: 2rem;
}

/* --------------------------------------------------------------------------
   11. Produkt-Block (WeCare/OS)
   -------------------------------------------------------------------------- */

/*
 * Hintergrund 1:1 von der WeCare/OS-Website übernommen (dort `.dark`,
 * Website/public/css/site.css). Das Produkt bringt sein eigenes Farbklima
 * mit – genau dafür ist der Block da. Wer hier etwas ändert, sollte es
 * dort mit ändern, sonst driften Firma und Produkt auseinander.
 *
 * `clip` statt `hidden`: Beides schneidet die Verlaufsebenen an den
 * runden Ecken ab, `hidden` macht den Kasten aber zum Scroll-Container.
 */
.product {
	position: relative;
	overflow: clip;
	display: grid;
	gap: clamp(1.5rem, 4vw, 3rem);
	padding: clamp(1.75rem, 4vw, 3.5rem);
	border: 1px solid var(--hairline);
	border-radius: var(--radius-l);
	background: #1b1a19;
}

.product::before {
	content: '';
	position: absolute;
	inset: 0;
	background:
		radial-gradient(60% 80% at 12% 8%, rgba(105, 92, 165, .55) 0%, transparent 62%),
		radial-gradient(55% 70% at 88% 22%, rgba(234, 81, 151, .42) 0%, transparent 60%),
		radial-gradient(50% 60% at 72% 96%, rgba(245, 158, 94, .34) 0%, transparent 62%),
		/*
		   Auf der WeCare/OS-Website steht `cover`. Dort ist der Hero fast
		   so hoch wie breit, hier ist der Kasten flach – `cover` würde
		   genau die farbigen Ränder des Bildes abschneiden und nur die
		   dunkle Mitte zeigen. Gezerrt statt beschnitten: Bei einem
		   Verlauf fällt die Verzerrung nicht auf, die Farbe schon. */
		url('../images/wecare-os-bg.webp') 0 0 / 100% 100% no-repeat;
	opacity: .95;

	/* Der Verlauf atmet: Lage und Deckkraft wandern langsam, die Farben
	   bleiben unverändert. Nur transform und opacity – beides läuft im
	   Compositor und kostet keine Layoutrunde. Bei reduzierter Bewegung
	   schaltet die Regel am Dateiende sie ab. */
	animation: wecare-verlauf 26s ease-in-out infinite;
	will-change: transform, opacity;
}

@keyframes wecare-verlauf {
	0%, 100% { transform: none; opacity: .9; }
	35% { transform: scale(1.07) translate3d(1.6%, -1.2%, 0); opacity: 1; }
	70% { transform: scale(1.04) translate3d(-1.4%, .8%, 0); opacity: .94; }
}

/* Legt sich über den Verlauf, damit der Text überall Kontrast behält. */
.product::after {
	content: '';
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, rgba(27, 26, 25, .55) 0%, rgba(27, 26, 25, .34) 45%, rgba(27, 26, 25, .8) 100%);
}

/* Hebt den Inhalt über beide Verlaufsebenen. */
.product > * {
	position: relative;
	z-index: 1;
}

@media (min-width: 60rem) {
	.product {
		grid-template-columns: 1fr 1fr;
		align-items: center;
	}
}

.product__media img {
	width: 100%;
	height: auto;
}

/*
 * Logo statt gesetztem Schriftzug. Bleibt ein <h2>, damit der Abschnitt
 * über `aria-labelledby` weiter einen Namen hat – den liefert jetzt der
 * Alternativtext des Bildes.
 */
.product__badge {
	margin-bottom: 1rem;
}

.product__logo {
	margin-bottom: .75rem;
}

/*
 * Steht unter dem Logo und gehört zu ihm, nicht zum Fließtext darunter –
 * deshalb der kleine Abstand nach oben und der normale nach unten. Fett,
 * aber ohne die goldene Linie des Leitsatzes: Der Kasten trägt die Farben
 * von WeCare/OS, Gold gehört DB Digital.
 */
.product__note {
	margin-top: 0;
	font-weight: 700;
	text-wrap: balance;
}

/* Der Produktsatz rückt näher heran: `p + p` setzt `.85em` seiner eigenen
   Größe an, und die ist hier `--step-2` – das ergab 22 px und löste die
   Zeile vom Logoblock ab. */
.product__note + .product__quote {
	margin-top: .75rem;
}

.product__logo img {
	display: block;
	width: min(100%, 17rem);
	height: auto;
}

.product__quote {
	font-size: var(--step-2);
	font-weight: 300;
	font-style: italic;
	line-height: 1.35;
}

/* --------------------------------------------------------------------------
   12. Referenzen
   -------------------------------------------------------------------------- */

.cases {
	display: grid;
	gap: clamp(3rem, 9vw, 6rem);
}

/*
 * Keine farbigen Flächen mehr: Text und Geräte stehen frei auf dem
 * Abschnittsgrund. Die Farbe kam vorher aus --accent, das entfällt.
 */
.case {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: clamp(1.5rem, 4vw, 3.5rem);
	color: var(--fg);
}

.case__media,
.case__body {
	width: 100%;
}

.case__media {
	position: relative;
	/* Platz fuer den Schatten unter dem schwebenden Geraet. */
	padding-block: 2% 8%;
}

/*
 * Das Geraet bringt seine Perspektive mit – das Bild ist ein freigestelltes
 * iPad, in das der Screenshot hineingerechnet wurde (siehe
 * _FILES/build-mockups.py). Das CSS dreht deshalb **nichts** mehr.
 *
 * Fruehere Fassungen drehten eine flache Grafik per `rotateX/Y/Z`. Das sah
 * nie nach Geraet aus: Die Kante bleibt dabei ueberall gleich breit, die
 * Ecken verjuengen sich nicht, und das Licht wandert nicht mit. Genau das
 * macht den Unterschied zwischen „gekippt" und „fotografiert".
 *
 * Gespiegelt wird ueber eine **eigene Bilddatei** (`-tablet-flip.webp`),
 * nicht ueber `scaleX(-1)` – das spiegelte den Screenshot mit und die
 * Schrift stuende seitenverkehrt.
 *
 * `drop-shadow` folgt der Alphakante des Bildes, nicht seinem Rechteck –
 * der Schatten nimmt also die Geraetesilhouette an, inklusive Perspektive.
 */
.case__tablet {
	width: 100%;
	filter: drop-shadow(0 30px 40px rgba(0, 0, 0, .55));
}

/*
 * Drei Ansichten hinter einem gemeinsamen Geraeterahmen.
 *
 * Der Rahmen hat dort, wo der Bildschirm sitzt, ein Loch; jede Slide ist
 * beim Bauen bereits perspektivisch in genau diese Flaeche gerechnet und
 * ausserhalb durchsichtig. Deshalb liegen sie einfach uebereinander – kein
 * `clip-path`, kein `mask-image`, keine Perspektive im CSS.
 *
 * Der Schatten sitzt am Rahmen, nicht am Stapel: Er folgt der Alphakante,
 * und die gehoert dem Geraet.
 */
.case__screen {
	position: relative;
}

.case__slides {
	position: absolute;
	inset: 0;
	margin: 0;
	padding: 0;
	list-style: none;
}

.case__slide {
	position: absolute;
	inset: 0;
	opacity: 0;
	transition: opacity .6s ease;
}

.case__slide.is-current {
	opacity: 1;
}

.case__slide img {
	display: block;
	width: 100%;
}

/*
 * Die Prozess-Symbole liegen flach ueber dem Geraet, ohne Perspektive –
 * deshalb als eigenes SVG im Browser und nicht ins Bild gerechnet. Es
 * bleibt dadurch vektorscharf und bei jeder Groesse lesbar.
 *
 * `z-index: 2` hebt es ueber den Rahmen: Der steht im Dokument nach den
 * Slides und laege sonst darauf.
 */
.case__overlay {
	position: absolute;
	inset: 0;
	z-index: 2;
}

/* Liegt ueber den Slides. `pointer-events: none`, damit der Rahmen keine
   Klicks schluckt – bedient wird ueber die Punkte darunter. */
.case__frame {
	position: relative;
	display: block;
	width: 100%;
	pointer-events: none;
	filter: drop-shadow(0 30px 40px rgba(0, 0, 0, .55));
}

/*
 * Ohne JavaScript braucht es keine Sonderregel: Die erste Slide traegt
 * `is-current` schon im Markup und ist damit sichtbar, die uebrigen
 * bleiben durchsichtig, und die Punkte bleiben `hidden`. Der Rahmen gibt
 * die Hoehe vor – er ist das einzige Element im Fluss.
 *
 * Ein erster Anlauf stellte den Stapel hier auf `position: static`. Damit
 * standen Slides und Rahmen untereinander statt uebereinander.
 */

/*
 * Mittig zur Seite, nicht zur Grafik: Die laeuft ueber die `.shell` hinaus
 * nach aussen (`--case-bleed`) und sitzt dadurch versetzt – Punkte in ihr
 * waeren sichtbar aus der Seitenmitte gerueckt. Bezug ist deshalb der
 * Artikel, der die volle Shell-Breite hat.
 *
 * Gestapelt (unter 60 rem) steht die Leiste als eigene Zeile im Fluss –
 * `.case` ist dort `flex-wrap: wrap`, das dritte Kind bricht also um.
 */
.case {
	position: relative;
}

.case__dots {
	position: relative;
	z-index: 3;
	flex: 0 0 100%;
	display: flex;
	justify-content: center;
	gap: .25rem;
	/* Naeher ans Geraet: Die Medienspalte polstert unten 8 % fuer den
	   Schatten, ohne Ausgleich stuenden die Punkte am Ende davon. */
	margin-top: -1.5rem;
}

/*
 * Keine runden Punkte wie unter dem Hero, sondern kurze Pillen. Die
 * Tastflaeche kommt aus der Hoehe des Knopfs und seiner Polsterung, nicht
 * aus der Pille selbst: 18 + 2x3 px sind die 24 px, die WCAG 2.5.8
 * verlangt.
 */
.case__dot {
	height: 28px;
	padding-inline: 3px;
	display: grid;
	place-items: center;
	border: 0;
	background: none;
	cursor: pointer;
}

.case__dot::before {
	content: '';
	width: 18px;
	height: 5px;
	border-radius: 999px;
	background: var(--muted-invert);
	opacity: .4;
	/* Die Breite waechst statt `transform: scale()` – ein skalierter Strich
	   wuerde auch dicker, und die Pille soll ihre Staerke behalten. */
	transition: width var(--transition), opacity var(--transition),
		background var(--transition);
}

.case__dot:hover::before {
	opacity: .7;
}

.case__dot[aria-current='true']::before {
	width: 30px;
	background: var(--gold);
	opacity: 1;
}

@media (min-width: 60rem) {
	/*
	 * Zwei Spalten. Die Grafik laeuft zur Aussenseite ueber das Textmass
	 * der .shell hinaus.
	 *
	 * Wie weit, haengt vom Fenster ab: Neben der .shell liegen
	 * (100vw - --shell) / 2 freier Rand plus der Seitenabstand innen. So
	 * weit darf verschoben werden, abzueglich 1 rem Luft.
	 *
	 * Der Deckel liegt bei 12 rem. Fruehere Fassungen standen bei 6 rem und
	 * brauchten 2 rem Sicherheitsabstand – damals kippte die Geraetekante
	 * per CSS-Perspektive nach aussen und waere sonst ueber die Fensterkante
	 * gewachsen. Seit die Perspektive im Bild steckt, endet das Geraet genau
	 * an seiner Bildkante, und der Ueberstand darf groesser ausfallen.
	 */
	.case {
		--case-bleed: max(0px, min(12rem, calc((100vw - var(--shell)) / 2 + var(--gutter) - 1rem)));

		/*
		 * Der Text rueckt in die leere Ecke der Grafik hinein.
		 *
		 * Das Geraet ist ein gedrehtes Rechteck: Sein Bildrahmen sitzt eng,
		 * aber oben und unten an der Textseite liegt nur Luft. Ohne
		 * Ueberlappung klafft dort eine Luecke, die wie ein Fehler aussieht,
		 * obwohl beide Spalten korrekt aneinanderstossen.
		 *
		 * Realisiert als negativer Aussenabstand an der Grafik: Der
		 * verkleinert nur ihren Platzbedarf, das Bild selbst bleibt voll
		 * sichtbar und der Text beginnt frueher.
		 */
		/* Nachgemessen: Bei 1150 px faengt sie an (darunter braucht die
		   Textspalte jeden Pixel), bei 1440 liegt sie bei rund 87 px, ab
		   etwa 1520 px greift der Deckel von 7 rem. */
		--case-overlap: max(0px, min(7rem, calc((100vw - 1150px) * .3)));

		flex-wrap: nowrap;

		/*
		 * Kein Abstand im Fluss: Der Ueberstand nach aussen schiebt die
		 * Grafik ohnehin vom Text weg, ein zusaetzlicher Abstand summierte
		 * sich darauf und riss eine sichtbare Luecke auf. Der Rahmen im
		 * Mockup laesst zudem rund 3 % Luft an jeder Bildkante.
		 */
		gap: 0;
	}

	/*
	 * ⚠️ Ab hier steht `.case` auf `flex-wrap: nowrap`. Eine Punktleiste
	 * mit `flex: 0 0 100%` bliebe dann **in derselben Zeile** und
	 * quetschte Grafik und Text auf einen Rest zusammen – genau so
	 * passiert am 02.10. Sie muss deshalb aus dem Fluss heraus.
	 *
	 * `bottom: 0` am Artikel trifft die Unterkante der Mediensspalte: Die
	 * Grafik ist das hoehere der beiden Kinder und gibt die Hoehe vor, ihr
	 * unteres Polster (8 %) traegt den Schatten – dort sitzt die Leiste.
	 */
	.case__dots {
		position: absolute;
		/* Ueber das Overlay der dritten Ansicht (z-index: 2) – sonst faengt
		   das SVG die Klicks ab und die Leiste ist nicht mehr bedienbar. */
		z-index: 3;
		inset-inline: 0;
		/*
		 * Grundwert waere 1,5 rem – das setzt die Leiste 24 px unter die
		 * Geraetekante. Die 128 px heben sie um glatte 100 px darueber.
		 *
		 * Nicht 100 px rechnen und 100 px erwarten: Der Bezug ist das Ende
		 * des Artikels, nicht die Geraetekante, und dazwischen liegen die
		 * 8 % Polsterung der Medienspalte plus die Hoehe der Leiste selbst.
		 */
		bottom: calc(1.5rem + 128px);
		flex: none;
		margin-top: 0;
	}

	.case--flip {
		flex-direction: row-reverse;
	}

	.case__media {
		/* Das Geraet traegt den Abschnitt, der Text begleitet ihn. */
		flex: 1 1 64%;
		width: auto;
		margin-inline-end: calc(-1 * var(--case-overlap));
		/*
		 * Der Ueberstand laeuft ueber `left`, nicht ueber einen negativen
		 * Aussenabstand: Ein negativer `margin-right` verschiebt das letzte
		 * Flex-Element nicht, er verkleinert nur dessen Platzbedarf.
		 */
		left: calc(-1 * var(--case-bleed));
	}

	.case--flip .case__media {
		left: var(--case-bleed);
		margin-inline-end: 0;
		margin-inline-start: calc(-1 * var(--case-overlap));
	}

	.case__body {
		flex: 1 1 36%;
		width: auto;
		/* Ueber der Grafik, nicht dahinter – die Ecke ist leer, der Text
		   darf hinein. */
		position: relative;
		z-index: 1;
	}
}

/*
 * Erst ab 75 rem darf die Grafik dominieren. Darunter braucht die
 * Textspalte den Platz: Bei 72/28 blieben ihr auf einem 1024er Schirm
 * 295 px, also knapp 38 Zeichen je Zeile – das liest sich nicht mehr.
 */
@media (min-width: 75rem) {
	.case__media {
		flex: 1 1 72%;
	}

	.case__body {
		flex: 1 1 28%;
	}
}


.case__body h3 {
	margin-bottom: .5rem;
}

/*
 * Kundenlogo statt gesetztem Namen. Bleibt ein <h3>, damit die Fallstudie
 * ihre Ueberschrift behaelt – den Namen liefert der Alternativtext des
 * Bildes. Gleiches Muster wie beim WeCare/OS-Logo im Produktkasten.
 *
 * Hoehe statt Breite vorgeben: Die drei Logos haben sehr verschiedene
 * Seitenverhaeltnisse (6,7:1 bis 2,5:1). Auf gleiche Breite gebracht
 * waere das eine winzig und das andere riesig; auf gleiche Hoehe gebracht
 * wirken sie gleich gewichtig.
 */
.case__logo {
	margin-bottom: .9rem;
}

.case__logo img {
	display: block;
	height: clamp(1.8rem, 2.6vw, 2.4rem);
	width: auto;
	max-width: 100%;
}

/*
 * Kompakte Logos wirken bei gleicher Hoehe kleiner als breite – g-lab
 * steht neben Another Cotton und B2Bgator sonst verloren. Hier gibt
 * deshalb die Breite das Mass vor, nicht die Hoehe.
 *
 * Muss NACH `.case__logo img` stehen: Beide Selektoren sind (0,1,1), bei
 * gleicher Spezifitaet entscheidet die Reihenfolge.
 */
.case__logo--wide img {
	width: 120px;
	height: auto;
}

/* Gleiche Optik wie `.eyebrow` – eigener Name, weil er im Textblock der
   Fallstudie sitzt und dort einen anderen Abstand nach unten braucht.
   Der doppelte Klassenselektor ist Pflicht: `.case__body p` setzt sonst
   `--step-0` und der Kicker käme eine Stufe zu groß heraus. */
.case__body .case__kicker {
	margin-bottom: .9rem;
	font-family: var(--font-mono);
	font-size: var(--step--1);
	font-weight: 500;
	letter-spacing: .15em;
	text-transform: uppercase;
	color: var(--muted-invert);
}

.case__body p {
	font-size: var(--step-0);
}

/* Lösung und Ergebnis stehen seit dem 04.10. als zwei schlichte Absätze da,
   ohne die Rubriken „Lösung" und „Ergebnis" davor – die Definitionsliste und
   ihre Regeln sind damit entfallen. Der Kicker über dem Namen trägt die
   Einordnung. */
.case__body p + p {
	margin-top: .9rem;
}

/* Die Einschraenkung eine Stufe kleiner – sie gehoert zum Satz, soll ihn aber
   nicht gleich schwer wiegen.

   ⚠️ Eine Einzelklasse genuegt hier: `.case__body p` (0,2,0) zielt auf den
   Absatz, dieses `span` erbt von ihm nur. Eine direkte Regel schlaegt
   Vererbung immer – unabhaengig von der Spezifitaet. */
.case__small {
	font-size: var(--step--1);
}

/* --------------------------------------------------------------------------
   13. Footer
   -------------------------------------------------------------------------- */

.site-footer {
	position: relative;
	z-index: 1;
	/*
	 * Zieht den Fußbereich über den Streifen, in dem die Sticky-Leiste im
	 * Fluss steht. Der hatte keinen eigenen Hintergrund – der klebende Hero
	 * schien dort als dunkles Band durch (sein Verlauf endet bei #121314,
	 * ringsum liegt #232426). Der Innenabstand gleicht den Zug wieder aus,
	 * die Seite wird dadurch nicht kürzer; der Wert muss nur größer sein als
	 * der Streifen, der Überschuss hebt sich auf.
	 *
	 * Die Leiste bleibt sichtbar: Sie trägt `z-index: 90`, der Fußbereich 1.
	 */

	background: var(--ink);
	color: var(--cream);
	/* Eine Stufe unter dem Fließtext – der Fußbereich ist Nachschlagewerk,
	   keine Lesestrecke. Die Rechtszeile darunter bleibt noch kleiner. */
	font-size: var(--step--1);
	padding-block: var(--section-y) clamp(2rem, 5vw, 3rem);
}

/*
 * Nur auf Seiten mit Sticky-Leiste. Auf termin.php, danke.php, impressum.php
 * und datenschutz.php gibt es sie nicht – dort zog der Fussbereich sonst um
 * 12 rem hoch und deckte das Seitenende zu. Aufgefallen an einer
 * abgeschnittenen Bestaetigung auf termin.php.
 */
.site-footer--under-cta {
	margin-top: calc(-1 * var(--cta-reserve));
	padding-top: calc(var(--section-y) + var(--cta-reserve));
}

.site-footer__card {
	display: grid;
	gap: clamp(1.5rem, 4vw, 2.5rem);
	padding: clamp(1.75rem, 4vw, 3rem);
	background: var(--cream);
	color: var(--ink);
	border-radius: var(--radius-l);
}

.site-footer__card a {
	color: var(--ink);
}

.site-footer__logo {
	width: clamp(140px, 22vw, 190px);
}

.site-footer__grid {
	display: grid;
	gap: clamp(1.25rem, 3vw, 2rem);
}

@media (min-width: 48rem) {
	.site-footer__grid {
		grid-template-columns: 4fr 3fr 3fr;
	}
}

.contact-link {
	display: inline-flex;
	align-items: center;
	gap: .6rem;
	/* 24 px Zielflaeche nach WCAG 2.5.8 – die Zeile selbst ist hoeher, der
	   Verweis darin kam aber nur auf 23 px. */
	min-height: 24px;
	/* Fett ist allein dem Firmennamen vorbehalten – der trägt sein eigenes
	   <strong>. Die Mindesthöhe sitzt auf der Zeile, nicht hier. */
}

.contact-link::before {
	content: '';
	width: 20px;
	height: 20px;
	flex: none;
	background: currentColor;
	-webkit-mask: var(--icon) center / contain no-repeat;
	mask: var(--icon) center / contain no-repeat;
}

.contact-link--phone {
	--icon: url('../images/icons/phone.svg');
}

.contact-link--whatsapp {
	--icon: url('../images/icons/whatsapp.svg');
}

.contact-link--mail {
	--icon: url('../images/icons/mail.svg');
}

.contact-link--pin {
	--icon: url('../images/icons/pin.svg');
	white-space: nowrap;
}

/* Firmenname: gleiche Zeilenhöhe wie die Links, aber ohne Symbol */
.contact-link--plain::before {
	display: none;
}

/* Handlungslink mit Pfeil statt Symboldatei */
.contact-link--action::before {
	content: '→';
	width: 20px;
	background: none;
	-webkit-mask: none;
	mask: none;
	font-size: 1.05em;
	line-height: 1;
	text-align: center;
	transition: transform var(--transition);
}

.contact-link--action:hover::before {
	transform: translateX(3px);
}

/* Trenner in der Adresszeile */
/* ⚠️ `.7` statt `.45` – bei .45 kam das Zeichen auf 2,7:1. Es ist zwar nur
   ein Trenner, aber es steht als Text im Dokument. */
.contact-link__divider {
	opacity: .7;
	padding-inline: .15rem;
}

.contact-link:hover {
	color: var(--gold);
}

/*
 * Drei Spalten mit je zwei Zeilen. Die feste Mindesthöhe liegt auf der
 * Zeile, nicht auf dem Link – sonst fiele die Zeile ohne Link aus der Reihe.
 */
.footer-lines {
	display: grid;
	gap: 0;
	align-content: start;
}

/*
 * Auf dem Handy bleiben 44px stehen – das ist die empfohlene Größe für
 * Tippziele, und dort ist ohnehin Platz. Ab Tablet rücken die Zeilen
 * zusammen, dort wird geklickt statt getippt.
 */
.footer-lines li {
	display: flex;
	align-items: center;
	min-height: 44px;
}

@media (min-width: 48rem) {
	.footer-lines li {
		min-height: 32px;
	}
}

.site-footer__legal {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	/* ⚠️ `center`, nicht der Standard `stretch`: Die beiden Verweise sind
	   `inline-flex` mit `min-height: 24px` und zentrieren ihren Text darin,
	   der Copyright-Span hat das nicht. Gestreckt sitzt sein Text an der
	   Oberkante, die der Verweise mittig – die Zeile lief dadurch sichtbar
	   auseinander. */
	align-items: center;
	gap: .5rem 1rem;
	margin-top: 1.5rem;
	font-size: var(--step--2);
	color: var(--muted-invert);
	text-align: center;
}

/*
 * WCAG 2.2 verlangt 24x24 px Zielflaeche (2.5.8). Die Rechtszeile ist die
 * kleinste Schriftstufe der Seite, die Verweise kamen damit auf 19 px
 * Hoehe. Die Polsterung hebt sie an, ohne die Zeile optisch zu veraendern
 * – der negative Ausgleich haelt den Abstand zur Fusskarte.
 */
.site-footer__legal a {
	display: inline-flex;
	align-items: center;
	min-height: 24px;
	padding-block: 2px;
}

.site-footer__legal a:hover {
	color: var(--gold);
}

/* --------------------------------------------------------------------------
   14. CTA-Leiste
   -------------------------------------------------------------------------- */

/*
 * Klebend statt fest: So bleibt die Leiste beim Scrollen am unteren Rand
 * stehen und kommt am Ende des Inhalts von selbst über dem Footer zur Ruhe.
 * Eine feste Positionierung bräuchte dafür eine Rechnung pro Scroll-Bild.
 */
.cta-bar {
	position: sticky;
	bottom: max(1rem, env(safe-area-inset-bottom));
	z-index: 90;
	margin-top: clamp(1.5rem, 4vw, 3rem);
	padding-inline: var(--gutter);
	visibility: hidden;
	/*
	 * Startet vollstaendig unter der Fensterkante und faehrt beim Scrollen
	 * herein. Die eigene Hoehe (100%) deckt die Leiste ab, der zweite Summand
	 * den Abstand, den `bottom` ihr darunter laesst – ohne ihn blitzt die
	 * Unterkante hervor.
	 *
	 * Ohne `opacity`: Ein gleichzeitiges Aufblenden laesst die Leiste
	 * halbdurchsichtig hereinfahren, und genau das Hereinfahren soll man sehen.
	 */
	transform: translateY(calc(100% + max(1rem, env(safe-area-inset-bottom))));
	transition: transform var(--transition), visibility var(--transition);
}

.cta-bar .btn--light {
	background-color: var(--gold);
	border-color: var(--gold);
	color: var(--ink);
}

.cta-bar .btn--light:hover {
	background-color: var(--gold-light);
	border-color: var(--gold-light);
	color: var(--ink);
}

.cta-bar.is-visible {
	visibility: visible;
	transform: translateY(0);
}

.cta-bar__inner {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: .75rem 1.5rem;
	/* Gleiches Textmaß wie .shell – dort zieht das Innenmaß den Gutter ab */
	max-width: calc(var(--shell) - 2 * var(--gutter));
	margin-inline: auto;
	padding: .85rem 1rem .85rem 1.6rem;
	border-radius: var(--radius-l);
	/* Bewusst nicht in Gold: Die Leiste liegt dauerhaft über dem Inhalt und
	   würde als Goldfläche mit der Leitfarbe um Aufmerksamkeit konkurrieren. */
	background: rgba(18, 19, 20, .55);
	border: 1px solid rgba(254, 249, 241, .3);
	backdrop-filter: blur(18px) saturate(1.3);
	-webkit-backdrop-filter: blur(18px) saturate(1.3);
	color: var(--cream);
	box-shadow: 0 18px 40px rgba(0, 0, 0, .45);
}

.cta-bar p {
	font-size: var(--step--1);
	line-height: 1.4;
}

.cta-bar__sub {
	display: block;
	/* Eine Stufe unter der Zeile darüber: Der Satz ist länger geworden und
	   soll die Frage nicht überstimmen. */
	font-size: var(--step--1);
}

/* Die Aufforderung im Fliesstext – Ersatz fuer den Knopf im Kopfbereich, der
   auf schmalen Schirmen entfaellt. Bewusst **nicht** fett: Die Frage davor
   traegt das Gewicht, dieser Teil haengt sich an.

   ⚠️ Nur schmal. Auf dem Schirm steht der Knopf oben weiterhin, dort waere
   der Satz eine dritte Aufforderung in derselben Zeile. */
.cta-bar__call {
	font-weight: 400;
}

@media (min-width: 48rem) {
	.cta-bar__call {
		display: none;
	}
}

/* Auf dem Handy nimmt die Leiste sonst ein Drittel des Bildschirms ein */
@media (max-width: 47.99rem) {
	/* Volle Breite: Die Leiste ist dort die einzige Aufforderung, seit der
	   Knopf im Kopfbereich entfaellt.

	   ⚠️ Flacher als sonst, aber nicht beliebig: 38 px bleiben deutlich ueber
	   den 24 px, die WCAG 2.5.8 verlangt. Die `min-height: 44px` aus `.btn`
	   muss dabei mit – sonst aendert weniger Polsterung an der Hoehe nichts. */
	.cta-bar .btn {
		width: 100%;
		min-height: 38px;
		padding-block: .35rem;
	}

	.cta-bar__inner {
		padding: .75rem;
		gap: .6rem;
	}

	.cta-bar p {
		font-size: .8125rem;
		line-height: 1.35;
	}

	.cta-bar__sub {
		display: none;
	}

	/* Bewusst nicht über die volle Breite: Als Goldfläche würde der Knopf
	   sonst die halbe Leiste einnehmen und wie ein Farbbalken wirken. */
	.cta-bar .btn {
		margin-inline: auto;
	}
}

@media (min-width: 48rem) {
	.cta-bar__inner {
		border-radius: var(--radius-pill);
		padding-inline: 2rem 1rem;
	}

	.cta-bar p {
		font-size: var(--step-0);
	}
}



/* --------------------------------------------------------------------------
   15. Dialog + Formular
   -------------------------------------------------------------------------- */

.dialog {
	/* Ohne das klebt der Dialog oben links: Der Browser zentriert ein
	   modales <dialog> über `margin: auto`, und der Reset `* { margin: 0 }`
	   oben in dieser Datei nimmt ihm genau das wieder weg. */
	margin: auto;
	width: min(42rem, calc(100% - 2rem));
	max-height: 90dvh;
	padding: 0;
	border: 0;
	border-radius: var(--radius-l);
	background: var(--cream);
	color: var(--ink);
	overflow: auto;
	overscroll-behavior: contain;
}

.dialog::backdrop {
	background: rgba(18, 19, 20, .75);
	backdrop-filter: blur(4px);
}

.dialog__inner {
	padding: clamp(1.5rem, 4vw, 2.5rem);
}

/*
 * Im Dialog eine Stufe kleiner als eine Abschnittsüberschrift: Der Kasten
 * ist 42 rem breit, in voller Größe brach „Kostenloses Erstgespräch" auf
 * zwei Zeilen und nahm dem Inhalt die Hälfte der sichtbaren Höhe.
 */
.dialog h2 {
	font-size: var(--step-3);
}

.dialog__head {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
	gap: 1rem;
	margin-bottom: 1.5rem;
}

.dialog__close {
	width: 44px;
	height: 44px;
	flex: none;
	display: grid;
	place-items: center;
	border: 0;
	border-radius: 50%;
	background: rgba(35, 36, 38, .08);
	cursor: pointer;
	font-size: 1.5rem;
	line-height: 1;
	transition: background var(--transition);
}

.dialog__close:hover {
	background: rgba(35, 36, 38, .18);
}

/*
 * Die direkten Wege ins Gespräch, über dem Formular. Termin und Anruf
 * stehen nebeneinander, solange der Platz reicht.
 */
.dialog__ways {
	display: flex;
	flex-wrap: wrap;
	gap: .75rem;
	margin-bottom: 1.75rem;
}

/* Trennt die Wege vom Formular, ohne eine zweite Überschrift zu setzen. */
.dialog__or {
	display: flex;
	align-items: center;
	gap: .9rem;
	margin-bottom: 1.25rem;
	font-size: var(--step--1);
	color: var(--muted);
}

.dialog__or::after {
	content: "";
	flex: 1;
	height: 1px;
	background: rgba(35, 36, 38, .15);
}

.form-grid {
	display: grid;
	gap: 1rem;
}

@media (min-width: 34rem) {
	.form-grid {
		grid-template-columns: 1fr 1fr;
	}

	.form-grid .field--full {
		grid-column: 1 / -1;
	}
}

.field label {
	display: block;
	margin-bottom: .35rem;
	font-size: var(--step--1);
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
}

.field input,
.field textarea {
	width: 100%;
	min-height: 48px;
	padding: .75rem 1rem;
	border: 1px solid var(--line);
	border-radius: var(--radius-s);
	background: var(--surface);
	transition: border-color var(--transition), box-shadow var(--transition);
}

.field textarea {
	min-height: 8rem;
	resize: vertical;
}

/*
 * `outline: none` ist hier nur zulaessig, weil der Ersatz staerker ist als
 * der Standardrahmen: kraeftiger Rand plus Schimmer. Mit 25 % Deckkraft
 * war der Schimmer auf hellem Grund kaum zu sehen – jetzt 45 %, und der
 * Rand wird zusaetzlich dicker.
 */
.field input:focus,
.field textarea:focus {
	border-color: var(--gold);
	box-shadow: 0 0 0 3px rgba(249, 178, 51, .45);
	outline: none;
}

/*
 * ⚠️ Hier stand ein zusaetzlicher gruener Ring fuer den Tastaturfokus (aus
 * dem Audit vom 02.10.: „auch erkennbar, wenn Gold auf Gold trifft"). Am
 * 04.10. entfernt – zwei Ringe in zwei Farben um dasselbe Feld lasen sich
 * wie ein Fehler. Der Fall, den er abdecken sollte, tritt hier nicht ein:
 * Die Felder stehen auf Weiss, nicht auf Gold.
 *
 * Ohne diese Regel faellt der Fokus auf `.field input:focus` zurueck –
 * goldener Rand samt Schimmer, fuer Maus und Tastatur gleich. Die globale
 * `:focus-visible`-Regel (gruen) greift nicht: `.field input:focus` ist
 * (0,2,1) und setzt `outline: none`, die globale nur (0,1,0).
 */

.field input[aria-invalid='true'],
.field textarea[aria-invalid='true'] {
	border-color: var(--red);
}

.field__error {
	display: block;
	margin-top: .35rem;
	font-size: var(--step--1);
	font-weight: 700;
	color: #c31032;
}

.field--consent {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: .75rem;
	align-items: start;
}

/* ⚠️ 24 px, nicht 22: WCAG 2.5.8 misst das Bedienelement selbst. Das Label
   daneben ist zwar auch klickbar, aber darauf sollte sich niemand verlassen. */
.field--consent input {
	width: 24px;
	height: 24px;
	min-height: 0;
	margin-top: .2rem;
	accent-color: var(--gold);
}

.field--consent label {
	margin: 0;
	font-size: var(--step--1);
	font-weight: 400;
	letter-spacing: 0;
	text-transform: none;
	line-height: 1.5;
}

.field--consent a {
	text-decoration: underline;
	font-weight: 700;
}

/* Spam-Falle: für Menschen unsichtbar, für Bots ausfüllbar */
.field--trap {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

.form-alert {
	padding: .9rem 1.1rem;
	margin-bottom: 1.25rem;
	border-radius: var(--radius-s);
	background: rgba(195, 16, 50, .1);
	border: 1px solid rgba(195, 16, 50, .35);
	color: #8f0c25;
	font-size: var(--step--1);
	font-weight: 700;
}

/*
 * Meldung im schrittweisen Formular – bewusst ohne Kasten. Sie steht
 * direkt ueber der Knopfreihe und erscheint erst auf einen Klick: Dort
 * reicht die Farbe, ein Rahmen waere eine zweite Warnung fuer dieselbe
 * Sache. Dieselbe Farbe wie die Feldfehler darueber.
 */
/*
 * Die Meldung zum laufenden Schritt steht als Kasten da, nicht als blosse
 * Zeile: Sie erscheint direkt unter dem letzten Feld, und ohne Flaeche las
 * sie sich wie ein Nachsatz zum Datenschutztext darueber.
 *
 * ⚠️ Flaeche und Rahmen kommen aus `currentColor`, nicht aus festen Werten.
 * Die Schriftfarbe wechselt mit dem Grund (hell `#c31032`, dunkel
 * `#ff8096`, siehe unten) – so zieht der Kasten automatisch mit, statt eine
 * dritte Stelle zu sein, die jemand vergisst.
 */
.step-error {
	padding: .7rem .9rem;
	border: 1px solid color-mix(in srgb, currentColor 30%, transparent);
	border-radius: var(--radius-s);
	background: color-mix(in srgb, currentColor 10%, transparent);
	margin-top: 1.25rem;
	margin-bottom: .9rem;
	font-size: var(--step--1);
	color: #c31032;
}

/* ⚠️ Der Kasten stand auf `font-weight: 700` – damit war alles fett und der
   Feldname darin hob sich nicht ab. Jetzt traegt nur er die Auszeichnung;
   auffaellig genug ist die Meldung durch Flaeche, Rahmen und Farbe. */
.step-error strong {
	font-weight: 700;
}

/*
 * Fehlerfarben auf dunklem Grund.
 *
 * Die Vorgaben sind fuer den hellen Dialog gemacht: #8f0c25 kommt auf
 * Anthrazit nur auf 1,7:1 und #c31032 auf 2,6:1 – beides unlesbar. Auf
 * dunklem Grund braucht es den Weg in die andere Richtung, also ein
 * aufgehelltes Rot (#ff8096, 6,5:1).
 */
.section--dark .form-alert {
	background: rgba(255, 41, 84, .12);
	border-color: rgba(255, 128, 150, .4);
	color: #ff8096;
}

.section--dark .field__error,
.section--dark .step-error {
	color: #ff8096;
}

.form-submit {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 1rem;
	margin-top: 1.5rem;
}

/*
 * Schrittweises Formular: Zurueck links, Weiter rechts. `margin-left: auto`
 * am ersten Knopf statt `space-between` – so sitzt „Weiter" auch dann
 * rechts, wenn „Zurueck" im ersten Schritt gar nicht da ist.
 */
.form-submit--steps [data-step-next],
.form-submit--steps [data-step-submit] {
	margin-left: auto;
}

/* Zurueck ist kein Knopf: Es fuehrt nicht weiter, es nimmt zurueck. */
.link-back {
	border: 0;
	background: none;
	padding: 0;
	color: inherit;
	font: inherit;
	font-size: var(--step--1);
	cursor: pointer;
	opacity: .7;
	transition: opacity var(--transition);
}

.link-back:hover {
	opacity: 1;
}

.form-hint {
	font-size: var(--step--1);
	color: var(--muted);
}

/* --------------------------------------------------------------------------
   16. Einblend-Animationen
   -------------------------------------------------------------------------- */

/*
 * Einblenden beim Scrollen. Der Standard schiebt von unten herein; mit einem
 * Wert am Attribut kommt das Element stattdessen von der Seite:
 *
 *   data-reveal            von unten  (Boxen, Kaesten)
 *   data-reveal="left"     von links  (Geraetegrafik der Case Studies)
 *   data-reveal="right"    von rechts (Textspalte, Ueberschriften)
 *
 * ⚠️ Die seitliche Strecke ist bewusst klein (2 rem) und **nur** der
 * Ausgangszustand. Ein Element, das weit ausserhalb startet, verbreitert das
 * Dokument und erzeugt Horizontalscroll – derselbe Fallstrick wie bei den
 * gedrehten Geraeten weiter oben. Nachgemessen: Dokumentbreite unveraendert,
 * auf dem Schirm wie bei 375 px.
 */
.js [data-reveal] {
	opacity: 0;
	transform: translateY(1.5rem);
	transition: opacity 700ms ease-out, transform 700ms cubic-bezier(.22, .61, .36, 1);
}

/*
 * ⚠️ Seitwaerts erst ab 48 rem. Darunter steht alles untereinander – Grafik
 * ueber Text, Karte unter Karte. Elemente, die dort abwechselnd von links und
 * rechts hereinkommen, lesen sich als Zickzack, nicht als Ordnung. Die
 * Richtung soll die Anordnung nachzeichnen; gibt es keine seitliche
 * Anordnung, gibt es auch keine seitliche Bewegung.
 *
 * Unterhalb greift damit der Standard: von unten.
 */
@media (min-width: 48rem) {
	.js [data-reveal='left'] {
		transform: translateX(-2rem);
	}

	.js [data-reveal='right'] {
		transform: translateX(2rem);
	}
}

.js [data-reveal].is-visible {
	opacity: 1;
	transform: none;
}

/*
 * Die Karten einer Reihe laufen gestaffelt ein, nicht alle zugleich. Die
 * Verzoegerung haengt am **Kind-Index**, nicht an einer Klasse – so stimmt
 * sie auch, wenn eine Karte dazukommt.
 *
 * ⚠️ Nur auf der Verzoegerung beim Erscheinen: `transition-delay` bleibt beim
 * Zuruecksetzen 0, sonst zuckt die Reihe beim schnellen Hoch- und
 * Runterscrollen nach.
 *
 * ⚠️ **Erst ab 40 rem** – das ist der Punkt, ab dem `.cards` mehrspaltig
 * wird. Darunter stehen die Karten untereinander und kommen ohnehin
 * nacheinander ins Bild; eine zusaetzliche Verzoegerung liesse die fuenfte
 * Karte dann eine Drittelsekunde warten, obwohl sie allein dasteht. Eine
 * Staffelung ordnet, was gleichzeitig passiert – nacheinander braucht sie
 * nicht.
 */
@media (min-width: 40rem) {
	.js .cards > [data-reveal].is-visible:nth-child(2) {
		transition-delay: 80ms;
	}

	.js .cards > [data-reveal].is-visible:nth-child(3) {
		transition-delay: 160ms;
	}

	.js .cards > [data-reveal].is-visible:nth-child(4) {
		transition-delay: 240ms;
	}

	.js .cards > [data-reveal].is-visible:nth-child(5) {
		transition-delay: 320ms;
	}
}

@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	*,
	*::before,
	*::after {
		animation-duration: .01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: .01ms !important;
	}

	.js [data-reveal] {
		opacity: 1;
		transform: none;
	}
}

/* --------------------------------------------------------------------------
   17. Inhaltsseiten (Impressum, Datenschutz, Danke)
   -------------------------------------------------------------------------- */

.legal {
	max-width: 48rem;
	padding-bottom: var(--section-y);
}

.legal p a,
.legal li a {
	font-weight: 700;
	text-decoration: underline;
}

.legal h2 {
	margin-top: 2.5rem;
	margin-bottom: .75rem;
	font-size: var(--step-2);
	text-transform: none;
}

.legal h3 {
	margin-top: 1.75rem;
	margin-bottom: .5rem;
	font-size: var(--step-1);
}

.legal p,
.legal li {
	color: var(--fg-muted);
}

.legal ul {
	display: grid;
	gap: .4rem;
	margin-top: .75rem;
	padding-left: 1.25rem;
	list-style: disc;
}

.legal .todo {
	display: block;
	padding: .85rem 1.1rem;
	margin-block: .75rem;
	border-left: 3px solid var(--red);
	background: rgba(255, 41, 84, .1);
	color: var(--fg);
	font-size: var(--step--1);
	font-weight: 700;
}

.thanks {
	display: grid;
	place-items: center;
	min-height: 70svh;
	text-align: center;
}

.thanks__inner {
	max-width: 36rem;
}

.thanks__title {
	margin-bottom: 1.25rem;
}

/* --------------------------------------------------------------------------
   16. Terminbuchung
   -------------------------------------------------------------------------- */

.booking-wrap {
	max-width: 42rem;
}

.booking__slots {
	border: 0;
	margin-bottom: 2rem;
}

/*
 * Monatsansicht. Sieben feste Spalten statt `auto-fill`: Die Wochentage
 * darueber muessen auf den Tagen darunter sitzen, und das tun sie nur,
 * wenn beide Raster dieselbe Teilung haben.
 */
.cal {
	margin-bottom: 1.75rem;
}

.cal__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: .5rem;
	margin-bottom: .9rem;
}

.cal__title {
	font-weight: 700;
	text-align: center;
	flex: 1;
}

.cal__arrow {
	width: 36px;
	height: 36px;
	flex: none;
	display: grid;
	place-items: center;
	border: 1px solid rgba(254, 249, 241, .25);
	border-radius: 50%;
	background: transparent;
	color: inherit;
	cursor: pointer;
	transition: border-color var(--transition), opacity var(--transition);
}

.cal__arrow:hover:not(:disabled) {
	border-color: var(--gold);
}

.cal__arrow:disabled {
	opacity: .25;
	cursor: default;
}

/* Winkel aus zwei Raendern – bleibt bei jeder Groesse gleich duenn. */
.cal__arrow span {
	width: 9px;
	height: 9px;
	border-top: 1.5px solid currentColor;
	border-right: 1.5px solid currentColor;
	transform: rotate(-135deg);
	margin-left: 3px;
}

.cal__arrow--next span {
	transform: rotate(45deg);
	margin-left: 0;
	margin-right: 3px;
}

.cal__weekdays,
.cal__grid {
	display: grid;
	grid-template-columns: repeat(7, 1fr);
	gap: 4px;
}

.cal__weekdays {
	margin-bottom: 6px;
	font-size: var(--step--2);
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	color: var(--muted-invert);
	text-align: center;
}

/*
 * Ueber die volle Breite, aber die Tagesfelder bleiben rund und handlich:
 * `aspect-ratio: 1` auf einer breiten Spalte ergaebe riesige Kreise,
 * deshalb eine feste Hoehe und der Kreis nur so gross wie noetig.
 */
.cal__day,
.cal__pad {
	display: grid;
	place-items: center;
	height: 2.6rem;
	border-radius: 999px;
	font-size: var(--step--1);
	font-variant-numeric: tabular-nums;
}

.cal__day.is-free,
.cal__day.is-selected {
	/* Der farbige Kreis soll nicht die ganze Spaltenbreite fuellen. */
	width: 2.6rem;
	margin-inline: auto;
}

/* Tage ohne Termin bleiben lesbar, aber zurueckgenommen – ein ausgegrauter
   Kalender wirkt kaputt, ein leerer wirkt geschlossen.

   ⚠️ `.55`, nicht `.3`: Bei .3 kam die Zahl auf 2,6:1. Sie ist Text und
   braucht 4,5:1 – man muss ablesen koennen, welcher Tag welcher ist, auch
   wenn er nicht waehlbar ist. Das Signal „frei" tragen Flaeche und Rahmen,
   nicht die Lesbarkeit der Ziffer. */
.cal__day {
	color: rgba(254, 249, 241, .55);
}

button.cal__day {
	border: 0;
	background: transparent;
	font-family: inherit;
	cursor: pointer;
	transition: background var(--transition), border-color var(--transition), color var(--transition);
}

button.cal__day:disabled {
	cursor: default;
}

/* Verfuegbar ist gruen und schwach – Gold bleibt der **Auswahl**. Die
   Flaeche traegt nur die Markierung, die Schrift behaelt ihre Grundfarbe
   (im Dialog umgekehrt, siehe `.dialog .cal__day.is-free`). */
.cal__day.is-free {
	/* ⚠️ Helleres Mint als `--green` (#16b079), nicht weniger Deckkraft:
	   Die Flaeche steht auf zwei Gruenden. Blasser hiesse im Dialog heller,
	   auf `termin.php` aber dunkler – ein hellerer Ton hellt beide auf.

	   Flaeche **und** Rahmen sind dieselben Werte wie bei
	   `.booking__time span`: Tag und Uhrzeit sind zwei Stufen derselben
	   Auswahl und sollen gleich aussehen.

	   ⚠️ `button.cal__day` setzt `border: 0`. Diese Regel ist (0,2,0) und
	   schlaegt es – wer den Rahmen woanders setzt, prueft das zuerst. */
	background: rgba(74, 222, 168, .18);
	border: 1px solid rgba(74, 222, 168, .45);
	color: var(--cream);
	font-weight: 700;
}

.cal__day.is-selected {
	background: var(--gold);
	border: 1px solid var(--gold);
	color: var(--ink);
}

/*
 * Vorschlagsmodus: Alle Werktage sind waehlbar, auch die ohne Termin im
 * Kalender. Sie sehen deshalb gleich aus – aber nicht golden: Gold heisst
 * „dieser Termin steht im Kalender", und das gilt hier fuer keinen von
 * ihnen. Gold bleibt der Auswahl.
 *
 * `button` im Selektor ist kein Zierrat: `.cal__day.is-free` ist (0,2,0)
 * und wuerde eine reine Klassenkette gleicher Laenge je nach Reihenfolge
 * schlagen.
 */
.cal.is-proposing button.cal__day:not(:disabled) {
	width: 2.6rem;
	margin-inline: auto;
	background: rgba(254, 249, 241, .1);
	/* `currentColor` statt fester Werte – die Schrift wechselt mit dem Grund,
	   der Rahmen zieht dadurch mit und braucht keine eigene Dialogregel. */
	border: 1px solid color-mix(in srgb, currentColor 25%, transparent);
	color: var(--cream);
	font-weight: 700;
}


.cal.is-proposing button.cal__day.is-selected {
	background: var(--gold);
	border-color: var(--gold);
	color: var(--ink);
}

.booking__slots legend {
	padding: 0 0 1rem;
	font-size: var(--step--1);
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
}

/* Sobald die Tabs stehen, sagt die Ueberschrift dasselbe noch einmal – sie
   bleibt nur als Gruppenname fuer die Sprachausgabe. */
.booking__slots.has-slot-tabs legend {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* Die zwei Modi an der Stelle der Ueberschrift – dieselbe Pillenform wie die
   Uhrzeiten darunter, damit die Auswahl als eine Familie liest.

   ⚠️ Der Rahmen kommt aus `currentColor`, nicht aus einem festen Wert:
   Dieselbe Leiste steht auf `termin.php` auf anthrazitem Grund und im Dialog
   auf cremefarbenem. So braucht sie keine Umkehrung – anders als
   `.booking__time span`, das dafuer eine eigene Dialogregel hat. */
.slot-tabs {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem;
	margin-bottom: 1.5rem;
}

.slot-tab {
	padding: .6rem 1.1rem;
	border: 1px solid currentColor;
	border-color: color-mix(in srgb, currentColor 30%, transparent);
	border-radius: var(--radius-pill);
	background: none;
	font: inherit;
	font-size: var(--step--1);
	font-weight: 700;
	color: inherit;
	cursor: pointer;
	transition: background var(--transition), border-color var(--transition), color var(--transition);
}

.slot-tab.is-current {
	background: var(--gold);
	border-color: var(--gold);
	color: var(--ink);
	cursor: default;
}

.slot-tab:focus-visible {
	outline: 2px solid var(--gold);
	outline-offset: 3px;
}

.booking__days {
	display: grid;
	gap: 1.1rem;
}

.booking__day-label {
	margin-bottom: .5rem;
	font-size: var(--step--1);
	font-weight: 700;
	color: var(--muted-invert);
}

.booking__times {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem;
}

/*
 * Die Uhrzeit ist der Knopf. Das Eingabefeld bleibt im Dokument – nur
 * optisch versteckt, nicht per `display: none`: Sonst nimmt der Browser
 * es aus der Tabulatorreihenfolge und `required` greift nicht mehr.
 */
.booking__time input {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
	pointer-events: none;
}

/* Verfuegbare Uhrzeit: dieselbe blassgruene Flaeche wie ein verfuegbarer Tag
   – die Auswahl im ersten Schritt liest sich dadurch als eine Logik.
   Gold bleibt der getroffenen Wahl. */
.booking__time span {
	display: inline-block;
	padding: .6rem 1.1rem;
	background: rgba(74, 222, 168, .18);
	border: 1px solid rgba(74, 222, 168, .45);
	border-radius: var(--radius-pill);
	font-size: var(--step--1);
	font-weight: 700;
	cursor: pointer;
	transition: background var(--transition), border-color var(--transition), color var(--transition);
}


.booking__time input:focus-visible + span {
	outline: 2px solid var(--gold);
	outline-offset: 3px;
}

.booking__time input:checked + span {
	background: var(--gold);
	border-color: var(--gold);
	color: var(--ink);
}

.booking__note,
.booking__empty {
	margin-top: 1rem;
	font-size: var(--step--1);
	color: var(--muted-invert);
}

.booking-done__title {
	margin-bottom: 1rem;
	font-size: var(--step-3);
}

.booking-done__slot {
	padding-inline-start: 1.125rem;
	border-inline-start: 3px solid var(--gold);
	font-size: var(--step-1);
	font-weight: 700;
}

.booking-done__meta {
	margin-top: .35rem;
	padding-inline-start: 1.125rem;
	font-size: var(--step--1);
	color: var(--muted-invert);
}

.booking-done__hint {
	margin-top: 1.5rem;
	color: var(--muted-invert);
}

/*
 * Im Dialog steht der helle Grund – dort kehren sich die Farben um, die
 * oben fuer den dunklen Abschnitt gedacht sind.
 */
.dialog .booking__day-label,
.dialog .booking__note,
.dialog .booking__empty,
.dialog .booking-done__meta,
.dialog .booking-done__hint {
	color: var(--muted);
}

.dialog .cal__arrow {
	border-color: rgba(35, 36, 38, .25);
}

.dialog .cal__weekdays {
	color: var(--muted);
}

.dialog .cal__day {
	color: rgba(35, 36, 38, .35);
}

/* ⚠️ Nicht redundant, auch wenn `.cal__day.is-free` dieselbe Farbe setzt:
   Beide sind (0,2,0), und die Dialogregel darueber steht spaeter – ohne
   diese Zeile bekaemen die freien Tage deren blasse 35 %. */
.dialog .cal__day.is-free {
	color: var(--ink);
}

.dialog .cal.is-proposing button.cal__day:not(:disabled) {
	background: rgba(35, 36, 38, .08);
	color: var(--ink);
}


.dialog .cal.is-proposing button.cal__day.is-selected {
	background: var(--gold);
	border-color: var(--gold);
	color: var(--ink);
}

/* Nachgeladene Slot-Auswahl im Dialog. */
.dialog__booking:not([hidden]) {
	margin-bottom: 1.5rem;
}

.dialog__booking .booking__slots {
	margin-bottom: 1.5rem;
}

/* --------------------------------------------------------------------------
   17. Terminbuchung: Schritte und Themen
   -------------------------------------------------------------------------- */

/*
 * Fortschritt. Traegt `hidden`, bis das Skript die Schritte uebernimmt –
 * ohne JavaScript gibt es keine Schritte und die Anzeige waere eine Luege.
 */
.steps {
	display: flex;
	gap: .5rem;
	margin-bottom: 1.75rem;
	list-style: none;
	font-size: var(--step--2);
	font-weight: 700;
	letter-spacing: .1em;
	text-transform: uppercase;
	color: var(--muted-invert);
}

/*
 * Drei Zustaende, drei Stufen – die Farbe allein reichte nicht, der
 * Unterschied war auf dem Schirm kaum zu sehen. Jetzt traegt zusaetzlich
 * die Deckkraft die Unterscheidung: Der laufende Schritt steht voll da,
 * die erledigten etwas zurueck, die kommenden deutlich blasser.
 */
/* ⚠️ `.6`, nicht `.35`: Die kommenden Schritte sind Text und brauchen
   4,5:1 (WCAG 1.4.3) – bei .35 waren es 2,2:1, bei .6 erst 3,9:1. Dass sie
   zurueckstehen, tragen Farbe und Linienstaerke, nicht die Unlesbarkeit. */
.steps li {
	flex: 1;
	padding-top: .55rem;
	border-top: 2px solid currentColor;
	opacity: .75;
	transition: color var(--transition), border-color var(--transition), opacity var(--transition);
}

/* Erledigt: gold, und zwar voll sichtbar – es ist eine Bestaetigung,
   kein Nebenschauplatz. */
.steps li.is-done {
	border-top-color: var(--gold);
	color: var(--gold);
	opacity: 1;
}

/*
 * Der laufende Schritt steht in der Textfarbe des Grundes, nicht in einer
 * Signalfarbe: Gold markiert, was hinter einem liegt. Auf dunklem Grund
 * ist das Creme, im Dialog Anthrazit – dieselbe Rolle, andere Richtung.
 */
.steps li.is-current {
	border-top-color: var(--cream);
	color: var(--cream);
	opacity: 1;
}

.booking__topics,
.booking__contact {
	border: 0;
}

.booking__topics legend,
.booking__contact legend {
	padding: 0 0 1rem;
	font-size: var(--step--1);
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
}

.topics {
	display: flex;
	flex-wrap: wrap;
	gap: .5rem;
	margin-bottom: 1.5rem;
}

/*
 * Dasselbe Muster wie bei den Uhrzeiten: Das Kaestchen bleibt im Dokument
 * und nur optisch versteckt – `display: none` naehme es aus der
 * Tabulatorreihenfolge.
 */
.topic input {
	position: absolute;
	width: 1px;
	height: 1px;
	opacity: 0;
	pointer-events: none;
}

.topic span {
	display: inline-block;
	padding: .6rem 1.1rem;
	border: 1px solid rgba(254, 249, 241, .3);
	border-radius: var(--radius-pill);
	font-size: var(--step--1);
	cursor: pointer;
	transition: background var(--transition), border-color var(--transition), color var(--transition);
}


.topic input:focus-visible + span {
	outline: 2px solid var(--gold);
	outline-offset: 3px;
}

/* ⚠️ **Kein** `font-weight` hier: Die Pille wuerde beim Anklicken breiter und
   die ganze Reihe spraenge um. Dieselbe Begruendung wie beim Ueberfahren der
   Uhrzeiten – die Farbe traegt den Zustand allein. */
.topic input:checked + span {
	background: var(--gold);
	border-color: var(--gold);
	color: var(--ink);
}

.field__opt {
	font-weight: 400;
	letter-spacing: 0;
	text-transform: none;
	opacity: .6;
}

/* Heller Grund im Dialog – dieselben Umkehrungen wie bei den Uhrzeiten. */
.dialog .steps {
	color: var(--muted);
}

/*
 * Im Dialog liegt heller Grund: Der laufende Schritt steht dort in
 * Anthrazit statt in Creme. Das Gold der erledigten Schritte bleibt das
 * Markengold.
 *
 * ⚠️ Gold kommt auf Creme nur auf 1,8:1. Getragen wird der Zustand
 * deshalb nicht von der Farbe allein, sondern zusaetzlich von der
 * Deckkraft (offene Schritte 35 %) und der Linie darueber. Eine dunklere
 * Fassung (`--gold-deep`, 3,9:1) stand hier und war erkennbar nicht das
 * Markengold.
 */
.dialog .steps li.is-current {
	border-top-color: var(--ink);
	color: var(--ink);
}

.dialog .topic span {
	border-color: rgba(35, 36, 38, .25);
}

/* Bestaetigung im Dialog: heller Grund, also umgekehrte Textfarben. */
.dialog .booking-done__meta,
.dialog .booking-done__hint {
	color: var(--muted);
}

.dialog .booking-done .eyebrow {
	color: var(--muted);
}

/* Im Dialog traegt die Ueberschrift des Dialogs schon „Termin steht". */
.dialog .booking-done .eyebrow,
.dialog .booking-done__title {
	display: none;
}

/* --------------------------------------------------------------------------
   18. Überfahren in der Terminbuchung
   -------------------------------------------------------------------------- */

/*
 * Diese Zustände stehen gesammelt am Ende und nicht bei ihren Bausteinen:
 * Sie müssen sowohl die dunkle Grundfassung schlagen als auch die
 * Umkehrungen für den hellen Dialog, und die stehen weiter oben verteilt.
 * Hier entscheidet die Reihenfolge, nicht ein doppelter Klassenselektor.
 */

/*
 * Tag im Kalender: dieselbe goldene Fläche wie die Auswahl. Dass beide
 * gleich aussehen, stört nicht – unter dem Zeiger ist ohnehin klar, was
 * gemeint ist, und ein dritter Farbton für „fast ausgewählt" wäre eine
 * Unterscheidung ohne Aussage.
 *
 * Die Dialogfassung ist bis aufs Komma dieselbe. Sie steht trotzdem da,
 * weil `.dialog .cal.is-proposing button.cal__day:not(:disabled)` sonst
 * mit gleicher Spezifität und späterer Position gewinnt.
 */
.cal button.cal__day:not(:disabled):hover,
.dialog .cal button.cal__day:not(:disabled):hover {
	background: var(--gold);
	border-color: var(--gold);
	color: var(--ink);
}

/* Der inaktive Modus-Tab: dieselbe goldene Fläche wie der aktive. Der aktive
   hat sie schon und ist `cursor: default` – ein Hover darauf sagt nichts. */
.slot-tab:not(.is-current):hover,
.dialog .slot-tab:not(.is-current):hover {
	background: var(--gold);
	border-color: var(--gold);
	color: var(--ink);
}

/* Uhrzeit und Thema: volle Fläche statt nur goldener Rahmen. Anthrazit als
   Schrift, weil Creme auf Gold nur auf rund 2:1 käme. Das Gewicht bleibt
   unverändert – sonst springt die Breite der Pille beim Überfahren. */
.booking__time:hover span,
.dialog .booking__time:hover span,
.topic:hover span,
.dialog .topic:hover span {
	background: var(--gold);
	border-color: var(--gold);
	color: var(--ink);
}

/*
 * „Weiter" und „Termin buchen": Gold bleibt die Ruhefarbe, beim Überfahren
 * kehrt sich der Knopf um.
 *
 * Bewusst nur im Dialog: Auf termin.php steht derselbe Knopf auf
 * anthrazitem Grund und verschwände darin. `.btn--outline` bleibt außen
 * vor, der hat seine eigene Umkehrung.
 */
.dialog .btn:not(.btn--outline):hover {
	background-color: var(--ink);
	border-color: var(--ink);
	color: var(--cream);
}
