/* ============================================================================
   DIE SAMMELKARTE — ERZEUGT, NICHT VON HAND GESCHRIEBEN.

   Quelle: docs/entwurf/kartensheet.html, Abschnitte 2 bis 4.
   Erzeugt mit: node scripts/karte-aus-sheet.mjs

   AENDERUNGEN GEHOEREN INS SHEET, NICHT HIERHER. Was hier steht, wird beim
   naechsten Lauf ueberschrieben; scripts/karte-sync-test.mjs faellt um, sobald
   beide auseinanderlaufen.

   Die Karte ist ein CONTAINER: alle Innenmasse stehen in cqw, damit dieselbe
   Karte in jeder Groesse gleich aussieht. Referenz ist 272 px Breite —
   1 cqw = 2,72 px. Die Breite kommt von aussen ueber --kb.
   ============================================================================ */

/* Seltenheitsfarben. Sie stehen hier und nicht in styles.css, weil die Karte
   ohne sie keinen Rahmen hat — eine Datei, die man einbinden kann, muss fuer
   sich funktionieren. Werte 1:1 aus rarityStyle in public/app.js. */
:root {
  --common: #8fa894;
  --uncommon: #5bbd84;
  --rare: #4aa6e0;
  --epic: #a877f0;
  --mythic: #f0c04a;
}

/* ===========================================================================
   2. DIE KARTE
   =========================================================================== */

/* --- Die vier Zahlen, die die Karte bewegen, MUESSEN angemeldet sein ---
   Eine nicht angemeldete Custom Property hat fuer den Browser den Typ
   „irgendein Text". Zwischen zwei Texten gibt es kein Dazwischen, also
   animiert er sie DISKRET: der Wert springt bei 50 % um, statt zu gleiten.

   Genau das ist mit `schweben` vier Wochen lang passiert. Die Karte stand
   drei Sekunden schraeg, klappte in einem Bild in die andere Lage und stand
   dort wieder drei Sekunden. Von aussen sieht das nicht nach einem kaputten
   Uebergang aus, sondern nach GAR KEINER Bewegung — man erwischt den einen
   Sprung nie.

   Mit `syntax` kennt der Browser den Typ und rechnet dazwischen. Das ist
   keine Feinheit: es ist der Unterschied zwischen einer Karte, die lebt, und
   einer, die ein Standbild ist.

   DIE VERERBUNG IST BEI DEN VIER NICHT GLEICH, und der Unterschied ist der
   Grund, warum Holo einmal stillstand:

   `--rx`/`--ry` erbt NICHT. Die Neigung wirkt auf `transform` der Karte
   selbst; geerbt wuerde eine Karte in einer Karte (die Rueckseite im Dreher)
   die Neigung der aeusseren uebernehmen und doppelt kippen.

   IHR RUHEWERT IST SEIT DEM 06.08.2026 NULL, und das haengt an der
   Ruheschaukel: die sitzt nicht mehr auf der Karte, sondern auf ihrem
   HALTER (siehe `@keyframes schweben`). Der Halter traegt damit auch die
   Ruhelage. Stuenden hier weiter 3deg/-2deg, kaeme die Neigung zweimal —
   einmal vom Halter, einmal von der Karte.

   `--gx`/`--gy` MUSS erben. Der Glanzfleck sitzt zwar auf `.karte::before` —
   einem Pseudoelement der Karte —, aber Holo, Kehrholo und der Metallwisch
   lesen denselben Wert auf `.kinnen::after`, also auf einem KIND. Mit
   `inherits:false` sah dieses Kind immer nur den Startwert 50 %: der
   Glanzfleck wanderte, die Folie stand. Auf einer Holokarte ist die Folie
   der ganze Effekt — die Karte sah damit im Raster tot aus, obwohl die Zahl
   an ihr korrekt lief. */
@property --rx{ syntax:'<angle>';      inherits:false; initial-value:0deg }
@property --ry{ syntax:'<angle>';      inherits:false; initial-value:0deg }
@property --gx{ syntax:'<percentage>'; inherits:true;  initial-value:50% }
@property --gy{ syntax:'<percentage>'; inherits:true;  initial-value:28% }
/* `--gs` ist die GLANZSTRECKE: eine Zahl, in die BEIDE Achsen einlaufen, und
   die einzige, an der die Folien haengen.

   Warum nicht `--gx`, wie bis zum 06.08.2026? Weil senkrechtes Scrollen `--gx`
   NICHT bewegt. Im Sammlungsraster steht eine Karte in ihrer Spalte; beim
   Scrollen wandert sie nach oben, nicht zur Seite. Gemessen ueber acht
   Scrollschritte in der Sammlung:

     --gy   52,0 %  ->  11,5 %     (wandert)
     --gx   58,5 %  ->  58,5 %     (steht)

   Holo und Kehrholo lasen ausschliesslich `--gx`. Beim Scrollen durch die
   eigene Sammlung bewegte sich damit an der Folie exakt nichts — die Karte
   war ein Standbild mit einem aufgemalten Regenbogen. Genau so kam es aus dem
   Feld zurueck: „sieht wie ein statisches Design aus".

   Die Gewichte (0,45 waagerecht, 0,62 senkrecht) folgen nicht der Optik,
   sondern der BEWEGUNG, die es hier gibt. Physikalisch schoebe eine 112-Grad-
   Bande vor allem waagerecht; das waere richtig gerechnet und im Produkt
   wirkungslos, weil die waagerechte Achse im Raster gedaempft ist und beim
   Scrollen stillsteht.

   DER WERT LIEGT ZWINGEND ZWISCHEN 0 UND 100 %, und daran haengt mehr als
   Ordnungsliebe: er ist die `background-position` der Folien, und die Folien
   laufen mit `background-repeat:no-repeat`.

   Ein Bild der Breite S·W (S > 1) deckt die Karte bei jeder Position p in
   [0, 100] vollstaendig ab — der Versatz ist (p/100)·(1−S)·W, also nie
   positiv, und die rechte Kante liegt bei W·((p/100)(1−S) + S) >= W fuer
   p <= 100. Ausserhalb dieses Bereichs endet das Bild im Sichtfeld, und
   genau dort stand die harte senkrechte Linie, die aus dem Feld gemeldet
   wurde: `--gs` lief bis 137 %, die Position mit Faktor 1,6 bis 219 %, und
   ab 100 % begann die naechste Kachel — bei einem schraegen Streifenmuster
   mit sichtbarer Fuge, weil sich das Muster nicht auf die Kachelbreite
   reimt.

   Deshalb wird geklemmt statt multipliziert. Das ist die einzige Loesung,
   die von Winkel, Seitenverhaeltnis und Kachelbreite UNABHAENGIG ist — die
   Alternative waere, die Farbstopps so zu waehlen, dass die Kachel exakt
   aufgeht, und die faellt bei der naechsten Winkelaenderung still um. */
@property --gs{ syntax:'<percentage>'; inherits:true;  initial-value:50% }

/* ---- DER KIPPANTEIL: was das GERAET beitraegt ----

   Vier eigene Groessen, und das ist der ganze Trick. Der Lagesensor koennte
   `--gs`, `--gx`, `--gy`, `--rx`, `--ry` auch direkt schreiben — genau so war
   es bis zum 06.08.2026, und genau daran ist es gescheitert:

   Eine laufende Animation schlaegt in der Kaskade jeden Inlinewert. Wer per
   JavaScript schreiben will, muss also `animation: none` setzen — und das
   haelt nicht nur die Ruheschaukel an, sondern auch `glanzlauf`, also die
   Zeitachse, die das SCROLLEN uebersetzt. Ein Sensor, der auf Android 60-mal
   je Sekunde feuert, haette den Schimmer damit dauerhaft abgeschaltet.

   Additiv geht beides gleichzeitig: die Zeitachse animiert `--gs`, der Sensor
   schreibt `--gk` daneben, und die Folie liest die Summe. Zwei Quellen, kein
   Vorrang, kein Streit um dieselbe Variable.

   Sie werden NICHT animiert, brauchen also kein `@property` fuer die
   Interpolation — angemeldet sind sie trotzdem, damit `calc()` sie sicher als
   Prozent bzw. Winkel behandelt. */
@property --gk { syntax:'<percentage>'; inherits:true;  initial-value:0% }
@property --kx { syntax:'<percentage>'; inherits:true;  initial-value:0% }
@property --ky { syntax:'<percentage>'; inherits:true;  initial-value:0% }
@property --krx{ syntax:'<angle>';      inherits:false; initial-value:0deg }
@property --kry{ syntax:'<angle>';      inherits:false; initial-value:0deg }

