/* ============================================================
   LUKON Core — SVG-Fassung (ersetzt die CSS-3D-Version)
   Nur Startseite. Reines Inline-SVG + Web Animations API.
   Keine Library, kein Canvas, kein WebGL, kein Build-Step.

   GEOMETRIE — planare Dimetrie 2:1 (Achsen ±26,57° = arctan 0,5).
   Bewusst KEINE echte Isometrie (30°): die würde die 45°-Signaturfase
   der Marke auf 35,26° verzerren. In der 2:1-Projektion bleibt die
   Grundfläche orthogonal und die Fase exakt 45°.
   Alle Pfade sind gerechnet, nicht geschätzt (Kantenlänge 200×100,
   Körperhöhe 92, Fasenschnitt bei 0,42 der Kantenlänge).

   AUFBAU (Reihenfolge = Zeichenreihenfolge = Verdeckung):
     #lc-shadow    Bodenschatten
     #lc-fills     die drei Körperflächen + Fasenfläche
     #lc-lights    Highlight, Rim-Light (statisch, keine Filter)
     #lc-eyes      Status-Augen in der Fase
     #lc-outlines  Silhouette + Innenkanten, EIGENE Ebene
   Outlines liegen bewusst getrennt über den Fills: aneinanderstoßende
   Flächen erzeugen sonst Hairline-Gaps durch Subpixel-Antialiasing.

   ANIMATION — bewusst 2D-native. Die CSS-3D-Fassung nutzte echte
   Achsdrehungen; die lassen sich in SVG nicht ohne Pfad-Morphing
   nachbauen. Statt sie zu faken, sind die Choreografien neu erfunden:
   Heben, Kippen, Rasten, Stauchen, Auffächern — alles über
   Gruppen-Transforms und opacity, nie über 'd'.
   ============================================================ */

.lc-stage {
  --lc-light: #56c692;     /* Deckfläche */
  --lc-mid:   #2c9468;     /* linke Fläche */
  --lc-dark:  #176a47;     /* rechte Fläche, im Schatten */
  --lc-cont:  #04301f;     /* Kontur */
  --lc-inner: #0f5c40;     /* Fase = Gehäuse für die Status-Augen */
  --lc-eye:   #eaf6ef;
  --lc-signal: #45d894;    /* Status-LED, heller als --green-mid für Leuchtkraft */

  position: fixed;
  inset: 0;
  z-index: 1;              /* über den Bühnen, unter Header (50) und Menü (60) */
  pointer-events: none;
  overflow: hidden;
  display: none;           /* nur breite Desktops, unten eingeschaltet */
}

.lc-holder {
  position: absolute;
  top: 0;
  left: 0;
  width: 200px;
  height: 200px;
  will-change: transform;
  /* Ankerwechsel: ausrollen statt einrasten.
     Vorher 1.05s cubic-bezier(.33,.9,.28,1) — diese Kurve erreicht bei 33%
     der Laufzeit schon 90% des Weges, die Bewegung war also nach ~350ms
     vorbei und kroch danach 700ms unsichtbar aus. Das liest sich als harter
     Anschlag mit anschliessendem Stillstand.
     Neu: gleichmaessiges Gleiten mit langem Ausrollen, kein Overshoot (der
     wirkt verspielt), sondern gedaempfte Schwere.
     Die Kurve wurde in vier Runden gegen zwei Kennzahlen optimiert:
       (a) Spitzen- zu Durchschnittstempo — misst, wie gleichmaessig es laeuft
       (b) Bremshaerte im letzten Drittel — misst, ob es AUSROLLT oder ABWUERGT
     Entscheidend ist (b): Ein Endtempo nahe null allein macht noch kein
     Ausrollen. Auch die VERZOEGERUNG muss zum Schluss hin abnehmen. Faellt
     sie erst spaet und dann stark, liest sich das, als fahre der Koerper in
     zaehe Masse — obwohl das Endtempo rechnerisch sauber gegen null geht.
       0.33,0.9,0.28,1   → Tempo 2.81 / Bremse 4.6  (Ausgangszustand)
       0.32,0.08,0.15,1  → Tempo 2.81 / Bremse 5.1  (Versuch 1)
       0.45,0.3,0.35,1   → Tempo 2.04 / Bremse 4.2  (Versuch 2)
       0.45,0.4,0.5,1    → Tempo 1.62 / Bremse 3.77 (Versuch 3)
       0.25,0.3,0.4,1    → Tempo 1.85 / Bremse 2.35 ← gewaehlt
     Bewusst etwas mehr Tempospitze zugunsten deutlich weicheren Auslaufens:
     die Bremshaerte ganz am Schluss sinkt von 1,61 auf 1,30.

     Dauer 1,4s statt 1,7s: bei fuenf Stationen muss der Cooldown knapp
     ueber der Reisedauer liegen (sonst ueberlappen sich zwei Reisen), und
     bei 1,7s war er mit 1,9s so lang, dass gemessen 2 von 5 Stationen
     verschluckt wurden. 1,4s bleibt deutlich ruhiger als die urspruenglichen
     1,05s und laesst alle fuenf Anker durch. */
  transition: transform 1.4s cubic-bezier(0.25, 0.3, 0.4, 1);
}

