/* ============================================================
   ModernOne — Seitenspezifische Komponenten
   Hero-Details, Referenz, Stil-Strecke, Vorher/Nachher-Regler,
   Ablauf-Linie, Preisrechner, Termin-Flow, Porträt, Werdegang.
   ============================================================ */

/* ---------- Startseite: Hero ---------- */
.scrollhint {
  display: flex;
  align-items: center;
  gap: 11px;
  font-size: 12px;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.scrollhint .arrow {
  color: var(--accent);
  font-size: 16px;
}

.hero-cta-row {
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  margin-top: 44px;
}

/* ---------- Startseite: Stil-Strecke (Platzhalter) ----------
   Jeder Abschnitt ist 300dvh hoch: 100dvh fuer den sticky Inhalt selbst,
   dazu 200dvh Scrollstrecke, waehrend der er stehen bleibt (sN steht auf
   der Stelle, sobald sein Kopf den Bildschirmrand erreicht, bis k3
   erreicht ist).

   Keyframe-Markierungen (sNkM) sind reine Entwicklerhilfe: sie zeigen beim
   Scrollen, an welcher Stelle der 200dvh-Sticky-Strecke man sich befindet,
   und dienen als Ankerpunkte fuer die spaetere Ausarbeitung der
   Stil-Strecke (Konzept Abschnitt 3). Sie scrollen normal mit (nicht
   sticky) und liegen bei k1 = 0dvh, k2 = 100dvh, k3 = 200dvh. Vor dem
   Ausarbeiten der eigentlichen Stile entfernen oder durch die echten
   Animationsschritte ersetzen. */
.stil-placeholder {
  position: relative;
  width: 100%;
  height: 300dvh;
  border-bottom: 1px solid var(--hairline);
}

/* Abschnitte mit nur zwei Keyframes. Die Hoehe ist um eine Bildschirmhoehe
   kuerzer, damit der letzte Keyframe wie ueberall am Ende der Sticky-Strecke
   liegt: Ein Abschnitt ist immer eine Bildschirmhoehe hoch plus je eine
   weitere pro Keyframe-Abstand. */
.stil-placeholder--k2 { height: 200dvh; }

/* ---------- Auftakt der Stil-Strecke (s0) ----------
   Ohne Trennlinie am unteren Rand: Der Auftakt und die erste Stil-Strecke
   gehoeren zusammen, eine Linie dazwischen wuerde sie auseinanderziehen. */
.stil-auftakt { border-bottom: 0; }

/* ---------- Wahl des Stils ----------
   Weisse Flaeche ueber die volle Hoehe zwischen Auftakt und Strecke. Sie
   traegt ihren Grund selbst, statt ihn vom Koerper zu nehmen: der wird
   von data-ton der Abschnitte eingefaerbt, und die Wahl soll davon
   unberuehrt weiss bleiben. */
.stil-wahl {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100dvh;
  padding: 80px 24px;
  background: #fff;
  border-bottom: 1px solid var(--hairline);
}

.stil-wahl__inhalt {
  width: 100%;
  max-width: 900px;
  text-align: center;
}

.stil-wahl__vor {
  margin: 0 0 10px;
  font-size: 12px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.stil-wahl__titel {
  margin: 0 0 40px;
  font-size: clamp(26px, 4vw, 42px);
  font-weight: 400;
  letter-spacing: -.01em;
  color: var(--ink);
}

/* Vier nebeneinander, auf schmalen Fenstern zwei und dann eine Spalte.
   auto-fit statt fester Spaltenzahl: die Kaertchen ordnen sich selbst. */
.stil-wahl__liste {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 12px;
}

.stil-wahl__knopf {
  display: block;
  padding: 18px 18px 20px;
  border: 1px solid var(--hairline);
  border-radius: 3px;
  background: #fff;
  font: inherit;
  color: inherit;
  /* Mittig wie die Ueberschrift darueber -- ausdruecklich gesetzt und
     nicht dem Browser ueberlassen, der Knoepfe von sich aus zentriert. */
  text-align: center;
  cursor: pointer;
  transition: border-color .25s var(--ease), box-shadow .25s var(--ease),
              transform .25s var(--ease);
}

.stil-wahl__knopf:hover { transform: translateY(-2px); }

.stil-wahl__knopf:hover,
.stil-wahl__knopf:focus-visible { border-color: var(--hairline-strong); }

/* Der gewaehlte traegt seinen eigenen Ton als Rahmen, damit die Wahl
   auch beim Zurueckscrollen noch abzulesen ist. */
.stil-wahl__knopf.ist-gewaehlt {
  border-color: var(--wahl-ton);
  box-shadow: inset 0 0 0 1px var(--wahl-ton);
}

/* Farbprobe: zeigt vorab den Ton, den die Seite im Stil annehmen wird. */
.stil-wahl__probe {
  display: block;
  width: 100%;
  height: 46px;
  margin-bottom: 14px;
  border: 1px solid var(--hairline);
  border-radius: 2px;
  background: var(--wahl-ton);
}

.stil-wahl__name {
  display: block;
  font-size: 15px;
  line-height: 1.3;
  color: var(--ink);
}

.stil-wahl__fach {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-4);
}

.stil-wahl__weiter {
  margin: 28px 0 0;
  font-size: 13px;
  color: var(--ink-3);
}

/* ---------- Buehne: die vier Stil-Abschnitte ----------
   Sie stehen verborgen, bis die Wahl einen von ihnen holt. display: none
   und nicht bloss unsichtbar: nur so faellt der Abschnitt ganz aus dem
   Fluss, die Seite wird nicht drei Bildschirmhoehen laenger als noetig,
   und der Browser holt die Bilder darin nicht. */
[data-stil-buehne] { display: none; }
[data-stil-buehne].ist-gewaehlt { display: block; }

/* ---------- Inhalt des Auftakts ----------
   Fuehrt in die Strecke ein: Titel, Erlaeuterung, ein Pfeil, der zum
   Weiterscrollen auffordert, und seitlich ein Link, der die ganze Strecke
   ueberspringt. */
.stil-auftakt__inhalt {
  max-width: 760px;
  padding: 0 24px;
  text-align: center;
}

.stil-auftakt__titel {
  margin: 0;
  font-size: clamp(30px, 4.2vw, 60px);
  line-height: 1.06;
  letter-spacing: -.03em;
  font-weight: 600;
  text-wrap: balance;
}

.stil-auftakt__lead {
  margin: 24px auto 0;
  max-width: 34em;
  font-size: 17px;
  line-height: 1.65;
  color: var(--ink-2);
  text-wrap: pretty;
}

.stil-auftakt__pfeil {
  display: block;
  width: clamp(56px, 6vw, 84px);
  height: auto;
  margin: 56px auto 0;
}

/* Seitlich statt im Textblock: Der Link gehoert nicht zur Einfuehrung,
   sondern ist ein Ausweg aus der Strecke. */
.stil-auftakt__skip {
  position: absolute;
  right: clamp(20px, 4vw, 56px);
  top: 50%;
  transform: translateY(-50%);
  font-size: 14px;
  letter-spacing: .01em;
  color: var(--ink-3);
  text-decoration: none;
  border-bottom: 1px solid var(--hairline);
  padding-bottom: 3px;
  transition: color .25s var(--ease), border-color .25s var(--ease);
}

.stil-auftakt__skip:hover,
.stil-auftakt__skip:focus-visible {
  color: var(--ink);
  border-bottom-color: currentColor;
}

/* Unter der Breite, ab der das Raster einspaltig wird, ist seitlich kein
   Platz mehr: Dort ruecken Pfeil und Link untereinander an den unteren Rand. */
@media (max-width: 860px) {
  .stil-auftakt__skip {
    top: auto;
    bottom: 40px;
    right: auto;
    left: 50%;
    transform: translateX(-50%);
  }

  .stil-auftakt__pfeil { margin-top: 40px; }
}


.stil-placeholder__sticky {
  position: sticky;
  top: 0;
  width: 100%;
  height: 100dvh;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.stil-placeholder__mark {
  font-size: clamp(40px, 6vw, 88px);
  line-height: 1;
  font-weight: 400;
  color: var(--ink-4);
  transition: color .3s var(--ease);
}

/* Farbe je Keyframe (per JS gesetzt): k1 rot, k2 blau, k3 gruen. */
.stil-placeholder__mark.is-k1 { color: var(--accent); }
.stil-placeholder__mark.is-k2 { color: var(--accent-blue); }
.stil-placeholder__mark.is-k3 { color: var(--accent-green); }

.stil-placeholder__keyframe {
  position: absolute;
  right: 16px;
  height: 100dvh;
  display: flex;
  align-items: flex-start;
  padding-top: 16px;
  font-size: 11px;
  font-family: var(--mono);
  letter-spacing: .04em;
  color: var(--ink-4);
  opacity: .55;
  pointer-events: none;
}

.stil-placeholder__keyframe[data-k="1"] { top: 0; }
.stil-placeholder__keyframe[data-k="2"] { top: 100dvh; }
.stil-placeholder__keyframe[data-k="3"] { top: 200dvh; }

/* ---------- Schrift der Titel von Stil 1 ----------
   Vorgesehen war Wide Road Regular von Letterlays. Deren Lizenz weist die
   Schrift zwar als frei auch fuer kommerzielle Nutzung aus, sagt aber
   nichts zur Einbettung als Webfont, und die Schrift selbst traegt
   "All rights reserved" in ihren Metadaten — zu unsicher, um die Datei
   auszuliefern.

   Stattdessen Archivo in der breiten, fetten Schnittweite: frei einbettbar
   (SIL Open Font License, Text liegt daneben), breit laufend wie das
   Vorbild und sachlich genug fuer die Firmenseite.

   swap statt block: Der Titel steht sofort in der Ersatzschrift und wechselt
   nach, sobald die Datei da ist — bei einem rein dekorativen Abschnitt
   besser als eine leere Flaeche. */
@font-face {
  /* Alpino Black (ITF Free Font License, siehe assets/fonts/
     alpino-ffl.txt): das Kuerzel M1A in der Kopfzeile waehrend Stil 3. */
  font-family: 'Alpino';
  src: url('../assets/fonts/Alpino-Black.woff2') format('woff2');
  font-weight: 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  /* Sentient (ITF Free Font License, siehe assets/fonts/sentient-ffl.txt):
     Serifen-Titel der Treuhandkanzlei in Stil 4. */
  font-family: 'Sentient';
  src: url('../assets/fonts/Sentient-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Sentient';
  src: url('../assets/fonts/Sentient-Medium.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

@font-face {
  /* Quilon Bold (ITF Free Font License, siehe assets/fonts/
     quilon-ffl.txt): Schriftzug im Auftakt von Stil 3. Schwerer als
     Bold gibt es Quilon nicht, auch variabel endet die Achse bei 700. */
  font-family: 'Quilon';
  src: url('../assets/fonts/Quilon-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Archivo Expanded';
  src: url('../assets/fonts/Archivo-Expanded-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* ---------- Schrift des Textes von Stil 1 ----------
   Vorgesehen war Reversal Bold von Typodermic. Deren kostenlose Lizenz ist
   eine reine Desktop-Lizenz und untersagt in Abschnitt 4.3 ausdruecklich
   jede Einbettung in eine "website or webfont implementation" — die Datei
   darf hier also weder liegen noch ausgeliefert werden. Solange keine
   Webfont-Lizenz vorliegt, steht hier Space Grotesk Bold: frei einbettbar
   (SIL Open Font License, Text liegt daneben) und im Charakter verwandt,
   naemlich schmal laufend, kontrastarm und technisch-freundlich.

   Zum Tausch reicht die Datei in assets/fonts, ein zweites @font-face und
   der geaenderte Name in --s1-text weiter unten. */
@font-face {
  font-family: 'Space Grotesk';
  src: url('../assets/fonts/SpaceGrotesk-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* ---------- Schrift des Seitentitels je Stil ----------
   Der Titel in der Kopfzeile wechselt mit dem Stil, der gerade auf der
   Buehne steht: js/main.js schreibt dessen Nummer in data-stil-aktiv am
   Wurzelelement. Beide Schriften stehen unter der SIL Open Font License. */
@font-face {
  font-family: 'Mozilla Text';
  src: url('../assets/fonts/MozillaText-SemiBold.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: 'Notable';
  src: url('../assets/fonts/Notable-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* Gesetzt wird die Schrift ueber data-marke an der Kopfzeile und nicht
   direkt ueber den laufenden Stil: js/main.js tauscht sie erst, wenn der
   Titel ausgeblendet ist, und misst ihn dabei neu auf die Mitte. */
.site-header[data-marke="1"] .brand {
  font-family: 'Mozilla Text', var(--font);
  font-weight: 600;
  letter-spacing: 0;
}

/* Notable ist eine reine Versalschrift, der Titel steht hier also in
   Grossbuchstaben; etwas Sperrung haelt ihn dabei lesbar. */
.site-header[data-marke="2"] .brand {
  font-family: 'Notable', var(--font);
  font-weight: 400;
  font-size: 30px;
  letter-spacing: .02em;
}

/* In Stil 3 steht statt des Namens das Kuerzel M1A (js/main.js tauscht
   den Text im selben unsichtbaren Moment wie die Schrift). Kurz und
   schwer, darum etwas gesperrt und eine Spur kleiner. */
.site-header[data-marke="3"] .brand {
  font-family: 'Quilon', var(--font);
  font-weight: 700;
  font-size: 31px;
  letter-spacing: .03em;
  /* Hier steht der Titel nicht ueber eine animierte Verschiebung in der
     Mitte, sondern durch die Lage selbst. Grund: die Faltbreiten aendern
     sich im Layout, eine Verschiebung liefe als Transform auf der
     Compositor-Uhr — bei den langen Bildabstaenden, die der
     Verzerrungsfilter in diesem Abschnitt verursacht, laufen beide
     auseinander und die Buchstaben zittern gegeneinander. So bleibt die
     Mitte eine Folge der Breite und wird im selben Durchgang gerechnet. */
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  transition: opacity .18s var(--ease);
}

/* Aufklappen zum vollen Namen, sobald die Fachzeile des Auftakts oben
   aus dem Bild ist: M, A und die Ziffer stehen fest, die uebrigen
   Stuecke fahren zwischen ihnen auf und die Ziffer zugleich zu — aus
   M1A wird ModernOne Architektur. Alle Stuecke sind gleich gebaute
   Inline-Bloecke, damit sie sauber auf einer Linie stehen; die Breiten
   misst js/main.js einmal aus und setzt sie in Pixeln.

   M und A stehen schon in Quilon, der Schrift des vollen Namens: beim
   Aufklappen waechst also nur, nichts blendet um. Allein die Ziffer
   steht in Alpino und faltet weg. */
.brand__t {
  display: inline-block;
  vertical-align: top;
  overflow: hidden;
  white-space: pre;
}

/* Gleichmaessig statt beschleunigt: Breite und Verschiebung teilen sich
   dieselbe Kurve, und weil sie linear laeuft, wandern auch M und A in
   gleichmaessigem Zug auf ihre Endposition. */
.brand__auf,
.brand__zu { transition: max-width .5s linear; }

.site-header[data-marke="3"] .brand { transition-timing-function: linear; }

/* Die Ziffer steht als einzige in Alpino, und dessen Metrik weicht ab:
   bei gleicher Punktgroesse sitzt seine Grundlinie fuenf Pixel tiefer
   und seine Versalhoehe liegt drei Pixel darueber. Die Groesse gleicht
   die Versalhoehe an die von Quilon an, der Versatz die Grundlinie. */
.brand__zahl {
  font-family: 'Alpino', var(--font);
  font-weight: 900;
  font-size: .86em;
  transform: translateY(-.7px);
}

/* ---------- Stil 1: fiktive Firmenwebsite im Rahmen ----------
   Miniatur einer sachlichen Schweizer Firmenseite (fiktive Truttmann
   Holzbau AG). Der Rahmen bleibt sticky stehen, die Seite darin wird per
   JS entlang der Keyframes k1 → k3 durchgescrollt (transform auf
   .stil-site__page, siehe js/main.js). Bilder sind Platzhalterflaechen. */
.stil-site {
  /* Eigener Markenakzent der fiktiven Firma (Tannengruen) — bewusst nicht
     der Seitenakzent, damit der Stil als fremde Website lesbar ist. */
  --s1-accent: oklch(0.46 0.09 150);
  --s1-pad: clamp(28px, 5vw, 64px);
  --s1-titel: 'Archivo Expanded', var(--font);
  --s1-text: 'Space Grotesk', var(--font);
  width: 100%;
  height: 100dvh;
  /* Buehnenton statt fester Seitenfarbe: Der Rahmen faerbt sich mit
     Seitengrund und Kopfzeile mit (data-ton am Abschnitt). */
  background: var(--buehne);
  overflow: hidden;
}

/* Der ganze Text der Seite steht in der Textschrift; die Titel setzen sich
   mit --s1-titel darueber hinweg. Die Schrift hat nur einen fetten Schnitt,
   darum gilt sie hier samt Gewicht. */
.stil-site__page {
  padding: 0 var(--s1-pad);
  font-family: var(--s1-text);
  font-weight: 700;
  will-change: transform;
}

/* Inhalt auf Lesebreite, Footer bricht per Negativ-Margin wieder aus. */
.stil-site__page > * {
  max-width: 1120px;
  margin-left: auto;
  margin-right: auto;
}




/* Der obere Abstand nimmt den Platz der entfernten Teile auf: Footer (196px
   Hoehe plus 16px Aussenabstand) und Navigation (63px). Die Seite behaelt
   dadurch ihre Laenge — was hier zaehlt, weil die Sticky-Strecke sie ueber
   ihre Laenge durchscrollt — und der Titel steht unveraendert an seinem
   Platz. */
.stil-site__hero { padding: 331px 0 48px; }

/* Die Titel stehen in der breiten Archivo. Sie laeuft von Haus aus breit,
   darum nur ein knapper negativer Zeichenabstand. */
.stil-site__hero h3 {
  margin: 0;
  font-family: var(--s1-titel);
  font-size: clamp(36px, 4.4vw, 66px);
  line-height: 1.02;
  letter-spacing: -.01em;
  font-weight: 700;
}

.stil-site__hero p {
  margin: 22px 0 12px;
  max-width: 34em;
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink-2);
}

.stil-site__cta {
  display: inline-block;
  margin-bottom: 36px;
  font-size: 14px;
  font-weight: 500;
  color: var(--s1-accent);
  border-bottom: 1.5px solid var(--s1-accent);
  padding-bottom: 2px;
}

/* Platzhalter fuer Fotografie: die Farbe der Seite sitzt in den Bildern,
   nicht im UI — jede Flaeche traegt einen eigenen, gedeckten Ton. */
.stil-site__img {
  display: flex;
  align-items: flex-end;
  padding: 14px 16px;
  aspect-ratio: 3 / 2;
  background: linear-gradient(160deg, #c5a37a, #96714c);
}

.stil-site__img span {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .05em;
  color: rgba(251, 250, 248, .85);
}

.stil-site__img--hero { aspect-ratio: 21 / 9; }

.stil-site__img--gruen { background: linear-gradient(160deg, #9db08b, #6d8259); }
.stil-site__img--ziegel { background: linear-gradient(160deg, #c2937f, #9a6a56); }
.stil-site__img--schiefer { background: linear-gradient(160deg, #93a7b4, #64798a); }
.stil-site__img--tanne { background: linear-gradient(160deg, #6f8471, #47594c); }

/* Die Fotos fuellen auch die schmalen Galerie- und Projektpaneele aus. */
.stil-site__img--foto { position: relative; overflow: hidden; }
.stil-site__img--foto picture,
.stil-site__img--foto img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
.stil-site__img--foto img { object-fit: cover; }
.stil-site__img--foto::after {
  content: "";
  position: absolute;
  inset: 50% 0 0;
  background: linear-gradient(transparent, rgba(0, 0, 0, .55));
  pointer-events: none;
}
.stil-site__img--foto span { position: relative; z-index: 1; color: #fff; }
.stil-site__img--foto .stil-galerie__leiste { z-index: 2; }

/* Akkordeon-Galerie im Hero: schmale Paneele nebeneinander, das gehoverte
   waechst per flex-grow auf, die uebrigen stauchen sich. Die Beschriftung
   erscheint erst im ausgeweiteten Zustand. */
.stil-galerie {
  display: flex;
  gap: 10px;
  aspect-ratio: 21 / 9;
}

.stil-galerie .stil-site__img {
  position: relative;
  flex: 1 1 0;
  aspect-ratio: auto;
  min-width: 0;
  overflow: hidden;
  transition: flex-grow .55s var(--ease);
}

.stil-galerie .stil-site__img span {
  opacity: 0;
  white-space: nowrap;
  transition: opacity .3s ease .15s;
}

/* Die Auswahl steckt in einer Klasse statt in :hover, denn sie soll bestehen
   bleiben, wenn der Zeiger die Galerie verlaesst — ein Hover-Zustand endet
   zwangslaeufig mit dem Zeiger. Auch das noetige Verweilen von einer Zehntel-
   sekunde steuert das Skript, siehe js/main.js. */
.stil-galerie .stil-site__img.is-aktiv { flex-grow: 4; }
.stil-galerie .stil-site__img.is-aktiv span { opacity: 1; }

/* Fortschrittsleiste am unteren Rand des ausgewaehlten Bildes. Sie laeuft
   erst los, wenn der Zeiger die Galerie verlassen hat, und schaltet am Ende
   zum naechsten Bild weiter — Ablauf und Laufzeit stehen in js/main.js.

   Bewegt wird ueber transform statt ueber die Breite: Das laesst sich
   fluessiger darstellen und macht den Fortschritt unabhaengig davon, wie
   breit das Paneel gerade ist. */
.stil-galerie__leiste {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 4px;
  background: rgba(255, 255, 255, .3);
  transform: scaleX(0);
  transform-origin: left center;
  pointer-events: none;
  transition: opacity .3s ease;
}

/* Ausgeblendet wird die Leiste, wenn sie durchgelaufen ist und das naechste
   Bild uebernimmt, und ebenso, wenn der Zeiger zurueck in die Galerie kommt
   und den Lauf unterbricht. Erst nach dem Ausblenden wird sie zurueckgesetzt,
   damit sie nicht sichtbar auf null zurueckspringt. */
.stil-galerie__leiste.is-aus { opacity: 0; }

/* Beim Unterbrechen durch den Zeiger kuerzer: Dort uebernimmt sofort wieder
   die Handsteuerung, und die Leiste soll dem nicht hinterherhaengen. */
.stil-galerie__leiste.is-aus--flott { transition-duration: .14s; }

.stil-site__sec {
  padding: 44px 0;
  border-top: 1px solid var(--hairline);
}

.stil-site__label {
  display: block;
  margin-bottom: 26px;
  font-size: 12px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--s1-accent);
}

.stil-site__split {
  display: grid;
  grid-template-columns: 3fr 2fr;
  gap: 48px;
  align-items: start;
}

.stil-site__split > p {
  margin: 0;
  max-width: 32em;
  font-size: 16px;
  line-height: 1.65;
  color: var(--ink-2);
}

.stil-site__stats {
  margin: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

.stil-site__stats dt {
  font-size: clamp(26px, 2.6vw, 40px);
  font-weight: 600;
  letter-spacing: -.02em;
}

.stil-site__stats dd {
  margin: 4px 0 0;
  font-size: 12px;
  color: var(--ink-4);
}

/* Die Spalten teilen die Zeile in Drittel: Das Bild nimmt genau eines ein,
   der Text die beiden anderen. Beim Hovern fahren zwei weitere Bilder hinter
   dem ersten hervor und decken die Zeile in drei gleichen Dritteln ab —
   dieselbe Breite wie im Ruhezustand, deshalb ohne Abstand zwischen den
   Spalten; den Abstand zum Text traegt der Text selbst. */
.stil-site__projekt {
  position: relative;
  display: grid;
  grid-template-columns: 2fr 3fr;
  gap: 36px;
  align-items: center;
  padding: 20px 0;
}

.stil-site__projekt + .stil-site__projekt { border-top: 1px solid var(--hairline); }

/* Haelt die Hoehe der Zeile frei; die Bilder darin liegen absolut darueber
   und koennen deshalb nach rechts hinauswachsen, ohne das Raster zu
   verschieben. Die Hoehe bleibt beim Hovern damit unveraendert. */
.stil-site__bildfeld {
  /* Bewusst ohne position: relative — sonst waere diese Zelle der Bezug der
     Bilder darin, und ein Drittel meinte ein Drittel der Zelle statt der
     Zeile. Bezug ist .stil-site__projekt. */
  aspect-ratio: 4 / 3;
}

/* Deckt die ganze Zeile ab, nicht nur die erste Spalte: Nur so laesst sich
   jedes Bild auf ein Drittel der Zeilenbreite legen. Weder die Flaeche noch
   die Bilder nehmen Zeigerereignisse an — sie liegen ueber Text und Zelle und
   wuerden sonst beides verdecken. */
.stil-site__bilder {
  position: absolute;
  /* Der Innenabstand der Zeile wird ausgespart, damit die Bilder genau so
     hoch sind wie die Zelle, die die Hoehe haelt. */
  top: 20px;
  bottom: 20px;
  left: 0;
  right: 0;
  z-index: 1;
  pointer-events: none;
}

/* Ruhezustand: so breit wie die erste Rasterspalte, also zwei Fuenftel der
   Zeile abzueglich des Spaltenabstands — unveraendert gegenueber der
   Fassung ohne Auffaechern. Beim Hovern wird daraus ein Drittel der Zeile,
   dieselbe Breite fuer alle drei. */
.stil-site__projekt .stil-site__img {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: calc((100% - 36px) * 2 / 5);
  aspect-ratio: auto;
  pointer-events: none;
  transition: width .55s var(--ease), transform .55s var(--ease);
}

/* Das erste Bild liegt obenauf, die beiden anderen genau darunter — sie
   fahren beim Hovern jeweils um ihre eigene Breite nach rechts hervor. */
.stil-site__projekt .stil-site__img:nth-child(1) { z-index: 3; }
.stil-site__projekt .stil-site__img:nth-child(2) { z-index: 2; }
.stil-site__projekt .stil-site__img:nth-child(3) { z-index: 1; }

/* Ausgeloest wird ueber die Rasterzelle, nicht ueber die Bilder: Sie ist
   genau das Rechteck des Ausgangsbildes und behaelt diese Groesse auch im
   aufgefaecherten Zustand. Die Bilder selbst taugen nicht als Flaeche — das
   erste wird beim Auffaechern schmaler, und die beiden anderen liegen dann
   ueber dem Text, wo ein Hovern die Zeile offen hielte. */
/* Ein Pixel breiter als das Drittel, damit die Bilder einander leicht
   ueberlappen: Bei exakt gleich breiten Dritteln bleibt an den Stossstellen
   je nach Rundung auf ganze Bildpunkte eine haarfeine Luecke sichtbar. Der
   Versatz nimmt das zusaetzliche Pixel wieder heraus, damit die Bilder trotz
   groesserer Breite genau auf den Dritteln sitzen. Das letzte bleibt exakt
   ein Drittel breit, sonst ragte es ueber die Zeile hinaus. */
.stil-site__bildfeld:hover .stil-site__img { width: calc(33.3333% + 1px); }
.stil-site__bildfeld:hover .stil-site__img:nth-child(2) { transform: translateX(calc(100% - 1px)); }
.stil-site__bildfeld:hover .stil-site__img:nth-child(3) {
  width: 33.3333%;
  transform: translateX(200%);
}

/* Gespiegelte Zeile: Bild rechts, Text links und rechtsbuendig, damit er zur
   Bildkante hin ausschliesst. Die Bilder haengen an der rechten Kante und
   faechern nach links auf — Vorzeichen und Bezugskante gedreht, die
   Ueberlappung um ein Pixel bleibt. */
.stil-site__projekt--gespiegelt { grid-template-columns: 3fr 2fr; }
.stil-site__projekt--gespiegelt .stil-site__bildfeld { grid-column: 2; grid-row: 1; }
.stil-site__projekt--gespiegelt > :last-child { grid-column: 1; grid-row: 1; text-align: right; }

.stil-site__projekt--gespiegelt .stil-site__img {
  left: auto;
  right: 0;
}

.stil-site__projekt--gespiegelt .stil-site__bildfeld:hover .stil-site__img:nth-child(2) {
  transform: translateX(calc(-100% + 1px));
}

.stil-site__projekt--gespiegelt .stil-site__bildfeld:hover .stil-site__img:nth-child(3) {
  transform: translateX(-200%);
}

@media (prefers-reduced-motion: reduce) {
  .stil-site__projekt .stil-site__img { transition: none; }
}

.stil-site__projekt h4 {
  margin: 0;
  font-family: var(--s1-titel);
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -.01em;
}

.stil-site__projekt p {
  margin: 8px 0 0;
  font-size: 13px;
  color: var(--ink-4);
}

.stil-site__news {
  display: grid;
  grid-template-columns: 100px 1fr;
  gap: 24px;
  padding: 16px 0;
}

.stil-site__news + .stil-site__news { border-top: 1px solid var(--hairline); }

.stil-site__news span {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-4);
  padding-top: 3px;
}

.stil-site__news p {
  margin: 0;
  max-width: 40em;
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink-2);
}





/* ---------- Stil 2: fiktives Innenarchitektur-Studio ----------
   Warmer Creme-Grund, Serifen-Headlines, Waldgruen als Akzent, Pfeil-CTAs
   — bewusst weicher und dekorativer als Stil 1, damit die beiden Stile
   klar auseinanderliegen. Gleiche Scroll-Mechanik (js/main.js). */
.stil-site2 {
  --s2-bg: #f4efe6;
  --s2-ink: #29261f;
  --s2-ink-soft: #6b6558;
  --s2-accent: #35523e;
  --s2-serif: Georgia, 'Times New Roman', serif;
  --s2-pad: clamp(28px, 5vw, 64px);
  width: 100%;
  height: 100dvh;
  background: var(--s2-bg);
  color: var(--s2-ink);
  overflow: hidden;
}

.stil-site2__page {
  padding: 0 var(--s2-pad);
  will-change: transform;
}

.stil-site2__page > * {
  max-width: 1060px;
  margin-left: auto;
  margin-right: auto;
}

/* Wie bei Stil 1 nimmt der obere Abstand grob den Platz der entfernten
   Teile auf (Navigation 69px, Fuss 196px plus 56px Aussenabstand), haelt
   die Seite also lang genug fuer die Sticky-Strecke und rueckt den Inhalt
   von der Kopfzeile weg. Der Titel steht dabei bewusst etwas hoeher als
   der reine Ausgleich ergaebe. */
.stil-site2__hero {
  padding: 325px 0 72px;
  text-align: center;
}

.stil-site2__hero h3 {
  margin: 0 auto;
  max-width: 14em;
  font-family: var(--s2-serif);
  font-size: clamp(38px, 4.6vw, 68px);
  line-height: 1.08;
  letter-spacing: -.01em;
  font-weight: 400;
}

.stil-site2__hero p {
  margin: 22px auto 14px;
  max-width: 30em;
  font-size: 16px;
  line-height: 1.65;
  color: var(--s2-ink-soft);
}

.stil-site2__cta {
  position: relative;
  display: inline-block;
  margin: 22px 0 44px;
  padding: 13px 26px;
  font-size: 14px;
  letter-spacing: .03em;
  color: var(--s2-bg);
  background: var(--s2-accent);
  border-radius: 0;
  transition: background .2s var(--ease), border-radius .3s var(--ease);
}

/* Hinter dem Knopf liegt eine gleich grosse Flaeche im selben Gruen, im
   Ruhezustand von ihm verdeckt. Beim Ueberfahren waechst sie darueber
   hinaus und stellt sich leicht schraeg — als schaue eine zweite Karte
   darunter hervor.

   Der Knopf traegt bewusst kein z-index: Ein eigener Stapel wuerde die
   Flaeche zwar hinter seinen Inhalt, aber vor seinen Grund legen, sodass
   sie quer ueber ihn liefe. */
.stil-site2__cta::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--s2-accent);
  /* Groesse und Drehung stehen als eigene Eigenschaften da, nicht in einem
     gemeinsamen transform: nur so laesst sich die Drehung spaeter einsetzen
     als das Wachsen. */
  scale: .72;
  rotate: 0deg;
  opacity: 0;
  transition: scale .38s var(--ease),
              rotate .32s var(--ease) .1s,
              opacity .38s var(--ease);
}

/* In der Hoehe waechst die Flaeche staerker als in der Breite: So schaut
   sie oben und unten deutlicher hinter dem Knopf hervor. */
a.stil-site2__cta:hover::before,
a.stil-site2__cta:focus-visible::before {
  scale: 1.16 1.34;
  rotate: -2deg;
  opacity: 1;
}

/* Der Verweis auf die Kontaktseite ist die einzige Schaltflaeche der Strecke,
   die wirklich fuehrt; die Farbe der Seite gilt auch beim Ueberfahren, sonst
   uebernaehme die Regel fuer gewoehnliche Verweise. */
a.stil-site2__cta:hover,
a.stil-site2__cta:focus-visible {
  color: var(--s2-bg);
  background: #4a7758;
  border-radius: 5px;
}

.stil-site2__img {
  display: flex;
  align-items: flex-end;
  padding: 14px 16px;
  aspect-ratio: 3 / 2;
  background: linear-gradient(160deg, #cdbfa6, #a3937a);
}

.stil-site2__img span {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .05em;
  color: rgba(251, 250, 248, .85);
}

/* Ueber die ganze Breite des Rahmens: Innenabstand der Seite mit negativen
   Aussenabstaenden aufheben und die Breitenbegrenzung der Seitenkinder loesen
   — dasselbe Vorgehen wie beim Footer. */
.stil-site2__img--hero {
  margin-left: calc(-1 * var(--s2-pad));
  margin-right: calc(-1 * var(--s2-pad));
  max-width: none;

  /* Hoehe unveraendert gegenueber der schmalen Fassung. Ein festes
     Seitenverhaeltnis waere hier falsch: Auf voller Breite waere das Bild
     dadurch deutlich hoeher geworden. Die Hoehe richtet sich deshalb
     weiterhin nach der frueheren Bildbreite — hoechstens 1060px, sonst die
     Seitenbreite ohne Innenabstand — im Verhaeltnis 21:9 (also mal 3/7). */
  aspect-ratio: auto;
  height: calc(min(1060px, 100vw - 2 * var(--s2-pad)) * 3 / 7);
}

.stil-site2__img--salbei { background: linear-gradient(160deg, #a9b39a, #7d8a6d); }
.stil-site2__img--lehm { background: linear-gradient(160deg, #c9a68b, #a17c60); }
.stil-site2__img--stein { background: linear-gradient(160deg, #bdb6ab, #8f887c); }
.stil-site2__img--nacht { background: linear-gradient(160deg, #7e8a8c, #545f63); }

/* Fotos passen sich der Drift-Wand und den hohen Portfolio-Kacheln an. */
.stil-site2__img--foto { position: relative; overflow: hidden; padding: 0; }
.stil-site2__img--foto picture,
.stil-site2__img--foto img {
  display: block;
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.stil-site2__img--foto img { object-fit: cover; }

/* Drift-Wand: Portierung der React-Bits-Komponente DriftWall (JS-CSS-
   Variante) als Vanilla-Version, Aufbau und Werte aus deren Quelle:
   Container mit Perspektive (1200px), darin eine zentrierte, raeumlich
   gekippte Ebene (rotateX 16, rotateY -14, translateZ -120, scale 1.18) aus
   Spalten, deren Tracks einzeln vertikal driften. Kacheln 200x132 mit
   18px Abstand und Radius 14, zurueckgenommen (Opacity 0.55 plus helles
   Overlay); die aktive Kachel unterm Zeiger tritt in voller Farbe hervor
   und hebt sich um 64px (translateZ). Anders als in der Quelle steht die
   Wand auf hellem statt dunklem Grund, passend zum Rest der Studio-Seite.
   Spaltenbau, Endlos-Kopien und Animation in js/main.js. */
.stil-drift {
  --dw-tile-w: 200px;
  --dw-tile-h: 132px;
  --dw-gap: 18px;
  --dw-radius: 14px;
  --dw-lift: 64px;
  --dw-dim: .55;
  --dw-overlay: #fff;
  /* Rechte Kante der breiten gruenen Flaeche, zugleich Bezugspunkt der
     schmalen Linie daneben. */
  --dw-kante: 30.5%;
  position: relative;
  max-width: none;
  margin: 0 calc(-1 * var(--s2-pad));
  height: min(600px, 70dvh);
  background: #fff;
  overflow: hidden;
  perspective: 1200px;
  perspective-origin: 50% 50%;
}

/* Gruene Wand im linken Drittel. Sie liegt ueber der Ebene und schneidet
   damit auch die Kacheln ab, die perspektivisch ins linke Drittel ragen.
   Der Ueberhang nach links und oben/unten sorgt dafuer, dass durch die
   Neigung nirgends eine Kante im Bild endet; sichtbar ist nur die rechte,
   um 12 Grad geneigte Kante (Neigung der Lanes, siehe rotateZ der Ebene
   plus deren perspektivische Verzerrung). Der Einfahrfortschritt steht in
   --dw-wand (0 = ganz links draussen, 1 = an Ort), gesetzt in js/main.js. */
.stil-drift__wand {
  position: absolute;
  top: -12%;
  bottom: -12%;
  z-index: 1;
  background: var(--s2-accent);
  /* Der Weg ist in vw angegeben, nicht in Prozent der eigenen Breite:
     sonst legte die schmale Linie nur ein paar Pixel zurueck und stuende
     schlagartig da, statt wie die breite Flaeche hereinzufahren. */
  transform: skewX(-12deg) translateX(calc((var(--dw-wand, 0) - 1) * 100vw));
}

/* Breite Wand: Der Ueberhang nach links bleibt, verschoben wird nur die
   sichtbare rechte Kante — sie steht in --dw-kante. */
.stil-drift__wand--flaeche {
  left: -30%;
  width: calc(var(--dw-kante) + 30%);
}

/* Schmale Linie, wenige Pixel rechts der Kante. Sie haengt an derselben
   Groesse wie die Flaeche und nicht an einem eigenen Prozentwert: Beide
   erhalten dieselbe Neigung, deren waagrechter Versatz aber von der Hoehe des
   Bandes abhaengt und nicht von seiner Breite. Zwei getrennte Prozentwerte
   liefen deshalb mit der Fensterbreite auseinander — bei 1280px lag die Linie
   hinter der Flaeche, bei 1920px stand sie 42 Pixel daneben. */
.stil-drift__wand--linie {
  left: calc(var(--dw-kante) + 16px);
  width: 10px;
}

/* Die Ebene fuellt nur das rechte Drittelpaar des Containers: ihr
   Mittelpunkt liegt bei zwei Dritteln der Breite, ihre Spaltenzahl deckt
   zwei Drittel ab (js/main.js). Links bleibt ein Drittel frei. */
.stil-drift__plane {
  position: absolute;
  top: 50%;
  left: 66.667%;
  display: flex;
  flex-direction: row;
  transform-style: preserve-3d;
  transform-origin: 50% 50%;
  /* rotateZ kippt die Spalten im Uhrzeigersinn (roll-Wert der Quelle). */
  transform: translate(-50%, -50%) scale(1.18) rotateX(16deg) rotateY(-14deg) rotateZ(9deg) translateZ(-120px);
  will-change: transform;
}

.stil-drift__col {
  position: relative;
  width: calc(var(--dw-tile-w) + var(--dw-gap));
  transform-style: preserve-3d;
}

.stil-drift__track {
  display: flex;
  flex-direction: column;
  will-change: transform;
  transform-style: preserve-3d;
}

.stil-drift__tile {
  position: relative;
  display: block;
  width: 100%;
  height: calc(var(--dw-tile-h) + var(--dw-gap));
  flex: 0 0 auto;
  transform-style: preserve-3d;
}

.stil-drift__inner {
  position: absolute;
  inset: calc(var(--dw-gap) / 2);
  display: block;
  border-radius: var(--dw-radius);
  overflow: hidden;
  background: #fff;
  opacity: var(--dw-dim);
  transform: translateZ(0);
  pointer-events: none;
  transition:
    transform .42s cubic-bezier(.22, 1, .36, 1),
    opacity .42s cubic-bezier(.22, 1, .36, 1),
    box-shadow .42s cubic-bezier(.22, 1, .36, 1);
}

/* Die Bilder aus der Quelle fuellen die Kacheln der Drift-Wand. */
.stil-drift__inner .stil-site2__img {
  width: 100%;
  height: 100%;
  aspect-ratio: auto;
  filter: saturate(.92);
  transition: filter .42s cubic-bezier(.22, 1, .36, 1);
}

.stil-drift__overlay {
  position: absolute;
  inset: 0;
  background: var(--dw-overlay);
  opacity: .42;
  pointer-events: none;
  transition: opacity .42s cubic-bezier(.22, 1, .36, 1);
}

.stil-drift__tile.is-aktiv .stil-drift__inner {
  opacity: 1;
  transform: translateZ(var(--dw-lift));
  box-shadow: 0 20px 48px -18px rgba(26, 24, 20, .32);
}

.stil-drift__tile.is-aktiv .stil-site2__img { filter: saturate(1.05); }

.stil-drift__tile.is-aktiv .stil-drift__overlay { opacity: 0; }

.stil-site2__sec { padding: 40px 0 48px; }

.stil-site2__label {
  display: block;
  margin-bottom: 26px;
  font-size: 12px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--s2-accent);
  text-align: center;
}

.stil-site2__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 22px;
}

@media (max-width: 760px) {
  .stil-site2__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

.stil-site2__tile .stil-site2__img { aspect-ratio: 4 / 5; }

.stil-site2__tile h4 {
  margin: 12px 0 0;
  font-family: var(--s2-serif);
  font-size: 16px;
  font-weight: 400;
  text-align: center;
}

.stil-site2__h {
  margin: 0 auto;
  max-width: 18em;
  font-family: var(--s2-serif);
  font-size: clamp(26px, 2.8vw, 40px);
  line-height: 1.15;
  font-weight: 400;
  text-align: center;
}

.stil-site2__leistungen {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 28px;
  margin-top: 40px;
}

.stil-site2__leistungen h4 {
  margin: 0 0 8px;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .02em;
}

.stil-site2__leistungen p {
  margin: 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--s2-ink-soft);
}

.stil-site2__quote {
  padding: 56px 0;
  border-top: 1px solid rgba(41, 38, 31, .14);
  border-bottom: 1px solid rgba(41, 38, 31, .14);
  text-align: center;
}

.stil-site2__quote p {
  margin: 0 auto;
  max-width: 26em;
  font-family: var(--s2-serif);
  font-style: italic;
  font-size: clamp(20px, 2.2vw, 28px);
  line-height: 1.4;
}

.stil-site2__quote span {
  display: block;
  margin-top: 18px;
  font-size: 13px;
  color: var(--s2-ink-soft);
}

.stil-site2__kontakt {
  padding: 64px 0 56px;
  text-align: center;
}

.stil-site2__kontakt p {
  margin: 18px auto 26px;
  max-width: 28em;
  font-size: 15px;
  line-height: 1.6;
  color: var(--s2-ink-soft);
}

.stil-site2__kontakt .stil-site2__cta { margin-bottom: 0; }

/* ---------- Eigener Zeiger in Stil 2 ----------
   Die Form folgt der Zeigerposition, die js/main.js als --zx und --zy
   (in Pixeln, ohne Einheit) setzt. Der Versatz von je 12 Pixeln holt den
   Klickpunkt der Zeichnung auf den Zeigerpunkt zurueck, siehe Kommentar am
   Markup in index.html. */
.stil-zeiger {
  position: fixed;
  left: 0;
  top: 0;
  z-index: 60;
  pointer-events: none;
  opacity: 0;
  transition: opacity .25s var(--ease);
  transform: translate3d(calc(var(--zx, 0) * 1px - 12px), calc(var(--zy, 0) * 1px - 12px), 0);
}

.stil-zeiger.is-sichtbar { opacity: 1; }

/* Dreieck und Kreis liegen uebereinander und loesen sich gegenseitig ab.
   Gedreht und skaliert wird um den Klickpunkt: transform-box view-box legt
   den Ursprung auf die linke obere Ecke der viewBox, 12/12 ruecken von dort
   auf den Nullpunkt der Zeichnung. */
.stil-zeiger__form {
  transform-box: view-box;
  transform-origin: 12px 12px;
  transition: opacity .2s var(--ease), scale .2s var(--ease);
}

.stil-zeiger__kreis { opacity: 0; scale: .4; }

.stil-zeiger.is-punkt .stil-zeiger__dreieck { opacity: 0; scale: .4; }
.stil-zeiger.is-punkt .stil-zeiger__kreis { opacity: 1; scale: 1; }

/* Solange das Dreieck laeuft, bleibt der gewoehnliche Zeiger aus. Die Klasse
   setzt js/main.js auf den Abschnitt, damit ohne Skript nichts fehlt. Der
   Nachfahrenselektor ist noetig, weil Verweise und Schaltflaechen sonst ihre
   eigene Zeigerform behielten und neben dem Kreis eine Hand erschiene. */
.hat-zeiger,
.hat-zeiger * { cursor: none; }

/* ---------- Stil 3: fiktives Architekturbuero ----------
   Radikal minimalistisches Portfolio nach dem Vorbild zweier realer
   Architekturbuero-Seiten: strikt Schwarzweiss, durchgehend kleine,
   einheitliche Schriftgroessen (kein Display-Hero), bildgetrieben mit
   grossem Auftaktbild, dichtes uniformes Werkraster mit Nummer, Typ,
   Kategorie und Ort, schlichter Text-Footer. Fotografie (hier graue
   Tonflaechen) ist das einzige grosse Element. Gleiche Scroll-Mechanik
   wie Stil 1/2 (js/main.js). */
.stil-site3 {
  /* Dunkel ist die Voreinstellung. Der Umschalter links in der Kopfzeile
     setzt data-hell und dreht die Palette; alles darunter liest nur diese
     vier Werte, damit der Wechsel an einer Stelle geschieht. */
  --s3-grund: #17171a;
  --s3-ink: #eceae5;
  --s3-grau: #8b8a85;
  --s3-hairline: rgba(236, 234, 229, .17);
  --s3-raster: #ffffff;
  --s3-pad: clamp(20px, 3vw, 40px);
  /* Der Rahmen steht auf allen Seiten ein Stueck ueber das Sichtfeld
     hinaus. Der Sticky-Behaelter schneidet den Ueberstand weg, aber der
     Verzerrungsfilter in js/main.js hat damit auch fuer die aeusserste
     sichtbare Zeile und Spalte noch Bildmaterial — sonst deckt er sie
     bei gebrochener Bildschirmskalierung nur zum Teil und laesst dort
     einen hellen Strich durchschimmern. */
  --s3-ueberstand: 10px;
  /* Seitenrand samt Ueberstand: haelt die sichtbaren Raender genau dort,
     wo sie ohne den Ueberstand laegen. */
  --s3-rand: calc(var(--s3-pad) + var(--s3-ueberstand));
  /* Auslauf unter dem Fuss: die Biegung setzt bei rund 85 Prozent der
     Bildhoehe ein, und Text soll nicht hineinlaufen. Am Ende der Strecke
     steht der Fuss dadurch oberhalb der Verzerrung, unter ihm bleibt
     ruhige Flaeche. */
  --s3-auslauf: 155px;
  position: relative;
  /* Breiter als der Behaelter und nicht schrumpfend; die Mitte bleibt
     durch justify-content in der Mitte, der Ueberstand verteilt sich
     also gleichmaessig auf beide Seiten. */
  width: calc(100% + var(--s3-ueberstand) * 2);
  flex-shrink: 0;
  height: calc(100dvh + var(--s3-ueberstand));
  align-self: flex-start;
  background: var(--s3-grund);
  color: var(--s3-ink);
  overflow: hidden;
  font-size: 13px;
}

.stil-site3[data-hell] {
  --s3-grund: #fff;
  --s3-ink: #1a1a1a;
  --s3-grau: #6e6e6a;
  --s3-hairline: rgba(26, 26, 26, .16);
  --s3-raster: #000000;
}

/* Das Zeigerraster liegt zwischen Grund und Seite. Es nimmt keine
   Zeigereignisse an, damit Verweise und der Hover im Werkraster
   weiterhin greifen; gelauscht wird am Rahmen. */
.stil-raster {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: block;
  pointer-events: none;
}

.stil-site3__page {
  position: relative;
  z-index: 1;
  /* Unten der Auslauf plus der Ausgleich fuer den Ueberstand des
     Rahmens; zusammen bestimmen sie, wo die Seite am Streckenende
     stehen bleibt. */
  padding: 0 var(--s3-rand) calc(var(--s3-auslauf) + var(--s3-ueberstand));
  will-change: transform;
}

/* Auftakt: ein grosses Bild, volle Breite, Bildlegende klein darunter. */
.stil-site3__hero {
  position: relative;
  margin: 0 calc(-1 * var(--s3-rand));
}

/* Siegel im Auftakt: es sitzt unter der ersten Titelzeile, aber als
   eigenes Element daneben — der Einflug des Titels laesst es also in
   Ruhe. Weil beide Zeilen mittig im Block stehen, endet die erste genau
   auf halber Hoehe; von dort ab ist links Platz, waehrend die zweite
   Zeile rechts laeuft. */
.stil-site3__siegel {
  position: absolute;
  /* Nimmt keine Zeigereignisse an: es liegt im selben Feld wie die
     Titelzeilen und faenge ihnen sonst den Hover weg. */
  pointer-events: none;
  /* Lage rechnet js/main.js: Mitte des freien Felds links neben der
     zweiten Titelzeile und unter der ersten. Die Werte hier gelten nur,
     bis die erste Messung durch ist. */
  left: 25%;
  top: 70%;
  transform: translate(-50%, -50%);
  width: 190px;
  height: 190px;
  /* Rein weiss beziehungsweise rein schwarz, nicht der gebrochene Ton
     der Palette: das Siegel soll als Stempel stehen. */
  color: #fff;
}

.stil-site3[data-hell] .stil-site3__siegel { color: #000; }

/* Der Ring dreht sich, die Marke darin steht still. */
.stil-site3__ring {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  animation: s3-siegel-dreht 12s linear infinite;
}

.stil-site3__ring text {
  font-family: 'Quilon', var(--font);
  font-weight: 700;
  font-size: 46px;
  letter-spacing: .9px;
  fill: currentColor;
}

@keyframes s3-siegel-dreht {
  to { transform: rotate(360deg); }
}

/* Solange das Siegel gar nicht zu sehen ist — ein anderer Abschnitt
   steht auf der Buehne, oder die Mini-Seite ist am Siegel vorbei
   hochgefahren (data-siegel-fern aus js/main.js) — ruht die Drehung.
   Sie wuerde sonst in jedem Bild den Verzerrungsfilter des Rahmens
   neu rechnen lassen, ohne dass sich sichtbar etwas tut. */
html:not([data-stil-aktiv="3"]) .stil-site3__ring,
.stil-site3[data-siegel-fern] .stil-site3__ring {
  animation-play-state: paused;
}

.stil-site3__marke {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 84px;
  height: 84px;
  margin: -42px 0 0 -42px;
  /* Angewinkelt, damit der Zirkel im drehenden Ring nicht wie
     hingestellt wirkt. */
  transform: rotate(-15deg);
}

@media (prefers-reduced-motion: reduce) {
  .stil-site3__ring { animation: none; }
}

/* Auftakt-Schriftzug anstelle des Bildes: nimmt dieselbe Flaeche ein,
   damit Legende und Scrollstrecke unveraendert sitzen. */
.stil-site3__titel {
  height: 74dvh;
  margin: 0;
  padding: 0 var(--s3-rand);
  display: flex;
  flex-direction: column;
  justify-content: center;
  font-family: 'Quilon', var(--font);
  font-weight: 700;
  /* Nicht markierbar: der Schriftzug ist Bild, kein Text zum Kopieren,
     und ein blauer Auswahlbalken quer ueber die Zeilen stoert den
     Einflug. */
  -webkit-user-select: none;
  user-select: none;
  font-size: clamp(64px, 10.5vw, 168px);
  line-height: .96;
  letter-spacing: -.015em;
  color: var(--s3-ink);
}

/* Einflug durchs Scrollen: die Wortmarke kommt von links, die Fachzeile
   von rechts. Beide haengen an --flug (0 bis 1), das der Streckenlauf in
   js/main.js aus der Lage des Abschnitts fuehrt — und das dort einrastet,
   sobald der Einflug einmal durch ist. Kein Uebergang: die Bewegung
   gehoert dem Scrollrad, nicht einer Uhr. Der Rahmen schneidet ab, es
   ragt nichts heraus. */
/* Durchgehend als direkte Kinder angesprochen: die Zeilen tragen seit
   dem Zeigerwechsel je einen inneren Span, und der waere sowohl erstes
   als auch letztes Kind seines Elternteils — ohne den Kindpfeil griffen
   die beiden Regeln darunter also auch auf ihn zu und ueberschrieben
   mit ihrer hoeheren Spezifitaet dessen eigene Groesse. */
.stil-site3__titel > span {
  display: block;
  opacity: var(--flug, 0);
}

.stil-site3__titel > span:first-child {
  transform: translateX(calc((var(--flug, 0) - 1) * 108%));
}

.stil-site3__titel > span:last-child {
  text-align: right;
  transform: translateX(calc((1 - var(--flug, 0)) * 108%));
}

/* Zeigt der Zeiger auf eine der beiden Zeilen, waechst sie und die
   andere weicht zurueck. Die Groesse laeuft ueber transform und nicht
   ueber font-size: so wird nichts neu umbrochen, das Siegel bleibt
   stehen, und die Bewegung kostet nur die Kompositionsebene.

   Der Ankerpunkt ist die jeweils aussenliegende Kante — die Wortmarke
   waechst nach rechts, die Fachzeile nach links. Beide Zeilen behalten
   damit ihre Aussenkante und schieben sich nicht gegenseitig.

   Sechs Prozent sind die Obergrenze: darueber schiebt sich die
   waschsende Fachzeile in das Siegel hinein, das links von ihr sitzt. */
.stil-site3__titel > span > span {
  display: inline-block;
  transform: scale(var(--zoom, 1));
  transition: transform .42s var(--ease);
}

.stil-site3__titel > span:first-child > span { transform-origin: left center; }
.stil-site3__titel > span:last-child > span { transform-origin: right center; }

/* Der aeussere Span ist zeilenbreit und spraeche auch neben der Schrift
   an; gezeigt wird deshalb auf den inneren. */
.stil-site3__titel > span { pointer-events: none; }
.stil-site3__titel > span > span { pointer-events: auto; }

/* Der Zustand haengt an data-zeigt statt an :hover, obwohl :hover hier
   genuegen wuerde. Der Grund steht im Perspektiv-Prototyp: der zeigt am
   Fuss eine Kopie der Seite, und in die laesst sich ein Schwebezustand
   nicht uebertragen — er ist keine Aenderung am Dokument, sondern nur
   ein Zustand des echten Zeigers. Als Attribut geschrieben wandert er
   mit. Gesetzt wird es in js/main.js, nur fuer echte Zeiger.

   Die beiden Raten setzt ebenfalls js/main.js aus dem gemessenen Platz;
   die Werte hier greifen nur, falls das Skript nicht laeuft. */
@media (hover: hover) {
  .stil-site3__titel[data-zeigt="1"] > span:first-child > span { --zoom: var(--zoom-gross, 1.06); }
  .stil-site3__titel[data-zeigt="1"] > span:last-child > span { --zoom: var(--zoom-klein, .94); }
  .stil-site3__titel[data-zeigt="2"] > span:last-child > span { --zoom: var(--zoom-gross, 1.06); }
  .stil-site3__titel[data-zeigt="2"] > span:first-child > span { --zoom: var(--zoom-klein, .94); }
}

@media (prefers-reduced-motion: reduce) {
  .stil-site3__titel > span { opacity: 1; transform: none; }
  .stil-site3__titel > span > span { transition: none; }
}


.stil-site3__img {
  display: flex;
  align-items: flex-end;
  padding: 12px 14px;
  aspect-ratio: 4 / 3;
  background: linear-gradient(165deg, #3a3937, #232320);
}

.stil-site3__img span {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: .05em;
  color: rgba(255, 255, 255, .8);
}

/* Nur Grau- und Betontoene, die Referenzen sind praktisch farblos. */
.stil-site3__img--a { background: linear-gradient(165deg, #3f3e3a, #292824); }
.stil-site3__img--b { background: linear-gradient(165deg, #39393b, #25252a); }
.stil-site3__img--c { background: linear-gradient(165deg, #3b3a36, #272622); }
.stil-site3__img--d { background: linear-gradient(165deg, #343432, #212120); }
.stil-site3__img--e { background: linear-gradient(165deg, #3e3c37, #2a2823); }
.stil-site3__img--f { background: linear-gradient(165deg, #2f2f2d, #1e1e1c); }

.stil-site3[data-hell] .stil-site3__img { background: linear-gradient(165deg, #c9c7c1, #97958f); }
.stil-site3[data-hell] .stil-site3__img--a { background: linear-gradient(165deg, #d3d0c9, #a5a29a); }
.stil-site3[data-hell] .stil-site3__img--b { background: linear-gradient(165deg, #b7b7b3, #878783); }
.stil-site3[data-hell] .stil-site3__img--c { background: linear-gradient(165deg, #c4c2bd, #8f8d88); }
.stil-site3[data-hell] .stil-site3__img--d { background: linear-gradient(165deg, #a9a9a5, #757571); }
.stil-site3[data-hell] .stil-site3__img--e { background: linear-gradient(165deg, #cfccc4, #9b978d); }
.stil-site3[data-hell] .stil-site3__img--f { background: linear-gradient(165deg, #9e9e9a, #6a6a66); }

/* Kachel mit echtem Bild statt Tonflaeche. Das Bild fuellt sie ganz aus;
   beim Hover wird die Kachel nach oben hin kleiner, der Ausschnitt
   wandert dann mit. */
.stil-site3__img--foto {
  padding: 0;
  overflow: hidden;
  background: #2a2926;
  cursor: pointer;
}

/* Anklickbar: jede Bildkachel schaltet reihum durch ihre Aufnahmen
   (js/main.js setzt data-wechsel-stand auf den Index des Bildes).
   Sichtbar ist genau die Aufnahme zum Stand, die uebrigen ruhen
   verborgen. Kind-Kombinator, damit die Regeln nur die Bilder der
   Kachel treffen und nicht die Kopie im Wechseldeck. */
.stil-site3__img--foto > picture { display: none; }

.stil-site3__img--foto > picture[data-bild="0"],
.stil-site3__img--foto[data-wechsel-stand="1"] > picture[data-bild="1"],
.stil-site3__img--foto[data-wechsel-stand="2"] > picture[data-bild="2"] { display: block; }

.stil-site3__img--foto[data-wechsel-stand="1"] > picture[data-bild="0"],
.stil-site3__img--foto[data-wechsel-stand="2"] > picture[data-bild="0"] { display: none; }

/* Wechseldeck: liegt beim Umschalten ueber der Kachel, zeigt schon den
   naechsten Stand und wird von einem Kreis freigestellt, der an der
   Tippstelle aufgeht (js/main.js setzt den clip-path). */
.stil-site3__wechsel {
  position: absolute;
  inset: 0;
  z-index: 1;
  /* Ausrollend statt der Hauskurve: der Kreis soll ab der Tippstelle
     sofort sichtbar aufgehen und weich ankommen — mit traegem Anlauf
     wirkte der Klick eine Viertelsekunde lang folgenlos. */
  transition: clip-path .55s cubic-bezier(.16, .74, .3, 1);
}

/* Ein Grund liegt nur noch unter dem Bild, solange es laedt: in jedem
   Stand kommt eine Aufnahme, keine Tonflaeche. */
.stil-site3__wechsel { background: #2a2926; }
.stil-site3[data-hell] .stil-site3__wechsel { background: #d3d0c9; }

.stil-site3__wechsel picture,
.stil-site3__wechsel img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Masse fuer beide, das display aber nur fuer das Bild selbst: welches
   <picture> sichtbar ist, entscheiden allein die Stand-Regeln weiter
   oben -- ein display: block hier wuerde sie ueberstimmen und alle
   Aufnahmen uebereinander zeigen. */
.stil-site3__img--foto picture,
.stil-site3__img--foto img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.stil-site3__img--foto img { display: block; }

.stil-site3__sec { padding: 48px 0 8px; }

/* Abschnitt ohne Ueberschrift: sie trug 18px Abstand nach unten, die
   hier ans obere Polster gehen, damit das Raster nicht hochrutscht. */
.stil-site3__sec--ohne-titel { padding-top: 66px; }

.stil-site3__sec > h4 {
  margin: 0 0 18px;
  font-size: 13px;
  font-weight: 400;
  text-transform: lowercase;
  color: var(--s3-grau);
}

/* Werkindex: uniforme Karten, drei Spalten, knappe Legenden. */
.stil-site3__werke {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 28px 20px;
}

/* Die Legende liegt unter dem Bild, ist im Ruhezustand aber davon
   verdeckt: das Bild ist absolut gesetzt und fuellt die ganze Karte. Beim
   Hovern wandert seine Unterkante um die Legendenhoehe nach oben, das Bild
   wird also nach oben hin kleiner und gibt den Text frei. Es steht dann
   genau auf der Flaeche des Platzhalters, also im 4:3-Format.
   .stil-site3__legende-h muss der tatsaechlichen Texthoehe entsprechen
   (zwei Zeilen a 18px plus 10px Abstand). */
.stil-site3__werk {
  position: relative;
  --s3-legende-h: 46px;
}

.stil-site3__platz { aspect-ratio: 4 / 3; }

.stil-site3__werk .stil-site3__img {
  position: absolute;
  inset: 0;
  /* Ueber der Legende halten: deren Zaehler ist selbst positioniert und
     stuende sonst durch die Dokumentreihenfolge auf dem Bild. */
  z-index: 1;
  aspect-ratio: auto;
  transition: bottom .45s var(--ease);
}

.stil-site3__werk:hover .stil-site3__img,
.stil-site3__werk.ist-schwebend .stil-site3__img { bottom: var(--s3-legende-h); }

.stil-site3__werk p {
  position: relative;
  margin: 0;
  padding-top: 10px;
  height: var(--s3-legende-h);
  font-size: 12px;
  line-height: 1.5;
}

/* Zaehler rechts in der Legende: welcher der drei Staende der Kachel
   gerade gezeigt wird (js/main.js schreibt ihn beim Durchschalten). */
.stil-site3__werk .zaehler {
  position: absolute;
  right: 0;
  top: 10px;
  display: flex;
  gap: 5px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--s3-grau);
}

/* Rollwerk: alter und neuer Wert liegen in derselben Zelle
   uebereinander, der alte rollt nach oben hinaus, der neue von unten
   herein (js/main.js tauscht die Klassen). Das Wort davor steht fest. */
/* Nur die vordere Zahl rollt; "/3" steht fest daneben. */
.stil-site3__werk .zaehler__rolle {
  display: inline-grid;
  overflow: hidden;
  vertical-align: bottom;
}

.stil-site3__werk .zaehler__rolle span {
  grid-area: 1 / 1;
  transition: transform .35s var(--ease), opacity .35s var(--ease);
}

.stil-site3__werk .zaehler__rolle .ist-neu { transform: translateY(115%); opacity: 0; }
.stil-site3__werk .zaehler__rolle .ist-weg { transform: translateY(-115%); opacity: 0; }

.stil-site3__werk p .nr {
  font-family: var(--mono);
  font-size: 11px;
  margin-right: 8px;
}

.stil-site3__werk p .ort {
  display: block;
  color: var(--s3-grau);
}

/* ---------- Startseite: Referenz ---------- */
.quote {
  margin: 0;
  font-size: clamp(24px, 2.7vw, 38px);
  line-height: 1.25;
  letter-spacing: -.02em;
  font-weight: 500;
  max-width: 26em;
  text-wrap: pretty;
}

.quote-person {
  display: flex;
  align-items: center;
  gap: 16px;
  align-self: end;
}

.quote-person__photo {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  flex: none;
  border: 1px solid var(--hairline-strong);
  background: repeating-linear-gradient(45deg, #f4f2ee, #f4f2ee 5px, #eae7e1 5px, #eae7e1 10px);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--mono);
  font-size: 8px;
  color: var(--ink-4);
}

.quote-person .name { font-size: 15px; font-weight: 600; }
.quote-person .role { font-size: 14px; color: var(--ink-4); margin-top: 3px; }

/* ---------- Abschluss-Sektionen ---------- */
.closing-actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 26px;
  margin-top: 44px;
  flex-wrap: wrap;
}

.closing-actions--wide { margin-top: 64px; }

/* ---------- Arbeit: Vorher/Nachher-Regler ---------- */
.compare {
  position: relative;
  border: 1px solid var(--hairline-strong);
  overflow: hidden;
  background: #f4f2ee;
}

.compare__scroll {
  height: 560px;
  overflow-y: auto;
  scrollbar-width: none;
  position: relative;
}

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

.compare__track { position: relative; height: 1900px; }

.compare__after,
.compare__before-inner {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 220px;
}

.compare__after {
  background: repeating-linear-gradient(45deg, #f4f2ee, #f4f2ee 8px, #eae7e1 8px, #eae7e1 16px);
}

.compare__before {
  position: absolute;
  inset: 0;
  clip-path: inset(0 50% 0 0);
}

.compare__before-inner {
  background: repeating-linear-gradient(45deg, #eceae4, #eceae4 8px, #ddd9d1 8px, #ddd9d1 16px);
}

.compare .ph-text {
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.9;
  color: var(--ink-footer);
  letter-spacing: .02em;
  text-align: center;
}

.compare__labels {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  justify-content: space-between;
  padding: 14px 16px;
  pointer-events: none;
}

.compare__labels span {
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-2);
  background: rgba(251, 250, 248, .86);
  padding: 5px 9px;
}

.compare__bar {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 2px;
  transform: translateX(-1px);
  background: var(--ink);
  cursor: ew-resize;
  touch-action: none;
}

.compare__handle {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 44px;
  height: 44px;
  box-sizing: border-box;
  border-radius: 50%;
  background: var(--bg);
  border: 3px solid var(--ink);
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: ew-resize;
  outline: none;
  -webkit-tap-highlight-color: transparent;
  color: var(--ink);
  transition: border-color .15s, color .15s;
}

.compare__handle span {
  font-size: 28px;
  color: inherit;
  line-height: 1;
  display: block;
  text-align: center;
  width: 100%;
}

.compare.dragging .compare__handle {
  border-color: var(--accent);
  color: var(--accent);
}

.compare__meta {
  display: flex;
  justify-content: space-between;
  gap: 32px;
  margin-top: 14px;
  flex-wrap: wrap;
}

.compare__meta p {
  margin: 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink-4);
  max-width: 44em;
}

.compare__value {
  font-size: 13px;
  color: var(--ink-4);
  font-family: var(--mono);
}

/* ---------- Arbeit: Ablauf mit mitlaufender Linie ---------- */
.flow {
  position: relative;
  margin-top: 52px;
}

/* Start- und Endpunkt setzt arbeit.js aus den gemessenen Punktmitten;
   die Werte hier sind nur der Stand ohne JS. */
.flow__track {
  position: absolute;
  left: 0;
  top: 53.5px;
  width: 1px;
  background: rgba(17, 17, 17, .14);
  bottom: 6px;
}

.flow__fill {
  width: 100%;
  background: var(--ink);
  height: 0;
  transition: height .5s var(--ease);
}

.flow-step {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 32px;
  padding: 40px 0;
  position: relative;
}

.flow-step:first-of-type { padding-top: 0; padding-bottom: 40px; }
.flow-step:last-of-type { padding-bottom: 0; }

.flow-step + .flow-step::before {
  content: '';
  position: absolute;
  left: 24px;
  right: 0;
  top: 0;
  height: 1px;
  background: var(--hairline);
}

.flow-dot {
  position: absolute;
  left: -5px;
  top: 48px;
  box-sizing: border-box;
  display: block;
  width: 11px;
  height: 11px;
  aspect-ratio: 1;
  border-radius: 50%;
  background: var(--bg);
  border: 1px solid rgba(17, 17, 17, .3);
  transition: background .25s, border-color .25s;
}

.flow-step:first-of-type .flow-dot { top: 8px; }

.flow-dot.on {
  background: var(--ink);
  border-color: var(--ink);
}

.flow-step__body { grid-column: 1 / span 6; padding-left: 34px; }

.flow-step__body h3 {
  margin: 0;
  font-size: 24px;
  line-height: 1.15;
  letter-spacing: -.02em;
  font-weight: 600;
}

.flow-step__body p {
  margin: 12px 0 0;
  font-size: 16px;
  line-height: 1.65;
  color: var(--ink-3);
  text-wrap: pretty;
}

.flow-step__benefit { grid-column: 8 / span 4; align-self: start; }

.flow-step__benefit p {
  margin: 10px 0 0;
  font-size: 16px;
  line-height: 1.55;
  color: var(--ink);
  font-weight: 500;
  text-wrap: pretty;
}

/* ---------- FAQ-Titel: „FAQ" morpht beim Scrollen zu „Fragen und Antworten" ---------- */
.faq-title__f,
.faq-title__tail {
  display: inline-block;
  vertical-align: top;
}

.faq-title__tail {
  position: relative;
  display: inline-grid;
  overflow: hidden;
  white-space: nowrap;
  transition: width .6s var(--ease);
  /* Der Kasten wird beschnitten, damit die Breite wandern kann -- dabei
     schnitt er dem "g" von "Fragen" die Unterlaenge ab. Das Polster
     macht ihn nach unten hin groesser, der negative Rand nimmt es dem
     Zeilenfluss wieder weg: die Ueberschrift bleibt also gleich hoch. */
  padding-bottom: .24em;
  margin-bottom: -.24em;
}

.faq-title__short,
.faq-title__long {
  grid-area: 1 / 1;
  justify-self: start;
  white-space: nowrap;
  transition: opacity .35s var(--ease);
}

.faq-title__long { opacity: 0; }

.faq-title.on .faq-title__short { opacity: 0; }
.faq-title.on .faq-title__long { opacity: 1; }

/* Vom Ablauf steht immer der Schritt voll da, der der Bildmitte am
   naechsten ist; die anderen treten zurueck. Welcher es ist, rechnet
   js/arbeit.js aus. Ohne Skript sind alle voll da -- die Klasse fehlt
   dann einfach, und der Ruhezustand ist der volle. */
/* Blass wird der Text, nicht der ganze Schritt: der Punkt an der Leiste
   liegt vor der durchgehenden Linie, und halb durchsichtig schien sie
   durch ihn hindurch. Leiste und Punkte bleiben darum, wie sie sind. */
#ablauf .flow-step__body,
#ablauf .flow-step__benefit {
  transition: opacity .4s var(--ease);
}

#ablauf:has(.ist-fokus) .flow-step:not(.ist-fokus) :is(.flow-step__body, .flow-step__benefit) {
  opacity: .35;
}

@media (prefers-reduced-motion: reduce) {
  #ablauf .flow-step__body,
  #ablauf .flow-step__benefit { transition: none; }
}

/* Ueberschrift, die auf einer Zeile bleiben soll: text-wrap: balance
   aus .h2 bricht sonst mitten im Satz um, sobald die Spalte schmal
   wird. Auf sehr schmalen Schirmen darf sie umbrechen -- nowrap wuerde
   dort die Seite aufspannen. */
.h2--eine-zeile { text-wrap: nowrap; }

@media (max-width: 560px) {
  .h2--eine-zeile { text-wrap: balance; }
}

/* ---------- Zeichen der Dienstleistungen ----------
   Zwei Auftritte: einer beim Erscheinen, einer beim Zeigen.

   Beim Erscheinen zeichnet sich jedes Zeichen selbst -- der Strich
   laeuft aus dem Nichts an die Stelle, wo er hingehoert (dasharray),
   waehrend das ganze Zeichen aus der Tiefe hereinkippt. Die vier gehen
   der Reihe nach los, damit die Reihe von links nach rechts entsteht
   und nicht auf einmal dasteht.

   Beim Zeigen tut jedes das, was es bedeutet: das Plus dreht sich in
   die Lage, der Stift schreibt, die Schieber fahren um, die Lichter
   blinken nacheinander. Das ist der Grund, warum die Teile im Markup
   eigene Namen tragen -- ohne sie waere es nur ein Wackeln. */
/* Bewegt wird nur verschoben, nicht gedreht oder vergroessert: fuer eine
   Drehung im Raum backt der Browser das Zeichen einmal in ein Bild und
   verzieht dieses -- waehrend der Bewegung war es darum unscharf. Eine
   Verschiebung kann er ohne dieses Bild rechnen, der Strich bleibt
   gestochen. */
.cards-4--dienste .tcard__icon {
  transition: transform .45s cubic-bezier(.22, 1.35, .4, 1);
}

/* --- Auftritt: Strich laeuft an, Zeichen kippt auf --- */
.cards-4--dienste .tcard__icon > * {
  stroke-dasharray: 200;
  stroke-dashoffset: 200;
}

.cards-4--dienste .ikon3d {
  opacity: 0;
  transform: translate(-50%, calc(-100% - 24px));
}

.cards-4--dienste.ist-da .ikon3d {
  animation: ds-auf .9s cubic-bezier(.2, .9, .25, 1) both;
  animation-delay: calc(var(--stufe, 0) * .13s);
}

.cards-4--dienste.ist-da .tcard__icon > * {
  animation: ds-strich 1.1s cubic-bezier(.65, 0, .35, 1) both;
  animation-delay: calc(var(--stufe, 0) * .13s + .1s);
}

.cards-4--dienste > :nth-child(2) { --stufe: 1; }
.cards-4--dienste > :nth-child(3) { --stufe: 2; }
.cards-4--dienste > :nth-child(4) { --stufe: 3; }

@keyframes ds-auf {
  0%   { opacity: 0; transform: translate(-50%, calc(-100% + 16px)); }
  55%  { opacity: 1; }
  100% { opacity: 1; transform: translate(-50%, calc(-100% - 24px)); }
}

@keyframes ds-strich {
  from { stroke-dashoffset: 200; }
  to   { stroke-dashoffset: 0; }
}

/* Nach dem Zeichnen darf nichts gestrichelt zurueckbleiben. */
.cards-4--dienste .tcard:hover .tcard__icon > * { stroke-dasharray: none; }

/* --- Beim Zeigen: das ganze Zeichen tritt einen Schritt vor --- */
.cards-4--dienste .tcard:hover .tcard__icon {
  transform: translateY(-5px);
}

/* 1 Neue Webseite: das Plus dreht sich in die Lage. */
.ds-plus {
  transform-box: view-box;
  transform-origin: 24px 28.5px;
  transition: transform .55s cubic-bezier(.34, 1.5, .5, 1);
}

.cards-4--dienste .tcard:hover .ds-plus--senkrecht { transform: rotate(90deg); }
.cards-4--dienste .tcard:hover .ds-plus--waagrecht { transform: rotate(90deg) scaleX(1.15); }

/* 2 Webseite ueberarbeiten: der Stift schreibt eine Zeile.

   Gesteuert wird das mit einer Klasse und nicht mit :hover -- beim
   Wegfahren riss die Endlos-Bewegung mitten im Takt ab und der Stift
   sprang von dort, wo er gerade war, an seinen Platz. Das Skript haelt
   ihn beim Wegfahren an der Stelle fest, an der er steht, und laesst
   ihn von dort zurueckgleiten. */
.ds-stift {
  transform-box: view-box;
  transform-origin: 32px 30px;
}

.cards-4--dienste .ds-stift.ist-schreibend {
  animation: ds-schreiben 1.05s cubic-bezier(.4, .1, .3, 1) infinite;
}

.cards-4--dienste .ds-stift.legt-zurueck {
  transition: transform .32s cubic-bezier(.3, .8, .3, 1);
}

/* Der Stift bleibt dabei im Fenster: weiter links wuerde die Spitze
   ueber den Rahmen hinauslaufen. */
@keyframes ds-schreiben {
  0%   { transform: translate(0, 0) rotate(0deg); }
  25%  { transform: translate(-4px, 2px) rotate(-5deg); }
  50%  { transform: translate(-7px, 0) rotate(2deg); }
  75%  { transform: translate(-3px, 2.5px) rotate(-3deg); }
  100% { transform: translate(0, 0) rotate(0deg); }
}

/* 3 Admin-Webtools: die Schieber fahren um. */
.ds-knopf {
  transform-box: view-box;
  transition: transform .5s cubic-bezier(.34, 1.45, .45, 1);
}

.cards-4--dienste .tcard:hover .ds-knopf--oben  { transform: translateX(13px); }
.cards-4--dienste .tcard:hover .ds-knopf--unten { transform: translateX(-13px); }

/* 4 Hosting und Betreuung: die Lichter gehen nacheinander an. */
.cards-4--dienste .tcard:hover .ds-licht {
  animation: ds-blinken 1.4s steps(1) infinite;
}

.cards-4--dienste .tcard:hover .ds-licht--unten { animation-delay: .7s; }

@keyframes ds-blinken {
  0%, 49%   { opacity: 1; }
  50%, 100% { opacity: .22; }
}

@media (prefers-reduced-motion: reduce) {
  .cards-4--dienste .ikon3d { opacity: 1; animation: none; }
  .cards-4--dienste .tcard__icon,
  .cards-4--dienste .tcard__icon > *,
  .cards-4--dienste .ds-plus,
  .cards-4--dienste .ds-knopf { animation: none; transition: none; transform: none; }
  .cards-4--dienste .tcard__icon > * { stroke-dasharray: none; stroke-dashoffset: 0; }
}

/* ---------- Karten-Panel (Preisrechner, Termin-Flow) ---------- */
.panel {
  margin-top: 64px;
  border: 1px solid var(--hairline-strong);
  background: #fff;
}

.progress { height: 2px; background: rgba(17, 17, 17, .1); }

.progress__fill {
  height: 100%;
  background: var(--ink);
  width: 0;
  transition: width .35s var(--ease);
}

.panel__body { padding: 48px 56px 56px; }
.panel__body--flow { padding: 44px 56px 56px; }

.panel__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
}

.panel__question {
  margin: 20px 0 0;
  font-size: clamp(22px, 2.2vw, 30px);
  line-height: 1.15;
  letter-spacing: -.02em;
  font-weight: 600;
  max-width: 20em;
}

/* Info-Punkt an der Frage. Die Blase haengt an der Frage, nicht am
   Punkt: so steht sie linksbuendig unter der Zeile und bleibt auch
   dann im Bild, wenn der Punkt weit rechts sitzt. */
.panel__question { position: relative; }

.panel__question .info-dot {
  display: inline-flex;
  margin-left: 10px;
  vertical-align: middle;
  /* Nicht mit der Ueberschrift wachsen: der Punkt bleibt 18 Pixel. */
  font-size: 11px;
  translate: 0 -2px;
}

.panel__question .tip {
  top: calc(100% + 12px);
  left: 0;
  width: min(340px, 100%);
  /* Die Blase erbt sonst Gewicht und enge Laufweite der Ueberschrift. */
  font-weight: 400;
  letter-spacing: normal;
}

.panel__question .info-dot:hover ~ .tip,
.panel__question .info-dot:focus ~ .tip,
.panel__question .info-dot:focus-visible ~ .tip {
  opacity: 1;
  visibility: visible;
  transform: none;
}

/* Hinweis auf uebernommene Antworten: eine Sprechblase, die neben dem
   Kasten schwebt und mit ihrem Zipfel auf den Zaehler zeigt. Sie liegt
   ausserhalb des Flusses -- so ruecken Zaehler und Ueberspringen nicht,
   wenn sie nach drei Sekunden verschwindet. Platz ist links, weil der
   Kasten erst in der zweiten Rasterspalte beginnt.

   Der Zipfel soll fliessend in die Pille uebergehen. Aneinandergesetzt
   bleibt an der Rundung immer eine Kerbe, egal wie die Kanten laufen.
   Darum liegen Pille und Zipfel in einer eigenen Lage, die durch
   Weichzeichner und Kontrast laeuft: der Weichzeichner laesst die
   beiden Formen ineinanderlaufen, der Kontrast holt die Kante wieder
   scharf heraus -- an der Naht entsteht dabei die runde Hohlkehle, die
   eine gezeichnete Blase hat. Der Text liegt in einer zweiten Lage
   darueber und bleibt davon unberuehrt. */
.panel__head-paar {
  position: relative;
  display: inline-flex;
  align-items: center;
}

.angaben-notiz {
  position: absolute;
  right: calc(100% + 30px);
  top: 50%;
  display: inline-flex;
  align-items: center;
  padding: 7px 14px;
  font-size: 12.5px;
  letter-spacing: -.005em;
  white-space: nowrap;
  color: #f4f2ee;
  opacity: 0;
  transform: translate(-8px, -50%);
  transition: opacity .3s var(--ease), transform .3s var(--ease);
}

.angaben-notiz.ist-da {
  opacity: 1;
  transform: translate(0, -50%);
}

.angaben-notiz__text { position: relative; z-index: 1; }

/* Die Formlage: Pille und Zipfel, verschmolzen. */
.angaben-notiz__form {
  position: absolute;
  inset: -6px -40px -6px -6px;
  filter: url(#blasen-guss);
  pointer-events: none;
}

.angaben-notiz__form::before,
.angaben-notiz__form::after {
  content: '';
  position: absolute;
  background: var(--ink);
}

/* Pille */
.angaben-notiz__form::before {
  inset: 6px 40px 6px 6px;
  border-radius: 999px;
}

/* Der Ansatz des Zipfels -- nur so lang, dass der Filter daraus die
   Hohlkehle an der Pille formt. Die eigentliche Spitze kommt ungefiltert
   darueber: der harte Schnitt der Deckkraft rundet feine Auslaeufer ab,
   eine Spitze wuerde darin stumpf. */
/* Breit braucht es keinen gefilterten Ansatz: der Tropfen unten greift
   mit seiner breiten Grundseite so weit in die Pille hinein, dass seine
   Ecken darin liegen -- die hohlen Bogen treten erst an der Rundung
   heraus, und damit gibt es keine Naht. Gefiltert wird nur die schmale
   Handy-Fassung. */
.angaben-notiz__form::after { display: none; }

/* Der Tropfen: breit an der Pille -- fast ueber ihre ganze Hoehe -- und
   in zwei hohlen Bogen zur Spitze auslaufend. Ungefiltert, damit die
   Spitze spitz bleibt; die Bogen zeichnet clip-path, mit einem Vieleck
   waeren es Geraden. */
.angaben-notiz::after {
  content: '';
  position: absolute;
  left: calc(100% - 15px);
  top: 50%;
  width: 34px;
  height: 26px;
  background: var(--ink);
  transform: translateY(-50%);
  clip-path: path('M0 0 C 11 3, 21 10, 34 13 C 21 16, 11 23, 0 26 Z');
}

/* Schmal ist links vom Kasten kein Platz -- im Fluss quetschte die
   Blase den Zaehler auf drei Zeilen. Dort schwebt sie darum ueber ihm,
   und der Zipfel zeigt nach unten. */
@media (max-width: 1150px) {
  .angaben-notiz {
    right: auto;
    left: 0;
    top: auto;
    bottom: calc(100% + 16px);
    transform: translateY(6px);
  }

  .angaben-notiz.ist-da { transform: none; }

  .angaben-notiz__form { inset: -6px -6px -40px -6px; }
  .angaben-notiz__form::before { inset: 6px 6px 40px 6px; }

  /* Schmal bleibt es beim gefilterten Zipfel: er laeuft weich aus, und
     genau so war er gewollt. Die aufgesetzte scharfe Spitze gilt nur
     fuer die breite Fassung. */
  .angaben-notiz__form::after {
    display: block;
    right: auto;
    left: 22px;
    top: auto;
    bottom: 12px;
    width: 13px;
    height: 34px;
    transform: none;
    clip-path: polygon(0 0, 46% 100%, 54% 100%, 100% 0);
  }

  .angaben-notiz::after { display: none; }
}

/* Sonst haelt das display oben den Platz weiter frei. */
.angaben-notiz[hidden] { display: none; }

.panel__hint {
  margin: 12px 0 0;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-4);
  max-width: 40em;
}

.panel__nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  margin-top: 40px;
  padding-top: 24px;
  border-top: 1px solid var(--hairline);
  flex-wrap: wrap;
}

/* Schrittleiste über dem Termin-Flow */
.steps-bar {
  display: flex;
  gap: 26px;
  padding: 22px 56px;
  border-bottom: 1px solid var(--hairline);
  flex-wrap: wrap;
}

.steps-bar span {
  font-size: 12px;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: #b5b0a8;
}

.steps-bar span.done { color: var(--ink-3); }
.steps-bar span.current { color: var(--ink); font-weight: 600; }

/* Antwortkärtchen (Preisrechner) */
.options {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
  margin-top: 36px;
}

/* Zwei Spalten, sobald das Feld selbst breit genug ist -- nicht der
   Bildschirm. Bisher hing es an 960 Pixeln Fensterbreite: bei 900 stand
   eine Spalte mit 802 Pixel breiten Kaertchen fuer drei Woerter. Ab 560
   Pixeln Innenbreite bekommt jedes Kaertchen 274, der laengste Titel
   ("In den naechsten Monaten") misst 177 plus 40 Polster. Der Container
   ist der Feldkoerper, damit die Regel auch dann stimmt, wenn das Feld
   auf einer anderen Seite schmaler oder breiter im Raster steht. */
[data-preisrechner] .panel__body { container-type: inline-size; }

@container (min-width: 560px) {
  .options { grid-template-columns: 1fr 1fr; }
}

/* Ohne Container-Abfragen (Safari vor 16, Firefox vor 110) bleibt die
   alte Schwelle: zwei Spalten ab Desktopbreite. */
@supports not (container-type: inline-size) {
  @media (min-width: 961px) {
    .options { grid-template-columns: 1fr 1fr; }
  }
}

.option {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 5px;
  text-align: left;
  padding: 18px 20px;
  background: var(--bg);
  color: var(--ink);
  border: 1px solid var(--hairline-strong);
  transition: background .15s, border-color .15s, color .15s;
}

.option .t { font-size: 17px; font-weight: 500; letter-spacing: -.01em; }
.option .n { font-size: 13px; line-height: 1.4; color: var(--ink-4); }

/* Ohne Zusatzzeile steht der Titel allein: die leere Zeile faellt weg,
   und der Titel sitzt in der Hoehe mittig statt oben. Die Mindesthoehe
   haelt die Kaertchen so hoch wie die mit Zusatzzeile. */
.option .n:empty { display: none; }
.option { justify-content: center; min-height: 76px; }

.option.active {
  background: var(--ink);
  color: var(--bg);
  border-color: var(--ink);
}

.option.active .n { color: rgba(251, 250, 248, .65); }

/* Chips (Termin-Flow) */
.chip {
  padding: 11px 18px;
  font-size: 15px;
  line-height: 1;
  background: var(--bg);
  color: var(--ink);
  border: 1px solid var(--hairline-strong);
  transition: background .15s, border-color .15s, color .15s;
}

.chip.active {
  background: var(--ink);
  color: var(--bg);
  border-color: var(--ink);
}

.chip-row { display: flex; gap: 10px; flex-wrap: wrap; }

.chip-group {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

/* Tagesliste */
.day-list { margin-top: 34px; border-top: 1px solid var(--hairline-strong); }

.day-row {
  display: grid;
  grid-template-columns: 220px 1fr;
  gap: 32px;
  align-items: center;
  padding: 20px 0;
  border-bottom: 1px solid var(--hairline);
}

.day-row__date { display: flex; flex-direction: column; gap: 3px; }
.day-row__date .wd { font-size: 16px; font-weight: 600; letter-spacing: -.01em; }
.day-row__date .d { font-size: 14px; color: var(--ink-4); }

/* SMS-Code */
.code-row { display: flex; gap: 12px; }

.code-input {
  width: 56px;
  height: 64px;
  text-align: center;
  font-size: 24px;
  font-weight: 600;
  color: var(--ink);
  background: var(--bg);
  border: 1px solid rgba(17, 17, 17, .24);
  outline: none;
  transition: border-color .15s;
}

.code-input.filled, .code-input:focus { border-color: var(--ink); }

.code-block { display: flex; flex-direction: column; gap: 12px; animation: rise .3s ease both; }
.code-block[hidden] { display: none; }

/* Ergebnis / Bestätigung */
.result-sum {
  font-size: clamp(34px, 4.2vw, 58px);
  line-height: 1;
  letter-spacing: -.035em;
  font-weight: 600;
}

.result-date {
  font-size: clamp(28px, 3.2vw, 44px);
  line-height: 1.06;
  letter-spacing: -.03em;
  font-weight: 600;
  text-wrap: balance;
}

.summary { margin-top: 14px; display: flex; flex-direction: column; gap: 10px; }

.summary .row {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  font-size: 14px;
  line-height: 1.4;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--hairline);
}

.summary .row .k { color: var(--ink-4); }
.summary .row .v { text-align: right; font-weight: 500; }

/* ---------- Preise: Bandbreiten-Karten ---------- */
.price-card {
  border-top: 2px solid var(--ink);
  padding-top: 18px;
  display: flex;
  flex-direction: column;
  height: 100%;
}

.price-card h3 { margin: 0; font-size: 17px; font-weight: 600; letter-spacing: -.01em; }

.price-card .amount {
  margin: 20px 0 0;
  font-size: clamp(26px, 2.6vw, 38px);
  line-height: 1;
  letter-spacing: -.03em;
  font-weight: 600;
}

.price-card .per { margin-top: 8px; display: block; font-size: 13px; color: var(--ink-4); }

.price-card p {
  margin: 20px 0 0;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ink-3);
}

.price-card p.narrow { max-width: 32em; }

/* Schalter zwischen Monats- und Jahresbetrag unter den laufenden
   Kosten. Die Betraege selbst stehen als data-monat/data-jahr an den
   Feldern, umgesetzt wird der Wechsel in js/preise.js.
   [hidden] braucht eine eigene Regel: display: flex schluege es sonst. */
.zeitschalter {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 16px;
  margin-top: 32px;
}

.zeitschalter[hidden] { display: none; }


/* Zwei gleich breite Haelften, darunter ein Laeufer, der von einer zur
   anderen faehrt. Gleich breit, damit der Weg genau eine halbe Breite
   ist und ohne Messung auskommt. */
.switch {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  border: 1px solid var(--hairline-strong);
  background: var(--bg);
}

/* Vier Pixel groesser als die halbe Flaeche, nach jeder Seite: der
   Laeufer deckt die Haarlinie ringsum ab und steht ein Stueck darueber
   hinaus. Der Weg nach rechts ist deshalb die eigene Breite abzueglich
   dieser acht Pixel, sonst schoesse er ueber die rechte Kante hinaus. */
.switch__laeufer {
  position: absolute;
  left: -4px;
  top: -4px;
  bottom: -4px;
  width: calc(50% + 8px);
  background: var(--ink);
  transition: transform .34s var(--ease);
}

.switch[data-stand="jahr"] .switch__laeufer { transform: translateX(calc(100% - 8px)); }

.switch__seite {
  position: relative;           /* ueber dem Laeufer */
  z-index: 1;
  margin: 0;
  padding: 11px 18px;
  font: inherit;
  font-size: 15px;
  line-height: 1;
  color: var(--ink);
  background: none;
  border: 0;
  cursor: pointer;
  transition: color .34s var(--ease);
}

/* Die gewaehlte Seite steht auf dem Laeufer und dreht ihren Ton um. */
.switch__seite[aria-pressed="true"] { color: var(--bg); }

/* Abstand nach aussen, sonst laege der Rahmen auf dem dunklen Laeufer. */
.switch__seite:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

/* Der neue Betrag kommt aus der Richtung, in die er sich bewegt: zum
   Jahresbetrag hinauf von unten, zurueck zum Monatsbetrag von oben. */
@keyframes betrag-hoch {
  from { opacity: 0; transform: translateY(.3em); }
  to   { opacity: 1; transform: none; }
}

@keyframes betrag-runter {
  from { opacity: 0; transform: translateY(-.3em); }
  to   { opacity: 1; transform: none; }
}

/* Nur das Wort wandert, "pro" und ", inkl. MWST" bleiben stehen;
   inline-block, weil eine reine Inline-Box kein transform annimmt. */
.per__zeit { display: inline-block; }

.ist-neu--hoch   { animation: betrag-hoch .32s var(--ease); }
.ist-neu--runter { animation: betrag-runter .32s var(--ease); }

@media (prefers-reduced-motion: reduce) {
  .switch__laeufer, .switch__seite { transition: none; }
  .ist-neu--hoch, .ist-neu--runter { animation: none; }
}

/* Info-Punkt mit Sprechblase */
.tipwrap {
  display: flex;
  align-items: center;
  gap: 10px;
  position: relative;
}

.info-dot {
  width: 18px;
  height: 18px;
  min-width: 18px;
  box-sizing: border-box;
  border-radius: 50%;
  border: 1px solid rgba(17, 17, 17, .35);
  background: none;
  padding: 0;
  font-size: 11px;
  font-style: italic;
  font-weight: 600;
  line-height: 1;
  color: var(--ink-3);
  display: flex;
  align-items: center;
  justify-content: center;
}

.tip {
  position: absolute;
  top: calc(100% + 12px);
  left: -6px;
  z-index: 5;
  /* Nicht fest 320 Pixel: auf einem 320 Pixel breiten Schirm ragte die
     Blase 18 Pixel aus dem Bild und zog einen Seitenlauf nach sich.
     Die 48 Pixel sind das Polster des Abschnitts auf beiden Seiten. */
  width: min(320px, calc(100vw - 48px));
  padding: 16px 18px;
  background: var(--ink);
  color: #e8e5df;
  font-size: 14px;
  line-height: 1.55;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity .18s, transform .18s, visibility .18s;
  pointer-events: none;
}

.tip strong { display: block; font-weight: 600; margin-bottom: 6px; }

/* Nur ueber dem Wort und dem Punkt, nicht ueber der ganzen Zeile: der
   Traeger ist ein Flexkasten und damit so breit wie die Karte, sodass
   die Blase sonst auch im leeren Raum daneben aufginge. Die Blase
   steht im Quelltext hinter beiden, darum das Geschwister-Zeichen. */
/* :focus zusaetzlich zu :focus-visible: ein Fingertipp erzeugt nicht in
   jedem Browser einen sichtbaren Fokus, und ohne Schweben waere die
   Blase auf dem Handy sonst gar nicht zu erreichen. */
.tipwrap > h3:hover ~ .tip,
.tipwrap > .info-dot:hover ~ .tip,
.tipwrap > .info-dot:focus ~ .tip,
.tipwrap > .info-dot:focus-visible ~ .tip {
  opacity: 1;
  visibility: visible;
  transform: none;
}

/* ---------- Über mich: Porträt & Werdegang ---------- */
.portrait { margin: 0; }

/* ---------- Sofortbild ----------
   Das Portraet liegt wie ein Sofortbild auf der Seite: weisser Rand,
   unten die breite Lasche mit Name und Adresse, das Ganze leicht
   schief. Die Drehung sitzt am Blatt und nicht am Bild, damit der Rand
   mitkippt -- am Bild allein wuerde es sich im geraden Rahmen drehen.
   Beim Zeigen richtet es sich fast auf; das ist die ganze Bewegung, die
   es braucht. */
.sofortbild {
  margin: 0;
  /* Der Platz fuer die Drehung: die Ecken laufen sonst ueber die
     Spaltenkante hinaus. */
  padding: 10px 14px;
}

.sofortbild__blatt {
  background: #fff;
  padding: 14px 14px 0;
  box-shadow:
    0 1px 2px rgba(17, 17, 17, .10),
    0 18px 40px -18px rgba(17, 17, 17, .30);
  transform: rotate(-2.4deg);
  transition: transform .5s var(--ease), box-shadow .5s var(--ease);
}

.sofortbild:hover .sofortbild__blatt {
  transform: rotate(-.6deg);
  box-shadow:
    0 1px 2px rgba(17, 17, 17, .10),
    0 26px 52px -20px rgba(17, 17, 17, .34);
}

/* Im Sofortbild traegt der Rahmen keine eigene Linie: der weisse Rand
   des Blattes ist schon der Rahmen. */
.sofortbild .portrait__frame {
  border: 0;
  aspect-ratio: 4 / 5;
}

/* Die Lasche unten ist breiter als der Rand ringsum -- daran erkennt
   man ein Sofortbild. */
.sofortbild__lasche {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 16px 4px 22px;
  margin: 0;
}

.sofortbild__name {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.01em;
  color: var(--ink);
}

.sofortbild__adresse {
  font-size: 13px;
  color: var(--ink-4);
}

/* Bei flachem Fenster ist nicht die Spalte das Mass, sondern die
   Fensterhoehe: das Sofortbild soll ganz zu sehen sein, ohne dass man
   erst scrollen muss. Die Breite rechnet sich darum aus der Hoehe
   zurueck -- der Rahmen ist 4:5, dazu kommen der weisse Rand und die
   Lasche, zusammen die 312 Pixel im Abzug. Ist das Fenster hoch
   genug, liegt der Wert ueber der Spaltenbreite und die Regel greift
   nicht. */
@media (min-width: 961px) {
  .sofortbild { max-width: calc((100svh - 312px) / 1.25 + 28px); }
}

/* Das kleinere Bild laesst in seiner Spalte Platz frei. Damit es nicht
   an der linken Kante klebt, ruecken ein paar Pixel nach rechts --
   nur dort, wo die Regel oben ueberhaupt greift. */
@media (min-width: 961px) and (max-height: 860px) {
  .sofortbild { margin-left: 48px; }
}

/* ---------- Zierband hinter dem Diplom ----------
   Ein schmales, im Uhrzeigersinn geneigtes Rechteck (1 zu 8). Beim
   Zeigen waechst es aus seiner Mitte in die Laenge, die Breite bleibt.
   Es ist laenger als der Abschnitt hoch ist; der Abschnitt schneidet es
   ab (overflow), damit es genau an den Trennlinien endet -- so braucht
   es keine Rechnung ueber die Neigung und stimmt bei jeder Hoehe.

   Gewachsen wird ueber scaleY nach der Drehung: damit laeuft es entlang
   seiner eigenen Laengsachse und nicht senkrecht. */
#nachweis {
  position: relative;
  overflow: hidden;
}

/* Immer hinter dem Blatt: beide bekommen eine Lage, statt sich auf die
   Reihenfolge im Quelltext zu verlassen. Ohne das lag das Band vor dem
   Blatt, sobald dieses keine Verschiebung trug -- ein positioniertes
   Element malt sonst ueber ein unpositioniertes. */
.nachweis-band {
  grid-column: 8 / span 5;
  grid-row: 1 / span 2;
  position: relative;
  z-index: 0;
  pointer-events: none;
}

.nachweis-band::before {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 80px;
  height: 640px;
  translate: -50% -50%;
  background: rgba(17, 17, 17, .06);
  transform: rotate(20deg) scaleY(0);
  transform-origin: 50% 50%;
  transition: transform .75s var(--ease);
}

#nachweis:has(.diplom:hover) .nachweis-band::before,
#nachweis:has(.diplom:focus-visible) .nachweis-band::before {
  transform: rotate(20deg) scaleY(1);
}

/* Schmal fallen die Spalten zusammen; dort nimmt das Band eine eigene
   Zeile ein und haette nichts, hinter dem es liegen koennte. */
@media (max-width: 960px) {
  .nachweis-band { display: none; }
}

/* ---------- Diplom als Bild ----------
   Es liegt wie ein Blatt auf der Seite: eigener weisser Grund, feine
   Kante, flacher Schatten. Beim Zeigen hebt es sich einen Hauch, damit
   man merkt, dass es sich oeffnen laesst. */
.diplom {
  display: block;
  position: relative;
  z-index: 1;
  /* Als Knopf bringt er die Schrift des Systems mit -- weg damit, er
     soll wie ein Blatt aussehen und nicht wie ein Knopf.

     Die Kante steht durchsichtig da und faerbt sich erst beim Zeigen:
     als border: 0 waere das Blatt beim Zeigen um zwei Pixel gewachsen
     und haette alles darin verschoben. */
  font: inherit;
  cursor: zoom-in;
  padding: 8px;
  background: #fff;
  border: 1px solid transparent;
  border-radius: 4px;
  box-shadow: 0 1px 2px rgba(17, 17, 17, .08), 0 14px 30px -18px rgba(17, 17, 17, .28);
  transition: transform .4s var(--ease), box-shadow .4s var(--ease),
              border-color .4s var(--ease);
}

.diplom img {
  display: block;
  width: 100%;
  height: auto;
}

/* Breit spannt das Blatt ueber beide Rasterzeilen und steht darin
   mittig: so sitzt es in der Hoehe des ganzen Abschnitts, von der
   Ueberschrift bis unter die Karte. Schmal darf es das nicht -- dort
   fallen die Spalten zusammen, und das Blatt stuende in der ersten
   Zeile ueber der Ueberschrift. */
@media (min-width: 961px) {
  .diplom {
    grid-row: 1 / span 2;
    align-self: center;
  }
}

/* Schmal steht das Blatt zwischen Ueberschrift und Karte: es ist das
   Stueck, um das es geht, und gehoert damit vor den Text und nicht
   dahinter. Geordnet wird im Raster, der Quelltext bleibt wie er ist --
   breit soll das Blatt weiter rechts neben beidem stehen. */
@media (max-width: 960px) {
  #nachweis .h2 { order: 1; }
  #nachweis .diplom { order: 2; margin-top: 40px; }
  #nachweis .nachweis-karte { order: 3; margin-top: 40px; }
}

.diplom:hover,
.diplom:focus-visible {
  border-color: var(--hairline);
  transform: translateY(-3px);
  box-shadow: 0 1px 2px rgba(17, 17, 17, .08), 0 22px 44px -20px rgba(17, 17, 17, .34);
}

/* Die Nachweis-Karte tragt keine Kartenlinie: sie steht allein im
   Abschnitt, und die Linie trennte sie von nichts. */
.nachweis-karte {
  border-top: 0;
  padding-top: 0;
  /* Stand vorher als Stilangabe im Markup; hier, weil die schmale
     Ansicht einen eigenen Wert braucht. */
  margin-top: 48px;
}

/* Verweis, der herunterlaedt: statt des Pfeils das Zeichen dafuer.
   Die Linie laeuft wie bei jedem Verweis unter allem durch, das Zeichen
   eingeschlossen. Damit sie dabei nicht tiefer rutscht, steht das
   Zeichen im Zeilenfluss auf der Grundlinie: sein Kasten endet dort,
   waehrend die Unterlaengen der Schrift ohnehin weiter reichen -- die
   Zeile wird also nicht hoeher. Ein Flex-Verweis oder ein Versatz nach
   unten wuerde sie verschieben. */
.link--laden { white-space: nowrap; }

.ikon-laden,
.ikon-skip {
  display: inline-block;
  width: 14px;
  height: 14px;
  margin-left: 3px;
  vertical-align: baseline;
}

/* Das Ueberspringen traegt sein Zeichen gleich dahinter; zusammen
   bleiben sie auf einer Zeile. */
.btn-plain--skip { white-space: nowrap; }

/* Das vergroesserte Blatt: nur das Bild auf dunklem Grund, nichts
   sonst. Erzeugt wird die Schicht in js/main.js. */
.lupe {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  /* Der Rand steht als eigener Wert da: die Hoechstmasse des Bildes
     rechnen mit ihm, und zwei Stellen mit derselben Zahl gehen sonst
     irgendwann auseinander. */
  --lupe-rand: clamp(16px, 4vw, 56px);
  padding: var(--lupe-rand);
  overflow: hidden;
  cursor: zoom-out;
  overscroll-behavior: contain;
  /* Aufziehen mit zwei Fingern bleibt erlaubt, Wischen mit einem nicht
     (das faengt js/main.js ab). */
  touch-action: pinch-zoom;
  opacity: 0;
  /* Dieselbe Dauer wie der Farbwechsel am Wurzelelement (.36s in
     css/main.css): Grund, Leisten oben und unten gehen so gemeinsam
     dunkel, nicht nacheinander. */
  transition: opacity .36s var(--ease);
}

.lupe.ist-da { opacity: 1; }

/* Wie beim Klappmenue liegt die Verdunkelung zusaetzlich im Inhalt
   selbst und nicht nur in der feststehenden Schicht: Safaris Glasleisten
   zeigen den scrollenden Inhalt und lassen feststehende Ebenen aus --
   sonst bleibt der Streifen hinter ihnen hell. Die Regeln dafuer stehen
   bei .hat-menue-offen in css/main.css.

   Anders als beim Menue dunkelt hier auch die Zeile oben mit: die
   Kopfzeile bekommt ihre eigene Flaeche, die bis unter die Statusleiste
   hinaufreicht (siehe css/main.css), und das Wurzelelement den Ton als
   Rueckfall fuer Safaris Leisten. */
/* Der Grund des Wurzelelements wechselt mit: er liegt dort, wo der
   Koerper nicht hinreicht -- hinter Safaris Glasleisten und im
   ueberzogenen Rand -- und bringt dort denselben Ton. Der Koerper selbst
   bleibt hell: die Flaeche darueber rechnet mit ihm, und auf dunklem
   Grund waere die Seite doppelt verdunkelt. */
html.hat-grossansicht {
  background-color: #3b3b3b;
  background-image: none;
  transition: background-color .36s var(--ease);
}

/* .82 wie die feststehende Schicht vorher: derselbe Ton wie bisher, und
   kraeftig genug, dass auch das Blatt des Diploms mit seinem weissen
   Grund dahinter mit abdunkelt. */
html.hat-grossansicht { --schleier: .82; }

/* Das <picture> bleibt ein Kasten und wird selbst zentriert. Mit
   display: contents hingen Bild und die <source>-Zeilen einzeln im
   Raster: der Browser legte dafuer zwei Zeilen an, das Bild landete in
   der unteren und sass damit zu tief. Als Rasterelement mit place-self
   schrumpft der Kasten auf das Bild. */
.lupe picture {
  display: block;
  place-self: center;
  line-height: 0;
  position: relative;
  z-index: 1;
}

/* Das Blatt fuellt das Fenster, soweit es kann. Die Masse stehen in
   Fenstereinheiten und nicht in Prozent: die Rasterzeile richtet sich
   nach dem Bild, ein max-height: 100% waere ein Bezug auf sich selbst --
   der Browser liess es fallen, und das Blatt stand unten heraus. Kein
   weisser Rand darum: in der Grossansicht soll nur das Blatt zu sehen
   sein, es bringt seinen eigenen Rand mit. */
.lupe img {
  max-width: calc(100vw - 2 * var(--lupe-rand));
  max-height: calc(100svh - 2 * var(--lupe-rand));
  width: auto;
  height: auto;
  box-shadow: 0 30px 70px -30px rgba(0, 0, 0, .7);
  transform: scale(.97);
  transition: transform .36s var(--ease);
}

.lupe.ist-da img { transform: none; }

/* Die dynamischen Fenstermasse, wo es sie gibt: sie ziehen beim Drehen
   und beim Ein- und Ausfahren der Browserleisten mit, waehrend svh auf
   dem Stand des kleinen Fensters stehen bleibt. */
@supports (max-height: 100dvh) {
  .lupe img {
    max-width: calc(100dvw - 2 * var(--lupe-rand));
    max-height: calc(100dvh - 2 * var(--lupe-rand));
  }
}

.lupe__zu {
  position: absolute;
  top: max(14px, env(safe-area-inset-top, 0px));
  right: 16px;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .12);
  color: #f4f2ee;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}

.lupe__zu:hover,
.lupe__zu:focus-visible { background: rgba(255, 255, 255, .22); }

/* ---------- Unterschrift unter dem Text ----------
   Sie steht am Ende der Biografie wie am Ende eines Briefes. Die Breite
   ist gedeckelt und die Hoehe rechnet das Bild selbst -- so bleibt der
   Schriftzug in jeder Spaltenbreite gleich gross zum Text daneben. */
.unterschrift { margin-top: 44px; }

.unterschrift img {
  display: block;
  width: min(300px, 62%);
  height: auto;
}

/* Im grossen Fenster ist Platz: der Namenszug rutscht weiter nach
   unten und an die rechte Kante der Textspalte -- wie eine
   Unterschrift am Ende eines Briefes, nicht wie eine weitere Zeile. */
@media (min-width: 961px) and (min-height: 861px) {
  .unterschrift { margin-top: 52px; }

  /* Etwas grosser und leicht gegen den Uhrzeigersinn gekippt, wie von
     Hand hingesetzt. Gedreht wird um die rechte Mitte, damit der Zug
     an der Spaltenkante stehen bleibt; der Platz fuer die
     ausschwenkende Ecke steht als Abstand unten. */
  .unterschrift img {
    width: min(356px, 72%);
    margin-left: auto;
    margin-right: -10px;  /* etwas ueber die Spaltenkante hinaus, wie hingesetzt */
    margin-bottom: 26px;
    transform: rotate(-10deg);
    transform-origin: 100% 50%;
  }
}

@media (max-width: 960px) {
  .sofortbild { padding: 10px 0; max-width: 420px; }
  .unterschrift { margin-top: 34px; }
  .unterschrift img { width: min(260px, 72%); }
}

/* Am Handy steht das Sofortbild gerade und weiter oben: gekippt stiess
   die Ecke gegen die Bildschirmkante, und das Polster ringsum war nur
   fuer die Drehung da. Der Kopfabstand des Abschnitts ist fuer eine
   Spalte gedacht, in der das Bild neben dem Text steht -- untereinander
   darf er kleiner sein. Steht nach dem Block darueber, weil es dieselbe
   Regel ueberschreibt. */
@media (max-width: 640px) {
  /* Oben zur Kopfzeile und unten zum Titel derselbe Abstand: der
     Kopfabstand des Abschnitts und der Zeilenabstand des Rasters
     tragen ihn je zur Haelfte der Strecke. */
  .sec:has(.sofortbild) { padding-top: 32px; }
  .sec:has(.sofortbild) > .grid { row-gap: 32px; }

  .sofortbild { padding: 0; }

  .sofortbild__blatt,
  .sofortbild:hover .sofortbild__blatt { transform: none; }
}

.portrait__frame {
  aspect-ratio: 4 / 5;
  border: 1px solid var(--hairline-strong);
  background: repeating-linear-gradient(45deg, #f4f2ee, #f4f2ee 6px, #eae7e1 6px, #eae7e1 12px);
  display: flex;
  align-items: flex-end;
  padding: 18px;
  overflow: hidden;
}

/* Traegt der Rahmen ein Bild, faellt der Innenabstand weg -- der galt
   nur dem Schild im leeren Rahmen. */
.portrait__frame:has(img) { display: block; padding: 0; }

.portrait__frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 22%;
  display: block;
}

.portrait__frame span {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .02em;
  color: var(--ink-3);
  background: var(--bg);
  padding: 6px 9px;
}

.portrait figcaption {
  margin: 12px 0 0;
  font-size: 13px;
  color: var(--ink-4);
}

.bio p {
  margin: 18px 0 0;
  font-size: 17px;
  line-height: 1.65;
  color: var(--ink-2);
  text-wrap: pretty;
}

.bio p:first-of-type { margin-top: 28px; }

/* ---------- Kontakt: Direkt-Karten ---------- */
.direct-card .big {
  margin: 11px 0 0;
  display: inline-block;
  font-size: 20px;
  letter-spacing: -.01em;
}

.direct-card a.big {
  border-bottom: 1px solid rgba(17, 17, 17, .3);
  padding-bottom: 2px;
}

/* ---------- Responsiv ---------- */
@media (max-width: 960px) {
  .panel__body, .panel__body--flow { padding: 28px 24px 36px; }
  .steps-bar { padding: 16px 24px; gap: 16px; }
  .day-row { grid-template-columns: 1fr; gap: 12px; }
  /* Untereinander braucht die Zeile keine Spaltenluecken mehr -- elf
     mal 32 Pixel sind mehr als die Spalte breit ist, und die Zeile
     schob dadurch die Seite zur Seite (waagrechte Bildlaufleiste auf
     schmalen Schirmen). */
  .flow-step { column-gap: 0; row-gap: 12px; }
  .flow-step__body { grid-column: 1 / span 12; }
  .flow-step__benefit { grid-column: 1 / span 12; padding-left: 34px; }
  .compare__scroll { height: 420px; }
  .quote-person { margin-top: 12px; }
  .textlinks { margin-top: 40px; }
}

/* ---------- Umschalter hell/dunkel fuer Stil 3 ----------
   Sitzt links in der Kopfzeile, wo sonst nichts steht — der Seitentitel
   liegt in der Mitte, der Burger rechts. Er erscheint und verschwindet
   mit dem Abschnitt, in derselben Bewegung wie der Burger, und faerbt
   sich ueber currentColor mit der Zeile mit. */
.stil-schalter {
  position: absolute;
  left: 48px;
  top: 50%;
  margin-top: -14px;
  height: 28px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--kopf-schrift);
  font: inherit;
  font-size: 12px;
  letter-spacing: .04em;
  opacity: 0;
  visibility: hidden;
  transform: translateX(-10px);
  transition: opacity .3s var(--ease),
              transform .4s var(--ease),
              visibility 0s linear .42s;
}

[data-stil-aktiv="3"] .stil-schalter {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity .3s var(--ease) .16s,
              transform .4s var(--ease) .16s,
              visibility 0s linear 0s;
}

.stil-schalter__spur {
  position: relative;
  width: 34px;
  height: 18px;
  border: 1px solid currentColor;
  border-radius: 9px;
  opacity: .5;
}

.stil-schalter__griff {
  position: absolute;
  left: 3px;
  top: 50%;
  width: 10px;
  height: 10px;
  margin-top: -5px;
  border-radius: 50%;
  background: currentColor;
  transition: transform .28s var(--ease);
}

.stil-schalter[aria-pressed="true"] .stil-schalter__griff { transform: translateX(14px); }

.stil-schalter__text {
  min-width: 3.6em;
  text-align: left;
  opacity: .8;
}

@media (max-width: 760px) {
  .stil-schalter { left: 24px; }
  .stil-schalter__text { display: none; }
}


/* Maus-Lupe in Stil 3 ------------------------------------------------------

   Der Zeiger wird in dieser Sektion durch einen Kreis ersetzt, der den
   Bildausschnitt unter sich invertiert und gleichzeitig in Schwarzweiss
   umrechnet. Umgesetzt mit backdrop-filter: der Kreis selbst bleibt leer,
   gefiltert wird nur das, was hinter ihm liegt. */
.stil-lupe {
  position: absolute;
  top: 0;
  left: 0;
  /* Ueber der Seite: .stil-site3__page steht selbst auf z-index 1 und liegt
     im selben Stapel wie die Lupe — ohne eigenen Wert geriete sie hinter
     Text und Bilder, und backdrop-filter haette nichts mehr zu filtern. */
  z-index: 2;
  /* Groesse hier ist der Hoechstwert; js/main.js skaliert die Form je nach
     Zeigergeschwindigkeit darunter. */
  width: 190px;
  height: 190px;
  margin: -95px 0 0 -95px;
  pointer-events: none;
  opacity: 0;
  /* Grundform: ein Sechsunddreissigeck, das als Kreis liest. Beide Umrisse
     haben gleich viele Punkte — beim Sechseck liegen je fuenf davon auf
     der Kante zwischen zwei Ecken — deshalb laesst sich der eine in den anderen
     ueberblenden. Daraus entsteht das Morphen zum Sechseck. */
  clip-path: polygon(50% 0%, 58.68% 0.76%, 67.1% 3.02%, 75% 6.7%,
                     82.14% 11.7%, 88.3% 17.86%, 93.3% 25%, 96.98% 32.9%,
                     99.24% 41.32%, 100% 50%, 99.24% 58.68%, 96.98% 67.1%,
                     93.3% 75%, 88.3% 82.14%, 82.14% 88.3%, 75% 93.3%,
                     67.1% 96.98%, 58.68% 99.24%, 50% 100%, 41.32% 99.24%,
                     32.9% 96.98%, 25% 93.3%, 17.86% 88.3%, 11.7% 82.14%,
                     6.7% 75%, 3.02% 67.1%, 0.76% 58.68%, 0% 50%,
                     0.76% 41.32%, 3.02% 32.9%, 6.7% 25%, 11.7% 17.86%,
                     17.86% 11.7%, 25% 6.7%, 32.9% 3.02%, 41.32% 0.76%);
  transition: opacity .18s var(--ease),
              clip-path .12s var(--ease);
  will-change: transform;
  -webkit-backdrop-filter: grayscale(1) invert(1);
  backdrop-filter: grayscale(1) invert(1);
}

.stil-lupe.is-an { opacity: 1; }

/* Ueber allem, was sonst einen Zeigefinger zeigen wuerde, morpht die Form
   zum Sechseck: dieselben sechsunddreissig Punkte, sechs davon als Ecken,
   die
   uebrigen gleichmaessig auf den Kanten dazwischen. Die Groesse morpht in
   js/main.js im selben Takt mit. */
.stil-lupe.ist-knopf {
  clip-path: polygon(50% 0%, 57.22% 4.17%, 64.43% 8.33%, 71.65% 12.5%,
                     78.87% 16.67%, 86.08% 20.83%, 93.3% 25%, 93.3% 33.33%,
                     93.3% 41.67%, 93.3% 50%, 93.3% 58.33%, 93.3% 66.67%,
                     93.3% 75%, 86.08% 79.17%, 78.87% 83.33%, 71.65% 87.5%,
                     64.43% 91.67%, 57.22% 95.83%, 50% 100%, 42.78% 95.83%,
                     35.57% 91.67%, 28.35% 87.5%, 21.13% 83.33%, 13.92% 79.17%,
                     6.7% 75%, 6.7% 66.67%, 6.7% 58.33%, 6.7% 50%,
                     6.7% 41.67%, 6.7% 33.33%, 6.7% 25%, 13.92% 20.83%,
                     21.13% 16.67%, 28.35% 12.5%, 35.57% 8.33%, 42.78% 4.17%);
}

/* Der eigene Zeiger entfaellt, solange die Lupe sichtbar ist — sonst laeuft
   ein zweiter Cursor im Kreis mit. */
[data-stil="3"] .stil-placeholder__sticky.hat-lupe,
[data-stil="3"] .stil-placeholder__sticky.hat-lupe * { cursor: none; }

/* Ohne Unterstuetzung fuer backdrop-filter bliebe nur ein leerer Kreis
   uebrig; dann bleibt der normale Zeiger stehen und die Lupe entfaellt. */
@supports not ((backdrop-filter: invert(1)) or (-webkit-backdrop-filter: invert(1))) {
  .stil-lupe { display: none; }
}

/* Auf Touch-Geraeten gibt es keinen Zeiger, dem die Lupe folgen koennte. */
@media (hover: none) {
  .stil-lupe { display: none; }
}

/* ---------- Stil 4: Treuhandkanzlei ----------
   Das klassisch-serioese Register der Strecke: warmes Papier, tiefes
   Marineblau, Serifen-Titel (Sentient), Haarlinien und viel Weissraum.
   Gleiche Scroll-Mechanik wie die Stile 1 bis 3. */
.stil-site4 {
  --s4-papier: #f6f3ec;
  --s4-tinte: #16222e;
  --s4-grau: #5f6a72;
  /* Akzent aus der Tintenfamilie statt eines Goldtons: dasselbe kuehle
     Blaugruen, nur heller und gesaettigter. Der fruehere Bronzeton lag
     mit 4.25:1 auf dem Papier unter dem Schwellenwert fuer kleine
     Schrift — und alle drei Stellen, an denen er steht, sind 11px.
     Dieser kommt auf 6.54:1. */
  --s4-akzent: #2f5d6b;
  --s4-linie: rgba(22, 34, 46, .16);
  --s4-pad: clamp(24px, 4vw, 64px);
  --s4-serif: 'Sentient', Georgia, serif;
  width: 100%;
  height: 100dvh;
  background: var(--s4-papier);
  color: var(--s4-tinte);
  overflow: hidden;
  font-size: 15px;
  line-height: 1.6;
}

.stil-site4__page {
  max-width: 1180px;
  margin: 0 auto;
  padding: 0 var(--s4-pad);
  will-change: transform;
}

.stil-site4__kopf {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 24px;
  padding: 26px 0 22px;
  border-bottom: 1px solid var(--s4-tinte);
}

.stil-site4__marke {
  font-family: var(--s4-serif);
  font-weight: 500;
  font-size: 21px;
  letter-spacing: .01em;
}

.stil-site4__marke em {
  display: block;
  font-family: var(--font);
  font-style: normal;
  font-weight: 400;
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--s4-grau);
  margin-top: 3px;
}

.stil-site4__nav {
  display: flex;
  gap: 26px;
  font-size: 13px;
  letter-spacing: .03em;
  color: var(--s4-grau);
}

.stil-site4__hero { padding: 96px 0 72px; }

.stil-site4__auge {
  margin: 0 0 22px;
  font-size: 11px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--s4-akzent);
}

.stil-site4__hero h3 {
  margin: 0;
  font-family: var(--s4-serif);
  font-weight: 400;
  font-size: clamp(38px, 4.6vw, 64px);
  line-height: 1.12;
  letter-spacing: -.01em;
}

.stil-site4__lead {
  max-width: 34em;
  margin: 28px 0 0;
  color: var(--s4-grau);
}

/* Kennzahlen: vier Werte auf einer Linie, die Zahl in Serife. */
.stil-site4__zahlen {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
  padding: 30px 0;
  border-top: 1px solid var(--s4-linie);
  border-bottom: 1px solid var(--s4-linie);
}

.stil-site4__zahlen strong {
  display: block;
  font-family: var(--s4-serif);
  font-weight: 500;
  font-size: 34px;
  line-height: 1.1;
}

.stil-site4__zahlen span {
  font-size: 12px;
  letter-spacing: .04em;
  color: var(--s4-grau);
}

.stil-site4__sek { padding: 64px 0 8px; }

.stil-site4__sek > h4 {
  margin: 0 0 30px;
  font-size: 11px;
  font-weight: 400;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--s4-akzent);
}

/* Leistungen: nummerierte Zeilen mit Haarlinien, Nummer im Akzent. */
.stil-site4__leistungen {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: leistung;
}

.stil-site4__leistungen li {
  counter-increment: leistung;
  display: grid;
  grid-template-columns: 64px 260px 1fr;
  gap: 18px;
  align-items: baseline;
  padding: 20px 0;
  border-top: 1px solid var(--s4-linie);
}

.stil-site4__leistungen li::before {
  content: counter(leistung, decimal-leading-zero);
  font-family: var(--mono);
  font-size: 12px;
  color: var(--s4-akzent);
}

.stil-site4__leistungen strong {
  font-family: var(--s4-serif);
  font-weight: 500;
  font-size: 19px;
}

.stil-site4__leistungen p {
  margin: 0;
  font-size: 14px;
  color: var(--s4-grau);
}

.stil-site4__team {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0 48px;
}

.stil-site4__team div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 0;
  border-top: 1px solid var(--s4-linie);
}

.stil-site4__team strong {
  font-family: var(--s4-serif);
  font-weight: 500;
  font-size: 16px;
}

.stil-site4__team span {
  font-size: 12px;
  color: var(--s4-grau);
  text-align: right;
}

.stil-site4__zitat {
  margin: 84px 0 0;
  padding: 0;
  font-family: var(--s4-serif);
  font-size: clamp(22px, 2.4vw, 30px);
  line-height: 1.35;
  max-width: 24em;
}

.stil-site4__zitat cite {
  display: block;
  margin-top: 16px;
  font-family: var(--font);
  font-style: normal;
  font-size: 12px;
  letter-spacing: .04em;
  color: var(--s4-grau);
}

.stil-site4__fuss {
  margin-top: 84px;
  padding: 22px 0 30px;
  border-top: 1px solid var(--s4-tinte);
  display: flex;
  flex-wrap: wrap;
  gap: 6px 36px;
  font-size: 13px;
}

.stil-site4__fuss span:first-child { font-family: var(--s4-serif); font-weight: 500; }

@media (max-width: 900px) {
  .stil-site4__zahlen { grid-template-columns: repeat(2, 1fr); }
  .stil-site4__leistungen li { grid-template-columns: 48px 1fr; }
  .stil-site4__leistungen p { grid-column: 2; }
  .stil-site4__team { grid-template-columns: 1fr; }
  .stil-site4__nav { display: none; }
}

/* Die Kartenreihe der Dienstleistungen auf arbeit.html. Eigene Klasse,
   weil .cards-4 auch auf preise.html steht und dort einen anderen
   Abstand traegt. */
.cards-4--dienste { margin-top: 120px; }

/* Abschnitt "Womit ich arbeite" auf derselben Seite: der Vorspann steht
   ohne Abstand unter der Ueberschrift, die Kartenreihe weiter darunter.
   Ueber die Kennung des Abschnitts, weil .cards-3 und .lead-md auch
   anderswo stehen und dort ihre Abstaende behalten. */
/* Die Appnamen sind nur fett, nicht farbig -- sie sollen den Satz nicht
   aufreissen. Schwarz wird allein der Name, auf dem die Maus steht. */
/* Die Karte reagiert als Ganzes auf das Zeigen, ist aber kein Verweis
   -- der Zeiger bleibt darum ueberall darin der normale, auch auf dem
   Text zwischen den Namen. */
#werkzeuge .tcard,
#werkzeuge .tcard * { cursor: default; }

#werkzeuge .tcard strong {
  color: var(--ink-4);
  transition: color .2s ease;
}

#werkzeuge .tcard strong:hover { color: var(--ink); }

/* Der Titel liegt in der ersten Zeile, der Faecher daneben spannt
   ueber sie und sitzt darin mittig. */
#werkzeuge .h2 { grid-row: 1; }
#werkzeuge .cards-3 { margin-top: 50px; }

/* ---------- Werkzeugfaecher (arbeit.html) ----------

   Acht quadratische Platzhalter, aufgefaechert und uebereinander
   geschoben, rechts neben der Ueberschrift. Beim Hereinscrollen
   springen sie einzeln nacheinander auf; zeigt man auf eine Karte,
   richtet sie sich gerade auf und schiebt ihre Nachbarn zur Seite --
   die naeheren zuerst.

   Lage und Neigung stehen als angemeldete Eigenschaften je Karte, das
   Schieben und Aufrichten setzt js/arbeit.js nur ueber --schub und
   --dreh. Angemeldet (@property) muessen sie sein, damit der Browser
   den Uebergang von transform daraus sauber rechnet; als gewoehnliche
   Variablen sprang die Bewegung. */
@property --lage {
  syntax: '<number>';
  inherits: false;
  initial-value: 0;
}

@property --dreh {
  syntax: '<angle>';
  inherits: false;
  initial-value: 0deg;
}

@property --schub {
  syntax: '<length>';
  inherits: false;
  initial-value: 0px;
}

@property --schritt {
  syntax: '<length>';
  inherits: true;
  initial-value: 0px;
}

.werkzeugfaecher {
  position: relative;
  /* Eine Spalte weiter links als der Text daneben endet, damit der
     Faecher trotz der groesseren Karten nicht an den Rand stoesst. */
  grid-column: 7 / span 6;
  grid-row: 1 / span 2;
  /* Auf Hoehe des Titels und des Satzes darunter, nicht darueber. */
  align-self: center;
  /* Schritt von Karte zu Karte, knapp die halbe Kartenbreite. Acht
     Karten spannen 7 Schritte plus eine Kartenbreite; das bleibt in den
     sechs Spalten und laesst dem Schub zur Seite noch Luft. */
  --karte: clamp(90px, 9.5vw, 124px);
  --schritt: clamp(43px, 4.5vw, 58px);
  height: calc(var(--karte) * 1.34);
}

.werkzeugkarte {
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--karte);
  aspect-ratio: 1 / 1;
  margin: calc(var(--karte) / -2) 0 0 calc(var(--karte) / -2);
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 6px 16px rgba(17, 17, 17, .07);
  overflow: hidden;
  /* Vor dem Aufspringen nicht da. Die Groesse steht in scale und nicht
     in transform: so bleibt transform fuer die Lage frei, und beides
     kommt sich nicht in die Quere. */
  scale: 0;
  transform: translateX(calc(var(--lage) * var(--schritt) + var(--schub))) rotate(var(--dreh));
  transition: transform .4s cubic-bezier(.34, 1.56, .64, 1);
}

/* Freiraum um das Zeichen: auf jeder Seite ein Viertel der Groesse des
   Zeichens selbst, wie es die Markenrichtlinie von Visual Studio Code
   verlangt. Das Zeichen misst damit zwei Drittel der Karte -- eine
   Kartenbreite ist das Zeichen plus zwei mal ein Viertel davon, also
   das Eineinhalbfache; zwei Drittel ist der Kehrwert.

   Die Vorlage fuellt ihr viewBox randlos aus (nachgemessen: Tusche von
   0 bis 100 in beiden Richtungen), der Freiraum kommt also allein aus
   dieser Breite und muss nicht um ein eingebautes Polster gerechnet
   werden. Der leere Platzhalter nimmt dasselbe Mass, damit beim
   Einsetzen der uebrigen Zeichen nichts springt. */
.werkzeugkarte__zeichen,
.werkzeugkarte__platz {
  display: block;
  /* Aus der Kartenbreite gerechnet, nicht als Anteil davon: geteilt
     durch anderthalb stimmt es auf die Aussenkante. */
  width: calc(var(--karte) / 1.5);
  height: auto;
}

/* Das Invertocat von GitHub verlangt nur ein Sechstel seiner Breite an
   Freiraum (nachgemessen an der Clearspace-Vorlage: 96 breites Zeichen
   in 128er Feld). Es ist ausserdem nicht ganz quadratisch, darum kein
   festes Seitenverhaeltnis -- gestaucht werden darf es nicht. */
.werkzeugkarte__zeichen--github {
  width: calc(var(--karte) / 1.36);
}

.werkzeugkarte__platz {
  background:
    radial-gradient(circle at 50% 50%,
      rgba(17, 17, 17, .09) 0 32%, transparent 32.5%);
}

/* Die Vorlage von Figma bringt schon viel Rand mit: das Zeichen selbst
   misst 400 x 600 in einem Feld von 1024 x 1280. Wuerde das Feld die
   Karte fuellen, waere das Zeichen winzig. Darum wird nach der Hoehe
   des Zeichens gerechnet -- sie soll wie ueberall zwei Drittel der
   Karte betragen, das Feld also das 1280/600-fache davon. Der
   ueberstehende Rand ist durchsichtig, die Karte schneidet ihn ab. */
.werkzeugkarte__zeichen--figma {
  width: auto;
  max-width: none;
  height: calc(var(--karte) / 1.52 * 1280 / 600);
}

/* Die Karten mit Zeichen sind Verweise. Der Rahmen fuer die Tastatur
   liegt aussen, sonst schnitte ihn die Karte am eigenen Rand ab. */
.werkzeugkarte:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

.werkzeugfaecher > :nth-child(1) { --lage: -3.5; --dreh:  8deg; --stufe: 0; }
.werkzeugfaecher > :nth-child(2) { --lage: -2.5; --dreh: -5deg; --stufe: 1; }
.werkzeugfaecher > :nth-child(3) { --lage: -1.5; --dreh:  6deg; --stufe: 2; }
.werkzeugfaecher > :nth-child(4) { --lage: -0.5; --dreh: -3deg; --stufe: 3; }
.werkzeugfaecher > :nth-child(5) { --lage:  0.5; --dreh:  4deg; --stufe: 4; }
.werkzeugfaecher > :nth-child(6) { --lage:  1.5; --dreh: -6deg; --stufe: 5; }
.werkzeugfaecher > :nth-child(7) { --lage:  2.5; --dreh:  5deg; --stufe: 6; }
.werkzeugfaecher > :nth-child(8) { --lage:  3.5; --dreh: -8deg; --stufe: 7; }

/* Aufspringen: ueber den Zielwert hinaus und zurueck, damit es federt.
   Eine echte elastische Kurve kennt CSS nicht -- die Stufen hier sind
   ihre Annaeherung. */
/* Wird ein Zeichen ueber seinen Namen im Text gezeigt, treten die
   uebrigen zurueck. Blass wird nur das Zeichen, nicht die Karte: waere
   die Karte durchsichtig, schienen die Nachbarn durch und der Stapel
   wuerde unleserlich. */
.werkzeugfaecher.ist-betont .werkzeugkarte:not(.ist-gemeint) .werkzeugkarte__zeichen {
  opacity: .2;
}

.werkzeugkarte__zeichen { transition: opacity .25s ease; }

@keyframes faecher-auf {
  0%   { scale: 0; }
  50%  { scale: 1.1; }
  68%  { scale: .94; }
  82%  { scale: 1.03; }
  92%  { scale: .99; }
  100% { scale: 1; }
}

.werkzeugfaecher.ist-auf .werkzeugkarte {
  animation: faecher-auf .85s cubic-bezier(.2, .7, .3, 1) both;
  animation-delay: calc(var(--stufe) * .07s);
}

/* Ohne Skript und bei abbestellter Bewegung stehen sie einfach da. */
@media (prefers-reduced-motion: reduce) {
  .werkzeugkarte { scale: 1; transition: none; }
  .werkzeugfaecher.ist-auf .werkzeugkarte { animation: none; }
}

@media (max-width: 960px) {
  .werkzeugfaecher {
    grid-column: 1 / span 12;
    grid-row: auto;
    margin-top: 40px;
  }

  /* Untereinander gehoert der Faecher unter den Vorspann, nicht
     zwischen Ueberschrift und Vorspann -- im Quelltext steht er
     dazwischen, weil er am Schreibtisch rechts neben der Ueberschrift
     sitzt. Die Reihenfolge stellt das hier gerade. */
  #werkzeuge .h2 { order: 1; grid-row: auto; }
  #werkzeuge .werkzeugfaecher { order: 2; }
  #werkzeuge .cards-3 { order: 3; }
}

/* Untereinander steht der Faecher unter dem Vorspann; dort darf er die
   ganze Breite nutzen und wird eine Stufe kleiner, damit der Schub zur
   Seite auf schmalen Schirmen nicht aus dem Bild laeuft. */
@media (max-width: 640px) {
  .werkzeugfaecher {
    --karte: clamp(62px, 17vw, 84px);
    --schritt: clamp(26px, 7.4vw, 36px);
    margin-top: 32px;
  }
}

/* ---------- Zeichen ueber der Karte ---------- */

/* Das Zeichen steht ueber der Oberlinie der Karte, mittig. Es haengt
   an der Karte statt im Textfluss, damit die drei Karten weiterhin auf
   derselben Hoehe beginnen -- im Fluss schoebe es die Zeile nach unten
   und liefe bei umbrechenden Titeln aus dem Tritt. */
.price-card--ikon { position: relative; }

.price-card__icon {
  position: absolute;
  top: 0;                         /* Unterkante der Linie */
  left: 50%;
  width: 86px;
  height: 86px;
  fill: var(--ink);
  transform: translate(-50%, calc(-100% - 14px));
}

/* Das Zeichen faedt einmal von unten ein, sobald es etwa auf halber
   Bildhoehe steht -- ausgeloest vom Skript, nicht an den Bildlauf
   gekoppelt -- und schwebt danach ruhig weiter.

   Der Versatz steckt in denselben Keyframes wie die Platzierung: das
   Zeichen haengt ueber der Karte an einem transform, und ein zweites
   transform aus einer Animation wuerde es sonst ueberschreiben. */
/* Das Zeichen startet schwarz und flach, wird auf dem Weg weiss und
   wirft dabei einen Schatten, und steht am Ende wieder schwarz und
   flach da. Der Schatten laeuft auf drop-shadow(0 0 0 transparent)
   aus statt auf none: zwischen einer Filterliste und none gibt es
   keinen Zwischenschritt, er spraenge sonst weg. */
@keyframes ikon-einfaden {
  0% {
    opacity: 0;
    transform: translate(-50%, calc(-100% + 12px));
    fill: var(--ink);
    filter: drop-shadow(0 0 0 transparent);
  }
  /* Vor und nach dem hellen Moment steht es schon wieder schwarz da,
     damit der Wechsel ein kurzes Aufblitzen bleibt und nicht ueber den
     ganzen Weg laeuft. */
  8% {
    fill: var(--ink);
    filter: drop-shadow(0 0 0 transparent);
  }
  26% {
    fill: #fff;
    filter: drop-shadow(0 3px 6px rgba(0, 0, 0, .26));
  }
  36% {
    fill: #fff;
    filter: drop-shadow(0 3px 6px rgba(0, 0, 0, .26));
  }
  52% {
    fill: var(--ink);
    filter: drop-shadow(0 0 0 transparent);
  }
  100% {
    opacity: 1;
    transform: translate(-50%, calc(-100% - 14px));
    fill: var(--ink);
    filter: drop-shadow(0 0 0 transparent);
  }
}

@keyframes ikon-schweben {
  0%, 100% { transform: translate(-50%, calc(-100% - 14px)); }
  50%      { transform: translate(-50%, calc(-100% - 21px)); }
}

/* Das Schweben steht hinter dem Einfaden in der Liste und beginnt
   genau dann, wenn jenes endet -- die spaetere Animation gewinnt beim
   transform, vor ihrem Start traegt sie nichts bei. */
.price-card__icon {
  --stufe: 0s;
  --schwebe: 4.6s;
  animation:
    ikon-einfaden .85s cubic-bezier(.2, .6, .2, 1) var(--stufe) both,
    ikon-schweben var(--schwebe) ease-in-out calc(var(--stufe) + .85s) infinite;
}

/* Abgestuft, damit die drei nicht als Block aufblenden -- und mit
   ungleichen Schwebedauern, damit sie auch nach einer Weile nicht in
   den Gleichtakt fallen. */
.cards-3 > :nth-child(2) .price-card__icon { --stufe: .13s; --schwebe: 5.4s; }
.cards-3 > :nth-child(3) .price-card__icon { --stufe: .26s; --schwebe: 4.1s; }

/* Mit JavaScript wartet es, bis es in der Bildmitte angekommen ist.
   Ohne Skript laeuft es beim Laden ab -- dann ist es wenigstens da. */
.price-card--ikon.wartet .price-card__icon {
  animation: none;
  opacity: 0;
}

.price-card--ikon.ist-sichtbar .price-card__icon {
  opacity: 1;
  animation:
    ikon-einfaden .85s cubic-bezier(.2, .6, .2, 1) var(--stufe) both,
    ikon-schweben var(--schwebe) ease-in-out calc(var(--stufe) + .85s) infinite;
}

/* Der Umlauf wiegt sich im selben Takt wie der grosse Stern, damit er
   nicht gegen ihn arbeitet -- gleiche Keyframes, gleiche Dauer, kein
   Versatz -- nur mit kleinerem Ausschlag, sonst kippt die flache Bahn
   viel staerker ins Auge als der Stern selbst. Der Drehpunkt ist die
   Mitte des Sterns im Zeichenraster. */
.stern-umlauf {
  transform-box: view-box;
  transform-origin: 34px 24px;
  animation: umlauf-wiegen 4.05s ease-in-out infinite;
}

@keyframes umlauf-wiegen {
  0%, 100% { transform: rotate(-1.6deg); }
  50%      { transform: rotate(1.6deg); }
}

/* Die Bahn ist nur angedeutet -- aber mit einem deckenden Grau, nicht
   mit durchsichtigem Schwarz: durchsichtig verschwindet die Linie genau
   dort, wo sie ueber dem Stern liegen soll. Das Grau ist das, was das
   frueher Durchsichtige auf dem Seitengrund ergab. */
.stern-umlauf__bahn {
  fill: none;
  stroke: #cbc7c3;
  stroke-width: .9;
}

/* Beide Punkte laufen auf der ganzen Ellipse und zur gleichen Zeit --
   zu sehen ist aber immer nur der, dessen Haelfte gerade stimmt. Kann
   der Browser offset-path nicht, stehen sie still in der Mitte; dann
   fehlt nur die Bewegung, nichts verrutscht. */
.stern-umlauf__punkt {
  offset-path: path('M18.5 24a15.5 5.27 0 1 0 31 0a15.5 5.27 0 1 0 -31 0');
  offset-rotate: 0deg;
  animation: stern-umlauf-vorn 7.5s linear infinite;
}

.stern-umlauf__punkt--hinten { animation-name: stern-umlauf-hinten; }

@keyframes stern-umlauf-vorn {
  0%          { offset-distance: 0%;   opacity: 0; }
  49.9%       {                        opacity: 0; }
  50%         {                        opacity: 1; }
  100%        { offset-distance: 100%; opacity: 1; }
}

@keyframes stern-umlauf-hinten {
  0%          { offset-distance: 0%;   opacity: 1; }
  49.9%       {                        opacity: 1; }
  50%         {                        opacity: 0; }
  100%        { offset-distance: 100%; opacity: 0; }
}

/* Die Verbindungslinien im Zeichen "Extrafunktionen": gestrichen statt
   gefuellt -- das Zeichen fuellt sonst alles mit Tusche.

   Im Ruhezustand ist keine zu sehen: sie treten nur zu ihrem Auftritt
   hervor -- die Linie waechst zum Stern, der Stern kommt auf die Mitte
   zu, am naechsten Punkt zieht sich die Linie zurueck, dann geht der
   Stern heim. Gesteuert von js/preise.js, samt dem Atmen der Kurve:
   Kurve, Endpunkt und sichtbare Laenge haengen an derselben
   Pfadangabe, getrennte Bewegungen darauf wuerden sich
   ueberschreiben. Ohne Skript und bei abbestellter Bewegung ist nichts
   davon zu sehen. */
.price-card__icon .stern-linie {
  fill: none;
  stroke: var(--ink);
  stroke-width: .55;
  opacity: .28;
  animation: none !important;
  /* Ohne Skript unsichtbar: der Strich ist durchgehend Luecke. Das
     Skript setzt Strich und Versatz, sobald eine Linie auftritt. */
  stroke-dasharray: 0 1;
}

/* Die einzelnen Sterne wiegen sich um die eigene Achse -- je groesser,
   desto weniger. Die ganz kleinen drehen ganz durch. transform-box
   sorgt dafuer, dass sich jeder Pfad um seine eigene Mitte dreht und
   nicht um den Nullpunkt des Zeichens. */
.price-card__icon path {
  transform-box: fill-box;
  transform-origin: 50% 50%;
}

.price-card__icon .stern--gross  { animation: stern-wiegen-1 4.05s ease-in-out infinite; }
.price-card__icon .stern--mittel { animation: stern-wiegen-2 3.25s ease-in-out infinite; }
.price-card__icon .stern--klein  { animation: stern-wiegen-3 2.75s ease-in-out infinite; }
.price-card__icon .stern--winzig { animation: stern-drehen 5.6s linear infinite; }

/* Negative Verzoegerungen setzen jeden Stern an eine andere Stelle
   seines Zyklus -- sonst wiegen sich alle im Gleichtakt. */
.price-card__icon path:nth-of-type(2) { animation-delay: -1.05s; }
.price-card__icon path:nth-of-type(3) { animation-delay: -1.95s; }
.price-card__icon path:nth-of-type(4) { animation-delay: -2.85s; }
.price-card__icon path:nth-of-type(5) { animation-delay: -1.45s; }
.price-card__icon path:nth-of-type(6) { animation-delay: -3.45s; }
.price-card__icon path:nth-of-type(7) { animation-delay: -0.55s; }

@keyframes stern-wiegen-1 {
  0%, 100% { transform: rotate(-5deg); }
  50%      { transform: rotate(5deg); }
}

@keyframes stern-wiegen-2 {
  0%, 100% { transform: rotate(-13deg); }
  50%      { transform: rotate(13deg); }
}

@keyframes stern-wiegen-3 {
  0%, 100% { transform: rotate(-28deg); }
  50%      { transform: rotate(28deg); }
}

@keyframes stern-drehen {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* Bei abbestellter Bewegung bleiben Sterne und Umlauf stehen -- die
   Bahn selbst darf bleiben, sie ist nur eine Linie. */
@media (prefers-reduced-motion: reduce) {
  .price-card__icon path,
  .stern-umlauf,
  .stern-umlauf__punkt { animation: none; }
}

/* Ein Zeichen ist breiter als hoch -- die Hoehe bleibt gleich, damit
   die drei in einer Flucht stehen. */
.price-card__icon--breit { width: calc(86px * 68 / 48); }

@media (max-width: 760px) {
  .price-card__icon { width: 54px; height: 54px; }
  .price-card__icon--breit { width: calc(54px * 68 / 48); }
}

/* ---------- Fragezeichen neben den Fragen und Antworten ----------
   Der Abschnitt traegt seinen Inhalt in den mittleren Spalten; links und
   rechts bleibt Platz. Dort steht je eine Reihe von drei Fragezeichen,
   ueber die ganze Hoehe des Abschnitts verteilt.

   Die Perspektive sitzt an der Reihe, nicht am Zeichen: so teilen sich
   die drei einen Fluchtpunkt und die Drehung sieht nach einer Drehung
   im Raum aus und nicht nach einem Verziehen. */
#faq { position: relative; }

.fragezeichen {
  position: absolute;
  top: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  justify-content: space-around;
  align-items: center;
  perspective: 900px;
  pointer-events: none;
}

/* Jede Reihe reicht vom Fensterrand bis an die Fragenspalte heran und
   richtet ihre Zeichen darin mittig aus -- ihr Mittelpunkt liegt damit
   genau zwischen den Zeilen und dem Rand, und zwar auf jeder
   Fensterbreite. Die Gasse ist aus demselben Raster gerechnet, das die
   Seite benutzt: zwoelf Spalten, 32 Pixel Luecke, 48 Pixel Polster, und
   die Fragen stehen ab der dritten Spalte. */
.fragezeichen {
  /* Ohne den Rollbalken gerechnet: 100vw zaehlt ihn mit, die Seite
     selbst ist aber um ihn schmaler -- sonst reicht die rechte Reihe
     ueber den Rand hinaus und die Seite laesst sich schieben. Die
     Breite hinterlegt js/main.js. */
  --sicht: calc(100vw - var(--rollbalken, 0px));
  --spalte: calc((min(var(--sicht), 1280px) - 96px - 352px) / 12);
  --gasse: calc(48px + 2 * var(--spalte) + 64px);
  --rand: max(0px, calc((var(--sicht) - 1280px) / 2));
  width: calc(var(--rand) + var(--gasse));
}

.fragezeichen--links  { left: calc(-1 * var(--rand)); }
.fragezeichen--rechts { right: calc(-1 * var(--rand)); }

/* Die rechte Reihe steht versetzt, damit die sechs nicht in Paaren
   nebeneinander liegen. */
.fragezeichen--rechts { padding-top: 9%; }

.fragezeichen__z {
  font-family: var(--font-display, var(--font));
  font-weight: 700;
  font-size: clamp(120px, 15vw, 228px);
  line-height: 1;
  color: var(--ink);
  opacity: .11;
  transform-style: preserve-3d;
  /* Jedes Zeichen steht ein wenig anders: leicht gekippt, etwas zur
     Seite und ein Hauch aus der Flaeche gedreht. Sechs gleich stehende
     Zeichen sahen nach einer Tapete aus. */
  --kipp: 0deg;
  --neig: 0deg;
  --seit: 0px;
  /* Vor dem Einfliegen unten und mitten in der Drehung. */
  transform: translate3d(0, 120px, -140px) rotateY(-180deg) rotateX(22deg);
}

/* Der Versatz zur Seite steht in Prozent der Zeichenbreite, damit er
   mit der Groesse mitwaechst. Nach innen versetzte wechseln sich mit
   nach aussen versetzten ab, so steht keines ueber dem anderen. */
.fragezeichen--links  > :nth-child(1) { --kipp: -13deg; --neig:  16deg; --seit:  30%; }
.fragezeichen--links  > :nth-child(2) { --kipp:   9deg; --neig: -12deg; --seit: -22%; }
.fragezeichen--links  > :nth-child(3) { --kipp: -18deg; --neig:  10deg; --seit:  42%; }
.fragezeichen--rechts > :nth-child(1) { --kipp:  15deg; --neig: -14deg; --seit: -34%; }
.fragezeichen--rechts > :nth-child(2) { --kipp: -10deg; --neig:  13deg; --seit:  24%; }
.fragezeichen--rechts > :nth-child(3) { --kipp:  20deg; --neig:  -9deg; --seit: -44%; }

/* Sobald der Abschnitt in Sicht kommt, suchen sie ihren Platz. */
.fragezeichen.ist-da .fragezeichen__z {
  animation: fragezeichen-einfliegen 1.5s cubic-bezier(.16, .84, .3, 1) both;
}

.fragezeichen__z:nth-child(2) { animation-delay: .18s; }
.fragezeichen__z:nth-child(3) { animation-delay: .36s; }

@keyframes fragezeichen-einfliegen {
  from {
    transform: translate3d(calc(var(--seit) * .3), 130px, -160px)
               rotateY(-200deg) rotateX(24deg) rotateZ(0deg);
  }
  to {
    transform: translate3d(var(--seit), 0, 0)
               rotateY(var(--neig)) rotateX(0deg) rotateZ(var(--kipp));
  }
}

/* Ohne Platz an den Seiten haben sie nichts verloren. */
@media (max-width: 1180px) {
  .fragezeichen { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .fragezeichen__z { transform: none; animation: none; }
}

/* ---------- Zeichen neben einer Ueberschrift ---------- */

/* Steht wie der Bildlauf auf der Startseite in der rechten Spalte,
   oben buendig mit der Ueberschrift. Quadratisch angelegt, damit die
   Flaeche schon vor dem Zeichnen steht. */
/* Absolut in seiner Rasterflaeche: so bestimmt es die Zeilenhoehe
   nicht mit. Als normales Rasterfeld zoege es die erste Zeile auf
   seine Hoehe und schoebe den Absatz darunter nach unten. */
#laufend .grid { position: relative; }

.kopfzeichen {
  position: absolute;
  grid-row: 1;
  top: 20px;
  left: 0;
  right: 0;
  margin: 0;
  display: flex;
  justify-content: center;
  color: var(--ink);
}

.kopfzeichen svg {
  display: block;
  width: min(190px, 100%);
  height: auto;
  aspect-ratio: 1 / 1;
}

/* Das viewBox ist fuer die groessere Kugel gewachsen, die Breite oben
   gleicht das aus -- der Server bleibt dadurch gleich gross. */
.kopfzeichen__wort {
  font-family: var(--font);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: -.02em;
}

/* Zwischen 641 und 900 Pixeln bleibt neben dem Vorspann Platz fuer das
   Zeichen: es steht rechts, der Text links und laeuft ueber mehrere
   Zeilen. Ueber der ganzen Breite darunter (wie es die Regel unten
   macht) blieb links davon eine leere Flaeche stehen.

   Beide Felder brauchen ihre Zeile ausdruecklich: das Zeichen steht im
   Quelltext vor dem Vorspann, und die selbsttaetige Platzierung rueckt
   nur vorwaerts -- der Vorspann waere also in Zeile 3 gerutscht. */
@media (min-width: 641px) and (max-width: 900px) {
  #laufend .kopfzeichen {
    position: static;
    grid-row: 2;
    grid-column: 8 / span 5;
    margin: 0;
    justify-content: flex-end;
  }

  #laufend .kopfzeichen svg { width: min(170px, 100%); }

  #laufend .lead-md {
    grid-row: 2;
    grid-column: 1 / span 7;
  }
}

@media (max-width: 640px) {
  .kopfzeichen {
    position: static;
    /* grid-row zuruecknehmen: der Grundzustand setzt die Zeile 1, damit
       das Zeichen neben der Ueberschrift schwebt. Steht es wieder im
       Fluss, schob ihn diese Zeile vor die Ueberschrift -- das Zeichen
       stand also ueber "Laufende Kosten:" statt darunter. */
    grid-row: auto;
    grid-column: 1 / span 12;
    justify-content: flex-start;
    margin-top: 28px;
  }
  .kopfzeichen svg { width: 150px; }
}

/* ---------- Zeichen auf den Karten "Keine extra Kosten" ---------- */
/* Die erste Karte tauscht am Handy Zeichen und Titel: dort ist nicht
   die Handy-, sondern die Desktop-Ansicht das Versprechen. Beide
   Fassungen stehen im Markup, hier gilt die grosse; die Umschaltung
   steht in css/preise-handy.css. */
.cards-4--ikonen .zeichen--schreibtisch,
.cards-4--ikonen .titel--schreibtisch { display: none; }

/* Eigene Klasse statt .cards-4 allein: dieselbe Kartenreihe steht auch
   auf der Arbeit-Seite, und die soll weder den Abstand noch die
   Zeichen erben. Der Abstand folgt den uebrigen Kartenreihen hier. */
.cards-4--ikonen { margin-top: 120px; }

/* Das Zeichen sitzt mittig ueber der Oberlinie der Karte, wie bei den
   Preiskarten. Absolut gesetzt, damit es die Zeile nicht verschiebt --
   die Karten stehen dadurch weiter in einer Flucht. */
.cards-4--ikonen .tcard { position: relative; }

/* Die Kartenzeichen als Koerper, gezeichnet in der Flaeche. Aufbau
   und Begruendung in js/preise.js; hier Masse und Bewegung.

   Jedes Teil bekommt dieselbe Drehung: waagrecht um den Kosinus
   gestaucht und um seine Lage in der Tiefe mal Sinus verschoben. Die
   Lage traegt jedes Teil als --lage (-0.5 hinten bis 0.5 vorne), die
   Tiefe steht in Einheiten des viewBox. Vierundzwanzig Stuetzstellen
   je Umdrehung, dazwischen geradlinig -- der Fehler gegen den echten
   Kreisbogen bleibt unter einem Prozent.

   In der Kantenlage stauchen sich beide Seiten auf null, waehrend die
   Flankenkopien um die volle Tiefe auseinanderstehen: uebrig bleibt
   genau die Seitenansicht. */
.ikon3d {
  position: absolute;
  top: 0;
  left: 50%;
  width: 56px;
  height: 56px;
  transform: translate(-50%, calc(-100% - 24px));
}

.ikon3d__koerper {
  width: 100%;
  height: 100%;
}

.tcard__icon {
  --tiefe: 5.2;               /* Einheiten des viewBox, ~6 Bildpunkte */
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;          /* die Flanke ragt knapp ueber den Rand */
  color: var(--ink);
  fill: none;
  stroke: currentColor;
  stroke-width: 3;
  stroke-linejoin: round;
}

.tcard__icon use {
  transform-box: view-box;
  transform-origin: 50% 50%;
  animation: k3d-drehen 7s linear infinite;
}

/* Flanke: die Silhouette ganz im vollen Ton, gestaffelt versetzt.
   Sie bekommt eine eigene Drehung, die kurz vor der Kante bei fuenf
   Prozent Breite stehen bleibt und das Vorzeichen in einem echten
   Sprung wechselt (step-end): bei null Breite waeren die Kopien
   Haarstriche mit Luecken dazwischen. Ueberblendet wuerde die Breite
   fuer einen Sekundenbruchteil doch durch null laufen, und ab und zu
   traefe ein Bild genau diesen Moment. */
.tcard__icon .k3d__flanke { fill: var(--ink); animation-name: k3d-flanke; }

/* Die beiden Seiten tragen das Zeichen auf Papier. Es ist immer nur
   die dem Betrachter zugewandte zu sehen; die andere liegt ohnehin
   vollstaendig unter der Flanke. */
.k3d__seite { fill: var(--bg); }
.tcard__icon .k3d__seite--vorne  { animation: k3d-drehen 7s linear infinite, k3d-vorne  7s linear infinite; }
.tcard__icon .k3d__seite--hinten { animation: k3d-drehen 7s linear infinite, k3d-hinten 7s linear infinite; }

@keyframes k3d-drehen {
  0% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0 * 1px)) scaleX(1); }
  4.1667% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.2588 * 1px)) scaleX(0.9659); }
  8.3333% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.5 * 1px)) scaleX(0.866); }
  12.5% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.7071 * 1px)) scaleX(0.7071); }
  16.6667% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.866 * 1px)) scaleX(0.5); }
  20.8333% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.9659 * 1px)) scaleX(0.2588); }
  25% { transform: translateX(calc(var(--lage) * var(--tiefe) * 1 * 1px)) scaleX(0); }
  29.1667% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.9659 * 1px)) scaleX(-0.2588); }
  33.3333% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.866 * 1px)) scaleX(-0.5); }
  37.5% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.7071 * 1px)) scaleX(-0.7071); }
  41.6667% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.5 * 1px)) scaleX(-0.866); }
  45.8333% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.2588 * 1px)) scaleX(-0.9659); }
  50% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0 * 1px)) scaleX(-1); }
  54.1667% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.2588 * 1px)) scaleX(-0.9659); }
  58.3333% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.5 * 1px)) scaleX(-0.866); }
  62.5% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.7071 * 1px)) scaleX(-0.7071); }
  66.6667% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.866 * 1px)) scaleX(-0.5); }
  70.8333% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.9659 * 1px)) scaleX(-0.2588); }
  75% { transform: translateX(calc(var(--lage) * var(--tiefe) * -1 * 1px)) scaleX(0); }
  79.1667% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.9659 * 1px)) scaleX(0.2588); }
  83.3333% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.866 * 1px)) scaleX(0.5); }
  87.5% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.7071 * 1px)) scaleX(0.7071); }
  91.6667% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.5 * 1px)) scaleX(0.866); }
  95.8333% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.2588 * 1px)) scaleX(0.9659); }
  100% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0 * 1px)) scaleX(1); }
}

