/* ==========================================================================
   tokens.css — die einzige Datei mit Farb-, Schrift- und Maßwerten
   ==========================================================================

   Regel für dieses Projekt: ausserhalb dieser Datei steht kein Farbwert, keine
   Pixelgröße und keine Schriftfamilie. app.css und die JS-Module greifen
   ausschliesslich über var(--…) zu. Wer Stil oder Farben ändern will, ändert
   hier — und nur hier.

   Nachprüfbar mit:
     grep -nE '#[0-9a-fA-F]{3,6}|[0-9]+px|font-family' public/assets/app.css
   Das darf nichts finden.

   Aufbau in drei Schichten, damit ein Umstyling nicht bedeutet, jede Regel
   anzufassen:

     1. PALETTE   die rohen Markenfarben, wie vorgegeben
     2. SEMANTIK  was eine Farbe BEDEUTET (Aktion, läuft, fertig, Fehler)
     3. FLÄCHEN   wo sie landet (Hintergrund, Text, Linie, Fokus)

   Ein Rebranding tauscht Schicht 1. Eine neue Bedeutungs-Zuordnung ändert
   Schicht 2. Beides ohne app.css anzufassen.

   Stand: HoFaS-Editorial ("Ink-Navy / Gold / Sage"), abgeglichen mit
   hofascommunications.com. Alle Kontrastwerte unten sind gerechnet, nicht
   geschätzt — die Rechnung steht in docs/design/kontrast.md und lässt sich
   mit scripts/contrast.py wiederholen.
   ========================================================================== */


/* == SCHRIFTEN ==============================================================
   Selbst ausgeliefert aus public/assets/fonts/, nicht vom Google-CDN.

   Das ist eine bewusste Abweichung von der Vorgabe "von Google Fonts laden":
   ein <link> auf fonts.googleapis.com überträgt die IP-Adresse jedes Besuchers
   an Google (LG München I, 3 O 17493/20) — bei einem Produkt, das Aufnahmen
   aus Bewerbungsgesprächen verarbeitet, ist das die falsche Zeile im Kopf der
   Seite. Es sind dieselben Schnitte in derselben Version, nur von unserem
   eigenen Server. Ein Build-Schritt ist dafür nicht nötig; die Dateien liegen
   im Repo.

   Geladen wird nur latin und latin-ext. Fraunces und Source Sans 3 sind
   Variable Fonts (400–700 in einer Datei), IBM Plex Mono liegt statisch in
   400 und 500 vor. Für deutschen Text lädt der Browser 107 KB (latin);
   latin-ext kommt nur, wenn ein Zeichen ausserhalb Latin-1 vorkommt.

   font-display: swap — die Seite ist sofort lesbar, notfalls in der
   Systemschrift. Ein leerer Bildschirm, während eine Schrift lädt, ist bei
   einem Upload-Formular auf dem Handy die schlechtere Wahl. */

