/* Fittsack — Bewegung und Piktogramme.

   Die Bewegungssprache in Kurzform. Neue Teile halten sich daran, statt
   eigene Dauern oder Kurven zu erfinden.

   Leitbild: Dinge werden hingestellt, angefasst, weggeräumt. Kommen bremst
   ab (--kurve), Gehen beschleunigt (--kurve-ab) und ist schneller als
   Kommen. Leben gibt es nur, wo gekocht oder gewartet wird.

   Takt: nur die Tokens unter "Takt" - eigene Zahlen allein für Schleifen
   und Gesten mit mehreren Schlägen.

   Siebzehn Gesten, jede mit festem Einsatz:
     Auftreten    - Seite, Karte, Listeneintrag: 8px herauf, gestaffelt.
     Abtreten     - was geht: ausblenden und absinken (.geht, app.js: weg,
                    dialogZu). Überlagerungen gehen zu ihrer Kante zurück.
     Eindrücken   - alles Antippbare, nach Größe klein/mittel/groß, dazu die
                    Welle vom Finger aus.
     Federn       - nur beim Einschalten und nach geglückter Aktion.
                    Ausnahme: Seite hinein/zurück schwingt nach.
     Zeichnen     - Piktogramme malen ihren Strich.
     Leben        - Dauerschleifen nur bei .lebt, im Kochmodus, beim Warten.
                    Beim Warten auf Gerichte fahren Beispielbilder durch
                    die leeren Kacheln (durchfahren, app.js: durchlaufen).
     Kopfschütteln - "Das ging nicht": Fehlermeldung, abgelehntes Feld,
                    gescheitertes Absenden. Schließt Federn aus.
     Aufleuchten  - ein angesprungenes Ziel.
     Ziehen       - etwas an einen anderen Platz legen: Finger halten
                    (--dauer-halten), Karte hebt sich und folgt, Ziele
                    leuchten; daneben losgelassen gleitet sie zurück.
                    Auch die Kacheln einer Box tauschen so.
     Verschieben  - ein Foto im Rahmen zurechtrücken: sofort anfassen,
                    ohne Halten; folgt dem Finger, bleibt am Rand stehen,
                    kein Nachfedern. Zwei Finger, Mausrad, Regler zoomen.
     Wachsen      - eine Kachel öffnet ihre Seite: die Seite wächst aus
                    dem Umriss der Kachel (Seitenübergang mit
                    view-transition-name), zurück schrumpft sie hinein.
     Blatt        - Einstellungen, Nachfragen, Details: Glasblatt von
                    unten, Griff oben; herunterziehen, ✕ oder ein Tipp
                    daneben schließt es.
     Einsammeln   - Abgehaktes fliegt als kleines Bild in die Korbleiste,
                    die Leiste federt.
     Blättern     - seitlich wischen: die Fläche folgt dem Finger, am Rand
                    zäh; sie rastet ein oder gleitet zurück, das Neue
                    kommt aus der Wischrichtung (wischkette.js).
     Herunterziehen - eine ganze Seite (Rezept) ganz oben nach unten
                    ziehen schließt sie: sie folgt dem Finger, schrumpft
                    leicht, ab ~110px oder mit Schwung schließt sie wie ‹,
                    sonst gleitet sie zurück (rezept.js).
     Festhalten   - Finger liegt --dauer-halten auf einer Zeile (Einkaufs-
                    posten, Angebot): ihr Detailblatt öffnet sich. Tipp
                    und Wischen behalten ihre Bedeutung (festhalten.js).
     Auftischen   - was Fittsack ungefragt vorbereitet hat, beim ersten
                    Zeigen: die Kacheln leuchten gestaffelt auf, ohne
                    Glocke. Einmal je Lieferung, nie als Schleife.

   Seitenwechsel haben Richtung (vor, zurueck, reiter-rechts/-links,
   seitwaerts; siehe unten und den Kopf von base.html). Hinein und zurück
   schieben die ganze Seite und federn nach - das einzige Federn, das
   nicht bestätigt. Eine Aktion auf derselben Seite lädt nicht neu:
   app.js tauscht nur den Inhalt, und was schon da war, tritt nicht noch
   einmal auf.

   Rückmeldung auf einen Druck in vier Takten: sofort eindrücken, während
   der Arbeit der Kreisel, der Warteschirm oder - wo Rezepte entstehen -
   Kacheln mitten im Inhalt (dazu die Auftragsleiste auf anderen Seiten),
   danach Toast und Federn - oder Kopfschütteln.

   Alles läuft über transform, opacity und stroke - nie über Layout oder
   filter, damit es auf dem Handy und dem Pi flüssig bleibt. Glas (die
   Unschärfe dahinter) und Auslaufen (Maske) stehen in style.css und werden
   nie animiert. Farben, Rundungen und Schatten stehen in tokens.css. Die Regel für
   prefers-reduced-motion in style.css deckt alles hier mit ab. */

/* ------------------------------------------------------------------ Takt */
/* Jede einmalige Bewegung nimmt eine dieser Dauern. Eigene Zahlen haben nur
   Schleifen (Dampf, Funken, Zeiger …) und die wenigen Gesten mit mehreren
   Schlägen (Wehen, Herzschlag, Aufleuchten, Konfetti) - dort ist der
   Rhythmus Teil der Form. Verzögerungen sind Choreografie, keine Dauern. */

:root {
  --dauer-tipp:      90ms;   /* Eindrücken beim Antippen */
  --dauer:           .18s;   /* Farbwechsel, jeder Abgang */
  --dauer-lang:      .32s;   /* ein einzelnes Teil kommt: Blatt, Toast, Ausklapper */
  --dauer-feder:     .5s;    /* Federn beim Einschalten */
  --dauer-auftritt:  .5s;    /* Seitenaufbau, Karten steigen auf */
  --dauer-zeichnen:  .7s;    /* Striche, Balken, Ring, Zeichengesten */
  --staffel:         45ms;   /* Abstand beim gestaffelten Auftritt */
  --dauer-halten:    400ms;  /* Finger halten, bis sich etwas zum Ziehen anhebt */
  --dauer-verweilen: 650ms;  /* über einem Reiter verweilen, bis er aufgeht */

  --kurve:       cubic-bezier(.2, .7, .2, 1);      /* kommt an, bremst ab */
  --kurve-ab:    cubic-bezier(.4, 0, 1, 1);        /* geht, beschleunigt */
  --kurve-feder: cubic-bezier(.34, 1.56, .64, 1);  /* nur zur Bestätigung */
  --kurve-schwung: cubic-bezier(.3, 1.4, .5, 1);  /* Seite hinein/zurück: ~5 % drüber */

  /* Wie tief sich etwas beim Antippen eindrückt - nach Größe. */
  --druck-klein:  .92;   /* runde Knöpfe, Zeichenknöpfe */
  --druck-mittel: .96;   /* Knöpfe, Chips, Kacheln */
  --druck-gross:  .985;  /* Karten und Zeilen */
}

/* ------------------------------------------------------------ Grundformen */
/* Allgemeine Abläufe, die viele Teile teilen. Die besonderen stehen bei
   ihrer Geste weiter unten. */

@keyframes einblenden { from { opacity: 0; } to { opacity: 1; } }
@keyframes hereinwachsen { from { transform: translateX(-50%) scaleX(0); } to { transform: translateX(-50%) scaleX(1); } }
@keyframes pop { from { transform: scale(0); } 70% { transform: scale(1.4); } to { transform: scale(1); } }
@keyframes drehen { to { transform: rotate(360deg); } }
/* Ein Lichtstreif zieht über einen Platz, der sich gleich füllt (Bento-Box). */
@keyframes schimmern { to { transform: translateX(100%); } }
/* Ein Gericht fährt durch eine leere Kachel: von links herein und abbremsen,
   kurz verweilen, nach rechts hinaus beschleunigen (.wk-durchlauf img;
   den Takt bis zum nächsten Gericht hält app.js). Zwei Abläufe statt
   einem, weil eine Kurve innerhalb von @keyframes keine Variable nimmt. */
@keyframes durchfahren-herein { from { transform: translateX(-100%); } to { transform: none; } }
@keyframes durchfahren-hinaus { from { transform: none; } to { transform: translateX(100%); } }
@keyframes pulsieren { 50% { box-shadow: 0 0 0 5px color-mix(in srgb, var(--blau) 20%, transparent); } }
@keyframes atmen { 50% { opacity: .45; } }
@keyframes toast-auf { from { opacity: 0; transform: translate(-50%, 14px); } to { opacity: 1; transform: translate(-50%, 0); } }
@keyframes toast-ab { to { opacity: 0; transform: translate(-50%, 14px); } }
@keyframes schnipseln {
  to { transform: translate(var(--drift, 0), 100vh) rotate(720deg); opacity: 0; }
}
@keyframes hervorheben-puls {
  0%   { background: var(--primaer-hell); box-shadow: 0 0 0 3px var(--primaer); }
  75%  { background: var(--primaer-hell); box-shadow: 0 0 0 3px var(--primaer); }
  100% { background: var(--flaeche); box-shadow: 0 0 0 0 transparent; }
}

/* Der Anteil im Ring soll sich füllen können - dafür muss der Browser die
   Zahl als Zahl kennen. Ohne @property steht der Ring wie bisher sofort. */
