/* =====================================================================
   ViewVault · Animationen                                    v1 · 10/2026
   ---------------------------------------------------------------------
   Einbinden im <head> JEDER Seite, NACH deiner eigenen CSS-Datei:

     <link rel="stylesheet" href="/animationen.css?v=1">
     <script src="/animationen.js?v=1"></script>

   · Element von allen Animationen ausnehmen:  data-keine-animation
   · Zahl hochzählen lassen:  data-zaehlen  ·  verhindern: data-nicht-zaehlen
   · Wer im Betriebssystem „Animationen reduzieren“ eingeschaltet hat,
     bekommt automatisch eine ruhige Version ohne Bewegung.
   ===================================================================== */


/* ---------------------------------------------------------------------
   0 · Stellschrauben
   --vv-akzent übernimmt automatisch deine Akzentfarbe, wenn deine
   Variable --akzent, --accent oder --color-accent heißt.
   Sonst: den Farbwert ganz rechts durch dein Rot ersetzen.
   --------------------------------------------------------------------- */
:root {
  --vv-akzent: var(--akzent, var(--accent, var(--color-accent, #b4483c)));
  --vv-licht: #f6e6cf;                        /* warmes Projektorlicht */
  --vv-feder: cubic-bezier(.2, .8, .2, 1);
  --vv-sanft: cubic-bezier(.16, 1, .3, 1);
}


/* ---------------------------------------------------------------------
   1 · Seitenwechsel
   Chrome, Edge, Safari: alte Seite dimmt weg, neue blendet auf,
   Kopfzeile bleibt stehen, angeklicktes Poster fliegt auf die neue Seite.
   Firefox: neue Seite gleitet herein (Abschnitt 2).
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }

  ::view-transition-old(root) {
    animation: vv-vt-raus 220ms cubic-bezier(.4, 0, 1, 1) both;
  }
  ::view-transition-new(root) {
    animation: vv-vt-rein 340ms cubic-bezier(.16, 1, .3, 1) 90ms both;
  }

  /* Kopfzeile bleibt stehen */
  ::view-transition-old(vv-kopf),
  ::view-transition-new(vv-kopf) { animation: none; mix-blend-mode: normal; }
  ::view-transition-old(vv-kopf) { opacity: 0; }
  ::view-transition-old(vv-kopf):only-child {
    opacity: 1;
    animation: vv-vt-raus 220ms ease-in both;
  }

  /* Poster-Flug */
  ::view-transition-group(vv-poster) {
    animation-duration: 520ms;
    animation-timing-function: cubic-bezier(.2, .8, .2, 1);
  }
  ::view-transition-old(vv-poster),
  ::view-transition-new(vv-poster) {
    mix-blend-mode: normal;
    height: 100%;
    object-fit: cover;
  }
  ::view-transition-old(vv-poster) { animation: none; }
  ::view-transition-new(vv-poster) { animation: vv-blende 520ms ease both; }
}

/* Poster reservieren ihren Platz schon vor dem Laden (kein Springen,
   und der Poster-Flug weiß, wohin er fliegen soll). Nach dem Laden gilt
   wieder das echte Seitenverhältnis des Bildes. */
:where(img[src*="/t/p/w92/"], img[src*="/t/p/w154/"], img[src*="/t/p/w185/"],
       img[src*="/t/p/w342/"], img[src*="/t/p/w500/"]) {
  aspect-ratio: auto 2 / 3;
}


/* ---------------------------------------------------------------------
   2 · Seiteneintritt und Einblenden beim Scrollen
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  :where(html) { scroll-behavior: smooth; }

  /* Inhalt gleitet gestaffelt herein */
  .vv-eintritt main > :not(script, style, template) {
    animation: vv-hoch 560ms var(--vv-sanft) 40ms backwards;
  }
  .vv-eintritt main > :nth-child(2)    { animation-delay: 100ms; }
  .vv-eintritt main > :nth-child(3)    { animation-delay: 160ms; }
  .vv-eintritt main > :nth-child(4)    { animation-delay: 220ms; }
  .vv-eintritt main > :nth-child(5)    { animation-delay: 280ms; }
  .vv-eintritt main > :nth-child(n+6)  { animation-delay: 330ms; }

  /* Seiten ohne <main>: alles außer der Kopfzeile */
  .vv-eintritt body:not(:has(main)) > :not(script, style, template, header, nav, [role="banner"], .vv-ladebalken, .vv-licht) {
    animation: vv-hoch 560ms var(--vv-sanft) 40ms backwards;
  }

  /* Weiter unten: erscheint erst, wenn man hinscrollt */
  .vv-verborgen { opacity: 0; }
  .vv-js .vv-erscheint {
    animation: vv-hoch 640ms var(--vv-sanft) var(--vv-v, 0ms) backwards;
  }
  .vv-js tr.vv-erscheint { animation-name: vv-blende; }
}


/* ---------------------------------------------------------------------
   3 · Knöpfe
   Heben sich beim Drüberfahren, leuchten im Akzent, ein Lichtstreif
   zieht drüber, beim Klicken geben sie nach.
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  :is(button, input[type="submit"], input[type="button"], input[type="reset"], [role="button"], .vv-knopf):not(:disabled, [aria-disabled="true"], [data-keine-animation]) {
    transition:
      translate 220ms var(--vv-feder),
      scale 160ms var(--vv-feder),
      filter 260ms ease,
      background-color 200ms ease,
      border-color 200ms ease,
      color 200ms ease,
      box-shadow 260ms ease,
      opacity 200ms ease;
  }

  @media (hover: hover) and (pointer: fine) {
    :is(button, input[type="submit"], input[type="button"], input[type="reset"], [role="button"], .vv-knopf):not(:disabled, [aria-disabled="true"], [data-keine-animation]):hover {
      translate: 0 -2px;
      filter: drop-shadow(0 6px 14px color-mix(in srgb, var(--vv-akzent) 40%, transparent));
    }
  }

  :is(button, input[type="submit"], input[type="button"], input[type="reset"], [role="button"], .vv-knopf):not(:disabled, [aria-disabled="true"], [data-keine-animation]):active {
    translate: 0 0;
    scale: .96;
    transition-duration: 90ms;
  }

  /* Lichtstreif */
  .vv-relativ { position: relative; }
  .vv-glanz::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    background: linear-gradient(105deg,
      transparent 38%,
      color-mix(in srgb, var(--vv-licht) 30%, transparent) 50%,
      transparent 62%) no-repeat;
    background-size: 260% 100%;
    background-position: 130% 0;
    opacity: 0;
    transition: opacity 200ms ease;
  }
  @media (hover: hover) and (pointer: fine) {
    .vv-glanz:not(:disabled):hover::after {
      opacity: 1;
      background-position: -30% 0;
      transition: background-position 750ms var(--vv-sanft), opacity 120ms ease;
    }
  }
}