@keyframes k3d-flanke {
  0% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0 * 1px)) scaleX(1); }
  4.1667% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.2588 * 1px)) scaleX(0.9659); }
  8.3333% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.5 * 1px)) scaleX(0.866); }
  12.5% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.7071 * 1px)) scaleX(0.7071); }
  16.6667% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.866 * 1px)) scaleX(0.5); }
  20.8333% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.9659 * 1px)) scaleX(0.2588); }
  24.99% { transform: translateX(calc(var(--lage) * var(--tiefe) * 1 * 1px)) scaleX(0.05); animation-timing-function: step-end; }
  25.01% { transform: translateX(calc(var(--lage) * var(--tiefe) * 1 * 1px)) scaleX(-0.05); }
  29.1667% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.9659 * 1px)) scaleX(-0.2588); }
  33.3333% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.866 * 1px)) scaleX(-0.5); }
  37.5% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.7071 * 1px)) scaleX(-0.7071); }
  41.6667% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.5 * 1px)) scaleX(-0.866); }
  45.8333% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0.2588 * 1px)) scaleX(-0.9659); }
  50% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0 * 1px)) scaleX(-1); }
  54.1667% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.2588 * 1px)) scaleX(-0.9659); }
  58.3333% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.5 * 1px)) scaleX(-0.866); }
  62.5% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.7071 * 1px)) scaleX(-0.7071); }
  66.6667% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.866 * 1px)) scaleX(-0.5); }
  70.8333% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.9659 * 1px)) scaleX(-0.2588); }
  74.99% { transform: translateX(calc(var(--lage) * var(--tiefe) * -1 * 1px)) scaleX(-0.05); animation-timing-function: step-end; }
  75.01% { transform: translateX(calc(var(--lage) * var(--tiefe) * -1 * 1px)) scaleX(0.05); }
  79.1667% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.9659 * 1px)) scaleX(0.2588); }
  83.3333% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.866 * 1px)) scaleX(0.5); }
  87.5% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.7071 * 1px)) scaleX(0.7071); }
  91.6667% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.5 * 1px)) scaleX(0.866); }
  95.8333% { transform: translateX(calc(var(--lage) * var(--tiefe) * -0.2588 * 1px)) scaleX(0.9659); }
  100% { transform: translateX(calc(var(--lage) * var(--tiefe) * 0 * 1px)) scaleX(1); }
}

