/* =========================================================
   ORBIT MENU — CLUSTER EDITION (OPTIMIZED)
   8 Module · drehbar per Drag · Three.js-Erde als Kern
   + Explosions-Effekt beim Öffnen
   ========================================================= */

#orbit-stage {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 10;
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
  transition:
    opacity 0.85s cubic-bezier(0.22, 1, 0.36, 1),
    visibility 0s linear 0.85s;
}

body.state-home #orbit-stage {
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
  transition:
    opacity 0.85s cubic-bezier(0.22, 1, 0.36, 1),
    visibility 0s linear 0s;
}

body:not(.state-home) #orbit-stage {
  pointer-events: none !important;
  visibility: hidden !important;
}

/* =========================================================
   BÜHNE
   ========================================================= */

.orbit {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  perspective: 1600px;
  perspective-origin: 50% 50%;
  user-select: none;
  -webkit-user-select: none;
  touch-action: none;
}

.orbit.is-expanded {
  cursor: grab;
}

.orbit.is-expanded.is-dragging {
  cursor: grabbing;
}

/* Geöffnet: Klick auf die Erde sammelt die Widgets wieder ein */
.orbit.is-expanded.is-over-earth:not(.is-dragging) {
  cursor: pointer;
}

/* Während des Rückflugs nichts mehr anklickbar */
.orbit.is-retracting,
.orbit.is-expanded.is-retracting .orbit-item {
  pointer-events: none;
}

/* =========================================================
   CLUSTER — preserve-3d & will-change entfernt
   ========================================================= */

.orbit-cluster {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  z-index: 10;
  /* will-change wird per JS nur beim Drag gesetzt */
}

/* =========================================================
   ERDE
   ========================================================= */

.orbit-core {
  position: absolute;
  top: 50%;
  left: 50%;
  /* etwas größer als die Kugel, damit die Atmosphäre Luft hat.
     Geöffnet schrumpft sie zusätzlich um --earth-open-scale. */
  width: calc(min(354px, 53vw) * var(--earth-zoom, 1));
  height: calc(min(354px, 53vw) * var(--earth-zoom, 1));
  transform: translate(-50%, -50%);
  /* KEIN border-radius / overflow – sonst clippt Chromium/Brave das Canvas */
  border-radius: 0;
  overflow: visible;
  pointer-events: auto;
  cursor: pointer;
  background: transparent;
  box-shadow: none;
  /* = Tiefe 0: Widgets davor haben z-index > 1000, dahinter < 1000 */
  z-index: 1000;
  will-change: transform;
}

.orbit-earth {
  position: absolute;
  inset: 0;
  border-radius: 0;
  overflow: visible;
  pointer-events: none;
  background: transparent;
  box-shadow: none;
}

.orbit-core:hover {
  transform: translate(-50%, -50%) scale(1.04);
  transition: transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
}

/* Nach dem Öffnen schrumpft die Erde und macht Platz für die Widgets.
   Sie ist dann kein Button mehr – pointer-events: none, damit ihre
   Fläche weder Klicks auf Widgets noch das Drehen per Drag blockiert. */
.orbit-core {
  --earth-open-scale: 0.68;
}

.orbit-core.is-open,
.orbit-core.is-open:hover {
  transform: translate(-50%, -50%) scale(var(--earth-open-scale));
  transition: transform 1.4s cubic-bezier(0.22, 1, 0.36, 1) 0.15s;
  pointer-events: none;
  cursor: default;
}

/* =========================================================
   EXPAND-EFFEKTE — gemeinsame Basis
   Alle Effekte sitzen im Zentrum und werden per CSS-Variablen
   aus dem JS parametrisiert (Winkel, Distanz, Dauer, Delay).
   ========================================================= */

.orbit-fx {
  position: absolute;
  left: 50%;
  top: 50%;
  pointer-events: none;
  opacity: 0;
  will-change: transform, opacity;
}

/* =========================================================
   PHASE 1 — AUFLADEN
   ========================================================= */

/* Goldener Staub: kleine Lichtpunkte, die spiralförmig eingesogen werden */
.orbit-charge-particle {
  width: var(--size, 3px);
  height: var(--size, 3px);
  margin: calc(var(--size, 3px) / -2) 0 0 calc(var(--size, 3px) / -2);
  border-radius: 50%;
  background: radial-gradient(circle,
    rgba(255, 244, 214, 1) 0%,
    rgba(255, 196, 120, 0.85) 55%,
    rgba(255, 170, 90, 0) 100%);
  box-shadow: 0 0 8px rgba(255, 190, 110, 0.6);
  z-index: 5;
  animation: chargeParticle var(--dur, 700ms) cubic-bezier(0.45, 0, 0.75, 0.6) var(--delay, 0ms) forwards;
}

