/* Schriften liegen im Projekt und werden vom eigenen Server geliefert.
   Ueber die Google-CDN eingebunden ginge bei jedem Aufruf die IP-Adresse
   des Besuchers an Google - genau dafuer hat das LG Muenchen I
   Schadensersatz zugesprochen (20.01.2022, Az. 3 O 17493/20).
   Beide Schriften stehen unter der SIL Open Font License 1.1,
   Nachweis in fonts/LIZENZ.txt. */
@font-face {
  font-family: "Anton";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/anton-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
    U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "Anton";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/anton-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
    U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
    U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}

@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/jetbrainsmono-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
    U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/jetbrainsmono-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
    U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
    U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}

:root {
  --ease-pane: cubic-bezier(0.22, 1, 0.36, 1);
  --ink: #ffffff;
  --paper: #000000;
  --surface: #141312;
  /* Browserfenster: gedaempftes Weiss statt #fff - eine grosse reinweisse
     Flaeche auf fast schwarzem Grund blendet. */
  --pane: #e7e4de;
  --pane-bar: #d8d4cc;
  --pane-line: #c2bdb4;
  --pane-ink: #2a2724;
  --panel: #141312;
  --panel-hover: #211f1c;
  --frame-inset: 22px;
  --frame-radius: 26px;
}

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

body {
  background: var(--paper);
  color: var(--ink);
  font-family: "Anton", "Arial Narrow", Impact, sans-serif;
  -webkit-font-smoothing: antialiased;
}


/* Lenis: von der Bibliothek benoetigte Basisregeln */
html.lenis,
html.lenis body {
  height: auto;
}

/* Hier empfiehlt die Bibliothek overflow: clip, damit im Halt auch
   Tastatur und Bildlaufleiste nichts bewegen. Das kostet aber die
   Bildlaufleiste ihren Platz: wo sie welchen belegt - Windows, Linux,
   jeder Zeiger ohne eingeblendete Leisten - wird die Seite dadurch
   fuenfzehn Pixel breiter, der ganze Inhalt rutscht zur Seite und
   beim Freigeben zurueck. Gemessen: clientWidth 1425 gegen 1440. Bei
   zwei Halten sind das vier seitliche Spruenge auf dem Weg nach
   unten - sie fielen staerker auf als das Anhalten selbst.

   scrollbar-gutter hilft dagegen nicht: mit clip ist das Element gar
   kein Scrollcontainer mehr, und dann wird auch keine Rinne
   reserviert. Mit hidden ebenso wenig, beides nachgemessen.

   Rad und Beruehrung faengt die Bibliothek im Halt ohnehin selbst mit
   preventDefault ab. Was ohne diese Regel durchkommt, sind Tastatur
   und Bildlaufleiste - und wer die benutzt, soll an einer Stufe erst
   recht nicht festsitzen. Auseinanderlaufen kann dabei nichts: die
   Bibliothek zieht ihren Stand beim naechsten nativen Scrollereignis
   selbst nach. */
.lenis:not(.lenis-autoToggle).lenis-stopped {
  overflow: visible;
}

.lenis [data-lenis-prevent] {
  overscroll-behavior: contain;
}

.lenis.lenis-smooth iframe {
  pointer-events: none;
}

/* ---------------------------------------------------------------
   Ladeschirm

   Nur auf breiten Schirmen, wo der Hintergrund an gut anderthalb
   Megabyte haengt. Bis Bundle und Lichtkarte da und uebersetzt sind,
   stand die Seite schwarz - und der Einflug der Ueberschrift lief in
   dieser Zeit ab, ohne dass ihn jemand sah.

   Standardmaessig AUS. Eingeschaltet wird er von ladeschirm.js ueber die
   Klasse laedt an <html>, abgeraeumt ebenfalls von dort, sobald der
   Hintergrund seine erste Bildfolge gemeldet hat. Laeuft kein Skript,
   gibt es keinen Schirm - besser gar keiner als einer, der nie geht.

   Die Klasse geht haelt ihn waehrend des Ausblendens am Leben,
   nachdem laedt schon weg ist: so faengt der Einflug der Ueberschrift
   an, waehrend der Schirm noch verschwindet, statt danach.
   --------------------------------------------------------------- */
.ladeschirm {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 50;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(20px, 3vh, 32px);
  background: var(--surface);
  opacity: 1;
  transition: opacity 0.55s var(--ease-pane);
}

.laedt .ladeschirm,
.ladeschirm.geht { display: flex; }

.ladeschirm.geht { opacity: 0; }

.ladeschirm__marke {
  font-size: clamp(2.4rem, 5.5vw, 4rem);
  line-height: 1;
  letter-spacing: -0.015em;
  text-transform: uppercase;
  color: var(--ink);
  transform: none;
  transition: transform 0.55s var(--ease-pane);
}

/* Dieselbe Akzentsetzung wie bei der Wortmarke im Fuss. */
.ladeschirm__marke i {
  font-style: normal;
  color: #e4726f;
}

/* Hebt sich beim Gehen leicht an - dieselbe Bewegung, mit der auf der
   Mobilfassung jeder Abschnitt hereinkommt. */
.ladeschirm.geht .ladeschirm__marke { transform: translateY(-12px); }

/* Der Balken kennt keinen Fortschritt und behauptet auch keinen: er
   laeuft durch. Eine Prozentzahl waere hier erfunden - wieviel vom
   Bundle schon da ist, weiss die Seite nicht. */
.ladeschirm__rail {
  display: block;
  width: clamp(140px, 16vw, 220px);
  height: 2px;
  background: rgba(255, 255, 255, 0.14);
  overflow: hidden;
}

.ladeschirm__rail i {
  display: block;
  height: 100%;
  width: 45%;
  background: linear-gradient(90deg, #f0b64a, #e4726f 55%, #8f6fd6);
  animation: ladebalken 1.15s var(--ease-pane) infinite;
}

@keyframes ladebalken {
  from { transform: translateX(-110%); }
  to   { transform: translateX(240%); }
}

/* Der Einflug der Ueberschrift wartet. Angehalten wird die Animation
   samt ihrer Verzoegerung; faellt laedt weg, laeuft sie vollstaendig
   von vorn ab - und zwar dann, wenn hinter ihr etwas zu sehen ist. */
.laedt .line__drop,
.laedt .line--1 .line__swing,
.laedt .line--2 .line__swing {
  animation-play-state: paused;
}

/* Shader-Hintergrund: fixiert hinter allem, faengt keine Klicks ab */
#bg {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

/* Rahmen: fixiert im Viewport, bleibt beim Scrollen stehen */
.frame {
  z-index: 1;
  position: fixed;
  inset: var(--frame-inset);
  border: 1.5px solid var(--ink);
  border-radius: var(--frame-radius);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Zweite Seite: vollflaechig ueber dem Hero, per Kreis freigelegt.
   Startradius 0 -> unsichtbar, bis das Scrollen ihn aufzieht.
   Eigener Hintergrund - er entfaltet sich aus demselben Loch wie die Schrift. */
.reveal {
  position: fixed;
  inset: 0;
  z-index: 2;
  /* Frueher eine deckende Flaeche in --surface. Sie hat den Shader
     vollstaendig verdeckt - ausgerechnet auf der Seite, die sonst
     nichts zu zeigen hat. Jetzt ein Verlauf: in der Mitte praktisch
     deckend, damit die Schrift ihren ruhigen Grund behaelt, zu den
     Raendern hin durchlaessig, sodass das Farbfeld darunter
     durchglimmt. Der Kreis wirkt damit wie ein Loch in den Hero statt
     wie ein Vorhang davor.

     Faellt bg.js aus - Telefon, gesperrtes Skript, langsame Leitung -,
     liegt darunter --paper. Dann bleibt die Flaeche schwarz, nichts
     blitzt auf. */
  background:
    radial-gradient(125% 95% at 50% 46%,
      rgba(20, 19, 18, 0.985) 0%,
      rgba(20, 19, 18, 0.955) 44%,
      rgba(20, 19, 18, 0.78) 100%);
  clip-path: circle(0px at 50% 50%);
  -webkit-clip-path: circle(0px at 50% 50%);
  will-change: clip-path;
}

/* Ueberschrift der zweiten Seite. Startet mittig und wandert beim
   Weiterscrollen nach oben, um darunter Platz freizugeben.
   Die Groesse ist so gewaehlt, dass sie auf breiten Schirmen einzeilig
   ueber die Rahmenbreite laeuft - daran erkennt man sie als Ueberschrift. */
.claim {
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(1.05rem, 2.72vw, 2.6rem);
  line-height: 1.3;
  text-align: center;
  max-width: 96%;
  will-change: transform;
}

/* Fliesstext darunter, erscheint waehrend die Ueberschrift hochwandert.

   Linksbuendig statt zentriert: zwei Zeilen sehr verschiedener Groesse
   brauchen eine gemeinsame Kante, sonst steht die kleine verloren
   ueber der grossen. Der Claim darueber laeuft ohnehin ueber die
   ganze Rahmenbreite und liest sich dadurch als Zeile, nicht als
   konkurrierender Block. */
.body {
  position: absolute;
  top: 38%;
  left: 0;
  right: 0;
  padding: 0 4%;
  text-align: left;
  /* Zwei Spalten: die beiden Zeilen links, das Karussell rechts.
     Als Raster und nicht mit einem Huellelement um die Absaetze -
     app.js greift die Absaetze ueber .body p ab, und je flacher der
     Baum bleibt, desto weniger kann daran zerbrechen. */
  display: grid;
  grid-template-columns: minmax(0, 0.6fr) minmax(0, 1.4fr);
  column-gap: clamp(8px, 1.5vw, 24px);
  align-items: center;
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.8rem, 1.5vw, 1.25rem);
  line-height: 1.75;
  opacity: 0;
  will-change: opacity, transform;
}

.body p {
  margin: 0;
}

/* Drei Saetze, die dramaturgisch verschieden sind, sahen bis hierher
   gleich aus: dieselbe Schrift, dieselbe Groesse, dieselbe Achse.
   Jetzt tragen sie drei Gewichte. */

/* Erster Satz: die Frage. Sie setzt nur an und bleibt klein und
   zurueckgenommen - eine Vorbemerkung, kein Konkurrent. */
.body p:nth-child(1) {
  grid-column: 1;
  grid-row: 1;
  align-self: end;
  /* Beide Zeilen teilen sich eine Breite und ruecken ans Karussell
     heran - so steht der Text nicht am linken Rand, sondern mit dem
     Ring zusammen in der Mitte. Gleiche Breite, damit die linke Kante
     beider Zeilen buendig bleibt. */
  justify-self: end;
  width: min(100%, 24rem);
  font-size: clamp(0.92rem, 1.3vw, 1.25rem);
  line-height: 1.5;
  letter-spacing: 0.01em;
  color: rgba(255, 255, 255, 0.78);
  margin-bottom: clamp(14px, 2.4vh, 28px);
}

/* Zweiter Satz: die Antwort. Sie holt Anton auf diese Seite, die
   sonst nur Mono kennt - das ist der Bruch, der der Flaeche gefehlt
   hat. Bewusst kleiner als der Claim darueber: der bleibt die
   Ueberschrift, das hier ist der Satz, auf den es ankommt.
   max-width in ch, damit die Zeile bricht, bevor sie die Rahmenbreite
   erreicht - eine Displayschrift ueber die volle Breite liest sich
   als Ueberschrift und stellt sich neben den Claim. */
.body p:nth-child(2) {
  grid-column: 1;
  grid-row: 2;
  align-self: start;
  justify-self: end;
  width: min(100%, 24rem);
  font-family: "Anton", "Arial Narrow", Impact, sans-serif;
  font-size: clamp(1.7rem, 3.5vw, 3.4rem);
  line-height: 1.02;
  letter-spacing: 0.005em;
  text-transform: uppercase;
}

/* Dritter Satz: ausgeblendet, aber NICHT geloescht.

   app.js startet die ganze Choreografie nur, wenn es unter .body
   genau drei Absaetze findet (bodyLines.length === 3). Wer diesen
   Absatz aus dem Markup nimmt, legt auf breiten Schirmen die
   komplette Seite still - kein Scrollen, keine Stationen, nichts.
   display:none laesst ihn im Dokument und nimmt ihn trotzdem aus
   Bild und Vorlesesoftware.

   Inhaltlich faellt er weg, weil er die Leistungsliste im
   Preisblock wiederholt. Auf Telefonen war er aus demselben Grund
   schon vorher ausgeblendet - jetzt gilt das ueberall. */
.body p:nth-child(3) {
  display: none;
}


/* --- Karussell der Arbeiten ------------------------------------

   Ein Ring aus Bildschirmfotos. Die Drehung setzt karussell.js, hier
   steht nur, wie die Teile aussehen und wo sie sitzen. Ohne Skript
   stehen alle Blaetter uebereinander in der Mitte - sichtbar, nicht
   kaputt.
   ---------------------------------------------------------------- */

.karussell {
  position: relative;
  grid-column: 2;
  grid-row: 1 / span 2;
  will-change: transform;
}

/* Die Pfeile liegen ueber der Buehne, direkt links und rechts neben
   dem vorderen Blatt. Den Abstand rechnet karussell.js aus der
   tatsaechlichen Breite des vorderen Blatts und setzt ihn als
   --karussell-rand - so bleiben die Pfeile am Blatt, egal wie breit
   der Schirm ist. */
.karussell__reihe {
  position: relative;
  width: 100%;
}

/* Traeger der Perspektive. Flach im Verhaeltnis 2:1, weil der Ring
   gekippt ist und kaum Hoehe braucht - hoeher waere nur Leerraum,
   der die Spalte nach unten aus dem Rahmen schiebt. */
.karussell__buehne {
  position: relative;
  /* Unter den Pfeilen: die Blaetter liegen im 3D-Raum der Buehne,
     die Buehne selbst ist fuer die Reihe aber eine flache Ebene -
     damit gewinnt z-index hier zuverlaessig. */
  z-index: 1;
  width: 100%;
  aspect-ratio: 2.1 / 1;
}

.karussell__ring {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
}

/* Jedes Blatt sitzt in der Mitte und wird von dort auf die Ringbahn
   geschoben. translate statt margin, weil transform von karussell.js
   gesetzt wird und die Zentrierung sonst ueberschreiben wuerde. */
.karussell__blatt {
  position: absolute;
  top: 50%;
  left: 50%;
  width: clamp(150px, 18vw, 330px);
  aspect-ratio: 16 / 10;
  margin: 0;
  transform-style: preserve-3d;
  transform-origin: 50% 50%;
  translate: -50% -50%;
  border-radius: 8px;
  overflow: hidden;
  background: var(--pane);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  /* Hintere Blaetter abdunkeln statt durchsichtig machen: bei
     Transparenz schiene das Blatt dahinter durch, und zwei Websites
     uebereinander lesen sich als Fehler. */
  filter: brightness(0.5) saturate(0.8);
  transition: filter 0.45s ease, box-shadow 0.45s ease;
}

.karussell__blatt.is-vorn {
  filter: none;
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.55);
}

