/* ==========================================================================
   Animationen für die Produkt-Mockups
   --------------------------------------------------------------------------
   Sicherheitsprinzip: Alles ist standardmäßig SICHTBAR.
   Versteckt wird nur, wenn JavaScript die Klasse .anim-ready gesetzt hat –
   und das tut es nur, wenn der Nutzer keine reduzierte Bewegung eingestellt
   hat. Ohne JS oder mit „Bewegung reduzieren" bleibt die Seite vollständig
   lesbar, es passiert lediglich keine Animation.
   ========================================================================== */

@keyframes pfScan{
  0%{opacity:0;transform:translateY(-40px)}
  12%{opacity:1}
  85%{opacity:1}
  100%{opacity:0;transform:translateY(330px)}
}
/* Erst leuchtet die Stelle blau auf – dieselbe Farbe wie das Ladezeichen
   rechts. Dann setzt sie sich auf die ruhige grüne Tönung. */
@keyframes pfHl{
  0%{background:rgba(228,238,252,0);box-shadow:inset 0 0 0 1.5px rgba(31,99,210,0)}
  8%{background:#dcE8fb;box-shadow:inset 0 0 0 2px #1f63d2}
  62%{background:#dcE8fb;box-shadow:inset 0 0 0 2px #1f63d2}
  100%{background:var(--tint-2);box-shadow:inset 0 0 0 1.5px var(--tint-line)}
}
@keyframes pfBadge{
  0%{opacity:0;transform:translateY(-50%) scale(.4)}
  60%{opacity:1;transform:translateY(-50%) scale(1.18)}
  100%{opacity:1;transform:translateY(-50%) scale(1)}
}
@keyframes pfBadgeTop{
  0%{opacity:0;transform:scale(.4)}
  60%{opacity:1;transform:scale(1.18)}
  100%{opacity:1;transform:scale(1)}
}
@keyframes pfRow{from{opacity:0;transform:translateY(7px)}to{opacity:1;transform:none}}
@keyframes pfPop{
  0%{opacity:0;transform:scale(.94)}
  70%{opacity:1;transform:scale(1.03)}
  100%{opacity:1;transform:scale(1)}
}
@keyframes pfPress{0%,100%{transform:scale(1)}45%{transform:scale(.965)}}

/* --- Scan-Effekt im Hero-Handy -------------------------------------------
   Ein Durchlauf dauert 3,6 s. Die Beträge wechseln über drei Durchläufe
   hinweg (10,8 s), damit der Hero nicht immer denselben Beleg zeigt.     */
.scanfx{position:relative;overflow:hidden}
.scanfx::after{
  content:"";position:absolute;left:0;right:0;top:0;height:38%;pointer-events:none;z-index:2;
  background:linear-gradient(180deg,rgba(196,240,74,0),rgba(196,240,74,.55),rgba(196,240,74,0));
  animation:pfScanLoop 3.6s cubic-bezier(.4,0,.5,1) infinite;
}
@keyframes pfScanLoop{
  0%{transform:translateY(-50%);opacity:0}
  5%{opacity:1}
  38%{opacity:1}
  46%,100%{transform:translateY(280%);opacity:0}
}

/* Erkannte Zeilen erscheinen im Takt des Scans */
.rvi{opacity:0;animation:pfItem 3.6s ease-in-out infinite;animation-delay:var(--d,0s)}
@keyframes pfItem{
  0%,6%{opacity:0;transform:translateY(5px)}
  16%,86%{opacity:1;transform:none}
  94%,100%{opacity:0;transform:translateY(5px)}
}

/* Wechselnde Werte: drei Varianten teilen sich einen 10,8-s-Zyklus */
.cyc{position:relative;display:inline-block;text-align:right;vertical-align:bottom}
.cyc>span{position:absolute;right:0;top:0;white-space:nowrap;opacity:0;animation:pfCyc 10.8s steps(1,end) infinite}
.cyc>span:first-child{position:relative}
.cyc>span:nth-child(1){animation-delay:0s}
.cyc>span:nth-child(2){animation-delay:3.6s}
.cyc>span:nth-child(3){animation-delay:7.2s}
@keyframes pfCyc{0%,33.33%{opacity:1}33.34%,100%{opacity:0}}

/* Der Punkt in der Kopfzeile pulsiert im selben Takt */
.phone-h .dot{animation:pfPulse 3.6s ease-in-out infinite}
@keyframes pfPulse{0%,100%{opacity:.3}18%{opacity:1}55%{opacity:.55}}

/* --- Scanlinie über dem Beleg -------------------------------------------- */
.scanline{
  position:absolute;left:0;right:0;top:0;height:38px;opacity:0;pointer-events:none;border-radius:14px;
  background:linear-gradient(180deg,rgba(196,240,74,0),rgba(196,240,74,.5),rgba(196,240,74,0));
}
/* Drei Durchläufe, bevor der erste Marker gesetzt wird. */
.anim-ready .doc.play .scanline{animation:pfScan .72s ease-in-out .2s 3 forwards}

/* --- Beleg: Felder leuchten nacheinander auf ---------------------------- */
.anim-ready .doc .drow.hl{background:rgba(241,247,230,0);box-shadow:none}
.anim-ready .doc .bn{opacity:0}
.anim-ready .doc.play .drow.hl{animation:pfHl 2s ease forwards;animation-delay:var(--d,1s)}
/* Auch der Kopf des Belegs leuchtet auf – sonst hätte Schritt 1 links
   kein Signal und die Reihenfolge wäre dort nicht ablesbar. */
.doc-top{border-radius:6px}
.anim-ready .doc.play .doc-top{animation:pfHl 2s ease forwards;animation-delay:var(--d,0s)}
.anim-ready .doc.play .drow .bn{animation:pfBadge .45s cubic-bezier(.2,.9,.3,1.4) forwards;animation-delay:var(--d,1s)}
.anim-ready .doc.play .doc-top .bn{animation:pfBadgeTop .45s cubic-bezier(.2,.9,.3,1.4) var(--d,.55s) forwards}
/* Ein Ring läuft einmal nach außen – das ist das „Einkreisen". */
.anim-ready .doc.play .bn::after{
  content:"";position:absolute;inset:-6px;border-radius:50%;
  border:2px solid #1f63d2;opacity:0;
  animation:pfRingPop .9s ease var(--d,0s) forwards;
}
@keyframes pfRingPop{
  0%{opacity:0;transform:scale(.45)}
  35%{opacity:.85}
  100%{opacity:0;transform:scale(1.55)}
}

/* --- Ergebnis-Panel: Zeile für Zeile ------------------------------------ */
.anim-ready .erk .erk-r,
.anim-ready .erk .erk-done,
.anim-ready .erk .erk-note{opacity:0}
.anim-ready .erk.play .erk-r{animation:pfRow .45s ease forwards;animation-delay:var(--d,0s)}
.anim-ready .erk.play .erk-done{animation:pfPop .5s cubic-bezier(.2,.9,.3,1.3) 1.35s forwards}
.anim-ready .erk.play .erk-note{animation:pfRow .4s ease 1.7s forwards}

/* --- Formular: ausfüllen und absenden ----------------------------------- */
.anim-ready .fmock .ff,
.anim-ready .fmock .fmock-btn,
.anim-ready .fmock .fmock-note{opacity:0}
.anim-ready .fmock.play .ff{animation:pfRow .45s ease forwards;animation-delay:var(--d,0s)}
.anim-ready .fmock.play .fmock-btn{
  animation:pfPop .45s ease 1.25s forwards, pfPress .45s ease 1.85s;
}
.anim-ready .fmock.play .fmock-note{animation:pfRow .4s ease 2.15s forwards}

/* --- Sicherheitsnetz ------------------------------------------------------
   Falls eine Animation aus irgendeinem Grund nicht startet, macht diese
   Regel nach 6 Sekunden alles wieder sichtbar.                             */
@keyframes pfFailsafe{to{opacity:1}}
.anim-ready .doc .bn,
.anim-ready .erk .erk-r,
.anim-ready .erk .erk-done,
.anim-ready .erk .erk-note,
.anim-ready .fmock .ff,
.anim-ready .fmock .fmock-btn,
.anim-ready .fmock .fmock-note{animation:pfFailsafe .1s linear 6s forwards}


/* --- Legende: Titel steht, Erklärung lädt nach --------------------------
   Ohne JS bleibt alles sichtbar: die Ladezeile ist dann unsichtbar und
   die Erklärung steht direkt da.                                        */
@keyframes pfSpin{to{transform:rotate(360deg)}}
@keyframes pfFadeOut{to{opacity:0}}

.anim-ready .legend .lgi .ld{opacity:0}
.anim-ready .legend .lgi .lload{opacity:1}
.anim-ready .legend.play .lgi .ld{animation:pfRow .38s ease forwards;animation-delay:var(--d,0s)}
/* Blinken und Ausblenden liegen auf verschiedenen Elementen – zwei
   Animationen auf derselben Opazität blieben sonst sichtbar stehen. */
.anim-ready .legend.play .lgi .lspin svg{animation:pfSpin 1.4s linear infinite}
.anim-ready .legend.play .lgi .lspin,
.anim-ready .legend.play .lgi .ltxt{animation:pfBlink 1.4s ease-in-out infinite}
/* Das Blau blendet erst aus, wenn der Text schon einfährt – vorher klaffte
   dazwischen ein leerer Moment. Die beiden überblenden sich jetzt. */
.anim-ready .legend.play .lgi .lload{animation:pfFadeOut .35s ease calc(var(--d,0s) + .3s) forwards}
@keyframes pfBlink{0%,100%{opacity:1}50%{opacity:.4}}

/* Sicherheitsnetz: nach 7 Sekunden ist alles lesbar. */
.anim-ready .legend .lgi .ld{animation:pfFailsafe .1s linear 20s forwards}

.anim-ready .legend .lgi .lload{animation:pfFadeOut .1s linear 20s forwards}

/* ==========================================================================
   Verordnungs-Tracker – Bewegung
   ========================================================================== */
/* Der Ring füllt sich einmal auf seinen Stand */
@keyframes vrFill{from{stroke-dashoffset:352}to{stroke-dashoffset:var(--off,117)}}
.anim-ready .vring .val{stroke-dashoffset:352}
.anim-ready .vring.play .val{animation:vrFill 1.6s cubic-bezier(.3,.8,.3,1) .25s forwards}

/* Balken in den Verordnungskarten wachsen nacheinander */
@keyframes vbGrow{from{width:0}to{width:var(--w,50%)}}
.anim-ready .vok-bar i{width:0}
.anim-ready .vokarte.play .vok-bar i{animation:vbGrow 1.1s cubic-bezier(.3,.8,.3,1) forwards;animation-delay:var(--d,0s)}

/* Termine fahren von unten ein, einer nach dem anderen */
@keyframes vtIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.anim-ready .tlist .trow{opacity:1}

/* Der Zähler springt beim Abzug kurz zusammen */
@keyframes vtTick{0%,100%{transform:scale(1)}40%{transform:scale(.82);opacity:.5}}

/* Der Warnhinweis pulst zweimal, dann bleibt er ruhig stehen */
@keyframes vwPulse{0%,100%{box-shadow:0 0 0 0 rgba(201,146,47,0)}45%{box-shadow:0 0 0 7px rgba(201,146,47,.18)}}
.anim-ready .vnote.pulse{animation:vwPulse 1.5s ease 1.2s 2}

/* Zahlen zählen sich selbst herunter – rein visuell über drei Zustände */
.cnt{position:relative;display:inline-block;text-align:right;vertical-align:bottom}
.cnt>span{position:absolute;right:0;top:0;opacity:0;animation:cntStep 5.4s steps(1,end) infinite}
.cnt>span:first-child{position:relative}
.cnt>span:nth-child(2){animation-delay:1.8s}
.cnt>span:nth-child(3){animation-delay:3.6s}
@keyframes cntStep{0%,33.33%{opacity:1}33.34%,100%{opacity:0}}

/* Sicherheitsnetz für den Tracker: Startet eine Animation nicht, stehen
   Ring, Balken und Termine nach sechs Sekunden trotzdem auf Endwert. */
.anim-ready .vring .val{animation:vrFill .1s linear 6s forwards}
.anim-ready .vok-bar i{animation:vbGrow .1s linear 6s forwards}

/* ==========================================================================
   Ausgangsrechnungen – Bewegung
   ========================================================================== */
/* Positionen fahren nacheinander ein */
@keyframes ivRow{from{opacity:0;transform:translateY(9px)}to{opacity:1;transform:none}}
.anim-ready .hono .hono-r,.anim-ready .hono .emp,.anim-ready .hono .hono-tot{opacity:0}
.anim-ready .hono.play .hono-r,
.anim-ready .hono.play .emp{animation:ivRow .45s cubic-bezier(.2,.8,.3,1) forwards;animation-delay:var(--d,0s)}
/* Die Summe kommt zuletzt und mit Nachdruck */
@keyframes ivTotal{0%{opacity:0;transform:scale(.92)}65%{opacity:1;transform:scale(1.04)}100%{opacity:1;transform:scale(1)}}
.anim-ready .hono.play .hono-tot{animation:ivTotal .55s cubic-bezier(.2,.9,.3,1.3) forwards;animation-delay:var(--d,1.2s)}

/* Das Schild „Empfänger ≠ Patient" springt auf */
@keyframes ivBadge{0%{opacity:0;transform:scale(.4) rotate(-8deg)}60%{opacity:1;transform:scale(1.14) rotate(2deg)}100%{opacity:1;transform:scale(1) rotate(0)}}
.anim-ready .empbadge{opacity:0}
.anim-ready .hono.play .empbadge{animation:ivBadge .5s cubic-bezier(.2,.9,.3,1.5) forwards;animation-delay:var(--db,1.1s)}
/* Der hervorgehobene Kasten bekommt kurz einen Ring */
@keyframes ivRing{0%{box-shadow:0 0 0 0 rgba(12,42,24,.35)}70%{box-shadow:0 0 0 9px rgba(12,42,24,0)}100%{box-shadow:0 0 0 0 rgba(12,42,24,0)}}
.anim-ready .hono.play .empbox.hl{animation:ivRing 1s ease forwards;animation-delay:var(--db,1.1s)}

/* Statuskette füllt sich und die Punkte springen an */
@keyframes pipeFill{from{width:0}to{width:100%}}
@keyframes pipeOn{0%{transform:scale(1)}45%{transform:scale(1.22)}100%{transform:scale(1)}}
@keyframes pipeSkin{to{background:var(--green-ink);border-color:var(--green-ink);color:var(--lime)}}
.anim-ready .pipe .pd{background:#fff;border-color:var(--line);color:#b4bbaf}
.anim-ready .pipe .pl i{width:0}
.anim-ready .pipe.play .pl i{animation:pipeFill 2.2s cubic-bezier(.4,0,.3,1) .4s forwards}
.anim-ready .pipe.play .pd{animation:pipeSkin .01s linear var(--d,0s) forwards, pipeOn .5s cubic-bezier(.2,.9,.3,1.4) var(--d,0s)}

/* Senden: kurzer Druck, dann die Bestätigung */
@keyframes ivPress{0%,100%{transform:scale(1)}45%{transform:scale(.96)}}
.anim-ready .hono .sendbtn,.anim-ready .hono .sendnote{opacity:0}
.anim-ready .hono.play .sendbtn{animation:ivRow .4s ease var(--ds,1.5s) forwards, ivPress .45s ease calc(var(--ds,1.5s) + .5s)}
.anim-ready .hono.play .sendnote{animation:ivRow .4s ease calc(var(--ds,1.5s) + .95s) forwards}

/* Sicherheitsnetz */
.anim-ready .hono .hono-r,.anim-ready .hono .emp,.anim-ready .hono .hono-tot,
.anim-ready .hono .sendbtn,.anim-ready .hono .sendnote,
.anim-ready .empbadge{animation:pfFailsafe .1s linear 8s forwards}
.anim-ready .pipe .pl i{animation:pipeFill .1s linear 8s forwards}

/* --- Hero des Trackers: drei Patienten, je drei Zahlen -------------------
   Ein Durchlauf dauert 12,6 s: 3 × 4,2 s je Patient, darin 3 × 1,4 s je Zahl.
   Der Ring fährt zwischen den Ständen weich nach. */
@keyframes pcStep{0%,33.33%{opacity:1}33.34%,100%{opacity:0}}
.pc>span{animation:pcStep 12.6s steps(1,end) infinite}
.pc>span:nth-child(2){animation-delay:4.2s}
.pc>span:nth-child(3){animation-delay:8.4s}

@keyframes ncStep{0%,11.11%{opacity:1}11.12%,100%{opacity:0}}
.nc>span{animation:ncStep 12.6s steps(1,end) infinite}
.nc>span:nth-child(2){animation-delay:1.4s}
.nc>span:nth-child(3){animation-delay:2.8s}
.nc>span:nth-child(4){animation-delay:4.2s}
.nc>span:nth-child(5){animation-delay:5.6s}
.nc>span:nth-child(6){animation-delay:7s}
.nc>span:nth-child(7){animation-delay:8.4s}
.nc>span:nth-child(8){animation-delay:9.8s}
.nc>span:nth-child(9){animation-delay:11.2s}

/* Umfang bei r=56 ist 352. Offset = 352 × (1 − offen/gesamt). */
@keyframes vrCycle{
  0%,8%{stroke-dashoffset:117}
  11.1%,19%{stroke-dashoffset:176}
  22.2%,30%{stroke-dashoffset:235}
  33.3%,41%{stroke-dashoffset:0}
  44.4%,52%{stroke-dashoffset:59}
  55.5%,63%{stroke-dashoffset:117}
  66.6%,74%{stroke-dashoffset:246}
  77.7%,85%{stroke-dashoffset:282}
  88.8%,97%{stroke-dashoffset:317}
  100%{stroke-dashoffset:117}
}
.anim-ready .vring.play .val{animation:vrCycle 12.6s cubic-bezier(.4,0,.3,1) .3s infinite}

/* Im Formular leuchtet das Feld selbst blau, nicht die ganze Zeile */
@keyframes pfField{
  0%{background:var(--soft);border-color:var(--line)}
  8%{background:#dcE8fb;border-color:#1f63d2}
  62%{background:#dcE8fb;border-color:#1f63d2}
  100%{background:var(--tint-2);border-color:var(--tint-line)}
}
.anim-ready .docform .drow.hl .fv{background:var(--soft);border-color:var(--line)}
.anim-ready .docform.play .drow.hl .fv{animation:pfField 2s ease forwards;animation-delay:var(--d,0s)}
.anim-ready .docform .fsave,.anim-ready .docform .fnote{opacity:0}
.anim-ready .docform.play .fsave{animation:pfRow .5s ease forwards, pfPress .5s ease calc(var(--dsave,11s) + .6s);animation-delay:var(--dsave,11s)}
.anim-ready .docform.play .fnote{animation:pfRow .45s ease calc(var(--dsave,11s) + 1.1s) forwards}
.anim-ready .docform .fsave,.anim-ready .docform .fnote{animation:pfFailsafe .1s linear 18s forwards}

/* Teilabrechnung: die Einheiten wechseln, die Summe rechnet mit */
.tcyc{position:relative;display:inline-block;text-align:right;vertical-align:bottom}
.tcyc>span{position:absolute;right:0;top:0;white-space:nowrap;opacity:0;
  animation:pfCyc 7.2s steps(1,end) infinite}
.tcyc>span:first-child{position:relative;opacity:1}
.tcyc>span:nth-child(2){animation-delay:2.4s}
.tcyc>span:nth-child(3){animation-delay:4.8s}
/* Die Auswahlzeile blinkt beim Wechsel kurz blau auf */
@keyframes tselFlash{0%,4%{background:#fff}10%,26%{background:#e9f1fc}40%,100%{background:#fff}}
.anim-ready .vsel-r{animation:tselFlash 7.2s ease infinite}
/* Die drei Felder darunter fahren gestaffelt ein */
.anim-ready .f3 .fs{opacity:0}
.anim-ready .docform.play .f3 .fs{animation:pfRow .45s ease forwards;animation-delay:var(--d,0s)}
.anim-ready .f3 .fs{animation:pfFailsafe .1s linear 18s forwards}

/* --- Terminliste als Umlauf ----------------------------------------------
   Ein Durchlauf dauert 12 s, jede der vier Zeilen ist 3 s lang dran.
   Hervorgehoben wird nur der Zähler, nicht die ganze Zeile – und hier
   ausnahmsweise in Grün, weil es kein Lesevorgang ist, sondern ein
   erledigter Termin. */
@keyframes tcActive{
  0%{background:var(--soft);border-color:var(--line);box-shadow:0 0 0 0 rgba(47,93,58,0)}
  3%{background:var(--tint);border-color:var(--green-ink);box-shadow:0 0 0 4px rgba(47,93,58,.14)}
  20%{background:var(--tint);border-color:var(--green-ink);box-shadow:0 0 0 4px rgba(47,93,58,.14)}
  25%,100%{background:var(--soft);border-color:var(--line);box-shadow:0 0 0 0 rgba(47,93,58,0)}
}
.anim-ready .tlist .trow{opacity:1}
.anim-ready .tlist.play .trow .tc{
  animation:tcActive 12s ease infinite, rcTick 12s ease infinite;
  animation-delay:var(--start,0s);
}
/* Der Zähler wechselt in der Mitte des eigenen Fensters */
.rcnt{position:relative;display:inline-block;text-align:right;vertical-align:bottom}
.rcnt>span{position:absolute;right:0;top:0;opacity:0}
.rcnt>span:first-child{position:relative;opacity:1}
@keyframes rcA{0%,11%{opacity:1}11.01%,100%{opacity:0}}
@keyframes rcB{0%,11%{opacity:0}11.01%,100%{opacity:1}}
.anim-ready .tlist.play .rcnt>span:nth-child(1){animation:rcA 12s steps(1,end) infinite;animation-delay:var(--start,0s)}
.anim-ready .tlist.play .rcnt>span:nth-child(2){animation:rcB 12s steps(1,end) infinite;animation-delay:var(--start,0s)}
/* Beim Sprung zuckt die Zahl kurz */
@keyframes rcTick{0%,9%{transform:scale(1)}12%{transform:scale(.82)}16%,100%{transform:scale(1)}}

/* Der Hinweis darunter blitzt bei jedem der vier Sprünge mit auf */
@keyframes noteTick{
  0%,9%{background:var(--tint);border-color:var(--tint-line)}
  12%,18%{background:#dcecc3;border-color:var(--green-ink)}
  24%,34%{background:var(--tint);border-color:var(--tint-line)}
  37%,43%{background:#dcecc3;border-color:var(--green-ink)}
  49%,59%{background:var(--tint);border-color:var(--tint-line)}
  62%,68%{background:#dcecc3;border-color:var(--green-ink)}
  74%,84%{background:var(--tint);border-color:var(--tint-line)}
  87%,93%{background:#dcecc3;border-color:var(--green-ink)}
  99%,100%{background:var(--tint);border-color:var(--tint-line)}
}
.anim-ready .vnote.calm.sync{animation:noteTick 12s ease infinite}

/* Die Auswahl der Zahlungsart wandert durch die drei Möglichkeiten */
@keyframes foptOn{
  0%,33.33%{background:var(--tint);border-color:var(--tint-line);color:var(--green-ink)}
  33.34%,100%{background:var(--soft);border-color:var(--line);color:var(--ink)}
}
.anim-ready .fopts .fopt{animation:foptOn 7.2s steps(1,end) infinite}
.anim-ready .fopts .fopt:nth-child(2){animation-delay:2.4s}
.anim-ready .fopts .fopt:nth-child(3){animation-delay:4.8s}

/* Das Feld blitzt blau auf und kehrt danach zu Weiß zurück –
   erledigt zeigt der Haken, nicht die Fläche. */
@keyframes pfField2{
  0%{background:#fff;border-color:var(--line)}
  8%{background:#e7effc;border-color:#1f63d2}
  62%{background:#e7effc;border-color:#1f63d2}
  100%{background:#fff;border-color:var(--line)}
}
.anim-ready .docform .drow.hl .fv{background:#fff;border-color:var(--line)}
.anim-ready .docform.play .drow.hl .fv{animation:pfField2 2s ease forwards;animation-delay:var(--d,0s)}
/* Im Formular markiert nur das Eingabefeld, nicht die ganze Zeile.
   Sonst lag ein zweiter Rahmen um Beschriftung plus Feld. */
.anim-ready .doc.docform.play .doc-top,
.anim-ready .doc.docform.play .drow.hl{animation:none;background:transparent;box-shadow:none}
/* Der Haken springt auf, wenn das Feld steht */
@keyframes fokIn{0%{opacity:0;transform:scale(.4)}60%{opacity:1;transform:scale(1.18)}100%{opacity:1;transform:scale(1)}}
.anim-ready .docform .fok{opacity:0}
.anim-ready .docform.play .fok{animation:fokIn .45s cubic-bezier(.2,.9,.3,1.4) forwards;animation-delay:calc(var(--d,0s) + 1.15s)}
.anim-ready .docform .fok{animation:pfFailsafe .1s linear 18s forwards}

/* --- Vorwarnung: drei Karten im Umlauf -----------------------------------
   12 s pro Durchlauf, jede Karte 4 s. Die aktive wird grün umrandet, ihr
   Balken wächst um eine Einheit, die Zahl zählt hoch und der Status
   springt weiter – läuft, läuft aus, abgeschlossen. */
@keyframes vkActive{
  0%{border-color:var(--line);box-shadow:0 22px 44px -30px rgba(12,42,24,.5)}
  3%{border-color:var(--green-ink);box-shadow:0 0 0 4px rgba(47,93,58,.13), 0 22px 44px -30px rgba(12,42,24,.5)}
  28%{border-color:var(--green-ink);box-shadow:0 0 0 4px rgba(47,93,58,.13), 0 22px 44px -30px rgba(12,42,24,.5)}
  33%,100%{border-color:var(--line);box-shadow:0 22px 44px -30px rgba(12,42,24,.5)}
}
/* Reihenfolge: erst läuft der Balken, dann springt die Zahl, zuletzt
   wechselt der Status. Vorher änderte sich der Status schon, während der
   Balken noch unterwegs war. */
@keyframes vkBar{0%,8%{width:var(--w1)}17%,100%{width:var(--w2)}}
@keyframes vkA{0%,17%{opacity:1}17.01%,100%{opacity:0}}
@keyframes vkB{0%,17%{opacity:0}17.01%,100%{opacity:1}}
@keyframes vkStatA{0%,20%{opacity:1}20.01%,100%{opacity:0}}
@keyframes vkStatB{0%,20%{opacity:0}20.01%,100%{opacity:1}}
@keyframes vkPop{0%,15%{transform:scale(1)}18%{transform:scale(.78)}22%,100%{transform:scale(1)}}
@keyframes vkStatPop{0%,19%{transform:scale(1)}22%{transform:scale(1.12)}26%,100%{transform:scale(1)}}

.anim-ready .vkstack .vok-bar i{width:var(--w1)}
.anim-ready .vkstack.play .vokarte{animation:vkActive 12s ease infinite;animation-delay:var(--start,0s)}
.anim-ready .vkstack.play .vok-bar i{animation:vkBar 12s cubic-bezier(.3,.8,.3,1) infinite;animation-delay:var(--start,0s)}
.anim-ready .vkstack.play .vcnt>span:nth-child(1){animation:vkA 12s steps(1,end) infinite;animation-delay:var(--start,0s)}
.anim-ready .vkstack.play .vcnt>span:nth-child(2){animation:vkB 12s steps(1,end) infinite;animation-delay:var(--start,0s)}
.anim-ready .vkstack.play .vsw>span:nth-child(1){animation:vkStatA 12s steps(1,end) infinite;animation-delay:var(--start,0s)}
.anim-ready .vkstack.play .vsw>span:nth-child(2){animation:vkStatB 12s steps(1,end) infinite;animation-delay:var(--start,0s)}
.anim-ready .vkstack.play .vcnt{animation:vkPop 12s ease infinite;animation-delay:var(--start,0s)}
.anim-ready .vkstack.play .vsw{display:inline-block;animation:vkStatPop 12s ease infinite;animation-delay:var(--start,0s)}
/* Sicherheitsnetz */
.anim-ready .vkstack .vok-bar i{animation:vkBar .1s linear 8s forwards}

/* ==========================================================================
   Patienten-Dokumentation – Bewegung
   ========================================================================== */
/* Die Balken des Schmerzverlaufs wachsen nacheinander hoch */
@keyframes nbGrow{from{height:0}to{height:var(--h,50%)}}
.anim-ready .nb i{height:0}
.anim-ready .nrs.play .nb i{animation:nbGrow .75s cubic-bezier(.3,.85,.3,1) forwards;animation-delay:var(--d,0s)}
.anim-ready .nb em{opacity:0}
.anim-ready .nrs.play .nb em{animation:pfRow .4s ease forwards;animation-delay:calc(var(--d,0s) + .5s)}
.anim-ready .nrs .nrs-note{opacity:0}
.anim-ready .nrs.play .nrs-note{animation:pfRow .5s ease 2.2s forwards}

/* Einträge im Verlauf fahren von unten ein */
@keyframes dkIn{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
.anim-ready .dkstack .dkent{opacity:0}
.anim-ready .dkstack.play .dkent{animation:dkIn .55s cubic-bezier(.2,.8,.3,1) forwards;animation-delay:var(--d,0s)}
/* Die Schlagworte poppen einzeln nach */
@keyframes tagPop{0%{opacity:0;transform:scale(.7)}65%{opacity:1;transform:scale(1.1)}100%{opacity:1;transform:scale(1)}}
.anim-ready .dkstack .tags span{opacity:0}
.anim-ready .dkstack.play .tags span{animation:tagPop .4s cubic-bezier(.2,.9,.3,1.4) forwards;animation-delay:var(--dt,0s)}

/* Textbausteine springen der Reihe nach an */
@keyframes tplOn{
  0%,6%{background:var(--soft);border-color:var(--line);color:var(--muted)}
  9%,22%{background:var(--forest);border-color:var(--forest);color:#fff}
  26%,100%{background:var(--soft);border-color:var(--line);color:var(--muted)}
}
.anim-ready .tpl span{animation:tplOn 8s ease infinite}
.anim-ready .tpl span:nth-child(2){animation-delay:2s}
.anim-ready .tpl span:nth-child(3){animation-delay:4s}
.anim-ready .tpl span:nth-child(4){animation-delay:6s}

/* Sicherheitsnetz */
.anim-ready .nb i{animation:nbGrow .1s linear 8s forwards}
.anim-ready .nb em,.anim-ready .nrs .nrs-note,
.anim-ready .dkstack .dkent,.anim-ready .dkstack .tags span{animation:pfFailsafe .1s linear 8s forwards}

/* ==========================================================================
   Kalender – Bewegung
   ========================================================================== */
/* Termine rutschen von rechts in ihre Zeitschiene */
@keyframes evIn{from{opacity:0;transform:translateX(16px)}to{opacity:1;transform:none}}
.anim-ready .dayplan .dp-ev{opacity:0}
.anim-ready .dayplan.play .dp-ev{animation:evIn .5s cubic-bezier(.2,.8,.3,1) forwards;animation-delay:var(--d,0s)}
/* Die Jetzt-Linie wandert langsam durch den Tag */
@keyframes nowMove{from{top:8%}to{top:86%}}
.anim-ready .dayplan .dp-now{opacity:0}
.anim-ready .dayplan.play .dp-now{opacity:1;animation:nowMove 14s linear 1.6s infinite}

/* Die drei Folgen eines Termins leuchten nacheinander auf */
@keyframes triOn{
  0%,4%{border-color:var(--line);box-shadow:none}
  8%{border-color:var(--green-ink);box-shadow:0 0 0 4px rgba(47,93,58,.12)}
  28%{border-color:var(--green-ink);box-shadow:0 0 0 4px rgba(47,93,58,.12)}
  33%,100%{border-color:var(--line);box-shadow:none}
}
@keyframes triIcon{
  0%,4%{background:var(--soft);color:var(--muted)}
  8%,28%{background:var(--forest);color:var(--lime)}
  33%,100%{background:var(--soft);color:var(--muted)}
}
@keyframes triVal{
  0%,6%{background:var(--soft);border-color:var(--line);color:var(--muted);transform:scale(1)}
  10%{background:var(--tint);border-color:var(--tint-line);color:var(--green-ink);transform:scale(1.08)}
  28%{background:var(--tint);border-color:var(--tint-line);color:var(--green-ink);transform:scale(1)}
  33%,100%{background:var(--soft);border-color:var(--line);color:var(--muted);transform:scale(1)}
}
.anim-ready .trio.play .tri{animation:triOn 9s ease infinite;animation-delay:var(--start,0s)}
.anim-ready .trio.play .tri .ti{animation:triIcon 9s ease infinite;animation-delay:var(--start,0s)}
.anim-ready .trio.play .tri .tv{animation:triVal 9s ease infinite;animation-delay:var(--start,0s)}

/* Sicherheitsnetz */
.anim-ready .dayplan .dp-ev{animation:evIn .1s linear 8s forwards}

/* ==========================================================================
   Preise – Bewegung
   ========================================================================== */
/* Der Umsatzregler wandert und der passende Tarif springt an */
@keyframes calcSlide{
  0%,6%{left:22%}
  22%,34%{left:44%}
  50%,62%{left:64%}
  78%,90%{left:86%}
  100%{left:22%}
}
@keyframes calcFill{
  0%,6%{width:22%}22%,34%{width:44%}50%,62%{width:64%}78%,90%{width:86%}100%{width:22%}
}
.anim-ready .calc.play .cknob{animation:calcSlide 16s cubic-bezier(.4,0,.3,1) infinite}
.anim-ready .calc.play .cfill{animation:calcFill 16s cubic-bezier(.4,0,.3,1) infinite}
/* Umsatzwert und Ergebnis wechseln im selben Takt */
.uc{position:relative;display:inline-block;text-align:right;vertical-align:bottom}
.uc>span{position:absolute;right:0;top:0;white-space:nowrap;opacity:0;
  animation:ucStep 16s steps(1,end) infinite}
.uc>span:first-child{position:relative;opacity:1}
.uc>span:nth-child(2){animation-delay:4s}
.uc>span:nth-child(3){animation-delay:8s}
.uc>span:nth-child(4){animation-delay:12s}
@keyframes ucStep{0%,25%{opacity:1}25.01%,100%{opacity:0}}
.ucl{position:relative;display:inline-block;text-align:left}
.ucl>span{position:absolute;left:0;top:0;white-space:nowrap;opacity:0;
  animation:ucStep 16s steps(1,end) infinite}
.ucl>span:first-child{position:relative;opacity:1}
.ucl>span:nth-child(2){animation-delay:4s}
.ucl>span:nth-child(3){animation-delay:8s}
.ucl>span:nth-child(4){animation-delay:12s}
/* Der Ergebniskasten wechselt die Farbe, wenn die Grenze überschritten wird */
@keyframes coutFlip{
  0%,24%{background:var(--forest)}
  25%,100%{background:var(--green-ink)}
}
.anim-ready .calc.play .cout .ci{animation:coutFlip 16s steps(1,end) infinite}

/* Der Sonderpreis zählt von 42 auf 15 herunter */
@keyframes prcDrop{
  0%,12%{opacity:1;transform:none}
  18%,100%{opacity:0;transform:translateY(-7px)}
}
@keyframes prcUp{
  0%,14%{opacity:0;transform:translateY(9px) scale(.9)}
  22%{opacity:1;transform:translateY(0) scale(1.06)}
  28%,100%{opacity:1;transform:none}
}
@keyframes prcOld{
  0%,16%{opacity:0}
  24%,100%{opacity:1}
}
.anim-ready .plan .prc-b{display:inline-block;opacity:1}
.anim-ready .plan .prc-a{position:absolute;left:0;top:0;opacity:0}
.anim-ready .plan .prc-old{opacity:0}
.anim-ready .plan.play .prc-b{animation:prcDrop 9s ease infinite}
.anim-ready .plan.play .prc-a{animation:prcUp 9s cubic-bezier(.2,.9,.3,1.3) infinite}
.anim-ready .plan.play .prc-old{animation:prcOld 9s ease infinite}
/* Die Leistungen haken sich der Reihe nach ab */
.anim-ready .plan li{opacity:0}
.anim-ready .plan.play li{animation:pfRow .45s ease forwards;animation-delay:var(--d,0s)}
.anim-ready .plan li{animation:pfFailsafe .1s linear 8s forwards}

/* ==========================================================================
   Hero der Dokumentation – ein Eintrag entsteht in 11 Sekunden
   0,3–3,0 s  Befund wird getippt
   3,2–4,6 s  Bausteine springen hinein
   4,8–6,4 s  Schmerzregler wandert von 7 auf 3
   6,6–7,4 s  Speichern wird gedrückt
   7,6–10,5 s Bestätigung steht, danach beginnt es von vorn
   ========================================================================== */
@keyframes typeIn{
  0%,3%{width:0}
  27%{width:100%}
  92%{width:100%}
  96%,100%{width:0}
}
@keyframes caretBlink{0%,45%{opacity:1}46%,90%{opacity:0}91%,100%{opacity:1}}
.anim-ready .dkw .typ{width:0}
.anim-ready .dkw.play .typ{animation:typeIn 11s steps(38,end) infinite}
.anim-ready .dkw.play .caret{animation:caretBlink .9s steps(1,end) infinite}

@keyframes chipIn{
  0%,29%{opacity:0;transform:scale(.5)}
  33%{opacity:1;transform:scale(1.15)}
  36%,90%{opacity:1;transform:scale(1)}
  94%,100%{opacity:0;transform:scale(.9)}
}
.anim-ready .dkchips span{opacity:0}
.anim-ready .dkw.play .dkchips span{animation:chipIn 11s ease infinite;animation-delay:var(--d,0s)}

@keyframes slideKnob{0%,43%{left:70%}58%,90%{left:30%}94%,100%{left:70%}}
@keyframes slideFill{0%,43%{width:70%}58%,90%{width:30%}94%,100%{width:70%}}
@keyframes nrsA{0%,47%{opacity:1}47.01%,100%{opacity:0}}
@keyframes nrsB{0%,47%{opacity:0}47.01%,90%{opacity:1}94%,100%{opacity:0}}
.anim-ready .dkw.play .dkrail .kn{animation:slideKnob 11s cubic-bezier(.4,0,.3,1) infinite}
.anim-ready .dkw.play .dkrail i{animation:slideFill 11s cubic-bezier(.4,0,.3,1) infinite}
.anim-ready .dkw .val>span{position:absolute;right:0;top:0;opacity:0}
.anim-ready .dkw .val>span:first-child{position:relative;opacity:1}
.anim-ready .dkw.play .val>span:nth-child(1){animation:nrsA 11s steps(1,end) infinite}
.anim-ready .dkw.play .val>span:nth-child(2){animation:nrsB 11s steps(1,end) infinite}

@keyframes savePress{0%,60%{transform:scale(1)}64%{transform:scale(.95)}68%,100%{transform:scale(1)}}
@keyframes doneIn{
  0%,66%{opacity:0;transform:translateY(6px)}
  71%,90%{opacity:1;transform:none}
  94%,100%{opacity:0;transform:translateY(6px)}
}
.anim-ready .dkw.play .dksave{animation:savePress 11s ease infinite}
.anim-ready .dkw .dkdone{opacity:0}
.anim-ready .dkw.play .dkdone{animation:doneIn 11s ease infinite}
/* Sicherheitsnetz: ohne Wiedergabe steht der Eintrag vollständig da */
.anim-ready .dkw .typ{animation:typeIn .1s linear 8s forwards}
.anim-ready .dkchips span,.anim-ready .dkw .dkdone{animation:pfFailsafe .1s linear 8s forwards}

/* --- Wochenraster: die Tage füllen sich von Montag nach Freitag ----------- */
@keyframes wkIn{from{opacity:0;transform:translateY(7px) scale(.96)}to{opacity:1;transform:none}}
.anim-ready .wcal .cell.ev{opacity:0}
.anim-ready .week.play .wcal .cell.ev{animation:wkIn .42s cubic-bezier(.2,.8,.3,1) forwards;animation-delay:var(--d,0s)}
/* Der freie Platz pulst, sobald die Woche steht */
@keyframes wkFree{
  0%,55%{background:#fff;box-shadow:0 0 0 0 rgba(47,93,58,0)}
  62%{background:var(--tint);box-shadow:0 0 0 5px rgba(47,93,58,.14)}
  78%{background:var(--tint);box-shadow:0 0 0 5px rgba(47,93,58,.14)}
  88%,100%{background:#fff;box-shadow:0 0 0 0 rgba(47,93,58,0)}
}
.anim-ready .wcal .cell.free{opacity:0}
.anim-ready .week.play .wcal .cell.free{
  animation:wkIn .42s cubic-bezier(.2,.8,.3,1) 1.5s forwards, wkFree 4s ease 2s infinite;
}
.anim-ready .week .week-note{opacity:0}
.anim-ready .week.play .week-note{animation:pfRow .5s ease 2.1s forwards}
/* Sicherheitsnetz */
.anim-ready .wcal .cell.ev,.anim-ready .wcal .cell.free,
.anim-ready .week .week-note{animation:pfFailsafe .1s linear 8s forwards}

/* ==========================================================================
   Preise – Bewegung
   ========================================================================== */
/* Der Umsatzregler wandert und der passende Tarif springt an */
@keyframes calcSlide{
  0%,6%{left:22%}
  22%,34%{left:44%}
  50%,62%{left:64%}
  78%,90%{left:86%}
  100%{left:22%}
}
@keyframes calcFill{
  0%,6%{width:22%}22%,34%{width:44%}50%,62%{width:64%}78%,90%{width:86%}100%{width:22%}
}
.anim-ready .calc.play .cknob{animation:calcSlide 16s cubic-bezier(.4,0,.3,1) infinite}
.anim-ready .calc.play .cfill{animation:calcFill 16s cubic-bezier(.4,0,.3,1) infinite}
/* Umsatzwert und Ergebnis wechseln im selben Takt */
.uc{position:relative;display:inline-block;text-align:right;vertical-align:bottom}
.uc>span{position:absolute;right:0;top:0;white-space:nowrap;opacity:0;
  animation:ucStep 16s steps(1,end) infinite}
.uc>span:first-child{position:relative;opacity:1}
.uc>span:nth-child(2){animation-delay:4s}
.uc>span:nth-child(3){animation-delay:8s}
.uc>span:nth-child(4){animation-delay:12s}
@keyframes ucStep{0%,25%{opacity:1}25.01%,100%{opacity:0}}
.ucl{position:relative;display:inline-block;text-align:left}
.ucl>span{position:absolute;left:0;top:0;white-space:nowrap;opacity:0;
  animation:ucStep 16s steps(1,end) infinite}
.ucl>span:first-child{position:relative;opacity:1}
.ucl>span:nth-child(2){animation-delay:4s}
.ucl>span:nth-child(3){animation-delay:8s}
.ucl>span:nth-child(4){animation-delay:12s}
/* Der Ergebniskasten wechselt die Farbe, wenn die Grenze überschritten wird */
@keyframes coutFlip{
  0%,24%{background:var(--forest)}
  25%,100%{background:var(--green-ink)}
}
.anim-ready .calc.play .cout .ci{animation:coutFlip 16s steps(1,end) infinite}

/* Der Sonderpreis zählt von 42 auf 15 herunter */
@keyframes prcDrop{
  0%,12%{opacity:1;transform:none}
  18%,100%{opacity:0;transform:translateY(-7px)}
}
@keyframes prcUp{
  0%,14%{opacity:0;transform:translateY(9px) scale(.9)}
  22%{opacity:1;transform:translateY(0) scale(1.06)}
  28%,100%{opacity:1;transform:none}
}
@keyframes prcOld{
  0%,16%{opacity:0}
  24%,100%{opacity:1}
}
.anim-ready .plan .prc-b{display:inline-block;opacity:1}
.anim-ready .plan .prc-a{position:absolute;left:0;top:0;opacity:0}
.anim-ready .plan .prc-old{opacity:0}
.anim-ready .plan.play .prc-b{animation:prcDrop 9s ease infinite}
.anim-ready .plan.play .prc-a{animation:prcUp 9s cubic-bezier(.2,.9,.3,1.3) infinite}
.anim-ready .plan.play .prc-old{animation:prcOld 9s ease infinite}
/* Die Leistungen haken sich der Reihe nach ab */
.anim-ready .plan li{opacity:0}
.anim-ready .plan.play li{animation:pfRow .45s ease forwards;animation-delay:var(--d,0s)}
.anim-ready .plan li{animation:pfFailsafe .1s linear 8s forwards}

/* ==========================================================================
   Hero der Dokumentation – ein Eintrag entsteht in 11 Sekunden
   0,3–3,0 s  Befund wird getippt
   3,2–4,6 s  Bausteine springen hinein
   4,8–6,4 s  Schmerzregler wandert von 7 auf 3
   6,6–7,4 s  Speichern wird gedrückt
   7,6–10,5 s Bestätigung steht, danach beginnt es von vorn
   ========================================================================== */
@keyframes typeIn{
  0%,3%{width:0}
  27%{width:100%}
  92%{width:100%}
  96%,100%{width:0}
}
@keyframes caretBlink{0%,45%{opacity:1}46%,90%{opacity:0}91%,100%{opacity:1}}
.anim-ready .dkw .typ{width:0}
.anim-ready .dkw.play .typ{animation:typeIn 11s steps(38,end) infinite}
.anim-ready .dkw.play .caret{animation:caretBlink .9s steps(1,end) infinite}

@keyframes chipIn{
  0%,29%{opacity:0;transform:scale(.5)}
  33%{opacity:1;transform:scale(1.15)}
  36%,90%{opacity:1;transform:scale(1)}
  94%,100%{opacity:0;transform:scale(.9)}
}
.anim-ready .dkchips span{opacity:0}
.anim-ready .dkw.play .dkchips span{animation:chipIn 11s ease infinite;animation-delay:var(--d,0s)}

@keyframes slideKnob{0%,43%{left:70%}58%,90%{left:30%}94%,100%{left:70%}}
@keyframes slideFill{0%,43%{width:70%}58%,90%{width:30%}94%,100%{width:70%}}
@keyframes nrsA{0%,47%{opacity:1}47.01%,100%{opacity:0}}
@keyframes nrsB{0%,47%{opacity:0}47.01%,90%{opacity:1}94%,100%{opacity:0}}
.anim-ready .dkw.play .dkrail .kn{animation:slideKnob 11s cubic-bezier(.4,0,.3,1) infinite}
.anim-ready .dkw.play .dkrail i{animation:slideFill 11s cubic-bezier(.4,0,.3,1) infinite}
.anim-ready .dkw .val>span{position:absolute;right:0;top:0;opacity:0}
.anim-ready .dkw .val>span:first-child{position:relative;opacity:1}
.anim-ready .dkw.play .val>span:nth-child(1){animation:nrsA 11s steps(1,end) infinite}
.anim-ready .dkw.play .val>span:nth-child(2){animation:nrsB 11s steps(1,end) infinite}

@keyframes savePress{0%,60%{transform:scale(1)}64%{transform:scale(.95)}68%,100%{transform:scale(1)}}
@keyframes doneIn{
  0%,66%{opacity:0;transform:translateY(6px)}
  71%,90%{opacity:1;transform:none}
  94%,100%{opacity:0;transform:translateY(6px)}
}
.anim-ready .dkw.play .dksave{animation:savePress 11s ease infinite}
.anim-ready .dkw .dkdone{opacity:0}
.anim-ready .dkw.play .dkdone{animation:doneIn 11s ease infinite}
/* Sicherheitsnetz: ohne Wiedergabe steht der Eintrag vollständig da */
.anim-ready .dkw .typ{animation:typeIn .1s linear 8s forwards}
.anim-ready .dkchips span,.anim-ready .dkw .dkdone{animation:pfFailsafe .1s linear 8s forwards}

/* --- Wochenansicht: die Tage füllen sich nacheinander --------------------- */
@keyframes wkGrow{from{height:0;opacity:0}to{height:var(--h,20%);opacity:1}}
.anim-ready .week .wblk{height:0;opacity:0}
.anim-ready .week.play .wblk{animation:wkGrow .5s cubic-bezier(.3,.85,.3,1) forwards;animation-delay:var(--d,0s)}
.anim-ready .week .week-note{opacity:0}
.anim-ready .week.play .week-note{animation:pfRow .5s ease 2.4s forwards}
/* Der freie Block blinkt, damit die Lücke auffällt */
@keyframes wkFree{0%,60%{opacity:1}70%{opacity:.35}80%,100%{opacity:1}}
.anim-ready .week.play .wblk.free{animation:wkGrow .5s cubic-bezier(.3,.85,.3,1) var(--d,0s) forwards,
  wkFree 3s ease 2.6s infinite}
/* Sicherheitsnetz */
.anim-ready .week .wblk{animation:wkGrow .1s linear 8s forwards}
.anim-ready .week .week-note{animation:pfFailsafe .1s linear 8s forwards}

/* --- Startseite v2: der Tagesstrahl läuft ab ------------------------------ */
@keyframes tsIn{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
.anim-ready .tlline .tcard{opacity:0}
.anim-ready .tlline.play .tcard{animation:tsIn .55s cubic-bezier(.2,.8,.3,1) forwards;animation-delay:var(--d,0s)}
@keyframes tdPop{0%{opacity:0;transform:scale(.4)}60%{opacity:1;transform:scale(1.18)}100%{opacity:1;transform:scale(1)}}
.anim-ready .tlline .tdot{opacity:0}
.anim-ready .tlline.play .tdot{animation:tdPop .45s cubic-bezier(.2,.9,.3,1.4) forwards;animation-delay:var(--d,0s)}
@keyframes tmPop{0%{opacity:0;transform:scale(.8)}65%{opacity:1;transform:scale(1.06)}100%{opacity:1;transform:scale(1)}}
.anim-ready .tlline .tmini span{opacity:0}
.anim-ready .tlline.play .tmini span{animation:tmPop .4s cubic-bezier(.2,.9,.3,1.4) forwards;animation-delay:var(--dm,0s)}
.anim-ready .tlline .tcard,.anim-ready .tlline .tdot,
.anim-ready .tlline .tmini span{animation:pfFailsafe .1s linear 9s forwards}

/* --- Startseite v3: das Fenster wechselt von selbst durch fünf Module -----
   20 s Umlauf, 4 s je Modul. Reiter, Inhalt und Plakette wechseln zugleich. */
@keyframes awPane{0%,17%{opacity:1}20%,100%{opacity:0}}
@keyframes awTab{
  0%,17%{color:var(--ink);border-bottom-color:var(--forest);background:#fff}
  20%,100%{color:var(--muted);border-bottom-color:transparent;background:var(--soft)}
}
.anim-ready .aw-pane{opacity:0}
.anim-ready .aw-pane:first-child{opacity:1}
.anim-ready .appwin.play .aw-pane{animation:awPane 20s steps(1,end) infinite}
.anim-ready .appwin.play .aw-pane:nth-child(2){animation-delay:4s}
.anim-ready .appwin.play .aw-pane:nth-child(3){animation-delay:8s}
.anim-ready .appwin.play .aw-pane:nth-child(4){animation-delay:12s}
.anim-ready .appwin.play .aw-pane:nth-child(5){animation-delay:16s}
.anim-ready .appwin.play .aw-tabs span{animation:awTab 20s steps(1,end) infinite}
.anim-ready .appwin.play .aw-tabs span:nth-child(2){animation-delay:4s}
.anim-ready .appwin.play .aw-tabs span:nth-child(3){animation-delay:8s}
.anim-ready .appwin.play .aw-tabs span:nth-child(4){animation-delay:12s}
.anim-ready .appwin.play .aw-tabs span:nth-child(5){animation-delay:16s}
/* Innerhalb eines Moduls fahren die Zeilen ein */
@keyframes awRow{
  0%{opacity:0;transform:translateY(8px)}
  4%,17%{opacity:1;transform:none}
  20%,100%{opacity:0;transform:translateY(-4px)}
}
.anim-ready .appwin.play .aw-pane .aw-r,
.anim-ready .appwin.play .aw-pane .aw-done{animation:awRow 20s ease infinite;animation-delay:var(--d,0s)}
.anim-ready .appwin.play .aw-pane:nth-child(2) .aw-r,
.anim-ready .appwin.play .aw-pane:nth-child(2) .aw-done{animation-delay:calc(4s + var(--d,0s))}
.anim-ready .appwin.play .aw-pane:nth-child(3) .aw-r,
.anim-ready .appwin.play .aw-pane:nth-child(3) .aw-done{animation-delay:calc(8s + var(--d,0s))}
.anim-ready .appwin.play .aw-pane:nth-child(4) .aw-r,
.anim-ready .appwin.play .aw-pane:nth-child(4) .aw-done{animation-delay:calc(12s + var(--d,0s))}
.anim-ready .appwin.play .aw-pane:nth-child(5) .aw-r,
.anim-ready .appwin.play .aw-pane:nth-child(5) .aw-done{animation-delay:calc(16s + var(--d,0s))}
/* Die Plakette wechselt den Text mit */
.awc{position:relative;display:inline-block}
.awc>span{position:absolute;left:0;top:0;white-space:nowrap;opacity:0;
  animation:awPane 20s steps(1,end) infinite}
.awc>span:first-child{position:relative;opacity:1}
.awc>span:nth-child(2){animation-delay:4s}
.awc>span:nth-child(3){animation-delay:8s}
.awc>span:nth-child(4){animation-delay:12s}
.awc>span:nth-child(5){animation-delay:16s}

/* --- Startseite v4: die Reiter wandern durch, das Panel wechselt mit ------
   20 s Umlauf, 4 s je Funktion. */
@keyframes fnOn{
  0%,18%{border-bottom-color:var(--forest)}
  20%,100%{border-bottom-color:transparent}
}
@keyframes fnIco{
  0%,18%{background:var(--forest);border-color:var(--forest);color:var(--lime)}
  20%,100%{background:var(--soft);border-color:var(--line);color:var(--muted)}
}
@keyframes fnTxt{0%,18%{color:var(--ink)}20%,100%{color:var(--muted)}}
@keyframes fsIn{
  0%{opacity:0;transform:translateY(10px)}
  3%,18%{opacity:1;transform:none}
  20%,100%{opacity:0;transform:translateY(-6px)}
}
.anim-ready .fscene{opacity:0}
.anim-ready .fscene:first-of-type{opacity:1}
.anim-ready .fstage.play .fscene{animation:fsIn 20s ease infinite}
.anim-ready .fnav.play .ft{animation:fnOn 20s steps(1,end) infinite}
.anim-ready .fnav.play .ft .fi{animation:fnIco 20s steps(1,end) infinite}
.anim-ready .fnav.play .ft b{animation:fnTxt 20s steps(1,end) infinite}
.anim-ready .fstage.play .fscene:nth-of-type(2),
.anim-ready .fnav.play .ft:nth-child(2),
.anim-ready .fnav.play .ft:nth-child(2) .fi,
.anim-ready .fnav.play .ft:nth-child(2) b{animation-delay:4s}
.anim-ready .fstage.play .fscene:nth-of-type(3),
.anim-ready .fnav.play .ft:nth-child(3),
.anim-ready .fnav.play .ft:nth-child(3) .fi,
.anim-ready .fnav.play .ft:nth-child(3) b{animation-delay:8s}
.anim-ready .fstage.play .fscene:nth-of-type(4),
.anim-ready .fnav.play .ft:nth-child(4),
.anim-ready .fnav.play .ft:nth-child(4) .fi,
.anim-ready .fnav.play .ft:nth-child(4) b{animation-delay:12s}
.anim-ready .fstage.play .fscene:nth-of-type(5),
.anim-ready .fnav.play .ft:nth-child(5),
.anim-ready .fnav.play .ft:nth-child(5) .fi,
.anim-ready .fnav.play .ft:nth-child(5) b{animation-delay:16s}

/* --- Startseite v5: in jeder Zeile bewegt sich ein Detail ----------------- */
@keyframes frIn{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
.anim-ready .flist .frow{opacity:0}
.anim-ready .flist.play .frow{animation:frIn .5s cubic-bezier(.2,.8,.3,1) forwards;animation-delay:var(--d,0s)}
@keyframes fsBar{from{width:0}to{width:var(--w,60%)}}
.anim-ready .flist .fstrip .sb i{width:0}
.anim-ready .flist.play .fstrip .sb i{animation:fsBar .8s cubic-bezier(.3,.85,.3,1) forwards;animation-delay:calc(var(--d,0s) + .35s)}
.anim-ready .flist .frow{animation:pfFailsafe .1s linear 8s forwards}
.anim-ready .flist .fstrip .sb i{animation:fsBar .1s linear 8s forwards}

/* --- Startseite v6: der Stapel blättert sich selbst durch -----------------
   20 s Umlauf, 4 s je Karte. Die oberste gleitet nach links weg. */
@keyframes dkCard{
  0%{opacity:1;transform:translate(0,0) scale(1) rotate(0);z-index:5}
  18%{opacity:1;transform:translate(0,0) scale(1) rotate(0);z-index:5}
  22%{opacity:0;transform:translate(-46px,-16px) scale(.95) rotate(-2.5deg);z-index:5}
  23%{opacity:0;transform:translate(0,26px) scale(.9) rotate(0);z-index:0}
  95%{opacity:0;transform:translate(0,14px) scale(.95) rotate(0);z-index:1}
  100%{opacity:1;transform:translate(0,0) scale(1) rotate(0);z-index:5}
}
.anim-ready .deck .dcard{opacity:0}
.anim-ready .deck .dcard:first-child{opacity:1}
.anim-ready .deck.play .dcard{animation:dkCard 20s cubic-bezier(.4,0,.3,1) infinite}
.anim-ready .deck.play .dcard:nth-child(2){animation-delay:4s}
.anim-ready .deck.play .dcard:nth-child(3){animation-delay:8s}
.anim-ready .deck.play .dcard:nth-child(4){animation-delay:12s}
.anim-ready .deck.play .dcard:nth-child(5){animation-delay:16s}
@keyframes dkDot{0%,18%{background:var(--forest);transform:scale(1.35)}20%,100%{background:var(--line);transform:scale(1)}}
.anim-ready .ddots.play i{animation:dkDot 20s steps(1,end) infinite}
.anim-ready .ddots.play i:nth-child(2){animation-delay:4s}
.anim-ready .ddots.play i:nth-child(3){animation-delay:8s}
.anim-ready .ddots.play i:nth-child(4){animation-delay:12s}
.anim-ready .ddots.play i:nth-child(5){animation-delay:16s}

/* --- Steuererklärung: die Formulare stapeln sich auf --------------------- */
@keyframes frmIn{from{opacity:0;transform:translateX(-14px)}to{opacity:1;transform:none}}
.anim-ready .forms .frm{opacity:0}
.anim-ready .forms.play .frm{animation:frmIn .5s cubic-bezier(.2,.8,.3,1) forwards;animation-delay:var(--d,0s)}
/* Die Kennung auf dem Formularblatt springt auf */
@keyframes frmKey{0%{opacity:0;transform:translateY(6px)}60%{opacity:1;transform:translateY(-1px)}100%{opacity:1;transform:none}}
.anim-ready .forms .frm .fk{opacity:0}
.anim-ready .forms.play .frm .fk{animation:frmKey .45s cubic-bezier(.2,.9,.3,1.4) forwards;animation-delay:calc(var(--d,0s) + .25s)}
/* Der Ablauf läuft Schritt für Schritt an */
@keyframes fstIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.anim-ready .flow .fst{opacity:0}
.anim-ready .flow.play .fst{animation:fstIn .5s cubic-bezier(.2,.8,.3,1) forwards;animation-delay:var(--d,0s)}
@keyframes fnPop{0%{transform:scale(.5)}60%{transform:scale(1.16)}100%{transform:scale(1)}}
.anim-ready .flow.play .fst .fn{animation:fnPop .45s cubic-bezier(.2,.9,.3,1.4) forwards;animation-delay:var(--d,0s)}
/* Sicherheitsnetz */
.anim-ready .forms .frm,.anim-ready .forms .frm .fk,
.anim-ready .flow .fst{animation:pfFailsafe .1s linear 8s forwards}