@keyframes chargeParticle {
  0%   { opacity: 0;   transform: rotate(var(--angle)) translateX(var(--from)) scale(0.6); }
  25%  { opacity: 0.95; }
  100% { opacity: 0;   transform: rotate(calc(var(--angle) + 55deg)) translateX(var(--to)) scale(1.2); }
}

/* Sonne taucht hinter dem Erdrand auf: warmer Lichtsaum am Rand + ein Glanzpunkt.
   Die Elemente sind --size groß (Radius der Erde = 100/1.7 %, siehe JS), der Saum
   liegt direkt an der Erdkante. z-index -1: unter dem Cluster mit der Erde. */
.orbit-halo,
.orbit-halo-out {
  width: var(--size, 600px);
  height: var(--size, 600px);
  margin: calc(var(--size, 600px) / -2) 0 0 calc(var(--size, 600px) / -2);
  border-radius: 50%;
  background: radial-gradient(circle closest-side,
    transparent 0%,
    transparent 56%,
    rgba(255, 206, 150, 0.55) 60%,
    rgba(255, 174, 110, 0.22) 70%,
    rgba(255, 150, 90, 0.06) 84%,
    transparent 100%);
  filter: blur(3px);
  mix-blend-mode: screen;
  z-index: -1;
}

.orbit-halo {
  animation: haloIn var(--dur, 1100ms) cubic-bezier(0.4, 0, 0.3, 1) forwards;
}

@keyframes haloIn {
  0%   { opacity: 0;   transform: scale(0.94); }
  100% { opacity: 0.9; transform: scale(1); }
}

.orbit-halo-out {
  animation: haloOut 1300ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

@keyframes haloOut {
  0%   { opacity: 0.9; transform: scale(1); }
  100% { opacity: 0;   transform: scale(1.12); }
}

/* Glanzpunkt am Erdrand mit feinem waagerechtem Linsenstreifen.
   Das Element sitzt nur auf dem Rand; Wachsen/Verblühen machen die
   Pseudo-Elemente, damit die Skalierung die Position nicht verschiebt. */
.orbit-glint,
.orbit-glint-out {
  width: var(--size, 120px);
  height: var(--size, 120px);
  margin: calc(var(--size, 120px) / -2) 0 0 calc(var(--size, 120px) / -2);
  transform: rotate(var(--angle, -35deg)) translateX(var(--r, 150px)) rotate(calc(var(--angle, -35deg) * -1));
  mix-blend-mode: screen;
  z-index: 7;
}

.orbit-glint::before,
.orbit-glint-out::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: radial-gradient(circle closest-side,
    rgba(255, 255, 250, 1) 0%,
    rgba(255, 246, 222, 0.95) 12%,
    rgba(255, 216, 152, 0.55) 30%,
    rgba(255, 180, 110, 0.16) 58%,
    transparent 100%);
}

.orbit-glint::after,
.orbit-glint-out::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 720%;
  height: 2px;
  margin: -1px 0 0 -360%;
  background: radial-gradient(ellipse closest-side,
    rgba(255, 244, 222, 0.9) 0%,
    rgba(255, 200, 140, 0.35) 35%,
    transparent 100%);
}

.orbit-glint {
  animation: glintFade var(--dur, 1100ms) ease-in forwards;
}

.orbit-glint::before,
.orbit-glint::after {
  animation: glintGrow var(--dur, 1100ms) cubic-bezier(0.5, 0, 0.5, 1) forwards;
}

@keyframes glintFade {
  0%   { opacity: 0; }
  100% { opacity: 1; }
}

@keyframes glintGrow {
  0%   { transform: scale(0.15); }
  100% { transform: scale(1); }
}