@property --anteil {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

/* ---------------------------------------------------------- Seitenwechsel */
/* Der Browser zeichnet den Wechsel selbst, wo er das kann (sonst wechselt
   die Seite wie früher ohne Übergang). Die Navigation bleibt stehen, nur
   der Inhalt bewegt sich - und zwar mit Richtung, die das Skript im Kopf
   von base.html ableitet:
     vor           - tiefer hinein: die neue Seite schiebt sich über die
                     ganze Breite von rechts herein, schießt ein wenig über
                     und federt zurück (--kurve-schwung)
     zurueck       - spiegelverkehrt, von links
     reiter-rechts - Tipp auf einen Reiter weiter rechts: der Inhalt gleitet
                     nach links weg, der neue kommt von rechts
     reiter-links  - spiegelverkehrt
     seitwaerts    - alles andere auf gleicher Höhe: nur überblenden
   Das Alte geht dabei schneller, als das Neue kommt. Die neue Seite trägt
   den Seitengrund, damit sie die alte zudeckt, statt durchzuscheinen; die
   Navigation liegt darüber, der Inhalt gleitet unter ihr durch. */

@view-transition { navigation: auto; }
.tabs { view-transition-name: tabs; }
.seitenleiste { view-transition-name: leiste; }
.buehne { view-transition-name: inhalt; }
::view-transition-group(tabs), ::view-transition-group(leiste) { z-index: 1; }

@keyframes seite-rein-rechts  { from { transform: translateX(100%); } }
@keyframes seite-rein-links   { from { transform: translateX(-100%); } }
@keyframes seite-raus-links   { to   { opacity: 0; transform: translateX(-30%); } }
@keyframes seite-raus-rechts  { to   { opacity: 0; transform: translateX(30%); } }
@keyframes reiter-rein-rechts { from { opacity: 0; transform: translateX(50%); } }
@keyframes reiter-rein-links  { from { opacity: 0; transform: translateX(-50%); } }

::view-transition-old(root), ::view-transition-new(root),
::view-transition-old(inhalt), ::view-transition-new(inhalt) { animation-duration: var(--dauer); }
/* Der Inhalt wechselt seine Höhe - die Gruppe soll dabei nicht zerren. */
::view-transition-group(inhalt) { animation-duration: 0s; }

html:active-view-transition-type(vor)::view-transition-new(inhalt),
html:active-view-transition-type(zurueck)::view-transition-new(inhalt) { background: var(--bg); }
html:active-view-transition-type(vor)::view-transition-old(inhalt)     { animation: seite-raus-links var(--dauer-lang) var(--kurve-ab) both; }
html:active-view-transition-type(vor)::view-transition-new(inhalt)     { animation: seite-rein-rechts var(--dauer-auftritt) var(--kurve-schwung) both; }
html:active-view-transition-type(zurueck)::view-transition-old(inhalt) { animation: seite-raus-rechts var(--dauer-lang) var(--kurve-ab) both; }
html:active-view-transition-type(zurueck)::view-transition-new(inhalt) { animation: seite-rein-links var(--dauer-auftritt) var(--kurve-schwung) both; }
html:active-view-transition-type(reiter-rechts)::view-transition-old(inhalt) { animation: seite-raus-links var(--dauer) var(--kurve-ab) both; }
html:active-view-transition-type(reiter-rechts)::view-transition-new(inhalt) { animation: reiter-rein-rechts var(--dauer-lang) var(--kurve) both; }
html:active-view-transition-type(reiter-links)::view-transition-old(inhalt)  { animation: seite-raus-rechts var(--dauer) var(--kurve-ab) both; }
html:active-view-transition-type(reiter-links)::view-transition-new(inhalt)  { animation: reiter-rein-links var(--dauer-lang) var(--kurve) both; }
/* Wachsen: das Foto der Kachel wird zum Foto der Rezeptseite, der übrige
   Inhalt blendet nur über. */
.rezeptseite .kochknopf, .kochmodus { view-transition-name: kochen; }
::view-transition-group(kochen) {
  z-index: 3; overflow: hidden; border-radius: var(--radius-rund);
  animation-duration: var(--dauer-auftritt); animation-timing-function: var(--kurve);
}
::view-transition-group(gericht) {
  z-index: 2; overflow: hidden; border-radius: var(--radius-kachel);
  animation-duration: var(--dauer-auftritt); animation-timing-function: var(--kurve);
}
/* Das Foto wächst hinter dem Rezeptblatt auf, wie es danach auch steht: seine
   Ebene liegt unter der des Inhalts (der an dieser Stelle ein Loch hat). */
html:active-view-transition-type(wachsen)::view-transition-group(gericht) { z-index: 0; }
html:active-view-transition-type(wachsen)::view-transition-group(inhalt)  { z-index: 1; }
html:active-view-transition-type(wachsen)::view-transition-old(inhalt) { animation: ausblenden var(--dauer) var(--kurve-ab) both; }
html:active-view-transition-type(wachsen)::view-transition-new(inhalt) { animation: einblenden var(--dauer-lang) var(--kurve) both; animation-delay: .12s; }
@media (prefers-reduced-motion: reduce) {
  ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; }
}

/* ------------------------------------------------------------ Aufsteigen */

@keyframes aufsteigen {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
@keyframes hereingleiten {
  from { opacity: 0; transform: translateX(-8px); }
  to   { opacity: 1; transform: none; }
}

.stapel > *, .mitte > .karte {
  animation: aufsteigen var(--dauer-auftritt) var(--kurve) both;
  animation-delay: var(--verzug, 0s);
}
/* Ein Kachelplatz ist nur eine Hülle - es steigen seine Teile, nicht er. */
.stapel > .kachelplatz { animation: none; }
.stapel > :nth-child(2)  { --verzug: calc(1 * var(--staffel)); }
.stapel > :nth-child(3)  { --verzug: calc(2 * var(--staffel)); }
.stapel > :nth-child(4)  { --verzug: calc(3 * var(--staffel)); }
.stapel > :nth-child(5)  { --verzug: calc(4 * var(--staffel)); }
.stapel > :nth-child(6)  { --verzug: calc(5 * var(--staffel)); }
.stapel > :nth-child(7)  { --verzug: calc(6 * var(--staffel)); }
.stapel > :nth-child(8)  { --verzug: calc(7 * var(--staffel)); }
.stapel > :nth-child(9)  { --verzug: calc(8 * var(--staffel)); }
.stapel > :nth-child(n+10) { --verzug: calc(9 * var(--staffel)); }

/* Was beim Laden unter dem Bildrand liegt, wartet, bis man hinscrollt
   (app.js setzt data-erscheint und später .im-blick). */
body.mit-bewegung .stapel > [data-erscheint] {
  animation: none;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity var(--dauer-auftritt) var(--kurve), transform var(--dauer-auftritt) var(--kurve);
  transition-delay: var(--verzug, 0s);
}
body.mit-bewegung .stapel > [data-erscheint].im-blick { opacity: 1; transform: none; }

.seitenkopf h1 { animation: hereingleiten var(--dauer-auftritt) var(--kurve) both; animation-delay: .05s; }
.seitenkopf .schulterzeile { animation: aufsteigen var(--dauer-auftritt) var(--kurve) both; animation-delay: .12s; }

/* Listen innerhalb einer Karte staffeln sich leicht nach - erst nach ihrer
   Karte, dann im Takt der Staffel. */
.liste > li, .einkaufsliste > li, .angebotsliste > li, .schrittueberblick > li, .rezeptliste > .gerichtkarte {
  animation: aufsteigen var(--dauer-auftritt) var(--kurve) both;
  animation-delay: calc(var(--verzug, 0s) + 80ms + var(--platz, 0) * var(--staffel));
}
:is(.liste, .einkaufsliste, .angebotsliste, .schrittueberblick) > li:nth-child(2), .rezeptliste > .gerichtkarte:nth-child(2) { --platz: 1; }
:is(.liste, .einkaufsliste, .angebotsliste, .schrittueberblick) > li:nth-child(3), .rezeptliste > .gerichtkarte:nth-child(3) { --platz: 2; }
:is(.liste, .einkaufsliste, .angebotsliste, .schrittueberblick) > li:nth-child(4), .rezeptliste > .gerichtkarte:nth-child(4) { --platz: 3; }
:is(.liste, .einkaufsliste, .angebotsliste, .schrittueberblick) > li:nth-child(n+5), .rezeptliste > .gerichtkarte:nth-child(n+5) { --platz: 4; }
/* Zeilen, die das Skript umhängt, sollen nicht jedes Mal neu aufsteigen. */
.einkaufsliste > li.wandert, #korb-liste > li { animation: none; }
/* Karten, die die Rezeptsuche ein- und ausblendet, ebenso. */
.rezeptliste.gefiltert > .gerichtkarte { animation: none; }
/* Angesprungenes leuchtet auf - das Staffeln oben ist spezifischer als
   .hervorgehoben und würde es sonst verdecken. */
.liste > li.hervorgehoben, .rezeptliste > .gerichtkarte.hervorgehoben { animation: hervorheben-puls 1.6s ease-out; }

/* ----------------------------------------------------------- Piktogramme */

@keyframes zeichnen {
  from { stroke-dashoffset: 1.05; }
  to   { stroke-dashoffset: 0; }
}
@keyframes fuellen { from { opacity: 0; } }

.pikto {
  width: 1.25em; height: 1.25em;
  flex: none;
  vertical-align: -.3em;
  overflow: visible;
}
.pikto * { transform-box: view-box; transform-origin: var(--ox, 12px) var(--oy, 12px); }
.pikto path, .pikto circle, .pikto rect {
  stroke-dasharray: 1 2;
  stroke-dashoffset: 0;
  animation: zeichnen var(--dauer-zeichnen) var(--kurve) both;
  animation-delay: calc(var(--verzug, 0s) + .12s + var(--n, 0) * 60ms);
}
.pikto .flaeche {
  fill: currentColor;
  fill-opacity: .16;
  stroke: none;
  stroke-dasharray: none;
  animation: fuellen var(--dauer-auftritt) ease-out both;
  animation-delay: calc(var(--verzug, 0s) + .5s);
}
.pikto g > path { animation-delay: calc(var(--verzug, 0s) + .12s); }

/* Bewegliche Teile - erst nach dem Zeichnen, damit sich nichts beißt. */
@keyframes dampfen {
  0%   { opacity: 0; transform: translateY(2px) scaleY(.8); }
  35%  { opacity: .9; }
  100% { opacity: 0; transform: translateY(-3.5px) scaleY(1.15); }
}
@keyframes funkeln {
  0%, 100% { opacity: .35; transform: scale(.7); }
  50%      { opacity: 1;   transform: scale(1.12); }
}
@keyframes ticken { to { transform: rotate(360deg); } }
@keyframes wehen {
  0%, 100% { transform: rotate(0deg); }
  50%      { transform: rotate(-9deg); }
}
@keyframes flackern {
  0%, 100% { transform: scale(1) translateY(0); opacity: .9; }
  50%      { transform: scale(1.12, .9) translateY(.6px); opacity: 1; }
}
@keyframes strahlen { to { transform: rotate(45deg); } }
@keyframes blaettern {
  0%, 100% { transform: scaleX(1); }
  50%      { transform: scaleX(.86); }
}
/* Punkte, die tippen: im Chat 4px, im Piktogramm 1.5 Einheiten (--hub). */
@keyframes tippen {
  0%, 60%, 100% { transform: translateY(0); opacity: .5; }
  30%           { transform: translateY(calc(-1 * var(--hub, 4px))); opacity: 1; }
}
@keyframes schweben {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-4px); }
}
@keyframes schlagen {
  0%, 100% { transform: scale(1); }
  14%      { transform: scale(1.12); }
  28%      { transform: scale(1); }
  42%      { transform: scale(1.08); }
}
@keyframes wackeln {
  0%, 100% { transform: rotate(0deg); }
  25%      { transform: rotate(-6deg); }
  75%      { transform: rotate(6deg); }
}
@keyframes wippen {
  0%, 100% { transform: rotate(0deg); }
  30%      { transform: rotate(-5deg) translateY(-1px); }
  70%      { transform: rotate(4deg); }
}
@keyframes nicken {
  0%, 100% { transform: translateY(0); }
  40%      { transform: translateY(1.5px); }
}
@keyframes blitzen {
  0%, 100% { opacity: 1; }
  20%      { opacity: .35; }
  40%      { opacity: 1; }
}

