diff --git a/POST-6.md b/POST-6.md
index d39a64d..7da585f 100644
--- a/POST-6.md
+++ b/POST-6.md
@@ -638,15 +638,72 @@ das Projekt bestätigt sie. Das ist die Funktion, die die Website meint mit
| Zeit | Was passiert |
|---|---|
-| 0,0 – 0,6 s | Ruhe. Der Verlauf steht: Sandra, Maike, Tobias |
-| 0,6 – 1,3 s | Der Zeiger fährt auf Tobias' Nachricht, der Pfeil erscheint an ihr |
+| 0,0 – 0,2 s | Ruhe. Der Verlauf steht: Sandra, Maike, Tobias |
+| 0,2 – 1,1 s | Der Zeiger fährt auf Tobias' Nachricht, der Pfeil erscheint an ihr |
| 1,3 – 1,6 s | Klick |
-| 1,6 – 2,0 s | Das Menü schnappt nach oben auf: Reagieren, Antworten, Im Thread antworten, Anpinnen, Aufgabe erstellen, Bearbeiten, Löschen |
+| 1,5 – 2,0 s | Das Menü schnappt nach oben auf: Reagieren, Antworten, Im Thread antworten, Anpinnen, Aufgabe erstellen, Bearbeiten, Löschen |
| 2,4 – 3,4 s | Der Zeiger geht auf „Aufgabe erstellen", die Zeile hebt sich, Klick |
| 3,6 – 4,8 s | Das Menü schließt, die Aufgabenkarte klappt in Tobias' Nachricht auf, der Verlauf rutscht nach |
| 4,8 – 5,4 s | Die Systemzeile „Aufgabe „Materialliste prüfen" im Projekt erstellt" erscheint |
| 5,4 – 6,0 s | Halt auf dem Ergebnis |
+### Die Kurven sind die von GSAP, die Bibliothek ist es nicht
+
+Die Website macht ihre Bewegungen mit **GSAP** (`gsap@3.14.2`, Standard-Lizenz;
+`HeroSection`, `Navbar`, `HoneycombSection`, `FAQSection` und weitere). Die
+Frage lag also nahe, es hier auch zu tun. Die Antwort ist: **die Kurven ja, die
+Bibliothek nein.**
+
+Was GSAP über eine Kurve hinaus kann — Zeitleisten, ScrollTrigger,
+MotionPathPlugin —, setzt voraus, dass etwas *läuft*. Hier läuft nichts:
+`animChat(i, t)` bekommt seinen Fortschritt von außen und zeichnet daraus den
+Stand. Die Funktion **ist** schon die Zeitleiste, und `animation.mjs` sampelt
+sie Bild für Bild. Ein `gsap.timeline({paused: true})` mit `.progress(t)` wäre
+genau dieselbe Konstruktion, nur mit 70 KB darunter — und das Repo ist autark,
+jede Datei in `vendor/` liegt dort, weil sie etwas kann, das man nicht in fünf
+Zeilen schreibt (DOM nach Canvas, ZIP). Ein Easing ist eine Zeile.
+
+Dazu kommt: **zwei der Kurven waren längst GSAPs.** `daempfen` ist Wort für
+Wort `power2.inOut`, `rueck` ist `back.out(1.70158)`. Die Datei sprach die
+Sprache schon, sie sagte es nur nicht. Jetzt stehen die Namen daneben, und der
+Satz ist vollständig:
+
+| in der Datei | GSAP | wofür |
+|---|---|---|
+| `daempfen` | `power2.inOut` | Wege mit Anfang und Ende: das Wandern zur Menüzeile, das Aufklappen der Karte |
+| `rueck` | `back.out(1.7)` | das Menü, das aufschnappt und einmal leicht überschwingt |
+| `raus` | `power2.out` | alles, was ankommt und liegen bleibt: der Zeiger, die Systemzeile |
+| `knall` | `expo.out` | der Klickring |
+
+**Der Zeiger fährt jetzt wie eine Hand und nicht wie ein Schlitten.** Er lag
+auf `power2.inOut` — langsam an, in der Mitte schnell, wieder abbremsend. So
+bewegt sich ein Schlitten auf einer Schiene. Eine Hand ist sofort schnell und
+wird zum Ziel hin langsam, also `power2.out`.
+
+**Und er fährt einen Bogen.** Auf der Geraden zwischen Start und Ziel liegt kein
+Zeiger, den je ein Mensch geführt hat. Der Stützpunkt einer quadratischen
+Bézierkurve sitzt quer zur Strecke, 13 % ihrer Länge nach außen — vom Verlauf
+weg, damit der Zeiger nicht über die Blasen streicht. Das sind rund 27 px
+Ausbuchtung auf 410 px Weg; es fällt nicht auf, und genau das ist der Punkt.
+Bei `p = 1` liegt die Bahn exakt auf dem Ziel, das anschließende Wandern zur
+Menüzeile setzt also sauber daran an.
+
+**Der Klickring geht auf zwei Kurven.** Der Radius auf `expo.out`, also fast
+sofort draußen, die Deckung linear hinterher. Beides auf derselben Kurve sah
+aus wie eine Blase, die sich aufbläst — ein Klick ist ein Stoß und kein
+Aufpumpen.
+
+**Der Anlauf ist von 0,6 s auf 0,18 s geschrumpft.** Am Ende steht das Bild
+eine halbe Sekunde still, damit man das Ergebnis liest. Lief vorne noch einmal
+eine halbe Sekunde nichts, waren das über den Schleifenstoß hinweg 1,2 von
+6 Sekunden Stillstand am Stück, und die Schleife sah aus, als hänge sie. Der
+Halt am Ende bleibt, der am Anfang ist auf ein Achtel geschrumpft.
+
+> **Nachgeprüft ist das an Einzelbildern, nicht am Lauf.** Kontaktabzüge über
+> die 180 Bilder und eine Nahaufnahme des Klickrings zeigen, was die Kurven
+> rechnen. Ob die Bewegung *läuft*, sieht man erst im Abspielen — dieser eine
+> Schritt steht noch aus.
+
### Warum Tobias' Nachricht
Nicht irgendeine: die Aufgabenkarte aus der Quelle trägt **„Tobias Wagner ·
diff --git a/animation/post6-animChat.mp4 b/animation/post6-animChat.mp4
index 24096eb..eb78763 100644
Binary files a/animation/post6-animChat.mp4 and b/animation/post6-animChat.mp4 differ
diff --git a/post6.html b/post6.html
index 6e338df..afe393f 100644
--- a/post6.html
+++ b/post6.html
@@ -3537,8 +3537,12 @@ if (location.search.indexOf("nur=anim") >= 0)
'';
+ /* Der Ring geht auf einer anderen Kurve als er verblasst: der Radius mit
+ knall, also fast sofort draussen, die Deckung linear hinterher. Beides auf
+ derselben Kurve sah aus wie eine Blase, die sich aufblaest -- ein Klick
+ ist ein Stoss und kein Aufpumpen. */
const klickRing = (x, y, p) => p <= 0 || p >= 1 ? "" :
- '';
@@ -3577,20 +3581,29 @@ if (location.search.indexOf("nur=anim") >= 0)
const innenB = B - 2 * RAND;
const bahnO = KOPF + 8, bahnU = H - FELD - 8;
- const zeigerAn = stufe(t, .10, .22);
- const pfeil = daempfen(stufe(t, .16, .24)); // der Pfeil an der Blase
- const klick1 = stufe(t, .22, .27);
+ /* Der Zeiger faehrt bei 0,03 los und nicht mehr bei 0,10. Am Ende steht
+ das Bild eine halbe Sekunde still, damit man das Ergebnis liest -- lief
+ vorn nochmal eine halbe Sekunde nichts, waren das ueber den
+ Schleifenstoss hinweg 1,2 von 6 Sekunden Stillstand am Stueck, und die
+ Schleife sah aus, als haenge sie. Der Halt am Ende bleibt, der am
+ Anfang ist auf ein Achtel geschrumpft. */
+ const zeigerAn = stufe(t, .03, .19);
+ const pfeil = daempfen(stufe(t, .13, .21)); // der Pfeil an der Blase
+ const klick1 = stufe(t, .21, .26);
/* rueck statt daempfen, und kuerzer: gedaempft war die Deckung nach
fuenf Bildern fertig, waehrend die Skalierung noch eine halbe Sekunde
von 0,96 auf 1,00 weiterkroch. Sichtbar war davon fast nichts, zu
spueren war es als Haenger. Jetzt schnappt es in einer Drittelsekunde
auf, schwingt einmal ganz leicht ueber und steht. */
- const auf = rueck(stufe(t, .26, .34));
+ const auf = rueck(stufe(t, .25, .33));
const wandern = daempfen(stufe(t, .40, .54));
const klick2 = stufe(t, .56, .61);
const zu = daempfen(stufe(t, .60, .66));
const klappen = daempfen(stufe(t, .62, .80)); // die Aufgabe klappt auf
- const system = daempfen(stufe(t, .80, .90));
+ /* raus statt daempfen: die Zeile kommt von unten herein und bleibt
+ liegen. Eine Kurve, die auch langsam anfaengt, laesst sie zaeh
+ aussehen -- sie soll ankommen, nicht anfahren. */
+ const system = raus(stufe(t, .80, .90));
const menueAn = Math.max(0, auf - zu);
let g = "";
@@ -3674,9 +3687,25 @@ if (location.search.indexOf("nur=anim") >= 0)
const zAn = zeigerAn * (1 - zWeg);
if (zAn > .01) {
const vonX = B - 60, vonY = H + 40;
- const p1 = daempfen(zeigerAn);
- let zx = vonX + (chevX - 2 - vonX) * p1;
- let zy = vonY + (chevY - 2 - vonY) * p1;
+ const zuX = chevX - 2, zuY = chevY - 2;
+ /* raus statt daempfen. Gedaempft faehrt der Zeiger langsam an, wird in
+ der Mitte schnell und bremst wieder ab -- das ist die Bewegung eines
+ Schlittens und nicht die einer Hand. Eine Hand ist sofort schnell und
+ wird zum Ziel hin langsam. */
+ const p1 = raus(zeigerAn);
+ /* Und sie faehrt einen Bogen. Auf der Geraden zwischen Start und Ziel
+ liegt kein Zeiger, den je ein Mensch gefuehrt hat; das faellt nicht
+ als Fehler auf, aber die Bewegung wirkt gestellt. Der Stuetzpunkt
+ sitzt quer zur Strecke, um ein Zehntel ihrer Laenge nach aussen --
+ weg vom Verlauf, damit der Zeiger nicht ueber die Blasen streicht.
+ Bei p1 = 1 liegt die Bahn exakt auf dem Ziel, das anschliessende
+ Wandern zur Menuezeile setzt also sauber daran an. */
+ const bx = zuX - vonX, by = zuY - vonY, BOGEN = .13;
+ const sx = (vonX + zuX) / 2 - by * BOGEN;
+ const sy = (vonY + zuY) / 2 + bx * BOGEN;
+ const u = 1 - p1;
+ let zx = u * u * vonX + 2 * u * p1 * sx + p1 * p1 * zuX;
+ let zy = u * u * vonY + 2 * u * p1 * sy + p1 * p1 * zuY;
if (wandern > 0) {
zx += (m.zielX - zx) * wandern;
zy += (m.zielY - 4 - zy) * wandern;
@@ -3707,10 +3736,29 @@ if (location.search.indexOf("nur=anim") >= 0)
/* Ein paar Verlaeufe. Linear sieht nach Maschine aus, deshalb sind Ein-
und Ausgang gedaempft. `stufe` blendet einen Abschnitt zwischen zwei
Zeitpunkten ein und liefert 0 davor und 1 danach. */
- const daempfen = x => x <= 0 ? 0 : x >= 1 ? 1 : x < .5
+ /* Die Kurven sind die von GSAP, mit dem die Website ihre Bewegungen macht --
+ als Formel und nicht als Bibliothek. Ein Verlauf ist eine Zeile Rechnung;
+ was GSAP darueber hinaus koennte (Zeitleisten, Motion-Path, ScrollTrigger),
+ braucht hier nichts: die Zeichenfunktion bekommt ihr t von aussen und ist
+ damit selbst schon die Zeitleiste. Die Namen stehen daneben, damit
+ nachvollziehbar bleibt, welche Kurve gemeint ist.
+
+ daempfen und rueck standen vorher unbenannt hier und sind Wort fuer Wort
+ GSAPs power2.inOut und back.out(1,70158) -- die Datei sprach die Sprache
+ also schon, sie sagte es nur nicht. */
+ const daempfen = x => x <= 0 ? 0 : x >= 1 ? 1 : x < .5 // power2.inOut
? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2;
- const rueck = x => x <= 0 ? 0 : x >= 1 ? 1
+ const rueck = x => x <= 0 ? 0 : x >= 1 ? 1 // back.out(1.7)
: 1 + 2.7 * Math.pow(x - 1, 3) + 1.7 * Math.pow(x - 1, 2);
+ /* Schnell los, lang aus. Alles, was ankommt und liegen bleibt -- ein Zeiger,
+ der ins Bild faehrt, eine Zeile, die einlaeuft -- gehoert hierher und
+ nicht auf eine Kurve, die auch langsam anfaengt. */
+ const raus = x => x <= 0 ? 0 : x >= 1 ? 1 // power2.out
+ : 1 - Math.pow(1 - x, 3);
+ /* Noch schaerfer: schnappt heraus und ist praktisch sofort fertig. Fuer den
+ Klickring, der einem Fingertipp folgt. */
+ const knall = x => x <= 0 ? 0 : x >= 1 ? 1 // expo.out
+ : 1 - Math.pow(2, -10 * x);
const stufe = (t, von, bis) => t <= von ? 0 : t >= bis ? 1 : (t - von) / (bis - von);
const VIS = {