.orbit-glint-out {
  animation: glintFadeOut 1000ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

.orbit-glint-out::before,
.orbit-glint-out::after {
  animation: glintBloom 1000ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

@keyframes glintFadeOut {
  0%   { opacity: 1; }
  100% { opacity: 0; }
}

@keyframes glintBloom {
  0%   { transform: scale(1); }
  100% { transform: scale(2.8); }
}

/* =========================================================
   PHASE 2 — KNALL (liegt über der Erde)
   ========================================================= */

.orbit-flash {
  width: var(--size, 400px);
  height: var(--size, 400px);
  margin: calc(var(--size, 400px) / -2) 0 0 calc(var(--size, 400px) / -2);
  border-radius: 50%;
  background: radial-gradient(circle,
    rgba(255, 246, 228, 0.55) 0%,
    rgba(255, 214, 160, 0.34) 20%,
    rgba(255, 180, 110, 0.14) 44%,
    rgba(255, 160, 90, 0.04) 62%,
    transparent 72%);
  mix-blend-mode: screen;
  z-index: 8;
  animation: releaseFlash 700ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

@keyframes releaseFlash {
  0%   { opacity: 0; transform: scale(0.55); }
  14%  { opacity: 1; }
  100% { opacity: 0; transform: scale(1.8); }
}

/* =========================================================
   PHASE 3 — WIDGETS FLIEGEN RAUS
   Position/Größe/Deckkraft steuert der RAF-Loop. CSS lässt die Icons
   wie Bokeh-Lichter unscharf starten und unterwegs scharf stellen.
   ========================================================= */

.orbit-item.is-bursting {
  animation: widgetFocus 1000ms cubic-bezier(0.2, 0.7, 0.2, 1) var(--burst-delay, 0ms) backwards;
}

@keyframes widgetFocus {
  0%   { filter: blur(16px) brightness(1.8); }
  55%  { filter: blur(4px) brightness(1.25); }
  100% { filter: blur(var(--dof-px, 0px)) brightness(1); }
}

/* =========================================================
   MODUL — Box-Shadow reduziert, preserve-3d raus
   ========================================================= */

.orbit-item {
  position: absolute;
  top: 0;
  left: 0;
  width: 84px;
  height: 84px;
  margin-left: -42px;
  margin-top: -42px;

  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;

  padding: 0;
  border: none;
  border-radius: 50%;

  /* Glanzlicht: folgt der Maus (--hx/--hy in %, vom JS gesetzt) */
  --spec: radial-gradient(circle at calc(var(--hx, 34) * 1%) calc(var(--hy, 26) * 1%),
    rgba(255, 255, 255, 0.5) 0%,
    rgba(255, 255, 255, 0.18) 9%,
    rgba(255, 255, 255, 0) 28%);

  /* Flache Fläche aus dem Akzent #004953, dünner Rand, kaum Schatten */
  background:
    var(--spec),
    linear-gradient(160deg,
      rgba(0, 73, 83, 0.6) 0%,
      rgba(2, 16, 20, 0.88) 100%);

  box-shadow:
    0 0 0 1px rgba(92, 160, 171, 0.26),
    0 6px 18px rgba(0, 0, 0, 0.5);

  color: var(--silver-pure);
  font-family: 'Space Grotesk', sans-serif;
  cursor: pointer;

  backface-visibility: hidden;
  -webkit-font-smoothing: antialiased;

  transform: translate3d(0, 0, 0) scale(0);
  opacity: 0;
  pointer-events: none;

  /* transform/opacity setzt der RAF-Loop jeden Frame – eine Transition
     darauf würde jede Bewegung verzögern. */
  transition:
    box-shadow 0.4s cubic-bezier(0.4, 0, 0.2, 1),
    background 0.4s ease;
}

/* Tiefenschärfe: hintere Kugeln werden unscharf (--dof-px setzt das JS) */
.orbit.is-expanded .orbit-item {
  filter: blur(var(--dof-px, 0px));
}

/* --depth-opacity wird per JS pro Frame gesetzt */
.orbit.is-expanded .orbit-item {
  opacity: var(--depth-opacity, 1);
  pointer-events: auto;
}

.orbit-item::after {
  content: "";
  position: absolute;
  inset: -12%;
  border-radius: 50%;
  background: radial-gradient(circle,
    rgba(0, 73, 83, 0.22),
    transparent 70%);
  z-index: -1;
  pointer-events: none;
  /* Hinter der Erde leuchtet der Schein kaum noch */
  opacity: calc(1 - var(--behind, 0) * 0.8);
}

/* =========================================================
   RÜCKSEITE — Widgets hinter der Erde
   --behind (0..1) wird per JS aus der Tiefe berechnet.
   ========================================================= */

.orbit-item::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 40%,
    rgba(0, 8, 10, 0.5) 0%,
    rgba(0, 3, 5, 0.78) 100%);
  opacity: calc(var(--behind, 0) * 0.85);
  pointer-events: none;
}

/* Hinter der Erde nicht anwählbar – Ziehen dreht dort den Orbit */
.orbit.is-expanded .orbit-item.is-behind {
  pointer-events: none;
  cursor: default;
}

.orbit-item-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  pointer-events: none;
  transition: transform 0.4s cubic-bezier(0.6, 0, 0.3, 1),
              opacity 0.4s ease,
              filter 0.4s ease;
}

