/* ══════════════════════════════════════════════════════════════
   Cloudsys — Tauchfahrt

   Die Schrift steht im Staub, nicht daneben: ein Partikelfeld
   hinter dem Text, ein zweites davor. Die Kamera taucht beim
   Scrollen nach vorne durch das Feld.

   Grund   #07060F
   Staub   #FF2D95 · #00F0FF · #FFD23F
   Glut    #FF4D00  (Green Hosting)
   Schrift #EDEAF7
   ══════════════════════════════════════════════════════════════ */

:root {
  --grund:   #07060F;
  --magenta: #FF2D95;
  --cyan:    #00F0FF;
  --zitrus:  #FFD23F;
  --glut:    #FF4D00;
  --ink:     #EDEAF7;
  --dim:     #7C7796;

  --sans: "Archivo", "Helvetica Neue", Arial, sans-serif;
  --mono: "JetBrains Mono", ui-monospace, monospace;

  --gutter: clamp(1.1rem, 3vw, 2.5rem);
  --ease:   cubic-bezier(.22, 1, .36, 1);
  --accent: var(--cyan);
  /* Wie weit eine Sektion seitlich driftet, bevor sie an ihren Platz kommt */
  --drift:  5rem;
}

/* Der Akzent folgt der Einfärbung des Staubs */
body.warm  { --accent: var(--zitrus); }
body.alarm { --accent: #FF6B6B; }

*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--grund);
  color: var(--ink);
  font-family: var(--sans);
  font-weight: 400;
  font-size: clamp(.95rem, .9rem + .2vw, 1.05rem);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* ── Die beiden Staubschichten ──────────────────────────────── */
#deep, #near {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
#deep { z-index: 0; }
#near { z-index: 4; pointer-events: none; }   /* liegt vor der Schrift */

/* Hält die Bildmitte ruhig genug zum Lesen */
.vignette {
  position: fixed;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background:
    radial-gradient(58% 46% at 50% 50%, rgba(7, 6, 15, .82) 0%, rgba(7, 6, 15, .5) 45%, transparent 78%),
    radial-gradient(120% 90% at 50% 120%, rgba(7, 6, 15, .55) 0%, transparent 60%);
}

main { position: relative; z-index: 3; }

.skip {
  position: absolute; left: -9999px;
  background: var(--cyan); color: var(--grund);
  padding: .75rem 1rem; z-index: 99;
}
.skip:focus { left: var(--gutter); top: .75rem; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: 2px;
}

a { color: inherit; }

/* ── HUD: das einzige Interface ─────────────────────────────── */
.hud, .hud-bottom {
  position: fixed;
  z-index: 5;
  font-family: var(--mono);
  font-size: .66rem;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--dim);
  pointer-events: none;
}
.hud {
  top: 0; left: 0; right: 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1.15rem var(--gutter);
}
.hud-tc { color: var(--ink); letter-spacing: .3em; }
.hud-tl { transition: opacity .6s var(--ease); }
body.moved .hud-tl { opacity: 0; }

.hud-bottom {
  bottom: 0; left: 0; right: 0;
  display: flex;
  justify-content: space-between;
  padding: 1.15rem var(--gutter);
  pointer-events: auto;
}
.hud-bottom a { text-decoration: none; transition: color .3s; }
.hud-bottom a:hover { color: var(--accent); }

/* ── Anfang: oben ein Wort, unten ein Wort ──────────────────── */
.hero {
  min-height: 100svh;
  display: grid;
  grid-template-rows: auto 1fr auto;
  align-items: center;
  padding: 4.5rem var(--gutter) 4.5rem;
  text-align: center;
}

h1 {
  display: contents;
  font-weight: 200;
  margin: 0;
}
h1 .up, h1 .down {
  display: block;
  font-size: clamp(2.6rem, 10vw, 9.5rem);
  line-height: .92;
  letter-spacing: -.035em;
  font-weight: 200;
  opacity: 0;
  animation: fade 1.6s var(--ease) forwards;
}
/* Ein Wort oben, ein Wort unten, der Absatz dazwischen */
h1 .up   { grid-row: 1; animation-delay: .2s; }
h1 .down { grid-row: 3; animation-delay: .45s; }

.lede {
  grid-row: 2;
  align-self: center;
  max-width: 42ch;
  margin: 0 auto;
  font-family: var(--mono);
  font-size: .72rem;
  line-height: 2;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--ink) 64%, transparent);
  opacity: 0;
  animation: fade 1.6s var(--ease) .8s forwards;
}

