/* ============================================================
   muveup Facelift: Motion
   Seitenübergang (View Transitions), Einblenden, gestaffelte Karten, Skeleton-Schimmer.
   Reduzierte Bewegung: Block am Dateiende, nur Deckkraft (design/MOTION.md, Prinzip 7).
   ============================================================ */

/* ---------- Seitenübergang zwischen Dokumenten (Chrome, Edge, Safari 18.2+) ----------
   Topbar, Bottom-Nav und Sidebar stehen still, der Inhalt schiebt: vorwärts nach links, zurück nach rechts.
   Sidebar, Reiter, Hauptkarte und rechte Spalte bekommen ihren Namen nur während des Wechsels (js/ui/vt-nav.js). */
@view-transition {
  navigation: auto;
}

.mu-topbar { view-transition-name: mu-topbar; }

@media (max-width: 900px) {
  .mu-bottom-nav { view-transition-name: mu-bottom-nav; }
}

::view-transition-group(mu-topbar),
::view-transition-group(mu-bottom-nav),
::view-transition-group(mu-sidebar) {
  animation: none;
}

::view-transition-old(mu-topbar),
::view-transition-new(mu-topbar),
::view-transition-old(mu-bottom-nav),
::view-transition-new(mu-bottom-nav),
::view-transition-old(mu-sidebar),
::view-transition-new(mu-sidebar) {
  animation: none;
}

::view-transition-old(mu-topbar),
::view-transition-old(mu-bottom-nav),
::view-transition-old(mu-sidebar) {
  display: none;
}

/* Die alte Fläche bleibt deckend stehen, die neue blendet darüber ein. Zwei gleichzeitige Blenden mit
   verschiedenen Kurven ließen den Seitenhintergrund kurz aufhellen, das wirkte als Flackern. */
::view-transition-old(root),
::view-transition-new(root) {
  mix-blend-mode: normal;
}

::view-transition-old(root) {
  animation: none;
}

::view-transition-new(root) {
  animation: mu-fade-in var(--dur-base) var(--ease-out) both;
}

::view-transition-group(mu-main),
::view-transition-group(mu-aside),
::view-transition-group(mu-tab),
::view-transition-group(mu-hero) {
  animation-duration: var(--dur-page);
  animation-timing-function: var(--ease-spring);
  overflow: clip;
}

::view-transition-old(mu-main),
::view-transition-old(mu-aside) {
  animation: mu-page-out-left var(--dur-fast) var(--ease-out) both;
}

::view-transition-new(mu-main),
::view-transition-new(mu-aside) {
  animation: mu-page-in-right var(--dur-page) var(--ease-out) both;
}

html:active-view-transition-type(mu-back, mu-tab-prev)::view-transition-old(mu-main),
html:active-view-transition-type(mu-back, mu-tab-prev)::view-transition-old(mu-aside) {
  animation-name: mu-page-out-right;
}

html:active-view-transition-type(mu-back, mu-tab-prev)::view-transition-new(mu-main),
html:active-view-transition-type(mu-back, mu-tab-prev)::view-transition-new(mu-aside) {
  animation-name: mu-page-in-left;
}

@keyframes mu-page-out-left { to { opacity: 0; transform: translateX(calc(-1 * var(--shift-page))); } }
@keyframes mu-page-in-right { from { opacity: 0; transform: translateX(var(--shift-page)); } }
@keyframes mu-page-out-right { to { opacity: 0; transform: translateX(var(--shift-page)); } }
@keyframes mu-page-in-left { from { opacity: 0; transform: translateX(calc(-1 * var(--shift-page))); } }

/* Fallback ohne View Transitions (js/ui/motion.js setzt die Klasse) */
.mu-page-enter .mu-page {
  animation: mu-rise-in var(--dur-page) var(--ease-out) both;
}

/* ---------- Bausteine ---------- */
.mu-fade-in {
  animation: mu-fade-in var(--dur-base) var(--ease-out) both;
}

.mu-rise-in {
  animation: mu-rise-in var(--dur-slow) var(--ease-spring) both;
}

.mu-pop-in {
  animation: mu-pop-in var(--dur-slow) var(--ease-spring) both;
}

/* Gestaffelt: Container bekommt .mu-stagger, js/ui/motion.js setzt --mu-i je Kind */
.mu-stagger > * {
  animation: mu-rise-in var(--dur-slow) var(--ease-spring) both;
  animation-delay: calc(var(--mu-i, 0) * var(--stagger));
}

/* Unschärfe für angedeutete Folgeinhalte, wird beim Scrollen scharf */
.mu-soft-blur {
  filter: var(--blur-soft);
  transition: filter var(--dur-slow) var(--ease-out);
}

.mu-soft-blur.is-in-view {
  filter: none;
}

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

@keyframes mu-fade-out {
  to { opacity: 0; }
}

@keyframes mu-rise-in {
  from { opacity: 0; transform: translateY(var(--shift-rise)); }
}