.orbit-item i {
  font-size: 20px;
  color: rgba(226, 232, 240, 0.92);
  transition: color 0.4s ease, transform 0.4s ease;
}

.orbit-item-label {
  /* Name sitzt unter dem Kreis und erscheint erst beim Überfahren */
  position: absolute;
  top: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.02em;
  color: rgba(226, 232, 240, 0.95);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.25s ease;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.9);
}

.orbit-item:hover {
  background:
    var(--spec),
    linear-gradient(160deg,
      rgba(0, 73, 83, 0.95) 0%,
      rgba(2, 20, 24, 0.92) 100%);

  box-shadow:
    0 0 0 1px rgba(92, 160, 171, 0.7),
    0 10px 26px rgba(0, 0, 0, 0.55);
}

.orbit-item:hover i {
  color: #ffffff;
  transform: scale(1.08);
}

.orbit-item:hover .orbit-item-label {
  opacity: 1;
}

.orbit-item[data-target="placeholder"] {
  background: var(--spec), linear-gradient(rgba(2, 14, 16, 0.85), rgba(2, 14, 16, 0.85));
  box-shadow: 0 0 0 1px rgba(92, 160, 171, 0.18);
}

.orbit.is-expanded .orbit-item[data-target="placeholder"] {
  opacity: calc(var(--depth-opacity, 1) * 0.75);
}

.orbit-item[data-target="placeholder"] i {
  color: rgba(226, 232, 240, 0.7);
}

.orbit.is-expanded .orbit-item[data-target="placeholder"]:hover {
  opacity: var(--depth-opacity, 1);
}

.orbit-item[data-target="empty"] {
  background: transparent;
  box-shadow: 0 0 0 1px rgba(92, 160, 171, 0.18);
}

.orbit.is-expanded .orbit-item[data-target="empty"] {
  opacity: calc(var(--depth-opacity, 1) * 0.45);
}

.orbit.is-expanded .orbit-item[data-target="empty"]:hover {
  opacity: calc(var(--depth-opacity, 1) * 0.9);
}

.orbit-item[data-target="empty"]:hover {
  box-shadow: 0 0 0 1px rgba(92, 160, 171, 0.5);
}

.orbit-item[data-target="empty"] i {
  color: rgba(226, 232, 240, 0.55);
}

/* =========================================================
   EINFLUG — Die Szene fliegt auf die angeklickte Scheibe zu; das Modul wird
   durch einen Kreis aufgedeckt, der von der Scheibe aus wächst.
   Beim Zurückgehen schließt sich der Kreis wieder auf die Scheibe.
   Variablen (vom JS am body gesetzt): --dive-x/-y Mittelpunkt, --dive-r0 Scheibenradius,
   --dive-rf Radius, der den ganzen Bildschirm deckt.
   ========================================================= */

/* Der Orbit bleibt während des Flugs sichtbar, obwohl der State schon wechselt */
body.is-diving-in:not(.state-home) #orbit-stage,
body.is-diving-out #orbit-stage {
  visibility: visible !important;
}

body.is-diving-in #orbit-stage,
body.is-diving-out #orbit-stage {
  /* Ebene einmal vorbereiten: kein Neu-Rastern beim Zoomen oder am Ende der Animation */
  will-change: transform, opacity;
  backface-visibility: hidden;
}

body.is-diving-in #orbit-stage {
  transform-origin: var(--dive-x) var(--dive-y);
  animation: diveZoomIn 720ms cubic-bezier(0.55, 0, 0.9, 0.45) both;
}

body.is-diving-out #orbit-stage {
  transform-origin: var(--dive-x) var(--dive-y);
  animation: diveZoomOut 720ms cubic-bezier(0.1, 0.55, 0.45, 1) both;
}

/* Leichtgewichtig: nur Skalierung (3,2x) und Deckkraft, kein Weichzeichner auf der großen Ebene.
   Die Szene ist schon bei 65 % ganz ausgeblendet, damit am Ende nichts Großes mehr verschwindet. */
@keyframes diveZoomIn {
  0%   { transform: scale(1); opacity: 1; }
  25%  { opacity: 1; }
  65%  { opacity: 0; }
  100% { transform: scale(3.2); opacity: 0; }
}

