/* ── RIGHT CONTEXT ── */
aside.ctx {
  position: fixed;
  right: 0;
  top: calc(var(--bild-achse) - var(--menue-h) / 2);
  height: var(--menue-h);
  width: var(--sw);
  z-index: 200;
  background: var(--white);
  transform: translateX(calc(100% + 2px));
  transition: transform 0.3s ease;
  overflow: hidden;
  display: grid;
  /* auto statt 48px: die ComfyUI-Leiste ist ausgeblendet und belegt dann 0 px,
     wird sie wieder eingeblendet, bekommt sie ihre Höhe automatisch */
  grid-template-rows: 1fr auto;
  gap: 4px;
  align-self: unset;
}
/* ── Materialplatz: Rechteck + schwarzer Masken-Keil ────────── */
.mat-slot {
  position: relative;
  flex: 1 1 0;
  min-height: 0;
  cursor: pointer;
  perspective: 800px;
}
/* Unter Umschalt liegt auch hier die rote Flaeche auf — blass fuer alle,
   voll fuer den Platz unter dem Zeiger und den, der gerade wandert.  */
.mat-slot::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--red);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s;
  z-index: 5;
}
body.sortier .mat-slot::after {
  opacity: 0.7;
}
body.sortier .mat-slot:hover::after {
  opacity: 0.9;
}
body.sortier .mat-slot.zieht::after,
.mat-slot.zieht::after {
  opacity: 1;
}
body.sortier .mat-slot {
  user-select: none;
}
/* Bildausschnitt begrenzen — auf der Seite selbst, nicht auf der Kartenseite */
.mat-img,
.mat-front {
  border-radius: 0;
}
.mat-img {
  overflow: hidden;
}
/* Karte: wendet sich per Doppelklick, wie die Historien-Miniaturen.
   Aufbau bewusst identisch zu .hist-card — kein overflow auf den Seiten:
   das flacht in Firefox den 3D-Kontext ab, backface-visibility greift dann
   nicht und die Vorderseite scheint durch die Rückseite. */
.mat-card {
  width: 100%;
  height: 100%;
  position: relative;
  transform-style: preserve-3d;
  transition: transform 0.4s ease;
}
.mat-slot.flipped .mat-card {
  transform: rotateY(180deg);
}
.mat-front,
.mat-back {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  /* backface-visibility allein genügt nicht: sobald ein Browser den 3D-Kontext
     abflacht, bleibt die abgewandte Seite sichtbar und scheint durch. Deshalb
     werden die Seiten zusätzlich hart umgeschaltet — nach der halben Drehzeit,
     wenn die Karte hochkant steht, also im unsichtbaren Moment. */
  transition: opacity 0s linear 0.2s;
}
.mat-back {
  opacity: 0;
  pointer-events: none;
}
.mat-slot.flipped .mat-front {
  opacity: 0;
  pointer-events: none;
}
.mat-slot.flipped .mat-back {
  opacity: 1;
  pointer-events: auto;
}
.mat-front {
  background: var(--white);
}
/* Platzhaltergrafik statt Platzhalterbild — die Flaeche bleibt hell */
.mat-slot:not(.flipped):hover .ph-x,
.mat-slot.drag-over .ph-x {
  stroke: var(--ph-dunkel);
}

/* Rückseite: roter Grund, weiße Schrift — hier steht die Materialbeschreibung */
/* kein opacity hier — das steuert die Seitenumschaltung weiter oben,
   ein opacity:1 an dieser Stelle würde sie überschreiben */
.mat-back {
  background: #e8391c;
  transform: rotateY(180deg);
}
/* Die Rückseite bleibt leer — rote Fläche heißt: Material ausgesetzt */

/* Materialbild: ohne Mouseover ausgegraut und halbtransparent */
.mat-img {
  position: absolute;
  inset: 0;
  z-index: 1;
  filter: grayscale(1);
  opacity: 0.5;
  transition:
    filter 0.25s ease,
    opacity 0.25s ease;
}
.mat-slot:not(.flipped):hover .mat-img,
.mat-slot.drag-over .mat-img {
  filter: none;
  opacity: 1;
}
.mat-img img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Masken-Keil: immer schwarz, Breite zeigt den Zustand.
   Die drei Punkte bleiben in gleicher Zahl, damit clip-path animieren kann. */