/* Sichtbarkeit springt, sie wird nicht ueberblendet: zwischen zwei
   Stuetzstellen gilt "sichtbar", sobald eine von beiden sichtbar ist.
   Darum die Stuetzstellen dicht beieinander an den Wechseln. */
@keyframes k3d-vorne {
  0%, 24.99%  { visibility: visible; }
  25%, 75%    { visibility: hidden; }
  75.01%, 100% { visibility: visible; }
}
@keyframes k3d-hinten {
  0%, 24.99%  { visibility: hidden; }
  25%, 75%    { visibility: visible; }
  75.01%, 100% { visibility: hidden; }
}

/* Versetzt anlaufen, damit die vier nicht im Gleichschritt stehen. */
.cards-4--ikonen > :nth-child(2) .tcard__icon use { animation-delay: -1.75s; }
.cards-4--ikonen > :nth-child(3) .tcard__icon use { animation-delay: -3.5s; }
.cards-4--ikonen > :nth-child(4) .tcard__icon use { animation-delay: -5.25s; }

@media (prefers-reduced-motion: reduce) {
  .tcard__icon use { animation: none; }
  .k3d__seite--hinten { visibility: hidden; }
}

.tcard__ikonwort {
  font-family: var(--font);
  font-weight: 700;
  letter-spacing: -.02em;
  stroke: none;
}