.lc-svg {
  width: 100%;
  height: 100%;
  overflow: visible;
  display: block;
}

/* transform-box/-origin MÜSSEN explizit stehen: sonst rotieren SVG-Gruppen
   um den Ursprung des Viewports statt um ihre eigene Mitte, und die
   Bounding Box verschiebt sich während der Animation mit. */
.lc-svg g {
  transform-box: view-box;
  transform-origin: 100px 96px;
}

/* ---------- Flächen ---------- */

#lc-face-top   { fill: var(--lc-light); }
#lc-face-left  { fill: var(--lc-mid); }
#lc-face-right { fill: var(--lc-dark); }
#lc-face-cham  { fill: var(--lc-inner); }

/* Jede Flaeche traegt ihre EIGENE Kontur — nicht nur die Outline-Ebene unten.
   Sonst bleibt beim Auffaechern (Section „Leistungen") ein Drahtgitter stehen,
   waehrend die Farbflaechen wegfliegen. Im Ruhezustand deckt sich dieser
   Stroke exakt mit den Kanten der Outline-Ebene und faellt nicht auf. */
#lc-fills path {
  stroke: var(--lc-cont);
  stroke-width: 4;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
}

/* Statisches Licht statt Filter — feGaussianBlur auf animierten Gruppen
   erzeugt große Offscreen-Bitmaps und kostet Frames. */
#lc-highlight { fill: #ffffff; opacity: .17; }
#lc-rim       { fill: none; stroke: #9fe8c4; stroke-width: 3; opacity: .5; }

/* ---------- Kontur ---------- */
/* non-scaling-stroke: beim Squash würde die Kontur sonst mitgestaucht
   und optisch „pumpen". */
#lc-outlines path {
  fill: none;
  stroke: var(--lc-cont);
  stroke-width: 5;
  stroke-linejoin: round;
  stroke-linecap: round;
  vector-effect: non-scaling-stroke;
}

#lc-edge-inner { stroke-width: 3.5; opacity: .85; }

/* ---------- Augen ---------- */
/* Bewusst Cartoon, nicht Technik: weiße Sklera, farbige Iris, dunkle Pupille,
   versetztes Glanzlicht. Das Glanzlicht ist der eigentliche Cartoon-Marker —
   ohne es wirken auch runde Augen wie Sensoren.
   Kein Mund, keine Brauen: der Ausdruck kommt allein aus Blick und Blinzeln.

   Die Iris behält die Klasse .lc-eye-led und die IDs, weil die
   Choreografien in main.js darauf pulsen (Statuspuls im Hero, Quittieren
   je Rast in „Prozess"). So bleibt die Statusidee erhalten, ohne dass das
   Auge technisch aussehen muss. */

.lc-eye-shell {
  fill: var(--lc-eye);
  stroke: var(--lc-cont);
  stroke-width: 2.5;
  vector-effect: non-scaling-stroke;
}

