/* ==========================================================================
   Martinis Carte Blanche — Karten-Sektion
   Portiert aus dem Claude-Design-Export "Karten Aufdecken.dc.html".
   Die @keyframes sind 1:1 aus dem Export übernommen — nicht nachjustieren,
   sie sind gegen das Referenzvideo (analysis/ref-frames.png) getuned.
   ========================================================================== */

/* --- Box-Modell ----------------------------------------------------------
   Der Export lief ohne box-sizing-Reset, alle Maße sind gegen content-box
   gerechnet (z.B. der Play-Kreis: 54px + 2px Rahmen = 58px außen). Ohne
   diese Festlegung verformt ein `* { box-sizing: border-box }` der
   Gastseite die Karte. Die zwei Stellen, die im Export explizit
   border-box hatten, sind unten einzeln gesetzt.                        */
.mcb,
.mcb *,
.mcb *::before,
.mcb *::after {
  box-sizing: content-box;
}

/* --- Tokens --------------------------------------------------------------
   --mcb-w / --mcb-h werden von cards.js gesetzt (H = W * 85/60, Skatmaß).
   Alles andere ist statisch und darf hier angepasst werden.              */
.mcb {
  --mcb-w: 320px;
  --mcb-h: 453px;
  --mcb-radius: 16px;
  --mcb-ink: #111111;
  --mcb-paper: #fdfdfc;
  --mcb-muted: #8a8a86;
  --mcb-kicker: #77756f;
  /* Bildunterschrift ist echter Fließtext, nicht Deko — dunkler als
     --mcb-muted, damit sie auf dem Kartenpapier 6:1 erreicht. */
  --mcb-caption: #5f5e5a;
  /* Unterkategorien — auf dem Kartenpapier geprüft (6,4:1 / 5,3:1). */
  --mcb-cat-herz: #b3261e;
  --mcb-cat-enter: #6b6a64;
  --mcb-hairline: rgba(0, 0, 0, 0.06);
  --mcb-pad-top: 18px;
  --mcb-font-display: "Cormorant Garamond", Georgia, serif;
  --mcb-font-mono: ui-monospace, Menlo, monospace;
}

/* --- Track & sticky viewport --------------------------------------------
   Trackhöhe = Karten × segVH + 100vh (von cards.js gesetzt), darin ein
   sticky 100vh-Fenster. Der Scrollweg im Track ist der Animations-
   fortschritt; das Fenster steht dabei still.                            */
.mcb-track {
  position: relative;
}

/* Einrastpunkte. Leere Marken von 1px, eine je Karte, in deren Ruhezone.
   cards.js setzt top und schaltet scroll-snap-type auf <html>; der Browser
   hält den Scroll dann an der Marke fest, sobald er in ihrer Nähe zur Ruhe
   kommt. `stop: always` heißt: auch ein kräftiger Wisch fliegt nicht über
   eine Karte hinweg, jede wird einzeln angefahren.

   Kein visibility/opacity — beides kann die Marke je nach Browser aus der
   Snap-Auswahl nehmen. Eine 1px-Marke ohne Füllung ist ohnehin unsichtbar. */
.mcb-snap {
  position: absolute;
  left: 0;
  width: 1px;
  height: 1px;
  pointer-events: none;
  scroll-snap-align: start;
  scroll-snap-stop: always;
}

.mcb-sticky {
  position: sticky;
  top: 0;
  /* Hier bewusst border-box: die Trackhöhe rechnet mit einem Fenster von
     genau 100vh. Mit content-box käme das padding-top oben drauf, das
     Fenster wäre höher als gerechnet und der angeheftete Scrollweg um
     eben diese 44px zu kurz — die letzte Karte rastet dann nicht mehr
     ein. Die Kartengeometrie selbst bleibt content-box. */
  box-sizing: border-box;
  height: 100vh;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: var(--mcb-pad-top);
}

.mcb-hint {
  font-family: var(--mcb-font-mono);
  font-size: 11px;
  letter-spacing: 3.5px;
  text-transform: uppercase;
  color: var(--mcb-muted);
  margin-bottom: 16px;
}

/* Der Stapel wird als Ganzes nach oben geschoben, damit die gerade
   aktive Karte im Fenster bleibt. */
