/* ── FOOTER ── */
/* Spaltenstruktur exakt wie .body → Button steht axial unter dem Bild */
/* Der Zwischenraum ist so gewaehlt, dass der Knopf oben zum Bild denselben
   Abstand hat wie unten zum Fensterrand. Unten stehen fest 46 px — aus
   dem Seitenrand (28), der Hoehe des Knopfblocks (54) und dessen
   Verschiebung nach oben (18), abzueglich Zaehler und Knopf (22 + 32).
   Oben ergibt sich der Abstand aus diesem Polster minus derselben 18 plus
   den 22 ueber dem Knopf, also 42 - 18 + 22 = 46. Der Knopf bleibt dabei
   stehen: was der Fuss oben zulegt, gibt das Bild ab.               */
footer {
  display: grid;
  grid-template-columns: var(--sw) 1fr var(--sw);
  align-items: center;
  padding: calc(var(--pad) + 14px) 0 0;
}
.f-status {
  opacity: 0;
  font-size: 9px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mid);
  transition: opacity 0.3s;
  pointer-events: none;
  white-space: nowrap;
  position: fixed;
  left: 0;
  right: 0;
  bottom: 16px;
  text-align: center;
  z-index: 50;
}
.gen-wrap {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-self: center;
  grid-column: 2;
  gap: 0;
  transform: translateY(-18px);
}
.gen-progress {
  width: 100%;
  height: 1px;
  background: transparent;
  overflow: hidden;
  opacity: 0;
}
.gen-progress.on {
  opacity: 1;
}
.gen-progress-fill {
  height: 100%;
  width: 0;
  background: var(--black);
}
@keyframes _progSteady {
  from {
    width: 0;
  }
  to {
    width: 88%;
  }
}
.gen-progress.on .gen-progress-fill {
  animation: _progSteady 180s linear forwards;
}
.gen-btn {
  font-family: var(--serif);
  font-size: 18px;
  font-weight: 400;
  font-style: italic;
  letter-spacing: 0.04em;
  color: var(--white);
  background: var(--black);
  border: none;
  cursor: pointer;
  padding: 0 26px;
  height: 32px;
  display: flex;
  align-items: center;
  white-space: nowrap;
  transition: opacity 0.15s;
  position: relative;
  overflow: hidden;
}
.gen-btn:hover {
  opacity: 0.75;
}
/* Der Generieren-Knopf bleibt im Loeschmodus unberuehrt — das Loeschen
   sitzt jetzt vollstaendig im Knopf am rechten Ende der Bildleiste. */
.gen-btn {
  transition:
    opacity 0.15s,
    background-color 0.25s ease;
}
/* Der Uebergang vom schwarzen Abonnieren- in den ausgegrauten Generieren-
   Knopf. Die Grundregel blendet in 0,15 s — das waere ein Umschalten.
   Die Klasse gilt nur fuer diesen einen Wechsel und faellt danach wieder
   weg. Der Weg zurueck aus der letzten Zappel-Auslenkung laeuft mit,
   sonst spraenge der Knopf in dem Moment an seinen Platz.           */
.gen-btn.weich-aus {
  transition:
    opacity 0.9s ease,
    background-color 0.9s ease,
    transform 0.55s ease !important;
}
.gen-btn:disabled {
  opacity: 0.35;
  cursor: default;
}
/* Ein ausgeschalteter Knopf gibt in Chrome keine Mausereignisse mehr her —
   auch kein Doppelklick kaeme an. Waehrend eines Auftrags ist er genau
   das: ausgeschaltet. Er laesst die Ereignisse darum durch, und die
   Wendekarte unter ihm faengt sie auf.                              */
.gen-btn:disabled {
  pointer-events: none;
}
.gen-btn canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* ── DIE WENDEKARTE UM DEN GENERIEREN-KNOPF ─────────────────────
   Solange gerechnet wird, ist der Knopf schwarz und zappelt. Ein Doppel-
   klick dreht ihn um die waagerechte Achse — dieselbe Bewegung wie bei
   einem Bild in der Historie — und bringt ihn dabei zur Ruhe: was man
   abbrechen will, soll stillhalten. Auf der Rueckseite steht nur das
   weisse Kreuz auf dem Rot, das in dieser App immer das Wegnehmen
   bedeutet.
   Die Perspektive steht in der Transformation selbst und nicht am
   Elternelement: .gen-wrap wuerde sonst zum Bezugsrahmen fuer alles,
   was darin absolut sitzt.                                         */