@keyframes mu-pop-in {
  from { opacity: 0; transform: scale(0.94); }
}

/* ---------- Schritte seitlich (MuveupMotion.step) ---------- */
@keyframes mu-slide-in-right {
  from { opacity: 0; transform: translateX(var(--shift-step)); }
}

@keyframes mu-slide-in-left {
  from { opacity: 0; transform: translateX(calc(-1 * var(--shift-step))); }
}

.mu-step-next {
  animation: mu-slide-in-right var(--dur-base) var(--ease-out) both;
}

.mu-step-prev {
  animation: mu-slide-in-left var(--dur-base) var(--ease-out) both;
}

/* ---------- Skeleton (js/ui/skeleton.js) ---------- */
/* Ein noch leerer Kalender zeigt von Anfang an dieselbe Fläche */
.mu-skel,
.mu-cal-frame > :empty {
  position: relative;
  display: block;
  overflow: hidden;
  border-radius: var(--r-xs);
  background: var(--color-surface-muted);
}

/* Schimmer nur mit transform, läuft auf dem Compositor */
.mu-skel::after, .mu-cal-frame > :empty::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--g-skeleton-sweep);
  transform: translateX(-100%);
  animation: mu-sweep var(--dur-sweep) var(--ease-in-out) infinite;
}

@keyframes mu-sweep {
  to { transform: translateX(100%); }
}

.mu-skel--text { height: 12px; width: 100%; border-radius: var(--r-pill); }
.mu-skel--text-sm { height: 10px; width: 60%; border-radius: var(--r-pill); }
.mu-skel--title { height: 20px; width: 45%; border-radius: var(--r-pill); }
.mu-skel--circle { width: 40px; height: 40px; border-radius: var(--r-round); flex: none; }
.mu-skel--avatar-lg { width: 96px; height: 96px; border-radius: var(--avatar-radius); flex: none; }
.mu-skel--pill { height: var(--control-h); width: 92px; border-radius: var(--r-pill); }
.mu-skel--block { width: 100%; }
.mu-skel--tile { height: 105px; border-radius: var(--r-md); }
.mu-skel--media { flex: 1 1 0; min-height: 0; border-radius: 0; }
.mu-skel--frame { aspect-ratio: 16 / 9; border-radius: var(--r-md); }
.mu-skel--date { width: 46px; height: 46px; flex: none; }
.mu-skel--name { width: 30%; height: 1lh; border-radius: var(--r-md); }
.mu-skel--chip { width: 76px; height: 26px; border-radius: var(--r-pill); }

.mu-skel-card {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-5);
  border-radius: var(--r-lg);
  background: var(--color-surface);
}

/* Skelett der Profilkarten hell wie alle Skelette, erst die fertige Karte ist dunkel (F24t Punkt 89, Danie):
   Vorschläge, Musikprofil, Direktanfrage, Einladung im Dashboard, Hörrunden im Onboarding. Die fertige Karte blendet
   über .mu-content-in (js/ui/skeleton.js) ruhig ein */
.mu-skel-artist {
  display: flex;
  flex-direction: column;
  width: var(--artist-card-w);
  height: var(--artist-card-h);
  max-width: 100%;
  border-radius: var(--r-xl);
  overflow: hidden;
  background: var(--color-surface);
  box-shadow: inset 0 0 0 var(--bw) var(--color-border);
}

/* Auf dunklen Flächen dunkel (F24t Punkt 119, Danie): das Skelett richtet sich nach dem Grund, auf dem es liegt.
   Einladung im Dashboard (dunkle Karte mit Konzertfoto) automatisch, sonst mit .mu-skel-artist--dark.
   Fläche wie die fertige Karte, Teile und Schimmer dezent heller. Die fertigen Karten blenden wie bisher ruhig ein
   (Einladung über .is-entering am Karussell) */
:is(.mu-skel-artist--dark, .mu-events-cta .mu-skel-artist) {
  background: var(--c-ink);
  box-shadow: inset 0 0 0 var(--bw) rgb(var(--c-white-rgb) / 0.08);
}
:is(.mu-skel-artist--dark, .mu-events-cta .mu-skel-artist) .mu-skel { background: rgb(var(--c-white-rgb) / 0.08); }
:is(.mu-skel-artist--dark, .mu-events-cta .mu-skel-artist) .mu-skel::after { background: var(--g-skeleton-sweep-dark); }

.mu-skel-artist__body {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4) var(--sp-4);
}

.mu-skel-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-2) 0;
}

.mu-skel-row__lines {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: var(--sp-2);
}

.mu-skel-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: var(--sp-4);
}

/* Balken im Monatsraster (MuveupCalendar.skeleton) */
.mu-cal--mini .mu-skel--text { height: 5px; }

/* Spalte des öffentlichen Profils, am Desktop so hoch wie die gefüllte Spalte */
.mu-skel-pp-col {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}
@media (min-width: 901px) {
  .mu-skel-pp-col { min-height: 215px; }
}