.mcb-stack {
  display: flex;
  flex-direction: column;
  align-items: center;
  will-change: transform;
  padding-bottom: 120px;
}

/* --- Karte ---------------------------------------------------------------
   Stapel-Layout: jede Karte ab der zweiten bekommt ein negatives
   margin-top (peek − H), rutscht also unter die vorherige. Beim Aufdecken
   läuft der Wert auf +18px, die Karte tritt aus dem Stapel heraus.       */
.mcb-card {
  position: relative;
  /* Drehpunkt der Verkantung (cards.js: splay) oben mittig — dort liegt
     die Karte unter ihrem Vorgänger, unten fächert sie sichtbar aus. */
  transform-origin: 50% 0;
  border-radius: var(--mcb-radius);
  /* Kontaktschatten nach unten auf die nächste Karte im Stapel — macht
     aus den flachen Streifen aufeinanderliegende Pappen. Der dynamische
     Schatten beim Anheben kommt weiter aus omLift. */
  box-shadow: 0 16px 22px -14px rgba(0, 0, 0, 0.45);
}

.mcb-lift {
  width: var(--mcb-w);
  height: var(--mcb-h);
  /* Von cards.js mit der Kartenhöhe skaliert (820px bei H = 453px).
     Perspektive und Karte im selben Maß zu vergrößern erhält die
     Projektion exakt — der Flip sieht auf jeder Größe gleich aus. */
  perspective: var(--mcb-persp, 820px);
  perspective-origin: 50% 28%;
}

.mcb-flip {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
}

.mcb--clickable .mcb-card {
  cursor: pointer;
}

/* --- Rückseite (Kartenrücken, im Ruhezustand sichtbar) -------------------
   Ein durchgehendes Stück. Die frühere Fassung teilte die Karte in drei
   Segmente, deren untere beim Anheben wegknickten (omBendA / omBendB) —
   die Segmentgrenze blieb dabei als Knick und Haarlinie quer über der
   Kartenmitte sichtbar (Jakob, 4.8.2026), deshalb entfernt: die Karte
   ist jetzt beim Flip steif.                                            */
.mcb-back {
  position: absolute;
  inset: 0;
  transform-style: preserve-3d;
  border-radius: var(--mcb-radius);
}

.mcb-panel {
  position: absolute;
  inset: 0;
  overflow: hidden;
  background: #ffffff;
  box-shadow: 0 0 0 1px var(--mcb-hairline);
  border-radius: var(--mcb-radius);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

.mcb-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* fill statt cover: die Karte darf höher sein als das Motiv (60:85),
     auf dem Handy füllt sie den Bildschirm. Strecken erhält den
     umlaufenden Zierrahmen — beschneiden würde ihn seitlich kappen und
     das Motiv liefe abgeschnitten ins Leere. Der Kreis in der Mitte wird
     dabei leicht oval; bis zum Deckel von 1,75 (cards.js) fällt das
     deutlich weniger auf als ein fehlender Rahmen. */
  object-fit: fill;
  display: block;
}

