/*
 * Bewegung von fotowand. Setzt tokens.css voraus.
 *
 * Drei Regeln (ausführlich in docs/DESIGN.md, Abschnitt Bewegung):
 *  1. Bewegung erklärt, was passiert – ein Foto kommt an, ein Upload ist fertig.
 *     Sie schmückt nicht.
 *  2. Nichts wartet auf eine Animation. Der Upload startet beim Tippen, das Foto steht
 *     in der Diashow, auch wenn die Animation abbricht. Deshalb animiert jede Klasse
 *     hier nur transform, opacity und filter und endet im Ruhezustand des Elements.
 *  3. Wer weniger Bewegung eingestellt hat, bekommt Überblendungen statt Flug.
 *     Das gilt für die Systemeinstellung und für data-motion="reduced" am <html>,
 *     damit Gastgeber es für eine Leinwand auch ausdrücklich abschalten können.
 */

/*
 * Neigung: Elemente tragen ihre Neigung über die eigenständige Eigenschaft `rotate`,
 * nicht über `transform`. So können die Animationen `transform` frei benutzen und
 * enden trotzdem in der richtigen Schräglage – auch wenn sie abbrechen oder bei
 * weniger Bewegung gar nicht laufen.
 */
.fw-tilt {
  rotate: var(--fw-tilt, 0deg);
}

/* ---------- Rückmeldung auf Druck ---------- */

.fw-pressable {
  transition: transform var(--duration-instant) var(--ease-standard),
              box-shadow var(--duration-fast) var(--ease-standard);
}
.fw-pressable:active {
  transform: scale(0.97);
}
.fw-pressable:focus-visible {
  /* Durchsichtig statt `none`: Im Kontrastmodus von Windows fehlt sonst jeder Fokus. */
  outline: 2px solid transparent;
  outline-offset: 2px;
  box-shadow: var(--focus-ring);
}

/* ---------- Gästeseite ---------- */

/* Vorschau erscheint sofort nach der Auswahl, noch bevor der Upload läuft. */
@keyframes fw-pop-in {
  0%   { opacity: 0; transform: scale(0.6); }
  100% { opacity: 1; transform: none; }
}
.fw-pop-in {
  animation: fw-pop-in var(--duration-base) var(--ease-spring) both;
}

/* Fortschritt: die Breite kommt als Variable, die Animation glättet die Sprünge. */
.fw-progress {
  transform-origin: left center;
  transform: scaleX(var(--fw-progress, 0));
  transition: transform var(--duration-base) var(--ease-standard);
}

/* Häkchen zeichnet sich, wenn das Foto angekommen ist. Pfad braucht pathLength="1". */
@keyframes fw-check-draw {
  from { stroke-dashoffset: 1; }
  to   { stroke-dashoffset: 0; }
}
.fw-check-draw {
  stroke-dasharray: 1;
  animation: fw-check-draw var(--duration-base) var(--ease-out) both;
}

/* Fehler: ein kurzes Kopfschütteln, einmal. Nie in Schleife – das wäre Alarm, kein Hinweis. */
@keyframes fw-shake {
  0%, 100% { transform: none; }
  20%      { transform: translateX(-5px); }
  40%      { transform: translateX(4px); }
  60%      { transform: translateX(-3px); }
  80%      { transform: translateX(2px); }
}
.fw-shake {
  animation: fw-shake 360ms var(--ease-standard) both;
}

/* Hinweise und Leisten schieben sich von unten herein. */
@keyframes fw-rise {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}
.fw-rise {
  animation: fw-rise var(--duration-base) var(--ease-out) both;
}

/* ---------- Fotokarte ---------- */

/*
 * Die Fotokarte landet: von oben, gegen ihre Neigung verdreht, und setzt mit einer
 * Feder auf. Zusammen mit .fw-tilt (Neigung zwischen -5deg und 5deg).
 */
@keyframes fw-card-land {
  0%   { opacity: 0; transform: translateY(-48px) rotate(calc(var(--fw-tilt, 0deg) * -2.4)) scale(1.08); }
  35%  { opacity: 1; }
  100% { opacity: 1; transform: none; }
}
.fw-card-land {
  animation: fw-card-land var(--duration-slow) var(--ease-spring) both;
}

/* ---------- Live-Signale ---------- */

@keyframes fw-live-pulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, currentColor 55%, transparent); }
  70%  { box-shadow: 0 0 0 10px color-mix(in srgb, currentColor 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, currentColor 0%, transparent); }
}
.fw-live-dot {
  width: 10px;
  height: 10px;
  border-radius: var(--radius-pill);
  background: currentColor;
  animation: fw-live-pulse 2s var(--ease-out) infinite;
}

/* Zähler springt kurz, wenn ein Foto dazukommt. Klasse nach jedem Zuwachs neu setzen. */
@keyframes fw-count-bump {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.14); }
  100% { transform: scale(1); }
}
.fw-count-bump {
  display: inline-block;
  animation: fw-count-bump var(--duration-base) var(--ease-spring);
}

/* ---------- Diashow: Bildwechsel je Theme ---------- */

/* Sehr langsame Verschiebung schützt Tafeln vor Einbrennen; reduziert bleibt sie statisch. */
@keyframes fw-screen-drift {
  from { transform: translate(0, 0); }
  to { transform: translate(var(--space-3), var(--space-2)); }
}
.fw-show-drift { animation: fw-screen-drift var(--duration-screen-drift) linear infinite alternate; }
@media (prefers-reduced-motion: reduce) { .fw-show-drift { animation: none; } }
:root[data-motion="reduced"] .fw-show-drift { animation: none; }

