/* ═══════════════════════════════════════════════════════════════════
   MOTION – Bewegungsebene für die Sonderkarten
   -----------------------------------------------------------------
   Gehört zu public/js/motion.js. Präfix dm- (Dampfstich Motion), neben
   wz- (wizard-motion.css) für die Bewegungen des Spielbretts. Das
   frühere cs- (card-scenes.css) ist am 02.08.2026 entfallen.

   Zwei Regeln, die hier ausnahmslos gelten:
    • Animiert werden NUR transform und opacity. Alles andere kostet
      Layout oder Paint; bei 23 Handkarten und laufender Szene ist das
      der Unterschied zwischen 60 und 30 fps.
    • Position und Maßstab der Figuren setzt der Takt in JS. Was hier
      steht, ist Aussehen und Eigenbewegung – nie die Lage.

   Zeiten und Kurve kommen aus tokens.css (--ds-t-*, --ds-ease). Wo hier
   trotzdem eine Zahl steht, ist es eine Dauer aus der Referenz, die
   nicht auf der 100/200/300/500-Skala liegt (420, 640, 700 …).
   ═══════════════════════════════════════════════════════════════════ */

/* ── Bühne ────────────────────────────────────────────────────────
   Liegt über dem Tisch, aber unter den Dialogen. pointer-events:none
   ist nicht verhandelbar: die Ebene darf nie einen Spielzug schlucken. */
.dm-buehne {
  position: absolute;
  inset: 0;
  z-index: 60;
  pointer-events: none;
  overflow: hidden;
  contain: layout paint;
}