/* In Ruhe steht die Spitze ein Drittel der Strecke vom rechten Rand zur
   Mitte, also bei 83 %. Weit genug, um den Keil als Flaeche zu lesen,
   nah genug, um nicht ins Bild zu ragen.                           */
.mat-wedge {
  position: absolute;
  inset: 0;
  z-index: 3;
  background: var(--black);
  clip-path: polygon(100% 0, 100% 100%, 83% 50%);
  transition: clip-path 0.25s ease;
}
/* Doppelklick auf den Keil dreht ihn um: er faehrt über den ganzen Platz
   auf und zeigt ein weisses Kreuz, wie die Rueckseite der
   Materialreferenz. Das Kreuz entfernt nur die Maske.
   Der Dreieck-Umriss behaelt dabei seine drei Punkte, sonst liesse sich
   der Weg dorthin nicht weich zeichnen.                            */

/* Kommt eine Maske an, wackelt die Spitze kurz nach — wie ein Pudding,
   der abgesetzt wird. Sie schiesst ueber die Mitte hinaus, kommt zurueck,
   schwingt kleiner werdend aus. Eine Rueckmeldung, die man sieht, ohne
   hinzusehen.                                                       */
@keyframes mat-wackeln {
  0% {
    clip-path: polygon(100% 0, 100% 100%, 83% 50%);
  }
  18% {
    clip-path: polygon(100% 0, 100% 100%, 28% 50%);
  }
  38% {
    clip-path: polygon(100% 0, 100% 100%, 64% 50%);
  }
  56% {
    clip-path: polygon(100% 0, 100% 100%, 40% 50%);
  }
  72% {
    clip-path: polygon(100% 0, 100% 100%, 56% 50%);
  }
  86% {
    clip-path: polygon(100% 0, 100% 100%, 46% 50%);
  }
  100% {
    clip-path: polygon(100% 0, 100% 100%, 50% 50%);
  }
}
.mat-wedge.wackelt {
  animation: mat-wackeln 0.72s cubic-bezier(0.33, 1, 0.5, 1);
}

/* Geladene Maske: der Keil BLEIBT, wo ihn das Ueberfahren hingefuehrt hat —
   mit der Spitze auf dem Kreuzungspunkt der Platzhaltermarkierung. Er stand
   vorher auf 72 % und rutschte damit nach dem Laden wieder ein Stueck
   zurueck; genau das sah aus, als loese sich die Maske wieder.        */
.mat-wedge.has-mask {
  clip-path: polygon(100% 0, 100% 100%, 50% 50%);
}
/* Ueberfahren und Ziehen: die Spitze faehrt bis in die Mitte des Platzes,
   also genau auf den Kreuzungspunkt der Platzhaltermarkierung.          */
.mat-wedge:hover,
.mat-wedge.drag-over {
  clip-path: polygon(100% 0, 100% 100%, 50% 50%);
}
/* Gewendet wird hier nichts mehr — an dieser schmalen Form sah das
   Kippen nur gequetscht aus. Stattdessen faehrt der Keil ein und wieder
   aus: die Spitze zieht sich an den rechten Rand zurueck, dort wechselt
   die Farbe, und dann schiebt er sich als roter Keil bis zur Mitte vor,
   mit demselben Nachwackeln wie beim Laden einer Maske. Geht der Zeiger,
   laeuft dasselbe Spiel zurueck in Schwarz.                         */