.mcb-shade-back {
  position: absolute;
  inset: 0;
  border-radius: var(--mcb-radius);
  background: linear-gradient(to top, rgba(10, 10, 12, 0.3), rgba(10, 10, 12, 0.85));
  opacity: 0;
  pointer-events: none;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* --- Vorderseite (Projekt) ----------------------------------------------- */
.mcb-front {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  transform: rotateX(180deg);
  border-radius: var(--mcb-radius);
  background: var(--mcb-paper);
  border: 2px solid var(--mcb-ink);
  box-sizing: border-box;
  padding: 10px;
}

.mcb-front-inner {
  position: relative;
  width: 100%;
  height: 100%;
  border: 1px solid var(--mcb-ink);
  border-radius: 8px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.mcb-head {
  height: 33%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 0 14px;
}

.mcb-kicker {
  font-size: 9px;
  letter-spacing: 4px;
  text-transform: uppercase;
  color: var(--mcb-kicker);
}

/* Unterkategorie über dem Schriftzug. Beide Töne sind gegen das
   Kartenpapier geprüft: Rot 6,4:1, Grau 5,3:1 — kleiner Text braucht
   4,5:1, die Reserve trägt auch das Sperren der Buchstaben. */
.mcb-cat {
  font-size: 10px;
  /* 700 statt Normalschnitt: bei 10px gesperrter Versalschrift wirkt
     Regular ausgedünnt bis unsichtbar. Größe bleibt bewusst gleich. */
  font-weight: 700;
  letter-spacing: 3px;
  text-transform: uppercase;
  text-align: center;
  margin-bottom: 14px;
}

.mcb-cat--herz {
  color: var(--mcb-cat-herz);
}

.mcb-cat--enter {
  color: var(--mcb-cat-enter);
}

.mcb-name {
  font-family: var(--mcb-font-display);
  font-weight: 600;
  font-size: var(--mcb-name-size, 29px);
  letter-spacing: 2px;
  color: var(--mcb-ink);
  text-align: center;
  line-height: 1.1;
  margin: 0;
  text-wrap: balance;
}

.mcb-rule {
  width: 44px;
  height: 1px;
  background: var(--mcb-ink);
}

/* --- Caviar Dreams (Nymphont, Freeware) — selbst gehostet ---------------- */
@font-face {
  font-family: "Caviar Dreams";
  src: url("../assets/fonts/CaviarDreams.ttf") format("truetype");
  font-weight: 400;
  font-display: swap;
}

@font-face {
  font-family: "Caviar Dreams";
  src: url("../assets/fonts/CaviarDreams_Bold.ttf") format("truetype");
  font-weight: 700;
  font-display: swap;
}

/* Zweizeiliger gesetzter Titel (project.heading): Hauptzeile groß,
   Unterzeile kleiner. */
.mcb-title {
  font-family: "Caviar Dreams", "Century Gothic", "Avant Garde", sans-serif;
  font-weight: 700;
  font-size: calc(var(--mcb-name-size, 29px) * 1.2);
  letter-spacing: 0.05em;
  color: var(--mcb-ink);
  text-align: center;
  line-height: 1.1;
  margin: 0;
  text-wrap: balance;
}

.mcb-title-sub {
  display: block;
  font-weight: 400;
  font-size: 0.44em;
  letter-spacing: 0.16em;
  margin-top: 7px;
}

/* --- Dunkle Kartenvariante (project.dark + project.bg) -------------------
   Hintergrundbild liegt auf .mcb-front (Inline-Style), Texte hell. Die
   Innenrahmen-Linie wird halbtransparent weiß, das Kategorierot eine
   hellere Stufe — #b3261e käme auf Schwarz nur auf ~2,6:1. */
.mcb-front--dark {
  background-color: #060607;
  background-size: cover;
  background-position: center;
}

.mcb-front--dark .mcb-front-inner {
  border-color: rgba(255, 255, 255, 0.32);
}

.mcb-card--dark .mcb-title {
  color: #ffffff;
}

.mcb-card--dark .mcb-title-sub {
  color: rgba(255, 255, 255, 0.86);
}

.mcb-card--dark .mcb-caption,
.mcb-card--dark .mcb-close,
.mcb-card--dark .mcb-rotatehint {
  color: #c9c7c2;
}

.mcb-card--dark .mcb-close:hover,
.mcb-card--dark .mcb-close:focus-visible {
  color: #ffffff;
}

.mcb-card--dark .mcb-cat--herz {
  color: #e0645c;
}

.mcb-card--dark .mcb-cat--enter {
  color: #b5b3ae;
}

/* Schriftzug als Bild statt gesetzter Überschrift. Freigestellt (das Weiß
   des Originals ist zu Transparenz gerechnet), damit auf dem Kartenpapier
   kein helleres Rechteck steht. Breite führt, die Höhe begrenzt bei sehr
   flachen Karten. */
.mcb-logo {
  display: block;
  width: 100%;
  max-width: 88%;
  height: auto;
  /* Darf im Kopfbereich schrumpfen. Ohne min-height:0 wächst ein fast
     quadratischer Schriftzug (Konrad Kater ist 1,28:1) über den Kopf
     hinaus; contain hält dabei das Seitenverhältnis. */
  flex: 0 1 auto;
  min-height: 0;
  object-fit: contain;
  margin: 0 auto;
}

.mcb-media {
  flex: 1;
  padding: 0 12px 12px 12px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 0;
}

/* --- YouTube-Player ------------------------------------------------------
   Vor dem Klick liegt hier nur das lokale Vorschaubild. Das Feld ist fest
   16:9, damit vom Bild nichts abgeschnitten wird; die verbleibende Höhe
   verteilt sich als Luft über und unter dem Block.                       */
.mcb-player {
  position: relative;
  width: 100%;
  aspect-ratio: 16 / 9;
  border-radius: 8px;
  overflow: hidden;
  background: #111111;
  flex: none;
}

.mcb-poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.mcb-playbtn {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0;
  padding: 0;
  background: rgba(10, 10, 12, 0.18);
  cursor: pointer;
  transition: background 0.25s ease;
}

.mcb-playbtn:hover,
.mcb-playbtn:focus-visible {
  background: rgba(10, 10, 12, 0.32);
}

.mcb-playbtn .mcb-play {
  background: rgba(255, 255, 255, 0.92);
}

.mcb-frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

/* Schließen und Bildunterschrift teilen sich denselben Platz unter dem
   Video — im Player selbst ist kein Rand frei, YouTube belegt alle vier. */
.mcb-close {
  display: none;
  margin: 12px auto 0;
  padding: 0;
  border: 0;
  background: none;
  font-family: inherit;
  font-size: 11px;
  letter-spacing: 0.3px;
  color: var(--mcb-caption);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.mcb-close:hover,
.mcb-close:focus-visible {
  color: var(--mcb-ink);
}

.mcb-media.is-playing .mcb-caption {
  display: none;
}

.mcb-media.is-playing .mcb-close {
  display: block;
}

/* --- Dreh-Hinweis am Video -----------------------------------------------
   Nur am Handy (hover:none) und nur solange das Video läuft. Am Desktop
   gibt es nichts zu drehen.                                              */
.mcb-rotatehint {
  display: none;
  margin: 12px 2px 0;
  font-size: 11px;
  letter-spacing: 0.3px;
  color: var(--mcb-caption);
  align-items: center;
  justify-content: center;
  gap: 7px;
}

.mcb-rotatehint svg {
  width: 15px;
  height: 15px;
  flex: none;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

@media (hover: none) {
  .mcb-media.is-playing .mcb-rotatehint {
    display: flex;
  }
}

/* --- Vollbild für Bildkarten --------------------------------------------- */
.mcb-shot {
  position: relative;
}

.mcb-expand {
  position: absolute;
  right: 8px;
  bottom: 8px;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(10, 10, 12, 0.55);
  color: #ffffff;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.mcb-expand:hover,
.mcb-expand:focus-visible {
  background: rgba(10, 10, 12, 0.8);
}

.mcb-expand svg {
  width: 14px;
  height: 14px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
}

/* Overlay hängt am <body> (siehe cards.js: fixed funktioniert nicht in
   transformierten Vorfahren), muss also ohne .mcb-Kontext auskommen. */
.mcb-lightbox {
  position: fixed;
  inset: 0;
  z-index: 999;
  background: rgba(8, 8, 10, 0.94);
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  padding: 4vmin;
}

.mcb-lightbox img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  box-sizing: border-box;
}

.mcb-lb-close {
  position: absolute;
  top: calc(10px + env(safe-area-inset-top));
  right: 14px;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.14);
  color: #ffffff;
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
}

.mcb-lb-close:hover,
.mcb-lb-close:focus-visible {
  background: rgba(255, 255, 255, 0.28);
}

/* --- Foto statt Video ----------------------------------------------------
   Kein festes Format: das Bild behält sein eigenes Seitenverhältnis und
   wird nie beschnitten. Bei einem Bandfoto kostet Beschnitt sofort Leute
   am Rand. Reicht die Höhe nicht, schrumpft es. */
.mcb-shot {
  width: 100%;
  border-radius: 8px;
  overflow: hidden;
  flex: 0 1 auto;
  min-height: 0;
  display: flex;
}

.mcb-shot-img {
  width: 100%;
  height: auto;
  max-height: 100%;
  object-fit: contain;
  display: block;
}

/* Musikschalter, gleiche Machart wie „Video schließen“. */
.mcb-audiobtn {
  display: block;
  margin: 10px auto 0;
  padding: 0;
  border: 0;
  background: none;
  font-family: inherit;
  font-size: 11px;
  letter-spacing: 0.3px;
  color: var(--mcb-caption);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.mcb-audiobtn:hover,
.mcb-audiobtn:focus-visible {
  color: var(--mcb-ink);
}

.mcb-caption {
  margin: 12px 2px 0;
  font-size: 11px;
  line-height: 1.45;
  letter-spacing: 0.3px;
  color: var(--mcb-caption);
  text-align: center;
  text-wrap: pretty;
}

/* Die Vorderseite liegt im Scroll-Modus die meiste Zeit weggedreht hinter
   der Karte. Ohne diese Sperre könnte ein Klick den Play-Knopf einer
   Karte treffen, die gar nicht offen liegt. */
.mcb-card:not(.is-revealed) .mcb-front {
  pointer-events: none;
}

/* Chromium prüft Treffer in preserve-3d-Ebenen anders, als es sie malt: der
   Klick bleibt an der Drehebene hängen und erreicht die Vorderseite nie —
   obwohl elementFromPoint an derselben Stelle den Play-Knopf meldet. Auf der
   Drehebene abschalten und auf der Vorderseite wieder einschalten löst das.
   pointer-events wird vererbt, die Rückseite bleibt damit ebenfalls taub.
   Im Klick-Modus kommen Klicks auf die Vorderseite trotzdem am Kartenrahmen
   an — sie steigen weiter auf, nur der Play-Knopf hält sie an. */
.mcb-card.is-revealed .mcb-flip {
  pointer-events: none;
}

.mcb-card.is-revealed .mcb-front {
  pointer-events: auto;
}

.mcb-video {
  flex: 1;
  width: 100%;
  border-radius: 8px;
  background: #000000;
  object-fit: cover;
  min-height: 0;
}

.mcb-media-empty {
  flex: 1;
  border-radius: 8px;
  background: repeating-linear-gradient(45deg, #f3f2ef 0 10px, #eae9e5 10px 20px);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 14px;
}

.mcb-play {
  width: 54px;
  height: 54px;
  border-radius: 50%;
  border: 2px solid var(--mcb-ink);
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.7);
}

.mcb-play::after {
  content: "";
  width: 0;
  height: 0;
  border-top: 9px solid transparent;
  border-bottom: 9px solid transparent;
  border-left: 15px solid var(--mcb-ink);
  margin-left: 4px;
}

.mcb-media-label {
  font-family: var(--mcb-font-mono);
  font-size: 10px;
  letter-spacing: 1.5px;
  color: var(--mcb-muted);
}

/* Abdunklung der Vorderseite, solange sie noch weggedreht ist, plus ein
   Lichtstreifen, der beim Auftreffen einmal über die Karte läuft. */
.mcb-shade-front {
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to bottom,
    rgba(10, 10, 12, 0.7),
    rgba(10, 10, 12, 0.32) 55%,
    rgba(10, 10, 12, 0.12)
  );
  opacity: 0;
  pointer-events: none;
}

.mcb-sheen {
  position: absolute;
  left: -20%;
  top: 0;
  width: 140%;
  height: 55%;
  background: linear-gradient(
    to bottom,
    rgba(255, 255, 255, 0),
    rgba(255, 255, 255, 0.5) 50%,
    rgba(255, 255, 255, 0)
  );
  opacity: 0;
  pointer-events: none;
}

/* --- Fächer-Modus (Desktop, ab 1024px; cards.js setzt die Klasse) --------
   Die Karten liegen absolut in der Mitte des sticky-Fensters; ihre
   Position auf dem Blatt kommt komplett aus dem Transform, das
   paintFan() pro Frame schreibt. margin-Stapelung und Stapel-Versatz
   des Mobil-Layouts sind hier bedeutungslos. */
.mcb--fan .mcb-stack {
  position: relative;
  flex: 1;
  width: 100%;
  min-height: 0;
  padding-bottom: 0;
}

.mcb--fan .mcb-card {
  position: absolute;
  left: 50%;
  top: 50%;
  margin: 0 !important;
  /* Rotation um die Kartenmitte — den Bogen rechnet paintFan() selbst. */
  transform-origin: 50% 50%;
}

/* Wartende Karten laden zum Klick ein. */
.mcb--fan .mcb-card:not(.is-revealed) {
  cursor: pointer;
}

/* --- Reduced motion ------------------------------------------------------
   Kein sticky, kein Scroll-Scrubbing: die Karten liegen aufgedeckt
   untereinander. cards.js setzt die Endzustände (siehe applyStatic).     */
@media (prefers-reduced-motion: reduce) {
  .mcb-sticky {
    position: static;
    height: auto;
    overflow: visible;
  }

  .mcb-stack {
    will-change: auto;
  }
}

/* ==========================================================================
   @keyframes — 1:1 aus dem Claude-Design-Export
   ========================================================================== */

@keyframes omFlip {
  0% {
    transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg) translateY(0) translateZ(0);
    animation-timing-function: cubic-bezier(0.55, 0.08, 0.7, 0.45);
  }
  16% {
    transform: rotateX(14deg) rotateY(-13deg) rotateZ(-4deg) translateY(3px) translateZ(12px);
    animation-timing-function: cubic-bezier(0.4, 0.15, 0.5, 0.85);
  }
  34% {
    transform: rotateX(62deg) rotateY(-6deg) rotateZ(-5.5deg) translateY(-14px) translateZ(58px);
    animation-timing-function: cubic-bezier(0.4, 0.25, 0.5, 0.95);
  }
  52% {
    transform: rotateX(122deg) rotateY(5deg) rotateZ(3.5deg) translateY(-38px) translateZ(100px);
    animation-timing-function: cubic-bezier(0.35, 0.4, 0.5, 1);
  }
  70% {
    transform: rotateX(160deg) rotateY(1.5deg) rotateZ(1.2deg) translateY(-20px) translateZ(44px);
    animation-timing-function: cubic-bezier(0.35, 0.5, 0.5, 1);
  }
  86% {
    transform: rotateX(174deg) rotateY(0.4deg) rotateZ(0.4deg) translateY(-6px) translateZ(12px);
    animation-timing-function: cubic-bezier(0.3, 0.55, 0.4, 1);
  }
  100% {
    transform: rotateX(180deg) rotateY(0deg) rotateZ(0deg) translateY(0) translateZ(0);
  }
}

@keyframes omLift {
  0% {
    transform: translateY(0) scale(1);
    filter: blur(0px) drop-shadow(0 3px 4px rgba(0, 0, 0, 0.22));
    animation-timing-function: cubic-bezier(0.55, 0.08, 0.7, 0.45);
  }
  16% {
    transform: translateY(2px) scale(1.01);
    filter: blur(0px) drop-shadow(3px 6px 8px rgba(0, 0, 0, 0.24));
    animation-timing-function: cubic-bezier(0.4, 0.15, 0.5, 0.85);
  }
  34% {
    transform: translateY(-10px) scale(1.05);
    filter: blur(0.25px) drop-shadow(5px 26px 26px rgba(0, 0, 0, 0.26));
    animation-timing-function: cubic-bezier(0.4, 0.25, 0.5, 0.95);
  }
  52% {
    transform: translateY(-24px) scale(1.1);
    filter: blur(0.5px) drop-shadow(2px 52px 46px rgba(0, 0, 0, 0.29));
    animation-timing-function: cubic-bezier(0.35, 0.4, 0.5, 1);
  }
  70% {
    transform: translateY(-12px) scale(1.05);
    filter: blur(0.15px) drop-shadow(0 28px 28px rgba(0, 0, 0, 0.25));
    animation-timing-function: cubic-bezier(0.35, 0.5, 0.5, 1);
  }
  86% {
    transform: translateY(-4px) scale(1.015);
    filter: blur(0px) drop-shadow(0 10px 13px rgba(0, 0, 0, 0.21));
    animation-timing-function: cubic-bezier(0.3, 0.55, 0.4, 1);
  }
  100% {
    transform: translateY(0) scale(1);
    filter: blur(0px) drop-shadow(0 4px 9px rgba(0, 0, 0, 0.17));
  }
}

@keyframes omFlipBack {
  0% {
    transform: rotateX(180deg) rotateY(0deg) rotateZ(0deg) translateY(0) translateZ(0);
    animation-timing-function: cubic-bezier(0.55, 0.08, 0.7, 0.45);
  }
  14% {
    transform: rotateX(170deg) rotateY(8deg) rotateZ(3deg) translateY(2px) translateZ(10px);
    animation-timing-function: cubic-bezier(0.4, 0.15, 0.5, 0.85);
  }
  34% {
    transform: rotateX(118deg) rotateY(5deg) rotateZ(4.5deg) translateY(-16px) translateZ(58px);
    animation-timing-function: cubic-bezier(0.4, 0.25, 0.5, 0.95);
  }
  52% {
    transform: rotateX(58deg) rotateY(-6deg) rotateZ(-3.5deg) translateY(-36px) translateZ(96px);
    animation-timing-function: cubic-bezier(0.35, 0.4, 0.5, 1);
  }
  72% {
    transform: rotateX(20deg) rotateY(-2deg) rotateZ(-1.5deg) translateY(-18px) translateZ(40px);
    animation-timing-function: cubic-bezier(0.35, 0.5, 0.5, 1);
  }
  88% {
    transform: rotateX(6deg) rotateY(0.5deg) rotateZ(0.4deg) translateY(-5px) translateZ(10px);
    animation-timing-function: cubic-bezier(0.3, 0.55, 0.4, 1);
  }
  100% {
    transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg) translateY(0) translateZ(0);
  }
}

@keyframes omLiftBack {
  0% {
    transform: translateY(0) scale(1);
    filter: blur(0px) drop-shadow(0 4px 10px rgba(0, 0, 0, 0.16));
    animation-timing-function: cubic-bezier(0.55, 0.08, 0.7, 0.45);
  }
  14% {
    transform: translateY(2px) scale(1.01);
    filter: blur(0px) drop-shadow(-3px 6px 8px rgba(0, 0, 0, 0.24));
    animation-timing-function: cubic-bezier(0.4, 0.15, 0.5, 0.85);
  }
  34% {
    transform: translateY(-10px) scale(1.05);
    filter: blur(0.25px) drop-shadow(-4px 26px 26px rgba(0, 0, 0, 0.26));
    animation-timing-function: cubic-bezier(0.4, 0.25, 0.5, 0.95);
  }
  52% {
    transform: translateY(-22px) scale(1.095);
    filter: blur(0.5px) drop-shadow(-2px 50px 44px rgba(0, 0, 0, 0.29));
    animation-timing-function: cubic-bezier(0.35, 0.4, 0.5, 1);
  }
  72% {
    transform: translateY(-11px) scale(1.048);
    filter: blur(0.15px) drop-shadow(0 26px 26px rgba(0, 0, 0, 0.25));
    animation-timing-function: cubic-bezier(0.35, 0.5, 0.5, 1);
  }
  88% {
    transform: translateY(-3px) scale(1.012);
    filter: blur(0px) drop-shadow(0 9px 12px rgba(0, 0, 0, 0.21));
    animation-timing-function: cubic-bezier(0.3, 0.55, 0.4, 1);
  }
  100% {
    transform: translateY(0) scale(1);
    filter: blur(0px) drop-shadow(0 3px 4px rgba(0, 0, 0, 0.22));
  }
}

@keyframes omShadeBack {
  0% {
    opacity: 0;
  }
  16% {
    opacity: 0.06;
  }
  34% {
    opacity: 0.2;
  }
  48% {
    opacity: 0.42;
  }
  56% {
    opacity: 0.52;
  }
  100% {
    opacity: 0.52;
  }
}

@keyframes omShadeFront {
  0% {
    opacity: 0.92;
  }
  50% {
    opacity: 0.92;
  }
  62% {
    opacity: 0.55;
  }
  76% {
    opacity: 0.26;
  }
  90% {
    opacity: 0.07;
  }
  100% {
    opacity: 0;
  }
}

@keyframes omSheen {
  0% {
    transform: translateY(-120%) rotate(-10deg);
    opacity: 0;
  }
  52% {
    transform: translateY(-120%) rotate(-10deg);
    opacity: 0;
  }
  62% {
    transform: translateY(-40%) rotate(-10deg);
    opacity: 0.5;
  }
  80% {
    transform: translateY(170%) rotate(-10deg);
    opacity: 0.32;
  }
  88% {
    transform: translateY(195%) rotate(-10deg);
    opacity: 0;
  }
  100% {
    transform: translateY(210%) rotate(-10deg);
    opacity: 0;
  }
}