/* Klassisch: ruhige Überblendung, dann langsames Heranzoomen, solange das Foto steht. */
@keyframes fw-show-classic-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes fw-show-drift {
  from { transform: scale(1); }
  to   { transform: scale(1.06); }
}
[data-show-theme="klassisch"] .fw-slide-enter {
  animation: fw-show-classic-in var(--duration-slide) var(--ease-standard) both;
}
/* Nur das Bild (erstes Kind) zoomt – Rahmen und Namensschild bleiben, wo sie sind. */
[data-show-theme="klassisch"] .fw-slide-enter > :first-child {
  animation: fw-show-drift var(--duration-drift) linear both;
}
[data-show-theme="klassisch"] .fw-slide-exit {
  animation: fw-fade-out var(--duration-slide) var(--ease-standard) both;
}
[data-show-theme="klassisch"] .fw-slide-exit > :first-child {
  /* Das gehende Foto bleibt auf dem Zoom stehen, den es erreicht hat – sonst springt es. */
  transform: scale(1.06);
}

/* Album: die neue Karte fliegt ein, die alte rutscht zur Seite auf den Stapel. */
@keyframes fw-show-album-in {
  0%   { opacity: 0; transform: translate(60px, 90px) rotate(14deg) scale(0.9); }
  60%  { opacity: 1; }
  100% { opacity: 1; transform: none; }
}
@keyframes fw-show-album-out {
  from { transform: none; filter: brightness(1); }
  to   { transform: translate(-360px, 30px) rotate(-11deg) scale(0.82); filter: brightness(0.55); }
}
[data-show-theme="album"] .fw-slide-enter {
  animation: fw-show-album-in 1100ms var(--ease-spring) both;
}
[data-show-theme="album"] .fw-slide-exit {
  animation: fw-show-album-out 1100ms var(--ease-standard) both;
}

/* Party: harter Einschlag mit kurzem Aufblitzen – schnell, laut, einmal. */
@keyframes fw-show-party-in {
  0%   { opacity: 0; transform: scale(1.22); filter: brightness(1.9) saturate(1.3); }
  30%  { opacity: 1; }
  100% { opacity: 1; transform: scale(1); filter: brightness(1) saturate(1); }
}
@keyframes fw-show-party-out {
  from { opacity: 1; transform: scale(1); }
  to   { opacity: 0; transform: scale(0.94); }
}
[data-show-theme="party"] .fw-slide-enter {
  animation: fw-show-party-in 520ms var(--ease-out) both;
}
[data-show-theme="party"] .fw-slide-exit {
  animation: fw-show-party-out 360ms var(--ease-in) both;
}

@keyframes fw-fade-in  { from { opacity: 0; } to { opacity: 1; } }
@keyframes fw-fade-out { from { opacity: 1; } to { opacity: 0; } }

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

/*
 * Alles, was fliegt, dreht, springt oder pulsiert, wird zur Überblendung oder steht
 * still. Die Information bleibt erhalten: Ein fertiger Upload zeigt sein Häkchen,
 * nur ohne Zeichnen.
 */
@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion="full"]) .fw-pop-in,
  :root:not([data-motion="full"]) .fw-rise,
  :root:not([data-motion="full"]) .fw-card-land,
  :root:not([data-motion="full"]) [data-show-theme] .fw-slide-enter {
    animation: fw-fade-in var(--duration-base) linear both;
  }
  :root:not([data-motion="full"]) [data-show-theme] .fw-slide-exit {
    transform: none;
    animation: fw-fade-out var(--duration-base) linear both;
  }
  :root:not([data-motion="full"]) [data-show-theme] .fw-slide-enter > :first-child,
  :root:not([data-motion="full"]) [data-show-theme] .fw-slide-exit > :first-child {
    transform: none;
    animation: none;
  }
  :root:not([data-motion="full"]) .fw-shake,
  :root:not([data-motion="full"]) .fw-count-bump,
  :root:not([data-motion="full"]) .fw-live-dot,
  :root:not([data-motion="full"]) .fw-check-draw {
    animation: none;
    stroke-dashoffset: 0;
  }
  :root:not([data-motion="full"]) .fw-pressable,
  :root:not([data-motion="full"]) .fw-progress {
    transition: none;
  }
}

:root[data-motion="reduced"] .fw-pop-in,
:root[data-motion="reduced"] .fw-rise,
:root[data-motion="reduced"] .fw-card-land,
:root[data-motion="reduced"] [data-show-theme] .fw-slide-enter {
  animation: fw-fade-in var(--duration-base) linear both;
}
:root[data-motion="reduced"] [data-show-theme] .fw-slide-exit {
  transform: none;
  animation: fw-fade-out var(--duration-base) linear both;
}
:root[data-motion="reduced"] [data-show-theme] .fw-slide-enter > :first-child,
:root[data-motion="reduced"] [data-show-theme] .fw-slide-exit > :first-child {
  transform: none;
  animation: none;
}
:root[data-motion="reduced"] .fw-shake,
:root[data-motion="reduced"] .fw-count-bump,
:root[data-motion="reduced"] .fw-live-dot,
:root[data-motion="reduced"] .fw-check-draw {
  animation: none;
  stroke-dashoffset: 0;
}
:root[data-motion="reduced"] .fw-pressable,
:root[data-motion="reduced"] .fw-progress {
  transition: none;
}