/* Vier Karten: ab 961 Pixeln in einer Reihe, darunter zwei mal zwei,
   unter 540 untereinander. Zwei Spalten geben bei 540 je 234 Pixel, der
   laengste Titel ("Technische SEO-Basis") misst 170. Vorher sprang die
   Reihe bei 960 von vier Spalten direkt auf eine; Tablets bekamen 720
   bis 912 Pixel breite Karten mit drei Zeilen Text.

   Sobald mehr als eine Reihe steht, haengt ueber jeder Karte der zweiten
   ein Zeichen, und die Zeichen stehen ausserhalb des Flusses: mit dem
   Zeilenabstand von 32 ragten sie 46 Pixel in die Karte darueber --
   gemessen auch zwischen 901 und 960, wo der groessere Abstand bisher
   nicht griff. Achtzig braucht ein Zeichen samt Luft zur Oberlinie. */
@media (max-width: 960px) {
  .cards-4--ikonen { grid-template-columns: 1fr 1fr; row-gap: 104px; }
}

@media (max-width: 539px) {
  .cards-4--ikonen { grid-template-columns: 1fr; }
}

/* Der Schlussabschnitt der Preisseite und der auf ueber-mich.html
   stehen luftiger als der auf index.html -- darum eine eigene Klasse
   daneben statt einer Aenderung an .sec--closing. Der Abstand
   staffelt mit der Breite, damit er im schmalen Fenster nicht zur
   leeren Flaeche wird. */
