/* Cybez — die Bewegungsschicht.
 *
 * Sie liegt über seiten.css und den beiden Häuten und ändert keine Farbe und
 * keine Schrift. Was sie hinzufügt, ist eine dritte Achse: der Bildschirm, den
 * das Produkt zeigt, bleibt stehen, während der Text an ihm vorbeiläuft.
 *
 * Drei Regeln, an denen sich alles hier misst:
 *
 *   Gebunden.  Was lang ist, hängt am Rollbalken, nicht an einer Uhr. Wer
 *              zurückrollt, sieht es rückwärts. Nichts läuft von selbst los.
 *   Leise.     Kleine Wege (8–24 px), lange Zeiten (.5–.9 s), eine Kurve.
 *              Nichts federt, nichts dreht sich um seiner selbst willen.
 *   Fest.      Nur transform, opacity und filter. Kein Umbruch, kein Sprung.
 *
 * ALLES hier hängt hinter .cy-bewegt, und die Klasse setzt erst das Skript.
 * Ohne Javascript steht die Seite fertig da — der Fehler, eine Seite mit CSS
 * zu verstecken und auf ein Skript zu warten, das sie wieder hervorholt, ist
 * hier einmal passiert und kommt nicht wieder.
 */

:where(.cy) {
  --cy-kurve: cubic-bezier(.22,.61,.24,1);
  --cy-kurve-lang: cubic-bezier(.16,.84,.28,1);
  --cy-tiefe: 1400px;
}

/* ------------------------------------------------------------- Auftritte */

/* Kleiner Weg als vorher, dazu eine Spur Maßstab: es liest sich als
   Näherkommen statt als Hochschieben. */
/* Gleiche Stärke wie die Grundregel in seiten.css, und diese Datei kommt
   später — nur so greift sie. :where() wäre hier schwächer gewesen und hätte
   wortlos nichts getan. */
.cy.cy-bewegt .cy-zeigt {
  opacity: 0;
  transform: translate3d(0, 20px, 0) scale(.988);
  transition: opacity .72s var(--cy-kurve), transform .82s var(--cy-kurve-lang);
  transition-delay: var(--cy-verzug, 0ms);
}
.cy.cy-bewegt .cy-zeigt.cy-da { opacity: 1; transform: none; }

/* Überschriften kommen Wort für Wort hinter einer Kante hervor.
 *
 * Geschnitten wird mit clip-path, nicht mit einer Hülle und overflow:hidden.
 * Der erste Versuch tat genau das — und ein inline-block mit overflow ≠
 * visible nimmt seine Unterkante als Grundlinie. Damit wuchs die Zeilenhöhe
 * der Überschrift, und beim Zerlegen sprang die halbe Seite: 0,098 an
 * Bildaufbau-Verschiebung, gemessen. clip-path rührt das Layout nicht an.
 *
 * Der Schnitt greift außen etwas über, damit Unterlängen und vietnamesische
 * Zeichen im Endzustand nicht angeschnitten werden. */
.cy.cy-bewegt .cy-wort {
  display: inline-block;
  transform: translate3d(0, .38em, 0);
  opacity: 0;
  clip-path: inset(-.25em -.12em 100% -.12em);
}
.cy.cy-bewegt .cy-auftritt .cy-wort {
  transform: none; opacity: 1;
  clip-path: inset(-.25em -.12em -.3em -.12em);
  transition: transform .78s var(--cy-kurve-lang),
              clip-path .78s var(--cy-kurve-lang),
              opacity .5s linear;
  transition-delay: calc(var(--cy-i, 0) * 42ms);
}

/* --------------------------------------------------------------- Kopfbild */

/* Der Film beginnt als Karte und geht beim Rollen auf. Die Werte kommen aus
   bewegung.js als --cy-auf (0 zu, 1 offen); die Kurve steckt im Skript. */
.cy--buehne.cy-bewegt .cy-held--film .cy-film {
  --cy-auf: 0;
  perspective: var(--cy-tiefe);
  border-radius: calc(28px * (1 - var(--cy-auf)));
  overflow: hidden;
  transform: scale(calc(.9 + .1 * var(--cy-auf)));
  will-change: transform;
}
.cy--buehne.cy-bewegt .cy-held--film .cy-film__video {
  transform: scale(calc(1.12 - .12 * var(--cy-auf)));
  filter: brightness(calc(.55 + .45 * var(--cy-auf)));
}

/* Ein Schimmer in der Produktfarbe hinter dem Kopfbereich. Sehr leise —
   er soll die Farbe des Produkts spürbar machen, nicht leuchten. */
