/* Nove Zenith, dunkles Erscheinungsbild. Keine Zahl in einer Regel, nur Rollen.
   Ergebnisfarben aus Tavellus/docs/design.md (dunkle Variante). */

@font-face {
  font-family: "Inter";
  src: url("/fonts/inter-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

:root {
  --surface-sunken: #08090B;
  --surface-base: #0B0D10;
  --surface-raised: #12151A;
  --surface-overlay: #181C22;

  --text-primary: #E9ECF1;
  --text-secondary: #A4ADBA;
  --text-tertiary: #7C8592;

  --border-subtle: #1A1E25;
  --border-default: #262C35;
  --border-strong: #353D48;

  --accent: #7FA8FF;
  --accent-strong: #A8C3FF;
  --accent-subtle: #121A2B;
  --accent-ink: #0B0D10;

  --result-positive: #3DBE92;
  --result-negative: #F0736A;

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 72px;
  --space-9: 120px;

  --radius-sm: 4px;
  --radius-md: 6px;
  --radius-lg: 10px;
  --radius-pill: 999px;

  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  --text-xs: 12px;
  --text-sm: 14px;
  --text-base: 16px;
  --text-md: 18px;
  --text-lg: 20px;
  --text-xl: 26px;
  --text-2xl: clamp(30px, 4.2vw, 44px);
  --text-display: clamp(40px, 7vw, 76px);

  --line-height: 1.6;
  --line-height-tight: 1.15;
  --measure: 60ch;
  --page-width: 1440px;
  --header-height: 64px;
  --rail-width: 168px;
  --karte-width: 340px;
  --header-cta-width: 148px;

  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --duration-fast: 160ms;
  --duration-base: 400ms;
  --duration-slow: 900ms;
  --stagger: 80ms;
  --shadow-lift: 0 14px 36px rgb(0 0 0 / 0.5);

  color-scheme: dark;
}

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

/* Der Platz der Scrollleiste bleibt reserviert, damit der Kopf nicht springt, wenn das
   offene Menü die Seite sperrt. */
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scrollbar-gutter: stable;
}

[id] {
  scroll-margin-top: var(--space-8);
}

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

/* Auf kurzen Seiten wie der Fehlerseite schließt der Fuß trotzdem unten ab. */
body {
  display: flex;
  flex-direction: column;
  min-height: 100svh;
  margin: 0;
  background: var(--surface-base);
  color: var(--text-primary);
  font-family: var(--font-family);
  font-size: var(--text-base);
  line-height: var(--line-height);
  font-feature-settings: "cv11", "ss01";
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

main {
  flex: 1;
}

h1,
h2,
h3 {
  margin: 0;
  line-height: var(--line-height-tight);
  font-weight: 600;
  text-wrap: balance;
}

p {
  margin: 0;
  text-wrap: pretty;
}

a {
  color: var(--accent);
  text-underline-offset: 3px;
}

a:hover {
  color: var(--accent-strong);
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

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

.skip-link {
  position: absolute;
  z-index: 10;
  left: var(--space-4);
  top: calc(-1 * var(--space-8));
  padding: var(--space-2) var(--space-3);
  background: var(--surface-raised);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
}

.skip-link:focus {
  top: var(--space-4);
}

.wrap {
  max-width: var(--page-width);
  margin: 0 auto;
  padding: 0 var(--space-4);
}

@media (min-width: 640px) {
  .wrap {
    padding: 0 var(--space-6);
  }
}

.num {
  font-variant-numeric: tabular-nums;
}

/* Kopf */

.site-header {
  position: sticky;
  top: 0;
  z-index: 5;
  background: color-mix(in srgb, var(--surface-base) 86%, transparent);
  border-bottom: 1px solid var(--border-subtle);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

/* Lesefortschritt. Die Linie unter dem Kopf füllt sich beim Scrollen in der Akzentfarbe.
   Browser ohne scroll-getriebene Animationen zeigen nur die graue Linie. */
@supports (animation-timeline: scroll()) {
  .site-header::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -1px;
    height: 2px;
    background: var(--accent);
    transform: scaleX(0);
    transform-origin: left;
    animation: lesefortschritt linear both;
    animation-timeline: scroll(root);
    pointer-events: none;
  }
}

@keyframes lesefortschritt {
  to {
    transform: scaleX(1);
  }
}

.site-header .wrap {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2) var(--space-5);
  /* Ein Pixel bleibt für die Linie unter dem Kopf. */
  min-height: calc(var(--header-height) - 1px);
}

.wordmark {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--text-primary);
  font-size: var(--text-base);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
}

.wordmark:hover {
  color: var(--text-primary);
}

.wordmark svg {
  flex: none;
  width: 32px;
  height: 32px;
}

.site-nav {
  display: flex;
  align-items: center;
  gap: var(--space-5);
}

.header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-5);
}

.site-nav .button {
  padding: var(--space-2) var(--space-4);
  min-height: 0;
  font-size: var(--text-sm);
  white-space: nowrap;
}

/* Gleich breit in beiden Sprachen, sonst rückt der Sprachschalter daneben beim Wechsel. */
.site-nav .header-cta {
  justify-content: center;
  min-width: var(--header-cta-width);
}

.site-nav .menu-cta {
  display: none;
}

/* Ab hier passt der Knopf in den Kopf. Schriftzug, Menü und Aktionen teilen sich drei
   Spalten, die äußeren gleich breit, damit das Menü in der Mitte der Seite steht. Wird es
   eng, gibt die Spalte des Schriftzugs zuerst nach. */
@media (min-width: 1000px) {
  .site-header .wrap {
    display: grid;
    grid-template-columns: 1fr auto 1fr;
  }

  .wordmark {
    justify-self: start;
  }

  .site-nav {
    grid-column: 2 / 4;
    display: grid;
    grid-template-columns: subgrid;
  }

  /* Feste Spalte, weil das Menü neben der Seitenleiste fehlt und die Gruppe sonst in die
     Mitte rutscht. */
  .header-actions {
    grid-column: 2;
    justify-self: end;
  }
}

@media (max-width: 999px) {
  .site-nav .header-cta {
    display: none;
  }
}

.site-nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-5);
  margin: 0;
  padding: 0;
  list-style: none;
}

.wordmark span,
.site-nav .sections a {
  position: relative;
}

.site-nav a {
  color: var(--text-secondary);
  font-size: var(--text-base);
  text-decoration: none;
}

.site-nav a:hover {
  color: var(--text-primary);
}

/* Akzentlinie unter Schriftzug und Menüpunkten, wächst beim Hovern von links auf. */
.wordmark span::after,
.site-nav .sections a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(-1 * var(--space-1));
  height: 2px;
  border-radius: 1px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--duration-fast) ease-out;
}

/* Die Laufweite hängt auch hinter das letzte H Abstand an, die Linie endet am Buchstaben. */
.wordmark span::after {
  right: 0.16em;
}

.wordmark:hover span::after,
.site-nav .sections a:hover::after {
  transform: scaleX(1);
}

@media (prefers-reduced-motion: reduce) {
  .wordmark span::after,
  .site-nav .sections a::after {
    transition: none;
  }
}

/* Sprachschalter als Kippschalter: zwei gleich breite Felder in einer Spur, darunter ein
   Knopf, der die aktuelle Sprache markiert. Steht EN vorn, liegt er rechts. Beim Wechsel
   setzt motion.js Lage und Dehnung des Knopfs in --lang-x, --lang-sx und --lang-sy. */
.lang {
  --lang-x: 0;
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  margin-left: var(--space-5);
  padding: var(--space-1);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-pill);
  background: var(--surface-sunken);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
}

.lang:has(> [aria-current]:last-child) {
  --lang-x: 1;
}

.lang::before {
  content: "";
  position: absolute;
  top: var(--space-1);
  bottom: var(--space-1);
  left: var(--space-1);
  width: calc(50% - var(--space-1));
  border-radius: var(--radius-pill);
  background: var(--surface-overlay);
  box-shadow: inset 0 0 0 1px var(--border-strong);
  transform: translateX(calc(var(--lang-x) * 100%)) scale(var(--lang-sx, 1), var(--lang-sy, 1));
}

/* Trennlinie zum Menü, mit dem Abstand davor genau in der Mitte. */
.lang::after {
  content: "";
  position: absolute;
  top: var(--space-1);
  bottom: var(--space-1);
  left: calc(-1 * var(--space-5) - 1px);
  width: 1px;
  background: var(--border-default);
}

/* Die Schriftgröße des Menüs gilt nicht für den Sprachschalter, beide Kürzel bleiben
   gleich groß. */
.lang a,
.lang span {
  position: relative;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  font-size: inherit;
  text-align: center;
  text-decoration: none;
  transition: color var(--duration-base) var(--ease-out);
}

.lang a {
  color: var(--text-tertiary);
}

.lang a:hover {
  color: var(--text-primary);
}

.lang [aria-current] {
  color: var(--text-primary);
}

/* Während der Knopf läuft, tauschen die Kürzel ihre Helligkeit. */
.lang.wechselt a {
  color: var(--text-primary);
}