.sec--closing-weit { padding-block: clamp(120px, 20vw, 200px); }
.sec--closing-weit .closing-actions--wide { margin-top: 40px; }

/* Der Schlussknopf steht allein, seit der Verweis daneben weg ist --
   darum groesser. Eigene Klasse statt einer Aenderung an .btn: der
   Knopf steht in dieser Form auf allen Seiten. */
.btn--gross {
  padding: 22px 40px;
  font-size: 17px;
}

@media (max-width: 640px) {
  .btn--gross { padding: 20px 26px; font-size: 16px; }
}

/* Der Vorspann dieser Seite kommt ohne Abstand zwischen Titel und
   Fliesstext aus. Eigene Klasse statt einer Aenderung an .lead: die
   Kopfabsaetze auf index.html und kontakt.html tragen dieselbe und
   sollen bleiben, wie sie sind. */
.sec--head .lead--dicht {
  margin-top: 0;
  /* 19 Pixel auf 272 Pixel Zeile (320er Schirm) gaben 28 Zeichen pro
     Zeile; mit 17 werden es 32. Ab 720 Pixeln Breite die vollen 19. */
  font-size: clamp(17px, 15.4px + .5vw, 19px);
}

/* Untereinander brauchen die Preiskarten Platz fuer ihre Sternzeichen:
   die haengen ausserhalb des Flusses 72 Pixel hoch und 14 ueber der
   Oberlinie, ragten mit dem Zeilenabstand von 32 also gemessen 34 bis
   52 Pixel in die Karte darueber. */