/* Dauerhaft lebendig sind nur Dampf und Funken - und nur da, wo das
   Zeichen als "lebt" markiert ist (Leerzustände, Warteschirm, Kochstart,
   aktive Kacheln), nicht in jeder Überschrift. */
.lebt .dampf, .pikto.lebt .dampf {
  animation: zeichnen var(--dauer-zeichnen) var(--kurve) both, dampfen 3.2s ease-in-out infinite;
  animation-delay: calc(var(--verzug, 0s) + .12s), calc(.6s + var(--n, 0) * 1.05s);
}
.lebt .funke, .pikto.lebt .funke {
  animation: zeichnen var(--dauer-zeichnen) var(--kurve) both, funkeln 2.4s ease-in-out infinite;
  animation-delay: calc(var(--verzug, 0s) + .12s + var(--n, 0) * 60ms), calc(.7s + var(--n, 0) * .8s);
}
.lebt .zeiger, .pikto.lebt .zeiger {
  animation: zeichnen var(--dauer-zeichnen) var(--kurve) both, ticken 6s steps(12) infinite;
  animation-delay: calc(var(--verzug, 0s) + .12s), .9s;
}
.lebt .flackert, .pikto.lebt .flackert {
  animation: zeichnen var(--dauer-zeichnen) var(--kurve) both, flackern 1.6s ease-in-out infinite;
  animation-delay: calc(var(--verzug, 0s) + .12s), .9s;
}
.lebt .strahlen, .pikto.lebt .strahlen { animation: strahlen 8s linear infinite; }
.lebt .sprechblase .punkt, .pikto.lebt.pikto-sprechblase .punkt {
  --hub: 1.5px;
  animation: zeichnen var(--dauer-zeichnen) var(--kurve) both, tippen 1.2s ease-in-out infinite;
  animation-delay: calc(var(--verzug, 0s) + .12s), calc(.8s + var(--n, 0) * .2s);
}
/* Blätter wehen und Seiten blättern beim Anfassen. */
@media (hover: hover) {
  :hover > .pikto .blatt, .pikto:hover .blatt { animation: wehen 1.2s ease-in-out; animation-delay: calc(var(--n, 0) * .15s); }
  :hover > .pikto .seite, .pikto:hover .seite { animation: blaettern var(--dauer-zeichnen) ease-in-out; animation-delay: calc(var(--n, 0) * .12s); }
  :hover > .pikto-moehre, .pikto-moehre:hover { animation: wackeln var(--dauer-zeichnen) ease-in-out; }
}

/* ------------------------------------------------------ Abschnittszeichen */

