/* GAIA Hero — Layout nach Briefing §5, erweitert um den mobilen Punkt-Modus.

   > 900px   Kugel rechts versetzt, Labels orbitieren, feste Lesezone links (aktiver Slot links)
   ≤ 900px   Kugel zentriert, Labels orbitieren weiter, Lesezone als Band darunter
   ≤ 600px   Kugel zentriert, Punkt-Indikatoren darunter, darunter Titel + wechselnder Text
   reduced   keine Mechanik: ruhiges Poster, vier gestapelte Abschnitte, Labels als Anker

   Eigenständig (eigene Tokens), damit die Vergleichsseiten in lab/ ohne css/style.css laufen. */

:root{
  --bg:#000000;
  --ink:#e2efe9;
  --pill:rgba(8,18,20,.9);    /* deckend genug, dass die Label-Schrift auch über den hellen Wolken der Kugel lesbar bleibt (WCAG 1.4.3) */
  --line:rgba(150,210,190,.28);
  --accent:#6fe0bd;

  --globe-x:62%;      /* Kugelmittelpunkt: rechts aus der Mitte gerückt */
  --globe-y:50%;
  --globe-w:44%;      /* dargestellte Kugelbreite; der Orbitradius hängt daran */

  /* --ring-r-factor setzt hero.js aus MENU_RADIUS_FACTOR — eine Quelle für den Umlaufradius. */
  --reader-left:clamp(24px,5vw,72px);
  --label-clear:86px;  /* halbe Label-Pille + Luft: so weit muss die Lesezone vor dem Ring enden */
}

*{box-sizing:border-box;margin:0;padding:0}
body{background:var(--bg);color:var(--ink);
  font-family:'Inter','Segoe UI',system-ui,sans-serif;-webkit-font-smoothing:antialiased}

/* Nur die CSS-Variante rastet ein. Mit Maus `proximity`: der Nutzer wird nie festgehalten,
   der Browser zieht nur nach, wenn er ohnehin nah an einem Punkt steht. */
:root:has(.hero[data-snap="css"]){scroll-snap-type:y proximity}

/* Auf Touch reicht das nicht: ein Fling überquert sonst beliebig viele Schritte („Glücksrad")
   und darf zwischen zwei Rastpunkten liegenbleiben. `mandatory` + `snap-stop:always` machen
   aus einer Wischgeste genau einen Abschnitt — das, was die Punkte ohnehin versprechen. */
@media (pointer:coarse) and (hover:none){
  :root:has(.hero[data-snap="css"]){scroll-snap-type:y mandatory}
  .hero[data-snap="css"] .snap{scroll-snap-stop:always}
  /* Pull-to-Refresh und Rubber-Banding konkurrieren sonst mit dem Umschlag in wrapScroll(). */
  :root:has(.hero){overscroll-behavior-y:contain}
}

.vh{position:absolute;width:1px;height:1px;margin:-1px;padding:0;border:0;
  overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}

/* ---------- Gerüst ---------- */

/* `svh` für die Strecke, nicht `vh`: `100vh` ist auf Mobil die *große* Viewport-Höhe (URL-
   Leiste eingefahren), während JS in der tatsächlich sichtbaren Höhe rechnet — jeder
   Rastpunkt läge dann um die Höhe der Browserleiste daneben, kumulativ über alle Schritte.
   `svh` ist die kleine, stabile Höhe: sie ändert sich beim Ein-/Ausfahren nicht.
   Die Bühne selbst darf `dvh` sein, sie füllt einfach das gerade Sichtbare. */
.hero{position:relative;height:calc(var(--steps,17) * 100svh)}
.pin{position:sticky;top:0;height:100dvh;overflow:hidden}
.stage{position:absolute;inset:0}

/* Rastpunkte + Scroll-Strecke. Absolut, damit sie die Höhe von .hero nicht verändern. */
.rails{position:absolute;inset:0;pointer-events:none}
.snap{height:calc(100% / var(--steps,17))}
.hero[data-snap="css"] .snap{scroll-snap-align:start}

.globe{display:block;width:100%;height:auto;background:var(--bg);
  pointer-events:none;user-select:none;
  opacity:0;transition:opacity .5s ease}
.hero.is-ready .globe{opacity:1}

.logo{position:absolute;top:clamp(18px,3.2vh,42px);left:50%;transform:translateX(-50%);
  z-index:6;pointer-events:none}