.lang.wechselt [aria-current] {
  color: var(--text-tertiary);
}

/* Die Liste trägt das popover-Attribut für das Menü auf schmalen Bildschirmen. Auf breiten
   ist sie eine gewöhnliche Zeile, deshalb fallen die Vorgaben des Browsers für Popover weg. */
.site-nav .sections {
  position: relative;
  inset: auto;
  width: auto;
  height: auto;
  margin: 0;
  padding: 0;
  overflow: visible;
  border: 0;
  background: none;
  color: inherit;
}

.site-nav .sections a[aria-current] {
  color: var(--text-primary);
}

/* Linie unter dem Abschnitt, in dem man gerade liest. Lage und Breite setzt motion.js. */
@media (min-width: 821px) {
  .site-nav .sections::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: var(--marker-w, 0);
    height: 2px;
    border-radius: 1px;
    background: var(--accent);
    opacity: 0;
    transform: translate(var(--marker-x, 0), var(--marker-y, 0));
    transition:
      transform var(--duration-base) var(--ease-out),
      width var(--duration-base) var(--ease-out),
      opacity var(--duration-fast);
    pointer-events: none;
  }

  .site-nav .sections.has-marker::before {
    opacity: 1;
  }

  .site-nav .sections.marker-jump::before {
    transition: opacity var(--duration-fast);
  }
}

.menu-button {
  display: none;
}

@media (max-width: 820px) {
  .lang {
    margin-left: 0;
  }

  .lang::after {
    display: none;
  }

  .menu-button {
    display: inline-grid;
    place-content: center;
    gap: 5px;
    width: 44px;
    height: 44px;
    margin-right: calc(-1 * var(--space-3));
    padding: 0;
    border: 0;
    border-radius: var(--radius-md);
    background: none;
    color: var(--text-primary);
    cursor: pointer;
    transition: background-color 120ms;
  }

  .menu-button:active {
    background: var(--surface-overlay);
  }

  .menu-button span {
    display: block;
    width: 20px;
    height: 1.5px;
    border-radius: 1px;
    background: currentColor;
    transition: transform var(--duration-fast) var(--ease-out);
  }

  /* Zwei Striche werden zum Kreuz, solange das Menü offen ist. */
  .site-nav:has(:popover-open) .menu-button span:first-child {
    transform: translateY(3.25px) rotate(45deg);
  }

  .site-nav:has(:popover-open) .menu-button span:last-child {
    transform: translateY(-3.25px) rotate(-45deg);
  }

  .site-nav .sections:not(:popover-open) {
    display: none;
  }

  .site-nav .sections:popover-open {
    position: fixed;
    inset: var(--header-height) 0 0;
    display: flex;
    flex-direction: column;
    flex-wrap: nowrap;
    gap: 0;
    padding: var(--space-4) var(--space-4) var(--space-7);
    overflow-y: auto;
    border-top: 1px solid var(--border-subtle);
    background: var(--surface-base);
    opacity: 1;
    transform: none;
    transition:
      opacity var(--duration-fast),
      transform var(--duration-base) var(--ease-out);
  }

  @starting-style {
    .site-nav .sections:popover-open {
      opacity: 0;
      transform: translateY(calc(-1 * var(--space-2)));
    }
  }

  .site-nav .sections::backdrop {
    background: transparent;
  }

  html:has(.sections:popover-open) {
    overflow: hidden;
  }

  .site-nav .sections li {
    border-bottom: 1px solid var(--border-subtle);
  }

  .site-nav .sections a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: var(--space-4) 0;
    color: var(--text-primary);
    font-size: var(--text-xl);
    font-weight: 500;
    letter-spacing: -0.015em;
  }

  .site-nav .sections a::after {
    display: none;
  }

  .site-nav .sections a[aria-current] {
    color: var(--accent);
  }

  /* Einträge folgen beim Öffnen kurz nacheinander. */
  .site-nav .sections:popover-open li {
    transition:
      opacity var(--duration-base) var(--ease-out),
      transform var(--duration-base) var(--ease-out);
  }

  .site-nav .sections:popover-open li:nth-child(2) { transition-delay: calc(1 * var(--stagger) / 2); }
  .site-nav .sections:popover-open li:nth-child(3) { transition-delay: calc(2 * var(--stagger) / 2); }
  .site-nav .sections:popover-open li:nth-child(4) { transition-delay: calc(3 * var(--stagger) / 2); }
  .site-nav .sections:popover-open li:nth-child(5) { transition-delay: calc(4 * var(--stagger) / 2); }
  .site-nav .sections:popover-open li:nth-child(6) { transition-delay: calc(5 * var(--stagger) / 2); }

  .site-nav .sections .menu-cta {
    display: block;
    padding-top: var(--space-6);
    border-bottom: 0;
  }

  .site-nav .sections .menu-cta a {
    justify-content: center;
    padding: var(--space-4) var(--space-5);
    color: var(--accent-ink);
    font-size: var(--text-base);
    letter-spacing: normal;
  }

  @starting-style {
    .site-nav .sections:popover-open li {
      opacity: 0;
      transform: translateY(var(--space-3));
    }
  }
}

@media (prefers-reduced-motion: reduce) {
  .site-nav .sections::before,
  .site-nav .sections:popover-open,
  .site-nav .sections:popover-open li,
  .menu-button span {
    transition: none;
  }
}

/* Seitenleiste. Auf breiten Bildschirmen stehen die Abschnitte statt im Kopf als Zeitachse
   ganz links und wandern mit. Jeder Punkt ist offen, aktuell oder erledigt, die Linie zum
   nächsten füllt sich mit dem Lesefortschritt (--progress aus motion.js). Der aktuelle
   Punkt wächst, leuchtet und pulsiert, sein Name steht groß. */

.rail {
  display: none;
}

@media (min-width: 1200px) {
  :root {
    /* Beginn des Inhalts rechts neben der Leiste. */
    --rail-space: calc(var(--space-6) + var(--rail-width) + var(--space-7));
    /* Abstand der rechten Linie vom Rand, 24 px hinter der Kante des Inhalts. Das
       Prozent bezieht sich auf die volle Breite von Einstieg und Abschnitten. */
    --axis-right: calc(
      max(var(--space-6), (100% - var(--page-width)) / 2 + var(--space-6)) - var(--space-5)
    );
  }

  main:has(> .rail) {
    position: relative;
  }

  /* Der Inhalt weicht nur so weit aus, wie die Leiste ihn sonst überdecken würde. */
  main:has(> .rail) .wrap {
    padding-left: max(
      var(--space-6),
      calc(var(--rail-space) - max(0px, (100vw - var(--page-width)) / 2))
    );
  }

  html:has(.rail) .site-nav .sections {
    display: none;
  }

  html:has(.rail) .lang {
    margin-left: 0;
  }

  html:has(.rail) .lang::after {
    display: none;
  }

  /* Eine senkrechte Linie trennt Leiste und Inhalt über die ganze Seite. Die
     waagerechten Trennlinien laufen über sie hinweg bis an beide Ränder. */
  main:has(> .rail)::before {
    content: "";
    position: absolute;
    z-index: -1;
    top: 0;
    bottom: 0;
    left: calc(
      max(var(--rail-space), (100% - var(--page-width)) / 2 + var(--space-6)) - var(--space-5)
    );
    width: 1px;
    background: var(--border-subtle);
  }

  /* Rechts neben dem Inhalt läuft eine Linie als Spiegelbild der linken und trifft so
     bei keiner Breite Text. Der Bogen im Einstieg richtet sich nach ihr: Er ist 900 px
     breit, seine gestrichelte Achse steht in der Mitte und geht in die Linie über. */
  main:has(> .rail) .hero-arc {
    right: calc(var(--axis-right) - 449.5px);
  }

  main:has(> .rail) :is(.facts, .section, .contact) {
    position: relative;
  }

  main:has(> .rail) :is(.facts, .section, .contact)::before {
    content: "";
    position: absolute;
    z-index: -1;
    top: 0;
    right: var(--axis-right);
    bottom: 0;
    width: 1px;
    background: var(--border-subtle);
  }

  .motion main:has(> .rail) .facts::before {
    animation: fade-in 1200ms ease-out 900ms backwards;
  }

  /* Unten endet die Leiste vor dem Fuß, damit der letzte Punkt nicht auf seiner Linie
     sitzt. */
  .rail {
    position: absolute;
    z-index: 2;
    top: 0;
    bottom: var(--space-8);
    left: var(--space-6);
    display: block;
    width: var(--rail-width);
  }

  /* Oben steht die Liste auf Höhe der Dachzeile im Einstieg und bleibt beim Scrollen dort.
     Die Punkte verteilen sich bis fast an den unteren Rand. */
  .rail-inner {
    position: sticky;
    top: calc(var(--header-height) + var(--space-9));
    display: flex;
    flex-direction: column;
    height: calc(100svh - var(--header-height) - var(--space-9) - var(--space-7));
  }

  .rail ol {
    display: flex;
    flex: 1;
    flex-direction: column;
  }

  .motion .rail-inner {
    animation: rail-in var(--duration-slow) var(--ease-out) 300ms backwards;
  }
}