.lc-eye-led     { fill: var(--lc-signal); transition: fill .4s; }
.lc-eye-pupille { fill: var(--lc-cont); }
.lc-eye-glanz   { fill: #ffffff; }

/* PFLICHT für jedes EINZELNE animierte SVG-Element (nicht nur für Gruppen):
   ohne transform-box bezieht sich transform-origin auf die View-Box, nicht
   auf das Element. Ein scale() auf der Iris (Statuspuls) skaliert dann um
   die Bildmitte 100/100 statt um den eigenen Mittelpunkt — die Iris wandert
   sichtbar aus dem Auge heraus. Mit fill-box ist der Bezug die eigene
   Bounding Box, center also wirklich der Kreismittelpunkt. */
#lc-eyes circle,
#lc-shadow {
  transform-box: fill-box;
  transform-origin: center;
}

/* Blinzeln: die Augen-Gruppe klappt vertikal zusammen — Origin auf
   Augenhöhe (y=94), sonst rutschen die Lider beim Zuklappen nach unten. */
#lc-eyes {
  transform-box: view-box;
  transform-origin: 100px 94px;
  transition: transform .09s ease-out;
}
.lc-stage.lc-blink #lc-eyes { transform: scaleY(.1); }

#lc-shadow { fill: #05442f; opacity: .16; }

/* ============================================================
   Idle-Leben — laufen DAUERHAFT und werden nie neu gestartet.

   Bewusst CSS-Animationen statt WAAPI: die Choreografien in main.js
   brechen bei jedem Stationswechsel ab und starten neu. Eine Ruhe-
   bewegung, die dabei mit-neustartet, springt sichtbar zurück auf
   ihren Anfangswert. Als CSS-Animation auf einer EIGENEN Ebene läuft
   sie ungestört durch — die Choreografie legt sich nur darüber.
   Kein requestAnimationFrame: das läuft compositor-seitig und wird
   vom Browser in Hintergrund-Tabs automatisch gedrosselt.

   Alle Werte sind absichtlich unter der Aufmerksamkeitsschwelle:
   ±0,9° Drehung und 4px Hub über 21s — sichtbar, dass er lebt,
   zu langsam, um vom Text abzulenken. Die Perioden sind teilerfremd
   (21s / 13s / 7,5s), damit sich kein erkennbares Muster einschwingt.
   ============================================================ */

@keyframes lc-drift {
  0%   { transform: rotate(-0.8deg) translateY(0)    scale(1); }
  22%  { transform: rotate(0.3deg)  translateY(-4px) scale(1.005); }
  47%  { transform: rotate(0.9deg)  translateY(-1px) scale(1); }
  71%  { transform: rotate(0.1deg)  translateY(-3px) scale(0.998); }
  100% { transform: rotate(-0.8deg) translateY(0)    scale(1); }
}
#lc-drift { animation: lc-drift 21s ease-in-out infinite; }

/* Der Schatten liegt AUSSERHALB der Drift-Ebene und läuft gegenläufig:
   hebt sich der Core, wird der Schatten kleiner und blasser. */
@keyframes lc-drift-schatten {
  0%, 100% { transform: scale(1);    opacity: .16; }
  22%      { transform: scale(.93);  opacity: .115; }
  71%      { transform: scale(.97);  opacity: .14; }
}
#lc-shadow { animation: lc-drift-schatten 21s ease-in-out infinite; }

/* Lichtwanderung auf der Deckfläche — reine opacity, kein Filter. */
@keyframes lc-schimmer {
  0%, 100% { opacity: .17; }
  50%      { opacity: .27; }
}
#lc-highlight { animation: lc-schimmer 13s ease-in-out infinite; }

/* Signalpuls der Iris: läuft jetzt dauerhaft in JEDER Station, nicht mehr
   nur als Hero-Choreografie. Die zwei Augen sind gegeneinander versetzt,
   damit es atmet statt zu blinken. */