.gen-flip {
  position: relative;
  transform-style: preserve-3d;
  transition: transform 0.5s cubic-bezier(0.4, 0, 0.3, 1);
}
.gen-flip.gedreht {
  transform: perspective(680px) rotateX(180deg);
}
.gen-flip #gen-btn {
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.gen-rueck {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #e8391c;
  color: #fff;
  transform: rotateX(180deg) translateZ(1px);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  /* Das Rot faengt nichts ab: was hier ankommt, gehoert der Karte und
     wendet sie zurueck. Nur das Kreuz in der Mitte hoert selbst zu.  */
  pointer-events: none;
}
/* Beide Seiten liegen sonst genau aufeinander, und welche der Browser
   dann vorn zeichnet, ist nicht gesagt — die Zahl des Zaehlers stand
   deshalb ueber dem Kreuz. Zwei Mittel dagegen: jede Seite steht einen
   Pixel vor ihrer eigenen Ebene (translateZ), und auf halber Drehung
   wird die abgewandte Seite ausdruecklich unsichtbar. Der Verzug von
   0,25 s ist die halbe Wendezeit — dort steht die Karte auf der Kante
   und man sieht den Wechsel nicht.                                  */
.gen-flip #gen-btn {
  transform: translateZ(1px);
  transition: visibility 0s 0.25s;
}
.gen-flip.gedreht #gen-btn {
  visibility: hidden;
}
.gen-rueck {
  visibility: hidden;
  transition: visibility 0s 0.25s;
}
.gen-flip.gedreht .gen-rueck {
  visibility: visible;
}
/* Das Kreuz selbst: nur so gross wie sein Feld, damit ringsum Rot bleibt,
   auf das man doppelklicken kann. Beim Ueberfahren wird der Strich
   deutlich dicker — mehr Rueckmeldung braucht es nicht.             */
.gen-x {
  width: 34px;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  color: inherit;
  cursor: pointer;
  pointer-events: none;
}
.gen-flip.gedreht .gen-x {
  pointer-events: auto;
}
.gen-x svg {
  display: block;
}
.gen-x svg path {
  stroke-width: 1.5;
  transition: stroke-width 0.13s;
}
.gen-x:hover svg path {
  stroke-width: 2.9;
}
/* Vom Klick an blinkt das Kreuz, und es hoert erst auf, wenn der Auftrag
   wirklich abgelegt ist — bei ComfyUI wie in der App.               */
@keyframes gen-x-blink {
  50% {
    opacity: 0.14;
  }
}
.gen-x.blinkt svg {
  animation: gen-x-blink 0.62s step-end infinite;
  opacity: 1;
}

/* ── Login-Feuerwerk ── */
@keyframes _fw {
  0% {
    transform: translate(-50%, -50%) translate(0, 0) scale(1);
    opacity: 1;
  }
  100% {
    transform: translate(-50%, -50%) translate(var(--fx), var(--fy)) scale(0);
    opacity: 0;
  }
}
/* Cursor-Blinken im Login-Button */
@keyframes _cursor-blink {
  50% {
    opacity: 0;
  }
}

/* ── Button-Animationen (CSS) ── */
@keyframes _btn-shake {
  0%,
  100% {
    transform: translate(0, 0) rotate(0deg);
  }
  10% {
    transform: translate(-6px, -1px) rotate(-1deg);
  }
  20% {
    transform: translate(6px, 1px) rotate(1deg);
  }
  30% {
    transform: translate(-6px, 1px) rotate(-1deg);
  }
  40% {
    transform: translate(6px, -1px) rotate(1deg);
  }
  50% {
    transform: translate(-4px, 0) rotate(-0.5deg);
  }
  60% {
    transform: translate(4px, 0) rotate(0.5deg);
  }
  70% {
    transform: translate(-3px, -1px) rotate(-0.5deg);
  }
  80% {
    transform: translate(3px, 1px) rotate(0.5deg);
  }
  90% {
    transform: translate(-1px, 0) rotate(0);
  }
}
@keyframes _btn-bounce {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-5px);
  }
}
@keyframes _btn-wave {
  0%,
  100% {
    transform: skewX(0);
  }
  25% {
    transform: skewX(-4deg);
  }
  75% {
    transform: skewX(4deg);
  }
}
@keyframes _btn-breathe {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.05);
  }
}
@keyframes _btn-wobble {
  0%,
  100% {
    transform: translate(0, 0) rotate(0);
  }
  30% {
    transform: translate(-3px, 0) rotate(-1.5deg);
  }
  70% {
    transform: translate(3px, 0) rotate(1.5deg);
  }
}
@keyframes _btn-stir {
  0%,
  100% {
    transform: rotate(0);
  }
  25% {
    transform: rotate(-6deg);
  }
  75% {
    transform: rotate(6deg);
  }
}
@keyframes _btn-pulse {
  0%,
  100% {
    box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.5);
  }
  50% {
    box-shadow: 0 0 0 8px rgba(255, 255, 255, 0);
  }
}