/* ---------------------------------------------------------------------
   4 · Links
   Navigation: Akzent-Linie gleitet von unten herein.
   Links im Fließtext: Unterstreichung rückt näher und färbt sich.
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  .vv-js a.vv-navlink {
    text-decoration-line: underline;
    text-decoration-color: transparent;
    text-decoration-thickness: 2px;
    text-underline-offset: .65em;
  }
  .vv-js a.vv-navlink.vv-bereit {
    transition:
      text-decoration-color 260ms ease,
      text-underline-offset 260ms var(--vv-feder),
      color 200ms ease;
  }
  .vv-js a.vv-navlink[aria-current="page"] {
    text-decoration-color: var(--vv-akzent);
    text-underline-offset: .38em;
  }

  :is(p, li, dd, blockquote, figcaption) > a:not([class]) {
    transition:
      color 200ms ease,
      text-decoration-color 200ms ease,
      text-underline-offset 200ms var(--vv-feder);
  }

  @media (hover: hover) and (pointer: fine) {
    .vv-js a.vv-navlink:hover {
      text-decoration-color: var(--vv-akzent);
      text-underline-offset: .38em;
    }
    :is(p, li, dd, blockquote, figcaption) > a:not([class]):hover {
      text-decoration-color: var(--vv-akzent);
      text-underline-offset: .3em;
    }
  }

  /* Kopfzeile bekommt beim Scrollen Tiefe (nur wenn sie oben klebt) */
  :where(.vv-kopfzeile) { transition: box-shadow 300ms ease; }
}
.vv-gescrollt .vv-kopfzeile {
  box-shadow: 0 14px 30px -20px rgb(0 0 0 / .9);
}


/* ---------------------------------------------------------------------
   5 · Poster
   Blenden weich auf, sobald geladen. Beim Drüberfahren heben sie sich,
   werden heller, kippen leicht zur Maus, ein Lichtreflex folgt.
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  img.vv-laedt-bild { opacity: 0; }
  img.vv-bild-ein  { animation: vv-bild 650ms var(--vv-sanft) backwards; }

  .vv-karte {
    transition:
      translate 380ms var(--vv-feder),
      scale 380ms var(--vv-feder),
      filter 380ms ease,
      transform 550ms var(--vv-feder);
  }
  .vv-karte:active { scale: .985; }

  .vv-glanzkarte::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: var(--vv-radius, 0);
    pointer-events: none;
    opacity: 0;
    background: radial-gradient(circle at var(--vv-gx, 50%) var(--vv-gy, 0%),
      color-mix(in srgb, var(--vv-licht) 26%, transparent),
      transparent 60%);
    transition: opacity 320ms ease;
  }

  @media (hover: hover) and (pointer: fine) {
    .vv-karte:hover {
      z-index: 2;
      translate: 0 -6px;
      scale: 1.035;
      filter: brightness(1.08) drop-shadow(0 16px 22px rgb(0 0 0 / .5));
      transform: perspective(900px) rotateX(var(--vv-kx, 0deg)) rotateY(var(--vv-ky, 0deg));
      transition:
        translate 380ms var(--vv-feder),
        scale 380ms var(--vv-feder),
        filter 380ms ease,
        transform 140ms linear;
    }
    .vv-glanzkarte:hover::after { opacity: 1; }

    /* In seitlich scrollenden Reihen: nicht anheben (würde abgeschnitten) */
    .vv-karte.vv-flach:hover {
      translate: none;
      scale: none;
      filter: brightness(1.1);
    }
  }
}