@keyframes lc-signal {
  0%, 100% { opacity: 1; }
  50%      { opacity: .55; }
}
#lc-led-l { animation: lc-signal 7.5s ease-in-out infinite; }
#lc-led-r { animation: lc-signal 7.5s ease-in-out infinite -2.4s; }

/* ============================================================
   Anker — Position, Größe und Ruhe-Neigung je Section.

   BEZUGSPUNKT IST DIE CONTAINER-KANTE, NICHT DER VIEWPORT-RAND.
   Der Inhalt liegt in einem festen 1140px-Container, seine Kanten
   stehen also bei 50vw ± 570px. Ein Anker, der am Viewportrand
   klebt (100vw - x), wandert bei breiteren Schirmen immer weiter
   vom Inhalt weg; einer, der an 50vw ± 570px hängt, behält seinen
   Abstand zum Text und rückt automatisch mit nach außen.

   Die X-Werte sind ausgerechnet, nicht geschätzt. Herleitung
   (Holder ist 200px breit, transform-origin liegt in seiner Mitte,
   die Skalierung wirkt also symmetrisch um X+100):
     rechts:  X = 50vw + 570 + abstand - 100 + 100·scale
     links:   X = 50vw - 570 - abstand - 100 - 100·scale
   Mit abstand = 24px ergibt das die Konstanten unten.

   Die Skalierungen sind durch die verfügbare Seitenluft gedeckelt:
   bei 1440px bleiben nur 143px links / 157px rechts neben dem
   Container. Mehr als scale(.55) passt dort nicht, ohne dass der
   Core über die Textkante ragt — und weil die Bühne fixed mit
   z-index 1 liegt, läge er dann ÜBER dem Text, nicht dahinter.
   ============================================================ */

/* Drei Anker: oben rechts (Hero) → links auf halber Höhe (Mitte) →
   rechts unten (über dem Footer). Die Seiten wechseln bewusst, damit jede
   Reise ein sichtbarer Weg ist und nicht ein Verrutschen. */
.lc-stage[data-anchor="hero"] .lc-holder {
  transform: translate(calc(50vw + 549px), var(--lc-y-hero, 26vh)) scale(.55) rotate(0deg);
}
.lc-stage[data-anchor="mitte"] .lc-holder {
  transform: translate(calc(50vw - 762px), 40vh) scale(.5) rotate(-5deg);
}
.lc-stage[data-anchor="unten"] .lc-holder {
  transform: translate(calc(50vw + 551px), 56vh) scale(.55) rotate(3deg);
}

/* Ab 1760px ist links und rechts je ≥310px Luft — dort darf der Core
   wieder auf seine ursprüngliche Größe wachsen, ohne den Text zu
   berühren. Abstand hier 32px, dieselbe Formel wie oben. */
@media (min-width: 1760px) {
  .lc-stage[data-anchor="hero"] .lc-holder {
    transform: translate(calc(50vw + 597px), var(--lc-y-hero, 26vh)) scale(.95) rotate(0deg);
  }
  .lc-stage[data-anchor="mitte"] .lc-holder {
    transform: translate(calc(50vw - 796px), 40vh) scale(.8) rotate(-5deg);
  }
  .lc-stage[data-anchor="unten"] .lc-holder {
    transform: translate(calc(50vw + 592px), 56vh) scale(.9) rotate(3deg);
  }
}