@keyframes rail-in {
  from {
    opacity: 0;
    transform: translateX(calc(-1 * var(--space-3)));
  }
}

.rail-title {
  margin-bottom: var(--space-5);
  color: var(--text-tertiary);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.rail ol {
  margin: 0;
  padding: 0;
  list-style: none;
}

.rail li {
  position: relative;
  flex: 1;
}

.rail li:last-child {
  flex: 0;
}

/* Verbindung von Punktmitte zu Punktmitte: grau darunter, Akzent darüber. Die Punkte
   liegen darüber und verdecken die Enden. */
.rail li:not(:last-child)::before,
.rail li:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 10px;
  bottom: -10px;
  left: 6px;
  width: 2px;
  border-radius: 1px;
  background: var(--border-default);
}

.rail li:not(:last-child)::after {
  background: var(--accent);
  box-shadow: 0 0 12px color-mix(in srgb, var(--accent) 60%, transparent);
  transform: scaleY(var(--progress, 0));
  transform-origin: top;
}

.rail a {
  display: grid;
  grid-template-columns: 14px auto minmax(0, 1fr);
  align-items: center;
  gap: var(--space-3);
  color: var(--text-tertiary);
  font-size: var(--text-sm);
  line-height: 20px;
  text-decoration: none;
  transition:
    color var(--duration-base),
    font-size var(--duration-base) var(--ease-out);
}

.rail a:hover {
  color: var(--text-primary);
}

.rail-num {
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  transition: color var(--duration-base);
}

.rail-dot {
  position: relative;
  z-index: 1;
  width: 14px;
  height: 14px;
  border: 1px solid var(--border-strong);
  border-radius: 50%;
  background: var(--surface-base);
  transition:
    background-color var(--duration-base),
    border-color var(--duration-base),
    box-shadow var(--duration-base),
    transform var(--duration-base) var(--ease-out);
}

.rail-dot::after {
  content: "";
  position: absolute;
  opacity: 0;
  transition:
    opacity var(--duration-base),
    transform var(--duration-base) var(--ease-out);
}

.rail [data-state="current"] a {
  color: var(--text-primary);
  font-size: var(--text-lg);
  font-weight: 600;
  letter-spacing: -0.01em;
}

.rail [data-state="current"] .rail-num {
  color: var(--accent);
}

.rail [data-state="current"] .rail-dot {
  border-color: var(--accent);
  box-shadow:
    0 0 0 5px var(--accent-subtle),
    0 0 24px color-mix(in srgb, var(--accent) 45%, transparent);
  transform: scale(1.45);
}

/* Ring, der vom aktuellen Punkt aus nach außen läuft. */
.rail-dot::before {
  content: "";
  position: absolute;
  inset: -1px;
  border: 1px solid var(--accent);
  border-radius: 50%;
  opacity: 0;
}

.motion .rail [data-state="current"] .rail-dot::before {
  animation: rail-pulse 2.4s var(--ease-out) infinite;
}

@keyframes rail-pulse {
  from {
    opacity: 0.7;
    transform: scale(1);
  }
  to {
    opacity: 0;
    transform: scale(2.4);
  }
}

/* Aktuell: Punkt in der Mitte. */
.rail [data-state="current"] .rail-dot::after {
  inset: 3px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 1;
}

.rail [data-state="done"] a {
  color: var(--text-secondary);
}

.rail [data-state="done"] .rail-dot {
  border-color: var(--accent);
  background: var(--accent);
}

/* Erledigt: Haken. */
.rail [data-state="done"] .rail-dot::after {
  top: 2px;
  left: 4px;
  width: 4px;
  height: 7px;
  border: solid var(--accent-ink);
  border-width: 0 1.5px 1.5px 0;
  opacity: 1;
  transform: rotate(45deg);
}

.rail [data-state="done"] a:hover,
.rail [data-state="current"] a:hover {
  color: var(--text-primary);
}

@media (prefers-reduced-motion: reduce) {
  .rail a,
  .rail-num,
  .rail-dot,
  .rail-dot::after {
    transition: none;
  }
}

/* Einstieg */

.hero {
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid var(--border-subtle);
}

.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(var(--border-subtle) 1px, transparent 1px),
    linear-gradient(90deg, var(--border-subtle) 1px, transparent 1px);
  background-size: 72px 72px;
  background-position: center top;
  mask-image: radial-gradient(ellipse 70% 80% at 70% 0%, #000 0%, transparent 75%);
  -webkit-mask-image: radial-gradient(ellipse 70% 80% at 70% 0%, #000 0%, transparent 75%);
  pointer-events: none;
}

.hero-arc {
  position: absolute;
  right: -10%;
  bottom: -12%;
  width: min(900px, 120vw);
  height: auto;
  color: var(--border-strong);
  pointer-events: none;
}

@media (max-width: 767px) {
  .hero-arc {
    display: none;
  }
}

.hero-arc .zenith,
.hero-arc .pulse {
  color: var(--accent);
}

/* Beim Laden zeichnen sich Horizont und Bögen nacheinander, dann erscheint der Zenit und
   sendet in ruhigem Takt einen Ring aus. */
.motion .hero-arc .arc {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: draw 1800ms var(--ease-out) forwards;
}

.motion .hero-arc .arc:nth-child(2) { animation-delay: 200ms; }
.motion .hero-arc .arc:nth-child(3) { animation-delay: 350ms; }
.motion .hero-arc .arc:nth-child(4) { animation-delay: 500ms; }

.motion .hero-arc .axis {
  animation: fade-in 1200ms ease-out 900ms backwards;
}

.motion .hero-arc .zenith {
  animation: fade-in 600ms ease-out 1400ms backwards;
}

.motion .hero-arc .pulse {
  transform-box: fill-box;
  transform-origin: center;
  animation: pulse 4s ease-out 2200ms infinite;
}

@keyframes draw {
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
}

@keyframes pulse {
  0% {
    opacity: 0.5;
    transform: scale(1);
  }

  60%,
  100% {
    opacity: 0;
    transform: scale(2.6);
  }
}

.hero .wrap {
  position: relative;
  padding-top: var(--space-8);
  padding-bottom: var(--space-8);
}

@media (min-width: 768px) {
  .hero .wrap {
    padding-top: var(--space-9);
    padding-bottom: var(--space-9);
  }
}

.eyebrow {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-5);
  color: var(--text-tertiary);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.eyebrow::before {
  content: "";
  width: var(--space-5);
  height: 1px;
  background: var(--accent);
}

.hero h1 {
  max-width: 16ch;
  font-size: var(--text-display);
  letter-spacing: -0.035em;
  line-height: 1.04;
}

/* Der graue Teil steht immer auf eigener Zeile. */
.hero h1 em {
  display: block;
  color: var(--text-tertiary);
  font-style: normal;
}

.hero .lead {
  max-width: 52ch;
  margin-top: var(--space-5);
  color: var(--text-secondary);
  font-size: var(--text-md);
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-6);
}

.button {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: 0 var(--space-5);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-md);
  color: var(--text-primary);
  font-size: var(--text-sm);
  font-weight: 500;
  text-decoration: none;
  transition: background-color 120ms, border-color 120ms, scale 120ms var(--ease-out);
}

.button:hover {
  background: var(--surface-overlay);
  color: var(--text-primary);
}

.button.primary {
  background: var(--text-primary);
  border-color: var(--text-primary);
  color: var(--accent-ink);
}

.button.primary:hover {
  background: var(--accent-strong);
  border-color: var(--accent-strong);
  color: var(--accent-ink);
}

/* Gedrückt gibt der Knopf etwas nach und wird eine Stufe dunkler. */
.button:active {
  background: var(--surface-raised);
  scale: 0.97;
}

.button.primary:active {
  background: var(--accent);
  border-color: var(--accent);
}

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

/* Prozess im Einstieg. Eine kleine App-Karte durchläuft die vier Leistungen: als Skizze,
   als Entwurf mit Raster und Maßen, im Bau mit Inspektor und zuletzt live. motion.js setzt
   die Phase in data-phase, zeichnet Skizze, Maße und Inspektor und zählt im Betrieb weiter.
   Ohne Skript und bei reduzierter Bewegung steht die fertige Karte da und die Schritte
   fehlen. Unter 768 px folgt die Karte dem Text. Ab 768 px, wo auch der Bogen erscheint,
   steht sie rechts neben ihm, und der Text hält ihr den Platz frei. */

.prozess {
  position: relative;
  max-width: var(--page-width);
  margin: 0 auto;
  padding: 0 var(--space-4) var(--space-8);
}

@media (min-width: 640px) {
  .prozess {
    padding-inline: var(--space-6);
  }
}

@media (max-width: 767px) {
  .hero .wrap:has(+ .prozess) {
    padding-bottom: var(--space-7);
  }
}