.karussell__blatt img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Pfeile in der Linienoptik des Rahmens statt der Glasknoepfe aus
   der Vorlage - auf dieser Seite gibt es kein Glas. */
.karussell__knopf {
  position: absolute;
  top: 50%;
  translate: 0 -50%;
  z-index: 2;
  width: clamp(38px, 3.2vw, 48px);
  height: clamp(38px, 3.2vw, 48px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  color: var(--ink);
  /* Die Pfeile liegen auf den hinteren Blaettern - deshalb fast
     deckend und weichgezeichnet, sonst liest sich das Blatt darunter
     durch den Pfeil hindurch. */
  background: rgba(20, 19, 18, 0.78);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 50%;
  cursor: pointer;
  transition: border-color 0.2s ease, background-color 0.2s ease, transform 0.15s ease;
}

[data-karussell-zurueck] { right: calc(50% + var(--karussell-rand, 190px)); }
[data-karussell-vor]     { left: calc(50% + var(--karussell-rand, 190px)); }

.karussell__knopf:hover {
  border-color: rgba(255, 255, 255, 0.7);
  background: rgba(255, 255, 255, 0.08);
}

.karussell__knopf:active { transform: scale(0.92); }

.karussell__knopf:focus-visible {
  outline: 1px solid var(--ink);
  outline-offset: 3px;
}

/* Unterschrift zum Blatt vorn: Name gross, Branche und Zaehler in
   Mono daneben. Ein div, kein p - siehe Kommentar im Markup. */
.karussell__unterschrift {
  /* Aus dem Fluss genommen: so misst das Karussell nur den Ring, und
     die Textspalte links zentriert sich auf dessen Mitte statt auf
     Ring plus Unterschrift. */
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  margin-top: clamp(4px, 1vh, 12px);
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px 14px;
  text-align: center;
}

.karussell__titel {
  font-family: "Anton", "Arial Narrow", Impact, sans-serif;
  font-size: clamp(1.05rem, 1.6vw, 1.5rem);
  text-transform: uppercase;
  letter-spacing: 0.01em;
}

.karussell__art,
.karussell__stand {
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.66rem, 0.8vw, 0.78rem);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
}

.karussell__stand {
  font-variant-numeric: tabular-nums;
  color: rgba(255, 255, 255, 0.38);
}

/* Vierte Seite. Die Ebene selbst steht still und hat keinen eigenen
   Hintergrund - sonst wuerde sie die dritte sofort verdecken. Bewegt
   wird nur die Platte im Rahmen. */
.outro {
  position: fixed;
  inset: 0;
  z-index: 3;
  /* Die Ebene ist durchsichtig und liegt ueber der dritten Seite -
     ohne das hier faengt sie deren Klicks ab. Erst die Platte selbst
     nimmt wieder Eingaben an, und die ist bis zum Uebergang
     ausserhalb des Rahmens und damit ohne Trefferflaeche. */
  pointer-events: none;
}

.outro .slab {
  pointer-events: auto;
}

/* Die verschiebbare Platte. Sie traegt den Hintergrund und den Inhalt,
   der Rahmen darum bleibt stehen - dadurch sieht man durchgehend ein
   Fenster statt zweier, die aneinander vorbeifahren. */
.slab {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  will-change: transform;
}

.slab--next {
  background: var(--surface);
  transform: translateX(100%);
}

/* Browserfenster in der Seite. Oeffnet sich per Kreis aus der Mitte,
   liegt innerhalb des Rahmens und laesst die Raender frei. */
.window {
  position: absolute;
  left: 8%;
  right: 8%;
  top: 34%;
  bottom: 10%;
  border: 1.5px solid var(--pane-line);
  border-radius: 14px;
  background: var(--pane-bar);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  clip-path: circle(0px at 50% 50%);
  -webkit-clip-path: circle(0px at 50% 50%);
  will-change: clip-path;
}

.window__bar {
  flex: 0 0 auto;
  height: clamp(30px, 5vh, 46px);
  border-bottom: 1.5px solid var(--pane-line);
  display: flex;
  align-items: center;
  padding: 0 clamp(10px, 1.2vw, 18px);
}

.window__dots {
  display: flex;
  gap: 6px;
}

.window__dots i {
  display: block;
  width: 7px;
  height: 7px;
  border: 1.5px solid rgba(42, 39, 36, 0.45);
  border-radius: 50%;
}

/* Der Tab sitzt auf der Trennlinie und unterbricht sie -
   daran erkennt man ihn als Tab und nicht als Kasten. */
.window__tab {
  margin-left: clamp(12px, 1.6vw, 24px);
  align-self: flex-end;
  width: clamp(90px, 17%, 210px);
  height: 62%;
  border: 1.5px solid var(--pane-line);
  border-bottom: none;
  border-radius: 9px 9px 0 0;
  background: var(--pane);
  position: relative;
  bottom: -1.5px;
}

/* Adresszeile. Waehrend des Tippens leuchtet der Rand auf,
   nach Enter geht er zurueck - daran liest man den Tastendruck. */
.window__address {
  flex: 0 0 auto;
  margin: clamp(8px, 1.1vh, 14px) clamp(10px, 1.2vw, 18px);
  padding: clamp(5px, 0.8vh, 10px) clamp(10px, 1vw, 16px);
  border: 1.5px solid rgba(42, 39, 36, 0.28);
  border-radius: 999px;
  background: var(--pane);
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.6rem, 1vw, 0.85rem);
  line-height: 1.4;
  color: rgba(42, 39, 36, 0.7);
  display: flex;
  align-items: center;
  min-height: 1.4em;
}

.window__address.is-typing {
  border-color: var(--pane-ink);
  color: var(--pane-ink);
}

.window__caret {
  display: inline-block;
  width: 1.5px;
  height: 1.1em;
  margin-left: 1px;
  background: var(--pane-ink);
  opacity: 0;
}

.window__address.is-typing .window__caret {
  animation: caret-blink 1s steps(1, end) infinite;
}