@keyframes diveZoomOut {
  0%   { transform: scale(3.2); opacity: 0; }
  35%  { opacity: 0; }
  75%  { opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

body.is-diving-in .module-slot.is-active {
  animation: diveReveal 720ms cubic-bezier(0.6, 0, 0.25, 1) both;
}

body.is-diving-in .module-slot.is-active > .module-inner {
  animation: diveSettle 720ms ease-out both;
}

/* Per Einflug geöffnet: nach dem Einflug darf die normale Öffnen-Animation des Moduls
   (openFromCenter) nicht nochmal starten, sonst springt das Bild auf 0,15 und wächst neu */
.module-slot.no-enter-anim.is-active > .module-inner {
  animation: none;
}

@keyframes diveReveal {
  from { clip-path: circle(var(--dive-r0) at var(--dive-x) var(--dive-y)); }
  to   { clip-path: circle(var(--dive-rf) at var(--dive-x) var(--dive-y)); }
}

@keyframes diveSettle {
  from { transform: scale(1.1); filter: blur(8px); opacity: 0.5; }
  to   { transform: none; filter: none; opacity: 1; }
}

/* Rückweg: das verlassene Modul bleibt sichtbar und schließt sich auf die Scheibe */
.module-slot.is-leaving {
  z-index: 100;
  animation: diveClose 720ms cubic-bezier(0.3, 0, 0.3, 1) both;
}

.module-slot.is-leaving > .module-inner {
  transform: none;
  opacity: 1;
  filter: none;
  visibility: visible !important;
  transition: none !important;
  animation: diveUnsettle 720ms ease-in both;
}

@keyframes diveUnsettle {
  from { transform: none; filter: none; opacity: 1; }
  to   { transform: scale(1.1); filter: blur(8px); opacity: 0.5; }
}

/* Scheiben-Farbe: Beim Schließen färbt sich der Kreis auf das dunkle Petrol der
   Scheibe (samt Glanzlicht), beim Aufdecken startet er in dieser Farbe und gibt
   dann das Modul frei. Der Kreis wirkt dadurch wie die Scheibe selbst. */
body.is-diving-in .module-slot.is-active::after,
.module-slot.is-leaving::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 50;
  pointer-events: none;
  background:
    radial-gradient(circle calc(var(--dive-r0) * 1.1)
        at calc(var(--dive-x) - var(--dive-r0) * 0.32) calc(var(--dive-y) - var(--dive-r0) * 0.48),
      rgba(255, 255, 255, 0.42) 0%,
      rgba(255, 255, 255, 0.12) 18%,
      transparent 70%),
    radial-gradient(circle var(--dive-rf) at var(--dive-x) var(--dive-y),
      rgba(0, 73, 83, 0.94) 0%,
      rgba(2, 14, 18, 0.985) 30%,
      #010709 100%);
}

body.is-diving-in .module-slot.is-active::after {
  animation: diveTintOut 720ms ease-out both;
}

.module-slot.is-leaving::after {
  animation: diveTintIn 720ms ease-in both;
}

@keyframes diveTintOut {
  0%   { opacity: 1; }
  60%  { opacity: 0; }
  100% { opacity: 0; }
}

@keyframes diveTintIn {
  0%   { opacity: 0; }
  35%  { opacity: 0; }
  100% { opacity: 1; }
}

@keyframes diveClose {
  from { clip-path: circle(var(--dive-rf) at var(--dive-x) var(--dive-y)); }
  to   { clip-path: circle(var(--dive-r0) at var(--dive-x) var(--dive-y)); }
}

@keyframes openFromCenter {
  0% {
    transform: translate3d(0, 0, 0) scale(0.15);
    opacity: 0;
    filter: blur(12px) brightness(1.6);
  }
  35% {
    transform: translate3d(0, 0, 0) scale(0.85);
    opacity: 0.85;
    filter: blur(4px) brightness(1.2);
  }
  70% {
    transform: translate3d(0, 0, 0) scale(1.03);
    opacity: 1;
    filter: blur(0);
  }
  100% {
    transform: translate3d(0, 0, 0) scale(1);
    opacity: 1;
    filter: none;
  }
}

/* =========================================================
   MOBILE
   ========================================================= */

@media (max-width: 640px) {
  .orbit { perspective: 1100px; }

  .orbit-core {
    width: calc(min(204px, 53vw) * var(--earth-zoom, 1));
    height: calc(min(204px, 53vw) * var(--earth-zoom, 1));
  }

  .orbit-item {
    width: 64px;
    height: 64px;
    margin-left: -32px;
    margin-top: -32px;
  }

  .orbit-item i { font-size: 17px; }
  .orbit-item-label { font-size: 11px; }
}

@media (prefers-reduced-motion: reduce) {
  .orbit-fx {
    display: none;
  }
}