.karte{
  container-type:inline-size;
  width:var(--kb,272px); aspect-ratio:63/88; position:relative; isolation:isolate;
  /* Radius und Rahmenbreite in PROZENT, nicht in cqw: ein Element kann seinen
     EIGENEN Container nicht abfragen — cqw faellt hier auf den Viewport zurueck
     und ergab auf jeder Kartengroesse dieselben 33 px Rand (bei der kleinen
     Karte die halbe Breite). Derselbe Fehler wie 7vw statt 7cqw, eine Ebene
     tiefer. Die Prozentwerte sind so gewaehlt, dass 272x380 wieder 9 px ergibt. */
  border-radius:3.3%/2.36%; display:flex; flex-direction:column;
  color:#f4f5ef;
  /* Kartenrand: metallischer Verlauf in der Seltenheitsfarbe. Fuenf Stopps,
     weil drei zu flach wirken und sieben zu unruhig. */
  background:linear-gradient(150deg,
    color-mix(in srgb, var(--rf) 92%, #fff) 0%,
    color-mix(in srgb, var(--rf) 55%, #000) 34%,
    color-mix(in srgb, var(--rf) 88%, #fff) 52%,
    color-mix(in srgb, var(--rf) 45%, #000) 74%,
    color-mix(in srgb, var(--rf) 75%, #fff) 100%);
  box-shadow:0 18px 42px rgba(0,0,0,.45), 0 2px 6px rgba(0,0,0,.3);
  /* NUR die Anteile, die JavaScript schreibt: Zeiger (`--rx`/`--ry`) und
     Geraet bzw. Finger (`--krx`/`--kry`). Die RUHELAGE und die Schaukel
     stehen auf dem Halter — siehe `@keyframes schweben`. */
  transform:perspective(1200px)
    rotateX(calc(var(--rx,0deg) + var(--krx,0deg)))
    rotateY(calc(var(--ry,0deg) + var(--kry,0deg)));
  transition:transform .25s cubic-bezier(.2,.7,.3,1);
  --rf:var(--common); --glanz:.10; --holo:0;
  /* Vitrinenwaende. Sie stehen HIER und nicht auf .szene, obwohl sie nur
     dort gebraucht werden: eine Regel am Element selbst schlaegt jede
     Vererbung, und eine Veredelung haette sie dann nicht mehr aendern
     koennen. Gemessen blieb der Raum bei .v-gold grau, waehrend der
     Kartenrand schon Metall trug. Ohne Veredelung traegt er die Farbe des
     Reichs — dieselbe Variable, die die Unterkante des Bildfelds faerbt. */
  --wand:color-mix(in srgb, var(--rm, #7fb6d8) 24%, #101923);
  --wandhell:color-mix(in srgb, var(--rm, #7fb6d8) 62%, #2c4256);
  --wandtief:color-mix(in srgb, var(--rm, #7fb6d8) 10%, #080c12);
  /* Fast matt als Normalfall. Ein Putz- oder Holzraum spiegelt nichts, und
     ein Spiegelbild an einer Wand, die offensichtlich nicht spiegeln kann,
     sieht nach Fehler aus statt nach Material. Nur Metall geht hoch. */
  --wandglanz:.07;
  /* Die Kante zur Kamera. Matte Raeume laufen auf Schwarz — das ist die
     Hohlkehle. Metall darf das NICHT: die Spiegelung lebt von hellen und
     dunklen Umschlaegen auf der Flaeche, und auf schwarzem Grund ist
     davon nichts zu sehen. Deshalb hebt Gold diesen Wert an. */
  --wandvorn:#04060a;
}
/* DIE RUHESCHAUKEL BEWEGT DIE PERSPEKTIVE, NICHT DAS LICHT.

   Am 06.08.2026 liefen hier zwischenzeitlich auch `--gx`, `--gy` und `--gs`
   mit: die Karte schimmerte dann von selbst. Das sah gut aus und war falsch,
   und der Grund steht in der Rueckmeldung, die es beendet hat — sinngemaess:
   der Schimmer soll daran haengen, WIE man scrollt, nicht von allein laufen.

   Das ist keine Geschmacksfrage. Eine Folie, die sich ohne Zutun bewegt, ist
   ein Bildschirmschoner: sie sagt nichts ueber die Karte und nichts ueber die
   eigene Bewegung. Eine Folie, die sich nur bewegt, WEIL man scrollt oder
   dreht, ist das Gegenteil — sie macht die eigene Hand sichtbar, und genau
   das tut echte Folie auf einem Tisch.

   Die Neigung bleibt: sie ist die Perspektive der Karte, kein Reflex.

   SIE SITZT AUF DEM HALTER UND BEWEGT `transform` — NICHT DIE KARTE UND
   NICHT `--rx`/`--ry`. Das ist die teuerste Einzelzeile, die dieses Projekt
   je hatte, und sie war voellig unsichtbar.

   Bis zum 06.08.2026 stand hier:

     @keyframes schweben{0%,100%{--rx:3deg;--ry:-2deg}50%{--rx:-2deg;--ry:2.5deg}}

   Custom Properties sind KEINE Compositor-Eigenschaften. Nur `transform`
   und `opacity` laufen dort; alles andere — auch eine ueber `@property`
   angemeldete Zahl — laesst den Browser bei JEDEM Bild den Stil neu rechnen.
   Auf jeder Karte, im Leerlauf, fuer immer.

   Am Sammlungsraster mit 12 Karten gemessen, Desktop, NICHTS angefasst:

                                   Recalcs/s   CPU je Sekunde
     --rx/--ry (bis 06.08.)             68       940 ms
     transform auf dem Halter            0         0 ms
     Schaukel ganz aus                   0         0 ms

   940 ms je Sekunde heisst: der Hauptthread ist voll, BEVOR jemand etwas
   anfasst. Ein Handy ist drei- bis fuenfmal langsamer. Genau das ist das
   Ruckeln, das vier Runden lang beim Drehen gesucht wurde — gemessen wurde
   immer nur waehrend der Bewegung, nie im Leerlauf.

   ZWEI WEGE WURDEN VERWORFEN, beide gemessen:

     `animation-composition:add` auf der Karte    839 ms/s — laeuft trotz
     reiner transform-Keyframes im Hauptthread, weil der Grundwert je Bild
     aufgeloest werden muss. Sieht richtig aus, kostet fast dasselbe.

     Ruheschaukel streichen                       0 ms/s, aber die Karten
     stehen dann tot im Raster.

   DER HALTER IST DIE LOESUNG, WEIL DORT NIEMAND SONST SCHREIBT. Eine
   laufende Animation schlaegt jeden Inlinewert — deshalb konnten Schaukel
   (CSS) und Kippung (JavaScript) nie auf demselben Element stehen, und
   deshalb gab es ueberhaupt die vier Zusatzgroessen `--gk`/`--kx`/`--ky`/
   `--krx`. Ein Schreiber je Element loest das strukturell:

     Halter   CSS, Ruhelage + Schaukel   transform
     Karte    JavaScript, Zeiger/Gerät   transform aus --rx/--ry/--krx/--kry

   DIE PERSPEKTIVE GEHOERT IN DIE KEYFRAMES. Ohne sie ist die Drehung eine
   reine Scherung ohne Tiefe — die Karte kippt dann flach weg, statt sich zu
   neigen. */
@keyframes schweben{
  0%,100%{transform:perspective(1200px) rotateX(3deg)  rotateY(-2deg)}
  50%    {transform:perspective(1200px) rotateX(-2deg) rotateY(2.5deg)}
}
/* Die drei Halter der App plus `.kartenhalt` fuer alles Weitere. `:has()`
   statt einer Klasse am Halter: die Karte entscheidet ueber `lebt`, ob sie
   schaukelt, und diese Entscheidung soll nicht an zwei Orten stehen. */
.kartenhalt{display:grid; justify-items:center}
.kartenplatz:has(> .karte.lebt),
.studio-karte:has(.karte.lebt),
.kartenhalt:has(.karte.lebt){animation:schweben 6s ease-in-out infinite}

/* ===========================================================================
   DER SCHIMMER HAENGT AM SCROLLEN — und zwar OHNE JavaScript.

   Das ist die dritte Fassung dieser Mechanik, und die ersten beiden sind an
   derselben Klasse Fehler gescheitert: sie hingen an einem `scroll`-Zuhoerer,
   und ob der in einem Capacitor-WebView ankommt, liess sich von aussen nicht
   entscheiden. Am Rechner lief es, auf dem Geraet nicht — viermal.

   `animation-timeline: view()` bindet den Fortschritt der Animation direkt an
   den Weg, den DIESE Karte durch das Sichtfeld nimmt. Kein Ereignis, kein
   rAF, kein Hauptthread: der Browser rechnet es im Compositor. Damit gibt es
   auch nichts mehr, was „nicht ankommen" koennte.

     0 %    die Karte tritt unten ins Bild
     100 %  sie verlaesst es oben

   Genau das ist die Bewegung, die eine echte Folie ins Licht dreht — und es
   ist ausschliesslich die Bewegung des Nutzers, kein Selbstlaeufer: steht das
   Bild, steht die Folie.

   `1ms linear` ist die uebliche Schreibweise: die Dauer wird von der Zeitachse
   ersetzt, Firefox braucht aber einen Wert ungleich null. Wo `view()` fehlt,
   greift der JavaScript-Rueckfall in `karte-leben.js` (Merkmalstest, nicht
   Browserabfrage).

   Die Werte bleiben zwischen 12 % und 88 %: `--gs` ist die
   `background-position` der Folien, und ausserhalb 0..100 % laeuft die
   Kachelkante ins Bild. Begruendung bei `@property --gs`. */
@keyframes glanzlauf{
  from{--gs:88%; --gx:32%; --gy:16%}
  to  {--gs:12%; --gx:68%; --gy:84%}
}
/* DIE KARTE TRAEGT NUR NOCH `glanzlauf`, und das ist genau richtig: die
   Zeitachse `view()` laeuft nur, WAEHREND gescrollt wird. Steht das Bild,
   steht die Animation — gemessen 0 Recalcs je Sekunde im Leerlauf. Die
   Ruheschaukel lief dagegen an der Uhr und damit immer; sie steht deshalb
   jetzt auf dem Halter. */
.karte{animation:glanzlauf 1ms linear; animation-timeline:view()}
/* Listenansichten duerfen dieselbe physische Karte zeigen, ohne fuer jede
   Offscreen-Karte eine eigene Scroll-Zeitachse und Sensorbewegung zu halten. */
.karte.karten-vorschau{animation:none;animation-timeline:auto}

/* Ebenen, damit sich Veredelungen nicht gegenseitig verdecken:
     1 Rand   2 Innenflaeche   3 Inhalt   4 Bildeffekt   5 Folie   6 Glanz   7 Siegel */
/* Der Kartenrand entsteht als MARGIN der Innenflaeche, nicht als Padding der
   Karte — sonst muesste die Karte ihre eigene Containerbreite kennen. */
.kinnen{
  flex:1; margin:2.6cqw; display:flex; flex-direction:column; gap:1.5cqw;
  border-radius:1.8cqw; padding:3cqw;
  background:linear-gradient(172deg,#1a231a 0%,#121a13 46%,#0c110d 100%);
  position:relative; z-index:2; overflow:hidden;
}
.kinnen > *{position:relative; z-index:3}

/* Glanzfleck UND Lichtwisch — liegen immer oben und folgen der Neigung.

   ZWEI EBENEN AUF EINEM ELEMENT, und das ist kein Sparen an DOM-Knoten,
   sondern die richtige Zuordnung: beide sind dasselbe Licht, einmal als
   weicher Fleck (woher es kommt) und einmal als harter Streifen (wie es ueber
   die Flaeche laeuft).

   DER STREIFEN IST DER TEIL, DEN MAN „SCHIMMERN" NENNT. Der weiche Fleck
   hebt eine grosse Flaeche um wenig an; das liest sich als Helligkeit, nicht
   als Bewegung. Erst eine schmale, harte Kante, die durchs Bild zieht, wird
   als wanderndes Licht gesehen. Deshalb hatte Metall bisher als einziges
   einen — und war als einziges unstrittig „glaenzend".

   `--wisch` ist 0, solange keine Veredelung ihn setzt: Matt bleibt matt.
   Nicht ueber `@property` angemeldet, weil er sich nie bewegt — er ist die
   STAERKE des Streifens, `--gs` ist seine Position. */
.karte::before{
  content:''; position:absolute; inset:0; border-radius:inherit; pointer-events:none; z-index:6;
  background:
    linear-gradient(104deg, transparent 36%,
      rgba(255,255,255,calc(var(--wisch,0) * .55)) 45%,
      rgba(255,255,255,var(--wisch,0)) 50%,
      rgba(255,255,255,calc(var(--wisch,0) * .55)) 55%, transparent 64%),
    radial-gradient(58% 42% at calc(var(--gx,50%) + var(--kx,0%)) calc(var(--gy,28%) + var(--ky,0%)),
      rgba(255,255,255,var(--glanz)) 0%, rgba(255,255,255,0) 60%);
  background-size:300% 100%, auto;
  background-position:calc(var(--gs,50%) + var(--gk,0%)) 0, 0 0;
  background-repeat:no-repeat, no-repeat;
  mix-blend-mode:screen;
}

/* --- Kopfzeile --- */
.kzeile{display:flex; align-items:flex-start; gap:2.2cqw}
.kzeile .nm{font-size:5.8cqw; font-weight:850; line-height:1.05; letter-spacing:-.02em; flex:1; min-width:0}
.kraftmarke{display:flex; align-items:baseline; gap:1.1cqw; flex:none}
.kraftmarke .z{font-size:6.8cqw; font-weight:900; line-height:1; color:var(--gold); font-variant-numeric:tabular-nums}
.kraftmarke .e{font-size:2.6cqw; letter-spacing:.1em; text-transform:uppercase; font-weight:850; color:rgba(240,192,74,.6)}
/* --- Artrang: eine Marke und ein Rahmenton ---
   Er gehoert der ART und liegt auf jedem Exemplar davon. Deshalb faerbt er
   NUR den Rand und setzt eine kleine Marke: Foto, Werte und Veredelung
   bleiben, was sie sind. Eine Auszeichnung, die das Innere veraendert, waere
   eine zweite Karte statt einer Auszeichnung. */
.rangmarke{flex:none; font-size:3cqw; letter-spacing:.4cqw; line-height:1;
  color:var(--rangfarbe,#a8925f); text-shadow:0 0 1.6cqw var(--rangfarbe,#a8925f)}
.karte.rang-1{--rangfarbe:#b8b2a4}
.karte.rang-2{--rangfarbe:#d8c07a}
.karte.rang-3{--rangfarbe:#f0c04a}
.karte.rang-1 .kinnen{box-shadow:inset 0 0 0 .5cqw rgba(184,178,164,.55)}
.karte.rang-2 .kinnen{box-shadow:inset 0 0 0 .7cqw rgba(216,192,122,.7)}
.karte.rang-3 .kinnen{box-shadow:inset 0 0 0 .9cqw rgba(240,192,74,.85),
  0 0 3cqw rgba(240,192,74,.25)}

.kmeta{display:flex; align-items:center; justify-content:space-between; gap:2cqw}
.ksterne{font-size:3.3cqw; letter-spacing:.55cqw; color:var(--rf); line-height:1}

/* --- DIE DREI AUSDAUERMARKEN SIND WEG (07.08.2026) ---
   `.kaus` stand hier und zeigte, wie viele Kaempfe DIESES Tier noch hat.
   Ausdauer gehoert seit dem Umbau dem SPIELER, nicht dem Exemplar — eine
   Marke je Karte waere jetzt dreimal dieselbe Zahl im Sammlungsraster und
   trotzdem die falsche.

   Die Kopfzeile traegt damit nur noch die Seltenheit. Das ist kein Verlust:
   `.kmeta` stand ohnehin unter Platzdruck, und Kraft (Vorrat INNERHALB eines
   Kampfes) steht weiterhin als Zahl oben rechts. */

/* --- Bildfeld: der Held der Karte ---
   2:1, nicht 4:3. Bei 4:3 sprengt der Inhalt das Format 63:88 — gemessen 1,84
   statt 1,40, die Karte wird zum Zettel. */
.kbild{
  position:relative; border-radius:3px; border:1px solid rgba(255,255,255,.22);
  /* Die Unterkante traegt die Reichsfarbe — zweiter Traeger ohne eigenes
     Element, in der Machart des Seitenstreifens der App (.zeile::before). */
  border-bottom:2px solid var(--rm);
  aspect-ratio:2/1; display:grid; place-items:center; overflow:hidden;
  background:var(--welt); box-shadow:0 2px 10px rgba(0,0,0,.45) inset;
}
.kbild .tier{font-size:17cqw; filter:drop-shadow(0 4px 10px rgba(0,0,0,.55)); position:relative; z-index:3}
/* Motivfeld: traegt entweder den echten Fang oder das Sinnbild. Die
   Veredelungen greifen auf DIESES Element, nicht auf .tier — sonst wirkt
   eine Entsaettigung nur auf das Emoji und laesst das Foto unberuehrt, und
   genau dort will man sie beurteilen. */
.kbild .motivfeld{position:absolute; inset:0; z-index:3; display:grid; place-items:center;
  overflow:hidden}
/* --- Ausschnitt: verschiebbar und zoombar ---
   Ein 2:1-Bildfeld schneidet aus einem Hochkantfoto einen schmalen Streifen
   aus der Mitte. Beim Rotkehlchen blieb davon fast nur Hintergrund uebrig —
   das Tier sass oben. Ein fester Zuschnitt kann das nicht loesen, weil das
   Tier in jeder Aufnahme woanders steht.
   Drei Werte je Fang, dieselben wie beim Deckbild in der Sammlung:
   Verschiebung in X und Y, dazu ein Zoom. Sie stehen als Variablen an der
   Karte und lassen sich damit speichern, uebertragen und vorbelegen. */
/* --- Das Foto wird GANZ gezeigt, der Rahmen trotzdem gefuellt ---
   object-fit:cover schnitt bei jeder Aufnahme, die nicht zufaellig 2:1 ist,
   oben und unten weg. Bei der Hauskatze (448x363) sind das 38 % der Hoehe —
   uebrig blieben die Augen. Und weil das Tier in jeder Aufnahme woanders
   sitzt, rettet auch kein anderer fester Ausschnitt das.

   Deshalb contain: das Foto bleibt vollstaendig. Die Flaeche daneben fuellt
   dieselbe Aufnahme, stark unscharf und ueberzoomt — die Konvention aus
   Musik- und Videoapps. Sie erfindet nichts hinzu, sie nimmt die Farben aus
   genau diesem Bild, und der Rahmen ist trotzdem randlos gefuellt.

   Der Zoom bleibt: ab --fz > 1 waechst das Bild ueber den Rahmen hinaus,
   also zurueck Richtung Anschnitt — dann aber gewollt und einstellbar. */
.kbild .motivfeld .grund{position:absolute; inset:0; width:100%; height:100%;
  object-fit:cover; transform:scale(1.6); filter:blur(18px) saturate(1.35) brightness(.66)}
/* Weicher Uebergang: ohne ihn steht das scharfe Bild als Rechteck auf
   der Fuellung, und die liest sich als grauer Kasten daneben statt als
   Fortsetzung. Der Schatten am Bildrand verbindet beides. */
.kbild .motivfeld::after{content:''; position:absolute; inset:0; z-index:2;
  pointer-events:none;
  background:linear-gradient(90deg, rgba(0,0,0,.34) 0%, transparent 22%,
    transparent 78%, rgba(0,0,0,.34) 100%)}
/* Absolut positioniert, nicht als Grid-Item: .motivfeld zentriert mit
   place-items, und ein zentriertes Item wird NICHT gestreckt — height:100%
   loeste sich dann gegen die Inhaltshoehe auf. Gemessen war das Bild 185x214
   in einem 185x91 grossen Feld, und weil overflow:hidden den Ueberstand
   abschnitt, sah contain exakt wie cover aus: das Foto fuellte den Rahmen,
   oben und unten fehlte trotzdem alles. */
.kbild .motivfeld .fot{position:absolute; inset:0; width:100%; height:100%;
  object-fit:contain; display:block;
  /* Wie im Vollbild-Ausrichter: erst zoomen, dann den Fokus innerhalb des
     gezoomten Bildes verschieben. */
  transform:scale(var(--fz,1)) translate(var(--fx,0%), var(--fy,0%));
  transform-origin:50% 50%;
  filter:drop-shadow(0 .4cqw 1.2cqw rgba(0,0,0,.6))}
.kbild .motivfeld:has(.fot) .tier{display:none}
/* DAS KATALOGBILD IST GEKENNZEICHNET. Es zeigt die ART, nicht diesen Fang —
   ohne Marke waere es die stille Behauptung, der Spieler haette die Aufnahme
   gemacht. Leicht entsaettigt und mit einem Woertchen in der Ecke: sichtbar,
   aber nicht laut. Ein eigenes Foto bleibt unberuehrt. */
.kbild .motivfeld .fot.stock{filter:saturate(.82) drop-shadow(0 .4cqw 1.2cqw rgba(0,0,0,.6))}
.kbild .stockmarke{position:absolute; left:2.5cqw; bottom:2cqw; z-index:3;
  font-style:normal; font-size:2.4cqw; font-weight:800; letter-spacing:.06em;
  text-transform:uppercase; color:rgba(255,255,255,.62);
  text-shadow:0 .2cqw .6cqw rgba(0,0,0,.9)}
/* Der Griff erscheint nur, wenn die Karte im Ausrichtemodus ist — sonst
   waere jede Karte im Raster versehentlich verschiebbar. */
/* In der Vitrine haengt das Foto als kleine Tafel im Raum — dort laesst sich
   ein Ausschnitt weder erkennen noch treffen. Zum Ausrichten tritt deshalb
   dasselbe flaechendeckende Bildfeld davor wie bei jeder anderen Karte, und
   der Raum verschwindet solange. Eingestellt wird EIN Ausschnitt, der
   danach in beiden Darstellungen gilt. */
.kbild.vitrine .richtfeld{display:none}
.karte.ausrichten .kbild.vitrine .richtfeld{display:grid; z-index:6}
.karte.ausrichten .kbild.vitrine .szene,
.karte.ausrichten .kbild.vitrine .dunst,
.karte.ausrichten .kbild.vitrine .lupe{display:none}
.karte.ausrichten .kbild{cursor:grab; outline:2px dashed var(--lime); outline-offset:-2px}
.karte.ausrichten .kbild:active{cursor:grabbing}
.ausrichthinweis{position:absolute; z-index:8; left:0; right:0; bottom:0;
  font-size:2.6cqw; letter-spacing:.06em; text-transform:uppercase; font-weight:850;
  text-align:center; padding:.8cqw 0; color:#0d1a06; background:var(--lime)}
.kbild .horizont{position:absolute; inset:auto 0 0 0; height:38%; z-index:2;
  background:linear-gradient(to top, rgba(0,0,0,.45), transparent)}

/* --- Vitrine: EIN Raum, zwei Kamerapositionen ---
   Das Bildfeld ist 242x121 px bei einer 272er Karte. Darin einen ganzen
   Raum zu zeigen ergibt briefmarkengrosse Waende — deshalb steht die Kamera
   auf der Karte DICHT vor dem Motiv: sichtbar sind das Tier, die Podestkante
   und die Bodenspiegelung. Erst der Klick faehrt sie zurueck.

   Gerechnet, nicht geschaetzt. Bei perspective:P erscheint ein Objekt bei
   Tiefe z um P/(P-z) skaliert. Mit P=85cqw (231 px):

     Kamera        Tafel (-18cqw)   Rueckwand (-55cqw)
     36cqw Karte      1,27x             0,82x
      4cqw Raum       0,86x             0,63x

   Die erste Fassung stand auf 46 cqw. Gemessen war die Tafel damit 1,53x
   vergroessert und die Rueckwand 0,92x — sie fuellte also fast das ganze
   Feld, und was daneben blieb, waren so stark verzerrte Waende, dass sie
   nicht mehr als Waende lesbar waren. Im Bild sah das aus wie ein Emoji auf
   einem Verlauf: kein Raum, kein Podest, keine Spiegelung.

   Bei einer Nahaufnahme entscheidet nicht der Zoom, sondern was NEBEN dem
   Motiv noch ins Feld passt. */
.kbild.vitrine{perspective:85cqw; perspective-origin:50% 34%; background:#04060a}
/* Der Raum ist BREITER als das Fenster, durch das man ihn sieht. Auf den
   ersten Blick unnoetig — bei 0 Grad ist der Ueberstand weggeschnitten. Er
   ist der einzige Grund, warum sich die Kamera ueberhaupt schwenken laesst:
   der Kasten ist 92 cqw tief, und beim Drehen wandert seine Rueckwand
   seitlich aus dem Feld. Gemessen sah man schon bei 28 Grad rechts einen
   schwarzen Keil neben der Seitenwand — den Punkt, an dem der Raum aufhoert.

   Der Ueberstand fuellt genau diesen Keil. Er wird zusammen mit der
   Schwenkgrenze KAM_MAX gewaehlt: mehr Winkel braucht mehr Ueberstand, und
   ein breiterer Raum laesst das Podest kleiner wirken. */
/* DER RAUM IST GROESSER ALS SEIN FENSTER, und zwar deutlich: gut zwei
   Feldbreiten und zwei Feldhoehen. Der Ueberstand ist bei 0 Grad
   weggeschnitten und trotzdem kein Verschnitt — er ist genau das, was beim
   Drehen ins Bild wandert.

   Gemessen wurde das, nicht geschaetzt (`dichtheit.mjs`): bei -16%/-26% waren
   23 von 24 Winkeln undicht, am schlimmsten 33 % dunkler Rand bei 300 Grad.
   Die Zahl ist der Anteil fast schwarzer Pixel im Randstreifen des Bildfelds
   — dort, wo der Kasten aufhoert, steht Nichts, und Nichts ist dunkler als
   jede Wand. */
.szene{
  position:absolute; inset:-60% -60%; transform-style:preserve-3d;
  /* GEDREHT WIRD UM DIE RAUMMITTE, nicht um die Vorderebene.
     Ohne `transform-origin` liegt die Achse bei z=0, also in der vorderen
     Oeffnung des Kastens. Der Raum SCHWENKT dann seitlich weg, statt sich zu
     drehen: schon bei 28 Grad stand rechts ein schwarzer Keil, und dagegen
     halfen nur Notbehelfe — Ueberstand und eine Schwenkgrenze von 20 Grad.
     Beides hat das Symptom bekaempft. Die Achse in die Mitte gelegt, bleibt
     der Kasten stehen und man dreht sich IN ihm. */
  transform-origin:50% 50% calc(var(--t) / -2);
  transform:translateZ(var(--kamZ,30cqw)) rotateX(var(--kamX,0deg)) rotateY(var(--kamY,0deg));
  transition:transform .22s ease-out;
  /* Raumtiefe. Bei 55 cqw fuellte die Rueckwand 74 von 94 px Feldhoehe — fuer
     Boden und Decke blieben je rund zehn Pixel, und ohne sichtbaren Boden
     liest sich kein Raum. Der Fluchtpunkt liegt zusaetzlich hoeher (34 %
     statt 46 %): der Blick geht leicht von oben auf das Podest. */
  --t:200cqw;
}
/* `> .w`, nicht ` .w` — und das ist kein Stilgeschmack, sondern ein
   behobener Fehler. `.w` heisst hier die WAND, im Markenblock auf der
   Rueckseite heisst `.w` der Schriftzug "WILD TRACK". Der Nachfahrenselektor
   traf beide: der Schriftzug bekam `position:absolute; inset:0`, legte sich
   ueber Ring und Unterzeile und war 63 px hoch statt 16. Gemessen starteten
   Ring und Schriftzug bei derselben Oberkante.

   Von aussen sah das aus, als wuerde die Rueckseite gar nicht rendern — die
   zweite Fehldiagnose an derselben Stelle. Sie rendert; zwei Regeln stritten
   sich um einen zwei Zeichen langen Klassennamen. Die Waende sind direkte
   Kinder von `.szene`, der Markenblock nicht — der Kindselektor trennt das
   sauber und laesst kein zweites Opfer zu. */
/* Die Waende sind EINSEITIG. Ohne das ist die Kartenrueckseite nicht
   erreichbar: sie steht im Raum, und wer sie ansehen will, muss hinter das
   Motiv — dort liegt die Rueckwand zwischen Kamera und Tafel, und im Bild
   war ab etwa 120 Grad nur noch Schiefer zu sehen. Zwei andere Wege dahin
   sind vorher gescheitert (Drehachse auf Motivtiefe legen, Kamera weiter
   zurueckziehen); beide scheiterten an derselben Wand.

   Eine Flaeche, die von hinten verschwindet, ist ausserdem das Richtige:
   eine echte Vitrine hat auch keine Rueckwand, die man von aussen sieht. */
/* Der `inset`-Schatten ist der Unterschied zwischen "Raum" und "Kasten".
   Sechs gleichmaessig ausgeleuchtete Flaechen mit harten Nahtkanten liest
   das Auge als Karton, und beim Drehen faellt genau das auf. In einem echten
   Raum ist es dort dunkel, wo zwei Waende zusammenstossen — Licht kommt aus
   der Ecke nicht mehr heraus. Jede Flaeche dunkelt deshalb zu ihren eigenen
   Raendern ab; wo zwei aneinanderstossen, summiert sich das zu einer weichen
   Kehle statt einer gezeichneten Linie. */
.szene > .w{position:absolute; inset:0; overflow:hidden; backface-visibility:hidden;
  box-shadow:inset 0 0 7cqw 2.5cqw rgba(0,0,0,.5)}

/* --- Material ---
   Hier lag bis zum 05.08.2026 ein Stapel aus elf harten Verlaufsstopps, der
   das Spitzlicht und die Buerstung von Metall NACHMALEN sollte. Er ist
   ersatzlos weg: beides steckt jetzt in der Materialaufnahme selbst
   (--wandtextur), und ein gemalter Reflex neben einem fotografierten ist
   nur noch Schmutz auf dem Bild.

   Was bleibt, ist das Spiegelbild des MOTIVS. Das kann kein Materialfoto
   mitbringen — es haengt am Fang, nicht am Stoff. */
/* Das Spiegelbild sitzt IN der Wand, nicht daneben. Das ist kein Stil,
   sondern Pflicht: filter/blur auf einem direkten Kind von .szene wuerde
   den ganzen 3D-Kontext zusammenklappen — derselbe Fehler wie beim
   Lichtkegel. Als Kind einer Wand ist es harmlos, weil die Wand selbst
   kein preserve-3d traegt. */
.szene > .w .refl{
  /* VON DER BILDFELDMITTE GERECHNET, nicht vom Wandfuss — und das ist
     derselbe Fehler, der beim Motiv schon einmal behoben wurde. Seit der
     Raum deutlich groesser ist als sein Fenster (Ueberstand 60 % je Seite),
     liegt der untere Rand jeder Wand weit UNTER dem sichtbaren Ausschnitt:
     `bottom:11cqw` schob die Spiegelung damit aus dem Bild.

     Gemessen war sie da — 54 x 89 px, `display:block` —, nur nirgends zu
     sehen. Auch mit `opacity:1` und der doppelten Groesse erschien nichts;
     genau das machte den Fall schwer, denn beides sieht nach "zu schwach
     eingestellt" aus, und man dreht dann an der falschen Zahl. */
  position:absolute; bottom:calc(50% - 11cqw); z-index:1; font-size:15cqw; line-height:1;
  opacity:calc(.5 * var(--wandglanz,.3)); pointer-events:none;
  filter:blur(2.5px) saturate(.55);
}
/* Die Tiefe des Motivs (24 cqw hinter der Raumkante) wird zur Position AN
   der Wand — die Seitenwaende sind um 90 Grad gedreht, ihre lokale x-Achse
   ist die Raumtiefe. */
/* DIE TIEFE WIRD GERECHNET, NICHT GESETZT. Hier stand `24cqw` — die
   Motivtiefe aus einer Zeit, in der der Raum 55 cqw tief war. Er ist heute
   200 cqw tief (`--t`), und das Motiv steht in seiner Mitte
   (`translateZ(calc(var(--t) / -2))`). Die Spiegelung sass damit fast an der
   Raumoeffnung, also perspektivisch weit ausserhalb des Bildfelds: gemessen
   bei x = -71 px, waehrend das Feld erst bei x = 109 px beginnt.

   Sie war deshalb bei JEDER Wand unsichtbar — auch bei Silber und Gold, wo
   sie das eigentliche Materialversprechen einloest. Und weil ein unsichtbarer
   Spiegel wie ein zu schwach eingestellter aussieht, dreht man an der
   Deckkraft statt an der Lage: mit `opacity:1` und doppelter Groesse erschien
   ebenfalls nichts. */
.szene .links .refl{left:calc(var(--t) / 2); transform:scaleX(-1) scaleY(1.04)}
.szene .rechts .refl{right:calc(var(--t) / 2); transform:scaleX(-1) scaleY(1.04)}
/* An der Rueckwand steht das Motiv fast davor — die Spiegelung ist dort
   kaum sichtbar und dient nur als Tiefenschein. */
.szene .hinten .refl{left:0; right:0; text-align:center; bottom:calc(50% - 9cqw);
  opacity:calc(.22 * var(--wandglanz,.3)); filter:blur(5px) saturate(.4)}
/* Jede Wand klappt um ihre eigene Kante nach HINTEN weg. Das Vorzeichen ist
   dabei nicht frei waehlbar: eine positive X-Rotation dreht +Y nach +Z, also
   zum Betrachter. Fuer den Boden (Ursprung an der Unterkante, Flaeche nach
   oben) muss die Drehung deshalb +90deg sein, fuer die Decke -90deg.

   Beim ersten Versuch stand es umgekehrt, und der Boden klappte nach vorne
   DURCH die Kameraebene. Gemessen war er dann 2540 px breit in einem 187 px
   breiten Feld und verdeckte alles — im Bild sah das aus wie ein flacher
   Verlauf ohne Raum. Ein 3D-Fehler zeigt sich selten als schiefes Bild,
   meistens als gar keines. */
/* Die Helligkeitsstaffel ist das, was den Raum lesbar macht — nicht die
   Perspektive. Rueckwand hell (dort haengt das Licht), Boden mittel,
   Seitenwaende und Decke fast schwarz. Lagen alle Flaechen im selben Ton,
   sah die Vitrine trotz korrekter Geometrie wie ein flacher Verlauf aus. */
/* Keine Flaeche laeuft auf Schwarz. Die Vorderkanten standen auf #04060a,
   und weil genau die das Bildfeld an den Raendern fuellen, sassen in allen
   vier Ecken schwarze Zwickel — der Raum hoerte sichtbar auf, statt das
   Feld zu tragen. Dunkelster Ton ist deshalb --wandtief, nie Schwarz. */
/* Zwei Hintergrundebenen je Wand: das Materialfoto oben, der Verlauf
   darunter. Das Foto traegt den STOFF, der Verlauf das LICHT — getrennt,
   damit eine Veredelung die Beleuchtung aendern kann, ohne das Material
   mitzuziehen, und umgekehrt.

   NICHT mehr gekachelt. `24% auto` wiederholte die Kachel vierfach, und
   genau daran ist der Vorgaenger gescheitert: in der Raumsicht las sich die
   Wiederholung als Tapete, weshalb dort die Textur ganz abgeschaltet wurde.
   `cover` legt das Foto einmal ueber die Flaeche — keine Naht, keine
   Wiederholung, und die Abschaltung in der Raumsicht wird ueberfluessig.

   `overlay` statt `soft-light`: soft-light laesst den Verlauf entscheiden
   und das Foto nur leicht modulieren — die satte Nussbaumfarbe waere unter
   einem dunkelgruenen Reichsverlauf verschwunden. Bei overlay entscheidet
   der Verlauf pro Stelle nur noch, ob AUFGEHELLT oder ABGEDUNKELT wird;
   Farbe und Detail kommen aus dem Foto. Das ist genau die gewuenschte
   Arbeitsteilung. */
/* HIER STAND `position:relative` UND HAT DEN GANZEN RAUM ABGESCHALTET.
   Derselbe Selektor steht weiter oben mit `position:absolute; inset:0` — bei
   gleicher Spezifitaet gewinnt der spaetere, und damit fielen alle sechs
   Waende aus der absoluten Lage zurueck in den Fluss. Gemessen: Hoehe 0 px,
   Oberkante 143 px ueber dem Bildfeld, also vollstaendig weggeschnitten.

   Der Fehler war von aussen nicht als Layoutfehler zu erkennen. Podest,
   Lichtkegel und Tafel liegen absolut und standen weiter richtig im Raum —
   sichtbar blieb ein schwebendes Foto vor Schwarz, und das liest sich als
   "die Waende sind noch nicht gebaut", nicht als "eine Zeile zu viel". Auch
   knallrot mit `!important` erschien nichts; erst das Boxmodell hat es
   gezeigt.

   `relative` war hier ueberfluessig: der Bezug fuer `::after` und `.refl`
   ist `absolute` genauso. */
.szene > .w{
  background-repeat:no-repeat, no-repeat;
  background-size:cover, cover;
  background-blend-mode:var(--wandmisch, overlay), normal;
}
/* DER FARBTON DER WAND liegt als eigene Schicht darueber, nicht in der
   Textur. So ergibt EINE Textur mehrere Waende — Schiefer, Moosgruen und
   Tiefseeblau teilen sich dasselbe Foto und sehen im Raum verschieden aus.
   Als zweite `background-image` waere sie mit dem Blendmodus der ersten
   verrechnet worden und haette das Material zugedeckt. */
.szene > .w::after{
  content:''; position:absolute; inset:0; pointer-events:none;
  background:var(--wandton, transparent); mix-blend-mode:color; opacity:.72;
}
.szene .hinten{transform:translateZ(calc(var(--t) * -1));
  background-image:var(--wandtextur), radial-gradient(105% 85% at 50% 26%,
    color-mix(in srgb,var(--wandhell) 92%,#fff) 0%, var(--wandhell) 32%,
    var(--wand) 68%, var(--wandtief) 100%)}
.szene .boden{top:auto; bottom:0; height:var(--t); transform-origin:50% 100%;
  transform:rotateX(90deg);
  background-image:var(--wandtextur), linear-gradient(to top,
    var(--wandtief) 0%, color-mix(in srgb,var(--wand) 78%,#000) 40%,
    color-mix(in srgb,var(--wandhell) 78%,#000) 100%)}
/* Decke und Seitenwaende laufen nach VORNE ins Schwarze. Ohne das liest
   sich der Raum als Kiste: fuenf gleich helle Flaechen mit harten Kanten
   sind ein Karton, kein Raum — und beim Drehen der Kamera faellt genau das
   auf. Ein Fotostudio loest es genauso, mit Licht hinten und Dunkelheit
   zur Kamera hin. */
.szene .decke{bottom:auto; top:0; height:var(--t); transform-origin:50% 0;
  transform:rotateX(-90deg);
  /* ohne Textur — Begruendung beim Container-Query weiter unten */
  background-image:none, linear-gradient(to bottom,
    var(--wandvorn) 34%, color-mix(in srgb,var(--wand) 62%,#000) 100%)}
/* Die Richtung ist bei den Seitenwaenden nicht offensichtlich, und sie war
   falsch: nach der 90-Grad-Drehung ist die zur KAMERA zeigende Kante bei
   .links die linke und bei .rechts die rechte — die Verlaeufe liefen also
   genau andersherum und dunkelten hinten ab statt vorne. Sichtbar wurde das
   als Karton mit hellen Seitenflaechen. */
.szene .links{right:auto; width:var(--t); transform-origin:0 50%; transform:rotateY(90deg);
  background-image:none, linear-gradient(to right,
    var(--wandvorn) 0%, var(--wandvorn) 18%, var(--wandtief) 58%, color-mix(in srgb,var(--wand) 82%,#000) 100%)}
.szene .rechts{left:auto; width:var(--t); transform-origin:100% 50%; transform:rotateY(-90deg);
  background-image:none, linear-gradient(to left,
    var(--wandvorn) 0%, var(--wandvorn) 18%, var(--wandtief) 58%, color-mix(in srgb,var(--wand) 82%,#000) 100%)}
/* DIE VIERTE WAND. Sie fehlte bis zum 05.08.2026 vollstaendig — der Raum war
   nach vorn offen, und wer sich weiter als ein paar Grad drehte, schaute
   hinaus. Genau das war der Befund „immer noch kein Raum mit vier Waenden",
   und die Schwenkgrenze von 20 Grad hat ihn nur verdeckt.

   Sie steht in der Vorderebene (z=0) und ist um 180 Grad gedreht, damit ihre
   Vorderseite nach INNEN zeigt. Zusammen mit `backface-visibility:hidden` an
   allen Waenden ergibt das genau das gewuenschte Verhalten: die Flaeche
   zwischen Kamera und Motiv verschwindet, die drei abgewandten bleiben
   stehen. Von vorn schaut man durch sie hindurch auf die Rueckwand, von
   hinten ist sie das, was man sieht.

   Ihr Verlauf ist der der Rueckwand, nur dunkler: sie liegt der Lichtquelle
   am weitesten entgegen, und ein zweiter heller Prospekt haette den Raum
   wieder zur Kiste gemacht. */
.szene .vorn{transform:rotateY(180deg);
  background-image:none, radial-gradient(105% 85% at 50% 26%,
    color-mix(in srgb,var(--wand) 88%,#000) 0%,
    color-mix(in srgb,var(--wand) 62%,#000) 42%, var(--wandtief) 100%)}
/* --- Was die Vitrine KOSTET, und wo gespart wird (07.08.2026) ------------
   Aus dem Feld: "am Handy ruckelt es, sowohl im Browser als auch in der App"
   — und die Waende waren dort teils gar nicht zu sehen. Gemessen im
   Sammlungsraster mit ZWEI Vitrinenkarten unter zwoelf, 6-fache
   CPU-Drosselung, DPR 3, 390 x 844:

     Raster wie es war ............ Median 78,7 ms   p95 97,0 ms
     Vitrine ganz aus ............. Median 42,3 ms   p95 48,5 ms

   **Zwei Vitrinen kosteten mehr als die zehn anderen Karten zusammen.**

   Der Hauptposten ist die TEXTUR, und zwar ueberall — auf der Buehne mit
   drehender Kamera macht sie ein Drittel der Bildzeit aus (36,5 gegen
   24,3 ms ohne). Kacheln statt `cover` bringt dagegen NICHTS (78,8 gegen
   78,7): teuer ist nicht die Skalierung, sondern die texturierte FLAECHE.

   Deshalb tragen nur noch Rueckwand, Boden und Podest das Material. Decke,
   Seitenwaende und Vorderwand behalten ihren Verlauf — dort steht die Flaeche
   perspektivisch so schraeg und so dunkel, dass niemand ein Material erkennt.

     Textur nur hinten und Boden ... Raster 66,6 ms   Buehne 30,3 ms

   Die Zahlen sind GEDROSSELT gemessen, nicht vom Geraet: es hing keines an
   adb. Sie taugen zum Vergleich der Varianten untereinander, nicht als
   absolute Bildzeit.

   Umgesetzt ist es an den vier Wandregeln oben: dort steht `none` an der
   Stelle, an der `var(--wandtextur)` stand. Eine Sammelregel danach waere
   kuerzer und falsch — sie muesste den Verlauf jeder Wand wiederholen, und
   damit staende er zweimal im Blatt. */

/* Eine kleine Karte zeigt keinen begehbaren Raum. Im Sammlungsraster ist sie
   196 x 98 px gross; Decke, Seitenwaende und Vorderwand sind dort ein paar
   dunkle Pixel am Rand und kosten trotzdem voll.

   `@container` statt einer Klasse von aussen: die Karte weiss selbst am
   besten, wie gross sie gerade ist, und eine Klasse waere ein zweiter
   Wahrheitsort daneben — genau der Fehler, den dieses Projekt bei
   `runtime-db.json` gegen Postgres schon traegt. Die Buehne (300 px) und die
   Raumsicht liegen darueber und bleiben vollstaendig. */
@container (max-width: 220px){
  /* NUR DIE VORDERWAND FAELLT WEG. Sie steht hinter der Kamera und ist
     ohnehin durch `backface-visibility` unsichtbar, solange man sich nicht
     halb um den Raum dreht — und das tut im Raster niemand.

     Decke und Seitenwaende BLEIBEN, obwohl sie hier teuer sind: der Raum geht
     seit dem 07.08.2026 mit der Geraetelage mit (+/-4,5 Grad quer, +/-2,5 hoch),
     und ohne sie stuende bei jeder Neigung ein schwarzer Keil im Bild. Sie
     tragen dabei kein Material mehr, nur ihren Verlauf — das ist der Teil der
     Ersparnis, der auch bei Bewegung gilt. */
  .szene .vorn{display:none}
  /* Ueberstand nur so viel, wie der Schwenk braucht. 60 % je Seite sind fuer
     eine volle Umdrehung gerechnet; hier sind es hoechstens 4,5 Grad, und die
     Rueckwand wandert dabei um rund 8 cqw zur Seite. 18 % lassen Luft. */
  .szene{inset:-18% -18%}
  /* Die Wandspiegelung sitzt in der Raummitte und ist bei kleinem Schwenk
     ohnehin ausserhalb des Feldes — hier kostet sie nur. */
  .szene > .w .refl{display:none}
}

/* Das Podest ist aus demselben Stoff wie der Raum. */
.szene .podest .oben, .szene .podest .vorn{
  background-blend-mode:var(--wandmisch, overlay), normal;
  background-repeat:no-repeat, no-repeat; background-size:cover, cover}

/* Lichtkegel von oben — gibt dem Raum eine Quelle und dem Tier einen Grund,
   beleuchtet zu sein. Liegt auf dem Boden, nicht davor.

   KEIN mix-blend-mode hier, obwohl "screen" fuer Licht das Naheliegende
   waere. Blend-Modi, Filter und Masken sind "grouping properties": auf einem
   direkten Kind eines preserve-3d-Containers zwingen sie den gesamten
   3D-Kontext zusammen. Gemessen war der Raum damit vollstaendig weg —
   sichtbar blieb nur die Rueckwand, ueber das ganze Feld gezogen, obwohl
   jede einzelne Flaeche geometrisch korrekt sass. Ein Element mit
   Blend-Modus killt also fuenf andere, und man sieht keinen Fehler, sondern
   ein plausibel aussehendes flaches Bild.

   Filter am Motiv sind unkritisch: die sitzen auf .tafel INNERHALB von
   .motiv, und .motiv selbst ist flach. */
.szene .kegel{position:absolute; left:50%; bottom:calc(50% - 22cqw); width:64cqw; height:30cqw;
  /* Zieht mit dem Podest in die Raummitte um — ein Lichtfleck, der woanders
     liegt als das, was er beleuchtet, faellt sofort auf. */
  transform:translateX(-50%) translateZ(calc(var(--t) / -2 + 11cqw)) rotateX(90deg); transform-origin:50% 100%;
  background:radial-gradient(58% 68% at 50% 55%, rgba(255,248,225,.4), rgba(255,248,225,0) 74%);
  pointer-events:none}

/* Podest. Die HOEHE ueber dem Boden ist der ganze Punkt: stand es auf
   bottom:0, lag seine Oberseite in derselben Ebene wie der Boden und war
   damit unsichtbar — gemessen war die Flaeche da, nur eben deckungsgleich
   mit dem, worauf sie stehen sollte. Die Klappkante liegt deshalb --ph ueber
   dem Boden, und die Vorderseite fuellt genau diesen Zwischenraum. */
/* Das Podest steht in der RAUMMITTE, auf derselben Tiefe wie die Drehachse.
   Vorher stand es bei -13 cqw, also dicht an der vorderen Oeffnung eines
   92 cqw tiefen Raums — das war eine Buehne mit Prospekt, kein Raum. Beim
   Drehen kreiste die Kamera nicht um das Motiv, sondern schob es seitlich aus
   dem Bild, und der Abstand aenderte sich staendig (dagegen lief die
   --kamnaehe-Korrektur, die es jetzt nicht mehr braucht). */
.szene .podest{position:absolute; left:50%; bottom:var(--ph,9cqw);
  width:50cqw; height:20cqw; --ph:calc(50% - 13cqw);
  transform-style:preserve-3d; transform:translateX(-50%) translateZ(calc(var(--t) / -2 + 11cqw))}
.szene .podest .oben{position:absolute; inset:0; transform-origin:50% 100%;
  transform:rotateX(90deg); border-radius:1cqw;
  background-image:var(--wandtextur), linear-gradient(to bottom,
    color-mix(in srgb,var(--wand) 60%,#000) 0%,
    color-mix(in srgb,var(--wandhell) 96%,#fff) 100%);
  box-shadow:0 0 5cqw rgba(0,0,0,.55)}
.szene .podest .vorn{position:absolute; left:0; right:0; top:100%; height:var(--ph,9cqw);
  border-radius:0 0 1cqw 1cqw;
  background-image:var(--wandtextur), linear-gradient(to bottom,
    color-mix(in srgb,var(--wandhell) 82%,#fff), color-mix(in srgb,var(--wand) 40%,#000));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.45), 0 1cqw 3cqw rgba(0,0,0,.7)}

/* Motiv und Spiegelung stehen in EINEM Traeger, gestapelt. Getrennt
   positioniert lag die Spiegelung 42 px ueber dem Bildfeld: scaleY(-1) klappt
   um den transform-origin, und bei einem eigenen bottom-Wert klappt sie damit
   aus dem Bild heraus statt unter das Motiv. Hier bleibt jeder Block, wo er
   liegt — gespiegelt wird nur sein Inhalt (origin bleibt die Mitte).
   Die Fuge zwischen beiden ist die Standflaeche und liegt auf der
   Podestoberkante (6 cqw ueber dem Boden). */
/* Die Standflaeche des Motivs ist die Podestoberkante (9 cqw ueber dem
   Boden), nicht der Boden selbst — sonst schwebt das Tier davor. Und es
   steht MITTIG auf dem Podest, also 11 cqw weiter hinten als dessen
   Vorderkante: auf gleicher Tiefe stuende es auf der Kante. */
/* DAS MOTIV steht in der Raummitte, also genau auf der Drehachse. Nicht das
   Podest — es steht 11 cqw davor, damit das Tier mittig darauf zu stehen
   kommt und nicht auf dessen Vorderkante.

   Diese Reihenfolge ist der Grund, warum die Abstandskorrektur entfallen
   konnte: was auf der Achse liegt, behaelt bei jeder Drehung denselben
   Abstand zur Kamera. Wer Podest und Motiv wieder tauscht, holt sich
   MOTIVTIEFE zurueck. */
/* Die Standhoehe rechnet von der BILDFELDMITTE, nicht vom Szenenboden.
   `bottom:11cqw` galt, solange der Raum nur wenig groesser war als sein
   Fenster. Seit er es deutlich ist (Ueberstand 60 % je Seite), liegt sein
   Boden weit UNTER dem sichtbaren Ausschnitt — das Motiv rutschte damit aus
   dem Bild, und im Feld stand nur noch Wand. Das Bildfeld ist 44,4 cqw hoch
   und in der Szene zentriert; `50% - 11cqw` setzt die Standflaeche also
   wieder dorthin, wo sie vorher lag, und bleibt bei jeder Raumgroesse
   richtig. */
.szene .motiv{position:absolute; left:0; right:0; bottom:calc(50% - 11cqw);
  transform:translateZ(calc(var(--t) / -2)); text-align:center; pointer-events:none;
  transform-style:preserve-3d}
/* Die Tafel hat zwei Seiten. Der Schatten sitzt deshalb auf dem BILD, nicht
   auf der Tafel: ein filter auf einem Kind von preserve-3d klappt den
   3D-Kontext zusammen, und dann gaebe es keine Rueckseite mehr — derselbe
   Fehler wie beim Lichtkegel, eine Ebene tiefer. */
.szene .tafel{font-size:15cqw; line-height:1; position:relative;
  transform-style:preserve-3d; display:inline-block;
  /* Halbe Blattstaerke. Ein gerahmtes Bild ist rund 2 cm dick; auf einem
     50 cqw breiten Podest sind das etwa 1,2 cqw. */
  --td:.6cqw}
/* Das Bild traegt die Blattstaerke NICHT mehr selbst — sie sitzt am Rahmen
   (`.brahmen`, weiter unten), weil der jetzt das Element im Raum ist. */
.szene .tafel > .tier{backface-visibility:hidden;
  transform:translateZ(var(--td))}

/* DIE RUECKSEITE DES BILDES — und zwar die eines Bildes, nicht die einer
   Karte.

   Hier hing bis zum 05.08.2026 die WORTMARKE, und das war zweimal falsch: ein
   Foto auf einem Podest traegt keinen Markenaufdruck, und die Marke gehoert
   an die Karte (das macht jetzt `.kartendreher`). Sie wurde deshalb entfernt —
   nur blieb danach GAR NICHTS dort, und wer sich um das Motiv drehte, sah es
   verschwinden. Ein Bild, das von hinten unsichtbar ist, ist kein Gegenstand
   im Raum, sondern ein Aufkleber auf der Luft.

   Was man wirklich sieht, wenn man hinter ein gerahmtes Foto tritt: die
   Rueckwandpappe, den umlaufenden Rahmen und die Aufhaengung. Genau das steht
   hier — graubraun, matt, mit einer Oese als einzigem Detail. */
.szene .tafel > .trueck{position:absolute; inset:0; display:block;
  transform:rotateY(180deg) translateZ(var(--td));
  backface-visibility:hidden; border-radius:.4cqw;
  border:.35cqw solid color-mix(in srgb,var(--wandtief) 70%,#000);
  background:
    linear-gradient(148deg, rgba(255,255,255,.07) 0%, rgba(0,0,0,.16) 62%),
    #6d6156;
  box-shadow:inset 0 0 2cqw rgba(0,0,0,.35)}
/* Die Aufhaengeoese. Ein einziges Detail reicht — eine leere braune Flaeche
   liest sich als Fehler, eine mit Oese als Rueckseite. */
.szene .tafel > .trueck::after{content:''; position:absolute;
  left:50%; top:18%; width:16%; height:5%; transform:translateX(-50%);
  border-radius:99px; background:rgba(0,0,0,.4);
  box-shadow:0 .25cqw 0 rgba(255,255,255,.13)}

/* Die Schnittkanten geben dem Bild seine Staerke. Ohne sie verschwindet es
   bei exakt 90 Grad zu einem Strich — derselbe Fehler wie bei der Karte
   selbst, und dort war er der Anlass fuer die Kartendicke. */
.szene .tafel > .tkante{position:absolute; top:0; bottom:0; display:block;
  width:calc(var(--td) * 2); border-radius:.1cqw;
  background:linear-gradient(to bottom,
    #cfc9bd 0%, #8a8176 22%, #e2dccf 52%, #837a70 82%, #c2bcb0 100%)}
.szene .tafel > .tkante.li{left:0; transform-origin:0 50%;
  transform:translateZ(var(--td)) rotateY(90deg)}
.szene .tafel > .tkante.re{right:0; transform-origin:100% 50%;
  transform:translateZ(var(--td)) rotateY(-90deg)}
/* Am Spiegelbild haben Rueckseite und Kanten nichts zu suchen: es zeigt die
   Unterseite des Motivs, nicht seine Rueckseite. */
.szene .spiegel .trueck, .szene .spiegel .tkante,
.szene .refl .trueck, .szene .refl .tkante{display:none}
/* Hier hing bis zum 05.08.2026 eine Rueckseite AM BILD in der Vitrine: wer
   die Kamera um das Motiv herumfuhr, sah dahinter die Wortmarke.
   Ersatzlos entfernt, und zwar aus einem inhaltlichen Grund, nicht weil sie
   nicht ging.

   Ein Foto auf einem Podest HAT keine Rueckseite mit Markenaufdruck — eine
   Sammelkarte hat eine. Die Wortmarke gehoerte also nie an das Bild, sondern
   an die Karte. Genau das macht jetzt `.kartendreher`: gedreht wird die
   Karte, und der Raum steckt darin.

   Die Fassung am Bild verhielt sich zusaetzlich uneinheitlich — mal kam die
   Marke, mal die gespiegelte Vorderseite. Ursache war der Aufbau selbst: um
   die Tafel stehen mit `.spiegel` und den drei `.refl` vier weitere Kopien
   desselben Fotos, und welche davon bei welchem Winkel vorn liegt, entschied
   die Zeichenreihenfolge. Ein Aufbau, der von der Zeichenreihenfolge abhaengt,
   ist nicht reparierbar, nur ersetzbar. */
/* Der echte Fang steht als GERAHMTES BILD auf dem Podest, nicht
   freigestellt: eine Alphamaske gibt es nicht, und ein rechteckiges Foto
   auf einem Sockel ist ohnehin das, was in einer Vitrine steht. */
/* Die Tafel hat ein FESTES Format (2:1, wie das Bildfeld) und zeigt darin
   denselben Ausschnitt wie die Karte. Vorher richtete sie sich nach dem
   Foto und ignorierte --fx/--fy/--fz — eingestellte Werte wirkten dadurch
   nirgends, und das sah aus, als wuerde nicht gespeichert. Jetzt gilt ein
   Ausschnitt fuer beide Darstellungen. */
/* DER RAHMEN HAELT DAS FORMAT, DAS BILD DARIN DEN AUSSCHNITT. Bis zum
   07.08.2026 trug das `<img>` beides — Rahmengroesse UND Zoom —, und damit
   vergroesserte `--fz` die Tafel, statt in das Foto zu zoomen. */
.szene .motiv .brahmen{width:56cqw; aspect-ratio:2/1; display:block;
  margin:0 auto; overflow:hidden; border-radius:.4cqw;
  border:.28cqw solid rgba(255,255,255,.7); background:rgba(8,10,14,.55);
  transform:translateZ(var(--td,.02px)); backface-visibility:hidden;
  box-shadow:0 1cqw 2.4cqw rgba(0,0,0,.8), 0 0 0 .1cqw rgba(0,0,0,.55)}
.szene .motiv .brahmen .fot{width:100%; height:100%; object-fit:contain;
  display:block; border:0; border-radius:0; background:none; box-shadow:none;
  /* Dieselbe Reihenfolge wie Karte und Vollbild-Ausrichter. */
  transform:scale(var(--fz,1)) translate(var(--fx,0%), var(--fy,0%))}
/* Die Spiegelung darunter macht dieselbe Bewegung mit, sonst laufen Bild
   und Spiegelbild auseinander — das erledigt jetzt dieselbe Regel, weil
   beide denselben Rahmen tragen. */
.szene .spiegel .brahmen{box-shadow:none}
.szene .tafel:has(.fot) .tier, .szene .spiegel:has(.fot) .tier,
.szene .refl:has(.fot) .tier{display:none}
.szene .refl .fot{height:22cqw; border-width:.35cqw; box-shadow:none}
/* Der Spiegel HAENGT an der Tafel (top:100%), statt im Fluss zu stehen.
   Im Fluss waere der Traeger doppelt so hoch, und bottom:6cqw haette dann
   seine Unterkante statt der Standflaeche auf das Podest gesetzt — gemessen
   stand das Motiv dadurch 41 px ueber dem Bildfeld. */
/* Die Maske laeuft "to bottom", nicht "to top": sie wird im lokalen
   Koordinatensystem angewendet und danach mitgespiegelt. Andersherum
   verblasst die Spiegelung genau dort, wo sie am Motiv ansetzt, und ist
   dort deckend, wo sie laengst auslaufen sollte. */
.szene .spiegel{position:absolute; top:100%; left:0; right:0;
  font-size:15cqw; line-height:1; transform:scaleY(-1);
  opacity:.42; filter:blur(.6px) saturate(.7);
  -webkit-mask-image:linear-gradient(to bottom, transparent 12%, #000 96%);
  mask-image:linear-gradient(to bottom, transparent 12%, #000 96%)}

/* Raumsicht: Kamera zurueck. Gesetzt auf der KARTE, nicht auf der Szene —
   so kann eine Veredelung die Kameraposition mitbestimmen. */
/* Die Zeitkurve ist eine VARIABLE, weil zwei verschiedene Bewegungen ueber
   dieselbe Regel laufen: der Klick-Schwung laeuft aus (.22,.9,.28,1, hinten
   weich), die Heimkehr faehrt an UND aus (.6,0,.3,1, symmetrisch). Mit einer
   festen Kurve sah die Heimkehr aus, als reisse sie am Anfang los. */
/* DER UEBERGANG STEHT AN DER VITRINE, NICHT AN DER RAUMSICHT (07.08.2026).
   Er hing an `.karte.raumsicht .szene` — und damit galt er nur auf dem Weg
   HINEIN. Beim Verlassen faellt die Regel weg, bevor sie animieren koennte:
   die Kamera sprang von 55 auf 30 cqw zurueck. Hinein eine Fahrt, hinaus ein
   Schnitt, und das liest sich als Fehler. Der Uebergang gehoert also dem
   Bildfeld, der Kameraabstand der Raumsicht. */
.kbild.vitrine .szene{
  transition:transform var(--kamdauer,.8s) var(--kamkurve,cubic-bezier(.22,.9,.28,1))}
.karte.raumsicht .szene{--kamZ:calc(var(--kamzoom,55cqw) - var(--kamnaehe,0cqw))}
/* Hier stand `--wandtextur:none` — die Notbremse gegen die Kachel, die in
   der Raumsicht als Tapete las. Mit `cover` gibt es keine Wiederholung
   mehr, also auch nichts abzuschalten: das Material bleibt sichtbar,
   gerade dort, wo man es sich ansieht. */
/* Der Dunst liegt FLACH vor der Szene, nicht darin — als Kind von .kbild,
   nicht von .szene. Damit sind Verlauf und Deckkraft hier unbedenklich;
   im 3D-Kontext waere beides eine Grouping-Property und wuerde den Raum
   zusammenklappen.
   Zwei Aufgaben: die Vignette frisst die vier Ecken, in denen die Kanten
   von Decke und Seitenwaenden zusammenlaufen. Der Lichtschleier legt sich
   ueber die Fuge zwischen Boden und Rueckwand — dieselbe Stelle, an der
   eine Hohlkehle im Studio den Uebergang verschwinden laesst. */
.kbild.vitrine .dunst{
  position:absolute; inset:0; z-index:4; pointer-events:none;
  background:
    radial-gradient(56% 44% at 50% 46%,
      rgba(255,252,238,calc(.14 + .12 * var(--wandglanz,.07))) 0%, transparent 74%),
    radial-gradient(96% 82% at 50% 44%, transparent 20%, rgba(3,5,9,.62) 62%, rgba(3,5,9,.97) 100%);
}
/* In der Raumsicht bleibt nur die VIGNETTE, der Lichtschleier faellt weg.
   Auf der kleinen Karte gibt er dem 94 px hohen Feld Tiefe; gross im Bild
   liegt derselbe Schleier als heller Fleck mitten auf dem Motiv und nimmt
   genau dort Sicht weg, wo man hinsieht. Eine Hilfe fuer die Briefmarke ist
   nicht automatisch eine Hilfe fuer das Plakat. */
.karte.raumsicht .kbild.vitrine .dunst,
.v-metall.raumsicht .kbild.vitrine .dunst{
  background:radial-gradient(120% 100% at 50% 46%, transparent 55%, rgba(3,5,9,.55) 100%)}
.kbild.vitrine .lupe{position:absolute; z-index:7; right:1.6cqw; bottom:1.4cqw;
  font-size:3.4cqw; color:rgba(255,255,255,.5); pointer-events:none;
  text-shadow:0 .3cqw .8cqw rgba(0,0,0,.9)}
.karte.raumsicht .lupe{display:none}

/* Raumdialog. Die Karte darin steht still — bewegt wird die Kamera. */
#raumDialog{border:0; background:transparent; padding:0; max-width:none; max-height:none;
  width:100%; height:100%; overflow:visible; color:#f4f5ef}
#raumDialog::backdrop{background:rgba(4,6,9,.92); backdrop-filter:blur(6px)}
/* Die Perspektive fuer die KARTENDREHUNG sitzt hier, nicht auf der Karte.
   Sonst dreht sich die Karte um eine Achse, die in ihr selbst liegt, und
   sieht dabei aus wie ein aufklappendes Buch statt wie ein Gegenstand vor
   dem Betrachter. */
.raumbuehne{display:grid; place-items:center; height:100%; perspective:1700px}

/* ---- Zwei Drehungen, die sich nicht ins Gehege kommen ----
   Im Raum gibt es zwei Dinge, die man drehen will, und sie liegen
   ineinander: die KAMERA im Vitrinenraum und die KARTE, die den Raum traegt.
   Beide auf dieselbe Geste zu legen ginge nicht — deshalb entscheidet, wo
   der Zug beginnt: im Bildfeld die Kamera, sonst die Karte. Der Knopf
   "Umdrehen" macht die zweite Drehung ausserdem auffindbar; eine Geste, die
   niemand vermutet, gibt es faktisch nicht.

   Der Dreher traegt preserve-3d, die Karte selbst NICHT: `.karte::before`
   ist der Glanzfleck und hat `mix-blend-mode`. Auf einem direkten Kind eines
   preserve-3d-Containers klappt eine solche Grouping-Property den ganzen
   3D-Kontext zusammen — genau der Fehler, der schon den Lichtkegel und die
   Wandspiegelung gekostet hat. Als Kind der flachen Karte ist er harmlos.

   Die Karte dreht deshalb als STARRES Blatt; der Raum darin bekommt seine
   Tiefe nicht aus dieser Drehung, sondern behaelt seine eigene Kamera. Echte
   Verschachtelung waere ohnehin ausgeschlossen: `.kinnen` und `.kbild`
   schneiden mit `overflow:hidden` ab, und das zwingt preserve-3d auf flat.
   Damit die Drehung trotzdem nach Raum aussiehtd, wandert ein Bruchteil des
   Kartenwinkels in die Raumkamera (siehe `stelleKarte`). */
.kartendreher{position:relative; transform-style:preserve-3d;
  transform:rotateY(var(--kartY,0deg)) rotateX(var(--kartX,0deg));
  transition:transform var(--kartdauer,.55s) var(--kartkurve, cubic-bezier(.22,.9,.28,1));
  /* Halbe Kartendicke. Eine echte Sammelkarte misst rund 0,3 mm bei 63 mm
     Breite; auf 380 px Kartenbreite waeren das 1,8 px. Gerundet auf 1,6 —
     duenner traegt die Kante keinen sichtbaren Verlauf mehr. */
  --dicke:1.6px}
/* Vorder- und Rueckseite liegen NICHT in derselben Ebene, sondern je eine
   halbe Dicke davor und dahinter. Ohne das ist die Karte ein Blatt ohne
   Staerke: genau von der Seite betrachtet verschwindet sie zu einem Strich,
   und das Konstrukt sieht kaputt aus statt duenn. */
.kartendreher > .karte{backface-visibility:hidden; transform:translateZ(var(--dicke))}
/* Die Rueckseite ist eine echte Karte im Rueckseitenzustand, nur um 180 Grad
   gedreht — kein nachgebauter Sonderfall. Sie sieht damit zwangslaeufig
   genauso aus wie die Rueckseite im Abschnitt darueber. */
.kartendreher > .kartenrueck{position:absolute; inset:0;
  transform:rotateY(180deg) translateZ(var(--dicke))}
.kartendreher > .kartenrueck::before{display:none}   /* kein zweiter Glanzfleck */

/* DIE ABGEWANDTE SEITE WIRD GANZ AUS DEM BILD GENOMMEN.

   `backface-visibility:hidden` macht sie unsichtbar, nimmt sie aber nicht aus
   dem Renderbaum: der Browser haelt und rastert weiterhin eine zweite volle
   Karte mit 79 Knoten, zwei `screen`-Ebenen inklusive. Beim Drehen ist das die
   Haelfte der Malarbeit fuer eine Flaeche, die niemand sieht.

   `.zeigt-rueck` setzt der Aufrufer, und zwar NUR beim Seitenwechsel — also
   zweimal je Umdrehung, nicht bei jedem Bild. Ohne die Klasse bleibt alles
   beim Alten; die Regel ist eine Ersparnis, keine Voraussetzung. */
.kartendreher:not(.dreht):not(.faehrt):not(.zeigt-rueck) > .kartenrueck{visibility:hidden}
.kartendreher:not(.dreht):not(.faehrt).zeigt-rueck > .karte{visibility:hidden}

/* `.faehrt` HEBT DIE REGEL AUF, und ohne sie war eine Kartenseite SCHWARZ.

   Beim Einrasten wird der Winkel sofort auf die naechste volle Umdrehung
   gesetzt — die Karte faehrt dorthin aber noch 0,4 Sekunden per Transition.
   Die Sichtbarkeit stand in dieser Zeit schon auf dem ENDZUSTAND: wer bei
   200 Grad losliess, sah eine Karte, die auf 360 zufaehrt und dabei durch 270
   laeuft. Dort zeigt sie die Rueckseite — die aber bereits versteckt war,
   waehrend die Vorderseite hinter `backface-visibility` liegt. Beide
   unsichtbar heisst: ein schwarzes Rechteck.

   Waehrend der Fahrt entscheidet deshalb wieder `backface-visibility` allein.
   Sie kostet dort nichts: es sind 24 Bilder, keine Dauerlast. */

/* SOLANGE SIE SICH DREHT, BEKOMMEN DIE FOLIEN EINE EIGENE EBENE.

   Gemessen an einer Karte, 80 Bilder je Lauf, dreimal im Wechsel:

     nur drehen          6,1 ms   der Compositor schiebt eine fertige Textur
     nur Licht           6,1 ms
     beides zusammen    30,3 ms   <- die Textur muss VERZERRT neu gerastert werden
     mit dieser Zeile   10,1 ms   Faktor 3

   Der Grund ist die Kombination, nicht eine der beiden Haelften: eine Karte im
   3D-Raum wird perspektivisch gerastert, und jede Inhaltsaenderung wirft diese
   Rasterung weg. `will-change: background-position` gibt den beiden
   Folienebenen eine eigene Compositor-Ebene — die Karte darunter bleibt
   stehen, nur die Folie wird neu gemalt.

   NUR WAEHREND DER BEWEGUNG. Eine dauerhafte Deklaration haelt fuer jede
   sichtbare Karte zwei Ebenen im Grafikspeicher; im Sammlungsraster waeren
   das 24 Stueck. `.dreht` setzt der Aufrufer beim Zufassen und nimmt es beim
   Stillstand wieder weg. */
.kartendreher.dreht .karte::before,
.kartendreher.dreht .karte .kinnen::after{will-change:background-position}

/* DIE VIER SCHNITTKANTEN.

   Es waren zwei — links und rechts — mit der Begruendung: „gedreht wird um
   die Hochachse, die Ober- und Unterkante bekommt man bei hoechstens 25 Grad
   Neigung nie zu sehen." Das stimmte, **bis die Karte sich am 06.08.2026 in
   ZWEI Achsen drehen liess.** Seither kippt sie ueber Kopf, und dort fehlte
   der Rand: aus dem Feld gemeldet als „von der Rueckseite ist es seitlich
   nicht komplett 3D, der Rand nicht ordentlich gefuellt".

   Die Begruendung ist nicht falsch geworden — ihre Voraussetzung ist
   entfallen. Wer eine Flaeche spart, weil man sie nicht sieht, muss bei jeder
   neuen Blickrichtung nachsehen.

   Jede ist so dick wie die Karte und klappt um ihre eigene Aussenkante nach
   hinten weg, sodass sie genau von Vorder- bis Rueckseite reicht. */
/* Der Schnitt ist HELL, nicht in der Seltenheitsfarbe. Eine echte Karte hat
   einen Papierkern, und den sieht man an der Kante — bei Yu-Gi-Oh und Pokemon
   ist er weiss, bei Magic schwarz. Die Farbe des Randes hoert am Schnitt auf.
   Nebenbei ist das die einzige Fassung, die ueberhaupt auffaellt: ein
   3 px breiter Streifen in der Kartenfarbe verschwindet vor dem dunklen
   Hintergrund, ein heller nicht. */
/* EINE FLACHE KANTE KANN KEINE RUNDUNG ABBILDEN.

   Drei Anlaeufe mit aufgeklappten Rechteckflaechen, drei Befunde aus dem
   Feld, und alle drei folgen aus derselben Geometrie:

     durchlaufend    ragten sie an den vier Ecken hinter der Rundung hervor
     eingezogen      rissen sie genau dort Luecken
     mit Radius      Rand geschlossen, aber die Ecken bleiben rechtwinklig

   Der letzte ist nicht behebbar: eine Kante ist ein PLANES Rechteck. Sie kann
   an ihren Enden gerundet sein, aber sie kann nicht um eine Ecke laufen. Vier
   davon ergeben zwangslaeufig einen Quader mit scharfen Kanten.

   Der Ausweg ist NICHT ein Stapel. Zwei Zwischenfassungen sind daran
   gescheitert und stehen hier als Warnung:

     6 Vollflaechen   perspektivisch neu gerastert bei jeder Drehung (p95
                      30,4 ms) und Streit im Tiefenpuffer — beim schnellen
                      Wenden blitzte die helle Schichtfarbe durch die Karte.
     4 Ringe          billiger und ohne Streit, aber sie liegen PARALLEL zur
                      Karte: flach gehalten ist jeder Ring selbst nur eine
                      Linie, und dazwischen steht eine Luecke.

   Der Rand steht SENKRECHT auf der Karte, also muessen es die Bauteile auch.
   Vier Kanten fuer die Geraden, vier Faecher fuer die Rundungen — siehe
   direkt darunter. */

/* ---- DIE ECKEN: EIN FAECHER JE RUNDUNG ----

   Sechste und letzte Fassung des Randes, und die erste, die die Rundungen
   ueberhaupt ADRESSIERT. Die fuenf davor haben es umschifft:

     2 Kanten           Rand fehlt oben und unten
     4 Kanten           ragen an den Ecken hervor
     4 Kanten eingezogen  reissen dort Luecken
     4 Kanten mit Radius  Rand zu, Ecken rechtwinklig
     6 Vollflaechen     rund, aber Tiefenpufferstreit und p95 30,4 ms
     4 Ringe            rund und billig, flach gehalten aber weg

   Alle sechs Befunde folgen aus einem Satz: EINE FLACHE KANTE IST EIN PLANES
   RECHTECK. Sie kann an ihren Enden gerundet sein, aber nicht um eine Ecke
   laufen. Und gekruemmte 3D-Flaechen gibt es in CSS nicht.

   Der Rand einer Karte ist an der Ecke ein VIERTELZYLINDER: Achse senkrecht
   zur Karte, Radius gleich dem Eckenradius, Hoehe gleich der Dicke. Ein
   Zylinder wird in CSS aus schmalen Streifen gebaut, die ringsum stehen —
   dasselbe Verfahren, mit dem jede CSS-3D-Trommel gebaut wird, und dasselbe,
   das auroratide fuer runde Kartenecken beschreibt.

   Vier Streifen je Ecke, also 22,5 Grad Fase. Bei einem Radius von rund
   10 px sind das 4 px lange Facetten — darunter sieht man die Einzelflaechen
   nicht mehr.

   DIE STREIFEN STEHEN SENKRECHT ZUR KARTE, genau wie die Kanten. Damit gilt
   fuer sie dieselbe gute Eigenschaft: bei 90 Grad zeigen sie ihre volle
   Flaeche. Das war der Grund, warum die Ringe wieder rausmussten — sie lagen
   PARALLEL zur Karte und waren flach gehalten selbst nur Linien.

   Gerechnet wird ohne feste Laenge: `left`/`top` stehen in Prozent der Karte,
   und `cos()`/`sin()` in `calc()` liefern die Bogenpunkte. Ein Containerabruf
   (`cqw`) waere naheliegender gewesen und ist verboten — `container-type`
   bringt `contain:layout` mit, und das flacht `transform-style:preserve-3d`
   ab. Der Rand haette danach in der Kartenebene gelegen. */
.kartendreher .fase{position:absolute;
  width:calc(var(--dicke) * 2);
  /* Reichlich Ueberlappung: gebraucht sind 0,39 des Radius je Facette, hier
     stehen 0,62. Eine Luecke zwischen zwei Facetten ist sichtbar, eine
     Ueberlappung nicht. */
  height:1.46%;
  background:linear-gradient(to bottom,
    #cfcdc2 0%, #7d7b73 16%, #e6e4d9 48%, #75736c 84%, #c4c2b8 100%);
  backface-visibility:visible}
/* Der Bogenpunkt in Prozent, je Ecke gespiegelt. 3,3 % der Breite und 2,36 %
   der Hoehe sind bei 63:88 derselbe Pixelwert — die Rundung ist also ein
   echter Kreis, und der Viertelzylinder stimmt exakt. */
.kartendreher .fase.or, .kartendreher .fase.ur{right:calc(3.3%  * (1 - cos(var(--w))))}
.kartendreher .fase.ol, .kartendreher .fase.ul{left: calc(3.3%  * (1 - cos(var(--w))))}
.kartendreher .fase.ol, .kartendreher .fase.or{top:  calc(2.36% * (1 - sin(var(--w))))}
.kartendreher .fase.ul, .kartendreher .fase.ur{bottom:calc(2.36% * (1 - sin(var(--w))))}
/* Die Drehung stellt den Streifen so, dass seine Aussenseite nach aussen
   zeigt. `rotate()` ist im Bildschirmsystem positiv im Uhrzeigersinn (Y zeigt
   nach unten), deshalb ist das Vorzeichen je Ecke verschieden. */
.kartendreher .fase.or{transform:translate(-50%,-50%) rotate(calc(-1 * var(--w))) rotateY(90deg)}
.kartendreher .fase.ol{transform:translate(-50%,-50%) rotate(calc(180deg + var(--w))) rotateY(90deg)}
.kartendreher .fase.ur{transform:translate(-50%,-50%) rotate(var(--w)) rotateY(90deg)}
.kartendreher .fase.ul{transform:translate(-50%,-50%) rotate(calc(180deg - var(--w))) rotateY(90deg)}

/* DIE RINGE ALLEIN REICHEN NICHT — SIE LIEGEN PARALLEL ZUR KARTE.

   Haelt man sie fast waagerecht, also genau von der Seite, ist jeder Ring
   selbst nur eine Linie, und zwischen den vier Linien steht eine Luecke von
   0,64 px. Aus dem Feld: „wenn man sie fast komplett flach haelt, glitcht der
   Rand weg, man sieht fast nichts mehr."

   Genau dort waren die alten flachen Kanten am besten: sie stehen SENKRECHT
   zur Karte und zeigen bei 90 Grad ihre volle Flaeche. Beide Formen decken
   also genau den Fall ab, in dem die andere versagt:

     Ringe    gut bei schraeger Ansicht (die Ecken), unsichtbar bei 90 Grad
     Kanten   gut bei 90 Grad (die Flaeche), eckig an den Ecken

   Zusammen ergibt das einen geschlossenen Rand in jeder Lage. Die Kanten sind
   dabei um die Eckenrundung EINGEZOGEN — allein war das ein Fehler (es riss
   Luecken), neben den Ringen ist es richtig: die Luecke ist genau der Teil,
   den die Ringe abdecken. */
.kartendreher .kante{position:absolute;
  background:linear-gradient(to bottom,
    #cfcdc2 0%, #7d7b73 16%, #e6e4d9 48%, #75736c 84%, #c4c2b8 100%)}
.kartendreher .kante.links, .kartendreher .kante.rechts{
  top:2.36%; bottom:2.36%; width:calc(var(--dicke) * 2)}
.kartendreher .kante.oben, .kartendreher .kante.unten{
  left:3.3%; right:3.3%; height:calc(var(--dicke) * 2);
  background:linear-gradient(to right,
    #cfcdc2 0%, #7d7b73 16%, #e6e4d9 48%, #75736c 84%, #c4c2b8 100%)}
.kartendreher .kante.links{left:0; transform-origin:0 50%;
  transform:translateZ(var(--dicke)) rotateY(90deg)}
.kartendreher .kante.rechts{right:0; transform-origin:100% 50%;
  transform:translateZ(var(--dicke)) rotateY(-90deg)}
.kartendreher .kante.oben{top:0; transform-origin:50% 0;
  transform:translateZ(var(--dicke)) rotateX(-90deg)}
.kartendreher .kante.unten{bottom:0; transform-origin:50% 100%;
  transform:translateZ(var(--dicke)) rotateX(90deg)}

/* UND SIE WERDEN NUR GEMALT, WENN MAN SIE SEHEN KANN.

   Die sichtbare Randbreite ist `dicke * 2 * sin(Winkel)`. Bei der Ruhelage
   (3 Grad Schaukel, bis 6 Grad Lagesensor) sind das unter 0,4 px — die Karte
   steht praktisch frontal, und vier Ringe werden fuer nichts gerastert. In
   der Buehne ist das der Normalfall: meistens steht sie still.

   `.kantig` setzt der Aufrufer, sobald ein Sinus 0,1 ueberschreitet (rund
   6 Grad). `visibility` statt `display`, damit dabei kein Layout anfaellt —
   ein Umbruch beim Andrehen waere genau der Ruckler, den die Regel
   verhindern soll. Gilt fuer beide Formen: frontal sieht man weder Ring
   noch Kante. */
.kartendreher:not(.kantig) .kante,
.kartendreher:not(.kantig) .fase{visibility:hidden}
.raumzu, .raumdreh{position:fixed; top:22px; font:inherit; font-size:13px; font-weight:800;
  letter-spacing:.06em; text-transform:uppercase; color:rgba(244,245,239,.7);
  background:rgba(255,255,255,.06); border:1px solid rgba(255,255,255,.18);
  border-radius:2px; padding:9px 15px; cursor:pointer}
.raumzu{right:24px}
.raumdreh{left:24px; color:var(--lime); border-color:rgba(201,255,66,.3)}
.raumzu:hover, .raumdreh:hover{color:#f4f5ef; background:rgba(255,255,255,.12)}

/* --- Typenzeile: Reich, Artname, Gruppe ---
   KEINE Kaesten. Die App fuehrt "Kanten statt Pillen, Typografie traegt statt
   Rahmen"; ein umrandetes Plaettchen mitten in der Zeile liegt optisch VOR der
   Karte statt auf ihr. Traeger sind Farbe und Versalien — dieselbe Machart wie
   bei der Gruppe rechts daneben. Der zweite Traeger ist die farbige Unterkante
   des Bildfelds, ganz ohne eigenes Element. */
.ktyp{display:flex; align-items:center; gap:2.2cqw; font-size:3.5cqw; padding:1cqw 0;
  border-bottom:1px solid rgba(255,255,255,.14)}
.ktyp .ws{font-style:italic; color:rgba(244,245,239,.62); flex:1; min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap}
.ktyp .gr{letter-spacing:.1em; text-transform:uppercase; font-weight:850; color:rgba(244,245,239,.4)}
.reich{display:inline-flex; align-items:center; gap:1cqw; flex:none;
  font-size:3.2cqw; letter-spacing:.12em; text-transform:uppercase; font-weight:850;
  color:color-mix(in srgb, var(--rm) 74%, #fff)}
.reich .z{font-size:3.6cqw; line-height:1}

/* --- Angriffe --- */
.kang{display:grid; gap:1.5cqw; padding:.4cqw 0}
/* Reihenfolge: NAME, dann Kostenpunkte, dann Zuschlag. Die Punkte vorn
   liessen die Namen ausgefranst beginnen — bei drei Punkten anders als bei
   vier —, und die Angabe, die man sucht, ist der Name. */
.kang .a{display:grid; grid-template-columns:auto auto 1fr; gap:1.4cqw; align-items:baseline}
.kang .an{grid-column:1}
.kang .kosten{grid-column:2}
.kang .ab{grid-column:3; text-align:right}
.kosten{display:flex; gap:.7cqw; align-self:center}
.kp{width:2.2cqw; height:2.2cqw; border-radius:50%; background:var(--gold); opacity:.85}
.kang .an{font-size:4.2cqw; font-weight:850; line-height:1.15}
.kang .ab{font-size:4.4cqw; font-weight:900; color:var(--lime); font-variant-numeric:tabular-nums}
/* Der Text wird NICHT abgeschnitten — er passt. Bei 3,2 cqw auf der
   Textspalte sind das rund 40 Zeichen je Zeile; zwei Zeilen fassen 78.
   Laengere Texte werden gekuerzt geschrieben, nicht gekuerzt dargestellt:
   ein abgeschnittener Satz ist eine kaputte Auskunft, keine kompakte. */
.kang .at{grid-column:1/-1; font-size:3.2cqw; line-height:1.3; color:rgba(244,245,239,.5);
  font-style:italic; text-wrap:pretty}

/* --- Werteleiste im Fuss ---
   Kuerzel und Zahl NEBENeinander. Untereinander plus eine Zeile "gegen X" war
   die Leiste 99 px hoch statt 36 und sprengte das Format.

   Gelesen wird SPALTENWEISE: jede Spalte ist ein Wertepaar, die zwei Seiten
   derselben Frage. Vorher liefen die acht Werte zeilenweise durch, und damit
   stand "Drohen" neben "Nerven" wie zwei unabhaengige Zahlen — genau das
   erzeugt die Frage, warum im Kampf ungleiche Werte verglichen werden.

   ZAHL VORN, Kuerzel dahinter. Mit space-between stand die Zahl am rechten
   Spaltenende und klebte am Kuerzel des naechsten Paares — zwei Werte, die
   nichts miteinander zu tun haben, sahen aus wie einer. Jetzt fuehrt die Zahl
   rechtsbuendig in fester Spalte, das Kuerzel folgt, und der ganze Restplatz
   liegt als Abstand ZWISCHEN den Paaren. Die wichtigere Angabe steht damit
   zugleich vorn. */
.kwerte{margin-top:auto; display:grid; grid-template-rows:auto auto; grid-auto-flow:column;
  grid-auto-columns:1fr; column-gap:2.6cqw; row-gap:.4cqw;
  border-top:1px solid rgba(255,255,255,.14); padding-top:1.5cqw}
/* OHNE ANGRIFFSBLOCK das Bild strecken statt eine Luecke stehen zu lassen.
   Fuer keine der 1000 Katalogarten gibt es heute Angriffe (jeder Erklaersatz
   ist redaktionell) — in der Sammlung klaffte dadurch zwischen Foto und
   Werteleiste ein leeres Drittel, das aussah, als fehle etwas beim Laden.
   Das Bild fuellt den Platz jetzt aus; sobald Angriffe da sind, greift die
   Regel von selbst nicht mehr. */
.kinnen:not(:has(.kang)) .kbild{flex:1; aspect-ratio:auto; min-height:0}
/* Zahlenspalte in cqw, NICHT in em: em rechnet gegen die geerbte
   Schriftgroesse der Karte, nicht gegen die Kartenbreite — die Leiste wurde
   damit 183 px hoch statt 49, weil die vier Spalten umbrachen. */
.kw{display:grid; grid-template-columns:6.2cqw auto; align-items:baseline;
  column-gap:1cqw; padding:.8cqw 0}
/* Feine Trennlinie zwischen den Paaren, nicht innerhalb. */
.kw:nth-child(2n+1):not(:first-child){box-shadow:-1.3cqw 0 0 -.6cqw rgba(255,255,255,.14)}
.kw .l{font-size:2.8cqw; letter-spacing:.05em; text-transform:uppercase; color:rgba(244,245,239,.45)}
.kw .z{font-size:4.8cqw; font-weight:900; line-height:1.15; font-variant-numeric:tabular-nums;
  text-align:right}
/* NOCH NICHT VERDIENT. Ein Fragezeichen in derselben Groesse wie eine Zahl
   waere ein Wert, der zufaellig anders aussieht; gedaempft liest es sich als
   Luecke. Die Beschriftung bleibt voll sichtbar — welcher Wert fehlt, ist die
   halbe Auskunft. */
.kw.unbekannt .z{color:rgba(244,245,239,.34); font-weight:800}

/* --- Fusszeile --- */
.kfuss{display:flex; justify-content:space-between; align-items:center; padding-top:1.1cqw; gap:1.5cqw;
  font-size:2.8cqw; letter-spacing:.08em; text-transform:uppercase; font-weight:850;
  color:rgba(244,245,239,.35)}
.kfuss span{overflow:hidden; text-overflow:ellipsis; white-space:nowrap}

/* --- Kleine Karte: VERGROESSERN statt weglassen (05.08.2026) ---

   Hier stand bis heute die umgekehrte Regel: unter der Schwelle fielen
   Kuerzel, Fuss und Zusatzangaben weg, weil sie sonst auf 3,4 px Schrift
   hinausliefen. Die Rechnung stimmte, der Schluss war falsch.

   Die kleine Karte hat naemlich PLATZ: ohne Angriffsblock — und den hat
   heute keine der 1000 Katalogarten — bleibt ein Drittel der Flaeche leer.
   Statt Text zu streichen, wird er relativ groesser gesetzt. 4,6 cqw statt
   3,3 cqw ergibt bei 178 px Kartenbreite 8,2 px, also ueber der eigenen
   Untergrenze von 7,5 px. Damit traegt die VOLLE Ansicht auch dort, wo zwei
   Karten nebeneinander stehen.

   Was weiterhin faellt: der wissenschaftliche Name und die Gruppe in der
   Typzeile. Sie sind Beiwerk, und der Platz gehoert den Werten. */
@container (max-width:227px){
  .kraftmarke .e, .ktyp .ws, .ktyp .gr{display:none}
  .kzeile .nm{font-size:7cqw}
  .kraftmarke .z{font-size:8cqw}
  .ksterne{font-size:5cqw; letter-spacing:.8cqw}
  /* Das Reich bleibt — als Zeichen ohne Wort. Es ist die kompakteste
     Angabe der Karte und gerade in der Tauschauswahl die nuetzlichste. */
  .ktyp{border-bottom:0; padding:0; justify-content:flex-end; margin-top:-1cqw}
  .reich{font-size:0; gap:0}
  .reich .z{font-size:5.4cqw}
  .kwerte{column-gap:2cqw; row-gap:.2cqw; padding-top:2cqw}
  /* Zahl vorn in fester Spalte, Kuerzel dahinter — dieselbe Ordnung wie
     gross, nur mit engerer Zahlenspalte. */
  .kw{grid-template-columns:5.6cqw auto; padding:.4cqw 0}
  .kw .z{font-size:6cqw}
  .kw .l{font-size:4.6cqw; letter-spacing:0}
  .kfuss{font-size:3.4cqw; padding-top:1.2cqw; margin-top:1cqw}
  .kang .an{font-size:4.2cqw}
  .kang .at{display:none}   /* der Erklaersatz braucht Zeilen, die hier fehlen */
  .kbild .tier{font-size:30cqw}
}

/* ===========================================================================
   3. VEREDELUNGEN — additiv, jede eine Klasse.
   Reihenfolge im Sheet = Reihenfolge der Wertigkeit.
   =========================================================================== */

/* MATT — kein Glanz. Der Grundzustand, absichtlich langweilig:
   wenn schon die haeufigste Karte funkelt, sagt die Abstufung nichts mehr. */
.v-matt{--glanz:.04}
.v-matt .kinnen{background:linear-gradient(172deg,#191f19,#10160f)}

/* GLANZ — ein weicher Lichtfleck, der der Neigung folgt. */
.v-glanz{--glanz:.13; --wisch:.06}

/* HOLO — Regenbogenstreifen ueber die ganze Karte, screen (siehe unten).
   Zwei ueberlagerte Muster: breite Farbbaender plus feines Linienraster,
   sonst wirkt es wie ein Farbfilter statt wie Folie. */
.v-holo{--holo:.6; --glanz:.16; --wisch:.11}
.v-holo::after{
  content:''; position:absolute; inset:0; border-radius:inherit; pointer-events:none; z-index:5;
  background:
    /* Fuenfmal breiter als die Karte, damit `no-repeat` ueber den ganzen
       Stellbereich traegt (Begruendung bei `@property --gs`). Die Stopps sind
       im selben Verhaeltnis mitgeschrumpft — 27 % statt 45 % bei 500 % statt
       280 % Kachelbreite —, sonst waeren die Baender doppelt so breit wie
       die Karte und man saehe nur noch einen Farbverlauf. */
    repeating-linear-gradient(112deg,
      rgba(255,0,110,.26) 0%, rgba(255,190,0,.26) 5.4%, rgba(80,255,190,.26) 10.8%,
      rgba(60,140,255,.26) 16.2%, rgba(200,80,255,.26) 21.6%, rgba(255,0,110,.26) 27%),
    repeating-linear-gradient(68deg, rgba(255,255,255,.07) 0 2px, transparent 2px 6px);
  background-size:500% 100%, auto;
  background-position:calc(var(--gs,50%) + var(--gk,0%)) 0, 0 0;
  background-repeat:no-repeat, repeat;
  /* SCREEN, NICHT COLOR-DODGE — und das ist keine Geschmacksfrage.

     `color-dodge` rechnet `Grund / (1 − Quelle)`. Die Formel BRAUCHT einen
     hellen Grund; auf dunklem verstaerkt sie nichts, weil fast nichts da ist,
     was sich verstaerken liesse. Die Innenflaeche dieser Karte liegt bei 0,14
     Helligkeit. Nachgerechnet an genau diesen Werten:

       color-dodge  +0,014     <- Holo, bis zum 06.08.2026
       screen       +0,072     <- Bronze, Kehrholo, Metall

     Fuenffacher Unterschied. Aus dem Feld kam das als „Bronze schon, aber
     Holo hat bei mir ueberhaupt keinen Effekt" — und das stimmte: die
     teuerste Veredelung nach Kehrholo war praktisch unsichtbar, waehrend die
     billigeren leuchteten.

     `screen` (`Grund + Quelle − Grund·Quelle`) begrenzt sich nach oben von
     selbst: auf einem hellen Foto hebt es kaum noch, auf dunklem Grund stark.
     Genau das tut Folie. */
  mix-blend-mode:screen; opacity:var(--holo);
}

/* KEHRHOLO — alles glaenzt AUSSER dem Bildfeld (Pokemons "Reverse Holo").
   Technisch das Gegenteil: die Folie liegt IN der Innenflaeche unter dem
   Inhalt, das Bildfeld deckt sie mit eigenem Hintergrund ab. */
.v-kehrholo{--glanz:.14; --wisch:.1}
.v-kehrholo .kinnen::after{
  content:''; position:absolute; inset:0; pointer-events:none; z-index:1;
  background:
    repeating-linear-gradient(100deg,
      rgba(255,60,140,.30) 0%, rgba(255,200,60,.30) 4%, rgba(90,255,200,.30) 8%,
      rgba(70,150,255,.30) 12%, rgba(210,90,255,.30) 16%, rgba(255,60,140,.30) 20%),
    repeating-linear-gradient(0deg, rgba(255,255,255,.05) 0 1px, transparent 1px 4px);
  background-size:500% 100%, auto; background-position:calc(var(--gs,50%) + var(--gk,0%)) 0, 0 0;
  background-repeat:no-repeat, repeat;
  mix-blend-mode:screen; opacity:.62;
}
.v-kehrholo .kbild{box-shadow:0 2px 10px rgba(0,0,0,.6) inset, 0 0 0 2px rgba(0,0,0,.5)}

/* KOSMOS — Sternenwolke hinter dem Tier, das Bild wird zum Fenster.
   Vorbild ist Pokemons "Cosmos Holo": nicht Streifen, sondern Schlieren. */
.v-kosmos{--holo:.3; --glanz:.15; --wisch:.09}
.v-kosmos .kbild::before{
  content:''; position:absolute; inset:0; z-index:2; pointer-events:none;
  background:
    radial-gradient(40% 62% at 22% 30%, rgba(150,190,255,.55), transparent 70%),
    radial-gradient(46% 54% at 76% 62%, rgba(255,160,220,.45), transparent 72%),
    radial-gradient(30% 40% at 52% 18%, rgba(200,255,230,.4), transparent 68%);
  mix-blend-mode:screen;
}
.v-kosmos .kbild::after{
  content:''; position:absolute; inset:0; z-index:2; pointer-events:none;
  background:
    radial-gradient(1.4px 1.4px at 12% 22%,#fff 60%,transparent),
    radial-gradient(1.1px 1.1px at 31% 68%,#fff 60%,transparent),
    radial-gradient(1.7px 1.7px at 58% 30%,#fff 60%,transparent),
    radial-gradient(1.2px 1.2px at 71% 78%,#fff 60%,transparent),
    radial-gradient(1.5px 1.5px at 87% 40%,#fff 60%,transparent),
    radial-gradient(1.1px 1.1px at 44% 88%,#fff 60%,transparent),
    radial-gradient(1.3px 1.3px at 92% 14%,#fff 60%,transparent);
  animation:funkeln 2.6s ease-in-out infinite;
}
@keyframes funkeln{0%,100%{opacity:.3}45%{opacity:.95}}

/* GLITZER — Lichtpunkte im Bildfeld. Kombinierbar mit jeder Folie. */
.v-glitzer .kbild .staub{
  position:absolute; inset:0; z-index:4; pointer-events:none;
  background:
    radial-gradient(1.6px 1.6px at 18% 24%,#fff 60%,transparent),
    radial-gradient(1.2px 1.2px at 62% 16%,#fff 60%,transparent),
    radial-gradient(1.8px 1.8px at 78% 58%,#fff 60%,transparent),
    radial-gradient(1.2px 1.2px at 34% 72%,#fff 60%,transparent),
    radial-gradient(1.5px 1.5px at 88% 34%,#fff 60%,transparent),
    radial-gradient(1.3px 1.3px at 8% 62%,#fff 60%,transparent);
  animation:funkeln 2.6s ease-in-out infinite;
}

/* ===========================================================================
   LEBENDES FOTO — Abzeichen und Abspielen

   Hier stand bis zum 05.08.2026 GAR NICHTS. Das Markup erzeugte
   `<div class="livezeichen">`, der Langdruck setzte `.spielt` — und keine
   einzige Regel hoerte darauf. Gemessen: das Abzeichen war ein ungestyltes
   27x24-Kaestchen mit `position:static`, und der gerechnete Stil des Motivs
   war vor und nach dem Langdruck identisch (transform none, filter none,
   animation none).

   Der Abschnitt daneben behauptete trotzdem "das Abzeichen pulst limette,
   das Motiv bewegt sich zwei Sekunden lang". Ein Blatt, das etwas
   beschreibt, was es selbst nicht tut, ist genau die Sorte Falschbehauptung,
   die MVP-SPEC verbietet — nur eine Ebene hoeher.

   WAS DAS HIER IST UND WAS NICHT: eine Nachstellung. Ein echtes lebendes
   Foto braucht ein `<video>` mit dem aufgezeichneten Clip; den gibt es
   weder im Blatt noch in der App (`MediaRecorder` ist nirgends
   implementiert). Bewegt wird deshalb das Standbild — langsamer Zoomschwenk,
   wie ihn ein Ken-Burns-Effekt macht. Das zeigt die BEDIENUNG richtig
   (Abzeichen, Langdruck, Dauer) und den INHALT bewusst nicht.
   =========================================================================== */
.karte .livezeichen{
  position:absolute; left:3.5cqw; top:3.5cqw; z-index:6; pointer-events:none;
  display:flex; align-items:center; gap:1.4cqw;
  padding:1cqw 2.2cqw 1cqw 1.8cqw; border-radius:99px;
  font-size:2.9cqw; font-weight:850; letter-spacing:.08em; text-transform:uppercase;
  color:#f4f5ef; background:rgba(10,13,9,.62);
  border:.25cqw solid rgba(255,255,255,.22);
  backdrop-filter:blur(2px); text-shadow:0 .2cqw .4cqw rgba(0,0,0,.6);
}
.karte .livezeichen i{
  width:1.7cqw; height:1.7cqw; border-radius:50%; background:#f4f5ef;
  box-shadow:0 0 0 .35cqw rgba(244,245,239,.22);
}
/* Beim Abspielen wird der Punkt zur Limette und pulst — dieselbe Konvention
   wie eine laufende Aufnahme. */
.karte.spielt .livezeichen i{
  background:var(--lime); box-shadow:0 0 0 .35cqw color-mix(in srgb,var(--lime) 30%,transparent);
  animation:livepuls 1s ease-in-out infinite;
}
@keyframes livepuls{0%,100%{opacity:1; transform:scale(1)}50%{opacity:.45; transform:scale(1.35)}}

/* Der Schwenk laeuft GENAU EINMAL und exakt so lange wie der Clip (2 s) —
   die Klasse wird nach 2000 ms wieder entfernt. Eine Endlosanimation waere
   ein Dauerzustand, kein Abspielen. */
.karte.spielt .kbild .motivfeld .fot{animation:liveschwenk 2s ease-in-out both}
/* Reihenfolge GENAU wie in der Grundregel: erst scale, dann translate. Bei
   `translate() scale()` skaliert der Versatz mit, und das Bild springt beim
   ersten Frame sichtbar an eine andere Stelle — die Animation begaenne dann
   woanders, als das Standbild aufgehoert hat. */
@keyframes liveschwenk{
  0%  {transform:scale(calc(var(--fz,1) * 1.045)) translate(calc(var(--fx,0%) - 1.5%), calc(var(--fy,0%) + 1%))}
  100%{transform:scale(calc(var(--fz,1) * 1.11))  translate(calc(var(--fx,0%) + 1.5%), calc(var(--fy,0%) - 1%))}
}
@media (prefers-reduced-motion:reduce){
  .karte.spielt .livezeichen i{animation:none}
  .karte.spielt .kbild .motivfeld .fot{animation:none}
}

/* WISCH — ein Lichtstreifen wandert ueber die Karte. Teuerster Effekt,
   deshalb nur an der Spitze. */
.v-wisch .kinnen::before{
  content:''; position:absolute; inset:0; border-radius:inherit; pointer-events:none; z-index:4;
  background:linear-gradient(104deg, transparent 38%, rgba(255,255,255,.22) 47%,
    rgba(255,255,255,.5) 50%, rgba(255,255,255,.22) 53%, transparent 62%);
  background-size:220% 100%; animation:wischen 4.2s ease-in-out infinite;
}
@keyframes wischen{0%{background-position:180% 0}55%,100%{background-position:-90% 0}}

/* PRAEGUNG — Relief statt Farbe. Vorbild ist Yu-Gi-Ohs "Ultimate Rare":
   der Rand ist erhaben, der Name steht heraus. Kein Leuchten, nur Licht
   und Schatten — deshalb funktioniert es auch auf einem matten Bildschirm.

   Die erste Fassung war unsichtbar, und zwar rechnerisch: das Muster stand
   auf rgba(255,255,255,.045) bei opacity .5, also 2,3 % Deckkraft. Auf
   dunklem Grund wird eine helle Flaeche ab etwa 5 % ueberhaupt erst
   wahrnehmbar. Die Kanten waren 1 px auf 272 px Kartenbreite.

   Relief entsteht nicht durch eine helle Linie, sondern durch den WECHSEL
   von Licht- und Schattenkante nebeneinander — deshalb liegen hier zwei
   versetzte Raster uebereinander statt einem. */
.karte.v-praegung{--glanz:.12; --wand:#2a2a26; --wandhell:#55554c}
.v-praegung .kinnen{
  box-shadow:
    inset 0 2px 0 rgba(255,255,255,.34), inset 0 -2px 0 rgba(0,0,0,.75),
    inset 2px 0 0 rgba(255,255,255,.14), inset -2px 0 0 rgba(0,0,0,.6),
    inset 0 0 0 3px rgba(0,0,0,.28);
}
.v-praegung .kinnen::after{
  content:''; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:
    repeating-linear-gradient(34deg,
      rgba(255,255,255,.15) 0 1px, transparent 1px 10px),
    repeating-linear-gradient(34deg,
      transparent 0 1px, rgba(0,0,0,.52) 1px 2.5px, transparent 2.5px 10px),
    repeating-conic-gradient(from 0deg at 50% 46%,
      rgba(255,255,255,.05) 0deg 3deg, rgba(0,0,0,.16) 3deg 6deg);
}
.v-praegung .kzeile .nm{
  color:#e9e6d8;
  text-shadow:0 2px 0 rgba(0,0,0,.9), 0 -1px 0 rgba(255,255,255,.55),
    0 3px 5px rgba(0,0,0,.6);
}
.v-praegung .ksterne, .v-praegung .kw .z{
  text-shadow:0 1px 0 rgba(0,0,0,.85), 0 -1px 0 rgba(255,255,255,.3);
}
/* Das Bildfeld sitzt eingelassen: Schatten oben innen, Lichtkante unten
   aussen — die Reihenfolge, die das Auge als Vertiefung liest. */
.v-praegung .kbild{
  border-width:2px; border-color:rgba(0,0,0,.55);
  box-shadow:inset 0 4px 9px rgba(0,0,0,.8), inset 0 -2px 4px rgba(0,0,0,.5),
    0 1px 0 rgba(255,255,255,.3);
}

/* ===== METALL: Gold, Silber, Bronze =====
   Struktur EINMAL, Palette dreimal. Vorher stand die gesamte Goldmechanik —
   Innenflaeche, Wisch, Schriftfarben, Dunst, Tafelschein — als eine Kette
   von `.v-gold`-Regeln da. Silber und Bronze haetten sie zweimal kopiert,
   und eine Aenderung am Wisch waere danach eine Aenderung an drei Stellen,
   von denen man zwei vergisst. Jetzt traegt jedes Metall zusaetzlich
   `v-metall` (vergeben im Renderer), und was sich unterscheidet, steht als
   Variable in genau einer Regel je Metall.

   Metall lebt vom KONTRAST innerhalb der Flaeche: eine polierte Oberflaeche
   spiegelt abwechselnd Lichtquelle und Umgebung, springt also zwischen fast
   Weiss und fast Schwarz. Die erste Goldfassung hatte ihre Stopps zwischen
   8 % und 22 % Helligkeit und war damit zwangslaeufig braun, egal wie golden
   der Farbton gewaehlt war. Alle drei Paletten reichen deshalb von rund 12 %
   bis 96 %.

   Der zweite Teil ist die Dispersion: echtes Gold kippt im Schatten nach Rot
   und im Mittelton nach Gruen, Bronze nach Oliv, Silber nach Blau. Ohne das
   wirkt jedes von ihnen wie farbiges Plastik. */
.karte.v-metall{--glanz:.4}
/* Die Innenflaeche traegt dasselbe Metall, aber unter einer dunklen Decke —
   ohne sie steht heller Text auf hellem Spitzlicht. Zwei Ebenen statt einer
   gedaempften Farbe, damit die Struktur erhalten bleibt. */
.v-metall .kinnen{
  background:
    linear-gradient(172deg, rgba(10,8,4,.84) 0%, rgba(7,5,3,.9) 55%, rgba(4,3,2,.94) 100%),
    var(--metallflaeche);
}
/* Wandernder Glanzstreifen: Metall wird erst durch Bewegung als Metall
   erkannt — ein Standbild kann Politur nicht von Lack unterscheiden. */
.v-metall .kinnen::after{
  content:''; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:linear-gradient(104deg, transparent 34%,
    var(--metallwisch) 45%, var(--metallwischhell) 50%,
    var(--metallwisch) 55%, transparent 66%);
  /* DER WISCH HAENGT AN DER HAND, NICHT AN DER UHR.

     Bis zum 06.08.2026 lief hier `@keyframes metallwisch` auf einer festen
     Zeitachse. Das sah gut aus und war trotzdem falsch: Metall bewegte sich,
     wenn man es ansah, und bewegte sich genauso, wenn man das Geraet kippte —
     also gar nicht ANDERS. Ein Reflex, der die Bewegung des Betrachters
     ignoriert, ist kein Reflex, sondern eine Schleife.

     Jetzt fuehrt `--gs` wie bei allen anderen Folien. In Ruhe bewegt ihn die
     Ruheschaukel weiter, der Eindruck bleibt also erhalten — nur folgt er
     jetzt dem Handgelenk. */
  background-size:260% 100%; mix-blend-mode:screen;
  background-position:calc(var(--gs,50%) + var(--gk,0%)) 0; background-repeat:no-repeat;
}
.v-metall .kzeile .nm, .v-metall .kang .an, .v-metall .kw .z{color:var(--metallschrift)}
.v-metall .kang .ab{color:var(--metallakzent)}
.v-metall .ktyp{border-bottom-color:var(--metalllinie)}
.v-metall .kwerte{border-top-color:var(--metalllinie)}
/* Bei Metall frisst die Vignette weniger — sonst liegt genau der Teil
   der Wand im Dunkeln, auf dem die Spiegelung sitzt. */
.v-metall .kbild.vitrine .dunst{background:
  radial-gradient(58% 46% at 50% 46%, var(--dunstlicht) 0%, transparent 76%),
  radial-gradient(118% 96% at 50% 44%, transparent 34%, var(--dunstrand) 100%)}
/* Der Widerschein des Metallraums auf dem Motiv — der Grund, warum die
   Vitrine bei Metall mehr ist als eine andere Wandfarbe. */
.v-metall .szene .tafel{filter:drop-shadow(0 2cqw 3cqw rgba(0,0,0,.8))
  drop-shadow(0 -.6cqw 1.4cqw var(--metallschein))}

.karte.v-gold{
  --rf:#e8bb4d; --wand:#7a5410; --wandhell:#f0c95f; --wandvorn:#2b1d05;
  --metallschrift:#ffe6a8; --metallakzent:#ffd066; --metalllinie:rgba(255,215,120,.3);
  --metallwisch:rgba(255,240,190,.18); --metallwischhell:rgba(255,250,225,.42);
  --metallschein:rgba(255,214,120,.5);
  --dunstlicht:rgba(255,246,214,.3); --dunstrand:rgba(12,7,1,.72);
  background:linear-gradient(148deg,
    #6b4a10 0%, #c9992e 6%, #fff3c0 11%, #e8c257 15%,
    #8a6318 26%, #4a3208 36%, #a8801f 46%, #f7dd8a 52%,
    #fffbe8 55%, #d9ae3c 61%, #7a5410 73%, #3a2606 85%,
    #b8912a 95%, #e8c257 100%);
  --metallflaeche:linear-gradient(148deg,
    #6b4a10 0%, #c9992e 8%, #fff3c0 14%, #8a6318 30%,
    #4a3208 42%, #a8801f 55%, #f7dd8a 62%, #7a5410 78%, #3a2606 100%);
}
/* Silber kippt kalt: die Mitteltoene ziehen nach Blau, die Spitzlichter
   bleiben rein weiss. Ein neutralgraues Silber sieht aus wie Zinn. */
.karte.v-silber{
  --rf:#ccd3dd; --wand:#4c5158; --wandhell:#e2e8f2; --wandvorn:#13161a;
  --metallschrift:#eef3fa; --metallakzent:#cddcf0; --metalllinie:rgba(206,222,244,.3);
  --metallwisch:rgba(224,236,255,.2); --metallwischhell:rgba(245,251,255,.48);
  --metallschein:rgba(206,226,255,.5);
  --dunstlicht:rgba(228,240,255,.28); --dunstrand:rgba(6,8,12,.72);
  background:linear-gradient(148deg,
    #3f434a 0%, #9aa4b2 6%, #ffffff 11%, #c3ccda 15%,
    #565c66 26%, #2b2f35 36%, #868f9d 46%, #e8eef8 52%,
    #ffffff 55%, #aeb8c6 61%, #4c5158 73%, #202329 85%,
    #929cab 95%, #c3ccda 100%);
  --metallflaeche:linear-gradient(148deg,
    #3f434a 0%, #9aa4b2 8%, #ffffff 14%, #565c66 30%,
    #2b2f35 42%, #868f9d 55%, #e8eef8 62%, #4c5158 78%, #1a1d22 100%);
}
/* Bronze ist keine dunklere Goldstufe: sie kippt im Schatten nach Oliv,
   nicht nach Rotgold. Ohne diesen Zug sind Gold und Bronze auf einer
   kleinen Karte nicht auseinanderzuhalten. */
.karte.v-bronze{
  --rf:#c98a52; --wand:#6b4526; --wandhell:#dda070; --wandvorn:#241205;
  --metallschrift:#ffd8b0; --metallakzent:#f0a866; --metalllinie:rgba(236,168,110,.3);
  --metallwisch:rgba(255,214,170,.18); --metallwischhell:rgba(255,236,208,.4);
  --metallschein:rgba(236,168,110,.5);
  --dunstlicht:rgba(255,232,200,.28); --dunstrand:rgba(14,7,2,.74);
  background:linear-gradient(148deg,
    #4a2c12 0%, #a2632c 6%, #ffe2c0 11%, #d1904f 15%,
    #6b4526 26%, #33210a 36%, #8f6330 46%, #f0bc85 52%,
    #fff2e0 55%, #c08a4e 61%, #6b4526 73%, #2a1a07 85%,
    #a87442 95%, #d1904f 100%);
  --metallflaeche:linear-gradient(148deg,
    #4a2c12 0%, #a2632c 8%, #ffe2c0 14%, #6b4526 30%,
    #33210a 42%, #8f6330 55%, #f0bc85 62%, #6b4526 78%, #2a1a07 100%);
}

/* REGENBOGEN — die Innenflaeche selbst ist der Farbverlauf, Schrift dunkel.
   Vorbild "Hyper/Rainbow Rare". Die einzige Karte mit heller Flaeche —
   deshalb muessen hier ALLE Textfarben umgestellt werden, nicht nur zwei. */
.v-regenbogen{--rf:#f7f3ff; --glanz:.24; --wisch:.14}
.v-regenbogen .kinnen{
  background:linear-gradient(148deg,#ffd9e8 0%,#ffeec2 18%,#d8ffd9 38%,#c9ecff 58%,#e2d5ff 78%,#ffd9e8 100%);
  color:#1a1520;
}
/* Die HELLE Karte braucht den umgekehrten Trick: `screen` hebt hier fast
   nichts mehr (die Formel begrenzt sich nach oben selbst), also faehrt der
   Farbverlauf mit `overlay` und verschiebt die Flaeche im FARBTON statt in
   der Helligkeit. Bis zum 06.08.2026 stand hier nur ein festes Linienraster —
   die teuerste Veredelung des Spiels war damit die einzige, die sich
   ueberhaupt nicht bewegte. */
.v-regenbogen .kinnen::after{
  content:''; position:absolute; inset:0; z-index:1; pointer-events:none; opacity:.55;
  background:
    repeating-linear-gradient(74deg, rgba(255,255,255,.6) 0 2px, transparent 2px 6px),
    repeating-linear-gradient(112deg,
      rgba(255,120,190,.5) 0%, rgba(255,225,120,.5) 5.4%, rgba(130,255,210,.5) 10.8%,
      rgba(120,180,255,.5) 16.2%, rgba(215,150,255,.5) 21.6%, rgba(255,120,190,.5) 27%);
  background-size:auto, 500% 100%;
  background-position:0 0, calc(var(--gs,50%) + var(--gk,0%)) 0;
  background-repeat:repeat, no-repeat;
  mix-blend-mode:overlay;
}
.v-regenbogen .ktyp .ws{color:rgba(26,21,32,.62)}
.v-regenbogen .ktyp .gr{color:rgba(26,21,32,.45)}
.v-regenbogen .ktyp{border-bottom-color:rgba(26,21,32,.2)}
.v-regenbogen .kang .at{color:rgba(26,21,32,.55)}
.v-regenbogen .kang .ab{color:#2f6b00}
.v-regenbogen .kw .l{color:rgba(26,21,32,.5)}
.v-regenbogen .kwerte{border-top-color:rgba(26,21,32,.2)}
.v-regenbogen .kfuss{color:rgba(26,21,32,.45)}
.v-regenbogen .kraftmarke .z{color:#8a5b00}
.v-regenbogen .kraftmarke .e{color:rgba(138,91,0,.6)}
.v-regenbogen .ksterne{color:#8a5b00}

/* VOLLBILD — das Foto fuellt die ganze Karte, der Text liegt darauf.
   Vorbild "Full Art". Der eigentliche Grund, warum es das im Spiel geben
   sollte: es ist die einzige Stufe, bei der das EIGENE Foto gross wird. */
.v-vollbild .kinnen{padding:0; background:var(--welt)}
.v-vollbild .kbild{
  position:absolute; inset:0; aspect-ratio:auto; border:0; border-radius:inherit; z-index:1;
}
.v-vollbild .kbild .tier{font-size:44cqw; opacity:.95}
/* Beim Vollbild ist Anschnitt der Zweck: das Foto TRAEGT die Karte.
   Dort also cover, und die unscharfe Fuellung entfaellt. */
.v-vollbild .kbild .motivfeld .fot{object-fit:cover}
.v-vollbild .kbild .motivfeld .grund{display:none}
.v-vollbild .kzeile{padding:3cqw 3cqw 0; z-index:3}
.v-vollbild .vhuelle{
  position:relative; z-index:3; margin-top:auto; padding:6cqw 3cqw 3cqw; display:flex;
  flex-direction:column; gap:1.5cqw;
  background:linear-gradient(to top, rgba(6,9,7,.94) 0%, rgba(6,9,7,.86) 55%, transparent 100%);
}
.v-vollbild .ksterne{padding:0 3cqw}
.v-vollbild .kzeile .nm{text-shadow:0 2px 8px rgba(0,0,0,.9)}

/* GEIST — durchscheinend, nicht bunt.
   Die erste Fassung trug ein Prismenraster und einen Regenbogennamen und war
   damit von Holo und Regenbogen kaum zu unterscheiden — drei Veredelungen mit
   demselben Traeger sind faktisch eine. Der Fehler lag in der Vorlage: Yu-Gi-Ohs
   "Ghost Rare" arbeitet mit Prismenfarben, weil auf FOLIE nichts durchscheinend
   sein kann. Ein Bildschirm kann das.

   Die vier Traeger hier haben mit Farbe nichts zu tun:
     milchige Flaeche  — die Karte wirkt, als saehe man durch sie hindurch
     doppeltes Motiv   — Gestalt und Nachbild, leicht versetzt
     kalte Entsaettigung — Geister haben keine Farbe
     wandernder Schleier — Nebel, der ueber die Karte zieht */
.karte.v-geist{--rf:#c3d4dc; --glanz:.55; --wand:#16242c; --wandhell:#4d7183}
/* Milchig statt schwarz: die hellen, entsaettigten Toene lesen sich als
   Transparenz, obwohl nichts durchscheint. */
.v-geist .kinnen{
  background:linear-gradient(168deg,
    rgba(104,138,156,.5) 0%, rgba(46,68,82,.66) 30%,
    rgba(24,38,48,.82) 62%, rgba(10,16,21,.94) 100%),
    linear-gradient(#0c1319,#0c1319);
}
/* Das Bildfeld nebelt von unten zu — der Boden verliert sich. */
.v-geist .kbild{
  background:linear-gradient(to top, #1c2c36 0%, #0f1a22 60%, #060c11 100%);
  border-color:rgba(190,225,240,.3);
}
.v-geist .kbild::before{
  content:''; position:absolute; inset:auto 0 0 0; height:62%; z-index:4; pointer-events:none;
  background:linear-gradient(to top, rgba(186,226,244,.34), transparent);
  mix-blend-mode:screen;
}
/* Schleier: zieht diagonal ueber die ganze Karte, langsamer als jeder
   Metallglanz — Nebel hat kein Tempo. */
.v-geist .kinnen::after{
  content:''; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:linear-gradient(115deg, transparent 28%,
    rgba(196,236,252,.12) 42%, rgba(228,248,255,.28) 50%,
    rgba(196,236,252,.12) 58%, transparent 72%);
  background-size:240% 100%; mix-blend-mode:screen;
  animation:nebelzug 9s ease-in-out infinite;
}
@keyframes nebelzug{0%,100%{background-position:160% 0}50%{background-position:-60% 0}}
/* Nachbild: dieselbe Gestalt versetzt, weichgezeichnet, dahinter. */
.v-geist .kbild .schemen{
  position:absolute; z-index:3; font-size:17cqw; opacity:.38;
  transform:translate(4.5cqw,-1.6cqw) scale(1.12);
  filter:blur(2px) saturate(0) brightness(1.9);
  animation:schweifen 5.5s ease-in-out infinite;
}
@keyframes schweifen{
  0%,100%{transform:translate(4.5cqw,-1.6cqw) scale(1.12); opacity:.38}
  50%{transform:translate(-4cqw,1.2cqw) scale(1.16); opacity:.16}
}
/* Kalt entsaettigt und ueberstrahlt. Kein Negativ mehr: umgekehrte Farben
   sind unlesbar, nicht gespenstisch — und auf einem Foto wird daraus Matsch. */
.v-geist .kbild .motivfeld{
  opacity:.84;
  filter:saturate(.12) brightness(1.45) contrast(.86)
    drop-shadow(0 0 2.2cqw rgba(190,240,255,.9))
    drop-shadow(0 0 5cqw rgba(120,200,240,.5));
}
/* Der Name leuchtet kalt aus sich heraus, statt durch den Regenbogen zu
   laufen — das war die Stelle, an der Geist wie Regenbogen aussah. */
.v-geist .kzeile .nm{
  color:#eef8fd;
  text-shadow:0 0 1.2cqw rgba(168,228,255,.95), 0 0 3.6cqw rgba(110,195,240,.6);
}
.v-geist .szene .tafel{filter:saturate(.12) brightness(1.4)
  drop-shadow(0 0 2.4cqw rgba(190,240,255,.9))}
.v-geist .kang .ab{color:#bfeaff}
.v-geist .kw .z{color:#dceef5}
.v-geist .ktyp{border-bottom-color:rgba(200,235,255,.28)}
.v-geist .kwerte{border-top-color:rgba(200,235,255,.28)}

/* ===========================================================================
   4. ZUSTAENDE
   =========================================================================== */

/* NICHT BESESSEN — der Katalogplatz. Grau, das Tier nur als Silhouette.
   Die Werte bleiben lesbar: man soll wissen, was einem fehlt. */
.z-verschlossen{--rf:#5c625c; --glanz:.03; box-shadow:0 8px 20px rgba(0,0,0,.3)}
.z-verschlossen .kinnen{background:linear-gradient(172deg,#191d19,#101310)}
.z-verschlossen .kbild{filter:grayscale(1) brightness(.42)}
.z-verschlossen .kbild .motivfeld{filter:brightness(.25) saturate(0)}
.z-verschlossen .kzeile .nm, .z-verschlossen .kang .an{color:rgba(244,245,239,.5)}
/* .5 statt .35: gedaempft ja, unlesbar nein — man soll sehen, was einem fehlt. */
.z-verschlossen .kang .ab, .z-verschlossen .kw .z{color:rgba(244,245,239,.5)}
.z-verschlossen .kraftmarke .z{color:rgba(240,192,74,.4)}

/* IM KAMPF — die Werteleiste wird zur Tastenreihe. */
.z-spielbar .kw{background:rgba(255,255,255,.05); border:1px solid rgba(255,255,255,.14);
  border-radius:2px; cursor:pointer; transition:border-color .15s, background .15s, transform .08s}
.z-spielbar .kw:hover{border-color:var(--lime); background:rgba(201,255,66,.14)}
.z-spielbar .kw:active{transform:scale(.94)}
.z-spielbar .kw.vorn .z{color:var(--lime)}
.z-spielbar .kw.hinten .z{color:rgba(244,245,239,.4)}

/* HERKUNFTSSIEGEL — wie kam dieses Stueck zu mir.
   `animal_history.kind` kennt heute CATCH | TRADE | SELL; BATTLE kaeme dazu.
   Der Unterschied ist der eigentliche Punkt: ein selbst gefangenes Tier ist
   der Beleg, draussen gewesen zu sein — ein erkauftes ist es nicht. Wer beides
   gleich aussehen laesst, macht den Beleg wertlos.

   Der Kasten mitten im Bild ist WEG: er lag optisch vor der Karte, verdeckte
   das Motiv und widersprach der Gestaltungsregel der App. Stattdessen die
   TCG-Konvention — ein kleines Zeichen in der Bildecke, wie das Set-Symbol bei
   Pokémon oder das Hologramm bei Yu-Gi-Oh. Den Klartext traegt die Fusszeile. */
.siegel{
  position:absolute; z-index:6; right:2cqw; bottom:1.4cqw;
  font-size:4cqw; line-height:1; color:var(--hf,var(--gold));
  text-shadow:0 .4cqw 1.2cqw rgba(0,0,0,.9), 0 0 .6cqw rgba(0,0,0,.7);
  opacity:.92;
}
/* Die Fusszeile traegt Herkunft und Erstfaenger — Typografie, kein Rahmen.
   Herkunftszeichen in seiner Farbe, damit ein gekauftes Tier auf einen Blick
   anders aussieht als ein selbst gefangenes. */
.kfuss .hk{color:var(--hf,var(--gold)); font-weight:900}

/* AUSSER GEFECHT — nach drei verlorenen Kaempfen gesperrt.
   Die Karte bleibt VOLLSTAENDIG lesbar: sie ist nicht weg, sie ist muede.
   Ein Zustand, der aussieht wie Verlust, wuerde als Fehler gelesen. */
.z-erschoepft{--glanz:.03}
.z-erschoepft .kinnen{filter:grayscale(.72) brightness(.62)}
.z-erschoepft::after{opacity:.1!important}
.sperrband{
  position:absolute; z-index:9; left:0; right:0; top:42%;
  padding:1.6cqw 3cqw; text-align:center;
  background:linear-gradient(90deg, transparent, rgba(255,115,103,.94) 12%,
    rgba(255,115,103,.94) 88%, transparent);
  color:#1a0805; font-size:3.2cqw; letter-spacing:.16em; text-transform:uppercase; font-weight:900;
  transform:rotate(-4deg); box-shadow:0 .8cqw 2.4cqw rgba(0,0,0,.5);
}
.sperrband small{display:block; font-size:2.4cqw; letter-spacing:.06em; font-weight:850;
  text-transform:none; opacity:.8; margin-top:.4cqw}

/* ===========================================================================
   3b. LEBENDES BILDFELD — Partikel auf einem Canvas, nicht in CSS.

   Der CSS-Weg (Verlaeufe plus Keyframes) sah nach Farbfolie aus, nicht nach
   Leben: gleichfoermige Streifen, keine Tiefe, kein Zufall. Ein Canvas
   rendert echte Partikel mit eigener Groesse, Geschwindigkeit und
   Lebensdauer — und kostet dabei WENIGER, weil nur EINE Ebene komponiert
   wird statt vier ueberlagerter Verlaufsschichten.

   Keine Bibliothek. three.js oder pixi.js waeren 400-600 KB gegen 155 KB
   fuer die ganze heutige Web-App, und sie koennen nichts, was hier gebraucht
   wird: Physik, Kollision und Shader spielen bei driftenden Punkten keine
   Rolle. Der Renderer darunter sind rund 60 Zeilen.

   Sie liegen UEBER dem Foto, nicht dahinter — das Bildfeld zeigt im Betrieb
   das eigene Foto des Fangs, dahinter ist nichts sichtbar.
   =========================================================================== */
.lebt-hg{position:absolute; inset:0; z-index:4; pointer-events:none; width:100%; height:100%}

/* RUECKSEITE */
.karte.rueck .kinnen{
  background:
    repeating-linear-gradient(45deg, rgba(255,255,255,.028) 0 6px, transparent 6px 12px),
    radial-gradient(60% 45% at 50% 42%, #1f2a1e 0%, #0c110d 78%);
  display:grid; place-items:center; padding:6cqw;
}
/* Die Marke steht an ZWEI Stellen: auf der grossen Rueckseitenkarte und
   klein auf der Rueckseite der Vitrinentafel. Die Regeln hingen nur an
   `.rueck`, und in der Vitrine erbte die Marke deshalb die 15cqw der Tafel —
   drei riesige Bloecke, die uebereinanderlagen. Von aussen sah das aus, als
   wuerde die Rueckseite gar nicht rendern; tatsaechlich war nur ihr Inhalt
   ohne Regeln. Ein fehlender Selektor sieht aus wie fehlende Geometrie. */
/* Geteilt wird die ANORDNUNG, nicht die Groesse. Die Marke steht an zwei
   Stellen — gross auf der Rueckseitenkarte, klein auf der Rueckseite der
   Vitrinentafel — und nur die Stapelung ist dieselbe. Die Masse der kleinen
   Fassung stehen bei der Vitrine (`.szene .rueckseite .marke`), weiter oben
   in dieser Datei.

   Die Regeln hingen urspruenglich allein an `.rueck`; in der Vitrine erbte
   die Marke deshalb die 15 cqw der Tafel, und drei riesige Bloecke lagen
   uebereinander. Ein fehlender Selektor sieht aus wie fehlende Geometrie. */
.rueck .marke, .szene .rueckseite .marke{
  display:grid; justify-items:center; text-align:center}
.rueck .marke{gap:2cqw}
.rueck .marke .w{font-size:9cqw}
.rueck .marke .u{font-size:2.8cqw; letter-spacing:.3em}
.rueck .marke .ring{width:26cqw; height:26cqw; font-size:11cqw}
.rueck .marke .w, .szene .rueckseite .marke .w{
  font-weight:900; letter-spacing:-.04em; line-height:.9; color:#e9ecdf}
.rueck .marke .u, .szene .rueckseite .marke .u{
  text-transform:uppercase; font-weight:850; color:rgba(233,236,223,.42)}
.rueck .marke .ring, .szene .rueckseite .marke .ring{
  border:1px solid rgba(201,255,66,.35); border-radius:50%;
  display:grid; place-items:center}

@media (prefers-reduced-motion:reduce){*{animation:none!important; transition:none!important}}