@keyframes caret-blink {
  0%, 50% { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}

/* Tabbeschriftung erscheint erst nach Enter */
.window__tabtext {
  display: block;
  padding: 0 clamp(8px, 0.8vw, 14px);
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.5rem, 0.75vw, 0.7rem);
  line-height: 1;
  color: var(--pane-ink);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.window__tab {
  display: flex;
  align-items: center;
}

.window__page {
  flex: 1 1 auto;
  background: var(--pane);
  position: relative;
}

/* Drei dunkle Flaechen im Fensterinhalt. Die Ueberschrift sagt,
   was dahinter liegt - mehr steht bewusst nicht drauf. */
.panes {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2px;
  opacity: 0;
  pointer-events: none;
}

.panes.is-live { pointer-events: auto; }

.pane {
  position: relative;
  color: var(--ink);
  perspective: 1400px;
  /* Liegt hinter beiden Kartenseiten und wird nur im Moment des
     Umschlagens sichtbar, wenn die Karte hochkant steht. Gemalter
     Verlauf in den Farben des Hero - eine zweite Shader-Szene waere
     fuer diesen Sekundenbruchteil nicht vertretbar. */
  background:
    radial-gradient(125% 95% at 12% 108%,
      #f2b850 0%,
      #e4726f 34%,
      #8f6fd6 63%,
      #241f33 88%,
      #17151c 100%);
}

.pane__inner {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  -webkit-transform-style: preserve-3d;
  transition: transform 0.9s var(--ease-pane);
}

.pane.is-open .pane__inner {
  transform: rotateY(180deg);
}

/* Um einen Hauch nach vorn geschoben. Ohne diesen Abstand liegen
   Vorder- und Rueckseite exakt in derselben Ebene, und manche mobilen
   Browser zeigen waehrend der Drehung kurz die spiegelverkehrte
   Vorderseite - sie koennen nicht entscheiden, welche Flaeche vorne
   liegt. Ein Pixel Abstand genuegt und ist nicht zu sehen. */
.pane__face--front {
  transform: translateZ(1px);
  border: 0;
  margin: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
}

.pane__face {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(14px, 2vw, 30px);
  background: var(--panel);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  /* Zweite Absicherung neben backface-visibility: die abgewandte Seite
     wird in dem Moment schlagartig ein- bzw. ausgeblendet, in dem die
     Karte hochkant steht und ohnehin nicht zu sehen ist. Dauer 0
     Sekunden - es gibt also nie einen Zwischenwert, der einen
     Stapelkontext erzeugen und die 3D-Ebene flachlegen koennte.

     ACHTUNG, der Verzoegerungswert haengt an BEIDEM: an der Dauer der
     Drehung (0.9s in .pane__inner) und an --ease-pane. Hier stand
     einmal 0.45s - die halbe Dauer, in der Annahme, das sei die halbe
     Drehung. Ist es nicht: cubic-bezier(0.22, 1, 0.36, 1) bremst so
     stark ab, dass nach der halben Zeit schon 173 Grad erreicht sind.
     Die Folge war ein Loch von einer Drittelsekunde, in dem die
     Vorderseite bereits weggedreht und die Rueckseite noch
     durchsichtig war - die Karte verschwand mitten in der Bewegung.

     90 Grad sind bei dieser Kurve nach 13,1 Prozent der Zeit erreicht,
     also nach 0.118s. Wer Dauer oder Kurve aendert, muss diesen Wert
     neu bestimmen. */
  transition: background-color 0.45s var(--ease-pane),
              opacity 0s linear 0.118s;
}

.pane__face--front { opacity: 1; }
.pane__face--back { opacity: 0; }

.pane.is-open .pane__face--front { opacity: 0; }
.pane.is-open .pane__face--back { opacity: 1; }


.pane__face--back {
  transform: rotateY(180deg) translateZ(1px);
  background: var(--panel-hover);
  /* Inhalt oben ausgerichtet, aber mittig, solange Platz ist.
     overflow als Sicherheitsnetz fuer sehr flache Fenster. */
  align-items: stretch;
  justify-content: flex-start;
  overflow-y: auto;
  padding: clamp(16px, 2.2vh, 30px) clamp(16px, 1.8vw, 30px);
}

/* Ablauf: grosse Ziffer, kurzer Titel, eine Zeile Erklaerung.
   Getrennt durch Haarlinien statt durch Kaesten - so bleibt Luft drin. */
.flow {
  display: block;
  margin: auto 0;
  width: 100%;
  text-align: left;
}

.flow__item {
  display: block;
  padding: clamp(10px, 1.7vh, 17px) 0;
}

.flow__item + .flow__item {
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.flow__no {
  display: block;
  font-family: "Anton", "Arial Narrow", Impact, sans-serif;
  font-size: clamp(0.62rem, 0.8vw, 0.76rem);
  letter-spacing: 0.18em;
  line-height: 1;
  color: rgba(255, 255, 255, 0.48);
  margin-bottom: clamp(5px, 0.8vh, 9px);
}

.flow__title {
  display: block;
  font-family: "Anton", "Arial Narrow", Impact, sans-serif;
  font-size: clamp(1rem, 1.45vw, 1.4rem);
  line-height: 1.1;
  text-transform: uppercase;
  margin-bottom: clamp(4px, 0.6vh, 7px);
}

.flow__text {
  display: block;
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.72rem, 0.95vw, 0.88rem);
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.5);
}

/* Referenz: wenige, aber belegbare Angaben - kein erfundener Kennwert */
.ref {
  display: block;
  margin: auto 0;
  width: 100%;
  text-align: left;
}

.ref__label,
.ref__who,
.ref__scope,
.ref__link {
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
}

.ref__label {
  display: block;
  font-size: clamp(0.6rem, 0.72vw, 0.7rem);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.48);
  margin-bottom: clamp(10px, 1.6vh, 18px);
}

.ref__name {
  display: block;
  font-family: "Anton", "Arial Narrow", Impact, sans-serif;
  font-size: clamp(1.3rem, 2.1vw, 2rem);
  line-height: 1.02;
  text-transform: uppercase;
  margin-bottom: clamp(10px, 1.5vh, 16px);
}

.ref__who {
  display: block;
  font-size: clamp(0.7rem, 0.9vw, 0.84rem);
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.5);
  padding-bottom: clamp(12px, 1.8vh, 20px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.ref__scope {
  display: block;
  font-size: clamp(0.64rem, 0.8vw, 0.76rem);
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.48);
  padding: clamp(12px, 1.8vh, 20px) 0 clamp(16px, 2.4vh, 26px);
  hyphens: auto;
}

.ref__link {
  display: inline-block;
  font-size: clamp(0.68rem, 0.86vw, 0.8rem);
  line-height: 1.4;
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.3);
  padding-bottom: 3px;
  transition: border-color 0.35s var(--ease-pane);
}

.ref__link:hover { border-bottom-color: var(--ink); }

/* Kontakt: Telefonnummer als groesstes Element, weil ein Anruf
   die kuerzeste Verbindung zum Auftrag ist. */
.contact {
  display: block;
  margin: auto 0;
  width: 100%;
  text-align: left;
}

.contact__label {
  display: block;
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.6rem, 0.72vw, 0.7rem);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.48);
  margin-bottom: clamp(10px, 1.6vh, 18px);
}

.contact__tel {
  display: block;
  font-family: "Anton", "Arial Narrow", Impact, sans-serif;
  font-size: clamp(1.35rem, 2.2vw, 2.1rem);
  line-height: 1.05;
  color: var(--ink);
  text-decoration: none;
  margin-bottom: clamp(16px, 2.4vh, 26px);
}

.contact__wa {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.66rem, 0.82vw, 0.78rem);
  line-height: 1;
  color: var(--ink);
  text-decoration: none;
  padding: 0.85em 1.1em;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 999px;
  transition: border-color 0.35s var(--ease-pane),
              background-color 0.35s var(--ease-pane);
}

.contact__wa:hover {
  border-color: var(--ink);
  background: rgba(255, 255, 255, 0.06);
}

.contact__mail {
  display: block;
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.64rem, 0.8vw, 0.76rem);
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.5);
  text-decoration: none;
  margin-top: clamp(16px, 2.4vh, 26px);
  padding-top: clamp(14px, 2vh, 22px);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  transition: color 0.35s var(--ease-pane);
  word-break: break-word;
}

.contact__mail:hover { color: var(--ink); }

/* Schliessen. Die Trefferflaeche ist bewusst 44px gross - das ist das
   Mass, unter dem ein Ziel auf dem Handy schwer zu treffen ist. Das
   Zeichen selbst bleibt zurueckhaltend, die Flaeche darum nicht. */
.pane__close {
  position: absolute;
  top: clamp(6px, 1vh, 12px);
  right: clamp(6px, 0.8vw, 12px);
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  cursor: pointer;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: clamp(1.3rem, 1.7vw, 1.6rem);
  line-height: 1;
  color: rgba(255, 255, 255, 0.55);
  transition: color 0.3s var(--ease-pane), background-color 0.3s var(--ease-pane);
}

.pane__close:hover,
.pane__close:focus-visible {
  color: var(--ink);
  background: rgba(255, 255, 255, 0.09);
}

.pane:hover .pane__close { color: rgba(255, 255, 255, 0.8); }

.pane__title {
  font-family: "Anton", "Arial Narrow", Impact, sans-serif;
  font-size: clamp(1.5rem, 3.8vw, 3.6rem);
  line-height: 1;
  text-transform: uppercase;
  text-align: center;
  opacity: 0.9;
  transition: opacity 0.45s var(--ease-pane);
}

.pane:hover .pane__face,
.pane:focus-within .pane__face {
  background: var(--panel-hover);
}


.pane:hover .pane__title,
.pane:focus-within .pane__title {
  opacity: 1;
}

/* Umlaufende Leuchtspur: der schwache Strich ist das Kabel,
   das helle Segment der Strom. pathLength normiert den Umfang auf 100,
   dadurch laeuft das Segment mit gleichbleibendem Tempo um die Kanten -
   anders als ein rotierender Farbverlauf, der an kurzen Seiten rast. */
.pane__spark {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.4s var(--ease-pane);
}

.pane__spark rect {
  x: 1px;
  y: 1px;
  width: calc(100% - 2px);
  height: calc(100% - 2px);
  fill: none;
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
}

.pane__track {
  stroke: rgba(255, 255, 255, 0.16);
}

.pane__current {
  stroke: url(#stromverlauf);
  stroke-dasharray: 13 87;
  filter: drop-shadow(0 0 4px rgba(228, 130, 110, 0.75));
}

.pane:hover .pane__spark,
.pane:focus-within .pane__spark {
  opacity: 1;
}

.pane:hover .pane__current,
.pane:focus-within .pane__current {
  animation: current-loop 2.4s linear infinite;
}

@keyframes current-loop {
  from { stroke-dashoffset: 0; }
  to { stroke-dashoffset: -100; }
}

/* nur Traeger fuer den Verlauf, nimmt keinen Platz ein */
.defs {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
  .pane:hover .pane__current,
  .pane:focus-within .pane__current { animation: none; }
  .pane__current { stroke-dasharray: none; }
}

/* Die uebrigen Flaechen treten zurueck, solange eine beruehrt wird */
.panes:has(.pane:hover) .pane:not(:hover) .pane__title {
  opacity: 0.32;
}

.pane__face--front:focus-visible,
.pane__close:focus-visible,
.ref__link:focus-visible,
.contact a:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: -3px;
}

/* Schmale Fenster: untereinander statt nebeneinander, sonst passt
   die Ueberschrift nicht in die Spalte. Und weil eine gedrittelte
   Hoehe fuer den Inhalt der Rueckseite nicht reicht, bekommt die
   geoeffnete Karte den ganzen Platz - die anderen weichen auf
   schmale Streifen zurueck. */
@media (max-width: 700px) {
  .panes {
    display: flex;
    flex-direction: column;
  }

  .pane {
    flex: 1 1 0;
    min-height: 0;
    transition: flex-grow 0.5s var(--ease-pane), flex-basis 0.5s var(--ease-pane);
  }

  .panes.has-open .pane {
    flex: 0 0 clamp(46px, 7vh, 58px);
  }

  .panes.has-open .pane.is-open {
    flex: 1 1 auto;
  }

  .panes.has-open .pane:not(.is-open) .pane__title {
    font-size: 1rem;
  }

  /* etwas kompakter, damit der Inhalt sicher hineinpasst */
  .pane__face--back {
    padding: clamp(14px, 2vh, 22px) clamp(16px, 4.5vw, 24px);
  }

  .flow__item {
    padding: clamp(8px, 1.3vh, 14px) 0;
  }
}

/* Ladebalken unter der Adresszeile, wie im Browser */
.window__progress {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 2;
  height: 2px;
  width: 0;
  background: var(--pane-ink);
  opacity: 0;
}

/* Kleines Wortzeichen oben links. Fuehrt zurueck an den Seitenanfang,
   deshalb eine Schaltflaeche und kein Schriftzug - sie muss mit der
   Tastatur erreichbar sein und sich als bedienbar ankuendigen. */
.mark {
  border: 0;
  padding: 0;
  background: transparent;
  font: inherit;
  cursor: pointer;
  color: inherit;
  position: absolute;
  top: clamp(18px, 3vh, 34px);
  left: clamp(20px, 3vw, 40px);
  font-size: clamp(11px, 1.05vw, 15px);
  letter-spacing: 0.22em;
  line-height: 1;
}