.logo img{display:block;width:clamp(180px,22vw,320px);height:auto}

/* ---------- Orbit-Modus (Desktop + Tablet) ---------- */

/* Kugel + Menü teilen einen Bezugsrahmen: das Menü kreist exakt um den Kugelmittelpunkt. */
.mode-orbit .orbit{position:absolute;left:var(--globe-x);top:var(--globe-y);
  transform:translate(-50%,-50%);width:var(--globe-w)}

.menu{position:absolute;left:50%;top:50%;width:0;height:0;z-index:4;pointer-events:none}

/* Nicht das ganze Element dimmen: `opacity` würde auch den Kontrast-Hintergrund der Pille
   ausblenden — genau dort, wo das Label über die hellen Wolken der Kugel wandert, wäre die
   Schrift dann unlesbar. Stattdessen nur Schrift und Rahmen zurücknehmen. */
.m-item{position:absolute;left:0;top:0;
  transform:translate(calc(-50% + var(--x,0px)), calc(-50% + var(--y,0px)));
  font-size:.74rem;letter-spacing:.16em;text-transform:uppercase;text-decoration:none;
  color:rgba(226,239,233,.78);white-space:nowrap;padding:.5rem .95rem;  /* ≥ 7:1 auch über hellen Wolken — AAA-Reserve (WCAG 1.4.6) */
  border:1px solid rgba(150,210,190,.16);
  border-radius:999px;background:var(--pill);backdrop-filter:blur(7px);
  transition:color .35s ease,border-color .35s ease,background .35s ease}