@media (min-width: 768px) {
  .hero .wrap:has(+ .prozess) {
    padding-right: calc(var(--space-6) + var(--karte-width) + var(--space-7));
  }

  /* Die längste Zeile, „Konzepte, die“, ist gut 6,2 em breit. Wird die Spalte neben der
     Karte zu schmal, schrumpft die Überschrift mit ihr. */
  .hero:has(.prozess) h1 {
    font-size: min(
      var(--text-display),
      (100vw - 2 * var(--space-6) - var(--karte-width) - var(--space-7)) / 6.5
    );
  }

  .prozess {
    position: absolute;
    top: 50%;
    right: max(var(--space-6), (100% - var(--page-width)) / 2 + var(--space-6));
    width: var(--karte-width);
    margin: 0;
    padding: 0;
    translate: 0 -50%;
  }
}

.karte {
  position: relative;
  display: grid;
  gap: var(--space-3);
  max-width: var(--karte-width);
  margin-inline: auto;
  padding: var(--space-5);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  background-color: var(--surface-raised);
  box-shadow: var(--shadow-lift);
  color: var(--text-primary);
  font-size: var(--text-sm);
  line-height: var(--line-height-tight);
  transition:
    opacity var(--duration-base) var(--ease-out),
    background-color var(--duration-base) var(--ease-out),
    border-color var(--duration-base) var(--ease-out),
    box-shadow var(--duration-slow) var(--ease-out);
}

/* Raster des Entwurfs, alle 8 px eine Linie. Eine Maske deckt es von oben nach unten auf. */
.karte::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(color-mix(in srgb, var(--accent) 9%, transparent) 1px, transparent 1px)
    0 0 / 100% var(--space-2);
  opacity: 0;
  mask: linear-gradient(#000 40%, transparent 60%) 0 100% / 100% 250% no-repeat;
  -webkit-mask: linear-gradient(#000 40%, transparent 60%) 0 100% / 100% 250% no-repeat;
  transition:
    opacity var(--duration-base) var(--ease-out),
    mask-position 1100ms var(--ease-out) 250ms,
    -webkit-mask-position 1100ms var(--ease-out) 250ms;
  pointer-events: none;
}

/* Lichtstreif, der beim Livegang einmal über die Karte läuft. */
.karte::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(
      105deg,
      transparent 40%,
      color-mix(in srgb, var(--text-primary) 7%, transparent) 50%,
      transparent 60%
    )
    120% 0 / 250% 100% no-repeat;
  opacity: 0;
  pointer-events: none;
}

.karte-kopf {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-bottom: var(--space-2);
}

.karte-icon {
  display: grid;
  place-items: center;
  width: var(--space-6);
  height: var(--space-6);
  border-radius: var(--radius-md);
  background-color: var(--accent-subtle);
  color: var(--accent-strong);
}

.karte-icon svg {
  width: var(--space-4);
  height: var(--space-4);
}

.karte-titel {
  font-weight: 600;
}

.karte-status {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-left: auto;
  padding: var(--space-1) var(--space-2);
  color: var(--result-positive);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.karte-status::before {
  content: "";
  width: calc(var(--space-1) * 1.5);
  height: calc(var(--space-1) * 1.5);
  border-radius: 50%;
  background: currentColor;
}

.karte-status .bau {
  display: none;
}

.karte-wert {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
}

.karte-zahl {
  font-size: var(--text-2xl);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
}

.karte-delta {
  color: var(--result-positive);
  font-size: var(--text-xs);
  font-weight: 600;
}

.karte-text {
  justify-self: start;
  margin: calc(var(--space-2) * -1) 0 var(--space-2);
  color: var(--text-tertiary);
}

/* Höhe jedes Balkens in --h, Reihenfolge in --b. Heute ist Freitag. */
.karte-balken {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: var(--space-2);
  height: var(--space-9);
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--text-tertiary);
  font-size: var(--text-xs);
  text-align: center;
}

.karte-balken li {
  display: grid;
  grid-template-rows: 1fr auto;
  gap: var(--space-2);
}

.karte-balken i {
  border-radius: var(--radius-sm);
  background-color: color-mix(in srgb, var(--accent) 45%, var(--surface-raised));
  transform: scaleY(var(--h));
  transform-origin: bottom;
  transition:
    transform var(--duration-slow) var(--ease-out),
    background-color var(--duration-base) var(--ease-out);
}

.karte-balken li:nth-child(1) { --h: 0.42; --b: 0; }
.karte-balken li:nth-child(2) { --h: 0.58; --b: 1; }
.karte-balken li:nth-child(3) { --h: 0.5; --b: 2; }
.karte-balken li:nth-child(4) { --h: 0.72; --b: 3; }
.karte-balken li:nth-child(5) { --h: 0.84; --b: 4; }
.karte-balken li:nth-child(6) { --h: 0.3; --b: 5; }
.karte-balken li:nth-child(7) { --h: 0.16; --b: 6; }

.karte-balken li:nth-child(5) {
  color: var(--text-primary);
}

.karte-balken li:nth-child(5) i {
  background-color: var(--accent);
}

.karte-knopf {
  display: flex;
  justify-content: center;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  background-color: var(--text-primary);
  color: var(--accent-ink);
  font-weight: 600;
}

/* Schein, Skizze, Maße und Inspektor legt motion.js über die Karte. */
.karte-schein,
.karte-skizze,
.karte-mass,
.karte-inspektor {
  position: absolute;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--duration-base) var(--ease-out);
}

.karte-skizze,
.karte-mass {
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.karte-skizze {
  color: var(--text-secondary);
}

.karte-skizze path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}

/* Wie ein Stift: langsam ansetzen, zügig ziehen, sanft absetzen. Dauer und Beginn jeder
   Linie in --t und --d. */
.karte-skizze.zeichnet path {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset var(--t) cubic-bezier(0.45, 0, 0.25, 1) var(--d);
}

/* Eine Maßlinie wächst aus ihrer Mitte, danach erscheint die Zahl. */
.mass {
  position: absolute;
  top: var(--y);
  left: var(--x);
  width: var(--w);
  height: var(--h);
  color: var(--accent);
  --start: calc(var(--i) * 140ms + 450ms);
}

.mass::before {
  content: "";
  position: absolute;
  inset: 0;
  opacity: 0;
  transition:
    opacity var(--duration-fast) var(--start),
    transform 520ms var(--ease-out) var(--start);
}

.mass.quer::before {
  border-left: 1px solid;
  border-right: 1px solid;
  background: linear-gradient(currentColor, currentColor) center / 100% 1px no-repeat;
  transform: scaleX(0);
}

.mass.hoch::before {
  border-top: 1px solid;
  border-bottom: 1px solid;
  background: linear-gradient(currentColor, currentColor) center / 1px 100% no-repeat;
  transform: scaleY(0);
}

.mass.schrift::before {
  border: 1px dashed;
  transform: scale(1.08);
}

.mass span {
  position: absolute;
  top: 50%;
  left: 50%;
  padding: 0 var(--space-1);
  border-radius: var(--radius-sm);
  background: var(--accent);
  color: var(--accent-ink);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  font-weight: 600;
  line-height: var(--line-height);
  white-space: nowrap;
  opacity: 0;
  translate: -50% -50%;
  scale: 0.8;
  transition:
    opacity var(--duration-fast) var(--ease-out) calc(var(--start) + 260ms),
    scale var(--duration-base) cubic-bezier(0.34, 1.56, 0.64, 1) calc(var(--start) + 260ms);
}

.mass.schrift span {
  left: var(--lx);
  margin-left: var(--space-3);
  translate: calc(var(--space-2) * -1) -50%;
  scale: 1;
  background: none;
  color: var(--accent);
  transition:
    opacity var(--duration-base) var(--ease-out) calc(var(--start) + 200ms),
    translate var(--duration-base) var(--ease-out) calc(var(--start) + 200ms);
}

.prozess[data-phase="design"] .mass::before {
  opacity: 1;
  transform: none;
}

.prozess[data-phase="design"] .mass span {
  opacity: 1;
  scale: 1;
}

.prozess[data-phase="design"] .mass.schrift span {
  translate: 0 -50%;
}

/* Beim Verlassen des Entwurfs gehen alle Maße zugleich und schnell. */
.prozess:not([data-phase="design"]) .mass::before,
.prozess:not([data-phase="design"]) .mass span {
  transition-delay: 0ms;
  transition-duration: var(--duration-fast);
}

.karte-inspektor {
  top: 0;
  left: 0;
  width: var(--w, 0);
  height: var(--h, 0);
  border-radius: var(--radius-sm);
  outline: 1px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  translate: var(--x, 0) var(--y, 0);
  transition:
    opacity var(--duration-base) var(--ease-out),
    translate 460ms cubic-bezier(0.2, 0.8, 0.2, 1),
    width 460ms cubic-bezier(0.2, 0.8, 0.2, 1),
    height 460ms cubic-bezier(0.2, 0.8, 0.2, 1);
}

.karte-inspektor.sofort {
  transition: opacity var(--duration-base) var(--ease-out) 300ms;
}