/* Ueberschrift */
.headline {
  font-weight: 400;
  font-size: clamp(3rem, 8.6vw, 10rem);
  line-height: 0.92;
  letter-spacing: -0.01em;
  text-align: center;
  text-transform: uppercase;
  width: 100%;
}

/* Drei Ebenen pro Zeile:
   .line        = Ausflug beim Scrollen (per JS, horizontal)
   .line__drop  = senkrechter Fall der Flugbahn
   .line__swing = Eindrehen aus der Hochkante in die Waagerechte
   Fall und Eindrehen ueberlagern sich -> daraus entsteht die Kurve. */
.line,
.line__drop {
  display: block;
}

/* Nur die scrollgesteuerte Ebene bleibt dauerhaft angekuendigt -
   sie bewegt sich waehrend des gesamten Uebergangs. */
.line {
  will-change: transform;
}

/* inline-block: die Box umschliesst genau das Wort,
   Drehpunkt in der Wortmitte -> beim Drehen bleibt das Wort auf seiner Bahn */
.line__swing {
  display: inline-block;
  transform-origin: 50% 50%;
}

/* Senkrechter Fall entlang der Flugbahn.
   Diese Ebene bewegt sich ausschliesslich vertikal. */
.line__drop {
  transform: translateY(-135vh);
  animation-name: drop-in;
  /* keine dauerhafte will-change-Ankuendigung: der Einflug laeuft
     einmalig beim Laden, danach waere die befoerderte Ebene nur noch
     belegter Speicher - auf schwachen Geraeten der teurere Posten. */
  animation-timing-function: cubic-bezier(0.5, 0, 0.2, 1);
  animation-fill-mode: forwards;
}

@keyframes drop-in {
  to { transform: translateY(0); }
}

/* Das Wort liegt auf dem Pfeil: hochkant (90 Grad) waehrend des Falls,
   in der Kurve dreht es sich auf 0 Grad in die Waagerechte und schiebt
   sich zugleich seitlich in die Endposition. Der Schwung startet vor
   Ende des Falls - die Ueberlagerung ergibt die Kurve. */
@keyframes swing-in-1 {
  to { transform: translateX(0) rotate(0deg); }
}

@keyframes swing-in-2 {
  to { transform: translateX(0) rotate(0deg); }
}

/* WEBDESIGN faellt zuerst - auf der rechten Bahn, hakt nach links ein */
.line--2 .line__drop {
  animation-duration: 0.8s;
  animation-delay: 0.05s;
}

.line--2 .line__swing {
  transform: translateX(16vw) rotate(90deg);
  animation: swing-in-2 0.8s cubic-bezier(0.3, 0.75, 0.3, 1) 0.6s forwards;
}

/* VELD folgt - auf der linken Bahn, hakt nach rechts ein */
.line--1 .line__drop {
  animation-duration: 0.7s;
  animation-delay: 1.05s;
}

.line--1 .line__swing {
  transform: translateX(-28vw) rotate(90deg);
  animation: swing-in-1 0.7s cubic-bezier(0.3, 0.75, 0.3, 1) 1.5s forwards;
}

/* Scrollraum, damit der Ausflug ausgeloest werden kann */
.scroll-space {
  height: 560vh;
}

@media (prefers-reduced-motion: reduce) {
  .line__drop,
  .line--1 .line__swing,
  .line--2 .line__swing {
    animation: none;
    transform: none;
  }

  /* Der Ladeschirm bleibt - er deckt eine echte Wartezeit ab, das ist
     keine Zierde. Nur der durchlaufende Balken haelt an und steht
     dann als ruhiger Strich da. */
  .ladeschirm__rail i {
    animation: none;
    width: 100%;
  }

  .ladeschirm,
  .ladeschirm__marke { transition-duration: 0.01s; }
}


/* ---------------------------------------------------------------
   Vierte Seite: Angebot, Person, Anfrage nebeneinander.
   Die Platte traegt den Inhalt, der Rahmen darum bleibt stehen -
   deshalb liegt die Aufteilung hier und nicht auf .outro.
   --------------------------------------------------------------- */
.final {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: 1fr 1fr 1.35fr;
  padding: clamp(56px, 9vh, 92px) clamp(20px, 3.4vw, 52px)
           clamp(24px, 4vh, 44px);
  gap: 0;
}

/* Haarlinien zwischen den Spalten statt Kaesten. Gleiche Staerke wie
   die Trennlinien im Browserfenster, damit beide Seiten eine Sprache
   sprechen. */
.final__col {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
  padding: 0 clamp(16px, 2vw, 34px);
}

.final__col + .final__col {
  border-left: 1px solid rgba(255, 255, 255, 0.1);
}

.final__col--offer { padding-left: 0; }
.final__col--quiz { padding-right: 0; }

/* Der Inhalt kommt nach, wenn die Platte steht. Gleiche Staffelung
   wie beim Fliesstext auf Seite zwei: nichts fliegt, es zieht nur nach. */
.final__col {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.55s var(--ease-pane), transform 0.55s var(--ease-pane);
}

.outro.is-there .final__col {
  opacity: 1;
  transform: none;
}

.outro.is-there .final__col--about { transition-delay: 0.09s; }
.outro.is-there .final__col--quiz { transition-delay: 0.18s; }

/* Kleine Ueberschrift ueber einem Block. Dieselbe Optik wie
   .ref__label und .contact__label auf den Karten. */
.offer__label,
.about__label,
.quiz__label,
.quiz__legend {
  display: block;
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.58rem, 0.7vw, 0.68rem);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.48);
}

/* --- Links oben: der Preis --- */
.offer {
  flex: 0 0 auto;
}

.offer__label { margin-bottom: clamp(8px, 1.2vh, 14px); }

/* Wo frueher die Summe stand, steht jetzt die Ueberschrift. Sie haelt
   dasselbe Gewicht wie .about__head in der Nachbarspalte, damit die drei
   Spalten unten in einer Zeile beginnen - eine Liste allein unter einem
   Miniaturlabel wuerde daneben abfallen. */
.offer__head {
  font-weight: 400;
  font-size: clamp(1.5rem, 2.7vw, 2.6rem);
  line-height: 1.02;
  text-transform: uppercase;
  margin-bottom: clamp(14px, 2.2vh, 24px);
}

.offer__list {
  list-style: none;
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.68rem, 0.86vw, 0.8rem);
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.62);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.offer__list li {
  padding: clamp(5px, 0.9vh, 9px) 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  hyphens: auto;
}

.offer__note {
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.66rem, 0.82vw, 0.76rem);
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.48);
  margin-top: clamp(10px, 1.5vh, 16px);
}

/* --- Links unten: der Schlusssatz. Sitzt am Fuss der Spalte,
   damit er wie ein Abbinder wirkt und nicht wie ein weiterer Block. --- */
.sendoff {
  margin-top: auto;
  padding-top: clamp(16px, 2.6vh, 28px);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.sendoff__text {
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.68rem, 0.86vw, 0.8rem);
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.62);
  margin-bottom: clamp(10px, 1.6vh, 18px);
}

.sendoff__tel {
  display: block;
  font-size: clamp(1.25rem, 2.1vw, 2rem);
  line-height: 1.05;
  color: var(--ink);
  text-decoration: none;
}

.sendoff__hint {
  display: block;
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.62rem, 0.76vw, 0.72rem);
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.48);
  margin-top: clamp(6px, 1vh, 10px);
  hyphens: auto;
}

/* --- Mitte: wer dahintersteht --- */

.about__label { margin-bottom: clamp(10px, 1.6vh, 18px); }

.about__head {
  font-weight: 400;
  font-size: clamp(1.5rem, 2.7vw, 2.6rem);
  line-height: 1.02;
  text-transform: uppercase;
  margin-bottom: clamp(14px, 2.2vh, 24px);
}

.about__text {
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.68rem, 0.86vw, 0.8rem);
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.55);
}

.about__text + .about__text {
  margin-top: clamp(10px, 1.6vh, 18px);
  padding-top: clamp(10px, 1.6vh, 18px);
  border-top: 1px solid rgba(255, 255, 255, 0.07);
}

/* --- Rechts: die vier Fragen --- */
/* Alle drei Spalten schlagen oben an derselben Linie an. Die
   kleinen Ueberschriften stehen dadurch nebeneinander und lesen
   sich als eine Zeile ueber die ganze Seite. */
.quiz {
  display: flex;
  flex-direction: column;
  flex: 0 0 auto;
  min-height: 0;
}

.quiz__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1em;
  margin-bottom: clamp(4px, 0.6vh, 7px);
}

.quiz__count {
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.58rem, 0.7vw, 0.68rem);
  letter-spacing: 0.14em;
  color: rgba(255, 255, 255, 0.48);
}

.quiz__count b {
  font-weight: 400;
  color: var(--ink);
}

/* Fortschritt. Die Anzeige ist der Grund, warum vier Fragen kurz
   wirken - ohne sie weiss niemand, wie weit es noch geht. */
/* Sitzt dicht unter dem Label und wirkt dadurch wie dessen
   Unterstreichung. Weiter unten geschoben draengt er die Frage
   aus der Linie, auf der die beiden Ueberschriften daneben stehen. */
.quiz__rail {
  height: 2px;
  background: rgba(255, 255, 255, 0.35);
  overflow: hidden;
  margin-bottom: clamp(7px, 1.1vh, 12px);
}

.quiz__bar {
  display: block;
  height: 100%;
  width: 25%;
  background: linear-gradient(90deg, #f0b64a, #e4726f 55%, #8f6fd6);
  transition: width 0.5s var(--ease-pane);
}

/* Feste Mindesthoehe: die vier Schritte sind unterschiedlich lang,
   ohne sie wandert der ganze Block bei jeder Antwort nach oben. */
.quiz__steps {
  position: relative;
  flex: 0 0 auto;
  min-height: clamp(250px, 39vh, 345px);
}

.quiz__step {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: clamp(9px, 1.5vh, 16px);
  margin: 0;
  border: 0;
  padding: 0;
}

.quiz__step[hidden] { display: none; }

/* Der Wechsel zwischen zwei Fragen: die neue zieht von rechts nach,
   in derselben Richtung, in der die ganze Seite hereingekommen ist. */
.quiz__step.is-entering {
  animation: quiz-step-in 0.42s var(--ease-pane) both;
}

@keyframes quiz-step-in {
  from { opacity: 0; transform: translateX(16px); }
  to   { opacity: 1; transform: none; }
}

.quiz__q {
  font-weight: 400;
  font-size: clamp(1.3rem, 2.3vw, 2.2rem);
  line-height: 1.08;
  text-transform: uppercase;
  margin-bottom: clamp(6px, 1vh, 12px);
}

/* Wo mehrere Antworten moeglich sind, muss das dastehen. Sonst
   klickt man eine an und wartet darauf, dass es weitergeht. */
.quiz__hint {
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.64rem, 0.8vw, 0.74rem);
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.48);
}

/* Der Abstand unter der Frage steckt schon im Zeilenabstand des
   Schrittes - sonst faellt der Hinweis von der Frage ab. */
.quiz__step:has(.quiz__hint) .quiz__q {
  margin-bottom: 0;
}

/* Eine Antwort ist ein Klick und schaltet selbst weiter. Ein
   Weiter-Knopf daneben waere ein zweiter Klick fuer dieselbe Aussage -
   ausser bei der Mehrfachauswahl, die ohne ihn nicht ginge. */