/* Skelett erst nach --delay-skel, schnelle Antworten zeigen kein Aufblitzen */
[aria-busy="true"] > [data-mu-skel] {
  animation: mu-fade-in var(--dur-base) var(--ease-out) var(--delay-skel) both;
}

/* Inhalt nach einem sichtbaren Skelett (js/ui/skeleton.js) */
.mu-content-in {
  animation: mu-fade-in var(--dur-base) var(--ease-out) both;
}

/* ---------- Besondere Momente (F21b): höchstens einer pro Ablauf ----------
   .mu-moment am Symbol eines Erfolgs (Dialog, Toast): Symbol springt leicht auf, der Haken zeichnet sich,
   ein Ring läuft einmal aus. Eingesetzt beim Fixieren und Buchen. Der Haken braucht pathLength="1". */
.mu-moment {
  position: relative;
  animation: mu-pop-in var(--dur-slow) var(--ease-pop) var(--dur-fast) both;
}

.mu-moment::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: 0 0 0 2px var(--color-success);
  opacity: 0;
  pointer-events: none;
  animation: mu-moment-ring var(--dur-moment) var(--ease-out) var(--dur-base) both;
}

.mu-moment path[pathLength] {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: mu-moment-check var(--dur-base) var(--ease-out) var(--dur-base) forwards;
}

@keyframes mu-moment-ring {
  from { opacity: 0.5; transform: scale(1); }
  to { opacity: 0; transform: scale(1.9); }
}

@keyframes mu-moment-check {
  to { stroke-dashoffset: 0; }
}

/* Konfetti beim ersten fixierten Gig (MuveupMotion.confetti). Fliegt aus der Mitte des Symbols,
   nachdem der Haken gezeichnet ist, und fällt leicht. Ohne Wirkung auf das Layout. */
.mu-confetti {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  pointer-events: none;
}

.mu-confetti__bit {
  position: absolute;
  width: 6px;
  height: 10px;
  margin: -5px 0 0 -3px;
  border-radius: 1px;
  background: var(--color-accent);
  opacity: 0;
  animation: mu-confetti-fly var(--dur-confetti) var(--ease-out) calc(var(--dur-base) + var(--d, 0ms)) forwards;
}

.mu-confetti__bit--2 { background: var(--color-primary); }
.mu-confetti__bit--3 { background: var(--c-purple-300); }
.mu-confetti__bit--4 { background: var(--c-orange-300); }

@keyframes mu-confetti-fly {
  0% { opacity: 1; transform: translate(0, 0) rotate(0deg) scale(0.5); }
  70% { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--x), var(--y)) rotate(var(--r)) scale(1); }
}

/* Karten fächern aus dem Stapel auf (Ende des Onboardings). Nur der Anfang ist festgelegt,
   jede Karte landet in ihrer eigenen Lage aus dem Seiten-CSS. */
.mu-deal > * {
  animation: mu-deal-in var(--dur-slow) var(--ease-spring) both;
}

.mu-deal > :nth-child(2) { animation-delay: calc(2 * var(--stagger)); }
.mu-deal > :nth-child(3) { animation-delay: calc(4 * var(--stagger)); }
.mu-deal > :nth-child(n + 4) { animation-delay: calc(6 * var(--stagger)); }

@keyframes mu-deal-in {
  from { opacity: 0; transform: translateY(var(--shift-rise)) scale(0.96); }
}

/* Reduzierte Bewegung: nur Deckkraft, kein Weg, kein Skalieren, kein Schimmer.
   Gewinnt gegen die 1-ms-Regel aus base.css, weil Klassen spezifischer sind als der Stern. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --shift-rise: 0px;
    --shift-page: 0px;
    --shift-step: 0px;
  }

  .mu-rise-in,
  .mu-pop-in,
  .mu-fade-in,
  .mu-content-in,
  .mu-stagger > * {
    animation-name: mu-fade-in !important;
    animation-duration: var(--dur-base) !important;
  }

  .mu-skel::after, .mu-cal-frame > :empty::after {
    display: none;
  }

  /* Momente: Symbol und Karten nur einblenden, Haken steht sofort, kein Ring */
  .mu-moment,
  .mu-deal > * {
    animation-name: mu-fade-in !important;
    animation-duration: var(--dur-base) !important;
  }

  .mu-moment::after,
  .mu-confetti {
    display: none;
  }

  .mu-moment path[pathLength] {
    animation: none !important;
    stroke-dashoffset: 0;
  }

  :root {
    --press-scale: 1;
    --press-scale-sm: 1;
    --press-scale-lg: 1;
  }

  .mu-soft-blur {
    filter: none;
  }

  ::view-transition-group(*) {
    animation: none !important;
  }

  ::view-transition-old(*) {
    animation: mu-fade-out var(--dur-fast) linear both !important;
  }

  ::view-transition-new(*) {
    animation: mu-fade-in var(--dur-base) linear both !important;
  }
}