.karte-inspektor::after {
  content: attr(data-tag) "  " attr(data-mass);
  position: absolute;
  bottom: 100%;
  left: -1px;
  margin-bottom: var(--space-1);
  padding: 0 var(--space-2);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface-overlay);
  box-shadow: var(--shadow-lift);
  color: var(--accent-strong);
  font-family: var(--font-mono);
  font-size: var(--text-xs);
  line-height: var(--line-height);
  white-space: pre;
}

/* Phasen. Die Teile wechseln nacheinander, ihre Reihenfolge steht in --i. Die Umrisse
   liegen immer da und bekommen nur Farbe, damit auch sie überblenden. */
.motion .karte [data-skizze] {
  outline: 1px dashed transparent;
  outline-offset: 2px;
  transition:
    opacity var(--duration-base) var(--ease-out),
    color var(--duration-base) var(--ease-out),
    background-color var(--duration-base) var(--ease-out),
    outline-color var(--duration-base) var(--ease-out);
  transition-delay: calc(var(--i, 0) * 60ms);
}

.prozess[data-phase="leer"] .karte {
  opacity: 0;
}

.prozess:is([data-phase="leer"], [data-phase="konzept"]) .karte {
  border-color: transparent;
  background-color: transparent;
  box-shadow: none;
}

.prozess:is([data-phase="leer"], [data-phase="konzept"]) [data-skizze] {
  opacity: 0;
  transition-delay: 0ms;
}

.prozess[data-phase="konzept"] .karte-skizze {
  opacity: 1;
}

/* Die Skizze strafft sich noch, bevor sie ausblendet, und die Flächen des Entwurfs füllen
   sich darunter von oben nach unten. */
.prozess[data-phase="design"] .karte-skizze {
  transition: opacity 500ms var(--ease-out) 500ms;
}

.prozess[data-phase="design"] .karte {
  box-shadow: none;
  transition-delay: 300ms;
}

.prozess[data-phase="design"] .karte::before {
  opacity: 1;
  mask-position: 0 0;
  -webkit-mask-position: 0 0;
}

.prozess[data-phase="design"] :is(.karte-mass, .mass) {
  opacity: 1;
}

.prozess[data-phase="design"] [data-skizze] {
  transition-delay: calc(350ms + var(--i) * 50ms);
}

/* Schon in der Skizze tragen die Teile unsichtbar das Grau des Entwurfs, sonst blitzen
   beim Einblenden kurz Text und Knopf in ihren echten Farben auf. */
.prozess:is([data-phase="leer"], [data-phase="konzept"], [data-phase="design"]) [data-skizze]:not(.karte-balken) {
  border-radius: var(--radius-sm);
  background-color: var(--border-default);
  color: transparent;
}

.prozess:is([data-phase="leer"], [data-phase="konzept"], [data-phase="design"]) .karte-balken li {
  color: transparent;
}

.prozess:is([data-phase="leer"], [data-phase="konzept"], [data-phase="design"]) .karte-balken i {
  background-color: var(--border-strong);
}

.prozess[data-phase="entwicklung"] .karte {
  box-shadow: none;
}

.prozess[data-phase="entwicklung"] [data-skizze] {
  outline-color: color-mix(in srgb, var(--accent) 40%, transparent);
}

.prozess[data-phase="entwicklung"] .karte-inspektor {
  opacity: 1;
}

/* Die Balken schießen ein wenig über ihr Ziel und setzen sich. */
.prozess[data-phase="entwicklung"] .karte-balken i {
  animation: balken-wachsen 900ms cubic-bezier(0.34, 1.3, 0.64, 1) backwards;
  animation-delay: calc(var(--b) * 60ms + 450ms);
}

.prozess[data-phase="entwicklung"] .karte-status {
  color: var(--text-tertiary);
}

.prozess[data-phase="entwicklung"] .karte-status::before {
  animation: bau-blinken 900ms ease-in-out infinite;
}

.prozess[data-phase="entwicklung"] .karte-status .bau {
  display: inline;
}

.prozess[data-phase="entwicklung"] .karte-status .live {
  display: none;
}

/* Live: Die Umrisse fallen von oben nach unten weg, ein Lichtstreif läuft einmal über die
   Karte, und der Punkt springt an, bevor er pulsiert. */
.prozess[data-phase="betrieb"] [data-skizze] {
  transition-delay: calc(var(--i) * 40ms);
}

.motion .prozess[data-phase="betrieb"] .karte::after {
  animation: glanz 1400ms var(--ease-out) 250ms both;
}

.motion .prozess[data-phase="betrieb"] .karte-status::before {
  animation:
    status-an 600ms cubic-bezier(0.34, 1.56, 0.64, 1) 500ms backwards,
    live-pulse 2.4s var(--ease-out) 1100ms infinite;
}

.motion .prozess[data-phase="betrieb"] .karte-status .live {
  animation: fade-in var(--duration-base) var(--ease-out) 500ms backwards;
}

/* Eine neue Buchung: Jede geänderte Ziffer schiebt sich in ihrem Fenster nach oben. Die
   alte steht in data-alt direkt darüber und rollt mit hinaus, die neue kommt grün von
   unten. Weiter links liegende Stellen folgen nach --n. */
.karte-zahl .ziffer {
  display: inline-block;
  clip-path: inset(0 -0.1em);
}

.karte-zahl .ziffer > span {
  position: relative;
  display: inline-block;
  animation:
    ziffer-rollen 650ms var(--ease-out) calc(var(--n) * 90ms) backwards,
    ziffer-gruen 1400ms var(--ease-out) calc(var(--n) * 90ms) backwards;
}

.karte-zahl .ziffer > span::before {
  content: attr(data-alt);
  position: absolute;
  bottom: 100%;
  left: 0;
  color: var(--text-primary);
}

/* Ein eigener Klick bucht: Der Knopf wird grün und bestätigt, Konfetti fliegt heraus. */
.motion .prozess[data-phase="betrieb"] .karte-knopf {
  cursor: pointer;
  user-select: none;
}

.motion .prozess[data-phase="betrieb"] .karte-knopf:active {
  scale: 0.97;
}

.motion .karte-knopf.gebucht {
  background-color: var(--result-positive);
  transition-delay: 0ms;
  animation: knopf-pop 500ms cubic-bezier(0.34, 1.56, 0.64, 1);
}

.konfetti {
  position: absolute;
  top: 0;
  left: 0;
  width: 6px;
  height: 10px;
  margin: -5px 0 0 -3px;
  border-radius: 1px;
  background-color: var(--accent);
  pointer-events: none;
}

.konfetti:nth-of-type(4n + 2) {
  background-color: var(--result-positive);
}

.konfetti:nth-of-type(4n + 3) {
  background-color: var(--accent-strong);
}

.konfetti:nth-of-type(4n) {
  background-color: var(--text-primary);
}

.konfetti:nth-of-type(3n) {
  width: 7px;
  height: 7px;
  border-radius: 50%;
}

@keyframes balken-wachsen {
  from {
    transform: scaleY(0);
  }
}

@keyframes bau-blinken {
  50% {
    opacity: 0.25;
  }
}

@keyframes status-an {
  from {
    transform: scale(0);
  }
}

@keyframes glanz {
  from {
    background-position: 120% 0;
    opacity: 1;
  }

  to {
    background-position: -20% 0;
    opacity: 1;
  }
}

@keyframes ziffer-rollen {
  from {
    translate: 0 100%;
  }
}

@keyframes ziffer-gruen {
  from,
  30% {
    color: var(--result-positive);
  }
}

@keyframes knopf-pop {
  40% {
    scale: 1.04;
  }
}

/* Die vier Schritte unter der Karte. Der aktuelle füllt seine Linie in --dauer, ein Klick
   springt in seine Phase. */
.prozess-schritte {
  display: none;
}

.motion .prozess-schritte {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: var(--space-2);
  max-width: var(--karte-width);
  margin: var(--space-4) auto 0;
  padding: 0;
  list-style: none;
}

.prozess-schritte button {
  position: relative;
  width: 100%;
  padding: var(--space-3) 0 var(--space-1);
  border: 0;
  background: none;
  color: var(--text-tertiary);
  font: inherit;
  font-size: var(--text-xs);
  font-weight: 500;
  text-align: left;
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--duration-fast);
}

.prozess-schritte button::before,
.prozess-schritte button::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 2px;
  border-radius: 1px;
  background: var(--border-default);
}

.prozess-schritte button::after {
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
}

.prozess-schritte button:hover,
.prozess-schritte [aria-current] {
  color: var(--text-primary);
}

.prozess-schritte button:active {
  color: var(--text-secondary);
}

.prozess-schritte .erledigt::after {
  transform: none;
}

.prozess-schritte [aria-current]::after {
  animation: schritt-fuellen var(--dauer) linear forwards;
}

.prozess-schritte [data-phase="betrieb"][aria-current]::after {
  background: var(--result-positive);
  animation: none;
  transform: none;
}

.prozess-schritte button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

@keyframes schritt-fuellen {
  to {
    transform: none;
  }
}

/* Kennzahlen unter dem Einstieg */

.facts {
  border-bottom: 1px solid var(--border-subtle);
}