@keyframes mat-rot-rein {
  0% {
    clip-path: polygon(100% 0, 100% 100%, 50% 50%);
    background: var(--black);
  }
  26% {
    clip-path: polygon(100% 0, 100% 100%, 100% 50%);
    background: var(--black);
  }
  27% {
    clip-path: polygon(100% 0, 100% 100%, 100% 50%);
    background: var(--red);
  }
  52% {
    clip-path: polygon(100% 0, 100% 100%, 34% 50%);
    background: var(--red);
  }
  68% {
    clip-path: polygon(100% 0, 100% 100%, 60% 50%);
    background: var(--red);
  }
  81% {
    clip-path: polygon(100% 0, 100% 100%, 43% 50%);
    background: var(--red);
  }
  92% {
    clip-path: polygon(100% 0, 100% 100%, 54% 50%);
    background: var(--red);
  }
  100% {
    clip-path: polygon(100% 0, 100% 100%, 50% 50%);
    background: var(--red);
  }
}
@keyframes mat-schwarz-rein {
  0% {
    clip-path: polygon(100% 0, 100% 100%, 50% 50%);
    background: var(--red);
  }
  26% {
    clip-path: polygon(100% 0, 100% 100%, 100% 50%);
    background: var(--red);
  }
  27% {
    clip-path: polygon(100% 0, 100% 100%, 100% 50%);
    background: var(--black);
  }
  52% {
    clip-path: polygon(100% 0, 100% 100%, 34% 50%);
    background: var(--black);
  }
  68% {
    clip-path: polygon(100% 0, 100% 100%, 60% 50%);
    background: var(--black);
  }
  81% {
    clip-path: polygon(100% 0, 100% 100%, 43% 50%);
    background: var(--black);
  }
  92% {
    clip-path: polygon(100% 0, 100% 100%, 54% 50%);
    background: var(--black);
  }
  100% {
    clip-path: polygon(100% 0, 100% 100%, 50% 50%);
    background: var(--black);
  }
}
/* Der rote Keil steht bis zur Mitte und schlaegt dabei alles andere —
   er muss deshalb NACH der geladenen Maske und dem Ueberfahren stehen:
   gleiche Spezifitaet, und dann entscheidet die Reihenfolge.        */
.mat-wedge.rot,
.mat-wedge.rot:hover {
  clip-path: polygon(100% 0, 100% 100%, 50% 50%);
  background: var(--red);
  animation: mat-rot-rein 0.82s cubic-bezier(0.33, 1, 0.5, 1);
}
.mat-wedge.zurueck,
.mat-wedge.zurueck:hover {
  animation: mat-schwarz-rein 0.82s cubic-bezier(0.33, 1, 0.5, 1);
}
/* Das Kreuz sitzt im Schwerpunkt des Dreiecks: bei den Punkten
   (100 % | 0), (100 % | 100 %) und (50 % | 50 %) liegt der bei 83 % / 50 %. */
.mat-wedge-del {
  position: absolute;
  left: 83%;
  top: 50%;
  transform: translate(-50%, -50%);
  width: 15px;
  height: 15px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  z-index: 2;
  font-size: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s;
}
/* Es taucht erst auf, wenn der rote Keil ausgefahren ist — vorher gibt
   es keine Flaeche, auf der es stehen koennte.                     */
.mat-wedge.rot .mat-wedge-del {
  opacity: 0.9;
  pointer-events: auto;
  transition-delay: 0.36s;
}
.mat-wedge-del:hover {
  opacity: 1;
}
/* Die Strichstaerke steckt in --kx, der halben Breite. Beim Ueberfahren
   wird sie fuer beide Kreuze — hier und auf der Rueckseite der
   Materialreferenz — auf denselben, kraeftigeren Wert gehoben; die
   blosse Aufhellung war als Rueckmeldung zu leise.                 */
.mat-wedge-del {
  --kx: 0.85px;
}
.mat-wedge-del:hover {
  --kx: 1.2px;
}
.mat-wedge-del::before,
.mat-wedge-del::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.mat-wedge-del::before {
  background: linear-gradient(
    to bottom right,
    transparent calc(50% - var(--kx)),
    #fff calc(50% - var(--kx)),
    #fff calc(50% + var(--kx)),
    transparent calc(50% + var(--kx))
  );
}
.mat-wedge-del::after {
  background: linear-gradient(
    to top right,
    transparent calc(50% - var(--kx)),
    #fff calc(50% - var(--kx)),
    #fff calc(50% + var(--kx)),
    transparent calc(50% + var(--kx))
  );
}

