/* Nur fuer die Effekt-Varianten. Ergaenzt style.css, ersetzt sie nicht.

   Grundregel: ohne JavaScript und bei "Bewegung reduzieren" steht die Karte
   sofort fertig da. Alles hier Definierte greift erst, wenn das Skript die
   Klasse .fx-on auf <html> gesetzt hat. */

.fx-ch {
  display: inline-block;
  white-space: pre;   /* sonst fallen die Leerzeichen zwischen den Spans weg */
  /* Uebergang fuer die Rueckkehr aus dem Absacken. Beim Absacken selbst wird
     er weiter unten durch einen langsameren ersetzt. */
  transition: transform 1s cubic-bezier(.22,.61,.36,1), opacity .7s ease;
}

/* ── Schaerfe ziehen ─────────────────────────────────────────────────────── */
.fx-on .fx-blur {
  /* Der Name kommt unscharf und minimal zu gross herein und zieht die Schaerfe
     rein wie ein Objektiv. Passt zum Fotografen und ist ruhiger als jede
     Bewegung ueber die Flaeche. */
  filter: blur(14px);
  opacity: 0;
  transform: scale(1.06);
}
.fx-on .fx-blur.fx-run {
  filter: blur(0);
  opacity: 1;
  transform: none;
  transition: filter 1.15s cubic-bezier(.22,.61,.36,1),
              opacity  .8s ease,
              transform 1.15s cubic-bezier(.22,.61,.36,1);
}

/* ── Leises Nachziehen ───────────────────────────────────────────────────── */
.fx-on .fx-fade { opacity: 0; }
.fx-on .fx-fade.fx-run {
  opacity: 1;
  transition: opacity .9s ease;
}

/* ── Decodieren ──────────────────────────────────────────────────────────── */
/* Waehrend ein Zeichen noch wuerfelt, steht es etwas leiser. */
.fx-scrambling { opacity: .55; }

/* ── Split-Flap ──────────────────────────────────────────────────────────── */
/* Jeder Zeichenwechsel klappt kurz um die Waagerechte, wie das Blatt einer
   Flughafenanzeige. Die Animation ist absichtlich kuerzer als der Takt des
   Rollens, damit die Bewegung hart wirkt und nicht verschwimmt. */
.fx-flip { animation: fx-flip 42ms linear; }
@keyframes fx-flip {
  from { transform: rotateX(62deg); opacity: .55; }
  to   { transform: rotateX(0);     opacity: 1; }
}

/* ── Schreibmaschine ─────────────────────────────────────────────────────── */
/* Noch nicht getippte Zeichen sind unsichtbar, belegen aber ihren Platz. So
   steht die Zeilenbreite von Anfang an fest und im Layout ruckelt nichts. */
.fx-hidden { visibility: hidden; }

.fx-typed {
  /* Winzige Streuung pro Anschlag, gesetzt vom Skript: Versatz, Neigung und
     Farbbandstaerke. Das unterscheidet den Effekt von einer reinen
     Textanimation, ohne dass die Zeile unruhig wird. */
  transform: translate(var(--fx-dx, 0), var(--fx-dy, 0)) rotate(var(--fx-tilt, 0));
  opacity: var(--fx-ink, 1);
  animation: fx-strike 110ms ease-out;
}
@keyframes fx-strike {
  from { opacity: .15; }
  to   { opacity: var(--fx-ink, 1); }
}

/* Der Cursor haengt hinter dem zuletzt angeschlagenen Zeichen. */
.fx-ch { position: relative; }
.fx-caret::after {
  content: "";
  position: absolute;
  left: 100%;
  top: .1em;
  width: .58em;
  height: 1em;
  background: currentColor;
  animation: fx-blink 1.05s steps(1) infinite;
}
@keyframes fx-blink {
  0%, 50%   { opacity: 1; }
  50.01%, 100% { opacity: 0; }
}

/* ── Entwicklerbad ───────────────────────────────────────────────────────── */
.fx-on .fx-develop {
  opacity: 0;
  filter: contrast(.25) brightness(1.5) blur(2px);
}
.fx-on .fx-develop.fx-run {
  opacity: 1;
  filter: none;
  /* Lange, weiche Kurve: der Abzug zieht langsam durch, nichts springt. */
  transition: opacity 2.4s ease, filter 2.8s ease;
}

/* ── Absacken bei Inaktivitaet ───────────────────────────────────────────── */
.fx-drifting .fx-ch {
  transform: translateY(var(--fx-y, 40vh)) rotate(var(--fx-rot, 0deg));
  opacity: 0;
  transition: transform 5s cubic-bezier(.45,.05,.75,.6) var(--fx-delay, 0ms),
              opacity   5s ease var(--fx-delay, 0ms);
}

@media (prefers-reduced-motion: reduce) {
  .fx-on .fx-blur,
  .fx-on .fx-fade,
  .fx-on .fx-develop,
  .fx-ch,
  .fx-typed,
  .fx-drifting .fx-ch {
    filter: none;
    opacity: 1;
    transform: none;
    transition: none;
    animation: none;
  }
  /* Falls das Skript mitten im Tippen abgebrochen wird: nichts verstecken. */
  .fx-hidden { visibility: visible; }
  .fx-caret::after { display: none; }
}