/* Stimmung der Status-LED je Anker — grün läuft, Gold während der Arbeit */
.lc-stage[data-anchor="mitte"] { --lc-signal: #e8bb5c; }

/* ---------- Nur breite Desktops ----------
   Der Inhalt liegt im festen 1140px-Container, die Seitenluft ist also
   (100vw - 1140px) / 2. Gemessen bleiben davon nach Abzug des Core:
     1440px →  nur 14–23px bis zum Bildschirmrand (klebt am Rand)
     1600px →  ~95px bis zum Rand, ~30px zum Inhalt  ← so soll es sein
   Deshalb liegt die Schwelle bei 1600px und nicht mehr bei 1440px.
   Der Core ist reine Deko — ihn auszublenden kostet keinen Inhalt,
   ihn an den Rand zu quetschen dagegen die Ruhe im Layout. */
@media (min-width: 1600px) {
  .lc-stage { display: block; }
}

/* ---------- Auftritt nach der Boot-Sequenz ----------
   Der Core wartet hinter der Hero-Unterkante — nur sein Gesicht ragt darueber —
   und schwebt eine Sekunde spaeter auf den Hero-Anker.

   Warum ueber die Variable --lc-y-hero und nicht als eigene Anker-Station:
   so bleibt data-anchor="hero" die ganze Zeit gesetzt. An diesem Attribut
   haengen in main.js das Blinzelmuster, die LED-Farbe und die Choreografie;
   eine vierte Station haette alle drei Stellen mitziehen muessen. Und die
   Anker-Koordinaten stehen weiter an genau einer Stelle je Media-Query.

   Warum clip-path auf der BUEHNE und nicht z-index:
   Die Buehne liegt bewusst auf z-index 1 ueber dem Inhalt (siehe oben), daran
   wird nichts geaendert. Ein verdeckendes Element gibt es an der Stelle auch
   nicht — gemessen reicht der dunkle Trust-Block nur bis x=1458, der Core
   steht bei x=1433-1545 also rechts daneben. Die Hero-Unterkante dagegen laeuft
   ueber die volle Breite: dort ist der zarte Tonwechsel vom Hero-Gruen zu
   Weiss, und genau daran wird beschnitten.

   --lc-kante setzt main.js aus der gemessenen Hero-Unterkante. Der Fallback
   562px ist der gemessene Wert bei 1680x950; die Hero hat eine feste Hoehe von
   486px, die Kante wandert also nicht mit der Fensterhoehe. */
.lc-stage[data-intro] {
  clip-path: inset(0 0 calc(100% - var(--lc-kante, 562px)) 0);
}

/* Waehrend des Wartens KEINE Transition: die Kante wird nachgemessen, sobald
   die Schriften stehen (mit der Fallback-Schrift ist die Hero gemessene 31px
   kuerzer). Ohne diese Regel wuerde jede Korrektur der Variable eine 1,4s
   lange Rutschbewegung ausloesen — der Core saesse dann beim Overlay-Abgang
   noch auf der falschen Hoehe und wanderte sichtbar nach unten.
   Er ist in dieser Phase hinter dem Boot-Overlay, ein harter Sprung ist dort
   also genau richtig. */
.lc-stage[data-intro="warten"] .lc-holder { transition: none; }

/* Warteposition. 106px unter der Kante: der Holder ist 200px hoch und wird um
   seine Mitte skaliert, die Augen sitzen im ViewBox bei cy=94 mit Radius 12.
   Daraus folgt fuer die Unterkante der Augen  y = ty + 100 + 6*scale  — der
   scale-Anteil sind bei 0.55 nur 3px, die Formel ist also praktisch
   groessenunabhaengig und gilt fuer beide Media-Staende. */
.lc-stage[data-intro="warten"],
.lc-stage[data-intro="bereit"] {
  --lc-y-hero: calc(var(--lc-kante, 562px) - 106px);
}

/* ---------- Reduzierte Bewegung ----------
   Kein Ankerwechsel, kein Idle-Drift, kein Schimmern, kein Signalpuls,
   kein Blinzeln — der Core steht still am Hero-Anker. Der Selektor fasst
   bewusst ALLE Ebenen: Holder (Anker), sämtliche SVG-Gruppen (Drift und
   Choreografie) und die Einzelelemente mit Dauer-Animation. Als Webagentur
   ist das Pflicht, nicht Kür. */
@media (prefers-reduced-motion: reduce) {
  .lc-holder, .lc-svg g, #lc-eyes, #lc-drift, #lc-lehnen,
  #lc-shadow, #lc-highlight, #lc-led-l, #lc-led-r {
    transition: none !important;
    animation: none !important;
  }
  .lc-stage[data-anchor] .lc-holder {
    transform: translate(calc(50vw + 549px), 26vh) scale(.55);
  }
}