@media (max-width: 960px) {
  .cards-3:has(.price-card--ikon) { row-gap: 104px; }
}

/* Der Info-Punkt ist 18 Pixel gross -- als Schaltflaeche fuer den Finger
   zu klein, empfohlen sind mindestens 24. Auf Geraeten mit grobem
   Zeiger vergroessert ein unsichtbares Feld die Trefferflaeche auf 44
   Pixel, ohne den Punkt selbst zu veraendern. Nur dort: mit der Maus
   soll die Blase weiter genau ueber Wort und Punkt aufgehen. */
@media (pointer: coarse) {
  .info-dot { position: relative; }
  .info-dot::after {
    content: '';
    position: absolute;
    inset: -13px;
  }
}

/* ---------- Fliessende Abstaende (Preise) ---------- */
/* Die Abschnittspolster standen auf jeder Breite gleich: 96 oben und
   unten, der Schluss 200 und 200 -- bei 320 Pixeln waren damit 15
   Prozent der Seitenhoehe leeres Polster, und um drei Zeilen Schluss-
   text lagen 400 Pixel Luft. Die Masse laufen jetzt mit der Breite:
   ab 960 Pixeln stehen die bisherigen Werte, bei 320 zwei Drittel
   davon. Ueber die Klasse am body nur auf dieser Seite; die anderen
   Seiten behalten .sec unveraendert. */