/* Gelöscht wird nur auf der Rückseite: ein weißes Kreuz oben links entfernt
   Materialbild und Maske zusammen — wie das Kreuz der Historien-Miniaturen. */
.mat-del {
  position: absolute;
  top: 8px;
  left: 8px;
  width: 16px;
  height: 16px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  z-index: 5;
  font-size: 0;
  opacity: 0.7;
  transition: opacity 0.15s;
}
/* Dieselbe Mechanik wie beim Kreuz des Maskenkeils, und beim Ueberfahren
   dieselbe Breite — die beiden gehoeren sichtbar zusammen.        */
.mat-del {
  --kx: 0.85px;
}
.mat-del:hover {
  --kx: 1.2px;
}
.mat-del::before,
.mat-del::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.mat-del::before {
  background: linear-gradient(
    to bottom right,
    transparent calc(50% - var(--kx)),
    #fff calc(50% - var(--kx)),
    #fff calc(50% + var(--kx)),
    transparent calc(50% + var(--kx))
  );
}
.mat-del::after {
  background: linear-gradient(
    to top right,
    transparent calc(50% - var(--kx)),
    #fff calc(50% - var(--kx)),
    #fff calc(50% + var(--kx)),
    transparent calc(50% + var(--kx))
  );
}
/* heller beim Überfahren — Rückmeldung, dass der Zeiger richtig sitzt */
.mat-del:hover {
  opacity: 1;
}

/* Ausgeblendete Zonen — bleiben im DOM, damit der übrige Code weiterläuft */
.ctx-hidden {
  display: none !important;
}
/* Waehrend eine Karte wendet, darf sie ueber ihren Platz hinausragen:
   die nahe Kante waechst durch die Perspektive, und ein Schnitt an der
   Kante liesse die Flaeche abgeschnitten kippen. Sobald sie steht, passt
   sie wieder in ihren Platz, und es wird wieder geschnitten.        */
body.mat-wendet .mat-list {
  overflow: visible;
}
body.mat-wendet aside.ctx {
  overflow: visible;
}
/* Und sie liegt ueber ihren Nachbarn. Jeder Platz traegt `perspective`
   und ist damit ein eigener Stapelzusammenhang; gemalt wird in der
   Reihenfolge des Dokuments, der Platz darunter also zuletzt. Er deckte
   die gewachsene Unterkante der wendenden Karte ab — sie sah beschnitten
   aus. Beim untersten Platz fiel es nie auf: unter ihm liegt nichts. */
.mat-slot.wendet {
  z-index: 30;
}
/* Drei Plätze teilen sich die Panelhöhe zu gleichen Teilen */
.mat-list {
  min-height: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

aside.ctx.open {
  transform: translateX(0);
}
/* Die senkrechten Linien beider Menues bleiben ausgeblendet — so
   gewuenscht.                                                        */
#ctx-line,
#panel-line {
  display: none !important;
}
#ctx-line {
  position: fixed;
  pointer-events: none;
  right: calc(var(--sw) + 22px);
  top: calc(var(--bild-achse) - var(--menue-h) / 2);
  height: var(--menue-h);
  width: 1px;
  background: var(--border);
  z-index: 199;
  transform: translateX(calc(var(--sw) + 26px));
  transition: transform 0.3s ease;
}
#ctx-line.open {
  transform: translateX(0);
}
body.menu-open #ctx-line {
  transform: translateX(calc(var(--sw) + 26px)) !important;
}
/* Vertikale Linie linkes Panel — Spiegel von #ctx-line */
#panel-line {
  position: fixed;
  pointer-events: none;
  left: calc(var(--sw) - 4px);
  top: calc(var(--bild-achse) - var(--menue-h) / 2);
  height: var(--menue-h);
  width: 1px;
  background: var(--border);
  z-index: 201;
  transform: translateX(calc(-1 * (var(--sw) + 26px)));
  transition: transform 0.3s ease;
}
#panel-line.open {
  transform: translateX(0);
}

#map {
  min-height: 0;
  background: var(--xlight);
  position: relative;
  overflow: hidden;
}