@keyframes fade { to { opacity: 1; } }

/* ── Ein Auftritt pro Leistung ──────────────────────────────── */
.act {
  min-height: 100svh;
  display: grid;
  place-items: center;
  padding: 5rem var(--gutter);
  text-align: center;
  /* Der seitliche Versatz beim Driften darf keine Bildlaufleiste erzeugen.
     `clip` statt `hidden`, weil `hidden` einen Scroll-Container aufmacht —
     das würde das Sticky der Gruppennamen brechen. */
  overflow-x: clip;
}

/* Rückfallebene: einmaliges Aufdecken per IntersectionObserver, wie bisher */
.act-inner {
  max-width: 44rem;
  opacity: 0;
  transform: translateY(1.5rem);
  transition: opacity 1s var(--ease), transform 1s var(--ease);
}
.act-inner.is-in { opacity: 1; transform: none; }

/* ── Driften und Zurücksinken ────────────────────────────────────
   Eine einzige Animation über die gesamte Sichtbarkeit der Sektion,
   an den Scroll gekoppelt statt einmalig ausgelöst. Dadurch läuft sie
   beim Zurückscrollen rückwärts — und sie läuft im Compositor, was bei
   zwei WebGL-Kontexten daneben kein Nebenaspekt ist.

   Die Sektion driftet aus dem Unscharfen an ihren Platz und sinkt danach
   in die Tiefe zurück, statt einfach zu verschwinden.                    */
@supports (animation-timeline: view()) {
  .act-inner {
    transition: none;
    animation: drift-links linear both;
    animation-timeline: view();
    animation-range: cover 0% cover 100%;
  }
  /* Richtungswechsel innerhalb der Gruppe: 1. links, 2. rechts, 3. links */
  .group section:nth-of-type(even) .act-inner { animation-name: drift-rechts; }

  .group { view-timeline-name: --gruppe; view-timeline-axis: block; }
  .group-name .rule {
    animation: linie-fuellen linear both;
    animation-timeline: --gruppe;
    animation-range: cover 0% cover 100%;
  }
}

/* Die Prozentwerte folgen nicht dem Gefühl, sondern der Geometrie des
   `cover`-Bereichs: er läuft über Sektionshöhe + Fensterhöhe. Bei einer
   Sektion von 100svh steht der Textblock erst ab 26 % im Bild, sitzt bei
   50 % genau mittig und verlässt das Bild oben bei 75 %.

   Deshalb driftet sie bis 24 % unsichtbar unterhalb des Bildes, steht von
   42 % bis 58 % scharf und ist bei 70 % zurückgesunken — solange sie noch
   zu sehen ist. Sonst spielte das Zurücksinken außerhalb des Bildes und
   die Sektion schöbe sich in voller Helligkeit durch die HUD-Zeile.       */
@keyframes drift-links {
  0%,
  24%  { opacity: 0;  transform: translate3d(calc(-1 * var(--drift)), 0, 0) scale(.96); filter: blur(8px); }
  42%,
  58%  { opacity: 1;  transform: translate3d(0, 0, 0)     scale(1);   filter: blur(0); }
  70%,
  100% { opacity: .1; transform: translate3d(0, -3rem, 0) scale(.88); filter: blur(6px); }
}
@keyframes drift-rechts {
  0%,
  24%  { opacity: 0;  transform: translate3d(var(--drift), 0, 0) scale(.96); filter: blur(8px); }
  42%,
  58%  { opacity: 1;  transform: translate3d(0, 0, 0)     scale(1);   filter: blur(0); }
  70%,
  100% { opacity: .1; transform: translate3d(0, -3rem, 0) scale(.88); filter: blur(6px); }
}
@keyframes linie-fuellen {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}

/* ── Gruppenname: bleibt stehen, bis der nächste ihn wegschiebt ──
   Zwei Geschwister mit gleichem Sticky-Versatz verdrängen einander von
   selbst — dasselbe Verhalten wie Abschnittsköpfe in iOS-Listen. Dafür
   braucht es keinen Scroll-Handler.

   Die Ecke oben links wird frei, sobald das HUD-Wort SCROLLEN nach 60 px
   ausblendet; genau dort steht der Name.                                 */