@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(fonts/fraunces-latin-400-700.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(fonts/fraunces-latin-ext-400-700.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
                 U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
                 U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(fonts/source-sans-3-latin-400-700.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url(fonts/source-sans-3-latin-ext-400-700.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
                 U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
                 U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Source Sans 3';
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url(fonts/source-sans-3-latin-400-700-italic.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Source Sans 3';
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url(fonts/source-sans-3-latin-ext-400-700-italic.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
                 U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
                 U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/ibm-plex-mono-latin-400.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/ibm-plex-mono-latin-ext-400.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
                 U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
                 U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/ibm-plex-mono-latin-500.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
                 U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
                 U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/ibm-plex-mono-latin-ext-500.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
                 U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113,
                 U+2C60-2C7F, U+A720-A7FF;
}


:root {

  /* == 1. PALETTE ==========================================================
     Die fünf vorgegebenen Markenfarben. Sie stehen unverändert hier — und
     genau deshalb braucht jede von ihnen Ableitungen, denn als Text taugen
     sie nicht alle.

     Gerechnet (WCAG 2.1, Schwelle AA: 4.5:1 für Fließtext, 3:1 für große
     Schrift ab 24px bzw. 19px fett und für Bedienelemente):

       ink-navy  #15172b  auf cream 16.51:1   Text überall, in jeder Größe
       sage-teal #2f6f62  auf cream  5.50:1   Text ab sofort erlaubt
       teal      #2f7d6f  auf cream  4.58:1   knapp über der Schwelle
       gold      #c9a84c  auf cream  2.14:1   ALS TEXT UNBRAUCHBAR
       cream     #faf7f1  auf ink   16.51:1   Text auf dunkler Fläche

     Gold ist der Markenakzent und fällt als Textfarbe auf Cream durch — mit
     2.14:1 nicht knapp, sondern deutlich. Auf Ink-Navy dagegen liegt es bei
     7.73:1 und ist dort erste Wahl. Also dieselbe Systematik wie beim ersten
     Farbsystem dieses Projekts:

       --*-ink   abgedunkelt, für Text und Linien auf hellem Grund
       --*-lift  aufgehellt, für Text auf dunklem Grund (Ink-Navy-Flächen)
       --*-soft  aufgehellt, als getönte Fläche

     Der Farbton bleibt jeweils erhalten. Es ist dieselbe Farbe, in der
     Helligkeit, die die Rolle verlangt. */

  --c-ink:        #15172b;   /* Vorgabe. Haupttext, dunkle Flächen */
  --c-ink-body:   #303243;   /* Ink bei 88 % auf Cream — 11.81:1.
                                Die vorgegebenen "85–90 % Deckkraft" für den
                                Fließtext, ausgerechnet statt per opacity:
                                opacity würde auch Kindelemente mitnehmen. */
  --c-ink-muted:  #4e4f5c;   /* Ink bei 75 % — 7.56:1. Sekundärtext, Entwurf */
  --c-ink-soft:   #e9e7e2;   /* getönte Fläche, Ink darauf 14.29:1 */
  --c-ink-line:   #e3e1dd;   /* Ink bei 10 % — die vorgegebene Kartenlinie.
                                1.22:1: eine Zierlinie, kein Bedienelement.
                                Wo eine Linie einen Zustand oder die Grenze
                                eines Eingabefelds trägt, steht --c-ink-rule. */
  --c-ink-rule:   #88878e;   /* Ink bei 50 % — 3.33:1 auf Cream.
                                Rahmen von Eingabefeldern und allem, was
                                anklickbar ist (WCAG 1.4.11). */

  --c-gold:       #c9a84c;   /* Vorgabe. Fläche, Zierlinie, Text AUF Ink-Navy
                                (7.73:1). Nie Text auf hell. */
  --c-gold-ink:   #7f6414;   /* Text auf Cream 5.26:1, auf Weiß 5.62:1 */
  --c-gold-line:  #a5842a;   /* 3.31:1 auf Cream. Das Gold, das eine
                                Zustandsänderung tragen darf — Hover-Rahmen
                                der Tarifkarte, aktiver Reiter. Reines Gold
                                bliebe dort unter der 3:1-Schwelle. */
  --c-gold-soft:  #f5ecd4;   /* getönte Fläche, --c-gold-ink darauf 4.77:1 */

  --c-sage:       #2f6f62;   /* Vorgabe. 5.50:1 auf Cream — texttauglich */
  --c-sage-lift:  #7fbfae;   /* 8.38:1 auf Ink-Navy */
  --c-sage-soft:  #e2eeea;   /* --c-sage darauf 4.94:1 */

  --c-teal:       #2f7d6f;   /* Vorgabe (accent-teal). 4.58:1 auf Cream —
                                über der Schwelle, aber ohne Reserve. Deshalb
                                nur für große Schrift (Prozess-Ziffern) und
                                Flächen, nicht für Fließtext: dafür ist
                                --c-sage mit 5.50:1 der sichere Nachbar. */

  --c-cream:      #faf7f1;   /* Vorgabe. Seitenhintergrund, Text auf Ink */
  --c-cream-dim:  #cccac9;   /* Cream bei 80 % auf Ink — 10.81:1.
                                Sekundärtext in Kopf und Fuß */
  --c-cream-line: #434453;   /* Cream bei 20 % auf Ink — Trennlinie im Dunkeln */
  --c-white:      #ffffff;   /* Datenflächen: Liste, Formular, Beleg */

  /* Abgeleitet, NICHT aus der Vorgabe: ein Fehlerton.
     Begründung wie beim ersten Farbsystem — 'failed' darf nicht aussehen wie
     'wird verarbeitet', und in dieser Palette trägt Gold die laufende
     Verarbeitung. Ein Fehlschlag in Goldtönen wäre die schlechteste
     Verwechslung dieser Oberfläche.
     Gewählt: ein gedecktes Ziegelrot. Warm genug, um neben Gold und Sage
     nicht wie ein Systemfehler-Rot aus einem anderen Programm zu wirken,
     und weit genug weg, um nie mit Gold verwechselt zu werden.
     Text auf Cream 6.95:1, Cream darauf 6.95:1. */
  --c-danger:      #9e2b25;
  --c-danger-lift: #e08a80;  /* 6.82:1 auf Ink-Navy */
  --c-danger-soft: #f7e3e0;  /* --c-danger darauf 6.02:1 */


  /* == 2. SEMANTIK =========================================================
     Was eine Farbe bedeutet. app.css benutzt nur diese Namen — dort steht
     nie "gold", immer "progress". Damit lässt sich die Zuordnung ändern, ohne
     dass ein Klassenname anschliessend das Gegenteil behauptet.

     Die Zuordnung folgt weiter dem Weg einer Aufnahme zum Beleg, jetzt in
     den Markenfarben:

       action    was die Person anklickt                          → Gold
       progress  unterwegs (uploading, queued, processing)        → Gold
       done      belegt, Protokoll liegt vor (completed)          → Sage
       muted     Entwurf, leeres Feld, Struktur (draft)           → Ink 75 %
       danger    fehlgeschlagen                                   → Ziegelrot

     Dass action und progress dieselbe Farbe tragen, ist Absicht der Vorgabe
     und in dieser UI unkritisch: eine Schaltfläche und eine Statusmarke
     stehen nie an derselben Stelle und tragen nie dieselbe Form.

     Zusätzlich zur Farbe trägt JEDER Zustand weiterhin eine eigene FORM
     (gefüllt / Ring / gestrichelt / Kerbe) und ein Wort. Ein Zustand, der
     sich nur im Farbton unterscheidet, wäre für Farbfehlsichtige und im
     Schwarzweiß-Ausdruck nicht mehr lesbar — und dieses Produkt wird
     gedruckt. Am Konzept ändert das Redesign nichts, nur an den Farben. */

  --action:        var(--c-gold);
  --action-ink:    var(--c-gold-ink);
  --action-line:   var(--c-gold-line);
  --action-soft:   var(--c-gold-soft);
  --on-action:     var(--c-ink);        /* Ink auf Gold: 7.73:1 */

  --progress:      var(--c-gold);
  --progress-ink:  var(--c-gold-ink);
  --progress-soft: var(--c-gold-soft);

  --done:          var(--c-sage);
  --done-ink:      var(--c-sage);       /* Sage ist auf Cream schon 5.50:1 —
                                           eine dunklere Ableitung braucht es
                                           für Text nicht */
  --done-lift:     var(--c-sage-lift);
  --done-soft:     var(--c-sage-soft);
  --on-done:       var(--c-cream);      /* Cream auf Sage: 5.50:1 */

  --muted:         var(--c-ink-muted);
  --muted-ink:     var(--c-ink);
  --muted-soft:    var(--c-ink-soft);

  --danger:        var(--c-danger);
  --danger-ink:    var(--c-danger);     /* 6.95:1 auf Cream, 7.43:1 auf Weiß */
  --danger-lift:   var(--c-danger-lift);
  --danger-soft:   var(--c-danger-soft);
  --on-danger:     var(--c-cream);

  /* Der zweite Markenakzent. Trägt Eyebrow-Label und Prozess-Ziffern —
     Stellen, an denen Gold als Text ausfällt und Ink-Navy zu beiläufig wäre. */
  --accent:        var(--c-sage);
  --accent-strong: var(--c-teal);       /* nur groß gesetzt, siehe --c-teal */


  /* == 3. FLÄCHEN ========================================================== */

  --bg:            var(--c-cream);      /* Seite */
  --surface:       var(--c-white);      /* Liste, Formular, Beleg — die
                                           Datenflächen bleiben weiß, damit
                                           die Register-Anmutung erhalten
                                           bleibt und getönte Meldungsflächen
                                           sich davon abheben */
  --surface-tint:  var(--c-cream);      /* Karten auf weißem Grund und
                                           Karten-auf-Cream mit --rule */
  --surface-sunk:  var(--c-ink-soft);   /* Spur des Fortschrittsbalkens */
  --surface-dark:  var(--c-ink);        /* Kopf, Fuß, dunkle Abschnitte */

  --text:          var(--c-ink-body);   /* Fließtext, 11.81:1 auf --bg */
  --heading:       var(--c-ink);        /* Überschriften voll, 16.51:1 */
  --text-2:        var(--c-ink-muted);  /* 7.56:1 — Sekundärtext */
  --text-3:        var(--c-ink-muted);  /* Feldlabels; die Größe trägt den
                                           Unterschied, nicht ein blasserer
                                           Ton, der die Schwelle reissen würde */

  --on-dark:       var(--c-cream);      /* Text auf --surface-dark, 16.51:1 */
  --on-dark-2:     var(--c-cream-dim);  /* Sekundär auf dunkel, 10.81:1 */
  --on-dark-accent: var(--c-gold);      /* Akzent auf dunkel, 7.73:1 */
  --rule-dark:     var(--c-cream-line); /* Trennlinie auf dunkel */

  --rule:          var(--c-ink-line);   /* Haarlinie, Zier — Karten, Zeilen */
  --rule-strong:   var(--c-ink-rule);   /* Bedienelement-Rahmen, 3.33:1 */
  --rule-brand:    var(--c-gold);       /* die Gold-Linie unter H1/H2 */

  /* Fokus: zwei Ringe. Der innere in Flächenfarbe trennt den äusseren vom
     Untergrund, damit derselbe Ring auf Cream UND auf einer goldenen
     Schaltfläche sichtbar bleibt (Ink auf Gold: 7.73:1). Ein einfarbiger Ring
     verschwindet sonst genau auf der Fläche seiner eigenen Farbe. */
  --focus-ring:      0 0 0 var(--space-1) var(--bg),
                     0 0 0 calc(var(--space-1) * 2) var(--c-ink);
  /* Auf Ink-Navy-Flächen wäre ein Ink-Ring unsichtbar — dort Gold, 7.73:1. */
  --focus-ring-dark: 0 0 0 var(--space-1) var(--surface-dark),
                     0 0 0 calc(var(--space-1) * 2) var(--c-gold);


  /* == TYPOGRAFIE ==========================================================
     Drei Schriften mit drei getrennten Aufgaben. Die Trennung ist die
     eigentliche Regel — nicht welche Schrift schöner ist:

       --font-display  Fraunces        Überschriften, große Zahlen
       --font-text     Source Sans 3   Fließtext, Formulare, Schaltflächen
       --font-value    IBM Plex Mono   Werte aus dem Register

     --font-value ist keine Dekoration, sondern eine Aussage, und die gab es
     in diesem Projekt schon vor dem Redesign: Monospace mit tabular-nums
     steht für "belegte Angabe" — Zeitstempel, Datum, Meeting-Nummer,
     Teile-Zähler, Dateigröße, Preis. Nie im Fließtext, nie in Überschriften.
     IBM Plex Mono übernimmt diese Rolle jetzt auch für Eyebrow-Label und
     Tags; das passt, weil beides Beschriftung ist und kein Satz.

     Die Systemschriften bleiben als Fallback hinter jedem Eintrag stehen —
     bei font-display: swap ist das die Schrift, die der Nutzer in der ersten
     Sekunde sieht. */

  --font-display: 'Fraunces', 'Iowan Old Style', Georgia, 'Times New Roman',
                  serif;
  --font-text:    'Source Sans 3', system-ui, -apple-system, 'Segoe UI', Roboto,
                  'Helvetica Neue', Arial, sans-serif;
  --font-value:   'IBM Plex Mono', ui-monospace, 'SF Mono', 'Cascadia Mono',
                  'Segoe UI Mono', 'Roboto Mono', Menlo, Consolas, monospace;

  /* Größen. Die drei oberen Stufen sind fluid: auf dem Handy soll eine
     Fraunces-Überschrift nicht über vier Zeilen laufen, auf dem Monitor darf
     sie den Aufmacher tragen. clamp() statt zusätzlicher Haltepunkte. */
  --fs-display: clamp(2rem, 1.35rem + 2.8vw, 3.25rem);   /* Hero-H1 */
  --fs-h1:      clamp(1.75rem, 1.45rem + 1.3vw, 2.375rem);
  --fs-h2:      clamp(1.375rem, 1.22rem + 0.68vw, 1.75rem);
  --fs-h3:      1.125rem;
  --fs-figure:  clamp(1.5rem, 1.2rem + 1.3vw, 2.125rem);  /* Preis, Kennzahl */

  --fs-eyebrow: 0.6875rem;   /* 11px, gesperrt und versal */
  --fs-label:   0.75rem;
  --fs-xs:      0.8125rem;
  --fs-sm:      0.875rem;
  --fs-base:    1rem;
  --fs-lg:      1.125rem;
  --fs-lede:    clamp(1.0625rem, 1rem + 0.35vw, 1.25rem);

  --lh-display: 1.12;
  --lh-tight:   1.25;
  --lh-base:    1.6;    /* Vorgabe für Fließtext in Source Sans 3 */

  --fw-normal: 400;
  --fw-medium: 500;
  --fw-bold:   600;
  --fw-heavy:  700;

  --tracking-eyebrow: 0.14em;   /* "weiter Buchstabenabstand" */
  --tracking-label:   0.08em;
  --tracking-tight:  -0.015em;  /* Fraunces groß gesetzt läuft sonst auseinander */


  /* == RAUM UND FORM ======================================================= */

  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;

  --radius:      2px;   /* Register, nicht App-Kachel */
  --radius-pill: 999px;

  --border:      1px;
  --border-mark: 2px;
  --border-brand: 3px;  /* Gold-Strich unter H1/H2 und links am Zitat */

  --rule-len:    var(--space-7);   /* Länge des Gold-Strichs unter H1/H2 */

  /* Bewusst ohne Schatten. Tiefe entsteht über Haarlinien und über die
     Ink-Navy-Flächen in Kopf und Fuß. Das Token existiert, damit ein späteres
     Umstyling einen Ort hat, statt Schatten in app.css zu streuen. */
  --shadow: none;

  --w-form:    34rem;   /* Anmeldung, Formulare */
  --w-page:    68rem;   /* Liste, Detail */
  --w-wide:    74rem;   /* Tarif-Karten, Prozess-Karten */
  --measure:   65ch;    /* Lesebreite für Fließtext */

  /* Belegspur: Breite der Marken-Spalte und der Zeitspalte */
  --trail-mark: 0.875rem;
  --trail-gap:  var(--space-4);

  /* Für den Honeypot des Kontaktformulars: aus dem Sichtfeld, aber im Layout.
     display:none und hidden erkennen manche Bots und lassen das Feld dann aus. */
  --offscreen: -9999px;


  /* == BEWEGUNG ============================================================
     Sparsam und nur für Zustandswechsel. Der Umschalter für
     prefers-reduced-motion steht weiter unten und setzt diese Tokens auf 0 —
     app.css muss die Media Query nicht kennen. */

  --dur-fast: 120ms;
  --dur-base: 200ms;
  --ease:     cubic-bezier(0.2, 0, 0.3, 1);
}


/* Nutzer, die weniger Bewegung eingestellt haben, bekommen keine.
   Zentral hier, damit es nicht in app.css vergessen wird. Die laufende
   Verarbeitung wird dann nicht animiert dargestellt, sondern über den Text
   und den mitlaufenden Zeitstempel — was ohnehin die ehrlichere Anzeige ist:
   der Zeitstempel kommt aus dem Job, die Animation kam von uns. */
@media (prefers-reduced-motion: reduce) {
  :root {
    --dur-fast: 0ms;
    --dur-base: 0ms;
  }
}