.facts-strip {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin: 0;
}

@media (min-width: 900px) {
  .facts-strip {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.facts-strip div {
  padding: var(--space-5) var(--space-4);
  border-top: 1px solid var(--border-subtle);
  border-left: 1px solid var(--border-subtle);
}

/* Im Raster aus zwei Spalten laufen die Linien bis an den Bildschirmrand, der Text
   steht trotzdem auf der Kante des übrigen Inhalts. */
@media (max-width: 899px) {
  .facts .wrap {
    padding: 0;
  }
}

@media (min-width: 640px) and (max-width: 899px) {
  .facts-strip div {
    padding-inline: var(--space-6);
  }
}

.facts-strip div:nth-child(-n + 2) {
  border-top: 0;
}

.facts-strip div:nth-child(odd) {
  border-left: 0;
}

@media (min-width: 900px) {
  .facts-strip div {
    padding: var(--space-6) var(--space-5);
    border-top: 0;
  }

  .facts-strip div:nth-child(odd) {
    border-left: 1px solid var(--border-subtle);
  }

  .facts-strip div:first-child {
    border-left: 0;
    padding-left: 0;
  }
}

.facts-strip dt {
  color: var(--text-tertiary);
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.facts-strip dd {
  margin: var(--space-2) 0 0;
  color: var(--text-primary);
  font-size: var(--text-md);
  font-weight: 500;
}

/* Abschnitte */

.section {
  padding: var(--space-8) 0;
  border-bottom: 1px solid var(--border-subtle);
}

@media (min-width: 768px) {
  .section {
    padding: var(--space-9) 0;
  }
}

.section-head {
  display: grid;
  gap: var(--space-4);
  margin-bottom: var(--space-7);
}

@media (min-width: 900px) {
  .section-head {
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    gap: var(--space-7);
    align-items: end;
  }
}

.section-head > div:only-child {
  grid-column: 1 / -1;
}

.section-head .eyebrow {
  margin-bottom: var(--space-4);
}

.section-head h2 {
  font-size: var(--text-2xl);
  letter-spacing: -0.025em;
}

.section-head > p {
  max-width: var(--measure);
  color: var(--text-secondary);
  font-size: var(--text-md);
}

/* Produkt */

.product {
  display: grid;
  gap: var(--space-7);
}

@media (min-width: 960px) {
  .product {
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    align-items: start;
  }
}

.product-copy h3 {
  font-size: var(--text-xl);
  letter-spacing: -0.015em;
}

.product-copy > p {
  max-width: var(--measure);
  margin-top: var(--space-4);
  color: var(--text-secondary);
}

.product-copy > p:first-of-type {
  color: var(--text-primary);
  font-size: var(--text-md);
}

.points {
  display: grid;
  gap: var(--space-4);
  margin: var(--space-6) 0 0;
  padding: 0;
  list-style: none;
}

.points li {
  display: grid;
  grid-template-columns: var(--space-5) minmax(0, 1fr);
  gap: var(--space-2);
  color: var(--text-secondary);
}

.points li::before {
  content: "";
  width: 10px;
  height: 1px;
  margin-top: 0.8em;
  background: var(--accent);
}

.points strong {
  color: var(--text-primary);
  font-weight: 500;
}

.spec {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-4) var(--space-5);
  margin: var(--space-6) 0 0;
  padding-top: var(--space-5);
  border-top: 1px solid var(--border-subtle);
  font-size: var(--text-sm);
}

.spec dt {
  color: var(--text-tertiary);
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.spec dd {
  margin: var(--space-1) 0 0;
  color: var(--text-primary);
}

/* Produktvorschau mit Beispieldaten */

.preview {
  margin: 0;
  background: var(--surface-raised);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: 0 24px 64px -32px rgb(0 0 0 / 0.8);
  overflow: hidden;
}

.preview-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border-default);
  font-size: var(--text-xs);
}

.preview-bar .dots {
  display: flex;
  gap: 6px;
}

.preview-bar .dots i {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--border-strong);
}

.preview-bar span {
  color: var(--text-tertiary);
}

.preview-stats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin: 0;
  border-bottom: 1px solid var(--border-subtle);
}

.preview-stats div {
  padding: var(--space-4);
}

.preview-stats div + div {
  border-left: 1px solid var(--border-subtle);
}

.preview-stats dt {
  color: var(--text-tertiary);
  font-size: var(--text-xs);
}

.preview-stats dd {
  margin: var(--space-1) 0 0;
  font-size: var(--text-lg);
  font-weight: 600;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}

.preview table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}

.preview caption {
  padding: var(--space-3) var(--space-4) var(--space-2);
  color: var(--text-tertiary);
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  text-align: left;
  text-transform: uppercase;
}

.preview th,
.preview td {
  padding: var(--space-2) var(--space-4);
  text-align: left;
  white-space: nowrap;
}

.preview thead th {
  color: var(--text-tertiary);
  font-size: var(--text-xs);
  font-weight: 500;
}

.preview tbody tr {
  border-top: 1px solid var(--border-subtle);
}

.preview tbody th {
  font-weight: 500;
}

.preview td {
  color: var(--text-secondary);
}

.preview .r,
.preview .amount {
  text-align: right;
}

.preview .pos {
  color: var(--result-positive);
}

.preview .neg {
  color: var(--result-negative);
}

@media (max-width: 479px) {
  .preview .side {
    display: none;
  }

  .preview th,
  .preview td {
    padding-left: var(--space-3);
    padding-right: var(--space-3);
  }
}

.preview figcaption {
  padding: var(--space-3) var(--space-4);
  border-top: 1px solid var(--border-subtle);
  color: var(--text-tertiary);
  font-size: var(--text-xs);
}

/* Leistungen */

.services {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--border-default);
}

.services li {
  display: grid;
  gap: var(--space-3);
  padding: var(--space-6) 0;
  border-bottom: 1px solid var(--border-subtle);
}

/* Gleiche Spalten wie der Kopf des Abschnitts, damit die Texte unter seinem Absatz in
   einer Flucht stehen. Nummer und Titel teilen sich die linke Spalte. */
@media (min-width: 900px) {
  .services li {
    grid-template-columns: minmax(0, 5fr) minmax(0, 6fr);
    gap: var(--space-7);
    align-items: baseline;
  }

  .services .index,
  .services h3 {
    grid-area: 1 / 1;
  }

  .services h3 {
    padding-left: calc(var(--space-8) + var(--space-6));
  }
}

.services .index {
  color: var(--accent);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}

.services h3 {
  font-size: var(--text-lg);
  letter-spacing: -0.01em;
}

.services p {
  max-width: var(--measure);
  color: var(--text-secondary);
}

/* Referenz */

.case {
  display: grid;
  gap: var(--space-6);
  padding: var(--space-5);
  background: var(--surface-raised);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
}

@media (min-width: 900px) {
  .case {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-7);
    padding: var(--space-7);
  }
}

.case .eyebrow {
  margin-bottom: var(--space-4);
}

.case h3 {
  font-size: var(--text-xl);
  letter-spacing: -0.015em;
}

.case-copy p {
  max-width: var(--measure);
  margin-top: var(--space-4);
  color: var(--text-secondary);
}

/* Kundenstimme: Karte wie der Status-Kasten, Anführungszeichen oben, darunter Foto,
   Name und Rolle. */
.case-quote {
  margin: var(--space-6) 0 0;
  padding: var(--space-5);
  background: var(--surface-base);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}

.case-quote::before {
  content: "\201C" / "";
  display: block;
  height: 0.5em;
  color: var(--border-strong);
  /* Inter zeichnet das Zeichen als zwei Keile, eine Serifenschrift als runde 66. */
  font-family: Georgia, "Times New Roman", serif;
  font-size: calc(var(--text-xl) * 2.6);
  line-height: 1;
}

.case-quote blockquote {
  margin: 0;
}

.case-copy .case-quote p {
  margin-top: 0;
  color: var(--text-primary);
  font-size: var(--text-md);
}

.case-quote figcaption {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--border-subtle);
}

.quote-avatar {
  flex: none;
  width: var(--space-7);
  height: var(--space-7);
  border-radius: var(--radius-pill);
}

.quote-name {
  display: block;
  color: var(--text-primary);
  font-size: var(--text-sm);
  font-weight: 500;
}

.quote-role {
  display: block;
  color: var(--text-tertiary);
  font-size: var(--text-xs);
}

.case-copy .link {
  display: inline-block;
  margin-top: var(--space-5);
  font-weight: 500;
  text-decoration: none;
}

.case-copy .link:hover {
  text-decoration: underline;
}

/* Kunde und Leistung teilen sich eine Zeile, Umfang und Status nehmen die volle Breite. */
.case dl {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-template-rows: auto auto 1fr;
  gap: var(--space-5) var(--space-4);
  margin: 0;
  font-size: var(--text-sm);
}

@media (min-width: 900px) {
  .case dl {
    padding-left: var(--space-6);
    border-left: 1px solid var(--border-default);
  }
}

