/* =====================================================================
 * Bewegung
 *
 * Eine einzige Dauer steuert die gesamte Seite: --fy-dur.
 * Alle anderen Zeitvariablen leiten sich daraus ab, damit sich das
 * Tempo an genau einer Stelle aendern laesst.
 *
 * Die Einblendungen sind richtungsabhaengig. Beim Scrollen nach unten
 * kommen Elemente von unten herein, beim Scrollen nach oben von oben.
 * Elemente, die den Sichtbereich verlassen, werden zurueckgesetzt und
 * blenden beim naechsten Vorbeikommen erneut ein.
 * ===================================================================== */

html:root {
  --fy-dur: 1500ms;
  --fy-dur-s: var(--fy-dur);
  --fy-dur-m: var(--fy-dur);
  --fy-dur-l: var(--fy-dur);
  --fy-ease: cubic-bezier(0.22, 0.61, 0.24, 1);
  --fy-shift: 34px;
  --fy-stagger-step: 90ms;
}

/* Grundzustand: sichtbar. Erst wenn JavaScript laeuft, wird versteckt. */
.fy-anim {
  opacity: 1;
}

html.fy-js .fy-anim {
  opacity: 0;
  transform: translate3d(var(--fy-x, 0), var(--fy-y, var(--fy-shift)), 0) scale(var(--fy-sc, 1));
  transition:
    opacity var(--fy-dur) var(--fy-ease),
    transform var(--fy-dur) var(--fy-ease),
    filter var(--fy-dur) var(--fy-ease);
  transition-delay: calc(var(--fy-stagger, 0) * var(--fy-stagger-step));
  /* Kein will-change: bei hundert Elementen erzeugt es hundert dauerhafte
   * Compositor-Ebenen. Genau das laesst Einblendungen auf schwachen
   * Geraeten flackern, statt sie ruhiger zu machen. */
  backface-visibility: hidden;
}

html.fy-js .fy-anim.is-in {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
  filter: none;
}

/* Richtungen. Sie werden zur Laufzeit gesetzt, je nach Scrollrichtung
 * und Position des Elements im Raster. */
html.fy-js .fy-anim[data-fy-dir="up"] {
  --fy-y: var(--fy-shift);
  --fy-x: 0;
}

html.fy-js .fy-anim[data-fy-dir="down"] {
  --fy-y: calc(var(--fy-shift) * -1);
  --fy-x: 0;
}

html.fy-js .fy-anim[data-fy-dir="left"] {
  --fy-x: calc(var(--fy-shift) * -1.4);
  --fy-y: 0;
}

html.fy-js .fy-anim[data-fy-dir="right"] {
  --fy-x: calc(var(--fy-shift) * 1.4);
  --fy-y: 0;
}

html.fy-js .fy-anim[data-fy-dir="scale"] {
  --fy-x: 0;
  --fy-y: calc(var(--fy-shift) * 0.4);
  --fy-sc: 0.965;
}

/* Bilder bekommen zusaetzlich eine leichte Unschaerfe, das wirkt
 * ruhiger als eine reine Verschiebung. */
html.fy-js .fy-anim-media {
  filter: blur(7px);
}

html.fy-js .fy-anim-media.is-in {
  filter: blur(0);
}

/* Der Hero laeuft beim Laden als eigene Abfolge, nicht ueber den
 * Beobachter, damit die erste Bildschirmseite sofort sitzt. */
@keyframes fy-rise {
  from {
    opacity: 0;
    transform: translate3d(0, 46px, 0) skewX(-8deg);
  }
  to {
    opacity: 1;
    transform: translate3d(0, 0, 0) skewX(-8deg);
  }
}

@keyframes fy-rise-plain {
  from {
    opacity: 0;
    transform: translate3d(0, 30px, 0);
  }
  to {
    opacity: 1;
    transform: translate3d(0, 0, 0);
  }
}

@keyframes fy-media-in {
  from {
    opacity: 0;
    transform: scale(1.04);
    filter: blur(10px);
  }
  to {
    opacity: 1;
    transform: scale(1);
    filter: blur(0);
  }
}

html.fy-js .fy-hero-line {
  animation: fy-rise var(--fy-dur) var(--fy-ease) both;
}

html.fy-js .fy-hero-line-offset {
  animation: fy-rise var(--fy-dur) var(--fy-ease) 140ms both;
}

html.fy-js .fy-hero-sub {
  animation: fy-rise-plain var(--fy-dur) var(--fy-ease) 240ms both;
}

html.fy-js .fy-hero-copy .fy-eyebrow {
  animation: fy-rise-plain var(--fy-dur) var(--fy-ease) 60ms both;
}

html.fy-js .fy-hero-copy .fy-lead {
  animation: fy-rise-plain var(--fy-dur) var(--fy-ease) 340ms both;
}

html.fy-js .fy-hero-copy .fy-row {
  animation: fy-rise-plain var(--fy-dur) var(--fy-ease) 440ms both;
}

html.fy-js .fy-hero-media {
  animation: fy-media-in var(--fy-dur) var(--fy-ease) 120ms both;
}

html.fy-js .fy-pillar {
  animation: fy-rise-plain var(--fy-dur) var(--fy-ease) both;
}


/* =====================================================================
 * Bewegung respektieren: harte Regel, keine Option.
 * ===================================================================== */
@media (prefers-reduced-motion: reduce) {
  html:root {
    --fy-dur: 1ms;
  }

  html.fy-js .fy-anim,
  html.fy-js .fy-anim-media {
    opacity: 1;
    transform: none;
    filter: none;
    transition: none;
  }

  html.fy-js .fy-hero-line,
  html.fy-js .fy-hero-line-offset,
  html.fy-js .fy-hero-sub,
  html.fy-js .fy-hero-media,
  html.fy-js .fy-pillar,
  html.fy-js .fy-hero-copy .fy-eyebrow,
  html.fy-js .fy-hero-copy .fy-lead,
  html.fy-js .fy-hero-copy .fy-row {
    animation: none;
    opacity: 1;
    transform: none;
  }

  html.fy-js .fy-hero-line,
  html.fy-js .fy-hero-line-offset {
    transform: skewX(-8deg);
  }
}

/* =====================================================================
 * Ausdrueckliche Wahl des Besuchers
 *
 * Die Voreinstellung kommt vom Browser. Wer Bewegung ausdruecklich
 * einschaltet, bekommt sie auch dann, wenn das Betriebssystem sie
 * global abgeschaltet hat. Umgekehrt gilt dasselbe.
 * ===================================================================== */
html.fy-js.fy-motion-on {
  --fy-dur: 1500ms;
}

html.fy-js.fy-motion-on .fy-anim {
  opacity: 0;
  transform: translate3d(var(--fy-x, 0), var(--fy-y, var(--fy-shift)), 0) scale(var(--fy-sc, 1));
  transition:
    opacity var(--fy-dur) var(--fy-ease),
    transform var(--fy-dur) var(--fy-ease),
    filter var(--fy-dur) var(--fy-ease);
}

html.fy-js.fy-motion-on .fy-anim.is-in {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
  filter: none;
}

html.fy-js.fy-motion-on .fy-anim-media {
  filter: blur(7px);
}

html.fy-js.fy-motion-on .fy-anim-media.is-in {
  filter: blur(0);
}