.group-name {
  position: sticky;
  top: 3.1rem;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: .9rem;
  /* Höhe und negative Marge heben sich auf: der Name verschiebt das
     Layout der Sektionen nicht, er legt sich darüber. */
  height: 1.5rem;
  margin: 0 0 -1.5rem;
  padding: 0 var(--gutter);
  font-family: var(--mono);
  font-size: .64rem;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--dim);
  pointer-events: none;
}
.group-name.alt { color: var(--magenta); }

/* Haarlinie als stiller Fortschrittsbalken durch die Gruppe */
.group-name .rule {
  flex: 0 0 auto;
  width: clamp(2.5rem, 10vw, 7rem);
  height: 1px;
  background: currentColor;
  opacity: .35;
  transform: scaleX(1);
  transform-origin: left center;
}

.act h2 {
  font-size: clamp(2.1rem, 7vw, 6rem);
  font-weight: 200;
  line-height: .96;
  letter-spacing: -.035em;
  margin: 0 0 1.6rem;
  text-wrap: balance;
}
.act h2 .thin { font-weight: 200; color: var(--dim); }

.line {
  max-width: 40ch;
  margin: 0 auto 2.25rem;
  font-size: clamp(1rem, 1.2vw, 1.2rem);
  color: color-mix(in srgb, var(--ink) 72%, transparent);
  text-wrap: pretty;
}

/* ── Fakten als Mono-Marken ─────────────────────────────────── */
.facts {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .5rem;
  margin: 0 0 2.25rem;
  padding: 0;
}
.facts li {
  font-family: var(--mono);
  font-size: .64rem;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--dim);
  border: 1px solid color-mix(in srgb, var(--ink) 16%, transparent);
  border-radius: 999px;
  padding: .42rem .85rem;
}
.facts a { text-decoration: none; color: var(--accent); }
.facts a:hover { text-shadow: 0 0 16px currentColor; }

.lnk {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  font-family: var(--mono);
  font-size: .66rem;
  letter-spacing: .17em;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--accent);
  padding-bottom: .3rem;
  border-bottom: 1px solid currentColor;
  transition: gap .3s var(--ease), text-shadow .3s var(--ease);
}
.lnk::after { content: "→"; }
.lnk:hover { gap: 1rem; text-shadow: 0 0 18px currentColor; }

.cta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 1.5rem;
}
.btn {
  font-family: var(--mono);
  font-size: .66rem;
  letter-spacing: .17em;
  text-transform: uppercase;
  text-decoration: none;
  padding: .9rem 1.7rem;
  border: 1px solid var(--ink);
  color: var(--ink);
  transition: background-color .3s var(--ease), color .3s var(--ease),
              border-color .3s var(--ease), box-shadow .3s var(--ease);
}
.btn:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--grund);
  box-shadow: 0 0 40px color-mix(in srgb, var(--accent) 45%, transparent);
}

/* ── Kennzahlen ─────────────────────────────────────────────── */
.zahlen {
  list-style: none;
  margin: 0; padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  gap: 2.5rem 1.5rem;
}
.zahlen li { display: grid; gap: .5rem; min-width: 0; }
.zahlen .v {
  font-size: clamp(1.8rem, 3.6vw, 3.2rem);
  font-weight: 200;
  line-height: 1;
  letter-spacing: -.02em;
  color: var(--accent);
  font-feature-settings: "tnum";
}
.zahlen .k {
  font-family: var(--mono);
  font-size: .6rem;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--dim);
}

/* ── Schmal ─────────────────────────────────────────────────── */
@media (max-width: 700px) {
  /* 5 rem wären auf 390 px ein Fünftel der Bildbreite — das driftet nicht,
     das springt. */
  :root { --drift: 2rem; }
  .hud-tr { display: none; }
  .lede { font-size: .66rem; letter-spacing: .1em; line-height: 1.9; }
  .vignette {
    background: radial-gradient(80% 46% at 50% 50%, rgba(7, 6, 15, .88) 0%, rgba(7, 6, 15, .55) 50%, transparent 82%);
  }
}

/* ── Reduzierte Bewegung ────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  h1 .up, h1 .down, .lede { opacity: 1; }
  /* Scroll-gekoppelte Animationen hängen nicht an der Dauer — sie müssen
     ausdrücklich abgeschaltet werden, sonst greift die Verkürzung oben
     ins Leere und die Sektionen blieben unsichtbar. */
  .act-inner {
    animation: none !important;
    opacity: 1;
    transform: none;
    filter: none;
  }
  .group-name .rule { animation: none !important; transform: scaleX(1); }
}