.gen-btn.anim-shake {
  animation: _btn-shake 0.28s ease-in-out infinite;
}
.gen-btn.anim-bounce {
  animation: _btn-bounce 0.55s ease-in-out infinite;
}
.gen-btn.anim-wave {
  animation: _btn-wave 0.7s ease-in-out infinite;
}
.gen-btn.anim-breathe {
  animation: _btn-breathe 1.6s ease-in-out infinite;
}
.gen-btn.anim-wobble {
  animation: _btn-wobble 0.45s ease-in-out infinite;
}
.gen-btn.anim-stir {
  animation: _btn-stir 0.6s ease-in-out infinite;
}
.gen-btn.anim-pulse {
  animation: _btn-pulse 1.2s ease-in-out infinite;
}
.f-right {
  display: none;
}
.copy-btn {
  font-size: 9px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--mid);
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  transition: color 0.15s;
}
.copy-btn:hover {
  color: var(--black);
}

/* ── EDGE HINTS ── */
.edge-hint {
  position: fixed;
  top: 50%;
  transform: translateY(-50%);
  z-index: 150;
  display: flex;
  align-items: center;
  gap: 10px;
  pointer-events: none;
  font-family: var(--serif);
  font-size: 21px;
  font-weight: 400;
  font-style: italic;
  letter-spacing: 0.04em;
  color: var(--black);
  /* Feste Zeilenhoehe: CJK-Schriften bringen von sich aus eine groessere
     mit, und dann waechst der Kasten und der Text verschiebt sich gegen
     das Dreieck. Mit 1 bleibt das Verhaeltnis in jeder Sprache gleich. */
  line-height: 1;
  transition: opacity 0.2s;
}
/* Das Dreieck war ein Schriftzeichen (U+25B6 bzw. U+25C0). EB Garamond
   hat es nicht, also sucht der Browser eine Ersatzschrift — und WELCHE,
   haengt am lang-Attribut. Zwischen Japanisch, Chinesisch und Koreanisch
   sind das drei verschiedene Schriften mit drei verschiedenen Groessen
   fuer dasselbe Zeichen, in CJK-Schriften oft geviertbreit. Daher das
   Springen. Als Form gezeichnet ist das Dreieck in jeder Sprache gleich
   gross und haengt an gar keiner Schrift mehr.
   Das Mass kommt vom Zeichen: bei 32 px druckte es eine Flaeche von
   23 x 25 px — die gezeichnete Form war mit 15 x 18 px deutlich kleiner
   geraten. Jetzt steht sie darueber, 26 x 28 px, und behaelt dabei das
   Verhaeltnis des Zeichens (etwas hoeher als breit).                 */
.edge-hint .eh-arrow {
  width: 26px;
  height: 28px;
  background: currentColor;
  flex: 0 0 auto;
  line-height: 1;
  font-style: normal;
}
.edge-hint-left .eh-arrow {
  clip-path: polygon(0 0, 100% 50%, 0 100%);
}
.edge-hint-right .eh-arrow {
  clip-path: polygon(100% 0, 0 50%, 100% 100%);
}
.edge-hint-left {
  left: 4px;
}
/* Rechts: tiefer, an Mitte des Noise-Bildes ausgerichtet (per JS gesetzt) */
.edge-hint-right {
  right: 4px;
}

.btn-count {
  position: relative;
  z-index: 2;
  pointer-events: none;
}