.dm-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.dm-ebene {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* ── Erwachen: Schimmer-Sweep über die Kartenfläche ───────────────
   Der Glow selbst ist box-shadow und wird in JS gesetzt (er hängt an
   der Kartenfarbe). Hier läuft nur der Streifen. */
.dm-schimmer {
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  overflow: hidden;
}
.dm-schimmer::after {
  content: '';
  position: absolute;
  top: -20%;
  bottom: -20%;
  width: 45%;
  background: linear-gradient(100deg,
    rgba(255, 255, 255, 0) 0%,
    rgba(255, 246, 214, .55) 50%,
    rgba(255, 255, 255, 0) 100%);
  /* Ausgangs- UND Endlage liegen außerhalb der Karte. forwards ist hier
     keine Kosmetik: ohne den Fill fiele der Streifen nach den 700 ms auf
     translateX(0) zurück und bliebe als heller Balken mitten auf der
     Karte stehen, solange die Szene läuft. */
  transform: translateX(-190%) skewX(-12deg);
  animation: dm-schimmer 700ms var(--ds-ease) forwards;
}
@keyframes dm-schimmer {
  to { transform: translateX(320%) skewX(-12deg); }
}

/* ── Geist: das Motiv bleibt blass liegen, solange die Figur draußen ist
   Sonst sähe man dasselbe Bild zweimal – einmal auf der Karte, einmal
   schwebend darüber. */
.dm-geist {
  /* Liegt auf der GANZEN Kartenfläche, nicht nur auf dem Motiv.
     Vorher blasste allein die Illustration ab, während Name, Trennlinie
     und Hinweisband in voller Deckkraft stehen blieben – die Karte fiel
     dadurch sichtbar in ihre Bestandteile auseinander. Sie soll als EIN
     Ding zurücktreten, solange ihre Figur draußen ist.
     .5 statt der .13 der Referenz: Dort lag der Wert auf dem Motiv
     allein; auf der ganzen Karte würde .13 sie vom Tisch verschwinden
     lassen. */
  opacity: .5;
  filter: grayscale(.85);
  transition: opacity var(--ds-t-move) ease-out, filter var(--ds-t-move) ease-out;
}
/* Beim Wiederanbinden nach einem Neuaufbau: OHNE Übergang. Ein frisches
   Element startet bei voller Deckkraft, die Transition liefe also erneut
   von 1 auf .5 – genau das war das verbliebene Blinken. */
.dm-geist--sofort { transition: none !important; }

/* ── Figur ────────────────────────────────────────────────────────
   left/top bleiben 0; die Lage kommt als translate3d aus dem Takt.
   Der negative Rand (in JS gesetzt) verschiebt den Kasten so, dass der
   ANKER auf dem Punkt sitzt: bei .dm-anker-mitte die Mitte, bei
   .dm-anker-fuss die Standlinie. */
.dm-sprite {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 3;
  pointer-events: none;
  will-change: transform, opacity;
  /* isolation hält den Farbauftrag unten IM Sprite. Ohne das mischte
     mix-blend-mode:color mit dem Spieltisch dahinter statt mit dem
     Motiv. */
  isolation: isolate;
}
.dm-anker-mitte { transform-origin: 50% 50%; }
.dm-anker-fuss  { transform-origin: 50% 100%; }

.dm-sprite-bild {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  transform-origin: 50% 50%;
  will-change: transform;
  /* Auch hier kein drop-shadow: Das Bild dreht sich je Bild (Modus
     „dreht"/„zittert"), der Filter wuerde jedes Mal neu gerastert. */
}

/* Angesagte Farbe auf dem schwebenden Motiv (Fließband/Dampfwolke) –
   dieselbe Maskentechnik wie .card-illu-tint in cards.css. */
.dm-sprite-tint {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: var(--dc, var(--gold));
  -webkit-mask-position: center; -webkit-mask-size: contain; -webkit-mask-repeat: no-repeat;
          mask-position: center;         mask-size: contain;         mask-repeat: no-repeat;
  mix-blend-mode: color;
  opacity: .92;
}

/* Bodenschatten – gibt der Figur Gewicht. Nur wo sie wirklich steht.
   Stauchung und Deckkraft setzt der Takt (im Schritttakt), hier steht
   nur, wie er aussieht. */
.dm-schatten {
  position: absolute;
  left: 50%;
  bottom: -6%;
  width: 62%;
  height: 11%;
  margin-left: -31%;
  transform-origin: 50% 50%;
  border-radius: 50%;
  pointer-events: none;
  background: radial-gradient(ellipse at 50% 50%,
    rgba(0, 0, 0, .55) 0%,
    rgba(0, 0, 0, .28) 55%,
    rgba(0, 0, 0, 0) 78%);
}
.dm-schatten--rig {
  bottom: -8px;
  height: 34px;
  width: 68%;
  margin-left: -34%;
  background: radial-gradient(ellipse at 50% 50%,
    rgba(0, 0, 0, .62) 0%,
    rgba(0, 0, 0, .34) 42%,
    rgba(0, 0, 0, 0) 72%);
}

/* ── Rig: zerlegte Figur ──────────────────────────────────────────
   --dm-k ist der Maßstab vom Quellbild auf die Zielbreite. Er steht als
   Variable statt als Inline-transform da, weil der Takt auf derselben
   Ebene rotateY schreibt – ein Inline-Wert würde das schlagen. */
.dm-rig {
  position: absolute;
  left: 0;
  top: 0;
  transform-origin: 50% 100%;
  scale: var(--dm-k, 1);
  will-change: transform;
  /* KEIN drop-shadow hier. Die vier Rig-Teile drehen sich je Bild INNERHALB
     dieses Containers – ein Filter darauf zwingt den Browser, die gesamte
     gefilterte Ebene in JEDEM Bild neu zu rastern. Auf dem Handy ist das
     der Unterschied zwischen fluessig und ruckelig. Das Gewicht der Figur
     traegt der Bodenschatten (.dm-schatten--rig), und der ist ein
     Verlauf-Div, das nur bewegt wird. */
}
.dm-rig--fee { transform-origin: 50% 34%; }

.dm-rig-teil {
  position: absolute;
  will-change: transform;
  backface-visibility: visible;
}
/* Die Flügel klappen um ihre Innenkante nach hinten weg – ohne
   preserve-3d flachte der Elternknoten das rotateY zu einem Stauchen ab. */
.dm-rig--fee .dm-teil-fluegelL,
.dm-rig--fee .dm-teil-fluegelR { transform-style: preserve-3d; }

/* ── Flash: radialer Lichtstoß über der Spielfläche ───────────────── */
.dm-flash {
  position: absolute;
  inset: 0;
  z-index: 5;
  pointer-events: none;
  mix-blend-mode: screen;
}

/* ── Plakette: Messing-Chip mit einem Wert (7½, 9¾) ───────────────── */
.dm-plakette {
  position: absolute;
  z-index: 6;
  pointer-events: none;
  white-space: nowrap;
  padding: 3px 10px;
  border-radius: 999px;
  border: 1px solid var(--gold-deep, #7a5a20);
  background: linear-gradient(160deg, #e6c072, #b8862c);
  color: #2a1e06;
  font-family: var(--f-ui, system-ui), sans-serif;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .02em;
  box-shadow: 0 6px 16px rgba(0, 0, 0, .5);
  opacity: 0;
  transform: translate(-50%, -50%) scale(.6);
  transition: opacity 220ms ease-out, transform 700ms var(--ds-ease);
}
.dm-plakette.is-in {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1) translateY(-52px);
}

/* ── Bote: Handkarte auf dem Fließband ───────────────────────────
   Rückseite, kein Motiv: Weitergegeben wird verdeckt, und welche
   Karte kommt, weiß der Client zu diesem Zeitpunkt gar nicht.

   Normalfall ist .dm-bote--karte: Darin steckt eine ECHTE Rückseite aus
   buildCard, also das Blatt, das der Spieler gewählt hat. Der Bote ist
   dann nur noch der Rahmen, der die Lage traegt – jede Verzierung hier
   laege doppelt auf der Karte. Die Kachel unten ist der Rückfall, wenn
   keine Karte gebaut werden konnte. */
.dm-bote {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 5;
  pointer-events: none;
  opacity: 0;
  border-radius: 3px;
  border: 1px solid var(--gold-deep, #7a5a20);
  background:
    repeating-linear-gradient(135deg, rgba(232, 205, 138, .16) 0 3px, transparent 3px 6px),
    linear-gradient(158deg, #6b5426, #2e2411);
  box-shadow: 0 4px 12px rgba(0, 0, 0, .55), inset 0 0 0 1px rgba(232, 205, 138, .28);
  will-change: transform, opacity;
}
.dm-bote--karte {
  border: 0;
  background: none;
  /* Der Schlagschatten bleibt: Er hebt die Karte vom Tisch ab, und die
     Karte selbst bringt nur ihren eigenen, viel knapperen mit. */
  box-shadow: 0 4px 12px rgba(0, 0, 0, .55);
  border-radius: 0;
}
.dm-bote--karte > .card { display: block; }

/* ── Scanbalken: nimmt Maß an einem Ziel (Trumpfanzeige) ─────────── */
.dm-scan {
  position: absolute;
  z-index: 6;
  pointer-events: none;
  overflow: hidden;
  border-radius: 6px;
  box-shadow: inset 0 0 0 1px rgba(143, 212, 224, .55);
}
.dm-scan::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  height: 34%;
  top: -34%;
  background: linear-gradient(180deg,
    rgba(143, 212, 224, 0) 0%,
    rgba(143, 212, 224, .55) 60%,
    rgba(232, 251, 255, .85) 100%);
  animation: dm-scan 780ms linear forwards;
}
@keyframes dm-scan {
  to { top: 100%; }
}

/* ── Zustände, die eine Szene hinterlässt ─────────────────────────
   Kein Bewegungsschritt: das überlebt den Rest des Stichs und wird beim
   Neuzeichnen wieder aufgetragen. Deshalb hier filter statt transform –
   es ist eine Eigenschaft des Zustands, keine Animation. */
.card.dm-verpufft {
  filter: grayscale(.7) brightness(.72);
  transition: filter var(--ds-t-move) ease-out;
}

.card.dm-zittert { animation: dm-zittern 480ms var(--ds-ease) 2; }
@keyframes dm-zittern {
  0%, 100% { transform: translateX(0); }
  25%      { transform: translateX(-2px) rotate(-.6deg); }
  75%      { transform: translateX(2px)  rotate(.6deg); }
}

/* Stampfer: die ANDEREN Stichkarten springen kurz auf und kippen.
   Einmal-Animation ohne Fill, damit sie danach exakt in ihrer Lage
   sitzen – ein Fill schlüge jeden späteren transform. */
.card.dm-sprung { animation: dm-sprung 380ms var(--ds-ease) 1; }
@keyframes dm-sprung {
  0%   { transform: translateY(0)    rotate(0deg); }
  22%  { transform: translateY(-8px) rotate(var(--dm-kipp, 3deg)); }
  100% { transform: translateY(0)    rotate(0deg); }
}

/* ── Reduzierte Bewegung ──────────────────────────────────────────
   Flüge werden zu Sofort-Zuständen, nicht zu „nichts": Was die Szene
   hinterlässt (vergraut, verwandelt), tritt weiterhin ein – es tritt
   nur ohne Weg ein. Die Ausnahme ist .dm-verpufft: der Zustand SOLL
   sichtbar bleiben, nur sein Übergang entfällt. */
@media (prefers-reduced-motion: reduce) {
  .dm-schimmer::after,
  .dm-scan::after,
  .card.dm-zittert,
  .card.dm-sprung {
    animation: none !important;
  }
  .dm-schimmer, .dm-flash, .dm-scan { display: none; }
  .dm-plakette {
    transition: none;
    opacity: 1;
    transform: translate(-50%, -50%) translateY(-40px);
  }
  .dm-sprite { transition: none !important; }
  .card.dm-verpufft { transition: none; }
  .dm-geist { transition: none; }
}