.abschnittkopf h2, .abschnittkopf h3,
h1:has(> .abschnittzeichen), h2:has(> .abschnittzeichen), h3:has(> .abschnittzeichen) { display: flex; align-items: center; gap: 10px; min-width: 0; }
.abschnitttext { display: flex; flex-direction: column; min-width: 0; line-height: 1.2; }
.abschnittunter { font-weight: 500; letter-spacing: 0; margin-top: 2px; }
.abschnittrechts { display: flex; align-items: center; gap: 8px; flex: none; }
.nur-vorleser { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.abschnittzeichen {
  flex: none;
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border-radius: 11px;
  animation: federn var(--dauer-feder) var(--kurve-feder) both;
  animation-delay: calc(var(--verzug, 0s) + .06s);
}
.abschnittzeichen .pikto { width: 20px; height: 20px; }
h3 .abschnittzeichen { width: 28px; height: 28px; border-radius: 9px; }
h3 .abschnittzeichen .pikto { width: 17px; height: 17px; }

/* Töne für Zeichen - passen zur Palette hell wie dunkel. */
.ton-gruen { background: var(--primaer-hell); color: var(--primaer-dunkel); }
.ton-gelb  { background: var(--akzent-hell);  color: var(--gelb); }
.ton-blau  { background: var(--blau-hell);    color: var(--blau-text); }
.ton-rosa  { background: var(--ton-3);        color: #8f3a56; }
.ton-sand  { background: var(--ton-4);        color: #7a5a1e; }
.ton-grau  { background: var(--flaeche-3);    color: var(--text-2); }
.ton-mint     { background: #dff2ec; color: #1f6b5a; }
.ton-lavendel { background: #e9e4f6; color: #5a4a8f; }
.ton-pfirsich { background: #fbe6d8; color: #9a4f22; }
.ton-rot      { background: var(--rot-hell); color: #a1352e; }
:where(:root[data-theme="dark"]) .ton-gelb     { color: #f0c98a; }
:where(:root[data-theme="dark"]) .ton-blau     { color: #b9cdf0; }
:where(:root[data-theme="dark"]) .ton-rosa     { color: #f0b3c6; }
:where(:root[data-theme="dark"]) .ton-sand     { color: #e6c98a; }
:where(:root[data-theme="dark"]) .ton-mint     { background: #1c352e; color: #8fd4bf; }
:where(:root[data-theme="dark"]) .ton-lavendel { background: #2b2640; color: #c2b4f0; }
:where(:root[data-theme="dark"]) .ton-pfirsich { background: #3b2718; color: #f0b088; }
:where(:root[data-theme="dark"]) .ton-rot      { color: #f0a9a4; }
@media (prefers-color-scheme: dark) {
  :where(:root:not([data-theme="light"])) .ton-gelb     { color: #f0c98a; }
  :where(:root:not([data-theme="light"])) .ton-blau     { color: #b9cdf0; }
  :where(:root:not([data-theme="light"])) .ton-rosa     { color: #f0b3c6; }
  :where(:root:not([data-theme="light"])) .ton-sand     { color: #e6c98a; }
  :where(:root:not([data-theme="light"])) .ton-mint     { background: #1c352e; color: #8fd4bf; }
  :where(:root:not([data-theme="light"])) .ton-lavendel { background: #2b2640; color: #c2b4f0; }
  :where(:root:not([data-theme="light"])) .ton-pfirsich { background: #3b2718; color: #f0b088; }
  :where(:root:not([data-theme="light"])) .ton-rot      { color: #f0a9a4; }
}

/* Gerichtzeichen in Listen: Farbe und Zeichen sagen, was auf den Teller
   kommt. Beim Erscheinen malen sie sich und leben kurz auf - Dampf steigt
   zweimal, Punkte ploppen - danach ist Ruhe, bis man die Zeile berührt. */
.gerichtkarte-zeichen .dampf {
  animation: zeichnen var(--dauer-zeichnen) var(--kurve) both, dampfen 3s ease-in-out 2;
  animation-delay: calc(var(--verzug, 0s) + .12s), calc(var(--verzug, 0s) + .8s + var(--n, 0) * .9s);
}
.gerichtkarte-zeichen .funke {
  animation: zeichnen var(--dauer-zeichnen) var(--kurve) both, funkeln 2.2s ease-in-out 2;
  animation-delay: calc(var(--verzug, 0s) + .12s), calc(var(--verzug, 0s) + .8s + var(--n, 0) * .6s);
}
.gerichtkarte-zeichen .blatt {
  animation: zeichnen var(--dauer-zeichnen) var(--kurve) both, wehen 1.6s ease-in-out 2;
  animation-delay: calc(var(--verzug, 0s) + .12s + var(--n, 0) * 60ms), calc(var(--verzug, 0s) + .9s + var(--n, 0) * .2s);
}
.gerichtkarte-zeichen .punkt {
  animation: zeichnen var(--dauer-zeichnen) var(--kurve) both, federn var(--dauer-feder) var(--kurve-feder);
  animation-delay: calc(var(--verzug, 0s) + .12s + var(--n, 0) * 60ms), calc(var(--verzug, 0s) + .7s + var(--n, 0) * .15s);
}
.gerichtkarte-zeichen .seite {
  animation: zeichnen var(--dauer-zeichnen) var(--kurve) both, blaettern 1.2s ease-in-out 1;
  animation-delay: calc(var(--verzug, 0s) + .12s), calc(var(--verzug, 0s) + .9s + var(--n, 0) * .15s);
}
@media (hover: hover) {
  .gerichtkarte-link:hover .gerichtkarte-zeichen .dampf, a.karte:hover .gerichtkarte-zeichen .dampf { animation: dampfen 3s ease-in-out infinite; animation-delay: calc(var(--n, 0) * -.9s); }
  .gerichtkarte-link:hover .gerichtkarte-zeichen .funke { animation: funkeln 2.2s ease-in-out infinite; animation-delay: calc(var(--n, 0) * .6s); }
  .gerichtkarte-link:hover .gerichtkarte-zeichen .blatt { animation: wehen 1.6s ease-in-out infinite; animation-delay: calc(var(--n, 0) * .2s); }
  .gerichtkarte-link:hover .gerichtkarte-zeichen .punkt { animation: federn var(--dauer-feder) var(--kurve-feder); animation-delay: calc(var(--n, 0) * .12s); }
  .gerichtkarte-link:hover .gerichtkarte-zeichen .seite { animation: blaettern 1.2s ease-in-out infinite; animation-delay: calc(var(--n, 0) * .15s); }
}
.gerichtkarte-zeichen .pikto { transition: transform var(--dauer-lang) var(--kurve); }
.gerichtkarte-link:hover .gerichtkarte-zeichen .pikto, a.karte:hover .gerichtkarte-zeichen .pikto { transform: scale(1.08); }

/* Dampf über den Fotos warmer Gerichte: drei Schwaden steigen versetzt
   und ohne Ende auf, jede wiegt sich dabei leicht zur Seite. Ohne
   Bewegung (reduced-motion, update: slow) bleibt der Dampf unsichtbar -
   eine stehende Schwade sähe wie ein Kratzer im Foto aus. */
@keyframes schwaden {
  0%   { opacity: 0;   transform: translate(0, 10px) scale(.85, .7); }
  30%  { opacity: .85; }
  60%  { transform: translate(-2px, -4px) scale(1, 1); }
  100% { opacity: 0;   transform: translate(2px, -16px) scale(1.15, 1.2); }
}
.dampfschwaden .schwade {
  opacity: 0;
  transform-box: fill-box; transform-origin: 50% 100%;
  animation: schwaden 3.6s ease-in-out infinite;
  animation-delay: calc(var(--n, 0) * -1.2s);
}

/* Kacheln mit Zeichen (Plankopf) und Tageskarten im Plan. */
.kachel.mit-zeichen { flex-direction: row; align-items: center; gap: 10px; }
.kachel.mit-zeichen .wert { white-space: nowrap; }
.kachel.mit-zeichen.rechts { justify-content: flex-end; text-align: right; }
.kacheltext { display: flex; flex-direction: column; min-width: 0; }
.abschnitt-titel h2 { display: flex; align-items: center; gap: 10px; }
.einstellung-inhalt .abschnittkopf { margin: 16px 0 8px; }
.einstellung-inhalt .abschnittkopf:first-child, .einstellung-inhalt > div:first-child > .abschnittkopf:first-child { margin-top: 0; }
.einstellung-inhalt .abschnittzeichen { width: 28px; height: 28px; border-radius: 9px; }
.einstellung-inhalt .abschnittzeichen .pikto { width: 17px; height: 17px; }
.karte .abschnittkopf + .chipreihe, .karte .abschnittkopf + .zaehler { margin-top: 2px; }

/* Zeilenzeichen (Einstellungen, Links) bekommen dieselbe Bewegung. */
.zeilenzeichen .pikto { width: 20px; height: 20px; }
.chip.chip-icon .pikto, .chip.chip-icon .ikon { width: 20px; height: 20px; }
.einstellung[open] > summary .zeilenzeichen { animation: federn var(--dauer-feder) var(--kurve-feder); }
.einstellung > summary .zeilenzeichen { transition: background var(--dauer), color var(--dauer); }
.leer-zeichen .pikto { width: 32px; height: 32px; }
.leer-zeichen { animation: schweben 5s ease-in-out infinite; animation-delay: .8s; }
.marke-zeichen .pikto { width: 20px; height: 20px; }
.gerichtkarte-zeichen .pikto { width: 26px; height: 26px; }
.rezeptzeichen .pikto { width: 88px; height: 88px; opacity: .8; }

/* ----------------------------------------------------------------- Federn */

@keyframes federn {
  0%   { transform: scale(.92); }
  60%  { transform: scale(1.05); }
  100% { transform: scale(1); }
}
@keyframes federn-klein {
  0%   { transform: scale(.96); }
  60%  { transform: scale(1.03); }
  100% { transform: scale(1); }
}
@keyframes zahlwechsel {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
@keyframes wachsen { from { transform: scaleX(0); } }
@keyframes ringfuellen { from { --anteil: 0; } }
@keyframes haken-zeichnen { from { stroke-dashoffset: 1.05; } to { stroke-dashoffset: 0; } }
@keyframes schalter-federn {
  0%   { transform: translateX(var(--x, 0)) scaleX(1); }
  45%  { transform: translateX(var(--x, 0)) scaleX(1.18); }
  100% { transform: translateX(var(--x, 0)) scaleX(1); }
}
@keyframes glanz { from { transform: translateX(-120%) skewX(-18deg); } to { transform: translateX(220%) skewX(-18deg); } }

/* Kopfschütteln: "Das ging nicht." Drei kurze Ausschläge - der Rhythmus
   ist Teil der Form, deshalb eine eigene Dauer. Eine Fehlermeldung kommt
   herein und schüttelt dann den Kopf; ein abgelehntes Feld oder ein Knopf,
   dessen Absenden scheiterte, schüttelt allein (app.js: schuetteln). */
@keyframes kopfschuetteln {
  0%, 100% { transform: translateX(0); }
  20%, 60% { transform: translateX(-4px); }
  40%, 80% { transform: translateX(4px); }
}
.meldung:not(.gut):not(.hinweis) {
  animation: aufsteigen var(--dauer-lang) var(--kurve), kopfschuetteln .4s ease-in-out var(--dauer-lang);
}
.schuettelt { animation: kopfschuetteln .4s ease-in-out !important; }

/* Nach einer Aktion ohne Neuladen federt die Stelle, an der sich etwas
   getan hat (app.js: gegenstueckFedern). */
.federt { animation: federn var(--dauer-feder) var(--kurve-feder) !important; }

/* Chips federn beim Auswählen. */
.chip[aria-pressed="true"] { animation: federn-klein var(--dauer-feder) var(--kurve-feder); }

/* Der Haken malt sein Häkchen, statt nur zu erscheinen. */
.haken .ikon path { stroke-dasharray: 1 2; stroke-dashoffset: 1.05; }
.hakenzeile input:checked ~ .haken { animation: federn var(--dauer-feder) var(--kurve-feder); }
.hakenzeile input:checked ~ .haken .ikon path { animation: haken-zeichnen var(--dauer-lang) var(--kurve) .05s both; }
.hakentext { transition: opacity var(--dauer), transform var(--dauer-lang) var(--kurve); }
.hakenzeile.erledigt .hakentext { transform: translateX(2px); }

/* Der Schalter drückt sich beim Umlegen kurz breit. */
.schalter input:checked + .schalterknopf::after { --x: 20px; animation: schalter-federn var(--dauer-lang) var(--kurve); }

/* Zähler: die neue Zahl rutscht von unten nach. */
.zaehler output.wechselt, .zaehler input.wechselt { animation: zahlwechsel var(--dauer-lang) var(--kurve); }

/* Balken wachsen beim Laden, der Ring füllt sich. */
.balken i { transform-origin: left; animation: wachsen var(--dauer-zeichnen) var(--kurve) both; animation-delay: calc(var(--verzug, 0s) + .2s); }
.ring { animation: ringfuellen var(--dauer-zeichnen) var(--kurve) both; animation-delay: calc(var(--verzug, 0s) + .15s); transition: --anteil var(--dauer-zeichnen) var(--kurve); }
.ring .ringzahl { animation: aufsteigen var(--dauer-auftritt) var(--kurve) both; animation-delay: calc(var(--verzug, 0s) + .3s); }
.kachel .wert { animation: zahlwechsel var(--dauer-lang) var(--kurve) both; animation-delay: calc(var(--verzug, 0s) + .25s); }

/* Tabs: das aktive Symbol federt, jedes auf seine Art. */
.tab .pikto { width: 24px; height: 24px; padding: 3px 0; transition: transform var(--dauer-lang) var(--kurve); }
.tab.aktiv .pikto { transform: translateY(-1px); animation: federn var(--dauer-feder) var(--kurve-feder); }
.tab.aktiv .pikto-blitz { animation: federn var(--dauer-feder) var(--kurve-feder), blitzen var(--dauer-zeichnen) ease-out .3s; }
.tab.aktiv .pikto-korb { animation: wippen var(--dauer-zeichnen) ease-in-out; }
.tab.aktiv .pikto-buch .seite { animation: blaettern var(--dauer-zeichnen) ease-in-out .2s; animation-delay: calc(.2s + var(--n, 0) * .12s); }
.tab.aktiv .pikto-person { animation: nicken var(--dauer-zeichnen) ease-in-out; }
.tab.aktiv .pikto-kalender .strich { animation: haken-zeichnen var(--dauer-lang) var(--kurve) .3s both; }
.tab .pikto .punkt, .tab .pikto .strich { animation-delay: calc(var(--n, 0) * 50ms); }
.tab:active .pikto, .tab:active .ikon { transform: scale(var(--druck-klein)); }
.navpunkt .pikto { width: 20px; height: 20px; }
.navpunkt.aktiv .pikto { animation: federn var(--dauer-feder) var(--kurve-feder); }
.marke:hover .marke-zeichen { animation: federn var(--dauer-feder) var(--kurve-feder); }

/* Knöpfe: das Symbol im Knopf nickt in seine Richtung. */
.knopf .ikon, .kochstart > .ikon, .zurueck .ikon, .gerichtpfeil .ikon {
  transition: transform var(--dauer-lang) var(--kurve);
}
@media (hover: hover) {
  .knopf:hover [data-ikon="arrow-right"], .knopf:hover [data-ikon="chevron-right"], .kochstart:hover > [data-ikon="chevron-right"],
  a.karte:hover .gerichtpfeil .ikon, .gerichtkarte-link:hover .gerichtpfeil .ikon { transform: translateX(3px); }
  .knopf:hover [data-ikon="arrow-left"], .knopf:hover [data-ikon="chevron-left"], .zurueck:hover .ikon { transform: translateX(-3px); }
  .knopf:hover [data-ikon="refresh-cw"], .knopf:hover [data-ikon="rotate-ccw"], .zeileweg:hover [data-ikon="refresh-cw"], .rundknopf:hover [data-ikon="refresh-cw"], .rundknopf:hover [data-ikon="rotate-ccw"] { transform: rotate(-50deg); }
  .knopf:hover [data-ikon="plus"] { transform: rotate(90deg); }
  .knopf:hover [data-ikon="x"] { transform: rotate(90deg); }
  .knopf:hover [data-ikon="send"] { transform: translate(2px, -2px); }
  .knopf:hover [data-ikon="sparkles"], .knopf:hover [data-ikon="wand-sparkles"] { animation: funkeln 1s ease-in-out infinite; }
  .knopf:hover [data-ikon="chef-hat"], .knopf:hover [data-ikon="cooking-pot"] { transform: translateY(-2px); }
  .knopf:hover [data-ikon="shopping-basket"], .knopf:hover [data-ikon="shopping-cart"] { animation: wippen var(--dauer-zeichnen) ease-in-out; }
  .knopf:hover [data-ikon="check"], .knopf:hover [data-ikon="circle-check"] { transform: scale(1.15); }
  .knopf:hover [data-ikon="copy"], .knopf:hover [data-ikon="share-2"] { transform: translateY(-2px); }
  .knopf:hover [data-ikon="map-pin"] { animation: nicken var(--dauer-zeichnen) ease-in-out; }
  .knopf:hover [data-ikon="log-out"] { transform: translateX(2px); }
  .knopf:hover [data-ikon="pencil"] { transform: rotate(-12deg); }
  .knopf:hover [data-ikon="trash"] { animation: wackeln var(--dauer-zeichnen) ease-in-out; }
  .zeileweg:hover [data-ikon="x"] { transform: rotate(90deg); }
  .zeileweg .ikon { transition: transform var(--dauer-lang) var(--kurve); }
}
.knopf:active .ikon { transform: scale(var(--druck-klein)); }

/* Meldungen: das Zeichen federt herein, der Text folgt. */
.meldung .pikto { width: 20px; height: 20px; margin-top: 2px; animation: federn var(--dauer-feder) var(--kurve-feder) both; animation-delay: .1s; }

/* Der große Kochstart: die Mütze wippt, beim Berühren läuft ein Glanz durch. */
.kochstart { position: relative; overflow: hidden; }
.kochstart-zeichen { animation: schweben 4s ease-in-out infinite; animation-delay: 1s; }
.kochstart-zeichen .pikto { width: 26px; height: 26px; }
.kochstart::after {
  content: "";
  position: absolute; top: 0; bottom: 0; left: 0; width: 40%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .18), transparent);
  transform: translateX(-120%) skewX(-18deg);
  pointer-events: none;
}
@media (hover: hover) { .kochstart:hover::after { animation: glanz var(--dauer-zeichnen) var(--kurve); } }

/* Toast bringt ein kleines Zeichen mit: Haken, i oder Ausrufezeichen. */
.toast .pikto { width: 18px; height: 18px; }

/* Kacheln im Inhalt treten auf wie eine Karte - auch dort, wo sie nicht
   in einem Stapel stehen (ein einzelnes Gericht im Plan). Die Leiste
   kommt wie ein Toast, geht mit .geht zur unteren Kante zurück; solange
   der Auftrag läuft, dreht ihr Kreisel. Fertig federt sie, gescheitert
   schüttelt sie den Kopf (app.js: leisteStellen). */
.kachelbau { animation: aufsteigen var(--dauer-auftritt) var(--kurve) both; }
.auftragsleiste { animation: aufsteigen var(--dauer-lang) var(--kurve); }
.auftragsleiste .pikto .kreisel { stroke-dasharray: none; animation: none; }
.auftragsleiste[data-zustand="laeuft"] .pikto.lebt { animation: drehen 1s linear infinite; }

/* --------------------------------------------------------- Warteschirm */
/* Ein großes Zeichen, das lebt, und eine Zeile Text. Kein Deckkraft-Start
   bei null - Safari friert Animationen nach dem Absenden ein. */

@keyframes blubbern {
  0%, 100% { transform: translateY(0) scale(1); opacity: .7; }
  50%      { transform: translateY(-2px) scale(1.25); opacity: 1; }
}
.warteschirm { gap: 14px; }
.warteschirm .wartezeichen {
  width: 148px; height: 148px;
  display: grid; place-items: center;
  border-radius: 44px;
  background: var(--primaer-hell); color: var(--primaer-dunkel);
  animation: schweben 4s ease-in-out infinite;
}
.warteschirm .wartezeichen .pikto { width: 84px; height: 84px; }
/* Jedes Zeichen bewegt sich - mindestens seine Kontur: eine kleine Lücke
   läuft ohne Ende den Strich entlang. Teile mit eigener Bewegung (Dampf,
   Funken, Blätter …) laufen ihre Schleife obendrauf. */
@keyframes konturlauf { to { stroke-dashoffset: -1; } }
.warteschirm .wartezeichen .pikto path, .warteschirm .wartezeichen .pikto circle, .warteschirm .wartezeichen .pikto rect {
  stroke-dasharray: .86 .14;
  stroke-dashoffset: 0;
  animation: konturlauf 3.2s linear infinite;
  animation-delay: calc(var(--n, 0) * -.4s);
}
.warteschirm .wartezeichen .pikto .flaeche { animation: none; stroke-dasharray: none; }
.warteschirm .wartezeichen .pikto .dampf { stroke-dasharray: none; animation: dampfen 2.6s ease-in-out infinite; animation-delay: calc(var(--n, 0) * -.85s); }
.warteschirm .wartezeichen .pikto .blase { stroke-dasharray: none; animation: blubbern 1.4s ease-in-out infinite; animation-delay: calc(var(--n, 0) * -.45s); }
.warteschirm .wartezeichen .pikto .funke { stroke-dasharray: none; animation: funkeln 2s ease-in-out infinite; animation-delay: calc(var(--n, 0) * .65s); }
.warteschirm .wartezeichen .pikto .punkt { stroke-dasharray: none; animation: funkeln 2.4s ease-in-out infinite; animation-delay: calc(var(--n, 0) * .4s); }
.warteschirm .wartezeichen .pikto .strich { stroke-dasharray: 1 2; animation: haken-zeichnen 2.4s var(--kurve) infinite; }
.warteschirm .wartezeichen .pikto .blatt { stroke-dasharray: none; animation: wehen 1.8s ease-in-out infinite; animation-delay: calc(var(--n, 0) * .3s); }
.warteschirm .wartezeichen .pikto .seite { stroke-dasharray: none; animation: blaettern 1.4s ease-in-out infinite; animation-delay: calc(var(--n, 0) * .2s); }
.warteschirm .wartezeichen .pikto .zeiger { stroke-dasharray: none; animation: ticken 6s steps(12) infinite; }
.warteschirm .wartezeichen .pikto .flackert { stroke-dasharray: none; animation: flackern 1.4s ease-in-out infinite; }
.warteschirm .wartezeichen .pikto .strahlen { animation: strahlen 8s linear infinite; }
.warteschirm .wartezeichen .pikto-moehre, .warteschirm .wartezeichen .pikto-kaese, .warteschirm .wartezeichen .pikto-brot { animation: wackeln 2.4s ease-in-out infinite; }
.warteschirm .wartezeichen .pikto-sprechblase .punkt { --hub: 1.5px; animation: tippen 1.2s ease-in-out infinite; animation-delay: calc(var(--n, 0) * .2s); }
.warteschirm h2 { font-size: 1.35rem; margin-top: 6px; }
.warteschliessen {
  position: absolute;
  top: max(14px, env(safe-area-inset-top)); right: 14px;
  width: 44px; height: 44px;
  border: 0; border-radius: 50%;
  background: var(--flaeche-3); color: var(--text-2);
  display: grid; place-items: center;
  cursor: pointer;
  animation: federn var(--dauer-feder) var(--kurve-feder) both;
  animation-delay: .4s;
}
.warteschliessen .ikon { width: 20px; height: 20px; transition: transform var(--dauer-lang) var(--kurve); }
.warteschliessen:hover { background: var(--linie); color: var(--text); }
.warteschliessen:hover .ikon { transform: rotate(90deg); }
.warteschirm.gescheitert .wartezeichen { background: var(--rot-hell); color: var(--rot); animation: none; }
.warteschirm.gescheitert .wartezeichen .pikto path, .warteschirm.gescheitert .wartezeichen .pikto circle { animation: none; stroke-dasharray: none; }
.warteschirm.gescheitert .wartezeichen .pikto .punkt { animation: funkeln 1.6s ease-in-out infinite; }
.warteschirm .warteknoepfe { justify-content: center; margin-top: 8px; animation: aufsteigen var(--dauer-auftritt) var(--kurve); }
.warteschirm .wartezeit { font-variant-numeric: tabular-nums; color: var(--text-3); min-height: 0; }
.warteschirm .wartehinweis { max-width: 34ch; margin-top: 6px; animation: aufsteigen var(--dauer-auftritt) var(--kurve); }

/* ------------------------------------------------------------ Kochmodus */

/* backwards statt both: danach darf das Eindrücken (:active) wieder greifen. */
.kochbild.aktiv > * { animation: aufsteigen var(--dauer-auftritt) var(--kurve) backwards; }
.kochbild.aktiv > :nth-child(2) { animation-delay: .06s; }
.kochbild.aktiv > :nth-child(3) { animation-delay: .12s; }
.kochbild.aktiv > :nth-child(4) { animation-delay: .18s; }
.kochbild.aktiv > :nth-child(n+5) { animation-delay: .24s; }
.kochbild.aktiv .kochnummer { animation: federn var(--dauer-feder) var(--kurve-feder) both; }
.kochnummer.fertigzeichen .pikto { width: 28px; height: 28px; }
.kochbild.aktiv .kochnummer.fertigzeichen .pikto path { animation: zeichnen var(--dauer-zeichnen) var(--kurve) both; animation-delay: .3s; }
/* Uhr-Kachel: der Ring zeichnet sich mit der Restzeit (stroke-dashoffset),
   beim Zurücksetzen malt er sich neu; ist die Zeit um, wackelt das Zeichen. */
.uk-rest { transition: stroke-dashoffset var(--dauer-zeichnen) var(--kurve); }
.uhrkachel.fertig .uk-ring .ikon { animation: wackeln .7s ease-in-out infinite; }
@keyframes blase-auf { from { opacity: 0; transform: translateY(-6px) scale(.97); } }
.timerchip .pikto { width: 16px; height: 16px; }
.timerchip:not(.fertig) .zeiger { animation: ticken 6s steps(12) infinite; }
.schrittnr, .schrittzahl { animation: federn var(--dauer-feder) var(--kurve-feder) both; animation-delay: calc(var(--verzug, 0s) + .15s); }

/* Das Vorgangszeichen im Koch-Wizard: groß, farbig, mit der Schrittzahl in
   der Ecke. Seine Teile laufen in Schleife - aber nur auf dem Bild, das
   gerade vorn ist, die anderen warten still. */
.kochbild > .kochzeichen { width: 76px; }
.kochzeichen {
  position: relative;
  width: 76px; height: 76px;
  display: grid; place-items: center;
  border-radius: 24px;
}
.kochzeichen .pikto { width: 42px; height: 42px; }
.kochzeichen .kochnummer {
  position: absolute; right: -8px; bottom: -8px;
  width: 30px; height: 30px;
  font-size: .9rem;
  border: 3px solid var(--bg);
}
.kochbild.aktiv .kochzeichen { animation: federn var(--dauer-feder) var(--kurve-feder) both; }
.schrittvorgang {
  flex: none; width: 24px; height: 24px; margin-top: 1px;
  display: grid; place-items: center;
  border-radius: 7px;
}
.schrittvorgang .pikto { width: 15px; height: 15px; }
.schrittueberblick > li { gap: 8px; }

/* Die Schleifen der Vorgangszeichen. */
@keyframes hackt {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  40%      { transform: translateY(-3px) rotate(-4deg); }
  55%      { transform: translateY(.5px) rotate(1deg); }
}
@keyframes ruehrt {
  0%, 100% { transform: rotate(-22deg); }
  50%      { transform: rotate(22deg); }
}
@keyframes tropft {
  0%   { transform: translateY(-2px); opacity: 0; }
  30%  { opacity: 1; }
  100% { transform: translateY(5px); opacity: 0; }
}
@keyframes kippt {
  0%, 100% { transform: rotate(-8deg); }
  50%      { transform: rotate(8deg); }
}
@keyframes pulst {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.12, .94); }
}
.kochbild.aktiv .kochzeichen .hebt       { animation: hackt .9s ease-in-out infinite; }
.kochbild.aktiv .kochzeichen .dreht      { animation: ticken 1.6s linear infinite; }
.kochbild.aktiv .kochzeichen .kreist     { animation: ruehrt 1.6s ease-in-out infinite; }
.kochbild.aktiv .kochzeichen .tropft     { animation: tropft 1.5s ease-in infinite; animation-delay: calc(var(--n, 0) * .45s); }
.kochbild.aktiv .kochzeichen .schuettelt { animation: wackeln .7s ease-in-out infinite; }
.kochbild.aktiv .kochzeichen .kippt      { animation: kippt 2.2s ease-in-out infinite; }
.kochbild.aktiv .kochzeichen .pulst      { animation: pulst 1.6s ease-in-out infinite; animation-delay: calc(var(--n, 0) * .2s); }
.kochbild.aktiv .kochzeichen .dampf      { animation: dampfen 3s ease-in-out infinite; animation-delay: calc(var(--n, 0) * -.95s); }
.kochbild.aktiv .kochzeichen .funke      { animation: funkeln 2.2s ease-in-out infinite; animation-delay: calc(var(--n, 0) * .7s); }
.kochbild.aktiv .kochzeichen .flackert   { animation: flackern 1.4s ease-in-out infinite; }
.kochbild.aktiv .kochzeichen .zeiger     { animation: ticken 6s steps(12) infinite; }
.kochbild.aktiv .kochzeichen .blatt      { animation: wehen 1.8s ease-in-out infinite; animation-delay: calc(var(--n, 0) * .3s); }
.kochbild.aktiv .kochzeichen .punkt      { animation: funkeln 2.4s ease-in-out infinite; animation-delay: calc(var(--n, 0) * .5s); }
.kochbild.aktiv .kochzeichen .strahlen   { animation: strahlen 8s linear infinite; }
.kochbild.aktiv .kochzeichen .blase, .lebt .blase { animation: blubbern 1.4s ease-in-out infinite; animation-delay: calc(var(--n, 0) * -.45s); }
.kochbild.aktiv .kochzeichen .pikto-gewuerz, .kochbild.aktiv .kochzeichen .pikto-schneeflocke { animation: wackeln 1.4s ease-in-out infinite; }
.kochbild.aktiv .kochzeichen .pikto-waage .punkt { animation: hackt 2s ease-in-out infinite; animation-delay: calc(var(--n, 0) * 1s); }
@media (update: slow) { .kochbild.aktiv .kochzeichen * { animation: none !important; } }

/* Der Fragebogen: das Piktogramm des Schritts zeichnet sich bei jedem Wechsel neu. */
.schritt.sichtbar .abschnittzeichen { animation: federn var(--dauer-feder) var(--kurve-feder) both; }
.schritt.sichtbar .pikto path { animation: zeichnen var(--dauer-zeichnen) var(--kurve) both; animation-delay: calc(.1s + var(--n, 0) * 60ms); }

/* Gemerkt-Knopf am Rezept und Bewertungsherz. */
.merkknopf.an .ikon { animation: federn var(--dauer-feder) var(--kurve-feder); }
.bewertungsreihe .chip.stufe-3[aria-pressed="true"] .ikon { animation: schlagen 1.2s ease-in-out .2s; }
.bewertungsreihe .chip.stufe-2[aria-pressed="true"] .ikon { animation: wippen var(--dauer-zeichnen) ease-in-out .1s; }
.bewertungsreihe .chip.stufe-1[aria-pressed="true"] .ikon { animation: nicken var(--dauer-zeichnen) ease-in-out .1s; }
.bewertungsreihe .chip .ikon { transition: transform var(--dauer-lang) var(--kurve); }
.bewertungsreihe .chip:hover .ikon { transform: scale(1.1); }

/* Regalkarten auf der Einkaufsliste blenden weich aus, wenn sie leer werden. */
.regal { transition: opacity var(--dauer-lang); }

/* ----------------------------------------------------------------- Ziehen */
/* Ein Gericht im Plan auf einen anderen Tag legen (verschieben.js). Der
   Finger liegt --dauer-halten, dann hebt sich die Karte: Eine Kopie
   (.zieht) folgt dem Finger über `translate` - ohne Übergang, sie klebt am
   Finger -, während `scale` sie einmal um den Finger herum handlich klein
   macht, damit die Tage darunter zu sehen bleiben. Ihr alter Platz bleibt blass
   stehen (.gezogen). Mögliche Tage tragen .ablage, der unter dem Finger
   .ablage-ziel; die anderen treten zurück. Daneben losgelassen gleitet die
   Kopie heim (.heimwaerts), über einem Tag tritt sie ab (.geht) und das
   Gericht federt am neuen Platz. */

@keyframes anheben { from { scale: 1; } }

.gerichtkarte[data-platz], .kachel[data-platz] { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.gerichtkarte.zieht, .kachel.gericht.zieht, .mahlzeitwahl.zieht {
  position: fixed; z-index: 75; margin: 0;
  pointer-events: none;
  scale: .6;
  box-shadow: var(--schatten-hoch);
  animation: anheben var(--dauer-lang) var(--kurve);
}
.gerichtkarte.zieht.heimwaerts, .kachel.gericht.zieht.heimwaerts, .mahlzeitwahl.zieht.heimwaerts {
  scale: 1;
  transition: translate var(--dauer-lang) var(--kurve), scale var(--dauer-lang) var(--kurve);
}
.gerichtkarte.gezogen, .kachel.gericht.gezogen, .mahlzeitwahl.gezogen { opacity: .35; transition: opacity var(--dauer) var(--kurve); }
.plan-zieht, .kachel-zieht { cursor: grabbing; -webkit-user-select: none; user-select: none; }
.plan-zieht .tagkarte:not(.ablage):not(.ablage-quelle) { opacity: .45; }
.tagkarte.ablage { background: var(--knopf); }
/* Ein anderer Platz derselben Box: unter dem Finger grüner Ring, er gibt
   ein wenig nach. Ein leerer Platz zeigt seinen Rand grün. */
.bento > .ablage-ziel { box-shadow: 0 0 0 3px var(--primaer), var(--schatten-kachel); transform: scale(.97);
  transition: transform var(--dauer) var(--kurve), box-shadow var(--dauer) var(--kurve); }
.bento > .kachel.geist.ablage-ziel { border-color: var(--primaer); box-shadow: none; }
.tagkarte.ablage-ziel { box-shadow: inset 0 0 0 2px var(--primaer); background: var(--primaer-hell); }
/* Am neuen Platz federt die Karte nur einen Hauch - sie ist groß. */
.gerichtkarte.federt, .kachel.gericht.federt, .mahlzeitwahl.federt { animation-name: federn-klein !important; }
/* Die Mahlzeit-Reiter auf Spontan tauschen den Platz (mahlzeitreihenfolge.js):
   dieselbe Geste, nur sind alle anderen Reiter Ziele. Der gehobene Reiter
   schwebt als Glaspille; das Ziel unter dem Finger wird grün. */
.mahlzeitreiter .mahlzeitwahl { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
.mahlzeitwahl.zieht {
  margin: 0; scale: 1; padding: 6px 12px;
  border-radius: var(--radius-rund);
  background: var(--glas-stark); color: var(--text);
}
.mahlzeitwahl.zieht::after { display: none; }
.mahlzeitwahl.ablage { color: var(--text-2); }
.mahlzeitwahl.ablage-ziel { color: var(--primaer); }

/* ------------------------------------------------------------ Verschieben */
/* Ein Foto im Rahmen zurechtrücken (Bildausschnitt, rezept.js). Anders als
   beim Ziehen wird nichts an einen anderen Platz gelegt, darum gibt es kein
   Halten und kein Anheben: Der Finger fasst sofort an, was verschoben wird,
   folgt ihm ohne Übergang und bleibt am Rand stehen - kein Nachfedern,
   kein Gummiband. Zwei Finger, Mausrad und Regler zoomen. */

.ausschnitt-flaeche {
  touch-action: none; cursor: grab;
  -webkit-user-select: none; user-select: none; -webkit-touch-callout: none;
}
.ausschnitt-flaeche.verschiebt { cursor: grabbing; }

/* -------------------------------------------------------------- Blättern */
/* Seitlich wischen zwischen Gleichrangigem (wischkette.js): Die Fläche
   (Box des Tags, Box der Mahlzeit, Kochbuch-Gruppe, sonst der Inhalt unter
   dem Kopf) folgt dem Finger ohne Übergang; wo nichts mehr kommt, wird es
   zäh. Losgelassen gleitet sie zurück oder geht zur Seite weg, das Neue
   kommt aus der Wischrichtung - auch beim Antippen eines Reiters. Bewegt
   wird über translate, damit es sich nicht mit Aufsteigen (transform)
   in die Quere kommt. */

.blaettert-zurueck { transition: translate var(--dauer-lang) var(--kurve), opacity var(--dauer-lang) var(--kurve); }
.blaettert-weg     { transition: translate var(--dauer) var(--kurve-ab), opacity var(--dauer) var(--kurve-ab); }
.blaettert-rein    { transition: translate var(--dauer-auftritt) var(--kurve), opacity var(--dauer-auftritt) var(--kurve); }

/* -------------------------------------------------------- Herunterziehen */
/* Die Rezeptseite ganz oben nach unten ziehen (rezept.js): Sie folgt dem
   Finger ohne Übergang (translate, scale - Ursprung oben in der Mitte,
   dort steht die Seite am Bildschirmrand) und schließt wie ‹. Sonst gleitet
   sie mit .zieht-zurueck an ihren Platz. Pull-to-Refresh und Gummiband
   lassen wir dafür los. */

html:has(.rezeptseite) { overscroll-behavior-y: contain; }
.rezeptseite { transform-origin: 50% 0; }
.zieht-zurueck { transition: translate var(--dauer-lang) var(--kurve), scale var(--dauer-lang) var(--kurve); }

/* ----------------------------------------------------------------- Abgang */
/* Was geht, geht schneller als es kam und beschleunigt dabei - es wird
   weggeräumt, nicht weggezaubert. app.js (weg, dialogZu) setzt .geht und
   entfernt das Element, wenn die Animation durch ist. Überlagerungen kommen
   von ihrer Kante und gehen dorthin zurück. !important, weil .geht über
   jeder Auftritts-Animation stehen muss, egal wie genau die zielt. */

@keyframes absinken  { to { opacity: 0; transform: translateY(6px) scale(.98); } }
@keyframes ausblenden { to { opacity: 0; } }
@keyframes blatt-auf { from { transform: translateY(100%); } }
@keyframes blatt-ab  { to { transform: translateY(100%); } }
@keyframes aufklappen { from { opacity: 0; transform: translateY(-4px) scale(.98); } }

.geht { animation: absinken var(--dauer) var(--kurve-ab) forwards !important; pointer-events: none; }
.warteschirm.geht, .kochblatt-schatten.geht, dialog.fotoschau.geht { animation-name: ausblenden !important; }
.kochblatt.geht, dialog.rueckmeldung.geht, dialog.ausschnittblatt.geht, dialog.blatt.geht { animation-name: blatt-ab !important; }
@media (min-width: 900px) { dialog.rueckmeldung.geht, dialog.ausschnittblatt.geht, dialog.blatt.geht { animation-name: absinken !important; } }
dialog[open]::backdrop { animation: einblenden var(--dauer-lang) var(--kurve); }
dialog.geht::backdrop { animation: ausblenden var(--dauer) var(--kurve-ab) forwards; }
dialog.fotoschau[open] { animation: einblenden var(--dauer-lang) var(--kurve); }

/* ------------------------------------------------------ Klick-Rückmeldung */
/* Jeder Tipp bekommt eine Antwort: das Element drückt sich kurz ein, und
   vom Finger aus läuft eine Welle nach außen (app.js setzt .welle). */

@keyframes wellen {
  from { transform: translate(-50%, -50%) scale(0); opacity: .45; }
  to   { transform: translate(-50%, -50%) scale(1); opacity: 0; }
}
.mit-welle { position: relative; overflow: hidden; }
.welle {
  position: absolute;
  left: var(--x, 50%); top: var(--y, 50%);
  width: var(--groesse, 120px); height: var(--groesse, 120px);
  border-radius: 50%;
  background: currentColor;
  pointer-events: none;
  transform: translate(-50%, -50%) scale(0);
  animation: wellen var(--dauer-auftritt) ease-out forwards;
}
/* Eindrücken: schnell hinein (--dauer-tipp), federnd zurück. Wie tief,
   hängt an der Größe - kleine Knöpfe deutlich, Karten nur einen Hauch.
   Farben wechseln dabei ohne Federn, sonst schießen sie über. */
.knopf, .chip, .tab, .navpunkt, .ich-kachel, .ortwahl a, .reiter a, .reiter button, .rundglas, .kochknopf, .kachel.gericht, .tagkarte, .tagchip, .werkzeug, .neuknopf, .blattzu, .zusammenfassung,
.hakenzeile, .gerichtkarte-link, a.karte, .karte[data-oeffnet-formular], .zeile-link,
.rundknopf, .zeileweg, .merkknopf, .ausschnittknopf, .fotoknopf, .rueckmeldung-knopf, .warteschliessen,
.fragknopf, .uhrkachel, .naechster, .timerchip, .titelknopf, .zurueck, .einstellung > summary, .spontan-einstellungen > summary,
.zaehler button, .zaehler .zaehlerknopf, .ortknopf span, .textlink, .kochstart,
.auftragsleiste-link, .auftragsleiste-zu, [data-bildschau] {
  transition-property: transform, background, color, border-color, box-shadow, opacity;
  transition-duration: var(--dauer-lang), var(--dauer), var(--dauer), var(--dauer), var(--dauer), var(--dauer);
  transition-timing-function: var(--kurve-feder), var(--kurve), var(--kurve), var(--kurve), var(--kurve), var(--kurve);
}
.zeileweg:active, .rundknopf:active, .fragknopf:active, .timerchip:active,
.zaehler button:active, .zaehler .zaehlerknopf:active, .merkknopf:active, .ausschnittknopf:active, .fotoknopf:active,
.rueckmeldung-knopf:active, .warteschliessen:active, .auftragsleiste-zu:active, .rundglas:active, .zurueck:active,
.neuknopf:active:not(:disabled), .blattzu:active,
.zutatbild[data-bildschau]:active, .vorratsbild[data-bildschau]:active { transform: scale(var(--druck-klein)); }
.knopf:active, .chip:active, .tagchip:active, .tagkarte:active, .ich-kachel:active,
.ortknopf span:active, .titelknopf:active, .kochstart:active, .kochknopf:active, .auftragsleiste-link:active,
.ortwahl a:active, .reiter a:active, .reiter button:active, .kachel.gericht:active, .werkzeug:active, .zusammenfassung:active,
.kochzutat-bild[data-bildschau]:active, .uhrkachel:active, .naechster:active { transform: scale(var(--druck-mittel)); }
.hakenzeile:active, .gerichtkarte-link:active, .zeile-link:active, a.karte:active,
.karte[data-oeffnet-formular]:active, .einstellung > summary:active, .spontan-einstellungen > summary:active,
.navpunkt:active,
.rezeptfoto[data-bildschau]:active, .rezeptzeichen[data-bildschau]:active,
.kochfoto-vorschau[data-bildschau]:active { transform: scale(var(--druck-gross)); }
:is(.knopf, .chip, .tab, .navpunkt, .ortwahl a, .reiter a, .reiter button, .rundglas, .kochknopf, .kachel.gericht, .tagkarte, .tagchip, .werkzeug, .neuknopf, .blattzu, .zusammenfassung,
.hakenzeile, .gerichtkarte-link, a.karte, .karte[data-oeffnet-formular], .zeile-link,
.rundknopf, .zeileweg, .merkknopf, .ausschnittknopf, .fotoknopf, .rueckmeldung-knopf, .warteschliessen,
.fragknopf, .uhrkachel, .naechster, .timerchip, .titelknopf, .einstellung > summary, .spontan-einstellungen > summary,
.zaehler button, .zaehler .zaehlerknopf, .ortknopf span, .kochstart,
.auftragsleiste-link, .auftragsleiste-zu, [data-bildschau]):active {
  transition-duration: var(--dauer-tipp);
  transition-timing-function: var(--kurve);
}

/* ---------------------------------------------- Ruhe, wo Ruhe gewünscht */

/* Auf Geräten, die langsam zeichnen, keine Schleifen. */
@media (update: slow) {
  .lebt .dampf, .lebt .funke, .lebt .zeiger, .lebt .flackert, .lebt .strahlen,
  .kochstart-zeichen, .karte.leer .leer-zeichen, .warteschirm .wartetopf .dampf,
  .warteschirm .wartetopf .blase, .uhrkachel.fertig .uk-ring .ikon, .timerchip .zeiger,
  .planeinladung-zeichen, .planeinladung-zeichen * {
    animation: none !important;
  }
  .dampfschwaden { display: none; }
}
/* Steht die Seite im Zurück-Speicher wieder auf, soll nichts bei null hängen:
   prefers-reduced-motion in style.css kürzt alle Dauern auf .001ms, damit
   jede Animation sofort an ihrem Ende steht - auch die hier. */
@media (prefers-reduced-motion: reduce) {
  body.mit-bewegung .stapel > [data-erscheint] { opacity: 1; transform: none; transition: none; }
  .dampfschwaden { display: none; }
}

/* ------------------------------------------ Einladung auf der leeren Planseite

   Wer hier landet, hat keinen Plan und will einen. Der Kalender füllt sich
   deshalb vor den Augen: Ein Tag nach dem anderen bekommt seinen Punkt, zum
   Schluss steht der Haken - dann fängt es von vorn an. Das Zeichen schwebt
   dazu leicht, damit die Fläche als anfassbar liest und nicht als Bild.

   Die Punkte werden nur heller und dunkler, nicht größer: Sie sind Pfade
   ohne Ausdehnung ("M8 13.5h.01"), ein transform an ihnen zöge sie zur
   Bildmitte. */

@keyframes einladung-schweben {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-5px); }
}
/* Das Ende ist der volle Kalender, nicht der leere: Bei reduzierter Bewegung
   kürzt style.css jede Dauer auf .001ms, und dann steht die Animation sofort
   auf ihrem letzten Bild. Stünde dort der leere Zustand, wären die Tage für
   diese Leute unsichtbar. Der Rücksprung zum Anfang ist dafür deutlich - er
   liest sich als "und jetzt die nächste Woche". */
@keyframes tag-fuellen {
  0%, 10%   { opacity: .2; }
  28%, 100% { opacity: 1; }
}
@keyframes woche-haken {
  0%, 48%   { stroke-dashoffset: 1.05; }
  66%, 100% { stroke-dashoffset: 0; }
}

.planeinladung-zeichen { animation: einladung-schweben 3.4s ease-in-out infinite; }

.planeinladung-zeichen .punkt {
  animation: zeichnen var(--dauer-zeichnen) var(--kurve) both,
             tag-fuellen 4.4s ease-in-out infinite;
  animation-delay: calc(.12s + var(--n, 0) * 60ms),
                   calc(.9s + var(--n, 0) * .3s);
}
.planeinladung-zeichen .strich {
  animation: zeichnen var(--dauer-zeichnen) var(--kurve) both,
             woche-haken 4.4s ease-in-out infinite;
  animation-delay: calc(.12s + var(--n, 0) * 60ms), .9s;
}

/* Beim Anfassen rückt die ganze Karte einen Hauch heraus - dieselbe Sprache
   wie bei den anderen klickbaren Karten, nur deutlicher. */
@media (hover: hover) {
  a.karte.planeinladung:hover .planeinladung-zeichen { animation-play-state: paused; transform: scale(1.06); }
}

/* ------------------------------------------------------------- Auftischen */
/* Die Gerichte aus der Nacht beim ersten Zeigen (.auftischen, Spontan-Seite).
   Los geht es mit .laeuft: Das Skript setzt es, sobald die Seite zu den
   Gerichten gerollt ist - vorher stünde die Geste schon außerhalb des Bildes.
   Erst zeichnet sich die Glocke, dann hebt sich die Haube um ihre rechte
   Kante - darunter steigt der Dampf auf, daneben blitzen Funken -, und sie
   setzt sich wieder. Danach leuchten die Karten nacheinander auf
   (hervorheben-puls). Das Zeichen ist nur 20 px groß; damit die Haube nicht
   neben dem Leuchten der Karten untergeht, wächst es für die Dauer der
   Geste (glocke-gross) und fällt danach zurück. Eigene Dauern, weil es eine
   Geste mit mehreren Schlägen ist; nichts davon läuft weiter. Ohne
   .auftischen stehen Dampf und Funken unsichtbar, die Haube liegt auf. */

@keyframes haube-heben {
  0%, 100% { transform: rotate(0deg) translateY(0); }
  28%, 64% { transform: rotate(24deg) translateY(-3px); }
}
@keyframes glocke-gross {
  0%, 100% { transform: scale(1); }
  12%, 88% { transform: scale(1.5); }
}
@keyframes dampf-einmal {
  0%   { opacity: 0; transform: translateY(2px) scaleY(.8); }
  40%  { opacity: .9; }
  100% { opacity: 0; transform: translateY(-6px) scaleY(1.3); }
}
@keyframes funke-einmal {
  0%, 100% { opacity: 0; transform: scale(.4); }
  45%      { opacity: 1; transform: scale(2.4); }
}

.pikto-servierglocke .dampf, .pikto-servierglocke .funke { opacity: 0; }
.auftischen.laeuft .abschnittzeichen {
  animation: glocke-gross 2.6s ease-in-out;
  animation-delay: .1s;
}
.auftischen.laeuft .pikto-servierglocke .haube {
  animation: haube-heben 1.5s var(--kurve) both;
  animation-delay: .3s;
}
.auftischen.laeuft .pikto-servierglocke .dampf {
  animation: dampf-einmal 1.2s ease-out;
  animation-delay: calc(.55s + var(--n, 0) * .18s);
}
.auftischen.laeuft .pikto-servierglocke .funke {
  animation: funke-einmal .9s ease-out;
  animation-delay: calc(.7s + var(--n, 0) * .15s);
}
.auftischen.laeuft .nachtgericht > .gerichtkarte {
  animation: hervorheben-puls 1.6s ease-out;
  animation-delay: calc(1s + var(--verzug, 0s) * 3);
}
/* Im Bento-Theme ohne Glocke: Die Kacheln leuchten nacheinander auf. */
.auftischen.laeuft .kachel.gericht {
  animation: hervorheben-puls 1.6s ease-out;
  animation-delay: calc(.15s + var(--platz, 0) * .2s);
}