.m-item.is-current{color:#fff;border-color:var(--accent);background:rgba(20,42,40,.85)}

/* .menu selbst ist pointer-events:none (0×0-Anker) — die Links sind wieder klickbar:
   Klick/Enter fährt zum Abschnitt (siehe stepTo() in hero.js). */
.mode-orbit .m-item{pointer-events:auto}
.mode-orbit .m-item:hover{color:#fff}
.m-item:focus-visible{outline:2px solid var(--accent);outline-offset:3px}

/* Feste Lesezone: die Labels rotieren, dieser Block nicht. Nur der Inhalt wird getauscht.

   Die Breite hängt an der Ringgeometrie, nicht an einer freien Zahl: das aktive Label steht
   links auf dem Ring, also bei `--globe-x − --globe-w × --ring-r-factor`. Endete die Lesezone
   fest bei 460px, schöbe sie sich auf schmalen Breiten (Tablet quer!) über genau dieses Label.
   `--label-clear` ist der Platz für die halbe Pille plus Abstand. */
.mode-orbit .reader{position:absolute;left:var(--reader-left);top:50%;transform:translateY(-50%);
  width:min(460px, calc(var(--globe-x) - var(--globe-w) * var(--ring-r-factor,.46)
                        - var(--label-clear) - var(--reader-left)));
  min-width:300px;
  height:clamp(240px,44vh,400px);z-index:5}  /* hoch genug für Kontakt inkl. Firmenblöcke */
.mode-orbit .reader-item{position:absolute;inset:0;display:flex;flex-direction:column;
  justify-content:safe center;gap:.7rem;padding:1.4rem 1.7rem;overflow-y:auto;  /* safe center + Scroll: vergrößerter Text (WCAG 1.4.4) scrollt im Panel statt herauszuquellen */
  border:1px solid var(--line);border-radius:16px;
  background:rgba(4,10,11,.75);backdrop-filter:blur(9px);  /* Fließtext ≥ 7:1 selbst über Weiß — AAA-Reserve (WCAG 1.4.6) */
  opacity:0;pointer-events:none}
.mode-orbit .reader-label{display:none}                     /* Desktop: das Label kreist ohnehin */

/* Genau ein Panel ist sichtbar — welches, entscheidet setActive() nach dem nächstgelegenen
   Schritt. Früher schrieb JS eine scroll-abhängige Opazität hier hinein; um jede Schrittmitte
   lag dabei ein Band, in dem *alle* Panels auf 0 standen. Wer dort liegenblieb — auf Touch der
   Normalfall — sah einen leeren Bildschirm. Jetzt ist immer eines auf 1.
   Das `.hero`-Präfix ist nötig, damit die Regel die modusspezifischen `opacity:0`/
   `pointer-events:none` schlägt: die haben dieselbe Spezifität und stehen später. */
.reader-item{transition:opacity .35s ease}
.hero .reader-item.is-active{opacity:1;pointer-events:auto}
/* Fokus in einem Panel (z. B. Kontakt-Link per Tastatur) blendet es ein – sonst läge der Fokus
   auf unsichtbarem Inhalt (WCAG 2.4.7). !important schlägt auch den Modus-Standard;
   nach dem Verlassen greift wieder die Klasse. */
.reader-item:focus-within{opacity:1 !important;pointer-events:auto}
.reader-item:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
.reader-item h2{font-size:1.42rem;font-weight:600;line-height:1.2;color:#fff}
.reader-item p{font-size:1rem;line-height:1.55;color:var(--ink)}
/* Die Firmenblöcke des alten Footers, kompakt im Kontakt-Panel. Volle Ink-Deckung:
   auch diese kleine Schrift hält die 7:1-Reserve auf dem Panel (WCAG 1.4.6). */
.reader-companies{display:flex;flex-wrap:wrap;gap:.5rem 1.6rem;margin-top:.3rem}
.reader-companies address{font-style:normal;font-size:.8rem;line-height:1.5;color:var(--ink)}
.reader-companies strong{display:block;font-weight:600;color:#fff}
.reader-companies span{display:block}
/* inline-block statt block: steht nach den Block-Zeilen ohnehin auf eigener Zeile, die
   Unterstreichung beim Hover bleibt aber an der Textbreite statt über die Spalte zu laufen. */
.reader-companies a{display:inline-block;margin-top:.15rem}

.reader-contact a,.reader-companies a{color:var(--accent);text-decoration:none;border-bottom:1px solid transparent}
.reader-contact a:hover,.reader-companies a:hover{border-bottom-color:var(--accent)}
/* Sichtbare Tastatur-Fokusmarkierung (WCAG 2.4.7) – nicht mehr outline:none. */
.reader-contact a:focus-visible,.reader-companies a:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-bottom-color:var(--accent)}

/* Tablet: Kugel zentriert, Labels orbitieren weiter, Lesezone als Band darunter.

   Bis 1200px statt bis 900px: im Seitenlayout schiebt sich die Lesezone sonst über das aktive
   Label — bei 1024px um rund 47px, bei 1180px (iPad quer) um rund 44px. Und ohne untere
   Grenze, denn `min-width:601px` ließ bei gebrochenen Breiten (600.5px) eine Lücke, in der
   weder dieser Block noch der Punkt-Modus griff und ein schmaler Schirm die Desktop-Tokens bekam.
   Im Punkt-Modus greifen die `.mode-orbit`-Regeln ohnehin nicht. */
@media (max-width:1200px){
  :root{--globe-x:50%;--globe-y:36%;--globe-w:58%}
  .mode-orbit .reader{left:50%;top:auto;bottom:5vh;transform:translateX(-50%);
    width:min(88%,640px);min-width:0;height:30vh;text-align:center}
  .mode-orbit .reader-item{align-items:center}
  .logo img{width:clamp(160px,30vw,260px)}
}

/* Flache Schirme (Tablet quer): die Kollision ist hier vertikal — bei 1024×768 stünde das
   untere Label bei y≈549, die Lesezone begänne bei y≈500. Kleinere Kugel, kürzeres Band,
   Mittelpunkt etwas tiefer, damit auch das obere Label das Logo nicht touchiert. */
@media (max-width:1200px) and (orientation:landscape){
  :root{--globe-x:50%;--globe-y:40%;--globe-w:38%}
  .mode-orbit .reader{bottom:3vh;height:26vh}
  .logo img{width:clamp(140px,18vw,200px)}
}

/* ---------- Punkt-Modus (Mobil) ---------- */
/* Die Kugel dreht sich weiter, aber die Labels kreisen nicht: darunter Indikatoren,
   darunter Titel und Text des aktiven Abschnitts. */

.mode-dots .pin{display:flex;flex-direction:column;align-items:center;justify-content:flex-start;
  gap:1.1rem;padding:calc(clamp(18px,3.2vh,42px) + 3.4rem) 1rem 1.5rem}
.mode-dots .stage{position:static}
/* Auch an der Höhe deckeln: im Querformat ist die Breite reichlich und die Höhe knapp —
   ohne `vh`-Grenze schöbe die Kugel Punkte und Text aus dem gepinnten Bereich heraus. */
.mode-dots .orbit{width:min(88%,420px,46vh);margin:0 auto}

/* Die Punkte sind Bedienelemente, keine Deko: Tippen springt zum Abschnitt. Der sichtbare
   Punkt bleibt klein, die Trefferfläche ist 44×44px (WCAG 2.5.5). */
.dots{display:flex;align-items:center;justify-content:center}
.dot{width:2.75rem;height:2.75rem;padding:0;border:0;background:none;
  display:grid;place-items:center;cursor:pointer;-webkit-tap-highlight-color:transparent}
.dot::before{content:'';width:9px;height:9px;border-radius:999px;
  background:rgba(226,239,233,.55);   /* ≥ 3:1 auf Schwarz (WCAG 1.4.11) — .28 war praktisch unsichtbar */
  transition:background .3s ease,transform .3s ease}
.dot.is-current::before{background:var(--accent);transform:scale(1.55)}
.dot:focus-visible{outline:2px solid var(--accent);outline-offset:-6px;border-radius:12px}

/* Scroll-Hinweis: im Punkt-Modus bewegt sich beim Scrollen nichts nach oben (die Bühne ist
   gepinnt), es fehlt also die übliche Rückmeldung. Verschwindet nach dem ersten Scrollen. */
.scroll-hint{display:flex;flex-direction:column;align-items:center;gap:.35rem;
  font-size:.68rem;letter-spacing:.18em;text-transform:uppercase;
  color:rgba(226,239,233,.62);transition:opacity .4s ease;pointer-events:none}
.scroll-hint-chevron{width:9px;height:9px;border-right:1.5px solid currentColor;
  border-bottom:1.5px solid currentColor;transform:rotate(45deg);
  animation:hint-nudge 1.8s ease-in-out infinite}
.hero.has-scrolled .scroll-hint{opacity:0}
@keyframes hint-nudge{0%,100%{transform:rotate(45deg) translate(0,0)}50%{transform:rotate(45deg) translate(3px,3px)}}

/* min-height blockierte das Schrumpfen im Flex-Container: der Kontaktblock rutschte auf
   niedrigen Schirmen unter die Browserleiste, wo `overflow:hidden` am .pin ihn abschnitt
   und kein Scrollen ihn je wieder hervorholte. Jetzt gibt die Zone nach, der Text scrollt. */
.mode-dots .reader{position:relative;width:100%;max-width:34rem;flex:1 1 auto;min-height:0}
.mode-dots .reader-item{position:absolute;inset:0;display:flex;flex-direction:column;
  justify-content:flex-start;gap:.55rem;text-align:center;align-items:center;overflow-y:auto;  /* vergrößerter Text scrollt im Panel (WCAG 1.4.4) statt vom Sheet beschnitten zu werden */
  opacity:0;pointer-events:none}
.mode-dots .reader-label{display:block;font-size:.7rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--accent)}
.mode-dots .reader-item h2{font-size:1.25rem}
.mode-dots .reader-item p{font-size:.95rem}
.mode-dots .reader-companies{justify-content:center;text-align:center}

/* ---------- Statisch: prefers-reduced-motion ---------- */
.hero.is-static{height:auto}
.static-hero{position:relative;min-height:80vh;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:1.6rem;padding:5.5rem 1.2rem 2rem}
.static-hero .globe{width:min(86%,520px);opacity:1}
.menu-static{display:flex;flex-wrap:wrap;gap:.6rem;justify-content:center;pointer-events:auto}
.menu-static .m-item{position:static;transform:none;color:var(--ink)}

.reader-stack{max-width:680px;margin:0 auto;padding:0 1.2rem 4rem;display:flex;
  flex-direction:column;gap:1.4rem}
.reader-stack .reader-item{position:relative;inset:auto;opacity:1;pointer-events:auto;
  display:flex;flex-direction:column;gap:.6rem;align-items:flex-start;
  padding:1.4rem 1.5rem;border:1px solid var(--line);border-radius:16px;
  scroll-margin-top:1.5rem}
.reader-stack .reader-label{display:block;font-size:.7rem;letter-spacing:.18em;
  text-transform:uppercase;color:var(--accent)}

@media (prefers-reduced-motion:reduce){
  :root:has(.hero){scroll-snap-type:none}
  .globe,.m-item,.dot::before,.reader-item,.scroll-hint{transition:none}
  .scroll-hint-chevron{animation:none}
}