/* ---------------------------------------------------------------------
   6 · Formulare
   Felder leuchten beim Reinklicken im Akzent; Häkchen und Sterne
   „ploppen“ beim Auswählen.
   --------------------------------------------------------------------- */
:is(input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="submit"], [type="button"], [type="reset"], [type="hidden"], [type="color"], [type="image"]), textarea, select):focus {
  box-shadow:
    0 0 0 3px color-mix(in srgb, var(--vv-akzent) 28%, transparent),
    0 0 22px -6px color-mix(in srgb, var(--vv-akzent) 55%, transparent);
}
@media (prefers-reduced-motion: no-preference) {
  :is(input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"], [type="submit"], [type="button"], [type="reset"], [type="hidden"], [type="color"], [type="image"]), textarea, select) {
    transition: border-color 200ms ease, box-shadow 280ms ease, background-color 200ms ease;
  }
  .vv-pop { animation: vv-pop 380ms var(--vv-feder); }
}


/* ---------------------------------------------------------------------
   7 · Meldungen, Dialoge, Aufklapper
   --------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
  :is([role="alert"], .alert, .flash, .meldung, .toast, .fehler, .erfolg) {
    animation: vv-meldung 480ms var(--vv-feder) backwards;
  }
  dialog[open] { animation: vv-dialog 320ms var(--vv-feder); }
  dialog[open]::backdrop { animation: vv-blende 320ms ease; }
  details[open] > :not(summary) { animation: vv-hoch-klein 320ms var(--vv-sanft); }
}


/* ---------------------------------------------------------------------
   8 · Ladebalken und Lichtkegel
   Ladebalken: dünner Lichtstreif oben, solange die nächste Seite lädt
   oder etwas gespeichert wird.
   Lichtkegel: sehr schwaches, warmes Licht folgt der Maus im Hintergrund.
   --------------------------------------------------------------------- */
.vv-ladebalken {
  position: fixed;
  inset: 0 0 auto 0;
  height: 2px;
  z-index: 2147483000;
  pointer-events: none;
  opacity: 0;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--vv-akzent) 25%, transparent),
    var(--vv-akzent) 55%,
    var(--vv-licht));
  box-shadow: 0 0 12px 1px color-mix(in srgb, var(--vv-akzent) 70%, transparent);
}
.vv-laedt .vv-ladebalken {
  opacity: 1;
  transform: scaleX(.86);
  transition: transform 9s cubic-bezier(.08, .82, .17, 1), opacity 150ms ease;
}
.vv-geladen .vv-ladebalken {
  opacity: 0;
  transform: scaleX(1);
  transition: transform 220ms ease-out, opacity 300ms ease 180ms;
}

.vv-licht {
  position: fixed;
  left: 0;
  top: 0;
  width: 900px;
  height: 900px;
  margin: -450px 0 0 -450px;
  border-radius: 50%;
  z-index: -1;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(closest-side,
    color-mix(in srgb, var(--vv-licht) 8%, transparent),
    transparent);
  transition: opacity 800ms ease;
  will-change: transform;
}
.vv-licht.vv-an { opacity: 1; }


/* ---------------------------------------------------------------------
   9 · Bewegungsabläufe
   (translate/scale statt transform: so bleiben eigene Transforms
   deiner Seite unangetastet)
   --------------------------------------------------------------------- */
@keyframes vv-hoch       { from { opacity: 0; translate: 0 16px; } }
@keyframes vv-hoch-klein { from { opacity: 0; translate: 0 -6px; } }
@keyframes vv-blende     { from { opacity: 0; } }
@keyframes vv-bild       { from { opacity: 0; scale: 1.04; filter: blur(6px); } }
@keyframes vv-meldung    { from { opacity: 0; translate: 0 -12px; } }
@keyframes vv-dialog     { from { opacity: 0; translate: 0 14px; scale: .97; } }
@keyframes vv-pop        { 0%, 100% { scale: 1; } 40% { scale: 1.25; } }
@keyframes vv-vt-raus    { to { opacity: 0; transform: scale(.985); filter: brightness(.7); } }
@keyframes vv-vt-rein    { from { opacity: 0; } }


/* ---------------------------------------------------------------------
   10 · Drucken: alles sichtbar, nichts Bewegtes
   --------------------------------------------------------------------- */
@media print {
  .vv-verborgen { opacity: 1 !important; }
  .vv-ladebalken, .vv-licht { display: none !important; }
}