.quiz__opt {
  display: block;
  width: 100%;
  text-align: left;
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.8rem, 1.05vw, 0.98rem);
  line-height: 1.35;
  color: rgba(255, 255, 255, 0.78);
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 12px;
  padding: clamp(13px, 2vh, 20px) clamp(15px, 1.5vw, 23px);
  cursor: pointer;
  transition: border-color 0.3s var(--ease-pane),
              background-color 0.3s var(--ease-pane),
              color 0.3s var(--ease-pane);
}

.quiz__opt:hover,
.quiz__opt:focus-visible {
  border-color: rgba(255, 255, 255, 0.55);
  background: rgba(255, 255, 255, 0.06);
  color: var(--ink);
}

.quiz__opt.is-picked {
  border-color: var(--ink);
  background: rgba(255, 255, 255, 0.1);
  color: var(--ink);
}

/* --- Letzter Schritt: die beiden Felder --- */
.quiz__field { display: block; }

.quiz__legend { margin-bottom: clamp(4px, 0.7vh, 7px); }

.quiz__input {
  display: block;
  width: 100%;
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.85rem, 1.1vw, 1rem);
  line-height: 1.3;
  color: var(--ink);
  background: transparent;
  border: 0;
  border-bottom: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 0;
  padding: clamp(8px, 1.3vh, 13px) 0;
  transition: border-color 0.3s var(--ease-pane);
}

.quiz__input:focus {
  outline: none;
  border-bottom-color: var(--ink);
}

.quiz__error {
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.72rem, 0.9vw, 0.84rem);
  line-height: 1.45;
  color: #e4726f;
}

.quiz__error[hidden] { display: none; }

.quiz__send,
.quiz__next {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.78rem, 1vw, 0.92rem);
  line-height: 1;
  color: var(--paper);
  background: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 999px;
  padding: 1.15em 1.5em;
  cursor: pointer;
  transition: opacity 0.3s var(--ease-pane);
}

.quiz__send:hover,
.quiz__next:hover { opacity: 0.85; }

/* Waehrend der Versand laeuft: nicht noch einmal ausloesbar, und
   sichtbar beschaeftigt - sonst drueckt man ein zweites Mal. */
.quiz__send:disabled,
.quiz__next:disabled {
  cursor: default;
  opacity: 0.35;
}

/* Nicht ueber die volle Breite: ein weisser Balken unter den drei
   Antwortflaechen laese sich als vierte Antwort. */
.quiz__next {
  align-self: flex-start;
  margin-top: clamp(2px, 0.6vh, 6px);
}

/* Der Punkt, an dem am ehesten abgebrochen wird: hier gibt jemand
   seine Nummer heraus. Drei Fragen lang war es ein Klick ohne Folgen,
   jetzt kostet es etwas - und wer zoegert, zoegert genau hier.

   Die Zeile steht deshalb UNTER dem Knopf und nicht ueber den
   Feldern: sie ist das Letzte, was vor dem Absenden gelesen wird.
   Der Wortlaut ist der des Schlusssatzes weiter unten auf der Seite,
   nur mit "Unverbindlich" anstelle der zwanzig Minuten - an dieser
   Stelle soll die Seite nicht ploetzlich anders klingen. */
.quiz__ruhig {
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.62rem, 0.76vw, 0.72rem);
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.48);
  hyphens: auto;
}

/* --- Abschluss --- */
.quiz__lead {
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.8rem, 1.02vw, 0.95rem);
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.72);
}

.quiz__summary {
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.74rem, 0.92vw, 0.86rem);
  line-height: 1.6;
  color: rgba(255, 255, 255, 0.55);
  white-space: pre-line;
  padding-bottom: clamp(6px, 1vh, 10px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.quiz__back {
  align-self: flex-start;
  margin-top: clamp(10px, 1.6vh, 18px);
  padding: 6px 0;
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.62rem, 0.76vw, 0.72rem);
  line-height: 1;
  color: rgba(255, 255, 255, 0.48);
  background: transparent;
  border: 0;
  cursor: pointer;
  transition: color 0.3s var(--ease-pane);
}

.quiz__back:hover { color: var(--ink); }
.quiz__back[hidden] { display: none; }

/* Wortmarke als Logo am Spaltenfuss. Sie sitzt auf derselben Hoehe
   wie die Telefonnummer in der linken Spalte - die beiden Enden der
   Seite tragen dadurch je ein Zeichen statt ins Leere zu laufen.
   Der Punkt in der Akzentfarbe der Leuchtspur. */
.sign {
  border: 0;
  padding: 0;
  background: transparent;
  font: inherit;
  text-align: left;
  cursor: pointer;
  color: var(--ink);
  margin-top: auto;
  padding-top: clamp(24px, 4vh, 44px);
  font-size: clamp(2.4rem, 4.6vw, 4.4rem);
  line-height: 0.9;
  letter-spacing: -0.015em;
  text-transform: uppercase;
}

.sign i {
  font-style: normal;
  color: #e4726f;
}

.sendoff__tel:focus-visible,
.quiz__opt:focus-visible,
.quiz__send:focus-visible,
.quiz__next:focus-visible,
.quiz__back:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

/* Schmalere Fenster: drei Spalten nebeneinander werden zu Saeulen,
   in denen kein Satz mehr umbrechen kann. Ab hier untereinander,
   und die Platte scrollt in sich - data-lenis-prevent im Markup
   haelt das vom Seitenscroll getrennt. */
@media (max-width: 1000px) {
  /* Eine Spalte statt drei. Die Flaeche scrollt NICHT mehr in sich
     selbst - verschachteltes Scrollen fuehlt sich unter dem Finger
     billig an: man zieht, die innere Box bewegt sich, am Ende geht
     nichts weiter. Stattdessen wandert die Spalte mit dem normalen
     Seitenscroll nach oben, gesteuert in app.js. */
  .final {
    grid-template-columns: 1fr;
    grid-auto-rows: min-content;
    gap: clamp(22px, 4vh, 38px);
    height: auto;
    bottom: auto;
    overflow: visible;
    will-change: transform;
  }

  /* Schleier unter der Wortmarke. Eine Maske an .final wuerde
     mitwandern; dieser Streifen gehoert zur stehenden Platte und
     schluckt den Inhalt, der darunter durchzieht. */
  .slab--next::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: clamp(58px, 9.5vh, 96px);
    background: linear-gradient(to bottom,
      var(--surface) 0,
      var(--surface) 55%,
      rgba(20, 19, 18, 0) 100%);
    z-index: 1;
    pointer-events: none;
  }

  .slab--next .mark { z-index: 2; }

  .final__col {
    padding: 0;
  }

  .final__col + .final__col {
    border-left: 0;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
    padding-top: clamp(22px, 4vh, 38px);
  }

  .sendoff { margin-top: clamp(18px, 3vh, 30px); }

  .sign {
    margin-top: clamp(26px, 4.5vh, 44px);
    padding-top: 0;
  }


  .quiz__steps { min-height: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .final__col {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .quiz__step.is-entering { animation: none; }
  .quiz__bar { transition: none; }
}


/* Koederfeld gegen Bots. Nicht display:none - manche Bots ueberspringen
   genau das. Stattdessen aus dem Bild geschoben und fuer Tastatur und
   Screenreader unerreichbar, damit es kein Mensch versehentlich trifft. */
.quiz__trapwrap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Rechtslinks unter der Wortmarke. Bewusst zurueckhaltend, aber nicht
   versteckt - das Impressum muss auffindbar sein. */
.legal {
  display: flex;
  flex-wrap: wrap;
  gap: 0 clamp(12px, 1.4vw, 20px);
  margin-top: clamp(10px, 1.6vh, 18px);
}

.legal a {
  font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
  font-size: clamp(0.62rem, 0.76vw, 0.72rem);
  line-height: 1.6;
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.48);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 0.3s var(--ease-pane), border-color 0.3s var(--ease-pane);
}

.legal a:hover {
  color: var(--ink);
  border-bottom-color: rgba(255, 255, 255, 0.4);
}

.legal a:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}


/* Beide Wortmarken fuehren zurueck an den Seitenanfang. Beim
   Ueberfahren tritt der Punkt hervor, damit erkennbar wird, dass hier
   etwas passiert - mehr Hinweis braucht es an dieser Stelle nicht. */
.mark:hover,
.sign:hover { opacity: 0.75; }

/* Beim Antippen und Anklicken kein Rahmen. Ohne diese Zeile zeichnet
   der Browser seinen eigenen, meist farbigen Ring um die Schaltflaeche. */
.mark:focus,
.sign:focus { outline: none; }

.mark,
.sign { -webkit-tap-highlight-color: transparent; }

/* Nur wer mit der Tastatur navigiert, braucht die Markierung. */
.mark:focus-visible,
.sign:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 4px;
  border-radius: 3px;
}


/* ================================================================
   MOBILFASSUNG

   Auf Telefonen laeuft keine Choreografie. Statt drei uebereinander
   festgenagelter Ebenen, die der Scrollstand ineinander ueberblendet,
   steht hier eine gewoehnliche Seite, die man von oben nach unten
   durchscrollt - mit Kopfzeile, Sprungmenue und der Anfrage ganz oben.

   Es sind aber DIESELBEN Bausteine. Kein zweiter Satz Markup, kein
   zweiter Text, der beim naechsten Preiswechsel vergessen wird. Die
   Traeger der Choreografie - Rahmen, Ebenen, Platten, das gemalte
   Browserfenster - werden per display:contents aus dem Layout
   genommen. Ihre Kinder ruecken damit direkt in <main> auf, und dort
   bringt order sie in die Reihenfolge, die auf einem Handschirm Sinn
   ergibt. Voraussetzung ist, dass app.js in dieser Betriebsart keine
   Stilwerte schreibt; die Abfrage unten steht dort wortgleich.

   Farbe und Schrift bleiben unangetastet: derselbe fast schwarze
   Grund, Anton fuer die Ueberschriften, JetBrains Mono fuer den Text,
   und der Verlauf aus Gold, Rose und Violett - der auf dem Desktop
   aus dem Shader kommt - hier als gemalte Linie. Man soll die Seite
   auf dem Telefon als dieselbe erkennen.
   ================================================================ */

/* Kopfzeile und Menue existieren nur in dieser Fassung. */
.mtop,
.mnav { display: none; }