.cy--buehne.cy-bewegt .cy-held--film::before {
  content: ""; position: absolute; inset: -10% 10% auto; height: 46vh; z-index: 0;
  background: radial-gradient(58% 50% at 50% 0%, color-mix(in oklab, var(--cy-farbe) 24%, transparent), transparent 72%);
  opacity: var(--cy-auf, 1); pointer-events: none;
}
.cy .cy-held--film { position: relative; }
.cy .cy-held--film > * { position: relative; z-index: 1; }

/* --------------------------------------------------------- Nutzen: Tiefe */

/* Hier stand einmal ein klebender Bildschirm — das Bild bleibt stehen, der
 * Text läuft vorbei. Am Bildschirmfoto war zu sehen, dass es nicht trägt: die
 * Nutzen-Texte sind vier Zeilen lang, da läuft nichts vorbei. Übrig blieben
 * Löcher von einem halben Bildschirm zwischen den Blöcken.
 *
 * Was bleibt, ist die Tiefe ohne die Leere: das Bild geht langsamer als der
 * Text, kippt eine Spur zur Seite und kommt beim Vorbeiziehen näher. Zwei
 * Grad und zwanzig Pixel — man sieht es nicht, man merkt es.
 */
@media (min-width: 861px) {
  .cy.cy-bewegt .cy-nutzen__bild { perspective: var(--cy-tiefe); }
  .cy.cy-bewegt .cy-nutzen__bild img {
    transform: translate3d(0, calc(var(--cy-lauf, 0) * -26px), 0)
               rotateY(calc(var(--cy-seite, 0) * var(--cy-lauf, 0) * -1.4deg))
               scale(calc(1.015 - var(--cy-lauf, 0) * .015));
    transition: none;
  }
  .cy.cy-bewegt .cy-nutzen__bild .cy-handy {
    transform: translate3d(0, calc(var(--cy-lauf, 0) * -52px), 0) scale(1.03);
  }
}

/* ------------------------------------------------------------ Produktkacheln */

.cy.cy-bewegt .cy-produkte__reihe { perspective: var(--cy-tiefe); }
.cy.cy-bewegt .cy-produkt {
  transform-style: preserve-3d;
  transition: transform .5s var(--cy-kurve), box-shadow .5s var(--cy-kurve);
  position: relative;
}
/* Die Neigung muss an .cy-zeigt.cy-da vorbei, das transform:none setzt —
   also eine Klasse mehr. Vor dem Auftritt gilt weiter der Auftritt selbst;
   eine Kachel, die man noch nicht sieht, neigt sich auch nicht. */
.cy.cy-bewegt .cy-produkt.cy-zeigt.cy-da,
.cy.cy-bewegt .cy-produkt:not(.cy-zeigt) {
  transform:
    rotateX(calc(var(--cy-neig-y, 0) * -3.2deg))
    rotateY(calc(var(--cy-neig-x, 0) * 3.2deg))
    translate3d(0, 0, 0);
}
.cy.cy-bewegt .cy-produkt.cy-angefasst { transition-duration: .12s; }
.cy.cy-bewegt .cy-produkt.cy-angefasst .cy-produkt__kopf { transform: translate3d(0, 0, 26px); }
.cy.cy-bewegt .cy-produkt__kopf { transition: transform .5s var(--cy-kurve); }

/* Ein Lichtstreif, der dem Zeiger folgt. Nur wo es einen Zeiger gibt. */
@media (hover: hover) {
  .cy.cy-bewegt .cy-produkt::after {
    content: ""; position: absolute; inset: 0; border-radius: inherit;
    pointer-events: none; opacity: 0; transition: opacity .4s var(--cy-kurve);
    background: radial-gradient(30% 40% at var(--cy-maus-x, 50%) var(--cy-maus-y, 50%),
      color-mix(in oklab, var(--cy-farbe) 26%, transparent), transparent 70%);
    mix-blend-mode: screen;
  }
  .cy.cy-bewegt .cy-produkt.cy-angefasst::after { opacity: 1; }
  .cy--kachel.cy-bewegt .cy-produkt::after { mix-blend-mode: multiply; }
}

/* --------------------------------------------------------------- Schieber */

/* Der Schieber hängt am Rollbalken statt an einer Uhr.
 *
 * Dazu bekommt er eine Bahn: einen hohen Kasten, in dem er festklebt, während
 * man daran vorbeirollt. Ein Bildschirm für die erste Ansicht, für jede
 * weitere 55 % dazu. Die Bahn baut bewegung.js, nicht der Server — ohne
 * Javascript bleibt der Schieber genau der, der er vorher war.
 *
 * Die Folien lagen bisher auf display:none und wurden hart umgeschaltet.
 * Gestapelt in einer Rasterzelle können sie sich überblenden — und die Bühne
 * springt beim Wechsel nicht mehr in der Höhe, weil die längste Bildunter-
 * schrift das Maß vorgibt statt der gerade sichtbaren.
 */