.seite-preise .sec { padding-block: clamp(64px, 10vw, 96px); }
.seite-preise .sec--head { padding-top: clamp(72px, 12.5vw, 120px); }
/* Der Schlussabschnitt behaelt sein eigenes, luftigeres Mass -- sonst
   zieht die Zeile darueber ihn auf das Mass der uebrigen Abschnitte
   dieser Seite herunter. */
.seite-preise .sec--closing-weit { padding-block: clamp(120px, 20vw, 200px); }

/* ---------- Kopfsektion der Preisseite ----------

   Titel, Vorspann und die beiden Verweise stehen links untereinander,
   die Muenze rechts daneben und auf halber Hoehe des Stapels.

   Vorher lag der Titel in derselben Rasterzeile wie die Muenze und der
   Vorspann in der Zeile darunter. Die Muenze ist hoeher als der Titel,
   also bestimmte sie die Zeilenhoehe -- unter dem Titel klaffte eine
   leere Flaeche von gut zweihundert Pixeln, und weiter unten sass der
   Vorspann auf halber Fensterbreite neben nichts. Zwischen 641 und 960
   Pixeln fielen die Spalten zusammen, dort lief der Vorspann ueber die
   ganze Breite und der Kopf zerfiel in drei zusammenhanglose Bloecke.

   Nebeneinander gibt es diese Luecke nicht mehr: der Stapel bestimmt die
   Hoehe, die Muenze richtet sich daran aus.

   Ab 700 Pixeln und nicht erst ab 900: bei 768 mal 600 ragte der
   gestapelte Kopf 21 Pixel unter die Bildkante, nebeneinander bleiben
   dort 200 uebrig. Sieben Spalten sind bei 768 Pixeln noch 400 breit,
   das traegt den Vorspann gut. */