@media (max-width: 760px), (pointer: coarse) and (max-height: 560px) {

  /* --- Grundgeruest ------------------------------------------- */

  body {
    background: var(--surface);
    /* Der Einflug der Ueberschrift schiebt die Woerter waehrend der
       Animation seitlich aus dem Bild. Auf der Choreografieseite
       faengt das der Rahmen ab, hier braucht es den Beschnitt.
       clip statt hidden: hidden macht die Flaeche scrollbar, und
       damit wuerde position:fixed in der Kopfzeile unnoetig teuer. */
    overflow-x: clip;
  }

  /* Der Shader wird auf Telefonen gar nicht geladen - der leere
     Traeger soll trotzdem keine Flaeche belegen. */
  #bg,
  .scroll-space { display: none; }

  /* Die Traeger der Choreografie verschwinden aus dem Layout, ihre
     Kinder ruecken in <main> auf. Alles, was sie an Position,
     Beschnitt und Hintergrund mitbrachten, faellt damit weg. */
  .reveal,
  .outro,
  .frame,
  .slab,
  .final,
  .final__col,
  .window,
  .window__page,
  .panes,
  .pane,
  .pane__inner { display: contents; }

  /* Sicherheitsnetz. Die Traeger tragen aus der Choreografie Werte
     mit, die sie unsichtbar machen: .reveal ist auf Radius 0
     beschnitten, .slab--next steht um eine ganze Breite verschoben,
     und .final__col wartet auf die Klasse is-there, die hier nie
     kommt. Solange display:contents gilt, hat nichts davon eine
     Wirkung - ein Element ohne Box kennt weder Deckkraft noch
     Beschnitt. Wer die Zeile darueber aber einmal anfasst, haette
     sonst eine leere Seite und keinen Hinweis, woran es liegt. */
  .reveal {
    clip-path: none;
    -webkit-clip-path: none;
  }

  .slab,
  .slab--next,
  .final__col {
    transform: none;
    opacity: 1;
  }

  /* Und der Teil des Netzes, der beim ersten Mal fehlte.

     display:contents nimmt dem Element die Box - damit verlieren
     opacity, clip-path und Hintergrund ihre Wirkung von selbst.
     pointer-events wird aber VERERBT und fliesst durch ein
     boxenloses Element hindurch, als waere nichts gewesen.

     .panes traegt aus der Choreografie pointer-events:none und wird
     erst bedienbar, wenn die nachgestellte Ladesequenz is-live
     setzt. Diese Sequenz laeuft hier nie. Die Folge: Ablauf,
     Referenz und Kontakt liessen sich nicht antippen, obwohl der
     Winkel daneben genau das versprach. */
  .panes { pointer-events: auto; }

  /* Was nur zur Inszenierung gehoert. Das gemalte Browserfenster
     erzaehlt auf dem Desktop, dass hier eine Website entsteht - auf
     einem Telefon, das selbst schon ein Browserfenster ist, waere es
     nur eine Attrappe um den Inhalt herum. */
  .mark,
  .window__bar,
  .window__address,
  .window__progress,
  .pane__spark,
  .pane__close { display: none; }

  main {
    display: flex;
    flex-direction: column;
    padding: 0 22px 56px;
    /* Platz fuer die haftende Kopfzeile */
    margin-top: 60px;
  }

  /* --- Reihenfolge ---------------------------------------------
     Die Anfrage steht oben: wer auf dem Telefon landet, soll nicht
     erst fuenf Bildschirme weit scrollen, um etwas sagen zu koennen.

     Was direkt darunter folgt, ist bewusst NICHT der Preis. Eine
     Zahl unmittelbar hinter der Frage liest sich wie ein Kassenzettel
     hinter dem Handschlag - wer gerade ueberlegt, ob er anfragt,
     bekommt zuerst einen Grund und dann den Betrag. Deshalb kommt
     nach der Umfrage der Haken, dann was passiert, wer es macht und
     fuer wen er es schon gemacht hat. Erst danach die Leistung.

     Ein Betrag steht nirgends mehr auf der Seite - er faellt im
     Gespraech. Was hier unten steht, ist die Liste dessen, was
     enthalten ist, und sie kommt bewusst nicht als erstes. */

     Die drei zuklappbaren Abschnitte stehen am Stueck, nicht
     verteilt: als Gruppe lesen sie sich als Einzelheiten zum
     Nachschlagen, einzeln zwischen den offenen Bloecken wirkten sie
     wie Loecher im Text. Sie sitzen am Ende, direkt ueber dem Fuss -
     dort sucht man Kontakt, und der Preis bleibt weit oben statt
     hinter drei Klappzeilen zu verschwinden. */

  .headline                              { order: 1; }
  .claim                                 { order: 2; }
  .quiz                                  { order: 3; }
  .body                                  { order: 4; }
  .about                                 { order: 5; }
  .offer                                 { order: 6; }
  .pane:nth-child(1) .pane__face--front  { order: 7; }
  .pane:nth-child(1) .pane__face--back   { order: 8; }
  .pane:nth-child(2) .pane__face--front  { order: 9; }
  .pane:nth-child(2) .pane__face--back   { order: 10; }
  .pane:nth-child(3) .pane__face--front  { order: 11; }
  .pane:nth-child(3) .pane__face--back   { order: 12; }
  .sign                                  { order: 14; }
  .legal                                 { order: 15; }

  /* Sprungziele duerfen nicht unter der Kopfzeile landen. */
  .quiz,
  .offer,
  .about,
  .pane__face--front { scroll-margin-top: 74px; }

  /* --- Kopfzeile ------------------------------------------------ */

  .mtop {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    z-index: 20;
    height: 60px;
    padding: 0 22px;
    background: var(--surface);
    /* Der Verlauf des Hero als Haarlinie. Er ist in dieser Fassung
       das einzige Farbige und traegt die Wiedererkennung. */
    border-bottom: 2px solid transparent;
    border-image: linear-gradient(90deg, #f0b64a, #e4726f 55%, #8f6fd6) 1;
  }

  .mtop__mark {
    border: 0;
    padding: 0;
    background: transparent;
    font: inherit;
    color: var(--ink);
    cursor: pointer;
    font-size: 1.6rem;
    line-height: 1;
    letter-spacing: -0.015em;
    text-transform: uppercase;
  }

  .mtop__mark i {
    font-style: normal;
    color: #e4726f;
  }

  .mtop__menu {
    display: flex;
    align-items: center;
    gap: 9px;
    border: 1px solid rgba(255, 255, 255, 0.35);
    border-radius: 999px;
    background: transparent;
    color: rgba(255, 255, 255, 0.8);
    font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
    font-size: 0.78rem;
    letter-spacing: 0.06em;
    /* 44px hoch: die kleinste Flaeche, die sich auf einem Touchschirm
       zuverlaessig treffen laesst. */
    height: 44px;
    padding: 0 16px;
    cursor: pointer;
  }

  .mtop__bars {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 4px;
    width: 15px;
  }

  .mtop__bars i {
    display: block;
    height: 1.5px;
    background: currentColor;
    transition: transform 0.3s var(--ease-pane);
  }

  .mtop__menu[aria-expanded="true"] {
    border-color: var(--ink);
    color: var(--ink);
  }

  .mtop__menu[aria-expanded="true"] .mtop__bars i:first-child {
    transform: translateY(2.75px) rotate(45deg);
  }

  .mtop__menu[aria-expanded="true"] .mtop__bars i:last-child {
    transform: translateY(-2.75px) rotate(-45deg);
  }

  /* --- Menue ----------------------------------------------------
     Klappt die Kopfzeile nach unten auf, statt die halbe Seite zu
     ueberdecken. Wer es oeffnet, hat den Text darunter noch im Blick
     und weiss, wo er gerade steht. */

  /* --- Menue: ein eigener Bildschirm ----------------------------

     Kein Streifchen, das unter der Kopfzeile aufklappt, sondern eine
     Flaeche, die den Schirm uebernimmt. Und sie kommt so herein, wie
     auf dem Desktop die zweite Seite und das Browserfenster
     hereinkommen: als Kreis, der sich aufzieht. Das ist die
     Signaturbewegung dieser Seite - auf dem Telefon ist das Menue die
     einzige Stelle, an der sie noch Platz hat.

     Der Kreis waechst aus dem Menueknopf heraus. Deshalb liegt das
     Overlay UNTER der Kopfzeile (z-index 15 gegen 20): der Knopf
     bleibt oben stehen, wird zum Kreuz und ist zugleich der Punkt,
     aus dem alles kommt und in den alles zurueckfaellt. Beide
     Flaechen tragen denselben Grund - man sieht keine Kante, nur wie
     sich die Farbe ueber die Seite zieht.

     Die Eintraege stehen in Anton und gross, wie die Titel der drei
     Karten. Eine Liste kleiner Links waere hier eine Bedienleiste;
     das hier ist eine Seite. */

  .mnav {
    display: flex;
    flex-direction: column;
    /* Die Eintraege stehen in der Mitte der Flaeche, nicht oben
       angeschlagen: darunter blieben sonst dreihundert Pixel Loch,
       und ein Loch dieser Groesse sieht nach Versehen aus. */
    justify-content: center;
    position: fixed;
    inset: 0;
    z-index: 15;
    padding: 92px 22px 40px;
    background: var(--surface);
    counter-reset: mnav;
    /* Mittelpunkt ist die Mitte des Menueknopfes: 22px Aussenabstand
       plus dessen halbe Breite, 30px unter der Oberkante. */
    /* Beide Enden in derselben Einheit: sonst haengt die Bewegung an
       einer Umrechnung zwischen Pixeln und Prozent, die nicht jeder
       Browser gleich sauber interpoliert. */
    clip-path: circle(0% at calc(100% - 77px) 30px);
    -webkit-clip-path: circle(0% at calc(100% - 77px) 30px);
    transition: clip-path 0.58s var(--ease-pane);
  }

  .mnav.is-offen {
    clip-path: circle(150% at calc(100% - 77px) 30px);
    -webkit-clip-path: circle(150% at calc(100% - 77px) 30px);
  }

  /* Ohne Skript bleibt hidden stehen und es gibt kein Menue. Eine
     Flaeche, die den ganzen Schirm fuellt und sich nicht schliessen
     laesst, waere schlimmer als gar keine: der Inhalt der Seite steht
     ohnehin vollstaendig darunter, das Menue ist nur die Abkuerzung.
     app.js nimmt hidden beim Start weg und fuehrt von da an inert. */
  .mnav[hidden] { display: none; }

  /* Solange das Menue offen ist, bewegt sich dahinter nichts. */
  .menu-offen { overflow: hidden; }

  .mnav a {
    display: flex;
    align-items: baseline;
    gap: 12px;
    font-family: "Anton", "Arial Narrow", Impact, sans-serif;
    font-size: clamp(1.9rem, 8.6vw, 2.5rem);
    line-height: 1.06;
    text-transform: uppercase;
    color: var(--ink);
    text-decoration: none;
    padding: 12px 0;
    /* Zieht mit dem Kreis nach, gestaffelt - siehe unten. */
    opacity: 0;
    transform: translateY(14px);
  }

  /* Die Ziffern nehmen die Zaehlung des Ablaufs auf (01 bis 04) und
     geben der Liste den Takt. Feste Spaltenbreite, damit die Woerter
     auf einer Kante stehen. */
  .mnav a::before {
    counter-increment: mnav;
    content: counter(mnav, decimal-leading-zero);
    flex: 0 0 30px;
    font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
    font-size: 0.62rem;
    letter-spacing: 0.16em;
    color: rgba(255, 255, 255, 0.38);
  }

  /* Die Nummer ist kein Sprungziel, sondern der Ausweg fuer alle, die
     nicht suchen wollen. Sie sitzt am Fuss, hinter einer Linie mit
     demselben farbigen Anfang wie jeder Abschnitt der Seite - und
     bekommt keine Ziffer. Zwei Klassen, sonst kaemen die Regeln gegen
     .mnav a und .mnav a::before nicht an. */
  .mnav a.mnav__tel {
    /* Aus dem Fluss genommen und an den Fuss gesetzt, damit die
       Eintraege darueber wirklich mittig stehen koennen - mit
       margin-top:auto schluckte sie den freien Platz und die
       Zentrierung waere wirkungslos. */
    position: absolute;
    left: 22px;
    right: 22px;
    bottom: 40px;
    padding-top: 26px;
    border-top: 1px solid rgba(255, 255, 255, 0.14);
    background-image: linear-gradient(90deg, #f0b64a, #e4726f 55%, #8f6fd6);
    background-repeat: no-repeat;
    background-origin: border-box;
    background-size: 100% 2px;
    background-position: 0 0;
    font-size: clamp(2rem, 9.5vw, 2.8rem);
    letter-spacing: 0;
    text-transform: none;
  }

  .mnav a.mnav__tel::before { content: none; }

  /* Telefon im Querformat. Dort ist der Schirm so flach, dass sieben
     Zeilen in dieser Groesse nicht zwischen Kopfzeile und Fuss passen -
     die Nummer stuende sonst ueber dem letzten Eintrag. Also wieder
     oben angeschlagen, die Nummer zurueck in den Fluss, und die
     Flaeche darf notfalls in sich scrollen. */
  @media (max-height: 620px) {
    .mnav {
      justify-content: flex-start;
      overflow-y: auto;
      padding-top: 76px;
    }

    .mnav a {
      font-size: 1.5rem;
      padding: 7px 0;
    }

    .mnav a.mnav__tel {
      position: static;
      margin-top: 20px;
      font-size: 1.7rem;
    }
  }

  /* --- Einstieg -------------------------------------------------
     Kurz gehalten. Zwei Zeilen Wortmarke, ein Satz, was es ist -
     dann kommt schon die erste Frage. */

  /* Der Einflug der Ueberschrift gehoert zur Choreografie: die Woerter
     fallen hochkant von oben herein und drehen sich in der Kurve in
     die Waagerechte. Das braucht die Buehne eines breiten Schirms und
     einen Rahmen, der den Ueberstand abfaengt. Auf einem Handschirm
     ist es nur noch Zappeln vor dem eigentlichen Inhalt - hier kommt
     die Ueberschrift mit dem uebrigen Einstieg ruhig herauf. */
  .line__drop,
  .line--1 .line__swing,
  .line--2 .line__swing {
    animation: none;
    transform: none;
  }

  /* .line kuendigt fuer die Choreografie dauerhaft eine
     Transformation an. Hier bewegt sich die Zeile nie, die
     Ankuendigung waere also ohnehin nur belegter Speicher - und sie
     kostet die Ueberschrift ihre Farbe: will-change hebt die Zeile
     auf eine eigene Compositing-Ebene, und ein Verlauf, der auf Text
     beschnitten wird, findet Schrift in einer fremden Ebene nicht
     mehr. Ohne diese Zeile bleibt die Ueberschrift unsichtbar. */
  .line { will-change: auto; }

  .headline {
    font-size: clamp(2.6rem, 15vw, 3.6rem);
    line-height: 0.9;
    text-align: left;
    margin-top: 18px;
  }

  /* Auf breiten Schirmen steht die Wortmarke weiss auf dem Shader -
     die Farbe kommt dort von hinten. Hier gibt es keinen Shader, also
     traegt die Ueberschrift den Verlauf selbst: dieselben drei Toene
     wie im Fortschrittsbalken der Umfrage, an jedem Abschnittsanfang
     und im SVG-Verlauf der Leuchtspur. Diagonal wie dieser, damit
     VELD im Gold anfaengt und WEBDESIGN im Violett endet.

     Der Verlauf liegt als Hintergrund der Ueberschrift und wird auf
     die Buchstaben beschnitten; die Fuellfarbe der Schrift wird dafuer
     durchsichtig gestellt. Genau deshalb steht das Ganze in einem
     @supports: wo der Beschnitt fehlt, bliebe sonst durchsichtige
     Schrift auf dunklem Grund stehen - also gar keine Ueberschrift. */
  @supports ((background-clip: text) or (-webkit-background-clip: text)) {
    .headline {
      background-image: linear-gradient(135deg,
        #f0b64a 0%,
        #e4726f 52%,
        #8f6fd6 100%);
      -webkit-background-clip: text;
      background-clip: text;
      color: transparent;
      -webkit-text-fill-color: transparent;
    }
  }

  .claim {
    font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
    font-size: 0.95rem;
    line-height: 1.55;
    text-align: left;
    color: rgba(255, 255, 255, 0.72);
    margin-top: 16px;
    padding-bottom: 22px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  }

  /* --- Abschnitte ----------------------------------------------
     Jeder Block traegt oben eine Haarlinie und darunter Luft. Das
     ersetzt die Kaesten, die eine solche Seite sonst braucht, und
     bleibt bei der Sprache der Choreografieseite. */

  /* Jeder Abschnitt beginnt mit einer Linie in den Farben des Hero -
     derselbe Verlauf wie im Fortschrittsbalken der Umfrage und in der
     Leuchtspur. Auf dem Desktop traegt der Shader die Farbe; hier, wo
     es ihn nicht gibt, kehrt sie an jedem Abschnittsanfang wieder und
     haelt die Seite als dieselbe erkennbar.

     Ueber die volle Breite und nicht nur als kurzer Anstrich: das
     trennt sichtbar, und es ist genau die Linie, die unter der
     Kopfzeile schon steht - dieselbe Staerke, dieselben Farbpunkte.
     Zwei Linienarten auf einer Seite: der Verlauf beginnt einen
     Abschnitt, die weisse Haarlinie trennt Zeilen innerhalb eines
     Abschnitts.

     background-origin auf border-box legt den Strich genau auf die
     Linie statt darunter. Die Haarlinie darunter bleibt stehen: sie
     haelt den einen Pixel im Layout und traegt die Trennung weiter,
     falls der Verlauf einmal nicht geladen wird. */
  .offer,
  .about,
  .sendoff,
  .pane__face--front {
    margin-top: 34px;
    padding-top: 30px;
    border-top: 1px solid rgba(255, 255, 255, 0.12);
    background-image: linear-gradient(90deg, #f0b64a, #e4726f 55%, #8f6fd6);
    background-repeat: no-repeat;
    background-origin: border-box;
    background-size: 100% 2px;
    background-position: 0 0;
  }

  /* --- Was auf dem Telefon wegbleibt ----------------------------

     Auf breiten Schirmen liegen diese Saetze weit auseinander - auf
     verschiedenen Seiten der Choreografie, in verschiedenen Spalten.
     Dort wirkt Wiederholung als Bekraeftigung. Untereinander
     gestapelt kommt dieselbe Aussage dreimal in Folge, und dann
     wirkt sie wie ein Versehen.

     Nur ausgeblendet, nicht geloescht: der Desktoptext bleibt
     unangetastet, und wer die Entscheidung zurueckdrehen will,
     loescht drei Regeln. */

  /* Der dritte Satz ist inzwischen ueberall ausgeblendet, die Regel
     dazu steht oben bei .body p:nth-child(3) - samt der Warnung,
     warum der Absatz im Markup bleiben MUSS. Hier braucht es sie
     nicht mehr.

     Was hier dagegen stehen muss: die Gewichtung der ersten beiden
     Zeilen gehoert der breiten Fassung. Auf dem Telefon laeuft der
     Text als gleichmaessiger Block, so wie .body p es ein paar
     Zeilen weiter oben setzt. Weil .body p:nth-child(n) schwerer
     wiegt als .body p, steht das hier ausgeschrieben - nicht mit
     !important. */
  .body p:nth-child(1),
  .body p:nth-child(2) {
    font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
    font-size: 0.95rem;
    line-height: 1.6;
    letter-spacing: 0;
    text-transform: none;
    color: rgba(255, 255, 255, 0.62);
    max-width: none;
    margin-bottom: 0;
  }

  /* Dritter Absatz: "Der Preis steht vor dem ersten Entwurf. Die
     Domain laeuft auf Ihren Namen ..." Preisbindung und Domain
     stehen beide schon in der Leistungsliste, die Domain zusaetzlich
     im Ablauf unter 04. */
  .about p.about__text:nth-of-type(3) { display: none; }

  /* Der Schlusssatz wiederholt die Telefonnummer, die im Kontakt-
     abschnitt in derselben Groesse steht, und "Zwanzig Minuten,
     kostenlos" aus Ablauf 01. Auf dem Desktop sitzt er am Fuss der
     linken Spalte, weit weg von beidem. */
  .sendoff { display: none; }

  /* Der Haken steht jetzt allein hinter der Umfrage - kein Titel,
     keine Linie: er ist ein Nachsatz zur Frage, kein neues Kapitel. */
  .body {
    position: static;
    opacity: 1;
    transform: none;
    margin-top: 34px;
    /* Das Raster der breiten Fassung stellt Text und Karussell
       nebeneinander. Hier ist dafuer keine Breite - beides steht
       untereinander, in Lesereihenfolge. */
    display: block;
    /* Auf der Choreografieseite steht der Satz mittig im Rahmen und
       haelt sich mit 6 Prozent von dessen Kanten fern. Hier gibt es
       keinen Rahmen, und die Einrueckung liesse den Text gegenueber
       der Preisliste darueber verspringen. */
    padding: 0;
    text-align: left;
  }

  .body p {
    transform: none;
    font-family: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
    font-size: 0.95rem;
    line-height: 1.6;
    text-align: left;
    color: rgba(255, 255, 255, 0.62);
  }

  .body p + p { margin-top: 12px; }

  /* Auf dem Telefon gibt es kein Karussell. karussell.js startet
     dort gar nicht erst, wenn <html> die Klasse is-mobil traegt - es
     laeuft also auch keine Uhr im Hintergrund. */
  .karussell { display: none; }

  /* --- Die drei Karten als Abschnitte --------------------------- */

  .pane__face,
  .pane__face--front,
  .pane__face--back {
    position: static;
    inset: auto;
    transform: none;
    opacity: 1;
    /* Nur die Farbe zuruecksetzen, nicht die Kurzschreibweise: die
       wuerde den farbigen Strich der Abschnittslinie mitloeschen. */
    background-color: transparent;
    backface-visibility: visible;
    -webkit-backface-visibility: visible;
    transition: none;
    overflow: visible;
  }

  /* Auf der Choreografieseite blendet die Vorderseite aus, sobald die
     Karte gedreht ist, und beide Seiten faerben sich beim Ueberfahren
     ein. Hier hat das keine Entsprechung: die Vorderseite IST die
     Ueberschrift des offenen Abschnitts, und einen Zeiger, der
     darueberfaehrt, gibt es nicht - der Zustand bliebe nach einem
     Antippen nur haengen. Die Regeln von dort wiegen mit zwei bis drei
     Klassen schwerer als eine, deshalb stehen sie hier ausgeschrieben. */
  .pane.is-open .pane__face--front,
  .pane.is-open .pane__face--back { opacity: 1; }

  .pane:hover .pane__face,
  .pane:focus-within .pane__face { background-color: transparent; }

  .pane:hover .pane__title,
  .pane:focus-within .pane__title { opacity: 1; }

  .pane__face--front {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    width: 100%;
    text-align: left;
    padding: 0;
    padding-top: 30px;
    /* Die Ueberschrift ist zugleich der Schalter. 44px Mindesthoehe
       aus demselben Grund wie beim Menue. */
    min-height: 44px;
    cursor: pointer;
  }

  /* Der Winkel zeigt, dass sich hier etwas zuklappen laesst. */
  .pane__face--front::after {
    content: "";
    flex: 0 0 auto;
    width: 9px;
    height: 9px;
    margin-right: 4px;
    border-right: 1.5px solid rgba(255, 255, 255, 0.5);
    border-bottom: 1.5px solid rgba(255, 255, 255, 0.5);
    transform: rotate(45deg) translate(-2px, -2px);
    transition: transform 0.3s var(--ease-pane);
  }

  .pane.is-open .pane__face--front::after {
    transform: rotate(-135deg) translate(-2px, -2px);
  }

  .pane__title {
    font-size: 1.55rem;
    line-height: 1;
    text-transform: uppercase;
    text-align: left;
    opacity: 1;
  }

  /* Zugeklappt heisst hier zusammengezogen, nicht weggedreht - und
     ausdruecklich nicht display:none. Was nicht da ist, kann sich
     nicht bewegen: der Abschnitt waere schlagartig da und schlagartig
     weg, und genau das soll er nicht sein.

     grid-template-rows faehrt die Zeile von null auf Inhalt, ohne
     dass irgendwer die Hoehe vorher kennen muss - anders als bei
     max-height, wo man einen Fantasiewert raten und dafuer ein
     ungleichmaessiges Tempo in Kauf nehmen muesste. Wo ein Browser
     das nicht bewegen kann, klappt der Abschnitt weiterhin ohne
     Uebergang auf: schlichter, nicht kaputt.

     Eine Eigenheit dieser Technik, damit sie niemanden ratlos macht:
     zwischen 0fr und 1fr wird der Anteil interpoliert, nicht die
     Hoehe - in Pixeln gemessen waechst sie im Quadrat. Nach einem
     Viertel der Strecke steht sie bei einem Sechzehntel, nach der
     Haelfte bei einem Viertel. Zusammen mit --ease-pane ergibt das
     denselben Zug wie bei der Karte auf breiten Schirmen: schnell
     auf, dann ruhig auslaufen.

     Der Text bleibt zugeklappt im Baum. app.js setzt dort inert -
     er ist damit weder antippbar noch antabbar noch fuer
     Vorlesesoftware vorhanden. */
  .pane__face--back {
    display: grid;
    grid-template-rows: 0fr;
    /* Zweiter Riegel: was ein Kind trotz allem ueberstehen laesst,
       endet spaetestens hier. Ohne ihn haengt die Sauberkeit der
       Seite daran, dass jedes kuenftige Kind sich schrumpfen laesst. */
    overflow: hidden;
    /* Die Polsterung gehoert zur Karte im Browserfenster. Hier ist
       der Abschnitt Teil der Seite und schlaegt an derselben Kante an
       wie alles andere. */
    padding: 0;
    margin-top: 0;
    margin-bottom: 0;
    transition: grid-template-rows 0.5s var(--ease-pane),
                margin-top 0.5s var(--ease-pane),
                margin-bottom 0.5s var(--ease-pane);
  }

  /* Der Beschnitt gehoert an das Kind: die Zeile wird auf null
     gefahren, und der Inhalt darin muss sich zusammenschieben
     duerfen, statt die Zeile aufzuhalten.

     margin:0 ist hier der entscheidende Teil. .flow, .ref und
     .contact tragen margin:auto 0 - auf der Karte im Browserfenster
     zentriert das den Inhalt senkrecht in der Flaeche. In einem Grid
     schaltet ein automatischer Rand auf der Blockachse das Strecken
     jedoch ab: das Kind ignoriert dann die null Pixel hohe Zeile,
     behaelt seine Inhaltshoehe und zentriert sich darin - es stand
     zugeklappt ueber dem naechsten Abschnitt. */
  .pane__face--back > * {
    margin: 0;
    min-height: 0;
    overflow: hidden;
  }

  .pane.is-open .pane__face--back {
    grid-template-rows: 1fr;
    margin-top: 20px;
    /* Luft nach unten, sonst klebt der aufgeklappte Inhalt an der
       Trennlinie der naechsten Zeile. Faehrt mit zusammen, sonst
       bliebe zugeklappt ein Abstand ohne Inhalt stehen. */
    margin-bottom: 26px;
  }

  /* Die drei Klappzeilen stehen am Stueck und sollen als eine Gruppe
     lesen, nicht als drei Abschnitte hintereinander. Nur die erste
     traegt deshalb Abstand und farbigen Strich eines Abschnitts-
     anfangs - die beiden darunter ruecken als Zeilen nach. */
  .pane:nth-child(2) .pane__face--front,
  .pane:nth-child(3) .pane__face--front {
    margin-top: 0;
    padding-top: 22px;
    background-image: none;
  }

  /* Schlussstrich unter der Gruppe. Jede Zeile hat eine Linie ueber
     sich; ohne diese hier liefe die letzte ohne Kante in die
     Wortmarke, und die Liste saehe unfertig aus. Sie sitzt an der
     Rueckseite und wandert deshalb mit, wenn Kontakt aufgeklappt
     wird - der Rahmen liegt dann unter dem Inhalt, wo er hingehoert. */
  .pane:nth-child(3) .pane__face--back {
    border-bottom: 1px solid rgba(255, 255, 255, 0.12);
  }

  /* --- Inhalte der Abschnitte ----------------------------------- */

  .flow__item { padding: 14px 0; }

  .flow__no,
  .ref__label,
  .contact__label,
  .offer__label,
  .about__label,
  .quiz__label,
  .quiz__legend,
  .quiz__hint { font-size: 0.68rem; }

  /* Kein Kleingedrucktes: die Zeile soll gelesen werden, sonst
     braucht sie niemand. */
  .quiz__ruhig { font-size: 0.82rem; }

  .flow__title,
  .ref__name { font-size: 1.3rem; }

  .flow__text,
  .ref__who,
  .ref__scope,
  .ref__link,
  .about__text,
  .offer__list,
  .offer__note,
  .sendoff__text,
  .sendoff__hint,
  .quiz__opt,
  .contact__mail,
  .contact__wa {
    font-size: 0.95rem;
    line-height: 1.6;
  }

  .offer__head,
  .about__head { font-size: 1.9rem; }
  .quiz__q { font-size: 1.75rem; }

  .contact__tel,
  .sendoff__tel { font-size: 2.1rem; }

  .offer__list li { padding: 11px 0; }

  /* --- Die vier Fragen -----------------------------------------
     Der oberste Block der Seite. Er bekommt als einziger einen
     eigenen Grund - er ist das, was hier passieren soll. */

  .quiz {
    margin-top: 30px;
    padding: 24px 20px 26px;
    border: 1px solid rgba(255, 255, 255, 0.14);
    border-radius: 18px;
    background: rgba(255, 255, 255, 0.03);
  }

  .quiz__steps { min-height: 0; }
  .quiz__opt { padding: 15px 18px; }

  .quiz__next,
  .quiz__send { width: 100%; }

  /* --- Fuss -----------------------------------------------------
     margin-top:auto schiebt beide auf der Desktopseite an den
     Spaltenfuss. Hier haengten sie damit an <main> und rissen den
     Fuss vom Text ab. */

  .sendoff {
    margin-top: 34px;
    padding-top: 30px;
  }

  .sign {
    margin-top: 34px;
    padding-top: 0;
    font-size: 3.2rem;
  }

  .legal { margin-top: 16px; }

  .legal a {
    font-size: 0.82rem;
    /* Rechtslinks muessen sich treffen lassen, auch mit dem Daumen. */
    padding: 6px 0;
  }

  /* --- Bewegung -------------------------------------------------

     Die Choreografie laesst sich auf einem Handschirm nicht
     nachbauen und soll es auch nicht. Ihr Prinzip bleibt aber:
     Inhalt kommt nach, statt einfach dazustehen. Jeder Abschnitt
     zieht herauf, sobald man ihn erreicht - einmal, und beim
     Zurueckscrollen nicht wieder.

     Der eigentliche Zweck ist ein Layoutproblem, das sich mit
     Abstaenden nicht sauber loesen liesse: unter der Umfrage ragte
     der Preis des naechsten Abschnitts in den ersten Bildschirm und
     sah aus wie ein Rest, den die Seite nicht mehr untergebracht
     hat. Was noch nicht an der Reihe ist, ist jetzt nicht zu sehen.

     Beide Klassen sitzen an <html> und werden im Kopf der Seite
     gesetzt. Fehlt mobil-auf - kein Beobachter, oder reduzierte
     Bewegung eingestellt -, greift von alldem nichts und die Seite
     steht vollstaendig sichtbar da.

     Warum die Kartenseiten eigens aufgefuehrt sind: sie bekommen
     ihre Deckkraft von der Choreografieseite mit drei Klassen
     (.pane.is-open .pane__face--front). Eine kuerzere Regel kaeme
     dagegen nicht an. Lieber ausgeschrieben als mit !important. */

  .is-mobil.mobil-auf .headline,
  .is-mobil.mobil-auf .claim,
  .is-mobil.mobil-auf .quiz,
  .is-mobil.mobil-auf .offer,
  .is-mobil.mobil-auf .body,
  .is-mobil.mobil-auf .about,
  .is-mobil.mobil-auf .sendoff,
  .is-mobil.mobil-auf .sign,
  .is-mobil.mobil-auf .legal,
  .is-mobil.mobil-auf .pane.is-open .pane__face--front,
  .is-mobil.mobil-auf .pane.is-open .pane__face--back {
    opacity: 0;
    transform: translateY(18px);
  }

  .is-mobil.mobil-auf .is-auf,
  .is-mobil.mobil-auf .pane.is-open .pane__face--front.is-auf,
  .is-mobil.mobil-auf .pane.is-open .pane__face--back.is-auf {
    opacity: 1;
    transform: none;
    transition: opacity 0.6s var(--ease-pane),
                transform 0.6s var(--ease-pane);
  }

  /* Der Einstieg steht beim Laden schon im Bild und deckt deshalb
     sofort auf. Gestaffelt statt gleichzeitig - das ist der Rest
     vom Einflug der Ueberschrift, nur ohne Flugbahn. */
  .is-mobil.mobil-auf .headline.is-auf { transition-delay: 0.06s; }
  .is-mobil.mobil-auf .claim.is-auf    { transition-delay: 0.18s; }
  .is-mobil.mobil-auf .quiz.is-auf     { transition-delay: 0.30s; }
  .is-mobil.mobil-auf .body.is-auf     { transition-delay: 0.42s; }

  /* Die Eintraege ziehen hinter dem Kreis her, nicht mit ihm. Der
     Versatz ab 0,16s laesst dem Kreis Zeit, Flaeche zu machen, bevor
     Schrift darauf erscheint - ohne ihn steht das Menue fertig da,
     waehrend es sich noch oeffnet.

     Uebergaenge statt Keyframes: beim Schliessen laeuft dieselbe
     Bewegung von selbst rueckwaerts, und es gibt keinen Zustand, in
     dem eine haengengebliebene Animation die Eintraege unsichtbar
     stehen liesse. */
  .mnav.is-offen a {
    opacity: 1;
    transform: none;
    transition: opacity 0.42s var(--ease-pane),
                transform 0.42s var(--ease-pane);
  }

  .mnav.is-offen a:nth-child(1) { transition-delay: 0.16s; }
  .mnav.is-offen a:nth-child(2) { transition-delay: 0.21s; }
  .mnav.is-offen a:nth-child(3) { transition-delay: 0.26s; }
  .mnav.is-offen a:nth-child(4) { transition-delay: 0.31s; }
  .mnav.is-offen a:nth-child(5) { transition-delay: 0.36s; }
  .mnav.is-offen a:nth-child(6) { transition-delay: 0.41s; }
  .mnav.is-offen a:nth-child(7) { transition-delay: 0.48s; }
}

/* Wer Bewegung abbestellt hat, bekommt dieselbe Flaeche ohne Aufzug:
   der Kreis springt auf, die Eintraege stehen sofort. mobil-auf wird
   in diesem Fall gar nicht erst gesetzt und kann hier nichts
   ausrichten - das Menue haengt nicht daran. */
@media (prefers-reduced-motion: reduce) {
  .mnav,
  .mnav a {
    transition: none;
    animation: none;
  }
}