/* Ohne Javascript ist die Bahn ein Kasten ohne eigene Höhe — der Schieber
   steht darin wie vorher. Erst html.cy-js gibt ihr die Länge, und bei
   „Bewegung reduzieren" bleibt sie ebenfalls aus. */
.cy .cy-bahn { position: relative; }

/* Nur auf breiten Bildschirmen.
 *
 * Am Handy trägt die Bahn nicht: der Schieber ist dort höher als das
 * Fenster, das Bild wird oben beschnitten, darunter steht ein halber leerer
 * Bildschirm — und die Seite wächst von 6.000 auf 9.700 Pixel. Wer auf einem
 * Telefon liest, tippt lieber auf die Reiter, als 2.700 Pixel durch einen
 * festgeklebten Kasten zu rollen. */
@media (min-width: 861px) and (prefers-reduced-motion: no-preference) {
  html.cy-js .cy .cy-bahn { height: calc(100svh + (var(--cy-folien, 1) - 1) * 55svh); }
  html.cy-js .cy .cy-bahn__halt { position: sticky; top: 5svh; }

  /* Gestapelt statt umgeschaltet: so können sie sich überblenden, und die
     Bühne springt beim Wechsel nicht mehr in der Höhe, weil die längste
     Bildunterschrift das Maß vorgibt statt der gerade sichtbaren. */
  html.cy-js .cy.cy-bewegt .cy-bahn .cy-schieber { margin-top: 0; padding-top: 3svh; }
  html.cy-js .cy.cy-bewegt .cy-bahn .cy-schieber__buehne { display: grid; }
  html.cy-js .cy.cy-bewegt .cy-bahn .cy-folie {
    display: block; grid-area: 1 / 1;
    opacity: 0; pointer-events: none;
    transform: scale(.986) translate3d(0, 10px, 0);
    transition: opacity .5s var(--cy-kurve), transform .66s var(--cy-kurve-lang);
  }
  html.cy-js .cy.cy-bewegt .cy-bahn .cy-folie.cy-an { opacity: 1; pointer-events: auto; transform: none; }
  /* Damit der ganze Schieber in einen Bildschirm passt — sonst klebt er, und
     man sieht trotzdem nicht alles. */
  html.cy-js .cy.cy-bewegt .cy-bahn .cy-folie img { max-height: 62svh; object-fit: contain; object-position: top; }
  html.cy-js .cy.cy-bewegt .cy-bahn .cy-punkt { transition: color .35s var(--cy-kurve), background-color .35s var(--cy-kurve); }
}

/* ----------------------------------------------------------------- Pakete */

/* Die Karten stellen sich auf. Sehr wenig Winkel — mehr sähe nach Spielerei
   aus, und ein Preis ist keine Spielerei. */
.cy.cy-bewegt .cy-pakete__reihe { perspective: var(--cy-tiefe); }
.cy.cy-bewegt .cy-paket.cy-zeigt { transform: translate3d(0, 26px, 0) rotateX(5deg); transform-origin: 50% 100%; }
.cy.cy-bewegt .cy-paket.cy-zeigt.cy-da { transform: none; }

/* ------------------------------------------------------------ Fortschritt */

/* Hängt im .cy, nicht am body: die Produktfarbe steht dort. */
.cy .cy-fortschritt {
  position: fixed; inset: 0 0 auto; height: 2px; z-index: 60;
  background: var(--cy-farbe, currentColor);
  transform: scaleX(var(--cy-weg, 0)); transform-origin: 0 50%;
  pointer-events: none;
}

/* ---------------------------------------------------------------- Ruhe */

/* „Bewegung reduzieren" schaltet die ganze Schicht ab — nicht abgeschwächt,
   sondern aus. Der Endzustand steht sofort da. */
@media (prefers-reduced-motion: reduce) {
  .cy.cy-bewegt .cy-zeigt,
  .cy.cy-bewegt .cy-wort,
  .cy.cy-bewegt .cy-paket.cy-zeigt {
    opacity: 1 !important; transform: none !important; transition: none !important;
  }
  .cy.cy-bewegt .cy-produkt,
  .cy.cy-bewegt .cy-produkt__kopf,
  html.cy-js .cy.cy-bewegt .cy-bahn .cy-folie,
  .cy.cy-bewegt .cy-nutzen__bild img,
  .cy.cy-bewegt .cy-nutzen__bild .cy-handy { transform: none !important; transition: none !important; }
  .cy--buehne.cy-bewegt .cy-held--film .cy-film,
  .cy--buehne.cy-bewegt .cy-held--film .cy-film__video { transform: none !important; border-radius: 0 !important; filter: none !important; }
  .cy.cy-bewegt .cy-produkt::after { display: none; }
  .cy .cy-fortschritt { display: none; }
}