.case dt {
  color: var(--text-tertiary);
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.case dd {
  margin: var(--space-1) 0 0;
}

/* Umfang als Kapseln, die umbrechen, damit die Spalte nicht höher wird als der Text. */
.scope {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin: var(--space-2) 0 0;
  padding: 0;
  list-style: none;
}

.scope li {
  padding: 2px var(--space-2);
  background: var(--surface-overlay);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-sm);
  color: var(--text-primary);
  font-size: var(--text-xs);
  line-height: var(--line-height);
}

/* Status füllt die Spalte nach unten auf und zeigt, wo das Projekt steht. */
.case dl > div:nth-child(n + 3) {
  grid-column: 1 / -1;
}

.case-status {
  align-self: end;
  padding: var(--space-5);
  background: var(--surface-base);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
}

.case-status dd > p {
  margin-top: var(--space-4);
  color: var(--text-tertiary);
  font-size: var(--text-xs);
}

/* Drei Stationen nebeneinander, die Linie läuft hinter den Punkten durch. */
.phases {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin: var(--space-5) 0 0;
  padding: 0;
  list-style: none;
}

.phases li {
  position: relative;
  padding-top: var(--space-5);
  color: var(--text-secondary);
}

.phases li::before {
  content: "";
  position: absolute;
  z-index: 1;
  top: 0;
  left: 0;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--accent);
}

.phases li:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 4px;
  left: 4px;
  width: 100%;
  height: 1px;
  background: var(--accent);
}

.phases .current {
  color: var(--text-primary);
}

.phases .current::before {
  background: var(--result-positive);
}

/* Hinter der letzten Station läuft die Linie aus: Der Betrieb geht weiter. */
.phases .current::after {
  content: "";
  position: absolute;
  top: 4px;
  left: 4px;
  width: 100%;
  height: 1px;
  background: linear-gradient(to right, var(--result-positive), transparent);
}

.motion .phases .current::before {
  animation: live-pulse 2.4s var(--ease-out) infinite;
}

@keyframes live-pulse {
  from {
    box-shadow: 0 0 0 0 color-mix(in srgb, var(--result-positive) 60%, transparent);
  }
  to {
    box-shadow: 0 0 0 8px transparent;
  }
}

/* Weg */

.timeline {
  position: relative;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* Akzentlinie über den Verbindungen, motion.js setzt ihre Länge in --fill. Sie liegt über
   den grauen Strecken und unter den Punkten. */
.timeline.has-fill::before {
  content: "";
  position: absolute;
  z-index: 1;
  top: calc(0.55em + 4px);
  left: 4px;
  width: 1px;
  height: var(--fill, 0);
  background: var(--accent);
}

.timeline.has-fill li::before {
  z-index: 2;
}

@media (min-width: 768px) {
  .timeline.has-fill::before {
    left: calc(200px - var(--space-5) + 4px);
  }
}

.timeline li {
  position: relative;
  display: grid;
  gap: var(--space-2);
  padding: 0 0 var(--space-7) var(--space-6);
}

.timeline li::before {
  content: "";
  position: absolute;
  top: 0.55em;
  left: 0;
  width: 9px;
  height: 9px;
  border: 1px solid var(--border-strong);
  border-radius: 50%;
  background: var(--surface-base);
}

.timeline li::after {
  content: "";
  position: absolute;
  top: calc(0.55em + 13px);
  bottom: 4px;
  left: 4px;
  width: 1px;
  background: var(--border-default);
}

.timeline li:last-child {
  padding-bottom: 0;
}

.timeline li:last-child::after {
  display: none;
}

.timeline li.done::before {
  background: var(--text-tertiary);
  border-color: var(--text-tertiary);
}

.timeline li.now::before {
  background: var(--accent);
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-subtle);
}

@media (min-width: 768px) {
  .timeline li {
    grid-template-columns: 200px minmax(0, 1fr);
    gap: var(--space-6);
    padding-left: 0;
  }

  .timeline li::before {
    left: 200px;
    margin-left: calc(-1 * var(--space-5));
  }

  .timeline li::after {
    left: calc(200px - var(--space-5) + 4px);
  }

  .timeline .when {
    padding-right: var(--space-6);
    text-align: right;
  }
}

.timeline .when {
  color: var(--text-tertiary);
  font-size: var(--text-sm);
  font-variant-numeric: tabular-nums;
}

.timeline li.now .when {
  color: var(--accent);
}

.timeline h3 {
  font-size: var(--text-md);
  letter-spacing: -0.005em;
}

.timeline p {
  max-width: var(--measure);
  margin-top: var(--space-2);
  color: var(--text-secondary);
}

/* Arbeitsweise */

/* Fugen und Rand sind der Hintergrund der Liste, der zwischen den Karten durchscheint. So
   kann der Schein der Maus beides zugleich erleuchten. */