@media (min-width: 700px) {
  /* Der Kopf nimmt eine Bildhoehe abzueglich der Kopfzeile ein, und der
     Platz, der im Stapel uebrig bleibt, verteilt sich auf die beiden
     Luecken darin: drei Teile zwischen Titel und Vorspann, einer
     zwischen Vorspann und Verweisen. Darum Rasterzeilen mit fr und
     nicht Abstaende in Pixeln -- fr teilt genau das auf, was da ist,
     und braucht keine geratenen Werte je Fenstergroesse. Die minmax
     halten die Luecken auch dann auseinander, wenn nichts uebrig ist.

     svh und nicht vh: auf einem Laptop mit ausgefahrener Leiste ist vh
     die groessere Hoehe, der Kopf ragte dann darunter. */
  .seite-preise .sec--head {
    display: flex;
    /* Nach oben begrenzt: auf einem 1080 Pixel hohen Schirm waeren 344
       Pixel zwischen Titel und Vorspann geraten, der Titel schwebte
       allein. 780 halten den Stapel zusammen und lassen unten Luft. */
    min-height: min(calc(100svh - 77px), 780px);
  }

  /* Steht der Sprachhinweis noch oben, ist eine Bildhoehe schon um
     seine Zeile kleiner. */
  body:has(.lang-banner:not([hidden])) .seite-preise .sec--head {
    min-height: min(calc(100svh - 77px - 37px), 780px);
  }

  .seite-preise .sec--head > .grid {
    flex: 1;
    grid-template-rows: auto minmax(24px, 3fr) auto minmax(16px, 1fr) auto;
    align-items: start;
    row-gap: 0;
  }

  .seite-preise .sec--head .h1 { grid-column: 1 / span 7; grid-row: 1; }

  .seite-preise .sec--head .lead--dicht {
    grid-column: 1 / span 7;
    grid-row: 3;
    margin-top: 0;
  }

  .seite-preise .sec--head .jumplinks {
    grid-column: 1 / span 7;
    grid-row: 5;
    justify-content: flex-start;
    margin-top: 0;
  }

  /* Ueber alle drei Zeilen und mittig darin. Das Mass folgt der
     Bildhoehe, damit der Kopf auch in flachen Fenstern ganz ins Bild
     passt; das Videobild traegt rund ein Drittel leeren Rand, darum
     eher groesser als knapp. */
  /* Fuenf Spalten statt vier und ein hoeheres Mass an der Bildhoehe:
     vier Spalten sind bei der Hoechstbreite von 1280 Pixeln nur 373
     breit, und weil das Videobild rund ein Drittel leeren Rand traegt,
     blieben davon 254 Pixel Muenze -- auf einem 1920er Schirm zu wenig.
     Ueber fuenf Spalten sind es 474, also 321 Pixel Muenze. Spalte 8
     bleibt frei: der Titel reicht bis Spalte 7. */
  .seite-preise .sec--head .kopfvideo {
    grid-column: 8 / span 5;
    grid-row: 1 / span 5;
    align-self: center;
    justify-self: end;
    width: min(100%, 62vh);
    margin: 0;
  }
}

/* Unter der Kopfzeile von 65 statt 77 Pixeln. */
@media (min-width: 700px) and (max-width: 960px) {
  .seite-preise .sec--head { min-height: min(calc(100svh - 65px), 780px); }

  body:has(.lang-banner:not([hidden])) .seite-preise .sec--head {
    min-height: min(calc(100svh - 65px - 37px), 780px);
  }
}

/* Flache Fenster: die Polster geben nach, damit die Muenze gross bleiben
   kann. Dieselben Werte wie in main.css, hier wiederholt, weil die
   Regeln weiter oben in dieser Datei sie sonst ueberstimmen. */
@media (min-width: 700px) and (max-height: 880px) {
  .seite-preise .sec--head {
    padding-top: clamp(52px, 10vh, 80px);
    padding-bottom: clamp(40px, 8vh, 64px);
  }
}

/* Unter 700 Pixeln stehen Titel, Muenze, Vorspann und Verweise
   untereinander -- nebeneinander blieben fuer den Vorspann keine
   vierzig Zeichen mehr. Der
   Vorspann bekommt ein Zeilenmass, sonst laufen seine Zeilen ueber die
   ganze Breite und lesen sich schlecht; Polster und Muenze laufen mit
   der Bildhoehe, damit der Kopf auch flach ins Bild passt. */
@media (min-width: 641px) and (max-width: 699px) {
  .seite-preise .sec--head {
    padding-top: clamp(32px, 7vh, 72px);
    padding-bottom: clamp(28px, 6vh, 96px);
  }

  .seite-preise .sec--head .kopfvideo {
    margin-top: clamp(16px, 3vh, 28px);
    width: min(100%, 30vh, 360px);
  }

  .seite-preise .sec--head .lead--dicht {
    max-width: 34em;
    font-size: clamp(17px, 2.6vh, 19px);
  }

  .seite-preise .sec--head .jumplinks { margin-top: clamp(22px, 4vh, 44px); }
}

/* ---------- Kartenreihen auf Tablets (Preise) ---------- */
/* Zwischen 726 und 960 Pixeln stehen die drei Preiskarten wieder
   nebeneinander. Der breiteste Betrag ("1'000 – 5'000 CHF") misst 204
   Pixel bei 26px Schrift; drei Spalten zu 210, zwei Zwischenraeume zu
   24 und das Seitenpolster von 48 ergeben 726. Darunter untereinander:
   zwei plus eine Waise saehe schlechter aus als eine Spalte. */
@media (min-width: 726px) and (max-width: 960px) {
  .cards-3:has(.price-card--ikon) { grid-template-columns: repeat(3, 1fr); }
}

/* Domain und Hosting bleiben bis 560 Pixel nebeneinander (je 244
   Pixel; der breiteste Betrag misst 154). */
@media (max-width: 960px) {
  #laufend .cards-2 { grid-template-columns: 1fr 1fr; }
}

@media (max-width: 559px) {
  #laufend .cards-2 { grid-template-columns: 1fr; }
}

/* Die Blase ist hoechstens so breit wie ihre Karte: in zwei Spalten
   zwischen 560 und 960 Pixeln ist die Karte 240 bis 440 breit, die
   feste Blase von 320 ragte gemessen 34 Pixel ueber die linke Karte
   hinaus und 10 in die rechte hinein. Das ersetzt hier auch die
   Fensterformel, die Karte ist einspaltig ohnehin so breit wie das
   Fenster abzueglich Polster. */
#laufend .cards-2 .tip { width: min(320px, 100%); }

/* ---------- Tippflaechen (Preise) ---------- */
/* Drei Bedienelemente waren fuer den Finger zu klein, empfohlen sind
   44 Pixel: "Zurueck" im Rechner 17 hoch, die Textverweise 21, die
   Seiten des Monats-/Jahresschalters 37. Wie beim Info-Punkt weitet
   ein unsichtbares Feld die Trefferflaeche, ohne das Bild zu aendern;
   nur der Schalter waechst sichtbar, weil sein Laeufer die Hoehe der
   Seiten mitnimmt. Nur bei grobem Zeiger, mit der Maus bleibt alles. */
@media (pointer: coarse) {
  .seite-preise .link,
  [data-preisrechner] .btn-back { position: relative; }

  .seite-preise .link::after,
  [data-preisrechner] .btn-back::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    top: -12px;
    bottom: -12px;
  }

  [data-preisrechner] .btn-back::after { top: -14px; bottom: -14px; }

  .switch__seite { padding-block: 15px; }
}

/* ---------- Fehlseite (404.html) ----------
   Die Ziffern stehen gross und blenden nach unten in den Seitenton
   aus: der Verlauf laeuft von der Tinte in die Buehnenfarbe und wird
   auf die Schrift beschnitten. So haengen sie nicht als Block im Bild,
   sondern loesen sich zur Ansage darunter hin auf. */
/* So hoch, dass der Fuss unter dem Fensterrand bleibt: abgezogen wird
   die Kopfzeile (76 Bildpunkte, siehe .site-header__inner). Mit svh und
   nicht vh -- sonst rechnet sie auf dem Handy mit eingefahrenen
   Browserleisten, und der Fuss schaute doch herein. */
.fehlseite {
  min-height: calc(100svh - 76px);
  display: grid;
  align-items: center;
}
.fehlseite__spalte { max-width: 640px; }

.fehlzahl {
  display: block;
  margin: 0 0 -.06em -.055em;
  font-family: Georgia, 'Times New Roman', serif;
  font-size: clamp(104px, 14vw, 176px);
  font-weight: 600;
  line-height: .9;
  letter-spacing: -.045em;
  background-image: linear-gradient(to bottom,
                    var(--ink) 8%,
                    color-mix(in oklab, var(--buehne), var(--ink) 28%) 58%,
                    var(--buehne) 96%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* Der Verlauf endet im Seitenton, unten ist die Ziffer also
     unsichtbar -- fuer die Auswahl bleibt sie es nicht, darum kein
     Text, den jemand markieren wuerde. */
  -webkit-user-select: none;
  user-select: none;
}

/* Ohne Beschnitt auf die Schrift waere die Zahl unsichtbar: dann steht
   sie schlicht in Tinte da. */
@supports not ((background-clip: text) or (-webkit-background-clip: text)) {
  .fehlzahl { background-image: none; color: var(--ink); }
}

/* Und ohne color-mix nur zwei Halte -- der Verlauf ist dann etwas
   steiler, der Eindruck derselbe. */
@supports not (background: color-mix(in oklab, #000, #fff 50%)) {
  .fehlzahl { background-image: linear-gradient(to bottom, var(--ink) 10%, var(--buehne) 94%); }
}

.fehlseite__titel {
  font-size: clamp(32px, 3.9vw, 54px);
  letter-spacing: -.028em;
}
.fehlseite__text { margin-top: 40px; }

/* Umbruch nur am Schreibtisch: dort steht der zweite Satz auf einer
   eigenen Zeile. Auf dem Handy bricht der Absatz ohnehin von selbst,
   ein fester Umbruch riss dort eine halbe Zeile auf. */
.br-breit { display: none; }

@media (min-width: 641px) {
  .br-breit { display: inline; }
}

.fehlseite__wege {
  margin-top: 80px;
  display: flex;
  align-items: center;
  gap: 28px;
  flex-wrap: wrap;
}

@media (max-width: 640px) {
  /* Dort ist die Kopfzeile 64 Bildpunkte hoch. */
  .fehlseite { min-height: calc(100svh - 64px); }
  .fehlzahl { font-size: clamp(92px, 30vw, 148px); }
  /* Die Zeile darf dort etwas mehr Gewicht haben: am Schreibtisch
     steht sie neben viel Weissraum, auf dem Handy traegt sie die
     Seite. */
  .fehlseite__titel { font-size: clamp(34px, 9.4vw, 42px); }
  /* Die doppelten Abstaende sind fuer den Schreibtisch gedacht; auf dem
     Handy bleibt es beim engeren Satz. */
  .fehlseite__text { margin-top: 20px; }
  .fehlseite__wege { margin-top: 40px; gap: 20px; }
}

/* ---------- Abschnitt in der Bildmitte, schmal ----------
   Derselbe Effekt wie auf Preise und Arbeit, hier fuer die uebrigen
   Seiten: der Abschnitt, dessen Flaeche die Bildmitte kreuzt, steht
   voll da und wirft nach oben und unten je einen Schatten von sich
   weg; alle anderen sind abgegraut. So trennt nicht ein Strich die
   Abschnitte, sondern die Aufmerksamkeit.

   Angehaengt wird das ueber die Klasse sek-fokus am main -- die Seiten
   mit eigener Handy-Fassung (css/preise-handy.css, css/arbeit-handy.css)
   bringen die Regeln selbst mit und bleiben hier aussen vor. Ueber :has,
   damit ohne Skript nichts abgegraut stehen bleibt; die Klasse
   ist-mitte setzt js/main.js. */
@media (max-width: 640px) {
  main.sek-fokus > .sec {
    position: relative;
    border-bottom: 0;
    transition: background-color .4s var(--ease);
  }

  /* Abgedunkelt, nicht ausgeblendet: der Schleier liegt sehr
     durchsichtig als Grund im Abschnitt, die Deckkraft nimmt nur der
     Inhalt zurueck. Sie sitzt am Raster und nicht am Abschnitt selbst,
     sonst blasste der seinen eigenen Grund mit weg. */
  main.sek-fokus:has(.ist-mitte) > .sec:not(.ist-mitte) {
    background: rgba(17, 17, 17, .05);
  }

  main.sek-fokus > .sec > .grid { transition: opacity .4s var(--ease); }
  main.sek-fokus:has(.ist-mitte) > .sec:not(.ist-mitte) > .grid { opacity: .62; }

  /* Beide Baender haengen am mittigen Abschnitt selbst, nicht am
     Nachbarn: der ist abgegraut, und seine Deckkraft nimmt alles darin
     mit. Pseudoelemente statt box-shadow, weil ein Schatten mit
     negativem Streuwert die Seitenkanten nicht erreicht. */
  main.sek-fokus > .sec::before,
  main.sek-fokus > .sec::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    height: 22px;
    pointer-events: none;
    opacity: 0;
    transition: opacity .4s var(--ease);
  }

  main.sek-fokus > .sec::before {
    bottom: 100%;
    background: linear-gradient(to top, rgba(17, 17, 17, .07), rgba(17, 17, 17, 0));
  }

  main.sek-fokus > .sec::after {
    top: 100%;
    background: linear-gradient(to bottom, rgba(17, 17, 17, .07), rgba(17, 17, 17, 0));
  }

  main.sek-fokus > .sec.ist-mitte::before,
  main.sek-fokus > .sec.ist-mitte::after { opacity: 1; }

  /* Zwei Kanten bleiben blank: ueber dem Seitenkopf steht die
     Kopfzeile, die durchscheint, und unter dem Schluss der dunkle
     Fuss. */
  main.sek-fokus > .sec--head::before,
  main.sek-fokus > .sec--closing::after,
  main.sek-fokus > .sec--last::after { display: none; }

  /* Der Nachweis haelt sein Band mit overflow: hidden im Rahmen. Schmal
     gibt es das Band nicht, und die Schatten liegen ausserhalb des
     Abschnitts -- sie waeren sonst weggeschnitten. */
  main.sek-fokus > #nachweis { overflow: visible; }
}