.principles {
  display: grid;
  gap: 1px;
  margin: 0;
  padding: 1px;
  list-style: none;
  background: var(--border-subtle);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

@media (min-width: 768px) {
  .principles {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

.principles li {
  padding: var(--space-6);
  background: var(--surface-base);
}

.principles h3 {
  font-size: var(--text-md);
}

.principles p {
  margin-top: var(--space-3);
  color: var(--text-secondary);
}

/* Kontakt */

.contact {
  position: relative;
  overflow: hidden;
  padding: var(--space-8) 0;
}

.contact .wrap {
  position: relative;
}

/* Ringe um das Zeichen, rechts hinter dem Kontakt. Sie greifen die Bögen im Einstieg auf
   und werden nach außen schwächer. Auf breiten Bildschirmen richten sie sich am Rand der
   Seite statt des Fensters aus, damit das Zeichen innerhalb bleibt. Unter 768 px fehlen
   sie wie die Bögen. */
.wellen {
  position: absolute;
  top: 50%;
  right: calc(max(0px, (100% - var(--page-width)) / 2) - 12%);
  width: min(720px, 70vw);
  height: auto;
  translate: 0 -50%;
  color: var(--border-default);
  mask-image: radial-gradient(circle closest-side, #000 50%, transparent);
  -webkit-mask-image: radial-gradient(circle closest-side, #000 50%, transparent);
  pointer-events: none;
}

@media (max-width: 767px) {
  .wellen {
    display: none;
  }
}

.wellen circle:nth-child(1) { --n: 0; }
.wellen circle:nth-child(2) { --n: 1; }
.wellen circle:nth-child(3) { --n: 2; }
.wellen circle:nth-child(4) { --n: 3; }
.wellen circle:nth-child(5) { --n: 4; }

.wellen circle {
  opacity: calc(1 - var(--n) * 0.15);
}

.wellen-marke {
  color: var(--border-strong);
}

@media (min-width: 768px) {
  .contact {
    padding: var(--space-9) 0;
  }
}

.contact h2 {
  max-width: 20ch;
  font-size: var(--text-2xl);
  letter-spacing: -0.025em;
}

.contact .mail {
  display: inline-block;
  margin-top: var(--space-6);
  color: var(--text-primary);
  font-size: clamp(22px, 4vw, 40px);
  font-weight: 500;
  letter-spacing: -0.02em;
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 8px;
  overflow-wrap: anywhere;
}

.contact .mail:hover {
  color: var(--accent-strong);
}

.topics {
  display: grid;
  gap: var(--space-5);
  margin: var(--space-7) 0 0;
  padding: var(--space-6) 0 0;
  list-style: none;
  border-top: 1px solid var(--border-subtle);
}

@media (min-width: 768px) {
  .topics {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--space-6);
  }
}

.topics h3 {
  font-size: var(--text-base);
}

.topics p {
  margin-top: var(--space-2);
  color: var(--text-secondary);
  font-size: var(--text-sm);
}

/* Rechtstexte und Fehlerseite */

.legal {
  padding-top: var(--space-8);
  padding-bottom: var(--space-8);
}

.legal h1 {
  margin-bottom: var(--space-6);
  font-size: var(--text-2xl);
  letter-spacing: -0.02em;
}

.legal h2 {
  margin: var(--space-6) 0 var(--space-3);
  font-size: var(--text-md);
}

.legal p,
.legal ul,
.legal address {
  max-width: var(--measure);
  margin: 0 0 var(--space-3);
  color: var(--text-secondary);
  font-style: normal;
}

.legal ul {
  padding-left: var(--space-5);
}

/* Kurzfassung und Widerspruchsrecht, das Art. 21 Abs. 4 DSGVO getrennt verlangt */
.legal-box {
  max-width: calc(var(--measure) + 2 * var(--space-5));
  margin: var(--space-6) 0;
  padding: var(--space-5);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  background: var(--surface-raised);
}

.legal .legal-box h2 {
  margin-top: 0;
}

.legal .legal-box p:last-child,
.legal .legal-box ul:last-child {
  margin-bottom: 0;
}

.legal .stand {
  margin-top: var(--space-7);
  color: var(--text-tertiary);
  font-size: var(--text-sm);
}

/* Fuß */

.site-footer {
  border-top: 1px solid var(--border-subtle);
  background: var(--surface-sunken);
  color: var(--text-tertiary);
  font-size: var(--text-sm);
}

.site-footer .wrap {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-4) var(--space-6);
}

.footer-main {
  row-gap: var(--space-6);
  align-items: flex-start;
  padding-top: var(--space-7);
  padding-bottom: var(--space-6);
}

.footer-brand {
  display: grid;
  gap: var(--space-1);
}

.footer-name {
  color: var(--text-primary);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.footer-nav {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-6) var(--space-7);
}

.footer-title {
  margin-bottom: var(--space-3);
  font-size: var(--text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.footer-nav ul {
  display: grid;
  gap: var(--space-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.footer-bottom {
  border-top: 1px solid var(--border-subtle);
}

.footer-bottom .wrap {
  align-items: center;
  padding-top: var(--space-5);
  padding-bottom: var(--space-5);
}

.site-footer a {
  color: var(--text-secondary);
  text-decoration: none;
}

.site-footer a:hover {
  color: var(--text-primary);
  text-decoration: underline;
}

/* Bewegung. Gilt nur mit der Klasse motion, die motion.js setzt, wenn der Browser keine
   reduzierte Bewegung wünscht. Ohne Skript ist alles sofort sichtbar. */

@media screen {
  .motion [data-reveal]:not([data-reveal="stagger"]),
  .motion [data-reveal="stagger"] > * {
    opacity: 0;
    transform: translateY(var(--space-5));
    transition:
      opacity var(--duration-slow) var(--ease-out),
      transform var(--duration-slow) var(--ease-out);
    transition-delay: calc(var(--i, 0) * var(--stagger));
  }

  .motion [data-reveal].is-in:not([data-reveal="stagger"]),
  .motion [data-reveal="stagger"].is-in > * {
    opacity: 1;
    transform: none;
  }

  /* Die kurze Akzentlinie vor jeder Dachzeile wächst nach dem Text heraus. */
  .motion [data-reveal] .eyebrow::before {
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--duration-slow) var(--ease-out) 300ms;
  }

  .motion .is-in .eyebrow::before {
    transform: none;
  }
}

/* Lichtschein, der der Maus über Karten folgt. Lage in --mx und --my aus motion.js. */
@media (hover: hover) and (pointer: fine) {
  .motion :is(.principles li, .case) {
    position: relative;
    isolation: isolate;
  }

  .motion :is(.principles li, .case)::before {
    content: "";
    position: absolute;
    z-index: -1;
    inset: 0;
    border-radius: inherit;
    background: radial-gradient(
      420px circle at var(--mx, 50%) var(--my, 50%),
      color-mix(in srgb, var(--accent) 8%, transparent),
      transparent 70%
    );
    opacity: 0;
    transition: opacity var(--duration-base);
    pointer-events: none;
  }

  .motion :is(.principles li, .case):hover::before {
    opacity: 1;
  }

  /* Dazu leuchten die Kanten in der Nähe der Maus auf: bei den Grundsätzen die Fugen des
     Rasters, bei Flow der Rahmen der Karte. */
  .motion .principles {
    position: relative;
    isolation: isolate;
  }

  .motion :is(.principles, .case)::after {
    content: "";
    position: absolute;
    border-radius: inherit;
    background: radial-gradient(
      240px circle at var(--mx, 50%) var(--my, 50%),
      color-mix(in srgb, var(--accent) 60%, transparent),
      transparent 70%
    );
    opacity: 0;
    transition: opacity var(--duration-base);
    pointer-events: none;
  }

  /* Unter den Karten, also nur in den Fugen sichtbar. */
  .motion .principles::after {
    z-index: -1;
    inset: 0;
  }

  /* Über der Karte, aber nur auf ihrem Rahmen. */
  .motion .case::after {
    inset: -1px;
    padding: 1px;
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
  }

  .motion :is(.principles, .case):hover::after {
    opacity: 1;
  }

  /* Über die Hauptknöpfe läuft beim Überfahren einmal ein Glanz. */
  .motion .button.primary:is(:hover, :focus-visible) {
    background-image: linear-gradient(
      110deg,
      transparent 40%,
      rgb(255 255 255 / 0.6) 50%,
      transparent 60%
    );
    background-size: 250% 100%;
    background-repeat: no-repeat;
    animation: knopf-glanz var(--duration-slow) ease-in-out both;
  }
}

@keyframes knopf-glanz {
  from {
    background-position: 130% 0;
  }

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

/* Ein Lichtpunkt umrundet langsam den Rand der Tavellus-Vorschau, sobald sie im Bild ist.
   Er liegt innen am Rahmen, weil die Vorschau alles außerhalb abschneidet. */
@property --strahl {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

@media screen {
  .motion .product .preview {
    position: relative;
  }

  .motion .product.is-in .preview::before {
    content: "";
    position: absolute;
    z-index: 1;
    inset: 0;
    padding: 1px;
    border-radius: calc(var(--radius-lg) - 1px);
    background: conic-gradient(
      from var(--strahl),
      transparent 0 280deg,
      var(--accent) 350deg,
      transparent 360deg
    );
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
    animation: strahl 8s linear infinite;
    pointer-events: none;
  }

  /* Die Ringe hinter dem Kontakt leuchten von innen nach außen nacheinander auf, wie eine
     Welle, die vom Zeichen ausgeht. */
  .motion .wellen.is-in circle {
    animation: welle 5s var(--ease-out) infinite;
    animation-delay: calc(var(--n) * 160ms);
  }
}

@keyframes strahl {
  to {
    --strahl: 360deg;
  }
}

@keyframes welle {
  0%,
  40%,
  100% {
    stroke: currentColor;
  }

  12% {
    stroke: var(--accent);
  }
}

/* Schein, der der Maus im Einstieg folgt. Lage in --hx und --hy aus motion.js, vor der
   ersten Bewegung steht er oberhalb des Bildes. */
@media (hover: hover) and (pointer: fine) {
  .motion .hero {
    background: radial-gradient(
      560px circle at var(--hx, 70%) var(--hy, -30%),
      color-mix(in srgb, var(--accent) 7%, transparent),
      transparent 70%
    );
  }
}

/* Die Wörter der Hauptüberschrift kommen nacheinander aus der Unschärfe. */
@media screen {
  .motion .hero h1 .word {
    display: inline-block;
    opacity: 0;
    filter: blur(10px);
    transform: translateY(0.25em);
    transition:
      opacity var(--duration-slow) var(--ease-out),
      filter var(--duration-slow) var(--ease-out),
      transform var(--duration-slow) var(--ease-out);
    transition-delay: calc(150ms + var(--w) * 70ms);
  }

  .motion .is-in h1 .word {
    opacity: 1;
    filter: none;
    transform: none;
  }

  /* Das wechselnde erste Wort schneidet seitlich ab, solange seine Breite nachgleitet. */
  .motion .hero h1[data-vorlauf] .word:first-child {
    overflow-x: clip;
    white-space: nowrap;
  }
}

/* Abschnittsüberschriften füllen sich beim Scrollen Zeile für Zeile mit Farbe. Der
   Hintergrund der Spanne läuft über alle Zeilen, als stünden sie hintereinander. */
@supports (animation-timeline: view()) {
  .motion :is(.section-head, .contact) h2 {
    view-timeline: --titel block;
  }

  .motion :is(.section-head, .contact) h2 .fill {
    /* Der Verlauf ist zweieinhalbmal so breit wie der Text. Am Anfang zeigt er nur den
       hellen, am Ende nur den dunklen Teil, der weiche Übergang liegt dazwischen. */
    background: linear-gradient(
      90deg,
      var(--text-primary) 40%,
      var(--text-tertiary) 60%
    ) 100% 0 / 250% 100% no-repeat;
    color: transparent;
    -webkit-background-clip: text;
    background-clip: text;
    animation: titel-fuellen linear both;
    animation-timeline: --titel;
    animation-range: entry 60% cover 50%;
  }
}

@keyframes titel-fuellen {
  to {
    background-position-x: 0;
  }
}

/* Die Tavellus-Vorschau, die Status-Karte und die Karte im Einstieg neigen sich zur Maus,
   ein Glanz folgt ihr. Die Karte im Einstieg braucht ihr ::after für den Lichtstreif beim
   Livegang, ihr Glanz liegt deshalb in .karte-schein. */
@media (hover: hover) and (pointer: fine) {
  .motion :is(.preview, .case-status) {
    position: relative;
  }

  .motion :is(.product .preview, .case-status, .karte).tilt {
    transform: perspective(1200px) rotateX(var(--rx)) rotateY(var(--ry));
    transition: transform var(--duration-fast) ease-out;
  }

  .motion :is(.preview, .case-status)::after,
  .motion .karte-schein {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: radial-gradient(
      360px circle at var(--mx, 50%) var(--my, 50%),
      color-mix(in srgb, var(--text-primary) 6%, transparent),
      transparent 70%
    );
    opacity: 0;
    transition: opacity var(--duration-base);
    pointer-events: none;
  }

  .motion :is(.preview, .case-status).tilt::after,
  .motion .karte.tilt .karte-schein {
    opacity: 1;
  }
}
